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

File FlavorSearchJob.java

 

Coverage histogram

../../../../../../img/srcFileCovDistChart0.png
83% of files have more coverage

Code metrics

20
64
8
1
246
156
21
0.33
8
8
2.62

Classes

Class Line # Actions
FlavorSearchJob 59 64 0% 21 92
0.00%
 

Contributing tests

No tests hitting this source file were found.

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.platform.flavor.internal.job;
21   
22    import java.util.ArrayList;
23    import java.util.Collection;
24    import java.util.HashSet;
25    import java.util.List;
26    import java.util.ListIterator;
27    import java.util.Set;
28    import java.util.concurrent.CopyOnWriteArrayList;
29   
30    import javax.inject.Inject;
31    import javax.inject.Named;
32   
33    import org.xwiki.component.annotation.Component;
34    import org.xwiki.extension.Extension;
35    import org.xwiki.extension.ExtensionId;
36    import org.xwiki.extension.ExtensionManager;
37    import org.xwiki.extension.InstallException;
38    import org.xwiki.extension.ResolveException;
39    import org.xwiki.extension.job.internal.AbstractInstallPlanJob;
40    import org.xwiki.extension.job.plan.internal.DefaultExtensionPlanTree;
41    import org.xwiki.extension.repository.result.IterableResult;
42    import org.xwiki.extension.version.Version;
43    import org.xwiki.job.Job;
44    import org.xwiki.job.JobGroupPath;
45    import org.xwiki.job.Request;
46    import org.xwiki.job.event.status.JobStatus;
47    import org.xwiki.platform.flavor.FlavorManager;
48    import org.xwiki.platform.flavor.FlavorQuery;
49    import org.xwiki.platform.flavor.job.FlavorSearchRequest;
50   
51    /**
52    * Filter existing flavor to keep only those that can be installed on provided namespace.
53    *
54    * @version $Id: 6ca4610262c77ec6a70758fc27fcb8284d4a4481 $
55    * @since 8.0RC1
56    */
57    @Component
58    @Named(FlavorSearchJob.JOBTYPE)
 
59    public class FlavorSearchJob extends AbstractInstallPlanJob<FlavorSearchRequest>
60    {
61    /**
62    * The id of the job.
63    */
64    public static final String JOBTYPE = "searchflavors";
65   
66    @Inject
67    private FlavorManager flavorManager;
68   
69    @Inject
70    private ExtensionManager extensionManager;
71   
72    private List<Extension> foundFlavors = new CopyOnWriteArrayList<>();
73   
 
74  0 toggle @Override
75    public String getType()
76    {
77  0 return JOBTYPE;
78    }
79   
 
80  0 toggle @Override
81    public JobGroupPath getGroupPath()
82    {
83    // We reuse install plan stuff but blocking in this job would cause more issues than it solves
84  0 return null;
85    }
86   
 
87  0 toggle @Override
88    protected FlavorSearchRequest castRequest(Request request)
89    {
90  0 FlavorSearchRequest installRequest;
91  0 if (request instanceof FlavorSearchRequest) {
92  0 installRequest = (FlavorSearchRequest) request;
93    } else {
94  0 installRequest = new FlavorSearchRequest(request);
95    }
96   
97  0 return installRequest;
98    }
99   
 
100  0 toggle @Override
101    protected DefaultFlavorSearchStatus createNewStatus(FlavorSearchRequest request)
102    {
103  0 Job currentJob = this.jobContext.getCurrentJob();
104  0 JobStatus currentJobStatus = currentJob != null ? currentJob.getStatus() : null;
105  0 return new DefaultFlavorSearchStatus(request, this.observationManager, this.loggerManager, this.foundFlavors,
106    currentJobStatus);
107    }
108   
109    /**
110    * Try to install the provided extension and update the plan if it's working.
111    *
112    * @param extensionId the extension version to install
113    * @param namespace the namespace where to install the extension
114    * @return true if the installation would succeed, false otherwise
115    */
 
116  0 toggle private Extension tryInstallExtension(ExtensionId extensionId, String namespace)
117    {
118  0 DefaultExtensionPlanTree currentTree = new DefaultExtensionPlanTree();
119   
120  0 try {
121  0 installExtension(extensionId, namespace, currentTree);
122   
123    // Cleanup
124  0 this.extensionsNodeCache.clear();
125   
126  0 return currentTree.get(0).getAction().getExtension();
127    } catch (InstallException e) {
128  0 this.logger.debug("Can't install extension [{}] on namespace [{}].", extensionId, namespace, e);
129    }
130   
131  0 return null;
132    }
133   
 
134  0 toggle @Override
135    protected void runInternal() throws Exception
136    {
137    // Get known flavors
138  0 Collection<ExtensionId> knownFlavors = this.flavorManager.getKnownFlavors();
139   
140    // Get remote flavors
141  0 IterableResult<Extension> flavors = this.flavorManager.searchFlavors(new FlavorQuery());
142   
143  0 this.progressManager.pushLevelProgress(knownFlavors.size() + flavors.getSize(), this);
144   
145  0 try {
146  0 Set<String> doneFlavors = new HashSet<>();
147   
148  0 String namespace = getRequest().getNamespaces().iterator().next();
149   
150    // Add known flavors
151  0 for (ExtensionId flavorId : knownFlavors) {
152  0 this.progressManager.startStep(this);
153   
154  0 if (flavorId.getVersion() != null) {
155  0 try {
156    // Get corresponding extension
157  0 Extension flavor = this.extensionManager.resolveExtension(flavorId);
158   
159    // Filter allowed flavors on namespace
160  0 if (this.namespaceResolver.isAllowed(flavor.getAllowedNamespaces(), namespace)) {
161    // Directly add the flavor without trying to validate it first (99% of the time it's valid
162    // or it
163    // mean
164    // the distribution was broken and you probably want to know about it)
165  0 this.foundFlavors.add(flavor);
166    }
167    } catch (ResolveException e) {
168  0 this.logger.debug("Failed to resolve extension [{}]", flavorId, e);
169    }
170    } else {
171    // Find a valid version of the flavor
172  0 Extension flavor = findValidVersion(flavorId.getId(), namespace);
173   
174  0 if (flavor != null) {
175  0 this.foundFlavors.add(flavor);
176    }
177    }
178   
179    // Remember we took care of this flavor
180  0 doneFlavors.add(flavorId.getId());
181    }
182   
183    // Add remote flavors
184  0 for (Extension flavor : flavors) {
185  0 this.progressManager.startStep(this);
186   
187    // Search only unknown flavors
188  0 if (!doneFlavors.contains(flavor.getId().getId())) {
189  0 Extension validExtension = findValidVersion(flavor.getId().getId(), namespace);
190  0 if (validExtension != null) {
191  0 this.foundFlavors.add(validExtension);
192    }
193    }
194    }
195    } finally {
196  0 this.progressManager.popLevelProgress(this);
197    }
198    }
199   
 
200  0 toggle private Extension findValidVersion(String flavorId, String namespace)
201    {
202  0 IterableResult<Version> versions;
203  0 try {
204  0 versions = this.repositoryManager.resolveVersions(flavorId, 0, -1);
205   
206  0 if (versions.getSize() == 0) {
207  0 this.logger.debug("Could not find any version for the flavor extension [{}]", flavorId);
208   
209  0 return null;
210    }
211   
212  0 List<Version> versionList = new ArrayList<Version>(versions.getSize());
213  0 for (Version version : versions) {
214  0 versionList.add(version);
215    }
216   
217  0 return findValidVersion(flavorId, namespace, versionList);
218    } catch (ResolveException e) {
219  0 this.logger.debug("Failed to resolve versions for extension id [{}]", flavorId, e);
220    }
221   
222  0 return null;
223    }
224   
 
225  0 toggle private Extension findValidVersion(String flavorId, String namespace, List<Version> versionList)
226    {
227  0 this.progressManager.pushLevelProgress(versionList.size(), flavorId);
228   
229  0 try {
230  0 for (ListIterator<Version> it = versionList.listIterator(versionList.size()); it.hasPrevious();) {
231  0 this.progressManager.startStep(flavorId);
232   
233  0 Version version = it.previous();
234   
235  0 Extension extension = tryInstallExtension(new ExtensionId(flavorId, version), namespace);
236  0 if (extension != null) {
237  0 return extension;
238    }
239    }
240    } finally {
241  0 this.progressManager.popLevelProgress(flavorId);
242    }
243   
244  0 return null;
245    }
246    }