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

File XarExtensionHandler.java

 

Coverage histogram

../../../../../../img/srcFileCovDistChart8.png
54% of files have more coverage

Code metrics

34
83
8
1
303
217
35
0.42
10.38
8
4.38

Classes

Class Line # Actions
XarExtensionHandler 66 83 0% 35 26
0.79279.2%
 

Contributing tests

This file is covered by 18 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.handler;
21   
22    import java.io.File;
23    import java.io.IOException;
24    import java.util.Collection;
25    import java.util.HashSet;
26    import java.util.Map;
27    import java.util.Set;
28   
29    import javax.inject.Inject;
30    import javax.inject.Named;
31    import javax.inject.Singleton;
32   
33    import org.xwiki.component.annotation.Component;
34    import org.xwiki.component.manager.ComponentLookupException;
35    import org.xwiki.component.manager.ComponentManager;
36    import org.xwiki.context.Execution;
37    import org.xwiki.context.ExecutionContext;
38    import org.xwiki.extension.ExtensionException;
39    import org.xwiki.extension.InstallException;
40    import org.xwiki.extension.InstalledExtension;
41    import org.xwiki.extension.LocalExtension;
42    import org.xwiki.extension.UninstallException;
43    import org.xwiki.extension.handler.internal.AbstractExtensionHandler;
44    import org.xwiki.extension.job.internal.AbstractExtensionJob;
45    import org.xwiki.extension.job.plan.ExtensionPlan;
46    import org.xwiki.extension.repository.InstalledExtensionRepository;
47    import org.xwiki.extension.repository.LocalExtensionRepository;
48    import org.xwiki.extension.xar.internal.handler.packager.PackageConfiguration;
49    import org.xwiki.extension.xar.internal.handler.packager.Packager;
50    import org.xwiki.extension.xar.internal.repository.XarInstalledExtension;
51    import org.xwiki.job.Job;
52    import org.xwiki.job.JobContext;
53    import org.xwiki.job.Request;
54    import org.xwiki.logging.marker.TranslationMarker;
55    import org.xwiki.model.reference.DocumentReference;
56    import org.xwiki.xar.XarEntry;
57    import org.xwiki.xar.XarException;
58   
59    /**
60    * @version $Id: f6b75830464f2c766b4e171e93177607a186a889 $
61    * @since 4.0M1
62    */
63    @Component
64    @Singleton
65    @Named(XarExtensionHandler.TYPE)
 
66    public class XarExtensionHandler extends AbstractExtensionHandler
67    {
68    public static final String TYPE = "xar";
69   
70    protected static final String PROPERTY_USERREFERENCE = "user.reference";
71   
72    protected static final String PROPERTY_CALLERREFERENCE = "caller.reference";
73   
74    protected static final String PROPERTY_CHECKRIGHTS = "checkrights";
75   
76    private static final TranslationMarker LOG_EXTENSIONPLAN_BEGIN =
77    new TranslationMarker("extension.xar.log.extensionplan.begin");
78   
79    private static final TranslationMarker LOG_EXTENSIONPLAN_END =
80    new TranslationMarker("extension.xar.log.extensionplan.end");
81   
82    @Inject
83    private Packager packager;
84   
85    @Inject
86    @Named(XarExtensionHandler.TYPE)
87    private InstalledExtensionRepository xarRepository;
88   
89    @Inject
90    private ComponentManager componentManager;
91   
92    @Inject
93    private LocalExtensionRepository localRepository;
94   
95    /**
96    * Used to access the execution context.
97    */
98    @Inject
99    private Execution execution;
100   
 
101  135 toggle protected static DocumentReference getRequestUserReference(String property, Request request)
102    {
103  135 Object obj = request.getProperty(property);
104   
105  135 if (obj instanceof DocumentReference) {
106  132 return (DocumentReference) obj;
107    }
108   
109  3 return null;
110    }
111   
 
112  78 toggle private void initializePagesIndex(Request request) throws ExtensionException, XarException, IOException
113    {
114  78 ExecutionContext context = this.execution.getContext();
115   
116  78 if (context != null) {
117  78 ExtensionPlan plan = (ExtensionPlan) context.getProperty(AbstractExtensionJob.CONTEXTKEY_PLAN);
118   
119  78 if (plan != null) {
120  75 if (context.getProperty(XarExtensionPlan.CONTEXTKEY_XARINSTALLPLAN) == null) {
121  53 if (request.isVerbose()) {
122  53 this.logger.info(LOG_EXTENSIONPLAN_BEGIN, "Preparing XAR extension plan");
123    }
124   
125  53 context.setProperty(XarExtensionPlan.CONTEXTKEY_XARINSTALLPLAN,
126    new XarExtensionPlan(plan, this.xarRepository, this.localRepository));
127   
128  53 if (request.isVerbose()) {
129  53 this.logger.info(LOG_EXTENSIONPLAN_END, "XAR extension plan ready");
130    }
131    }
132    }
133    }
134    }
135   
 
136  60 toggle private XarExtensionPlan getXARExtensionPlan()
137    {
138  60 ExecutionContext context = this.execution.getContext();
139   
140  60 if (context != null) {
141  60 return (XarExtensionPlan) context.getProperty(XarExtensionPlan.CONTEXTKEY_XARINSTALLPLAN);
142    }
143   
144  0 return null;
145    }
146   
 
147  55 toggle @Override
148    public void install(LocalExtension localExtension, String namespace, Request request) throws InstallException
149    {
150    // Only import XAR when it's a local order (otherwise it will be imported several times and the wiki will
151    // probably not be in an expected state)
152  55 if (!request.isRemote()) {
153  55 String wiki;
154  55 try {
155  55 wiki = XarHandlerUtils.getWikiFromNamespace(namespace);
156    } catch (UnsupportedNamespaceException e) {
157  1 throw new InstallException("Failed to extract wiki id from namespace", e);
158    }
159   
160  54 installInternal(localExtension, wiki, request);
161    }
162    }
163   
 
164  6 toggle @Override
165    public void upgrade(Collection<InstalledExtension> previousLocalExtensions, LocalExtension newLocalExtension,
166    String namespace, Request request) throws InstallException
167    {
168    // Only import XAR when it's a local order (otherwise it will be imported several times and the wiki will
169    // probably not be in an expected state)
170  6 if (!request.isRemote()) {
171  6 String wiki;
172  6 try {
173  6 wiki = XarHandlerUtils.getWikiFromNamespace(namespace);
174    } catch (UnsupportedNamespaceException e) {
175  0 throw new InstallException("Failed to extract wiki id from namespace", e);
176    }
177   
178    // Install new pages
179  6 installInternal(newLocalExtension, wiki, request);
180    }
181    }
182   
 
183  60 toggle private void installInternal(LocalExtension newLocalExtension, String wiki, Request request) throws InstallException
184    {
185  60 try {
186  60 initializePagesIndex(request);
187    } catch (Exception e) {
188  0 throw new InstallException("Failed to initialize extension plan index", e);
189    }
190   
191    // import xar into wiki (add new version when the page already exists)
192  60 PackageConfiguration configuration =
193    createPackageConfiguration(newLocalExtension, request, wiki, getXARExtensionPlan());
194  60 try {
195  60 this.packager.importXAR("Install extension [" + newLocalExtension + "]",
196    new File(newLocalExtension.getFile().getAbsolutePath()), configuration);
197    } catch (Exception e) {
198  0 throw new InstallException("Failed to import xar for extension [" + newLocalExtension + "]", e);
199    }
200    }
201   
 
202  18 toggle @Override
203    public void uninstall(InstalledExtension installedExtension, String namespace, Request request)
204    throws UninstallException
205    {
206  18 try {
207  18 initializePagesIndex(request);
208    } catch (Exception e) {
209  0 throw new UninstallException("Failed to initialize extension plan index", e);
210    }
211   
212    // Only remove XAR when it's a local order (otherwise it will be deleted several times and the wiki will
213    // probably not be in an expected state)
214  18 if (!request.isRemote()) {
215  18 Job currentJob;
216  18 try {
217  18 currentJob = this.componentManager.<JobContext>getInstance(JobContext.class).getCurrentJob();
218    } catch (ComponentLookupException e1) {
219  0 currentJob = null;
220    }
221   
222  18 if (currentJob == null) {
223  0 String wiki;
224  0 try {
225  0 wiki = XarHandlerUtils.getWikiFromNamespace(namespace);
226    } catch (UnsupportedNamespaceException e) {
227  0 throw new UninstallException("Failed to extract wiki id from namespace", e);
228    }
229   
230    // TODO: delete pages from the wiki which belong only to this extension (several extension could have
231    // some common pages which will cause all sort of other issues but still could happen technically)
232   
233    // TODO: maybe remove only unmodified page ? At least ask for sure when question/answer system will be
234    // implemented
235   
236  0 PackageConfiguration configuration =
237    createPackageConfiguration(null, request, wiki, getXARExtensionPlan());
238  0 try {
239  0 XarInstalledExtension xarLocalExtension =
240    (XarInstalledExtension) this.xarRepository.resolve(installedExtension.getId());
241  0 Collection<XarEntry> pages = xarLocalExtension.getXarPackage().getEntries();
242  0 this.packager.unimportPages(pages, configuration);
243    } catch (Exception e) {
244    // Not supposed to be possible
245  0 throw new UninstallException(
246    "Failed to get xar extension [" + installedExtension.getId() + "] from xar repository", e);
247    }
248    } else {
249    // The actual delete of pages is done in XarExtensionJobFinishedListener
250    }
251    }
252    }
253   
 
254  60 toggle private PackageConfiguration createPackageConfiguration(LocalExtension extension, Request request, String wiki,
255    XarExtensionPlan xarExtensionPlan)
256    {
257  60 PackageConfiguration configuration = new PackageConfiguration();
258   
259  60 configuration.setInteractive(request.isInteractive());
260  60 configuration.setUser(getRequestUserReference(PROPERTY_USERREFERENCE, request));
261  60 configuration.setWiki(wiki);
262  60 configuration.setVerbose(request.isVerbose());
263  60 configuration.setSkipMandatorytDocuments(true);
264  60 configuration.setXarExtensionPlan(xarExtensionPlan);
265   
266  60 try {
267  60 Job currentJob = this.componentManager.<JobContext>getInstance(JobContext.class).getCurrentJob();
268  60 if (currentJob != null) {
269  57 configuration.setJobStatus(currentJob.getStatus());
270    }
271    } catch (Exception e) {
272  0 this.logger.error("Failed to lookup JobContext, it will be impossible to do interactive install");
273    }
274   
275    // Filter entries to import if there is a plan
276  60 if (extension != null && xarExtensionPlan != null) {
277  57 Map<String, Map<XarEntry, LocalExtension>> nextXAREntries = xarExtensionPlan.nextXAREntries;
278   
279  57 Set<String> entriesToImport = new HashSet<String>();
280   
281  57 Map<XarEntry, LocalExtension> nextXAREntriesOnRoot = nextXAREntries.get(null);
282  57 if (nextXAREntriesOnRoot != null) {
283  16 for (Map.Entry<XarEntry, LocalExtension> entry : nextXAREntriesOnRoot.entrySet()) {
284  156 if (entry.getValue() == extension) {
285  86 entriesToImport.add(entry.getKey().getEntryName());
286    }
287    }
288    }
289  57 Map<XarEntry, LocalExtension> nextXAREntriesOnWiki = nextXAREntries.get(wiki);
290  57 if (nextXAREntriesOnWiki != null) {
291  57 for (Map.Entry<XarEntry, LocalExtension> entry : nextXAREntriesOnWiki.entrySet()) {
292  495 if (entry.getValue() == extension) {
293  268 entriesToImport.add(entry.getKey().getEntryName());
294    }
295    }
296    }
297   
298  57 configuration.setEntriesToImport(entriesToImport);
299    }
300   
301  60 return configuration;
302    }
303    }