Skip to content

Commit

Permalink
Merge d9065e6 into 7bf8645
Browse files Browse the repository at this point in the history
  • Loading branch information
circlespainter committed Sep 29, 2015
2 parents 7bf8645 + d9065e6 commit 1333e91
Show file tree
Hide file tree
Showing 6 changed files with 157 additions and 19 deletions.
53 changes: 40 additions & 13 deletions capsule/src/main/java/Capsule.java
Expand Up @@ -87,7 +87,6 @@
import javax.management.MBeanServerConnection;
import javax.management.remote.JMXConnector;
import javax.management.remote.JMXConnectorFactory;
import javax.management.remote.JMXConnectorServer;
import javax.management.remote.JMXServiceURL;

import static java.util.Collections.*;
Expand Down Expand Up @@ -1072,14 +1071,16 @@ public boolean isAgent() {

//<editor-fold defaultstate="collapsed" desc="Capsule JAR">
/////////// Capsule JAR ///////////////////////////////////
private static Path findOwnJarFile() {
final URL url = MY_CLASSLOADER.getResource(Capsule.class.getName().replace('.', '/') + ".class");
assert url != null;
private static Path findJarFile(Class<? extends Capsule> capsuleClass) {
assert capsuleClass != null;
final URL url = MY_CLASSLOADER.getResource(capsuleClass.getName().replace('.', '/') + ".class");
if (url == null) // Could happen with embedded capsules
throw new IllegalStateException("The " + capsuleClass + " class must be in a JAR file, but was not found");
if (!"jar".equals(url.getProtocol()))
throw new IllegalStateException("The Capsule class must be in a JAR file, but was loaded from: " + url);
throw new IllegalStateException("The " + capsuleClass + " class must be in a JAR file, but was loaded from: " + url);
final String path = url.getPath();
if (path == null) // || !path.startsWith("file:")
throw new IllegalStateException("The Capsule class must be in a local JAR file, but was loaded from: " + url);
throw new IllegalStateException("The " + capsuleClass + " class must be in a local JAR file, but was loaded from: " + url);

try {
final URI jarUri = new URI(path.substring(0, path.indexOf('!')));
Expand All @@ -1089,6 +1090,10 @@ private static Path findOwnJarFile() {
}
}

private static Path findOwnJarFile() {
return findJarFile(Capsule.class);
}

private String toJarUrl(String relPath) {
return "jar:file:" + getJarFile().toAbsolutePath() + "!/" + relPath;
}
Expand Down Expand Up @@ -1656,8 +1661,12 @@ private <T> T agentAttributes(Entry<String, T> attr, T value) {
if (ATTR_JAVA_AGENTS == attr) {
// add the capsule as an agent
final Map<Object, String> agents = new LinkedHashMap<>(cast(ATTR_JAVA_AGENTS, value));
assert isWrapperCapsule() ^ findOwnJarFile().equals(getJarFile());
agents.put(processOutgoingPath(findOwnJarFile()), isWrapperCapsule() ? processOutgoingPath(getJarFile()) : "");
Path ownJar = null;
try {
ownJar = findOwnJarFile();
} catch (final IllegalStateException ignored) {}
if (ownJar != null)
agents.put(processOutgoingPath(ownJar), isWrapperCapsule() ? processOutgoingPath(getJarFile()) : "");
return (T) agents;
}

Expand Down Expand Up @@ -2281,9 +2290,9 @@ private List<Object> buildClassPath0(List<Object> classPath0) {
final long start = clock();
final List<Object> classPath = new ArrayList<>();

// the capsule jar
// The caplets and capsule jars
if (!isWrapperOfNonCapsule() && getAttribute(ATTR_CAPSULE_IN_CLASS_PATH))
classPath.add(getJarFile());
addCapsuleJars(classPath);

if (hasAttribute(ATTR_APP_ARTIFACT)) {
final String artifact = getAttribute(ATTR_APP_ARTIFACT);
Expand All @@ -2298,12 +2307,30 @@ private List<Object> buildClassPath0(List<Object> classPath0) {

classPath.addAll(nullToEmpty(getAttribute(ATTR_DEPENDENCIES)));

// the capsule jar
// The caplets and capsule jars
if (!isWrapperOfNonCapsule() && isDeepEmpty(classPath))
classPath.add(getJarFile());
addCapsuleJars(classPath);

// Remove duplicate JARs while preserving order
final List<Object> ret = new ArrayList<>(new LinkedHashSet<>(classPath));

time("buildClassPath", start);
return classPath;

return ret;
}

private void addCapsuleJars(List<Object> classPath) {
Capsule c = this.cc;
do {
Path p = null;
try {
p = findJarFile(c.getClass());
} catch (final IllegalStateException ignored) {} // Ignore non-JARs
if (p != null && !classPath.contains(p))
classPath.add(p);
} while ((c = sup) != null);

classPath.add(getJarFile());
}

/**
Expand Down
85 changes: 85 additions & 0 deletions capsule/src/test/java/CapsuleAgentTest.java
@@ -0,0 +1,85 @@
/*
* Capsule
* Copyright (c) 2014-2015, Parallel Universe Software Co. All rights reserved.
*
* This program and the accompanying materials are licensed under the terms
* of the Eclipse Public License v1.0, available at
* http://www.eclipse.org/legal/epl-v10.html
*/
import capsule.test.Pair;
import co.paralleluniverse.capsule.Jar;
import co.paralleluniverse.capsule.test.CapsuleTestUtils;
import co.paralleluniverse.common.FlexibleClassLoader;
import co.paralleluniverse.common.JarClassLoader;
import co.paralleluniverse.common.PathClassLoader;
import org.junit.Test;

import java.io.IOException;
import java.nio.file.FileVisitResult;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.SimpleFileVisitor;
import java.nio.file.attribute.BasicFileAttributes;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;

/**
* @author circlespainter
*/
public class CapsuleAgentTest {
@Test
public void testWrapperCapsuleAgent() throws Exception {
final Jar wrapper = new Jar()
.setAttribute("Manifest-Version", "1.0")
.setAttribute("Main-Class", "Capsule")
.setAttribute("Premain-Class", "Capsule")
.setAttribute("Capsule-Agent", "true")
.setAttribute("Caplets", "MyCapsule")
.addClass(TestCapsule.class)
.addClass(Pair.class)
.addClass(JarClassLoader.class)
.addClass(PathClassLoader.class)
.addClass(FlexibleClassLoader.class)
.addClass(MyCapsule.class)
.addClass(Capsule.class);

final Jar app = new Jar()
.setAttribute("Manifest-Version", "1.0")
.setAttribute("Main-Class", Capsule.class.getName())
.setAttribute("Premain-Class", Capsule.class.getName())
.setAttribute("Capsule-Agent", "true")
.setAttribute("Application-Class", MainTest.class.getName())
.addClass(Capsule.class)
.addClass(MainTest.class);

final Path wrapperPath = Files.createTempFile("capsule-agent-test-wrapper", ".jar");
CapsuleTestUtils.newCapsule(wrapper, wrapperPath); // Create
final Path appPath = Files.createTempFile("capsule-agent-test-app", ".jar");
CapsuleTestUtils.newCapsule(app, appPath); // Create
final Path cacheDir = Files.createTempDirectory("capsule-agent-test-cache");

final ProcessBuilder pb = new ProcessBuilder("java", "-jar", wrapperPath.toString(), appPath.toString());
pb.environment().put("CAPSULE_CACHE_DIR", cacheDir.toAbsolutePath().toString());
assertEquals(0, pb.start().waitFor());

final Path appCache = cacheDir.resolve("apps").resolve(MainTest.class.getName());
assertTrue(Files.exists(appCache.resolve(MyCapsule.WRAPPER_AGENT_OK_FNAME)));

Files.delete(wrapperPath);
Files.delete(appPath);
Files.walkFileTree(cacheDir, new SimpleFileVisitor<Path>() {
@Override
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
Files.delete(file);
return FileVisitResult.CONTINUE;
}

@Override
public FileVisitResult postVisitDirectory(Path dir, IOException exc) throws IOException {
Files.delete(dir);
return FileVisitResult.CONTINUE;
}
});
}
}
9 changes: 5 additions & 4 deletions capsule/src/test/java/CapsuleTest.java
Expand Up @@ -11,6 +11,7 @@
import co.paralleluniverse.capsule.test.CapsuleTestUtils;
import co.paralleluniverse.capsule.test.CapsuleTestUtils.StringPrintStream;
import static co.paralleluniverse.capsule.test.CapsuleTestUtils.*;

import co.paralleluniverse.common.ZipFS;
import com.google.common.jimfs.Jimfs;
import java.io.IOException;
Expand Down Expand Up @@ -41,7 +42,6 @@
import static com.google.common.truth.Truth.*;
import java.nio.file.Paths;
import org.joor.Reflect;
import org.junit.Ignore;
//import static org.mockito.Mockito.*;

public class CapsuleTest {
Expand Down Expand Up @@ -1206,14 +1206,14 @@ public void testMerge() throws Exception {
.addEntry("META-INF/x.txt", emptyInputStream());

Class<?> capsuleClass = loadCapsule(wrapper);
setProperties(capsuleClass, props);
// setProperties(capsuleClass, props);

Path fooPath = mockDep(capsuleClass, "com.acme:foo", "jar", "com.acme:foo:1.0").get(0);
Files.createDirectories(fooPath.getParent());
app.write(fooPath);

props.setProperty("capsule.merge", "out.jar");
props.setProperty("capsule.log", "verbose");
// props.setProperty("capsule.log", "verbose");

int exit = main0(capsuleClass, "com.acme:foo");

Expand Down Expand Up @@ -1556,7 +1556,8 @@ private Jar newCapsuleJar() {
return new Jar()
.setAttribute("Manifest-Version", "1.0")
.setAttribute("Main-Class", "TestCapsule")
.setAttribute("Premain-Class", "TestCapsule");
.setAttribute("Premain-Class", "TestCapsule")
.setAttribute("Capsule-Agent", "true");
}

private Jar makeRealCapsuleJar(Jar jar) throws IOException {
Expand Down
10 changes: 10 additions & 0 deletions capsule/src/test/java/MainTest.java
@@ -0,0 +1,10 @@
import java.util.Arrays;

/**
* Created by fabio on 9/29/15.
*/
public class MainTest {
public static void main(String[] args) {
System.out.print(Arrays.toString(args));
}
}
15 changes: 15 additions & 0 deletions capsule/src/test/java/MyCapsule.java
Expand Up @@ -7,6 +7,9 @@
* http://www.eclipse.org/legal/epl-v10.html
*/

import java.io.IOException;
import java.lang.instrument.Instrumentation;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.List;
Expand All @@ -17,6 +20,8 @@
* A custom capsule example
*/
public class MyCapsule extends TestCapsule {
public static final String WRAPPER_AGENT_OK_FNAME = "startJMXServer-specialized.empty";

public MyCapsule(Path jarFile) {
super(jarFile);
}
Expand Down Expand Up @@ -52,6 +57,16 @@ else if (arg.startsWith("-Xms"))
return super.attribute(attr); //To change body of generated methods, choose Tools | Templates.
}

@Override
protected void agent(Instrumentation inst) {
try {
Files.createFile(getWritableAppCache().resolve(WRAPPER_AGENT_OK_FNAME));
} catch (final IOException e) {
throw new RuntimeException(e);
}
super.agent(inst);
}

@Override
protected List<String> buildArgs(List<String> args) {
return super.buildArgs(args);
Expand Down
4 changes: 2 additions & 2 deletions capsule/src/test/java/TestCapsule.java
Expand Up @@ -51,7 +51,7 @@ public static void reset() {
public static void mock(String coords, String type, List<Path> paths) {
if (DEPS == null)
DEPS = new HashMap<>();
DEPS.put(new Pair(coords, type), paths);
DEPS.put(new Pair<>(coords, type), paths);
}

@Override
Expand All @@ -68,7 +68,7 @@ protected Object lookup0(Object o, String type, Map.Entry<String, ?> attrContext
if (o instanceof String) {
String x = (String) o;
if (x.contains(":"))
o = new Pair(x, type.isEmpty() ? "jar" : type);
o = new Pair<>(x, type.isEmpty() ? "jar" : type);
}
return super.lookup0(o, type, attrContext, context); //To change body of generated methods, choose Tools | Templates.
}
Expand Down

0 comments on commit 1333e91

Please sign in to comment.