Author: rmannibucau Date: Fri May 23 17:39:42 2014 New Revision: 1597138 URL: http://svn.apache.org/r1597138 Log: TOMEE-1222 adding some utilities to JarLocation
Added: tomee/tomee/trunk/arquillian/ziplock/src/main/java/org/apache/ziplock/ClassLoaders.java tomee/tomee/trunk/arquillian/ziplock/src/test/java/org/apache/ziplock/JarLocationTest.java tomee/tomee/trunk/arquillian/ziplock/src/test/resources/ tomee/tomee/trunk/arquillian/ziplock/src/test/resources/resources.txt Modified: tomee/tomee/trunk/arquillian/ziplock/src/main/java/org/apache/ziplock/JarLocation.java Added: tomee/tomee/trunk/arquillian/ziplock/src/main/java/org/apache/ziplock/ClassLoaders.java URL: http://svn.apache.org/viewvc/tomee/tomee/trunk/arquillian/ziplock/src/main/java/org/apache/ziplock/ClassLoaders.java?rev=1597138&view=auto ============================================================================== --- tomee/tomee/trunk/arquillian/ziplock/src/main/java/org/apache/ziplock/ClassLoaders.java (added) +++ tomee/tomee/trunk/arquillian/ziplock/src/main/java/org/apache/ziplock/ClassLoaders.java Fri May 23 17:39:42 2014 @@ -0,0 +1,181 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.ziplock; + +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.IOException; +import java.net.MalformedURLException; +import java.net.URL; +import java.net.URLClassLoader; +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.HashSet; +import java.util.Set; + +public final class ClassLoaders { + private static final boolean DONT_USE_GET_URLS = Boolean.getBoolean("xbean.finder.use.get-resources"); + private static final ClassLoader SYSTEM = ClassLoader.getSystemClassLoader(); + + private static final boolean UNIX = !System.getProperty("os.name").toLowerCase().contains("win"); + + public static Set<URL> findUrls(final ClassLoader classLoader) throws IOException { + if (classLoader == null || (SYSTEM.getParent() != null && classLoader == SYSTEM.getParent())) { + return Collections.emptySet(); + } + + final Set<URL> urls = new HashSet<URL>(); + + if (URLClassLoader.class.isInstance(classLoader) && !DONT_USE_GET_URLS) { + if (!isSurefire(classLoader)) { + for (final Collection<URL> item : Arrays.asList( + Arrays.asList(URLClassLoader.class.cast(classLoader).getURLs()), findUrls(classLoader.getParent()))) { + for (final URL url : item) { + addIfNotSo(urls, url); + } + } + } else { // http://jira.codehaus.org/browse/SUREFIRE-928 - we could reuse findUrlFromResources but this seems faster + for (final URL url : fromClassPath()) { + urls.add(url); + } + } + } else { + for (final URL url : findUrlFromResources(classLoader)) { + urls.add(url); + } + } + + return urls; + } + + private static void addIfNotSo(final Set<URL> urls, final URL url) { + if (UNIX && isNative(url)) { + return; + } + + urls.add(url); + } + + public static File toFile(final URL url) { + if ("jar".equals(url.getProtocol())) { + try { + final String spec = url.getFile(); + final int separator = spec.indexOf('!'); + if (separator == -1) { + return null; + } + return toFile(new URL(spec.substring(0, separator + 1))); + } catch (final MalformedURLException e) { + return null; + } + } else if ("file".equals(url.getProtocol())) { + String path = decode(url.getFile()); + if (path.endsWith("!")) { + path = path.substring(0, path.length() - 1); + } + return new File(path); + } + return null; + } + + public static String decode(String fileName) { + if (fileName.indexOf('%') == -1) return fileName; + + StringBuilder result = new StringBuilder(fileName.length()); + ByteArrayOutputStream out = new ByteArrayOutputStream(); + + for (int i = 0; i < fileName.length();) { + char c = fileName.charAt(i); + + if (c == '%') { + out.reset(); + do { + if (i + 2 >= fileName.length()) { + throw new IllegalArgumentException("Incomplete % sequence at: " + i); + } + + int d1 = Character.digit(fileName.charAt(i + 1), 16); + int d2 = Character.digit(fileName.charAt(i + 2), 16); + + if (d1 == -1 || d2 == -1) { + throw new IllegalArgumentException("Invalid % sequence (" + fileName.substring(i, i + 3) + ") at: " + String.valueOf(i)); + } + + out.write((byte) ((d1 << 4) + d2)); + + i += 3; + + } while (i < fileName.length() && fileName.charAt(i) == '%'); + + + result.append(out.toString()); + + continue; + } else { + result.append(c); + } + + i++; + } + return result.toString(); + } + + public static boolean isNative(final URL url) { + final File file = toFile(url); + if (file != null) { + final String name = file.getName(); + if (!name.endsWith(".jar") && !file.isDirectory() + && name.contains(".so") && file.getAbsolutePath().startsWith("/usr/lib")) { + return true; + } + } + return false; + } + + + private static boolean isSurefire(ClassLoader classLoader) { + return System.getProperty("surefire.real.class.path") != null && classLoader == SYSTEM; + } + + private static Collection<URL> fromClassPath() { + final String[] cp = System.getProperty("java.class.path").split(System.getProperty("path.separator", ":")); + final Set<URL> urls = new HashSet<URL>(); + for (final String path : cp) { + try { + urls.add(new File(path).toURI().toURL()); // don't build the url in plain String since it is not portable + } catch (final MalformedURLException e) { + // ignore + } + } + return urls; + } + + public static Set<URL> findUrlFromResources(final ClassLoader classLoader) throws IOException { + final Set<URL> set = new HashSet<URL>(); + for (final URL url : Collections.list(classLoader.getResources("META-INF"))) { + final String externalForm = url.toExternalForm(); + set.add(new URL(externalForm.substring(0, externalForm.lastIndexOf("META-INF")))); + } + set.addAll(Collections.list(classLoader.getResources(""))); + return set; + } + + private ClassLoaders() { + // no-op + } +} Modified: tomee/tomee/trunk/arquillian/ziplock/src/main/java/org/apache/ziplock/JarLocation.java URL: http://svn.apache.org/viewvc/tomee/tomee/trunk/arquillian/ziplock/src/main/java/org/apache/ziplock/JarLocation.java?rev=1597138&r1=1597137&r2=1597138&view=diff ============================================================================== --- tomee/tomee/trunk/arquillian/ziplock/src/main/java/org/apache/ziplock/JarLocation.java (original) +++ tomee/tomee/trunk/arquillian/ziplock/src/main/java/org/apache/ziplock/JarLocation.java Fri May 23 17:39:42 2014 @@ -16,10 +16,12 @@ */ package org.apache.ziplock; -import java.io.ByteArrayOutputStream; import java.io.File; +import java.io.IOException; import java.net.MalformedURLException; import java.net.URL; +import java.util.Set; +import java.util.regex.Pattern; /** * @version $Rev$ $Date$ @@ -30,18 +32,33 @@ public class JarLocation { return jarLocation(JarLocation.class); } - public static File jarLocation(Class clazz) { - try { - String classFileName = clazz.getName().replace(".", "/") + ".class"; + public static File jarFromPrefix(final String prefix) { + return jarFromRegex(prefix + ".*\\.jar"); + } - ClassLoader loader = clazz.getClassLoader(); - URL url; - if (loader != null) { - url = loader.getResource(classFileName); - } else { - url = clazz.getResource(classFileName); + public static File jarFromRegex(final String regex) { + final Pattern pattern = Pattern.compile(regex); + try { + final Set<URL> urls = ClassLoaders.findUrls(Thread.currentThread().getContextClassLoader()); + for (final URL url : urls) { + final File f = new File(decode(url.getFile())); + if (f.exists() && pattern.matcher(f.getName()).matches()) { + return f; + } } + throw new IllegalArgumentException(regex + " not found in " + urls); + } catch (final IOException e) { + throw new IllegalStateException(e); + } + } + + public static File jarFromResource(final String resourceName) { + return jarFromResource(Thread.currentThread().getContextClassLoader(), resourceName); + } + public static File jarFromResource(final ClassLoader loader, final String resourceName) { + try { + URL url = loader.getResource(resourceName); if (url == null) { throw new IllegalStateException("classloader.getResource(classFileName) returned a null URL"); } @@ -60,13 +77,25 @@ public class JarLocation { return new File(decode(url.getFile())); } else if ("file".equals(url.getProtocol())) { - return toFile(classFileName, url); + return toFile(resourceName, url); } else { throw new IllegalArgumentException("Unsupported URL scheme: " + url.toExternalForm()); } - } catch (RuntimeException e) { + } catch (final RuntimeException e) { + throw e; + } catch (final Exception e) { + throw new IllegalStateException(e); + } + } + + public static File jarLocation(final Class clazz) { + try { + final String classFileName = clazz.getName().replace(".", "/") + ".class"; + final ClassLoader loader = clazz.getClassLoader(); + return jarFromResource(loader, classFileName); + } catch (final RuntimeException e) { throw e; - } catch (Exception e) { + } catch (final Exception e) { throw new IllegalStateException(e); } } @@ -77,47 +106,8 @@ public class JarLocation { return new File(decode(path)); } - - public static String decode(String fileName) { - if (fileName.indexOf('%') == -1) return fileName; - - StringBuilder result = new StringBuilder(fileName.length()); - ByteArrayOutputStream out = new ByteArrayOutputStream(); - - for (int i = 0; i < fileName.length();) { - char c = fileName.charAt(i); - - if (c == '%') { - out.reset(); - do { - if (i + 2 >= fileName.length()) { - throw new IllegalArgumentException("Incomplete % sequence at: " + i); - } - - int d1 = Character.digit(fileName.charAt(i + 1), 16); - int d2 = Character.digit(fileName.charAt(i + 2), 16); - - if (d1 == -1 || d2 == -1) { - throw new IllegalArgumentException("Invalid % sequence (" + fileName.substring(i, i + 3) + ") at: " + String.valueOf(i)); - } - - out.write((byte) ((d1 << 4) + d2)); - - i += 3; - - } while (i < fileName.length() && fileName.charAt(i) == '%'); - - - result.append(out.toString()); - - continue; - } else { - result.append(c); - } - - i++; - } - return result.toString(); + public static String decode(final String fileName) { + return ClassLoaders.decode(fileName); } } Added: tomee/tomee/trunk/arquillian/ziplock/src/test/java/org/apache/ziplock/JarLocationTest.java URL: http://svn.apache.org/viewvc/tomee/tomee/trunk/arquillian/ziplock/src/test/java/org/apache/ziplock/JarLocationTest.java?rev=1597138&view=auto ============================================================================== --- tomee/tomee/trunk/arquillian/ziplock/src/test/java/org/apache/ziplock/JarLocationTest.java (added) +++ tomee/tomee/trunk/arquillian/ziplock/src/test/java/org/apache/ziplock/JarLocationTest.java Fri May 23 17:39:42 2014 @@ -0,0 +1,45 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.ziplock; + +import org.junit.Test; + +import java.io.File; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +public class JarLocationTest { + @Test + public void resource() { + final File thisJar = JarLocation.jarFromResource("resources.txt"); + assertTrue(thisJar.exists()); + } + + @Test + public void regex() { + final File api = JarLocation.jarFromRegex("shrinkwrap-api.*\\.jar"); + assertTrue(api.exists()); + } + + @Test + public void prefix() { + final File api = JarLocation.jarFromPrefix("shrinkwrap-api"); + assertTrue(api.exists()); + assertEquals(JarLocation.jarFromRegex("shrinkwrap-api.*\\.jar"), api); + } +} Added: tomee/tomee/trunk/arquillian/ziplock/src/test/resources/resources.txt URL: http://svn.apache.org/viewvc/tomee/tomee/trunk/arquillian/ziplock/src/test/resources/resources.txt?rev=1597138&view=auto ============================================================================== --- tomee/tomee/trunk/arquillian/ziplock/src/test/resources/resources.txt (added) +++ tomee/tomee/trunk/arquillian/ziplock/src/test/resources/resources.txt Fri May 23 17:39:42 2014 @@ -0,0 +1,16 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */