1. Project Clover database Tue Dec 20 2016 21:24:09 CET
  2. Package org.xwiki.extension.xar.internal.job

File RepairXarJob.java

 

Coverage histogram

../../../../../../img/srcFileCovDistChart9.png
38% of files have more coverage

Code metrics

28
75
7
1
314
202
24
0.32
10.71
7
3.43

Classes

Class Line # Actions
RepairXarJob 60 75 0% 24 18
0.836363683.6%
 

Contributing tests

This file is covered by 3 tests. .

Source view

1    /*
2    * See the NOTICE file distributed with this work for additional
3    * information regarding copyright ownership.
4    *
5    * This is free software; you can redistribute it and/or modify it
6    * under the terms of the GNU Lesser General Public License as
7    * published by the Free Software Foundation; either version 2.1 of
8    * the License, or (at your option) any later version.
9    *
10    * This software is distributed in the hope that it will be useful,
11    * but WITHOUT ANY WARRANTY; without even the implied warranty of
12    * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13    * Lesser General Public License for more details.
14    *
15    * You should have received a copy of the GNU Lesser General Public
16    * License along with this software; if not, write to the Free
17    * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
18    * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
19    */
20    package org.xwiki.extension.xar.internal.job;
21   
22    import java.util.Collection;
23    import java.util.Collections;
24    import java.util.Map;
25   
26    import javax.inject.Inject;
27    import javax.inject.Named;
28   
29    import org.xwiki.component.annotation.Component;
30    import org.xwiki.extension.Extension;
31    import org.xwiki.extension.ExtensionDependency;
32    import org.xwiki.extension.ExtensionId;
33    import org.xwiki.extension.InstallException;
34    import org.xwiki.extension.InstalledExtension;
35    import org.xwiki.extension.LocalExtension;
36    import org.xwiki.extension.ResolveException;
37    import org.xwiki.extension.event.ExtensionInstalledEvent;
38    import org.xwiki.extension.internal.ExtensionUtils;
39    import org.xwiki.extension.job.InstallRequest;
40    import org.xwiki.extension.job.internal.AbstractExtensionJob;
41    import org.xwiki.extension.repository.CoreExtensionRepository;
42    import org.xwiki.extension.repository.ExtensionRepositoryManager;
43    import org.xwiki.extension.repository.InstalledExtensionRepository;
44    import org.xwiki.extension.repository.LocalExtensionRepository;
45    import org.xwiki.extension.repository.LocalExtensionRepositoryException;
46    import org.xwiki.extension.xar.internal.handler.XarExtensionHandler;
47    import org.xwiki.job.DefaultJobStatus;
48    import org.xwiki.job.Request;
49    import org.xwiki.logging.marker.BeginTranslationMarker;
50    import org.xwiki.logging.marker.EndTranslationMarker;
51   
52    /**
53    * Make sure the provided XAR extension properly is registered in the installed extensions index.
54    *
55    * @version $Id: 98910ec2b19bb8ef04eb235fe6e7ea803309e143 $
56    * @since 4.3M1
57    */
58    @Component
59    @Named(RepairXarJob.JOBTYPE)
 
60    public class RepairXarJob extends AbstractExtensionJob<InstallRequest, DefaultJobStatus<InstallRequest>>
61    {
62    /**
63    * The id of the job.
64    */
65    public static final String JOBTYPE = "repairxar";
66   
67    private static final BeginTranslationMarker LOG_REPAIR_BEGIN =
68    new BeginTranslationMarker("extension.xar.log.repair.begin");
69   
70    private static final BeginTranslationMarker LOG_REPAIR_NAMESPACE_BEGIN =
71    new BeginTranslationMarker("extension.xar.log.repair.begin.namespace");
72   
73    private static final EndTranslationMarker LOG_REPAIR_END = new EndTranslationMarker("extension.xar.log.repair.end");
74   
75    private static final EndTranslationMarker LOG_REPAIR_END_NAMESPACE =
76    new EndTranslationMarker("extension.xar.log.repair.end.namespace");
77   
78    /**
79    * Used to resolve extensions to install.
80    */
81    @Inject
82    protected ExtensionRepositoryManager repositoryManager;
83   
84    /**
85    * Used to set a local extension as installed.
86    */
87    @Inject
88    private InstalledExtensionRepository installedRepository;
89   
90    /**
91    * Used to store downloaded extensions.
92    */
93    @Inject
94    private LocalExtensionRepository localRepository;
95   
96    @Inject
97    private CoreExtensionRepository coreRepository;
98   
 
99  15 toggle @Override
100    public String getType()
101    {
102  15 return JOBTYPE;
103    }
104   
 
105  3 toggle @Override
106    protected InstallRequest castRequest(Request request)
107    {
108  3 InstallRequest installRequest;
109  3 if (request instanceof InstallRequest) {
110  3 installRequest = (InstallRequest) request;
111    } else {
112  0 installRequest = new InstallRequest(request);
113    }
114   
115  3 return installRequest;
116    }
117   
 
118  3 toggle @Override
119    protected void runInternal() throws Exception
120    {
121  3 this.progressManager.pushLevelProgress(getRequest().getExtensions().size(), this);
122   
123  3 try {
124  3 for (ExtensionId extensionId : getRequest().getExtensions()) {
125  3 this.progressManager.startStep(this);
126   
127  3 if (getRequest().getNamespaces() != null) {
128  1 this.progressManager.pushLevelProgress(getRequest().getNamespaces().size(), this);
129   
130  1 try {
131  1 for (String namespace : getRequest().getNamespaces()) {
132  1 this.progressManager.startStep(this);
133   
134  1 repairExtension(extensionId, namespace, false, Collections.emptyMap());
135    }
136    } finally {
137  1 this.progressManager.popLevelProgress(this);
138    }
139    } else {
140  2 repairExtension(extensionId, null, false, Collections.emptyMap());
141    }
142    }
143    } finally {
144  3 this.progressManager.popLevelProgress(this);
145    }
146    }
147   
148    /**
149    * @param extensionId the extension unique identifier
150    * @return the stored local extension
151    * @throws InstallException failed to store extension
152    */
 
153  6 toggle private LocalExtension getLocalXARExtension(ExtensionId extensionId) throws InstallException
154    {
155  6 LocalExtension localExtension = this.localRepository.getLocalExtension(extensionId);
156   
157  6 if (localExtension == null) {
158  6 this.progressManager.pushLevelProgress(2, this);
159   
160  6 try {
161  6 this.progressManager.startStep(this);
162   
163  6 Extension extension = this.repositoryManager.resolve(extensionId);
164   
165  5 this.progressManager.startStep(this);
166   
167  5 if (extension.getType().equals(XarExtensionHandler.TYPE)) {
168  5 localExtension = this.localExtensionRepository.storeExtension(extension);
169    }
170    } catch (ResolveException e) {
171  1 throw new InstallException("Failed to find extension", e);
172    } catch (LocalExtensionRepositoryException e) {
173  0 throw new InstallException("Failed save extension in local repository", e);
174    } finally {
175  6 this.progressManager.popLevelProgress(this);
176    }
177  0 } else if (!localExtension.getType().equals(XarExtensionHandler.TYPE)) {
178  0 localExtension = null;
179    }
180   
181  5 return localExtension;
182    }
183   
184    /**
185    * @param extensionId the unique extension identifier
186    * @param namespace the namespace where to install extension
187    * @param dependency indicate of the extension is installed as a dependency of another
188    * @param managedDependencies the managed dependencies
189    * @throws InstallException failed to repair extension
190    */
 
191  6 toggle private void repairExtension(ExtensionId extensionId, String namespace, boolean dependency,
192    Map<String, ExtensionDependency> managedDependencies) throws InstallException
193    {
194  6 if (this.installedRepository.getInstalledExtension(extensionId.getId(), namespace) != null) {
195  0 this.logger.debug("Extension [{}] already installed on namespace [{}]", extensionId.getId(), namespace);
196   
197  0 return;
198    }
199   
200  6 if (getRequest().isVerbose()) {
201  6 if (namespace != null) {
202  2 this.logger.info(LOG_REPAIR_NAMESPACE_BEGIN, "Repairing XAR extension [{}] on namespace [{}]",
203    extensionId, namespace);
204    } else {
205  4 this.logger.info(LOG_REPAIR_BEGIN, "Repairing XAR extension [{}] on all namespaces", extensionId,
206    namespace);
207    }
208    }
209   
210  6 this.progressManager.pushLevelProgress(2, this);
211   
212  6 try {
213  6 this.progressManager.startStep(this);
214   
215  6 LocalExtension localExtension = getLocalXARExtension(extensionId);
216   
217  5 this.progressManager.startStep(this);
218   
219  5 if (localExtension != null) {
220  5 repairExtension(localExtension, namespace, dependency, managedDependencies);
221    }
222    } finally {
223  6 if (getRequest().isVerbose()) {
224  6 if (namespace != null) {
225  2 this.logger.info(LOG_REPAIR_END_NAMESPACE, "Done repairing XAR extension [{}] on namespace [{}]",
226    extensionId, namespace);
227    } else {
228  4 this.logger.info(LOG_REPAIR_END, "Done repairing XAR extension [{}] on all namespaces", extensionId,
229    namespace);
230    }
231    }
232   
233  6 this.progressManager.popLevelProgress(this);
234    }
235    }
236   
237    /**
238    * @param localExtension the local extension to install
239    * @param namespace the namespace where to install extension
240    * @param dependency indicate of the extension is installed as a dependency of another
241    * @param managedDependencies the managed dependencies
242    * @throws InstallException failed to repair extension
243    */
 
244  5 toggle private void repairExtension(LocalExtension localExtension, String namespace, boolean dependency,
245    Map<String, ExtensionDependency> managedDependencies) throws InstallException
246    {
247  5 this.progressManager.pushLevelProgress(2, this);
248   
249  5 try {
250  5 this.progressManager.startStep(this);
251   
252  5 Collection<? extends ExtensionDependency> dependencies = localExtension.getDependencies();
253   
254  5 if (!dependencies.isEmpty()) {
255  3 this.progressManager.pushLevelProgress(dependencies.size(), this);
256   
257  3 try {
258  3 for (ExtensionDependency extensionDependency : dependencies) {
259  3 this.progressManager.startStep(this);
260   
261    // Replace with managed dependency if any
262  3 ExtensionDependency resolvedDependency =
263    ExtensionUtils.getDependency(extensionDependency, managedDependencies, localExtension);
264   
265  3 repairDependency(resolvedDependency, namespace,
266    ExtensionUtils.append(managedDependencies, localExtension));
267    }
268    } finally {
269  3 this.progressManager.popLevelProgress(this);
270    }
271    }
272   
273  5 this.progressManager.startStep(this);
274   
275  5 InstalledExtension installedExtension =
276    this.installedRepository.installExtension(localExtension, namespace, dependency);
277   
278  5 this.observationManager.notify(new ExtensionInstalledEvent(installedExtension.getId(), namespace),
279    installedExtension);
280    } finally {
281  5 this.progressManager.popLevelProgress(this);
282    }
283    }
284   
285    /**
286    * @param extensionDependency the extension dependency to install
287    * @param namespace the namespace where to install extension
288    * @param managedDependencies the managed dependencies
289    */
 
290  3 toggle private void repairDependency(ExtensionDependency extensionDependency, String namespace,
291    Map<String, ExtensionDependency> managedDependencies)
292    {
293    // Skip core extensions
294  3 if (this.coreRepository.getCoreExtension(extensionDependency.getId()) == null) {
295    // TODO: take into account managed dependencies
296  3 if (extensionDependency.getVersionConstraint().getVersion() == null) {
297  0 this.logger.warn(
298    "Can't repair extension dependency [{}] with version range ([{}])"
299    + " since there is no way to know what has been installed",
300    extensionDependency.getId(), extensionDependency.getVersionConstraint());
301   
302    } else {
303  3 try {
304  3 repairExtension(
305    new ExtensionId(extensionDependency.getId(),
306    extensionDependency.getVersionConstraint().getVersion()),
307    namespace, true, managedDependencies);
308    } catch (InstallException e) {
309  1 this.logger.warn("Failed to repair dependency [{}]", extensionDependency, e);
310    }
311    }
312    }
313    }
314    }