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

File DefaultDistributionManager.java

 

Coverage histogram

../../../../../img/srcFileCovDistChart7.png
64% of files have more coverage

Code metrics

28
100
21
1
431
294
42
0.42
4.76
21
2

Classes

Class Line # Actions
DefaultDistributionManager 74 100 0% 42 56
0.6241610662.4%
 

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.extension.distribution.internal;
21   
22    import java.util.Arrays;
23    import java.util.List;
24    import java.util.Map;
25    import java.util.concurrent.ConcurrentHashMap;
26   
27    import javax.inject.Inject;
28    import javax.inject.Provider;
29    import javax.inject.Singleton;
30   
31    import org.slf4j.Logger;
32    import org.xwiki.component.annotation.Component;
33    import org.xwiki.component.manager.ComponentLookupException;
34    import org.xwiki.component.manager.ComponentManager;
35    import org.xwiki.component.phase.Initializable;
36    import org.xwiki.component.phase.InitializationException;
37    import org.xwiki.context.ExecutionContext;
38    import org.xwiki.context.ExecutionContextException;
39    import org.xwiki.context.ExecutionContextManager;
40    import org.xwiki.extension.CoreExtension;
41    import org.xwiki.extension.ExtensionId;
42    import org.xwiki.extension.distribution.internal.job.DistributionJob;
43    import org.xwiki.extension.distribution.internal.job.DistributionJobStatus;
44    import org.xwiki.extension.distribution.internal.job.DistributionRequest;
45    import org.xwiki.extension.distribution.internal.job.FarmDistributionJob;
46    import org.xwiki.extension.distribution.internal.job.FarmDistributionJobStatus;
47    import org.xwiki.extension.distribution.internal.job.WikiDistributionJob;
48    import org.xwiki.extension.distribution.internal.job.WikiDistributionJobStatus;
49    import org.xwiki.extension.repository.CoreExtensionRepository;
50    import org.xwiki.extension.version.internal.DefaultVersion;
51    import org.xwiki.job.Job;
52    import org.xwiki.job.JobStatusStore;
53    import org.xwiki.job.event.status.JobStatus;
54    import org.xwiki.logging.LoggerManager;
55    import org.xwiki.model.reference.DocumentReference;
56    import org.xwiki.model.reference.WikiReference;
57    import org.xwiki.observation.ObservationManager;
58    import org.xwiki.security.authorization.AuthorizationManager;
59    import org.xwiki.security.authorization.Right;
60   
61    import com.google.common.base.Objects;
62    import com.xpn.xwiki.XWikiContext;
63    import com.xpn.xwiki.XWikiException;
64    import com.xpn.xwiki.plugin.rightsmanager.RightsManager;
65   
66    /**
67    * Default {@link DistributionManager} implementation.
68    *
69    * @version $Id: 73689ee8e13511e0c75bbd5927ca9319804399b1 $
70    * @since 4.2M3
71    */
72    @Component
73    @Singleton
 
74    public class DefaultDistributionManager implements DistributionManager, Initializable
75    {
76    private static final String JOBID = "distribution";
77   
78    /**
79    * The repository with core modules provided by the platform.
80    */
81    @Inject
82    private CoreExtensionRepository coreExtensionRepository;
83   
84    @Inject
85    private JobStatusStore jobStore;
86   
87    /**
88    * Used to lookup components dynamically.
89    */
90    @Inject
91    private ComponentManager componentManager;
92   
93    /**
94    * Used to create a new Execution Context from scratch.
95    */
96    @Inject
97    private ExecutionContextManager executionContextManager;
98   
99    /**
100    * Used to send extensions installation and upgrade related events.
101    */
102    @Inject
103    protected Provider<ObservationManager> observationManagerProvider;
104   
105    /**
106    * Used to isolate job related log.
107    */
108    @Inject
109    protected Provider<LoggerManager> loggerManagerProvider;
110   
111    /**
112    * Used to check various rights.
113    */
114    @Inject
115    private AuthorizationManager authorizationManager;
116   
117    /**
118    * Used to access current {@link XWikiContext}.
119    */
120    @Inject
121    private Provider<XWikiContext> xcontextProvider;
122   
123    /**
124    * USed to manipulated jobs statuses.
125    */
126    @Inject
127    private JobStatusStore jobStatusStorage;
128   
129    @Inject
130    private Logger logger;
131   
132    private CoreExtension distributionExtension;
133   
134    private ExtensionId mainUIExtensionId;
135   
136    private ExtensionId wikiUIExtensionId;
137   
138    private FarmDistributionJob farmDistributionJob;
139   
140    private Map<String, WikiDistributionJob> wikiDistributionJobs =
141    new ConcurrentHashMap<String, WikiDistributionJob>();
142   
 
143  1 toggle @Override
144    public void initialize() throws InitializationException
145    {
146    // Get the current distribution
147  1 this.distributionExtension = this.coreExtensionRepository.getEnvironmentExtension();
148   
149    // Extract various configuration from the distribution extension
150  1 if (this.distributionExtension != null) {
151    // Distribution UI
152  1 String mainUIId = this.distributionExtension.getProperty("xwiki.extension.distribution.ui");
153   
154  1 if (mainUIId != null) {
155  0 String mainUIVersion =
156    this.distributionExtension.getProperty("xwiki.extension.distribution.ui.version");
157   
158  0 this.mainUIExtensionId =
159  0 new ExtensionId(mainUIId, mainUIVersion != null ? new DefaultVersion(mainUIVersion)
160    : this.distributionExtension.getId().getVersion());
161    }
162   
163  1 String wikiUIId = this.distributionExtension.getProperty("xwiki.extension.distribution.wikiui");
164   
165  1 if (wikiUIId != null) {
166  1 String wikiUIVersion =
167    this.distributionExtension.getProperty("xwiki.extension.distribution.wikiui.version");
168   
169  1 this.wikiUIExtensionId =
170  1 new ExtensionId(wikiUIId, wikiUIVersion != null ? new DefaultVersion(wikiUIVersion)
171    : this.distributionExtension.getId().getVersion());
172    }
173    }
174    }
175   
 
176  4 toggle private List<String> getFarmJobId()
177    {
178  4 return Arrays.asList(JOBID);
179    }
180   
 
181  0 toggle @Override
182    public FarmDistributionJob startFarmJob()
183    {
184  0 try {
185  0 this.farmDistributionJob = this.componentManager.getInstance(Job.class, "distribution");
186   
187  0 XWikiContext xcontext = this.xcontextProvider.get();
188   
189  0 final DistributionRequest request = new DistributionRequest();
190  0 request.setId(getFarmJobId());
191  0 request.setWiki(xcontext.getMainXWiki());
192  0 request.setUserReference(xcontext.getUserReference());
193   
194  0 Thread distributionJobThread = new Thread(new Runnable()
195    {
 
196  0 toggle @Override
197    public void run()
198    {
199    // Create a clean Execution Context
200  0 ExecutionContext context = new ExecutionContext();
201   
202  0 try {
203  0 executionContextManager.initialize(context);
204    } catch (ExecutionContextException e) {
205  0 throw new RuntimeException("Failed to initialize farm distribution job execution context", e);
206    }
207   
208  0 farmDistributionJob.initialize(request);
209  0 farmDistributionJob.run();
210    }
211    });
212   
213  0 distributionJobThread.setDaemon(true);
214  0 distributionJobThread.setName("Farm distribution initialization");
215  0 distributionJobThread.start();
216   
217    // Wait until the job is ready (or finished)
218  0 this.farmDistributionJob.awaitReady();
219   
220  0 return this.farmDistributionJob;
221    } catch (ComponentLookupException e) {
222  0 this.logger.error("Failed to create farm distribution job", e);
223    }
224   
225  0 return null;
226    }
227   
 
228  25 toggle private List<String> getWikiJobId(String wiki)
229    {
230  25 return Arrays.asList(JOBID, "wiki", wiki);
231    }
232   
 
233  3 toggle @Override
234    public WikiDistributionJob startWikiJob(String wiki)
235    {
236  3 try {
237  3 WikiDistributionJob wikiJob = this.componentManager.getInstance(Job.class, "wikidistribution");
238  3 this.wikiDistributionJobs.put(wiki, wikiJob);
239   
240  3 final DistributionRequest request = new DistributionRequest();
241  3 request.setId(getWikiJobId(wiki));
242  3 request.setWiki(wiki);
243  3 request.setUserReference(this.xcontextProvider.get().getUserReference());
244   
245  3 Thread distributionJobThread = new Thread(new Runnable()
246    {
 
247  3 toggle @Override
248    public void run()
249    {
250    // Create a clean Execution Context
251  3 ExecutionContext context = new ExecutionContext();
252   
253  3 try {
254  3 executionContextManager.initialize(context);
255    } catch (ExecutionContextException e) {
256  0 throw new RuntimeException("Failed to initialize wiki distribution job execution context", e);
257    }
258   
259  3 WikiDistributionJob job = wikiDistributionJobs.get(request.getWiki());
260  3 job.initialize(request);
261  3 job.run();
262    }
263    });
264   
265  3 distributionJobThread.setDaemon(true);
266  3 distributionJobThread.setName("Distribution initialization of wiki [" + wiki + "]");
267  3 distributionJobThread.start();
268   
269    // Wait until the job is ready (or finished)
270  3 wikiJob.awaitReady();
271   
272  3 return wikiJob;
273    } catch (ComponentLookupException e) {
274  0 this.logger.error("Failed to create distribution job for wiki [" + wiki + "]", e);
275    }
276   
277  0 return null;
278    }
279   
 
280  4 toggle private DistributionState getDistributionState(DistributionJobStatus<?> previousStatus)
281    {
282  4 return DistributionJobStatus.getDistributionState(
283  4 previousStatus != null ? previousStatus.getDistributionExtension() : null,
284  4 this.distributionExtension != null ? this.distributionExtension.getId() : null);
285    }
286   
 
287  4 toggle @Override
288    public DistributionState getFarmDistributionState()
289    {
290  4 FarmDistributionJobStatus previousStatus = null;
291   
292  4 try {
293  4 previousStatus = getPreviousFarmJobStatus();
294    } catch (Exception e) {
295  0 this.logger.error("Failed to load previous status", e);
296    }
297   
298  4 return getDistributionState(previousStatus);
299    }
300   
 
301  0 toggle @Override
302    public DistributionState getWikiDistributionState(String wiki)
303    {
304  0 return getDistributionState(getPreviousWikiJobStatus(wiki));
305    }
306   
 
307  8 toggle @Override
308    public CoreExtension getDistributionExtension()
309    {
310  8 return this.distributionExtension;
311    }
312   
 
313  0 toggle @Override
314    public ExtensionId getMainUIExtensionId()
315    {
316  0 return this.mainUIExtensionId;
317    }
318   
 
319  15 toggle @Override
320    public ExtensionId getWikiUIExtensionId()
321    {
322  15 return this.wikiUIExtensionId;
323    }
324   
 
325  4 toggle @Override
326    public FarmDistributionJobStatus getPreviousFarmJobStatus()
327    {
328  4 JobStatus jobStatus = this.jobStore.getJobStatus(getFarmJobId());
329   
330  4 FarmDistributionJobStatus farmJobStatus;
331  4 if (jobStatus != null) {
332  0 if (jobStatus instanceof FarmDistributionJobStatus) {
333  0 farmJobStatus = (FarmDistributionJobStatus) jobStatus;
334    } else {
335    // RETRO-COMPATIBILITY: the status used to be a DistributionJobStatus
336  0 farmJobStatus =
337    new FarmDistributionJobStatus(jobStatus, this.observationManagerProvider.get(),
338    this.loggerManagerProvider.get());
339    }
340    } else {
341  4 farmJobStatus = null;
342    }
343   
344  4 return farmJobStatus;
345    }
346   
 
347  17 toggle @Override
348    public WikiDistributionJobStatus getPreviousWikiJobStatus(String wiki)
349    {
350  17 return (WikiDistributionJobStatus) this.jobStore.getJobStatus(getWikiJobId(wiki));
351    }
352   
 
353  50 toggle @Override
354    public FarmDistributionJob getFarmJob()
355    {
356  50 return this.farmDistributionJob;
357    }
358   
 
359  33 toggle @Override
360    public WikiDistributionJob getWikiJob(String wiki)
361    {
362  33 return this.wikiDistributionJobs.get(wiki);
363    }
364   
 
365  76 toggle @Override
366    public DistributionJob getCurrentDistributionJob()
367    {
368  76 XWikiContext xcontext = this.xcontextProvider.get();
369   
370  76 return xcontext.isMainWiki() ? getFarmJob() : getWikiJob(xcontext.getWikiId());
371    }
372   
 
373  4 toggle @Override
374    public boolean canDisplayDistributionWizard()
375    {
376  4 XWikiContext xcontext = this.xcontextProvider.get();
377   
378  4 DocumentReference currentUser = xcontext.getUserReference();
379   
380    // Check if its the user that started the DW (this avoid loosing all access to the DW during an install/upgrade)
381  4 DistributionJob job = getCurrentDistributionJob();
382  4 if (job != null && Objects.equal(currentUser, job.getRequest().getUserReference())) {
383  1 this.logger.debug("The user [{}] started the DW so he can access it", currentUser);
384   
385  1 return true;
386    }
387   
388    // If not guest make sure the user has admin right
389  3 if (currentUser != null) {
390  3 return this.authorizationManager.hasAccess(Right.ADMIN, currentUser,
391    new WikiReference(xcontext.getWikiId()));
392    }
393   
394    // Give guess access if there is no other user already registered
395  0 if (xcontext.isMainWiki()) {
396    // If there is no user on main wiki let guest access distribution wizard
397  0 try {
398  0 return RightsManager.getInstance().countAllGlobalUsersOrGroups(true, null, xcontext) == 0;
399    } catch (XWikiException e) {
400  0 this.logger.error("Failed to count global users", e);
401    }
402    }
403   
404  0 return false;
405    }
406   
 
407  3 toggle @Override
408    public void deletePreviousWikiJobStatus(String wiki)
409    {
410  3 this.jobStatusStorage.remove(getWikiJobId(wiki));
411  3 this.wikiDistributionJobs.remove(wiki);
412    }
413   
 
414  2 toggle @Override
415    public void copyPreviousWikiJobStatus(String sourceWiki, String targetWiki)
416    {
417  2 WikiDistributionJobStatus sourceStatus = getPreviousWikiJobStatus(sourceWiki);
418   
419  2 if (sourceStatus != null) {
420  2 WikiDistributionJobStatus targetStatus =
421    new WikiDistributionJobStatus(sourceStatus, this.observationManagerProvider.get(),
422    this.loggerManagerProvider.get());
423   
424  2 DistributionRequest request = targetStatus.getRequest();
425  2 request.setId(getWikiJobId(targetWiki));
426  2 request.setWiki(targetWiki);
427   
428  2 this.jobStatusStorage.store(targetStatus);
429    }
430    }
431    }