Skip to content

Commit

Permalink
0.4.2 release
Browse files Browse the repository at this point in the history
  • Loading branch information
pron committed May 24, 2014
1 parent 51b3b42 commit fe769c0
Show file tree
Hide file tree
Showing 4 changed files with 82 additions and 30 deletions.
10 changes: 6 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ With Capsule, you just distribute a single JAR and run it.

or:

co.paralleluniverse:capsule:0.4.1
co.paralleluniverse:capsule:0.4.2

On Maven Central.

Expand All @@ -44,7 +44,9 @@ Discuss Capsule on the capsule-user [Google Group/Mailing List](https://groups.g

## Usage Examples

Before we delve into the specifics of defining a Capsule distribution, let us look at a few different ways of packaging a capsule. The examples are snippets of [Gradle](http://www.gradle.org/) build files, but the same could be achieved with [Ant](http://ant.apache.org/) or [Maven](http://maven.apache.org/). The full Gradle file is [here](https://github.com/puniverse/capsule-demo/blob/master/build.gradle), and a Maven POM is [here](https://github.com/puniverse/capsule-demo/blob/master/pom.xml).
Before we delve into the specifics of defining a Capsule distribution, let us look at a few different ways of packaging a capsule. The examples are snippets of [Gradle](http://www.gradle.org/) build files, but the same could be achieved with [Ant](http://ant.apache.org/) or [Maven](http://maven.apache.org/).

**A complete usage example, for both Gradle and Maven**, is found in the [capsule-demo](https://github.com/puniverse/capsule-demo) project, which contains both a `build.gradle` file that creates a few kinds of capsules, as well as Maven POM and assemblies that create both a full capsule (with embedded dependencies) and a capsule with external dependencies (that are resolved at launch).

We'll assume that the application's `gradle.build` file applies the [`java`](http://www.gradle.org/docs/current/userguide/java_plugin.html) and [`application`](http://www.gradle.org/docs/current/userguide/application_plugin.html) plugins, and that the build file declare the `capsule` configuration and contains the dependency `capsule 'co.paralleluniverse:capsule:VERSION'`.

Expand Down Expand Up @@ -227,13 +229,13 @@ The dependencies are downloaded the first time the capsule is launched, and plac

The `CAPSULE_REPOS` environment variable can be set to a colon (`:`) separated list of Maven repository URLS, which will override those specified in the manifest or the POM.

Capsule can make use of Maven repositories in another way: the `Application` manifest attribute can specify the Maven coordinates of the application's main JAR file, which can in itself be a module. The artifact can be given with a version range, for example: `Application: com.acme:foo:[1.0,2.0)` or with no version at all. The newest version matching the range (or the newest version if no range is given), will be downloaded, cached and launched. If the application's main artifact is a capsule, then all configurations will be taken based on those in the artifact capsule.
Capsule can make use of Maven repositories in another way: the `Application` manifest attribute can specify the Maven coordinates of the application's main JAR file, which can in itself be a capsule. The artifact can be given with a version range, for example: `Application: com.acme:foo:[1.0,2.0)` or with no version at all. The newest version matching the range (or the newest version if no range is given), will be downloaded, cached and launched. If the application's main artifact is a capsule, then all configurations will be taken based on those in the artifact capsule.

Native dependencies can be specified in the `Native-Dependencies-Linux`/`Native-Dependencies-Win`/`Native-Dependencies-Mac` attributes, each for its respective OS. A native dependency is written as a plain dependency but can be followed by a comma and a new filename to give the artifact once downloaded (e.g.: `com.acme:foo-native-linux-x64:1.0,foo-native.so`). Each native artifact must be a single native library, with a suffix matching the OS (`.so` for Linux, `.dll` for windows, `.dylib` for Mac). The native libraries are downloaded and copied into the application cache (and renamed if requested).

Adding `-Dcapsule.reset=true`, can force a re-download of SNAPSHOT versions.

The command: `java -Dcapsule.tree -jar app.jar`, will print out the dependency tree for the module, and then quit without launching the app.
The command: `java -Dcapsule.tree -jar app.jar`, will print the dependency tree for the capsule, and then quit without launching the app.

Two more system properties affect the way Capsule searches for dependencies. If `capsule.offline` is defined or set to `true` (`-Dcapsule.offline` or `-Dcapsule.offline=true`), Capsule will not attempt to contact online repositories for dependencies (instead, it will use the local Maven repository/cache only). `capsule.local` determines the path for the local Maven repository/cache Capsule will use (which, by default, is the `deps` subdirectory of the Capsule cache).

Expand Down
2 changes: 1 addition & 1 deletion build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ targetCompatibility = '1.7'
[compileJava, compileTestJava]*.options*.encoding = 'UTF-8'

group = "co.paralleluniverse"
version = "0.4.1"
version = "0.4.2"
status = "integration"
description = "Simple Java deployment"
ext.url = "http://puniverse.github.com/java-launcher"
Expand Down
35 changes: 29 additions & 6 deletions src/main/java/Capsule.java
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ public final class Capsule implements Runnable {
* We do a lot of data transformations that would have really benefitted from Java 8's lambdas and streams,
* but we want Capsule to support Java 7.
*/
private static final String VERSION = "0.4.1";
private static final String VERSION = "0.4.2";

private static final String PROP_RESET = "capsule.reset";
private static final String PROP_VERSION = "capsule.version";
Expand Down Expand Up @@ -904,13 +904,36 @@ private List<Path> getDefaultCacheClassPath() {
}

private Path getPath(String p) {
if (isDependency(p))
if (isDependency(p) && dependencyManager != null)
return getDependencyPath(dependencyManager, p);
else {
if (appCache == null)
throw new IllegalStateException("Capsule not extracted. Cannot obtain path " + p);

if (appCache == null)
throw new IllegalStateException(
(isDependency(p) ? "Dependency manager not found. Cannot resolve" : "Capsule not extracted. Cannot obtain path")
+ " " + p);
if (isDependency(p)) {
Path f = appCache.resolve(dependencyToLocalJar(true, p));
if (Files.isRegularFile(f))
return f;
f = appCache.resolve(dependencyToLocalJar(false, p));
if (Files.isRegularFile(f))
return f;
throw new IllegalArgumentException("Dependency manager not found, and could not locate artifact " + p + " in capsule");
} else
return toAbsolutePath(appCache, p);
}
}

private String dependencyToLocalJar(boolean withGroupId, String p) {
String[] coords = p.split(":");
StringBuilder sb = new StringBuilder();
if (withGroupId)
sb.append(coords[0]).append('-');
sb.append(coords[1]).append('-');
sb.append(coords[2]);
if (coords.length > 3)
sb.append('-').append(coords[3]);
sb.append(".jar");
return sb.toString();
}

private List<Path> getPath(List<String> ps) {
Expand Down
65 changes: 46 additions & 19 deletions src/main/java/capsule/PomReader.java
Original file line number Diff line number Diff line change
Expand Up @@ -49,35 +49,62 @@ public List<String> getRepositories() {
final List<Repository> repos = pom.getRepositories();
if (repos == null)
return null;
final List<String> repositories = new ArrayList<String>();
for(Repository repo : repos)
final List<String> repositories = new ArrayList<String>(repos.size());
for (Repository repo : repos)
repositories.add(repo.getUrl());
return repositories;
}

public List<String> getDependencies() {
List<Dependency> deps = pom.getDependencies();
final List<Dependency> deps = pom.getDependencies();
if (deps == null)
return null;

final List<String> dependencies = new ArrayList<String>();
final List<String> dependencies = new ArrayList<String>(deps.size());
for (Dependency dep : deps) {
if (!dep.isOptional()) {
String coords = dep.getGroupId() + ":" + dep.getArtifactId() + ":" + dep.getVersion()
+ (dep.getClassifier() != null && !dep.getClassifier().isEmpty() ? ":" + dep.getClassifier() : "");
List<Exclusion> exclusions = dep.getExclusions();
if (exclusions != null && !exclusions.isEmpty()) {
StringBuilder sb = new StringBuilder();
sb.append('(');
for (Exclusion ex : exclusions)
sb.append(ex.getGroupId()).append(':').append(ex.getArtifactId()).append(',');
sb.delete(sb.length() - 1, sb.length());
sb.append(')');
coords += sb.toString();
}
dependencies.add(coords);
}
if (includeDependency(dep))
dependencies.add(dep2desc(dep));
}
return dependencies;
}

private static boolean includeDependency(Dependency dep) {
if (dep.isOptional())
return false;
if ("co.paralleluniverse".equals(dep.getGroupId()) && "capsule".equals(dep.getArtifactId()))
return false;

switch (dep.getScope().toLowerCase()) {
case "compile":
case "runtime":
return true;
default:
return false;
}
}

private static String dep2desc(Dependency dep) {
String coords = dep2coords(dep);
List<Exclusion> exclusions = dep.getExclusions();
if (exclusions != null && !exclusions.isEmpty()) {
StringBuilder sb = new StringBuilder();
sb.append('(');
for (Exclusion ex : exclusions)
sb.append(exclusion2coord(ex)).append(',');
sb.delete(sb.length() - 1, sb.length());
sb.append(')');

coords += sb.toString();
}
return coords;
}

private static String dep2coords(Dependency dep) {
return dep.getGroupId() + ":" + dep.getArtifactId() + ":" + dep.getVersion()
+ (dep.getClassifier() != null && !dep.getClassifier().isEmpty() ? ":" + dep.getClassifier() : "");
}

private static String exclusion2coord(Exclusion ex) {
return ex.getGroupId() + ":" + ex.getArtifactId();
}
}

0 comments on commit fe769c0

Please sign in to comment.