Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion emjar-maven-plugin/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,11 @@ Maven Plugin Mojo for building bundling jars that contain dependency artifact ja

* bundleSuffix

Suffix appended to `finalName` when building output bundle name. Defaults to `-emjar`.
Suffix appended to `finalName` when building output bundle name.
Defaults to `-emjar`. (Due to the way pom files are parsed and
passed to plugins, an empty suffix cannot be directly configured.
Use the value `NONE` to indicate that no suffix should be
appended.)

* explicitOrderings

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,7 @@ public class EmJarMojo
private String finalName;

/**
* Suffix for generated Java Archive file.
* Suffix for generated Java Archive file ("NONE" for none).
*
* @parameter
* property="bundleSuffix"
Expand Down Expand Up @@ -177,6 +177,7 @@ public class EmJarMojo

private static final String CREATED_BY = "Created-By";
private static final int CHUNK_SIZE = 16 * 1024;
private static final String NONE = "NONE";

private final Map<Artifact, Map<Artifact, Set<String>>> conflicts = new HashMap<>();
private final Map<String, Set<Artifact>> seen = new HashMap<>();
Expand Down Expand Up @@ -482,7 +483,8 @@ public void execute()
throws MojoExecutionException
{
try {
final File outFile = new File(outputDirectory, finalName + bundleSuffix + ".jar");
final String suffix = NONE.equals(bundleSuffix) ? "" : bundleSuffix;
final File outFile = new File(outputDirectory, finalName + suffix + ".jar");
getLog().info("Building jar: " + outFile.getPath());
if (ignoreConflicts && conflictsFatal) {
throw new MojoExecutionException(
Expand Down
6 changes: 6 additions & 0 deletions emjar/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -53,5 +53,11 @@
<version>${google.guava.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.4</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>
64 changes: 41 additions & 23 deletions emjar/src/main/java/com/comoyo/emjar/EmJarClassLoader.java
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
import java.net.URLStreamHandlerFactory;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.concurrent.ConcurrentHashMap;
Expand Down Expand Up @@ -72,15 +73,14 @@ public class EmJarClassLoader
{
public final static String EMJAR_LOG_QUIET_PROP = "emjar.log.quiet";
public final static String EMJAR_LOG_DEBUG_PROP = "emjar.log.debug";
public final static String EMJAR_CLASS_PATH_PROP = "emjar.class.path";
public final static String JAVA_CLASS_PATH_PROP = "java.class.path";

protected static boolean DEBUG = false;
protected static boolean QUIET = false;

public final static String SEPARATOR = "!/";

private final static HandlerFactory factory = new HandlerFactory();
private final static Handler handler = new Handler();

static {
try {
ClassLoader.registerAsParallelCapable();
Expand All @@ -89,28 +89,45 @@ public class EmJarClassLoader
}
}

private EmJarClassLoader(
final Handler handler, final Properties props, final ClassLoader parent) {
super(getClassPath(props, handler), parent, new HandlerFactory(handler));
}

public EmJarClassLoader()
{
super(getClassPath(System.getProperties()), null, factory);
this(new Handler(), System.getProperties(), null);
}

public EmJarClassLoader(ClassLoader parent)
public EmJarClassLoader(final ClassLoader parent)
{
super(getClassPath(System.getProperties()), parent, factory);
this(new Handler(), System.getProperties(), parent);
}

protected EmJarClassLoader(Properties props)
protected EmJarClassLoader(final Properties props)
{
super(getClassPath(props), null, factory);
this(new Handler(), props, null);
}

private static URL[] getClassPath(final Properties props)
private static URL[] getClassPath(final Properties props, final Handler handler)
{
final String classPath = props.getProperty("java.class.path");
QUIET = "true".equalsIgnoreCase(props.getProperty(EMJAR_LOG_QUIET_PROP, ""));
DEBUG = "true".equalsIgnoreCase(props.getProperty(EMJAR_LOG_DEBUG_PROP, ""));

final ArrayList<URL> urls = new ArrayList<>();
addClassPathUrls(props.getProperty(JAVA_CLASS_PATH_PROP), urls, handler);
addClassPathUrls(props.getProperty(EMJAR_CLASS_PATH_PROP), urls, handler);
if (DEBUG) {
System.err.println("EmJar: using classpath " + urls);
}
return urls.toArray(new URL[0]);
}

private static void addClassPathUrls(
final String classPath, final List<URL> urls, final Handler handler) {
if (classPath == null) {
return;
}
for (String elem : classPath.split(File.pathSeparator)) {
final File file = new File(elem);
try {
Expand Down Expand Up @@ -142,10 +159,6 @@ private static URL[] getClassPath(final Properties props)
// Trying to get by on the classpath entries we can process.
}
}
if (DEBUG) {
System.err.println("EmJar: using classpath " + urls);
}
return urls.toArray(new URL[0]);
}

private static URL uriToUrl(URI uri, Handler handler)
Expand All @@ -160,16 +173,15 @@ private static URL uriToUrl(URI uri, Handler handler)
handler);
}

@Override
public Class<?> loadClass(String name)
throws ClassNotFoundException
{
return super.loadClass(name);
}

private static class HandlerFactory
implements URLStreamHandlerFactory
{
private final Handler handler;

public HandlerFactory(final Handler handler) {
this.handler = handler;
}

@Override
public URLStreamHandler createURLStreamHandler(String protocol)
{
Expand Down Expand Up @@ -244,6 +256,11 @@ protected URLConnection openConnection(URL url)
final String root = path.substring(0, i);
final String nested = path.substring(i + SEPARATOR.length(), j);
final String entry = path.substring(j + SEPARATOR.length());
if (!nested.endsWith(".jar")) {
final URL urlDefaultHandler
= new URL(url.getProtocol(), url.getHost(), url.getPort(), url.getFile());
return urlDefaultHandler.openConnection();
}

Map<String, Map<String, OndemandEmbeddedJar.Descriptor>> rootJar
= rootJars.get(root);
Expand All @@ -260,13 +277,14 @@ protected URLConnection openConnection(URL url)
}
final Map<String, OndemandEmbeddedJar.Descriptor> descriptors
= rootJar.get(nested);
final URL rootUrl = new URL("jar:file:" + root + SEPARATOR);
if (descriptors != null) {
conn = new OndemandEmbeddedJar.Connection(
bundle.toURL(), root, descriptors, entry);
rootUrl, root, descriptors, entry);
}
else {
conn = new PreloadedEmbeddedJar.Connection(
bundle.toURL(), root, nested, entry);
rootUrl, root, nested, entry);
}
connections.put(path, conn);
}
Expand Down
43 changes: 42 additions & 1 deletion emjar/src/test/java/com/comoyo/emjar/EmJarClassLoaderTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,17 @@
import java.io.BufferedReader;
import java.io.File;
import java.io.FilenameFilter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.JarURLConnection;
import java.net.URISyntaxException;
import java.net.URL;
import java.net.URLClassLoader;
import java.net.URLConnection;
import java.util.Enumeration;
import java.util.Properties;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import java.util.jar.Manifest;

Expand Down Expand Up @@ -57,12 +61,49 @@ public boolean accept(File dir, String name) {
return new EmJarClassLoader(props);
}

/**
* In order to construct a URL, getResourceAsStream ultimately
* calls sun.net.www.ParseUtil.encodePath(). This encodes the
* name's char array to UTF-8 under the assumption that it is
* UCS-2, not UTF-16. Doing so causes bad encodings of non-BMP
* entities. Java 7 was able to process these wrongly encoded
* strings and reconstruct the original char sequence, but Java 8
* is not. Thus the following, which more or less replicates the
* functionality of getResourceAsStream in order to verify that at
* least EmJar's handling of unicode is up to snuff.
*/
private static InputStream getResourceAsStreamRobust(
final URLClassLoader loader, final String searchName)
throws IOException {
for (final URL url : loader.getURLs()) {
if (!"jar".equals(url.getProtocol())) {
continue;
}
final URLConnection conn = url.openConnection();
if (!(conn instanceof JarURLConnection)) {
continue;
}
final JarURLConnection jarConn = (JarURLConnection) conn;
final JarFile jarFile = jarConn.getJarFile();
final Enumeration<JarEntry> it = jarFile.entries();
while (it.hasMoreElements()) {
final JarEntry je = it.nextElement();
if (searchName.equals(je.getName())) {
return jarFile.getInputStream(je);
}
}
}
return null;
}

@Test
public void testClassPathQuoting()
throws Exception
{
final EmJarClassLoader loader = testLoader();
final InputStream is = loader.getResourceAsStream("entry-" + WEIRD + ".txt");
final String searchName = "entry-" + WEIRD + ".txt";
final InputStream is = getResourceAsStreamRobust(loader, searchName);
assertNotNull("Did not find " + searchName + " in classpath", is);
final BufferedReader entry = new BufferedReader(new InputStreamReader(is));
assertEquals("Contents mismatch for weird entry", WEIRD, entry.readLine());
}
Expand Down
6 changes: 5 additions & 1 deletion emjar/src/test/java/com/comoyo/emjar/EmJarTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
import java.io.File;
import java.net.URI;
import java.net.URISyntaxException;
import org.apache.http.client.utils.URIBuilder;

public abstract class EmJarTest
{
Expand All @@ -28,7 +29,10 @@ protected File getResourceFile(String name)
throws URISyntaxException
{
final ClassLoader cl = getClass().getClassLoader();
final URI uri = cl.getResource("com/comoyo/emjar/" + name).toURI();
final URI base = cl.getResource("com/comoyo/emjar/").toURI();
URIBuilder builder = new URIBuilder(base);
builder.setPath(builder.getPath() + name);
final URI uri = builder.build();
if (!"file".equals(uri.getScheme())) {
throw new IllegalArgumentException(
"Resource " + name + " not present as file (" + uri + ")");
Expand Down
2 changes: 1 addition & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,7 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId>
<version>2.2.1</version>
<version>2.4</version>
<executions>
<execution>
<id>attach-sources</id>
Expand Down