Skip to content

Commit

Permalink
[issue 89] add classpath/classpathRef options to ant task
Browse files Browse the repository at this point in the history
  • Loading branch information
joelittlejohn committed Mar 25, 2013
1 parent 62da917 commit 4d2d091
Show file tree
Hide file tree
Showing 9 changed files with 191 additions and 12 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,20 @@

import java.io.File;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;

import org.apache.tools.ant.BuildException;
import org.apache.tools.ant.Task;
import org.apache.tools.ant.types.Path;
import org.apache.tools.ant.types.Reference;

import com.googlecode.jsonschema2pojo.AnnotationStyle;
import com.googlecode.jsonschema2pojo.Annotator;
Expand Down Expand Up @@ -74,6 +83,8 @@ public class Jsonschema2PojoTask extends Task implements GenerationConfig {

private SourceType sourceType = SourceType.JSONSCHEMA;

private Path classpath;

/**
* Execute this task (it's expected that all relevant setters will have been
* called by Ant to provide task configuration <em>before</em> this method
Expand Down Expand Up @@ -105,13 +116,42 @@ public void execute() throws BuildException {
return;
}

ClassLoader extendedClassloader = buildExtendedClassloader();
Thread.currentThread().setContextClassLoader(extendedClassloader);

try {
Jsonschema2Pojo.generate(this);
} catch (IOException e) {
throw new BuildException(
"Error generating classes from JSON Schema file(s) "
+ source.getPath(), e);
throw new BuildException("Error generating classes from JSON Schema file(s) " + source.getPath(), e);
}
}

/**
* Build a classloader using the additional elements specified in
* <code>classpath</code> and <code>classpathRef</code>.
*
* @return a new classloader that includes the extra path elements found in
* the <code>classpath</code> and <code>classpathRef</code> config
* values
*/
private ClassLoader buildExtendedClassloader() {
final List<URL> classpathUrls = new ArrayList<URL>();
for (String pathElement : getClasspath().list()) {
try {
classpathUrls.add(new File(pathElement).toURI().toURL());
} catch (MalformedURLException e) {
throw new BuildException("Unable to use classpath entry as it could not be understood as a valid URL: " + pathElement, e);
}
}

final ClassLoader parentClassloader = Thread.currentThread().getContextClassLoader();

return AccessController.doPrivileged(new PrivilegedAction<ClassLoader>() {
@Override
public ClassLoader run() {
return new URLClassLoader(classpathUrls.toArray(new URL[classpathUrls.size()]), parentClassloader);
}
});
}

/**
Expand Down Expand Up @@ -366,4 +406,27 @@ public SourceType getSourceType() {
return sourceType;
}

public Path createClasspath() {
if (classpath == null) {
classpath = new Path(getProject());
}
return classpath.createPath();
}

public void setClasspath(Path classpath) {
if (classpath == null) {
this.classpath = classpath;
} else {
this.classpath.append(classpath);
}
}

public void setClasspathRef(Reference classpathRef) {
createClasspath().setRefid(classpathRef);
}

public Path getClasspath() {
return (classpath == null) ? new Path(getProject()) : classpath;
}

}
24 changes: 23 additions & 1 deletion jsonschema2pojo-ant/src/site/Jsonschema2PojoTask.html
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,29 @@ <h3>Parameters</h3>
</ul>
</td>
<td align="center" valign="top">No (default <code>JSONSCHEMA</code>)</td>
</tr>
</tr>
<tr>
<td valign="top">classpath</td>
<td valign="top">Additional classpath to use. Any path elements provided here will be added to the classpath when this task is invoked.
<p>
If a support for filesets/filelists/dirsets etc is required, this property can also be set as a nested element like:
<pre>
&lt;jsonschema2pojo ...
&lt;classpath>
&lt;fileset dir="custom-libs">
&lt;include name="**/*.jar" />
&lt;/fileset>
&lt;/classpath>
&lt;jsonschema2pojo/>
</pre>
</td>
<td align="center" valign="top">No</td>
</tr>
<tr>
<td valign="top">classpathRef</td>
<td valign="top">Additional classpath to use, given as a reference to a path defined elsewhere. Can be used in conjuction with the <code>classpath</code> option (the result is the union of all paths).</td>
<td align="center" valign="top">No</td>
</tr>
</table>

<h3>Examples</h3>
Expand Down
22 changes: 21 additions & 1 deletion jsonschema2pojo-integration-tests/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -57,11 +57,12 @@
</configuration>
</plugin>
<plugin>
<!-- copy dependencies so that tests for Ant task can build a classpath -->
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<executions>
<!-- copy dependencies so that tests for Ant task can build a taskdef classpath -->
<execution>
<id>ant-libs</id>
<phase>pre-integration-test</phase>
<goals>
<goal>copy-dependencies</goal>
Expand All @@ -70,6 +71,25 @@
<outputDirectory>${project.build.directory}/ant-libs</outputDirectory>
</configuration>
</execution>
<!-- copy dependencies from some random artifact so that tests for Ant task can custom classpath -->
<execution>
<id>custom-libs</id>
<phase>pre-integration-test</phase>
<goals>
<goal>copy</goal>
</goals>
<configuration>
<artifactItems>
<artifactItem>
<groupId>org.clojure</groupId>
<artifactId>clojure</artifactId>
<version>1.5.1</version>
<type>jar</type>
<outputDirectory>${project.build.directory}/custom-libs</outputDirectory>
</artifactItem>
</artifactItems>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
package com.googlecode.jsonschema2pojo.integration.ant;

import static com.googlecode.jsonschema2pojo.integration.util.CodeGenerationHelper.*;
import static java.util.Arrays.*;
import static org.hamcrest.Matchers.*;
import static org.junit.Assert.*;

Expand All @@ -25,6 +26,7 @@
import java.io.IOException;
import java.lang.reflect.Field;
import java.net.URISyntaxException;
import java.util.List;

import org.apache.commons.io.FileUtils;
import org.apache.tools.ant.Project;
Expand All @@ -40,11 +42,22 @@ public void antTaskExecutesSuccessfullyWithValidSchemas() throws URISyntaxExcept

File outputDirectory = invokeAntBuild("/ant/build.xml");

ClassLoader resultsClassLoader = compile(outputDirectory);
ClassLoader resultsClassLoader = compile(outputDirectory, buildCustomClasspath());

Class<?> generatedClass = resultsClassLoader.loadClass("com.example.WordDelimit");

assertThat(generatedClass, is(notNullValue()));

}

/**
* This test uses the ant 'classpath' config and the schemas refer to a
* class from a custom classpath element. This should result in the custom
* classpath element being read and no new type being generated. To test the
* result, we need to compile with the same custom classpath.
*/
private List<String> buildCustomClasspath() {
return asList(new File("target/custom-libs/clojure-1.5.1.jar").getAbsolutePath());
}

@Test
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
package com.googlecode.jsonschema2pojo.integration.util;

import static org.apache.commons.io.FileUtils.*;
import static org.apache.commons.lang.StringUtils.*;
import static org.hamcrest.Matchers.*;
import static org.junit.Assert.*;
import static org.mockito.Mockito.*;
Expand All @@ -30,6 +31,7 @@
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;

Expand Down Expand Up @@ -114,7 +116,17 @@ private static MavenProject getMockProject() throws DependencyResolutionRequired
*/
public static ClassLoader compile(File sourceDirectory) {

new Compiler().compile(sourceDirectory);
return compile(sourceDirectory, new ArrayList<String>());

}

public static ClassLoader compile(File sourceDirectory, List<String> classpath) {

List<String> fullClasspath = new ArrayList<String>();
fullClasspath.addAll(classpath);
fullClasspath.add(System.getProperty("java.class.path"));

new Compiler().compile(sourceDirectory, join(fullClasspath, File.pathSeparatorChar));

try {
return URLClassLoader.newInstance(new URL[] { sourceDirectory.toURI().toURL() }, Thread.currentThread().getContextClassLoader());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@

package com.googlecode.jsonschema2pojo.integration.util;

import static java.util.Arrays.*;
import static org.apache.commons.io.FileUtils.*;
import static org.hamcrest.Matchers.*;
import static org.junit.Assert.*;
Expand All @@ -35,15 +36,15 @@
*/
public class Compiler {

public void compile(File directory) {
public void compile(File directory, String classpath) {

JavaCompiler javaCompiler = ToolProvider.getSystemJavaCompiler();
StandardJavaFileManager fileManager = javaCompiler.getStandardFileManager(null, null, null);

Iterable<? extends JavaFileObject> compilationUnits = fileManager.getJavaFileObjectsFromFiles(findAllSourceFiles(directory));

if (compilationUnits.iterator().hasNext()) {
Boolean success = javaCompiler.getTask(null, fileManager, null, null, null, compilationUnits).call();
Boolean success = javaCompiler.getTask(null, fileManager, null, asList("-classpath", classpath), null, compilationUnits).call();
assertThat("Compilation was not successful, check stdout for errors", success, is(true));
}

Expand Down
20 changes: 17 additions & 3 deletions jsonschema2pojo-integration-tests/src/test/resources/ant/build.xml
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,20 @@
</taskdef>

<target name="generate">

<path id="custom.libs">
<fileset dir="${project.build.directory}/custom-libs">
<include name="**/*.jar" />
</fileset>
</path>

<!-- use default config -->
<jsonschema2pojo source="${project.build.directory}/test-classes/schema/properties/propertiesWithWordDelimiters.json"
<jsonschema2pojo source="${project.build.directory}/test-classes/ant/example.json"
targetDirectory="${targetDirectory}"
targetPackage="com.example"/>

<!-- specify every config arg -->
<jsonschema2pojo source="${project.build.directory}/test-classes/schema/properties/propertiesWithWordDelimiters.json"
<jsonschema2pojo source="${project.build.directory}/test-classes/ant/exampleWithExtraClasspath.json"
targetDirectory="${targetDirectory}"
targetPackage="com.example"
generateBuilders="true"
Expand All @@ -28,7 +35,14 @@
includeToString="false"
annotationStyle="NONE"
customAnnotator="com.googlecode.jsonschema2pojo.NoopAnnotator"
includeJsr303Annotations="true"/>
includeJsr303Annotations="true"
classpathRef="custom.libs">
<classpath>
<fileset dir="${project.build.directory}/custom-libs">
<include name="**/*.jar" />
</fileset>
</classpath>
</jsonschema2pojo>

<!-- use json input -->
<jsonschema2pojo source="${project.build.directory}/test-classes/json/example/torrent.json"
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{
"type" : "object",
"javaType" : "com.example.WordDelimit",
"properties" : {
"property_with_underscores" : {
"type" : "string"
},
"property-with-hyphens" : {
"type" : "string"
},
"property_with mixed-delimiters" : {
"type" : "string"
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
{
"type" : "object",
"javaType" : "com.example.WordDelimit",
"properties" : {
"property_with_underscores" : {
"type" : "string"
},
"property-with-hyphens" : {
"type" : "string"
},
"property_with mixed-delimiters" : {
"type" : "string"
},
"property-refer-custom-classpath" : {
"type" : "object",
"javaType" : "clojure.lang.Var"
}
}
}

0 comments on commit 4d2d091

Please sign in to comment.