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

File FilesystemResourceReferenceSerializer.java

 

Coverage histogram

../../../../img/srcFileCovDistChart10.png
0% of files have more coverage

Code metrics

8
34
3
1
146
93
10
0.29
11.33
3
3.33

Classes

Class Line # Actions
FilesystemResourceReferenceSerializer 60 34 0% 10 3
0.9333333493.3%
 

Contributing tests

This file is covered by 2 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.webjars.internal;
21   
22    import java.io.File;
23    import java.io.FileOutputStream;
24    import java.io.IOException;
25    import java.io.InputStream;
26    import java.net.JarURLConnection;
27    import java.net.URISyntaxException;
28    import java.net.URL;
29    import java.util.ArrayList;
30    import java.util.Enumeration;
31    import java.util.List;
32    import java.util.jar.JarEntry;
33    import java.util.jar.JarFile;
34   
35    import javax.inject.Inject;
36    import javax.inject.Named;
37    import javax.inject.Provider;
38    import javax.inject.Singleton;
39   
40    import org.apache.commons.io.IOUtils;
41    import org.apache.commons.lang3.StringUtils;
42    import org.xwiki.component.annotation.Component;
43    import org.xwiki.resource.ResourceReferenceSerializer;
44    import org.xwiki.resource.SerializeResourceReferenceException;
45    import org.xwiki.resource.UnsupportedResourceReferenceException;
46    import org.xwiki.url.ExtendedURL;
47    import org.xwiki.url.filesystem.FilesystemExportContext;
48    import org.xwiki.url.internal.RelativeExtendedURL;
49   
50    /**
51    * Converts a {@link WebJarsResourceReference} into a {@link ExtendedURL} (with the Context Path added) that points
52    * to a absolute URL pointing to a file on the local filesystem. This can be used when exporting to HTML for example.
53    *
54    * @version $Id: 22a5f99662063f30d071ed7a078cbe06697286c5 $
55    * @since 7.2M1
56    */
57    @Component
58    @Named("filesystem")
59    @Singleton
 
60    public class FilesystemResourceReferenceSerializer
61    implements ResourceReferenceSerializer<WebJarsResourceReference, ExtendedURL>
62    {
63    /**
64    * Prefix for locating resource files (JavaScript, CSS) in the classloader.
65    */
66    private static final String WEBJARS_RESOURCE_PREFIX = "META-INF/resources/webjars";
67   
68    private static final String WEBJAR_PATH = "webjars";
69   
70    @Inject
71    private Provider<FilesystemExportContext> exportContextProvider;
72   
 
73  2 toggle @Override
74    public ExtendedURL serialize(WebJarsResourceReference reference)
75    throws SerializeResourceReferenceException, UnsupportedResourceReferenceException
76    {
77    // Copy the resource from the webjar to the filesystem
78  2 FilesystemExportContext exportContext = this.exportContextProvider.get();
79  2 try {
80  2 copyResourceFromJAR(WEBJARS_RESOURCE_PREFIX, reference.getResourceName(), WEBJAR_PATH, exportContext);
81    } catch (IOException e) {
82  0 throw new SerializeResourceReferenceException(
83    String.format("Failed to extract and copy WebJAR resource [%s]", reference.getResourceName()), e);
84    }
85   
86  2 List<String> pathSegments = new ArrayList<>();
87   
88    // Adjust path for links inside CSS files (since they need to be relative to the CSS file they're in).
89  5 for (int i = 0; i < exportContext.getCSSParentLevel(); i++) {
90  3 pathSegments.add("..");
91    }
92   
93  2 pathSegments.add(WEBJAR_PATH);
94  2 for (String resourceSegment : StringUtils.split(reference.getResourceName(), '/')) {
95  6 pathSegments.add(resourceSegment);
96    }
97   
98  2 return new RelativeExtendedURL(pathSegments);
99    }
100   
 
101  2 toggle private File getJARFile(String resourceName) throws IOException
102    {
103    // Get the JAR URL by looking up the passed resource name to extract the location of the JAR
104  2 URL resourceURL = Thread.currentThread().getContextClassLoader().getResource(resourceName);
105  2 JarURLConnection connection = (JarURLConnection) resourceURL.openConnection();
106  2 URL jarURL = connection.getJarFileURL();
107   
108  2 File file;
109  2 try {
110  2 file = new File(jarURL.toURI());
111    } catch (URISyntaxException e) {
112  0 file = new File(jarURL.getPath());
113    }
114   
115  2 return file;
116    }
117   
 
118  2 toggle private void copyResourceFromJAR(String resourcePrefix, String resourceName, String targetPrefix,
119    FilesystemExportContext exportContext) throws IOException
120    {
121    // Note that we cannot use ClassLoader.getResource() to access the resource since the resourcePath may point
122    // to a directory inside the JAR, and in this case we need to copy all resources inside that directory in the
123    // JAR!
124   
125  2 String resourcePath = String.format("%s/%s", resourcePrefix, resourceName);
126  2 JarFile jar = new JarFile(getJARFile(resourcePath));
127  26 for (Enumeration<JarEntry> enumeration = jar.entries(); enumeration.hasMoreElements();) {
128  24 JarEntry entry = enumeration.nextElement();
129  24 if (entry.getName().startsWith(resourcePath) && !entry.isDirectory()) {
130    // Copy the resource!
131    // TODO: Won't this cause collisions if the same resource is available on several subwikis for example?
132  2 String targetPath = targetPrefix + entry.getName().substring(resourcePrefix.length());
133  2 File targetLocation = new File(exportContext.getExportDir(), targetPath);
134  2 if (!targetLocation.exists()) {
135  2 targetLocation.getParentFile().mkdirs();
136  2 FileOutputStream fos = new FileOutputStream(targetLocation);
137  2 InputStream is = jar.getInputStream(entry);
138  2 IOUtils.copy(is, fos);
139  2 fos.close();
140  2 is.close();
141    }
142    }
143    }
144  2 jar.close();
145    }
146    }