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

File JarURLStreamHandler.java

 

Coverage histogram

../../../../../../img/srcFileCovDistChart6.png
69% of files have more coverage

Code metrics

10
31
3
1
159
84
10
0.32
10.33
3
3.33

Classes

Class Line # Actions
JarURLStreamHandler 59 31 0% 10 20
0.5454545654.5%
 

Contributing tests

This file is covered by 4 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.classloader.internal.protocol.jar;
21   
22    import java.io.IOException;
23    import java.net.MalformedURLException;
24    import java.net.URL;
25    import java.net.URLConnection;
26    import java.net.URLStreamHandler;
27    import java.net.URLStreamHandlerFactory;
28    import java.util.regex.Matcher;
29    import java.util.regex.Pattern;
30   
31    import javax.inject.Inject;
32    import javax.inject.Named;
33    import javax.inject.Singleton;
34   
35    import org.xwiki.classloader.ExtendedURLStreamHandler;
36    import org.xwiki.classloader.internal.protocol.jar.JarURLConnection.JarOpener;
37    import org.xwiki.component.annotation.Component;
38   
39    import edu.emory.mathcs.util.classloader.ResourceUtils;
40   
41    /**
42    * Handler for the "jar" protocol. Note that we don't use the JDK's JAR URL Connection class since it doesn't support
43    * using a URL Stream Handler Factory for handling nested protocols (the protocol inside the "jar" protocol, for
44    * example: {@code jar:http://...} or {@code jar:attachmentjar://...}, etc).
45    * <p>
46    * Originally written by Dawid Kurzyniec and released to the public domain, as explained at
47    * http://creativecommons.org/licenses/publicdomain
48    * </p>
49    * <p>
50    * Source: http://dcl.mathcs.emory.edu/php/loadPage.php?content=util/features.html#classloading
51    * </p>
52    *
53    * @version $Id: 3a4233e941eb0753b218d67f440448298ec5110c $
54    * @since 2.0.1
55    */
56    @Component
57    @Named("jar")
58    @Singleton
 
59    public class JarURLStreamHandler extends URLStreamHandler implements ExtendedURLStreamHandler
60    {
61    /**
62    * Used to parse the string representation of a {@code URL} into a {@code URL} using the format:
63    * "jar:" + url + "!" + /<path>/ + <file>? + "#"<anchor>?
64    */
65    private static final Pattern ABSOLUTE_JAR_URL_PATTERN =
66    Pattern.compile("jar:(.*)!(/(?:.*/)?)((?:[^/#]+)?)((?:#.*)?)");
67   
68    /**
69    * The JAR protocol name.
70    */
71    private static final String JAR_PROTOCOL = "jar";
72   
73    /**
74    * Separator for JAR in a URL.
75    */
76    private static final String JAR_PROTOCOL_SEPARATOR = "!";
77   
78    /**
79    * The actual logic to load JARs and cache them on the local filesystem.
80    */
81    private JarOpener opener = new JarProxy();
82   
83    /**
84    * Stream factory passed to the JAR URL Connection class we create so that it can support custom protocols even if
85    * they are not globally registered (the problems with global registration are described at
86    * http://accu.org/index.php/journals/1434).
87    */
88    @Inject
89    private URLStreamHandlerFactory handlerFactory;
90   
 
91  0 toggle @Override
92    public String getProtocol()
93    {
94  0 return JAR_PROTOCOL;
95    }
96   
 
97  6 toggle @Override
98    public URLConnection openConnection(URL url) throws IOException
99    {
100  6 return new JarURLConnection(url, this.opener, this.handlerFactory);
101    }
102   
103    /**
104    * {@inheritDoc}
105    *
106    * Implementation copied from Emory's Classloader Utilities. We had to copy it since we cannot extend Emory's
107    * JarURLStreamHandler implementation since it extends the JDK's JAR URL Connection (see this class's description
108    * to understand why we cannot use it).
109    *
110    * @see URLStreamHandler#parseURL(URL, String, int, int)
111    */
 
112  88 toggle @Override
113    protected void parseURL(URL u, String spec, int start, int limit)
114    {
115  88 Matcher matcher = ABSOLUTE_JAR_URL_PATTERN.matcher(spec);
116  88 if (matcher.matches()) {
117    // spec is an absolute URL
118  0 String base = matcher.group(1);
119  0 try {
120    // Verify
121  0 new URL(base);
122    } catch (MalformedURLException e) {
123  0 throw new IllegalArgumentException(e.toString());
124    }
125  0 String path = matcher.group(2) + matcher.group(3);
126  0 path = ResourceUtils.canonizePath(path);
127  0 String ref = matcher.group(4);
128  0 if (ref.length() == 0) {
129  0 ref = null;
130    } else {
131  0 ref = ref.substring(1);
132    }
133  0 setURL(u, JAR_PROTOCOL, "", -1, "", "", base + JAR_PROTOCOL_SEPARATOR + path, null, ref);
134    } else {
135  88 matcher = ABSOLUTE_JAR_URL_PATTERN.matcher(u.toString());
136  88 if (matcher.matches()) {
137  88 String ref = spec.substring(limit);
138  88 if (ref.length() == 0) {
139  88 ref = null;
140    } else {
141  0 ref = ref.substring(1);
142    }
143  88 String newSpec = spec.substring(start, limit);
144  88 String base = matcher.group(1);
145  88 String path;
146  88 if (newSpec.length() > 0 && newSpec.charAt(0) == '/') {
147  3 path = newSpec;
148    } else {
149  85 String cxtDir = matcher.group(2);
150  85 path = cxtDir + newSpec;
151    }
152  88 path = ResourceUtils.canonizePath(path);
153  88 setURL(u, JAR_PROTOCOL, "", -1, "", "", base + JAR_PROTOCOL_SEPARATOR + path, null, ref);
154    } else {
155  0 throw new IllegalArgumentException("Neither URL nor the spec are valid JAR URLs");
156    }
157    }
158    }
159    }