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

File DefaultAttachmentClassLoaderFactory.java

 

Coverage histogram

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

Code metrics

8
20
4
1
143
73
9
0.45
5
4
2.25

Classes

Class Line # Actions
DefaultAttachmentClassLoaderFactory 51 20 0% 9 1
0.9687596.9%
 

Contributing tests

This file is covered by 57 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.rendering.internal.macro.script;
21   
22    import java.io.UnsupportedEncodingException;
23    import java.net.URI;
24    import java.net.URISyntaxException;
25    import java.net.URL;
26    import java.net.URLEncoder;
27    import java.net.URLStreamHandlerFactory;
28    import java.util.LinkedHashSet;
29    import java.util.Set;
30    import java.util.StringTokenizer;
31   
32    import javax.inject.Inject;
33    import javax.inject.Named;
34    import javax.inject.Singleton;
35   
36    import org.apache.commons.lang3.StringUtils;
37    import org.xwiki.classloader.ExtendedURLClassLoader;
38    import org.xwiki.classloader.ExtendedURLStreamHandler;
39    import org.xwiki.classloader.URIClassLoader;
40    import org.xwiki.component.annotation.Component;
41   
42    /**
43    * Supports the following syntax for JARs attached to wiki pages:
44    * {@code attach:(wiki):(space).(page)@(attachment)}.
45    *
46    * @version $Id: 2df95e73b8ac06265c94b64bd4c01f2a4b88e225 $
47    * @since 2.0.1
48    */
49    @Component
50    @Singleton
 
51    public class DefaultAttachmentClassLoaderFactory implements AttachmentClassLoaderFactory
52    {
53    /**
54    * The prefix to specify a JAR attached to a wiki page. This is because we also support {@code http://} prefixes
55    * to load JARs from remote locations.
56    */
57    private static final String ATTACHMENT_PREFIX = "attach:";
58   
59    /**
60    * The Stream handler factory to use in the created classloader in order to be able to load our custom
61    * {@code attachmentjar} custom protocol.
62    */
63    @Inject
64    private URLStreamHandlerFactory streamHandlerFactory;
65   
66    /**
67    * The stream handler for our custom {@code attachmentjar} protocol. We use it to get access to the protocol
68    * name and to transform from URI to URL.
69    */
70    @Inject
71    @Named("attachmentjar")
72    private ExtendedURLStreamHandler attachmentJarHandler;
73   
 
74  6297 toggle @Override
75    public ExtendedURLClassLoader createAttachmentClassLoader(String jarURLs, ClassLoader parent) throws Exception
76    {
77  6297 URI[] uris = extractURIs(jarURLs).toArray(new URI[0]);
78  6297 return new URIClassLoader(uris, parent, this.streamHandlerFactory);
79    }
80   
 
81  4 toggle @Override
82    public void extendAttachmentClassLoader(String jarURLs, ExtendedURLClassLoader source) throws Exception
83    {
84  4 for (URI uri : extractURIs(jarURLs)) {
85  4 if (uri.getScheme().equalsIgnoreCase(this.attachmentJarHandler.getProtocol())) {
86  1 source.addURL(new URL(null, uri.toString(),
87    this.streamHandlerFactory.createURLStreamHandler(uri.getScheme())));
88    } else {
89  3 source.addURL(uri.toURL());
90    }
91    }
92    }
93   
94    /**
95    * @param jarURLs the comma-separated list of JARs locations, specified using either an already registered
96    * protocol (such as {@code http}) or using the format {@code attach:(wiki):(space).(page)@(filename)}.
97    * @return the list of URIs
98    * @throws URISyntaxException in case of an invalid URI
99    */
 
100  6300 toggle private Set<URI> extractURIs(String jarURLs) throws URISyntaxException
101    {
102    // Parse the passed JAR URLs to tokenize it.
103  6300 Set<URI> uris = new LinkedHashSet<URI>();
104  6301 if (StringUtils.isNotEmpty(jarURLs)) {
105  5 StringTokenizer tokenizer = new StringTokenizer(jarURLs, ",");
106  13 while (tokenizer.hasMoreElements()) {
107  8 String token = tokenizer.nextToken().trim();
108  8 if (token.startsWith(ATTACHMENT_PREFIX)) {
109  3 uris.add(createURI(token));
110    } else {
111  5 uris.add(new URI(token));
112    }
113    }
114    }
115   
116  6300 return uris;
117    }
118   
119    /**
120    * @param attachmentReference the attachment reference in the form {@code attach:(wiki):(space).(page)@(filename)}
121    * @return a URI of the form {@code attachmentjar://(wiki):(space).(page)@(filename)}.
122    * The {@code (wiki):(space).(page)@(filename)} part is URL-encoded
123    * @throws URISyntaxException in case of an invalid URI
124    */
 
125  3 toggle private URI createURI(String attachmentReference) throws URISyntaxException
126    {
127  3 String uriBody = attachmentReference.substring(ATTACHMENT_PREFIX.length());
128   
129  3 try {
130    // Note: we encode using UTF8 since it's the W3C recommendation.
131    // See http://www.w3.org/TR/html40/appendix/notes.html#non-ascii-chars
132    // TODO: Once the xwiki-url module is usable, refactor this code to use it and remove the need to
133    // perform explicit encoding here.
134  3 uriBody = URLEncoder.encode(uriBody, "UTF-8");
135    } catch (UnsupportedEncodingException e) {
136    // Not supporting UTF-8 as a valid encoding for some reasons. We consider XWiki cannot work
137    // without that encoding.
138  0 throw new RuntimeException("Failed to URL encode [" + uriBody + "] using UTF-8.", e);
139    }
140   
141  3 return new URI(this.attachmentJarHandler.getProtocol() + "://" + uriBody);
142    }
143    }