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

File XarInstalledExtensionRepository.java

 

Coverage histogram

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

Code metrics

42
69
15
1
295
212
41
0.59
4.6
15
2.73

Classes

Class Line # Actions
XarInstalledExtensionRepository 67 69 0% 41 26
0.793650879.4%
 

Contributing tests

This file is covered by 21 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.repository;
21   
22    import java.io.IOException;
23    import java.util.ArrayList;
24    import java.util.Collection;
25    import java.util.LinkedHashSet;
26    import java.util.List;
27    import java.util.Locale;
28    import java.util.Map;
29    import java.util.Set;
30    import java.util.concurrent.ConcurrentHashMap;
31   
32    import javax.inject.Inject;
33    import javax.inject.Named;
34    import javax.inject.Singleton;
35   
36    import org.slf4j.Logger;
37    import org.xwiki.component.annotation.Component;
38    import org.xwiki.component.phase.Initializable;
39    import org.xwiki.component.phase.InitializationException;
40    import org.xwiki.extension.ExtensionId;
41    import org.xwiki.extension.InstallException;
42    import org.xwiki.extension.InstalledExtension;
43    import org.xwiki.extension.LocalExtension;
44    import org.xwiki.extension.ResolveException;
45    import org.xwiki.extension.UninstallException;
46    import org.xwiki.extension.repository.DefaultExtensionRepositoryDescriptor;
47    import org.xwiki.extension.repository.InstalledExtensionRepository;
48    import org.xwiki.extension.repository.internal.installed.AbstractInstalledExtensionRepository;
49    import org.xwiki.extension.xar.internal.handler.UnsupportedNamespaceException;
50    import org.xwiki.extension.xar.internal.handler.XarExtensionHandler;
51    import org.xwiki.extension.xar.internal.handler.XarHandlerUtils;
52    import org.xwiki.model.reference.DocumentReference;
53    import org.xwiki.model.reference.LocalDocumentReference;
54    import org.xwiki.model.reference.WikiReference;
55    import org.xwiki.xar.XarEntry;
56    import org.xwiki.xar.XarException;
57   
58    /**
59    * Local repository proxy for XAR extensions.
60    *
61    * @version $Id: 73ba5ec8c2fc0fb86a018f2b89dafc355e03d30d $
62    * @since 4.0M1
63    */
64    @Component
65    @Singleton
66    @Named(XarExtensionHandler.TYPE)
 
67    public class XarInstalledExtensionRepository extends AbstractInstalledExtensionRepository<XarInstalledExtension>
68    implements InstalledExtensionRepository, Initializable
69    {
70    @Inject
71    private transient InstalledExtensionRepository installedRepository;
72   
73    @Inject
74    private Logger logger;
75   
76    /**
77    * Index used to find extensions owners of a document installed on a specific wiki.
78    */
79    private Map<DocumentReference, Collection<XarInstalledExtension>> documents = new ConcurrentHashMap<>();
80   
81    /**
82    * Index used to find extensions owners of a document installed on root namespace.
83    */
84    private Map<LocalDocumentReference, Collection<XarInstalledExtension>> rootDocuments = new ConcurrentHashMap<>();
85   
 
86  27 toggle @Override
87    public void initialize() throws InitializationException
88    {
89  27 setDescriptor(new DefaultExtensionRepositoryDescriptor(XarExtensionHandler.TYPE, XarExtensionHandler.TYPE,
90    this.installedRepository.getDescriptor().getURI()));
91   
92  27 loadExtensions();
93    }
94   
 
95  25 toggle void pagesRemoved(ExtensionId extensionId, String namespace) throws UnsupportedNamespaceException
96    {
97  25 pagesUpdated(extensionId, namespace, false);
98    }
99   
 
100  63 toggle void pagesAdded(ExtensionId extensionId, String namespace) throws UnsupportedNamespaceException
101    {
102  63 pagesUpdated(extensionId, namespace, true);
103    }
104   
 
105  88 toggle private void pagesUpdated(ExtensionId extensionId, String namespace, boolean add)
106    throws UnsupportedNamespaceException
107    {
108  88 XarInstalledExtension installedExtension = (XarInstalledExtension) getInstalledExtension(extensionId);
109   
110  88 pagesUpdated(installedExtension, namespace, add);
111    }
112   
 
113  113 toggle private void pagesUpdated(XarInstalledExtension installedExtension, String namespace, boolean add)
114    throws UnsupportedNamespaceException
115    {
116  113 if (installedExtension != null) {
117  111 for (XarEntry xarEntry : installedExtension.getXarPackage().getEntries()) {
118  457 if (namespace != null) {
119  298 DocumentReference reference = new DocumentReference(xarEntry,
120    new WikiReference(XarHandlerUtils.getWikiFromNamespace(namespace)));
121   
122  298 synchronized (this.documents) {
123  298 Collection<XarInstalledExtension> referenceExtensions = this.documents.get(reference);
124  298 if (referenceExtensions != null || add) {
125  298 Set<XarInstalledExtension> newSet = referenceExtensions != null
126    ? new LinkedHashSet<>(referenceExtensions) : new LinkedHashSet<>();
127   
128  298 if (add) {
129  206 newSet.add(installedExtension);
130    } else {
131  92 newSet.remove(installedExtension);
132    }
133   
134  298 this.documents.put(reference, newSet);
135    }
136    }
137    } else {
138  159 synchronized (this.rootDocuments) {
139  159 Collection<XarInstalledExtension> referenceExtensions = this.rootDocuments.get(xarEntry);
140  159 if (referenceExtensions != null || add) {
141  159 Set<XarInstalledExtension> newSet = referenceExtensions != null
142    ? new LinkedHashSet<>(referenceExtensions) : new LinkedHashSet<>();
143   
144  159 if (add) {
145  131 newSet.add(installedExtension);
146    } else {
147  28 newSet.remove(installedExtension);
148    }
149   
150  159 this.rootDocuments.put(xarEntry, newSet);
151    }
152    }
153    }
154    }
155    }
156    }
157   
 
158  88 toggle void updateCachedXarExtension(ExtensionId extensionId)
159    {
160  88 InstalledExtension installedExtension = this.installedRepository.getInstalledExtension(extensionId);
161   
162  88 if (installedExtension != null && installedExtension.getType().equals(XarExtensionHandler.TYPE)) {
163  62 if (getInstalledExtension(installedExtension.getId()) == null) {
164  62 try {
165  62 addCacheXarExtension(installedExtension);
166    } catch (Exception e) {
167  0 this.logger.error("Failed to parse extension [{}]", installedExtension.getId(), e);
168    }
169    }
170    } else {
171  26 removeCachedXarExtension(extensionId);
172    }
173    }
174   
 
175  87 toggle private XarInstalledExtension addCacheXarExtension(InstalledExtension installedExtension)
176    throws IOException, XarException
177    {
178  87 XarInstalledExtension xarExtension = new XarInstalledExtension(installedExtension, this);
179   
180  87 addCachedExtension(xarExtension);
181   
182  87 return xarExtension;
183    }
184   
 
185  26 toggle protected void removeCachedXarExtension(ExtensionId extensionId)
186    {
187  26 XarInstalledExtension extension = (XarInstalledExtension) getInstalledExtension(extensionId);
188   
189  26 if (extension != null) {
190  24 super.removeCachedExtension(extension);
191    }
192    }
193   
 
194  27 toggle private void loadExtensions()
195    {
196  27 for (InstalledExtension localExtension : this.installedRepository.getInstalledExtensions()) {
197  25 if (localExtension.getType().equalsIgnoreCase(XarExtensionHandler.TYPE)) {
198  25 try {
199    // Add XAR extension to the cache
200  25 XarInstalledExtension xarInstalledExtension = addCacheXarExtension(localExtension);
201   
202    // Add extension pages to the index
203  25 if (xarInstalledExtension.getNamespaces() == null) {
204  25 pagesUpdated(xarInstalledExtension, null, true);
205    } else {
206  0 for (String namespace : localExtension.getNamespaces()) {
207  0 pagesUpdated(xarInstalledExtension, namespace, true);
208    }
209    }
210    } catch (Exception e) {
211  0 this.logger.error("Failed to parse extension [{}]", localExtension.getId(), e);
212   
213  0 continue;
214    }
215    }
216    }
217    }
218   
219    /**
220    * @param reference the reference of the document
221    * @return the extension owners of the passed document
222    * @since 8.1M2
223    */
 
224  157 toggle public Collection<XarInstalledExtension> getXarInstalledExtensions(DocumentReference reference)
225    {
226  157 Collection<XarInstalledExtension> wikiExtensions = this.documents
227  157 .get(reference.getLocale() == null ? new DocumentReference(reference, Locale.ROOT) : reference);
228  157 Collection<XarInstalledExtension> rootExtensions =
229  157 this.rootDocuments.get(reference.getLocaleDocumentReference().getLocale() == null
230    ? new LocalDocumentReference(reference.getLocaleDocumentReference(), Locale.ROOT)
231    : reference.getLocaleDocumentReference());
232   
233  157 List<XarInstalledExtension> allExtensions = new ArrayList<>();
234   
235  157 if (wikiExtensions != null) {
236  95 allExtensions.addAll(wikiExtensions);
237    }
238   
239  157 if (rootExtensions != null) {
240  81 allExtensions.addAll(rootExtensions);
241    }
242   
243  157 return allExtensions;
244    }
245   
246    // InstalledExtensionRepository
247   
 
248  2 toggle @Override
249    public InstalledExtension getInstalledExtension(String id, String namespace)
250    {
251  2 InstalledExtension extension = this.installedRepository.getInstalledExtension(id, namespace);
252   
253  2 if (extension != null) {
254  1 if (extension.getType().equals(XarExtensionHandler.TYPE)) {
255  1 extension = this.extensions.get(extension.getId());
256    } else {
257  0 extension = null;
258    }
259    }
260   
261  2 return extension;
262    }
263   
 
264  0 toggle @Override
265    public InstalledExtension installExtension(LocalExtension extension, String namespace, boolean dependency,
266    Map<String, Object> properties) throws InstallException
267    {
268  0 throw new UnsupportedOperationException("Not implemented");
269    }
270   
 
271  0 toggle @Override
272    public void uninstallExtension(InstalledExtension extension, String namespace) throws UninstallException
273    {
274  0 throw new UnsupportedOperationException("Not implemented");
275    }
276   
 
277  0 toggle @Override
278    public Collection<InstalledExtension> getBackwardDependencies(String id, String namespace) throws ResolveException
279    {
280  0 InstalledExtension extension = this.installedRepository.getInstalledExtension(id, namespace);
281   
282  0 return extension.getType().equals(XarExtensionHandler.TYPE)
283    ? this.installedRepository.getBackwardDependencies(id, namespace) : null;
284    }
285   
 
286  0 toggle @Override
287    public Map<String, Collection<InstalledExtension>> getBackwardDependencies(ExtensionId extensionId)
288    throws ResolveException
289    {
290  0 InstalledExtension extension = this.installedRepository.resolve(extensionId);
291   
292  0 return extension.getType().equals(XarExtensionHandler.TYPE)
293    ? this.installedRepository.getBackwardDependencies(extensionId) : null;
294    }
295    }