1. Project Clover database Sat Feb 2 2019 06:45:20 CET
  2. Package org.xwiki.extension.repository.internal.local

File LocalExtensionStorage.java

 

Coverage histogram

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

Code metrics

18
59
12
1
296
145
24
0.41
4.92
12
2

Classes

Class Line # Actions
LocalExtensionStorage 46 59 0% 24 13
0.8539325685.4%
 

Contributing tests

This file is covered by 93 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.repository.internal.local;
21   
22    import java.io.File;
23    import java.io.FileInputStream;
24    import java.io.FileNotFoundException;
25    import java.io.FileOutputStream;
26    import java.io.IOException;
27   
28    import javax.xml.parsers.ParserConfigurationException;
29    import javax.xml.transform.TransformerException;
30   
31    import org.slf4j.Logger;
32    import org.slf4j.LoggerFactory;
33    import org.xwiki.component.manager.ComponentLookupException;
34    import org.xwiki.component.manager.ComponentManager;
35    import org.xwiki.extension.ExtensionId;
36    import org.xwiki.extension.InvalidExtensionException;
37    import org.xwiki.extension.internal.PathUtils;
38    import org.xwiki.extension.repository.internal.ExtensionSerializer;
39   
40    /**
41    * Manipulate the extension filesystem repository storage.
42    *
43    * @version $Id: 6ec8eee082854f4d6c650ca9a09cfda0efe13629 $
44    * @since 4.0M1
45    */
 
46    public class LocalExtensionStorage
47    {
48    /**
49    * Logging tool.
50    */
51    private static final Logger LOGGER = LoggerFactory.getLogger(LocalExtensionStorage.class);
52   
53    /**
54    * The extension of the descriptor files.
55    */
56    private static final String DESCRIPTOR_EXT = "xed";
57   
58    /**
59    * The extension of the descriptor files prefixed with dot.
60    */
61    private static final String DESCRIPTOR_SUFFIX = '.' + DESCRIPTOR_EXT;
62   
63    /**
64    * The repository.
65    */
66    private DefaultLocalExtensionRepository repository;
67   
68    /**
69    * Used to read/write in the repository storage itself.
70    */
71    private ExtensionSerializer extensionSerializer;
72   
73    /**
74    * @see #getRootFolder()
75    */
76    private File rootFolder;
77   
78    /**
79    * @param repository the repository
80    * @param rootFolder the repository folder
81    * @param componentManager used to lookup needed components
82    * @throws ComponentLookupException can't find ExtensionSerializer
83    */
 
84  257 toggle public LocalExtensionStorage(DefaultLocalExtensionRepository repository, File rootFolder,
85    ComponentManager componentManager) throws ComponentLookupException
86    {
87  257 this.repository = repository;
88  257 this.rootFolder = rootFolder;
89   
90  257 this.extensionSerializer = componentManager.getInstance(ExtensionSerializer.class);
91    }
92   
93    /**
94    * @return the repository folder
95    */
 
96  1285 toggle public File getRootFolder()
97    {
98  1285 return this.rootFolder;
99    }
100   
101    /**
102    * Load extension from repository storage.
103    *
104    * @throws IOException when failing to load extensions
105    */
 
106  257 toggle protected void loadExtensions() throws IOException
107    {
108    // Load local extension from repository
109   
110  257 if (this.rootFolder.exists()) {
111  197 loadExtensions(this.rootFolder);
112    } else {
113  60 this.rootFolder.mkdirs();
114    }
115    }
116   
117    /**
118    * @param folder the folder from where to load the extension
119    * @throws IOException when failing to load extensions
120    */
 
121  2301 toggle protected void loadExtensions(File folder) throws IOException
122    {
123  2301 if (!this.rootFolder.exists()) {
124  0 throw new IOException("Directory does not exist: " + this.rootFolder);
125    }
126   
127  2301 if (!this.rootFolder.isDirectory()) {
128  0 throw new IOException("Not a directory: " + this.rootFolder);
129    }
130   
131  2301 File[] files = folder.listFiles();
132   
133  2301 if (files == null) {
134  0 throw new IOException("Could not list files: " + this.rootFolder);
135    }
136   
137  2301 for (File child : files) {
138  7108 if (child.isDirectory()) {
139  2104 loadExtensions(child);
140  5004 } else if (child.getName().endsWith(DESCRIPTOR_SUFFIX)) {
141  2502 try {
142  2502 DefaultLocalExtension localExtension = loadDescriptor(child);
143   
144  2502 this.repository.addLocalExtension(localExtension);
145    } catch (Exception e) {
146  0 LOGGER.warn("Failed to load extension from file [" + child + "] in local repository", e);
147    }
148    }
149    }
150    }
151   
152    /**
153    * Local extension descriptor from a file.
154    *
155    * @param descriptor the descriptor file
156    * @return the extension descriptor
157    * @throws InvalidExtensionException error when trying to load extension descriptor
158    */
 
159  2502 toggle private DefaultLocalExtension loadDescriptor(File descriptor) throws InvalidExtensionException
160    {
161  2502 FileInputStream fis;
162  2502 try {
163  2502 fis = new FileInputStream(descriptor);
164    } catch (FileNotFoundException e) {
165  0 throw new InvalidExtensionException("Failed to open descriptor for reading", e);
166    }
167   
168  2502 try {
169  2502 DefaultLocalExtension localExtension =
170    this.extensionSerializer.loadLocalExtensionDescriptor(this.repository, fis);
171   
172  2502 localExtension.setDescriptorFile(descriptor);
173  2502 localExtension.setFile(getFile(descriptor, DESCRIPTOR_EXT, localExtension.getType()));
174   
175  2502 if (!localExtension.getFile().getFile().exists()) {
176  0 throw new InvalidExtensionException("Failed to load local extension [" + descriptor + "]: ["
177    + localExtension.getFile() + "] file does not exists");
178    }
179   
180  2502 return localExtension;
181    } finally {
182  2502 try {
183  2502 fis.close();
184    } catch (IOException e) {
185  0 LOGGER.error("Failed to close stream for file [" + descriptor + "]", e);
186    }
187    }
188    }
189   
190    /***
191    * Update the extension descriptor in the filesystem repository.
192    *
193    * @param extension the local extension descriptor to save
194    * @throws ParserConfigurationException error when trying to save the descriptor
195    * @throws TransformerException error when trying to save the descriptor
196    * @throws IOException error when trying to save the descriptor
197    */
 
198  1364 toggle public void saveDescriptor(DefaultLocalExtension extension) throws ParserConfigurationException,
199    TransformerException, IOException
200    {
201  1364 File file = extension.getDescriptorFile();
202   
203  1364 if (file == null) {
204  514 file = getNewDescriptorFile(extension.getId());
205  514 extension.setDescriptorFile(file);
206    }
207   
208  1364 FileOutputStream fos = new FileOutputStream(file);
209   
210  1364 try {
211  1364 this.extensionSerializer.saveExtensionDescriptor(extension, fos);
212    } finally {
213  1364 fos.close();
214    }
215    }
216   
217    /**
218    * @param id the extension identifier
219    * @param type the extension type
220    * @return the file containing the extension
221    */
 
222  514 toggle protected File getNewExtensionFile(ExtensionId id, String type)
223    {
224  514 return new File(getRootFolder(), getFilePath(id, type));
225    }
226   
227    /**
228    * @param id the extension identifier
229    * @return the file containing the extension descriptor
230    */
 
231  514 toggle private File getNewDescriptorFile(ExtensionId id)
232    {
233  514 return new File(getRootFolder(), getFilePath(id, DESCRIPTOR_EXT));
234    }
235   
236    /**
237    * @param baseFile the extension file
238    * @param baseType the type of the extension
239    * @param type the type of the file to get
240    * @return the extension descriptor file
241    */
 
242  2502 toggle private File getFile(File baseFile, String baseType, String type)
243    {
244  2502 String baseName = getBaseName(baseFile.getName(), baseType);
245   
246  2502 return new File(baseFile.getParent(), baseName + '.' + PathUtils.encode(type));
247    }
248   
249    /**
250    * @param fileName the name of the file of the provided type
251    * @param type the type of the file
252    * @return the base name which is the name without the typed extension
253    */
 
254  2502 toggle private String getBaseName(String fileName, String type)
255    {
256  2502 return fileName.substring(0, fileName.length() - PathUtils.encode(type).length() - 1);
257    }
258   
259    /**
260    * Get file path in the local extension repository.
261    *
262    * @param id the extension id
263    * @param fileExtension the file extension
264    * @return the encoded file path
265    */
 
266  1028 toggle private String getFilePath(ExtensionId id, String fileExtension)
267    {
268  1028 String encodedId = PathUtils.encode(id.getId());
269  1028 String encodedVersion = PathUtils.encode(id.getVersion().toString());
270  1028 String encodedType = PathUtils.encode(fileExtension);
271   
272  1028 return encodedId + File.separator + encodedVersion + File.separator + encodedId + '-' + encodedVersion + '.'
273    + encodedType;
274    }
275   
276    /**
277    * Remove extension from storage.
278    *
279    * @param extension extension to remove
280    * @throws IOException error when deleting the extension
281    */
 
282  13 toggle public void removeExtension(DefaultLocalExtension extension) throws IOException
283    {
284  13 File descriptorFile = extension.getDescriptorFile();
285   
286  13 if (descriptorFile == null) {
287  0 throw new IOException("Exception does not exists");
288    }
289   
290  13 descriptorFile.delete();
291   
292  13 DefaultLocalExtensionFile extensionFile = extension.getFile();
293   
294  13 extensionFile.getFile().delete();
295    }
296    }