jaulib v1.3.0
Jau Support Library (C++, Java, ..)
TestJarUtil.java
Go to the documentation of this file.
1/**
2 * Author: Sven Gothel <sgothel@jausoft.com>
3 * Copyright (c) 2021 Gothel Software e.K.
4 * Copyright (c) 2011 Gothel Software e.K.
5 * Copyright (c) 2011 JogAmp Community.
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining
8 * a copy of this software and associated documentation files (the
9 * "Software"), to deal in the Software without restriction, including
10 * without limitation the rights to use, copy, modify, merge, publish,
11 * distribute, sublicense, and/or sell copies of the Software, and to
12 * permit persons to whom the Software is furnished to do so, subject to
13 * the following conditions:
14 *
15 * The above copyright notice and this permission notice shall be
16 * included in all copies or substantial portions of the Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
19 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
21 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
22 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
23 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
24 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25 */
26
27package jau.test.pkg;
28
29import java.io.IOException;
30import java.net.JarURLConnection;
31import java.net.MalformedURLException;
32import java.net.URISyntaxException;
33import java.net.URL;
34import java.net.URLClassLoader;
35import java.net.URLConnection;
36import java.net.URLStreamHandler;
37import java.util.Enumeration;
38import java.util.jar.JarEntry;
39import java.util.jar.JarFile;
40
41import org.jau.net.Uri;
42import org.jau.pkg.JarUtil;
43import org.jau.pkg.cache.TempCacheReg;
44import org.jau.pkg.cache.TempFileCache;
45import org.jau.pkg.cache.TempJarCache;
46import org.jau.sys.AndroidVersion;
47import org.jau.sys.RuntimeProps;
48import org.junit.Assert;
49import org.junit.BeforeClass;
50import org.junit.FixMethodOrder;
51import org.junit.Test;
52import org.junit.runners.MethodSorters;
53
54import jau.test.junit.util.JunitTracer;
55import jau.test.net.URIDumpUtil;
56
57@FixMethodOrder(MethodSorters.NAME_ASCENDING)
58public class TestJarUtil extends JunitTracer {
59 static TempFileCache fileCache;
60
61 @BeforeClass
62 public static void init() {
64 // ClassLoader -> JarURL doesn't work w/ Dalvik
65 setTestSupported(false);
66 // we allow basic TempFileCache initialization (test) ..
67 }
68 // may already been initialized by other test
69 // Assert.assertFalse(TempCacheReg.isTempFileCacheUsed());
70 Assert.assertTrue(TempFileCache.initSingleton());
71 Assert.assertTrue(TempCacheReg.isTempFileCacheUsed());
72
73 fileCache = new TempFileCache();
74 Assert.assertTrue(fileCache.isValid(false));
75 System.err.println("tmp dir: "+fileCache.getTempDir());
76 }
77
78 static class TestClassLoader extends URLClassLoader {
79 public TestClassLoader(final URL[] urls) {
80 super(urls);
81 }
82 public TestClassLoader(final URL[] urls, final ClassLoader parent) {
83 super(urls, parent);
84 }
85 }
86
87 void validateJarFile(final JarFile jarFile) throws IllegalArgumentException, IOException {
88 Assert.assertNotNull(jarFile);
89 Assert.assertTrue("jarFile has zero entries: "+jarFile, jarFile.size()>0);
90 final Enumeration<JarEntry> entries = jarFile.entries();
91 System.err.println("Entries of "+jarFile.getName()+": ");
92 int i = 0;
93 while(entries.hasMoreElements()) {
94 System.err.println(i+": "+entries.nextElement().getName());
95 i++;
96 }
97 }
98
99 void validateJarFileURL(final Uri jarFileURI) throws IllegalArgumentException, IOException, URISyntaxException {
100 Assert.assertNotNull(jarFileURI);
101 final URL jarFileURL = jarFileURI.toURL();
102 final URLConnection aURLc = jarFileURL.openConnection();
103 Assert.assertTrue("jarFileURI/URL has zero content: "+jarFileURL, aURLc.getContentLength()>0);
104 System.err.println("URLConnection: "+aURLc);
105 Assert.assertTrue("Not a JarURLConnection: "+aURLc, (aURLc instanceof JarURLConnection) );
106 final JarURLConnection jURLc = (JarURLConnection) aURLc;
107 final JarFile jarFile = jURLc.getJarFile();
108 validateJarFile(jarFile);
109 }
110
111 void validateJarUtil(final String expJarName, final String clazzBinName, final ClassLoader cl) throws IllegalArgumentException, IOException, URISyntaxException {
112 final Uri.Encoded expJarNameE = Uri.Encoded.cast(expJarName);
113 final Uri.Encoded jarName= JarUtil.getJarBasename(clazzBinName, cl);
114 Assert.assertNotNull(jarName);
115 Assert.assertEquals(expJarNameE, jarName);
116
117 final Uri jarUri = JarUtil.getJarUri(clazzBinName, cl);
118 Assert.assertNotNull(jarUri);
119 System.err.println("1 - jarUri:");
120 URIDumpUtil.showUri(jarUri);
121
122 final Uri jarSubUri = jarUri.getContainedUri();
123 Assert.assertNotNull(jarSubUri);
124 System.err.println("2 - jarSubUri:");
125 URIDumpUtil.showUri(jarSubUri);
126
127 final URL jarSubURL= jarSubUri.toURL();
128 final URLConnection urlConn = jarSubURL.openConnection();
129 Assert.assertTrue("jarSubURL has zero content: "+jarSubURL, urlConn.getContentLength()>0);
130 System.err.println("URLConnection of jarSubURL: "+urlConn);
131
132 final Uri jarFileURL = JarUtil.getJarFileUri(clazzBinName, cl);
133 validateJarFileURL(jarFileURL);
134
135 final JarFile jarFile = JarUtil.getJarFile(clazzBinName, cl);
136 validateJarFile(jarFile);
137 }
138
139 @Test
140 public void testJarUtilFlat01() throws IOException, IllegalArgumentException, URISyntaxException {
141 System.err.println("XXXXXXXXXXXXXXXXXXXXXXXXXXXX");
142 validateJarUtil("jaulib-fat.jar", "org.jau.base.JaulibVersion", this.getClass().getClassLoader());
143 System.err.println("XXXXXXXXXXXXXXXXXXXXXXXXXXXX");
144 }
145
146 // @Test // FIXME: Build ClassInJar0 and corresponding jar files
147 public void testJarUtilJarInJar01() throws IOException, ClassNotFoundException, IllegalArgumentException, URISyntaxException {
148 System.err.println("XXXXXXXXXXXXXXXXXXXXXXXXXXXX");
149
150 Assert.assertTrue(TempJarCache.initSingleton());
151 Assert.assertTrue(TempCacheReg.isTempJarCacheUsed(false));
152 Assert.assertTrue(TempJarCache.isInitialized(false));
153
154 final ClassLoader rootCL = this.getClass().getClassLoader();
155
156 // Get containing JAR file "TestJarsInJar.jar" and add it to the TempJarCache
157 TempJarCache.addAll(RuntimeProps.class, JarUtil.getJarFileUri("ClassInJar0", rootCL));
158
159 // Fetch and load the contained "ClassInJar1.jar"
160 final URL ClassInJar1_jarFileURL = JarUtil.getJarFileUri(TempJarCache.getResourceUri("ClassInJar1.jar")).toURL();
161 final ClassLoader cl = new URLClassLoader(new URL[] { ClassInJar1_jarFileURL }, rootCL);
162 Assert.assertNotNull(cl);
163 validateJarUtil("ClassInJar1.jar", "ClassInJar1", cl);
164 System.err.println("XXXXXXXXXXXXXXXXXXXXXXXXXXXX");
165 }
166
167 // @Test // FIXME: Build ClassInJar0 and corresponding jar files
168 public void testJarUtilJarInJar02() throws IOException, ClassNotFoundException, IllegalArgumentException, URISyntaxException {
169 System.err.println("XXXXXXXXXXXXXXXXXXXXXXXXXXXX");
170
171 Assert.assertTrue(TempJarCache.initSingleton());
172 Assert.assertTrue(TempCacheReg.isTempJarCacheUsed(false));
173 Assert.assertTrue(TempJarCache.isInitialized(false));
174
175 final ClassLoader rootCL = this.getClass().getClassLoader();
176
177 // Get containing JAR file "TestJarsInJar.jar" and add it to the TempJarCache
178 TempJarCache.addAll(RuntimeProps.class, JarUtil.getJarFileUri("ClassInJar0", rootCL));
179
180 // Fetch and load the contained "ClassInJar1.jar"
181 final URL ClassInJar2_jarFileURL = JarUtil.getJarFileUri(TempJarCache.getResourceUri("sub/ClassInJar2.jar")).toURL();
182 final ClassLoader cl = new URLClassLoader(new URL[] { ClassInJar2_jarFileURL }, rootCL);
183 Assert.assertNotNull(cl);
184 validateJarUtil("ClassInJar2.jar", "ClassInJar2", cl);
185 System.err.println("XXXXXXXXXXXXXXXXXXXXXXXXXXXX");
186 }
187
188 /**
189 * Tests JarUtil's ability to resolve non-JAR URLs with a custom resolver. Meant to be used
190 * in cases like an OSGi plugin, where all classes are loaded with custom classloaders and
191 * therefore return URLs that don't start with "jar:". Adapted from test 02 above.
192 * @throws URISyntaxException
193 * @throws IllegalArgumentException
194 */
195 // @Test // FIXME: Build ClassInJar0 and corresponding jar files
196 public void testJarUtilJarInJar03() throws IOException, ClassNotFoundException, IllegalArgumentException, URISyntaxException {
197 System.err.println("XXXXXXXXXXXXXXXXXXXXXXXXXXXX");
198
199 Assert.assertTrue(TempJarCache.initSingleton());
200 Assert.assertTrue(TempCacheReg.isTempJarCacheUsed(false));
201 Assert.assertTrue(TempJarCache.isInitialized(false));
202
203 /** This classloader mimics what OSGi's does -- it takes jar: URLs and makes them into bundleresource: URLs
204 * where the JAR is not directly accessible anymore. Here I leave the JAR name at the end of the URL so I can
205 * retrieve it later in the resolver, but OSGi obscures it completely and returns URLs like
206 * "bundleresource:4.fwk1990213994:1/Something.class" where the JAR name not present. */
207 class CustomClassLoader extends ClassLoader {
208 CustomClassLoader() {
209 super(TestJarUtil.this.getClass().getClassLoader());
210 }
211
212 /** Override normal method to return un-resolvable URL. */
213 @Override
214 public URL getResource(final String name) {
215 final URL url = super.getResource(name);
216 if(url == null)
217 return(null);
218 URL urlReturn = null;
219 try {
220 // numbers to mimic OSGi -- can be anything
221 urlReturn = new URL("bundleresource", "4.fwk1990213994", 1, url.getFile(),
222 new URLStreamHandler() {
223 @Override
224 protected URLConnection openConnection(final URL u) throws IOException {
225 return null;
226 }
227 });
228 } catch(final MalformedURLException e) {
229 // shouldn't happen, since I create the URL correctly above
230 Assert.assertTrue(false);
231 }
232 return urlReturn;
233 }
234 };
235
236 /* This resolver converts bundleresource: URLs back into jar: URLs. OSGi does this by consulting
237 * opaque bundle data inside its custom classloader to find the stored JAR path; we do it here
238 * by simply retrieving the JAR name from where we left it at the end of the URL. */
240 @Override
241 public URL resolve( final URL url ) {
242 if( url.getProtocol().equals("bundleresource") ) {
243 try {
244 return new URL( Uri.JAR_SCHEME, "", url.getFile() );
245 } catch(final MalformedURLException e) {
246 return url;
247 }
248 } else {
249 return url;
250 }
251 }
252 } );
253
254 final ClassLoader rootCL = new CustomClassLoader();
255
256 // Get containing JAR file "TestJarsInJar.jar" and add it to the TempJarCache
257 TempJarCache.addAll(RuntimeProps.class, JarUtil.getJarFileUri("ClassInJar0", rootCL));
258
259 // Fetch and load the contained "ClassInJar1.jar"
260 final URL ClassInJar2_jarFileURL = JarUtil.getJarFileUri(TempJarCache.getResourceUri("sub/ClassInJar2.jar")).toURL();
261 final ClassLoader cl = new URLClassLoader(new URL[] { ClassInJar2_jarFileURL }, rootCL);
262 Assert.assertNotNull(cl);
263 validateJarUtil("ClassInJar2.jar", "ClassInJar2", cl);
264 System.err.println("XXXXXXXXXXXXXXXXXXXXXXXXXXXX");
265 }
266
267 public static void main(final String args[]) throws IOException {
268 final String tstname = TestJarUtil.class.getName();
269 org.junit.runner.JUnitCore.main(tstname);
270 }
271
272}
static void main(final String args[])
void testJarUtilJarInJar03()
Tests JarUtil's ability to resolve non-JAR URLs with a custom resolver.
This class implements an immutable Uri as defined by RFC 2396.
Definition: Uri.java:162
final java.net.URL toURL()
Returns a new URL instance using the encoded input string, new URL(uri.input), i.e.
Definition: Uri.java:1331
static final String JAR_SCHEME
{@value}
Definition: Uri.java:294
static Uri getJarFileUri(final String clazzBinName, final ClassLoader cl)
The Class's "com.jogamp.common.GlueGenVersion" Uri jar:sub_protocol:/some/path/gluegen-rt....
Definition: JarUtil.java:304
static void setResolver(final Resolver r)
Setting a custom Resolver instance.
Definition: JarUtil.java:87
static boolean isTempJarCacheUsed(final boolean forExecutables)
static boolean isTempFileCacheUsed()
File getTempDir()
Temporary directory for individual files (eg.
boolean isValid(final boolean forExecutables)
static boolean initSingleton()
Documented way to kick off static initialization.
Static Jar file cache handler using an underlying instance of TempFileCache, see getTempFileCache().
static boolean isInitialized(final boolean forExecutables)
static synchronized final void addAll(final Class<?> certClass, final Uri jarUri)
Adds all types, native libraries, class files and other files (resources) if not yet added.
static boolean initSingleton()
Documented way to kick off static initialization.
static synchronized final Uri getResourceUri(final String name)
Similar to ClassLoader#getResource(String).
static final boolean isAvailable
Runtime platform properties derived from PlatformProps and runtime query.
Interface allowing users to provide an URL resolver that will convert custom classloader URLs like Ec...
Definition: JarUtil.java:71