mirror of
https://github.com/querydsl/querydsl.git
synced 2026-06-30 21:08:30 +08:00
added initial contents
This commit is contained in:
parent
b680178886
commit
2c8df0dca1
51
pom.xml
Normal file
51
pom.xml
Normal file
@ -0,0 +1,51 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd" xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
||||
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>com.mysema.codegen</groupId>
|
||||
<artifactId>codegen</artifactId>
|
||||
<version>0.1.0</version>
|
||||
<name>Codegen</name>
|
||||
<description>Code generation and compilation for Java</description>
|
||||
<parent>
|
||||
<groupId>com.mysema.home</groupId>
|
||||
<artifactId>mysema-source</artifactId>
|
||||
<version>0.2.0</version>
|
||||
</parent>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<inceptionYear>2010</inceptionYear>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>net.sourceforge.collections</groupId>
|
||||
<artifactId>collections-generic</artifactId>
|
||||
<version>4.01</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.mysema.commons</groupId>
|
||||
<artifactId>mysema-commons-lang</artifactId>
|
||||
<version>0.1.7</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>commons-lang</groupId>
|
||||
<artifactId>commons-lang</artifactId>
|
||||
<version>2.4</version>
|
||||
</dependency>
|
||||
|
||||
<!-- test -->
|
||||
<dependency>
|
||||
<groupId>junit</groupId>
|
||||
<artifactId>junit</artifactId>
|
||||
<version>4.4</version>
|
||||
<scope>test</scope>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>javax.servlet</groupId>
|
||||
<artifactId>servlet-api</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
</project>
|
||||
82
src/main/java/com/mysema/codegen/CodeWriter.java
Normal file
82
src/main/java/com/mysema/codegen/CodeWriter.java
Normal file
@ -0,0 +1,82 @@
|
||||
/*
|
||||
* Copyright (c) 2010 Mysema Ltd.
|
||||
* All rights reserved.
|
||||
*
|
||||
*/
|
||||
package com.mysema.codegen;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.util.Collection;
|
||||
|
||||
import org.apache.commons.collections15.Transformer;
|
||||
|
||||
/**
|
||||
* @author tiwe
|
||||
*
|
||||
*/
|
||||
public interface CodeWriter extends Appendable{
|
||||
|
||||
CodeWriter annotation(Annotation annotation) throws IOException;
|
||||
|
||||
CodeWriter annotation(Class<? extends Annotation> annotation) throws IOException;
|
||||
|
||||
CodeWriter beginClass(String simpleName) throws IOException;
|
||||
|
||||
CodeWriter beginClass(String simpleName, String superClass, String... interfaces) throws IOException;
|
||||
|
||||
<T> CodeWriter beginConstructor(Collection<T> params, Transformer<T, String> transformer) throws IOException;
|
||||
|
||||
CodeWriter beginConstructor(String... params) throws IOException;
|
||||
|
||||
CodeWriter beginInterface(String simpleName, String... interfaces) throws IOException;
|
||||
|
||||
CodeWriter beginLine(String... segments) throws IOException;
|
||||
|
||||
<T> CodeWriter beginPublicMethod(String returnType, String methodName, Collection<T> parameters, Transformer<T, String> transformer) throws IOException;
|
||||
|
||||
CodeWriter beginPublicMethod(String returnType, String methodName, String... args) throws IOException;
|
||||
|
||||
<T> CodeWriter beginStaticMethod(String type, String name, Collection<T> params, Transformer<T, String> transformer) throws IOException;
|
||||
|
||||
CodeWriter beginStaticMethod(String returnType, String methodName, String... args) throws IOException;
|
||||
|
||||
CodeWriter end() throws IOException;
|
||||
|
||||
CodeWriter field(String type, String name) throws IOException;
|
||||
|
||||
CodeWriter imports(Class<?>... imports) throws IOException;
|
||||
|
||||
CodeWriter imports(Package... imports) throws IOException;
|
||||
|
||||
CodeWriter javadoc(String... lines) throws IOException;
|
||||
|
||||
String join(String prefix, String suffix, Iterable<String> args);
|
||||
|
||||
String join(String prefix, String suffix, String... args);
|
||||
|
||||
CodeWriter line(String... segments) throws IOException;
|
||||
|
||||
CodeWriter nl() throws IOException;
|
||||
|
||||
CodeWriter packageDecl(String packageName) throws IOException;
|
||||
|
||||
CodeWriter privateField(String type, String name) throws IOException;
|
||||
|
||||
CodeWriter privateStaticFinal(String type, String name, String value) throws IOException;
|
||||
|
||||
CodeWriter protectedField(String type, String name) throws IOException;
|
||||
|
||||
CodeWriter publicField(String type, String name) throws IOException;
|
||||
|
||||
CodeWriter publicFinal(String type, String name) throws IOException;
|
||||
|
||||
CodeWriter publicFinal(String type, String name, String value) throws IOException;
|
||||
|
||||
CodeWriter publicStaticFinal(String type, String name, String value) throws IOException;
|
||||
|
||||
CodeWriter staticimports(Class<?>... imports) throws IOException;
|
||||
|
||||
CodeWriter suppressWarnings(String type) throws IOException;
|
||||
|
||||
}
|
||||
23
src/main/java/com/mysema/codegen/Evaluator.java
Normal file
23
src/main/java/com/mysema/codegen/Evaluator.java
Normal file
@ -0,0 +1,23 @@
|
||||
/*
|
||||
* Copyright (c) 2010 Mysema Ltd.
|
||||
* All rights reserved.
|
||||
*
|
||||
*/
|
||||
package com.mysema.codegen;
|
||||
|
||||
/**
|
||||
* Evaluator defines an interface for returning a value as a result of
|
||||
* evaluating an expression using the given argument array
|
||||
*
|
||||
* @author tiwe
|
||||
*
|
||||
*/
|
||||
public interface Evaluator<T> {
|
||||
|
||||
/**
|
||||
* @param args
|
||||
* @return
|
||||
*/
|
||||
T evaluate(Object... args);
|
||||
|
||||
}
|
||||
159
src/main/java/com/mysema/codegen/EvaluatorFactory.java
Normal file
159
src/main/java/com/mysema/codegen/EvaluatorFactory.java
Normal file
@ -0,0 +1,159 @@
|
||||
/*
|
||||
* Copyright (c) 2010 Mysema Ltd.
|
||||
* All rights reserved.
|
||||
*
|
||||
*/
|
||||
package com.mysema.codegen;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.StringWriter;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.io.Writer;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URISyntaxException;
|
||||
import java.net.URL;
|
||||
import java.net.URLClassLoader;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import javax.tools.JavaCompiler;
|
||||
import javax.tools.SimpleJavaFileObject;
|
||||
import javax.tools.JavaCompiler.CompilationTask;
|
||||
|
||||
|
||||
/**
|
||||
* EvaluatorFactory is a factory implementation for creating Evaluator instances
|
||||
*
|
||||
* @author tiwe
|
||||
*
|
||||
*/
|
||||
public class EvaluatorFactory {
|
||||
|
||||
private final File classDir;
|
||||
|
||||
private final ClassLoader loader;
|
||||
|
||||
private final String classpath;
|
||||
|
||||
private final JavaCompiler compiler;
|
||||
|
||||
private final List<String> compilationOptions;
|
||||
|
||||
public EvaluatorFactory(JavaCompiler compiler, File classDir,
|
||||
URLClassLoader parent) {
|
||||
try {
|
||||
this.compiler = compiler;
|
||||
this.classDir = classDir;
|
||||
if (!classDir.exists()){
|
||||
if (!classDir.mkdirs()){
|
||||
throw new IllegalArgumentException(
|
||||
classDir.getAbsolutePath() + " could not be created");
|
||||
}
|
||||
}
|
||||
this.classpath = SimpleCompiler.getClassPath(parent);
|
||||
this.loader = new URLClassLoader(new URL[] { classDir.toURI().toURL() }, parent);
|
||||
this.compilationOptions = Arrays.asList(
|
||||
"-classpath", classpath,
|
||||
"-d", classDir.getAbsolutePath(),
|
||||
"-g:none");
|
||||
} catch (MalformedURLException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
private void compile(String source, Class<?> projectionType,
|
||||
String[] names, Class<?>[] types, String id) throws IOException,
|
||||
UnsupportedEncodingException {
|
||||
// create source
|
||||
StringWriter writer = new StringWriter();
|
||||
JavaWriter javaw = new JavaWriter(writer);
|
||||
javaw.beginClass(id, null);
|
||||
String[] params = new String[names.length];
|
||||
for (int i = 0; i < params.length; i++) {
|
||||
params[i] = toName(types[i]) + " " + names[i];
|
||||
}
|
||||
|
||||
javaw.beginStaticMethod(toName(projectionType), "eval", params);
|
||||
javaw.line("return ", source, ";");
|
||||
javaw.end();
|
||||
javaw.end();
|
||||
|
||||
// compile
|
||||
try {
|
||||
SimpleJavaFileObject javaFileObject = new StringJavaFileObject(id, writer.toString());
|
||||
Writer out = new StringWriter();
|
||||
|
||||
CompilationTask task = compiler.getTask(out, null, null,
|
||||
compilationOptions, null, Collections.singletonList(javaFileObject));
|
||||
if (!task.call().booleanValue()) {
|
||||
throw new RuntimeException("Compilation of " + source + " failed.\n" + out.toString());
|
||||
}
|
||||
} catch (URISyntaxException e) {
|
||||
throw new IOException(e);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
protected String toId(String source, Class<?> returnType, Class<?>... types) {
|
||||
StringBuilder b = new StringBuilder("Q");
|
||||
b.append("_").append(source.hashCode());
|
||||
b.append("_").append(returnType.getName().hashCode());
|
||||
for (Class<?> type : types) {
|
||||
b.append("_").append(type.getName().hashCode());
|
||||
}
|
||||
return b.toString().replace('-', '0');
|
||||
}
|
||||
|
||||
protected String toName(Class<?> cl) {
|
||||
if (cl.isArray()) {
|
||||
return toName(cl.getComponentType()) + "[]";
|
||||
} else if (cl.getPackage() == null || cl.getPackage().getName().equals("java.lang")) {
|
||||
return cl.getSimpleName();
|
||||
} else {
|
||||
return cl.getName().replace('$', '.');
|
||||
}
|
||||
}
|
||||
|
||||
public <T> Evaluator<T> createEvaluator(String source,
|
||||
Class<? extends T> projectionType, String[] names, Class<?>[] types) {
|
||||
|
||||
try {
|
||||
String id = toId(source, projectionType, types);
|
||||
if (!new File(classDir, id + ".class").exists()) {
|
||||
compile(source, projectionType, names, types, id);
|
||||
}
|
||||
|
||||
Class<?> clazz = loader.loadClass(id);
|
||||
final Method method = clazz.getMethod("eval", types);
|
||||
return new Evaluator<T>() {
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public T evaluate(Object... args) {
|
||||
try {
|
||||
return (T) method.invoke(null, args);
|
||||
} catch (IllegalAccessException e) {
|
||||
throw new IllegalArgumentException(e);
|
||||
} catch (InvocationTargetException e) {
|
||||
throw new IllegalArgumentException(e);
|
||||
}
|
||||
}
|
||||
};
|
||||
} catch (ClassNotFoundException e) {
|
||||
throw new RuntimeException(e);
|
||||
} catch (SecurityException e) {
|
||||
throw new RuntimeException(e);
|
||||
} catch (NoSuchMethodException e) {
|
||||
throw new RuntimeException(e);
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
throw new RuntimeException(e);
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
420
src/main/java/com/mysema/codegen/JavaWriter.java
Normal file
420
src/main/java/com/mysema/codegen/JavaWriter.java
Normal file
@ -0,0 +1,420 @@
|
||||
/*
|
||||
* Copyright (c) 2010 Mysema Ltd.
|
||||
* All rights reserved.
|
||||
*
|
||||
*/
|
||||
package com.mysema.codegen;
|
||||
|
||||
import static com.mysema.codegen.Symbols.ASSIGN;
|
||||
import static com.mysema.codegen.Symbols.COMMA;
|
||||
import static com.mysema.codegen.Symbols.DOT;
|
||||
import static com.mysema.codegen.Symbols.NEWLINE;
|
||||
import static com.mysema.codegen.Symbols.QUOTE;
|
||||
import static com.mysema.codegen.Symbols.SEMICOLON;
|
||||
import static com.mysema.codegen.Symbols.SPACE;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import org.apache.commons.collections15.Transformer;
|
||||
import org.apache.commons.lang.StringEscapeUtils;
|
||||
|
||||
import com.mysema.commons.lang.Assert;
|
||||
|
||||
/**
|
||||
* @author tiwe
|
||||
*
|
||||
*/
|
||||
public final class JavaWriter implements Appendable, CodeWriter{
|
||||
|
||||
private static final String EXTENDS = " extends ";
|
||||
|
||||
private static final String IMPLEMENTS = " implements ";
|
||||
|
||||
private static final String IMPORT = "import ";
|
||||
|
||||
private static final String IMPORT_STATIC = "import static ";
|
||||
|
||||
private static final String PACKAGE = "package ";
|
||||
|
||||
private static final String PRIVATE = "private ";
|
||||
|
||||
private static final String PRIVATE_STATIC_FINAL = "private static final ";
|
||||
|
||||
private static final String PROTECTED = "protected ";
|
||||
|
||||
private static final String PUBLIC = "public ";
|
||||
|
||||
private static final String PUBLIC_CLASS = "public class ";
|
||||
|
||||
private static final String PUBLIC_FINAL = "public final ";
|
||||
|
||||
private static final String PUBLIC_INTERFACE = "public interface ";
|
||||
|
||||
private static final String PUBLIC_STATIC = "public static ";
|
||||
|
||||
private static final String PUBLIC_STATIC_FINAL = "public static final ";
|
||||
|
||||
private final Appendable appendable;
|
||||
|
||||
private final Set<Class<?>> importedClasses = new HashSet<Class<?>>();
|
||||
|
||||
private final Set<Package> importedPackages = new HashSet<Package>();
|
||||
|
||||
private String indent = "";
|
||||
|
||||
private String type;
|
||||
|
||||
public JavaWriter(Appendable appendable){
|
||||
this.appendable = Assert.notNull(appendable,"appendable");
|
||||
importedPackages.add(Object.class.getPackage());
|
||||
}
|
||||
|
||||
@Override
|
||||
public JavaWriter annotation(Annotation annotation) throws IOException {
|
||||
append(indent).append("@").appendType(annotation.annotationType()).append("(");
|
||||
boolean first = true;
|
||||
for (Method method : annotation.annotationType().getDeclaredMethods()){
|
||||
if (!first){
|
||||
append(COMMA);
|
||||
}
|
||||
append(method.getName()+"=");
|
||||
try {
|
||||
Object value = method.invoke(annotation);
|
||||
annotationConstant(value);
|
||||
} catch (IllegalArgumentException e) {
|
||||
throw new RuntimeException(e);
|
||||
} catch (IllegalAccessException e) {
|
||||
throw new RuntimeException(e);
|
||||
} catch (InvocationTargetException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
first = false;
|
||||
}
|
||||
return append(")").nl();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public JavaWriter annotation(Class<? extends Annotation> annotation) throws IOException{
|
||||
return append(indent).append("@").appendType(annotation).nl();
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private void annotationConstant(Object value) throws IOException{
|
||||
if (value instanceof Class){
|
||||
appendType((Class)value).append(".class");
|
||||
}else if (value instanceof Number){
|
||||
append(value.toString());
|
||||
}else if (value instanceof Enum){
|
||||
Enum enumValue = (Enum)value;
|
||||
append(enumValue.getDeclaringClass().getName()+DOT+enumValue.name());
|
||||
}else if (value instanceof String){
|
||||
append(QUOTE + StringEscapeUtils.escapeJava(value.toString()) + QUOTE);
|
||||
}else{
|
||||
throw new IllegalArgumentException("Unsupported annotation value : " + value);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public JavaWriter append(char c) throws IOException {
|
||||
appendable.append(c);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public JavaWriter append(CharSequence csq) throws IOException {
|
||||
appendable.append(csq);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public JavaWriter append(CharSequence csq, int start, int end) throws IOException {
|
||||
appendable.append(csq, start, end);
|
||||
return this;
|
||||
}
|
||||
|
||||
private JavaWriter appendType(Class<?> type) throws IOException{
|
||||
if (importedClasses.contains(type) || importedPackages.contains(type.getPackage())){
|
||||
append(type.getSimpleName());
|
||||
}else{
|
||||
append(type.getName());
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public JavaWriter beginClass(String simpleName) throws IOException{
|
||||
return beginClass(simpleName, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public JavaWriter beginClass(String simpleName, String superClass, String... interfaces) throws IOException{
|
||||
nl().append(indent + PUBLIC_CLASS + simpleName);
|
||||
if (superClass != null){
|
||||
append(EXTENDS + superClass);
|
||||
}
|
||||
if (interfaces.length > 0){
|
||||
append(IMPLEMENTS).join(COMMA, interfaces);
|
||||
}
|
||||
append(" {").nl().nl();
|
||||
goIn();
|
||||
|
||||
type = simpleName;
|
||||
if (type.contains("<")){
|
||||
type = type.substring(0, type.indexOf('<'));
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> JavaWriter beginConstructor(Collection<T> parameters, Transformer<T,String> transformer) throws IOException {
|
||||
append(indent + PUBLIC + type).params(parameters, transformer).append(" {").nl();
|
||||
return goIn();
|
||||
}
|
||||
|
||||
@Override
|
||||
public JavaWriter beginConstructor(String... parameters) throws IOException{
|
||||
append(indent + PUBLIC + type).params(parameters).append(" {").nl();
|
||||
return goIn();
|
||||
}
|
||||
|
||||
@Override
|
||||
public JavaWriter beginInterface(String simpleName, String... interfaces) throws IOException {
|
||||
nl().append(indent + PUBLIC_INTERFACE + simpleName);
|
||||
if (interfaces.length > 0){
|
||||
append(EXTENDS).join(COMMA, interfaces);
|
||||
}
|
||||
append(" {").nl().nl();
|
||||
goIn();
|
||||
|
||||
type = simpleName;
|
||||
if (type.contains("<")){
|
||||
type = type.substring(0, type.indexOf('<'));
|
||||
}
|
||||
return this;
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public JavaWriter beginLine(String... segments) throws IOException {
|
||||
append(indent);
|
||||
for (String segment : segments){
|
||||
append(segment);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
private JavaWriter beginMethod(String returnType, String modifiers, String methodName, String... args) throws IOException{
|
||||
append(indent + modifiers + returnType + SPACE + methodName).params(args).append(" {").nl();
|
||||
return goIn();
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> JavaWriter beginPublicMethod(String returnType, String methodName, Collection<T> parameters, Transformer<T, String> transformer) throws IOException {
|
||||
return beginMethod(returnType, PUBLIC, methodName, transform(parameters, transformer));
|
||||
}
|
||||
|
||||
@Override
|
||||
public JavaWriter beginPublicMethod(String returnType, String methodName, String... args) throws IOException{
|
||||
return beginMethod(returnType, PUBLIC, methodName, args);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> JavaWriter beginStaticMethod(String returnType, String methodName, Collection<T> parameters, Transformer<T, String> transformer) throws IOException {
|
||||
return beginMethod(returnType, PUBLIC_STATIC, methodName, transform(parameters, transformer));
|
||||
}
|
||||
|
||||
@Override
|
||||
public JavaWriter beginStaticMethod(String returnType, String methodName, String... args) throws IOException{
|
||||
return beginMethod(returnType, PUBLIC_STATIC, methodName, args);
|
||||
}
|
||||
|
||||
@Override
|
||||
public JavaWriter end() throws IOException{
|
||||
goOut();
|
||||
return line("}").nl();
|
||||
}
|
||||
|
||||
@Override
|
||||
public JavaWriter field(String type, String name) throws IOException {
|
||||
return stmt(type + SPACE + name).nl();
|
||||
}
|
||||
|
||||
private JavaWriter goIn(){
|
||||
indent += " ";
|
||||
return this;
|
||||
}
|
||||
|
||||
private JavaWriter goOut(){
|
||||
if (indent.length() >= 4){
|
||||
indent = indent.substring(0, indent.length() - 4);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public JavaWriter imports(Class<?>... imports) throws IOException{
|
||||
for (Class<?> cl : imports){
|
||||
importedClasses.add(cl);
|
||||
line(IMPORT + cl.getName() + SEMICOLON);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public JavaWriter imports(Package... imports) throws IOException {
|
||||
for (Package p : imports){
|
||||
importedPackages.add(p);
|
||||
line(IMPORT + p.getName() + ".*;");
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public JavaWriter javadoc(String... lines) throws IOException {
|
||||
line("/**");
|
||||
for (String line : lines){
|
||||
line(" * " + line);
|
||||
}
|
||||
return line(" */");
|
||||
}
|
||||
|
||||
private JavaWriter join(String sep, String... args) throws IOException{
|
||||
for (int i = 0; i < args.length; i++){
|
||||
if (i > 0){
|
||||
append(sep);
|
||||
}
|
||||
append(args[i]);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String join(String prefix, String suffix, Iterable<String> args) {
|
||||
StringBuilder builder = new StringBuilder();
|
||||
boolean first = true;
|
||||
for (String arg : args){
|
||||
if (!first){
|
||||
builder.append(COMMA);
|
||||
}
|
||||
builder.append(prefix).append(arg).append(suffix);
|
||||
first = false;
|
||||
}
|
||||
return builder.toString();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String join(String prefix, String suffix, String... args) {
|
||||
return join(prefix, suffix, Arrays.asList(args));
|
||||
}
|
||||
|
||||
@Override
|
||||
public JavaWriter line(String... segments) throws IOException{
|
||||
append(indent);
|
||||
for (String segment : segments){
|
||||
append(segment);
|
||||
}
|
||||
return nl();
|
||||
}
|
||||
|
||||
@Override
|
||||
public JavaWriter nl() throws IOException {
|
||||
return append(NEWLINE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public JavaWriter packageDecl(String packageName) throws IOException{
|
||||
return line(PACKAGE + packageName + SEMICOLON).nl();
|
||||
}
|
||||
|
||||
private <T> JavaWriter params(Collection<T> parameters, Transformer<T,String> transformer) throws IOException{
|
||||
append("(");
|
||||
boolean first = true;
|
||||
for (T param : parameters){
|
||||
if (!first){
|
||||
append(COMMA);
|
||||
}
|
||||
append(transformer.transform(param));
|
||||
first = false;
|
||||
}
|
||||
append(")");
|
||||
return this;
|
||||
}
|
||||
|
||||
private JavaWriter params(String... params) throws IOException{
|
||||
append("(");
|
||||
join(COMMA, params);
|
||||
append(")");
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public JavaWriter privateField(String type, String name) throws IOException {
|
||||
return stmt(PRIVATE + type + SPACE + name).nl();
|
||||
}
|
||||
|
||||
@Override
|
||||
public JavaWriter privateStaticFinal(String type, String name, String value) throws IOException {
|
||||
return stmt(PRIVATE_STATIC_FINAL + type + SPACE + name + ASSIGN + value).nl();
|
||||
}
|
||||
|
||||
@Override
|
||||
public JavaWriter protectedField(String type, String name) throws IOException {
|
||||
return stmt(PROTECTED + type + SPACE + name).nl();
|
||||
}
|
||||
|
||||
@Override
|
||||
public JavaWriter publicField(String type, String name) throws IOException {
|
||||
return stmt(PUBLIC + type + SPACE + name).nl();
|
||||
}
|
||||
|
||||
@Override
|
||||
public JavaWriter publicFinal(String type, String name) throws IOException {
|
||||
return stmt(PUBLIC_FINAL + type + SPACE + name).nl();
|
||||
}
|
||||
|
||||
@Override
|
||||
public JavaWriter publicFinal(String type, String name, String value) throws IOException {
|
||||
return stmt(PUBLIC_FINAL + type + SPACE + name + ASSIGN + value).nl();
|
||||
}
|
||||
|
||||
@Override
|
||||
public JavaWriter publicStaticFinal(String type, String name, String value) throws IOException {
|
||||
return stmt(PUBLIC_STATIC_FINAL + type + SPACE + name + ASSIGN + value).nl();
|
||||
}
|
||||
|
||||
@Override
|
||||
public JavaWriter staticimports(Class<?>... imports) throws IOException{
|
||||
for (Class<?> cl : imports){
|
||||
line(IMPORT_STATIC + cl.getName() + ".*;");
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
private JavaWriter stmt(String stmt) throws IOException{
|
||||
return line(stmt + SEMICOLON);
|
||||
}
|
||||
|
||||
@Override
|
||||
public JavaWriter suppressWarnings(String type) throws IOException{
|
||||
return line("@SuppressWarnings(\"" + type +"\")");
|
||||
}
|
||||
|
||||
private <T> String[] transform(Collection<T> parameters, Transformer<T,String> transformer){
|
||||
String[] rv = new String[parameters.size()];
|
||||
int i = 0;
|
||||
for (T value : parameters){
|
||||
rv[i++] = transformer.transform(value);
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
}
|
||||
121
src/main/java/com/mysema/codegen/SimpleCompiler.java
Normal file
121
src/main/java/com/mysema/codegen/SimpleCompiler.java
Normal file
@ -0,0 +1,121 @@
|
||||
/*
|
||||
* Copyright (c) 2010 Mysema Ltd.
|
||||
* All rights reserved.
|
||||
*
|
||||
*/
|
||||
package com.mysema.codegen;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.io.Writer;
|
||||
import java.net.URL;
|
||||
import java.net.URLClassLoader;
|
||||
import java.net.URLDecoder;
|
||||
import java.nio.charset.Charset;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.lang.model.SourceVersion;
|
||||
import javax.tools.DiagnosticListener;
|
||||
import javax.tools.JavaCompiler;
|
||||
import javax.tools.JavaFileManager;
|
||||
import javax.tools.JavaFileObject;
|
||||
import javax.tools.StandardJavaFileManager;
|
||||
import javax.tools.ToolProvider;
|
||||
|
||||
/**
|
||||
* @author tiwe
|
||||
*
|
||||
*/
|
||||
public class SimpleCompiler implements JavaCompiler{
|
||||
|
||||
private final ClassLoader classLoader;
|
||||
|
||||
private String classPath;
|
||||
|
||||
private final JavaCompiler compiler;
|
||||
|
||||
public static String getClassPath(URLClassLoader classLoader) {
|
||||
try{
|
||||
StringBuilder path = new StringBuilder();
|
||||
for (URL url : ((URLClassLoader)classLoader).getURLs()){
|
||||
if (path.length() > 0){
|
||||
path.append(File.pathSeparator);
|
||||
}
|
||||
String decodedPath = URLDecoder.decode(url.getPath(),"UTF-8");
|
||||
path.append(new File(decodedPath).getAbsolutePath());
|
||||
}
|
||||
return path.toString();
|
||||
}catch(UnsupportedEncodingException e){
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public SimpleCompiler(){
|
||||
this(ToolProvider.getSystemJavaCompiler(), Thread.currentThread().getContextClassLoader());
|
||||
}
|
||||
|
||||
public SimpleCompiler(JavaCompiler compiler, ClassLoader classLoader){
|
||||
this.compiler = compiler;
|
||||
this.classLoader = classLoader;
|
||||
}
|
||||
|
||||
private String getClasspath(){
|
||||
if (classPath == null){
|
||||
if (classLoader instanceof URLClassLoader){
|
||||
classPath = getClassPath((URLClassLoader)classLoader);
|
||||
}else{
|
||||
throw new IllegalArgumentException("Unsupported ClassLoader " + classLoader);
|
||||
}
|
||||
}
|
||||
return classPath;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<SourceVersion> getSourceVersions() {
|
||||
return compiler.getSourceVersions();
|
||||
}
|
||||
|
||||
@Override
|
||||
public StandardJavaFileManager getStandardFileManager(
|
||||
DiagnosticListener<? super JavaFileObject> diagnosticListener,
|
||||
Locale locale, Charset charset) {
|
||||
return compiler.getStandardFileManager(diagnosticListener, locale, charset);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompilationTask getTask(Writer out, JavaFileManager fileManager,
|
||||
DiagnosticListener<? super JavaFileObject> diagnosticListener,
|
||||
Iterable<String> options, Iterable<String> classes,
|
||||
Iterable<? extends JavaFileObject> compilationUnits) {
|
||||
return compiler.getTask(out, fileManager, diagnosticListener, options, classes, compilationUnits);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int isSupportedOption(String option) {
|
||||
return compiler.isSupportedOption(option);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int run(InputStream in, OutputStream out, OutputStream err, String... arguments) {
|
||||
for (String a : arguments){
|
||||
if (a.equals("-classpath")){
|
||||
return compiler.run(in, out, err, arguments);
|
||||
}
|
||||
}
|
||||
|
||||
// no classpath given
|
||||
List<String> args = new ArrayList<String>(arguments.length + 2);
|
||||
args.add("-classpath");
|
||||
args.add(getClasspath());
|
||||
for (String arg : arguments){
|
||||
args.add(arg);
|
||||
}
|
||||
return compiler.run(in, out, err, args.toArray(new String[args.size()]));
|
||||
}
|
||||
|
||||
}
|
||||
38
src/main/java/com/mysema/codegen/StringJavaFileObject.java
Normal file
38
src/main/java/com/mysema/codegen/StringJavaFileObject.java
Normal file
@ -0,0 +1,38 @@
|
||||
/*
|
||||
* Copyright (c) 2010 Mysema Ltd.
|
||||
* All rights reserved.
|
||||
*
|
||||
*/
|
||||
package com.mysema.codegen;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
|
||||
import javax.tools.SimpleJavaFileObject;
|
||||
|
||||
/**
|
||||
* @author tiwe
|
||||
*
|
||||
*/
|
||||
public class StringJavaFileObject extends SimpleJavaFileObject {
|
||||
|
||||
private final String contents;
|
||||
|
||||
public StringJavaFileObject(String className, String contents) throws URISyntaxException{
|
||||
super(new URI(className), Kind.SOURCE);
|
||||
this.contents = contents;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CharSequence getCharContent(boolean ignoreEncodingErrors) throws IOException {
|
||||
return contents;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isNameCompatible(String simpleName, Kind kind) {
|
||||
return kind.equals(getKind()) &&
|
||||
(simpleName.equals(toUri().getPath()) || toUri().getPath().endsWith("/" + simpleName));
|
||||
}
|
||||
|
||||
}
|
||||
47
src/main/java/com/mysema/codegen/Symbols.java
Normal file
47
src/main/java/com/mysema/codegen/Symbols.java
Normal file
@ -0,0 +1,47 @@
|
||||
/*
|
||||
* Copyright (c) 2010 Mysema Ltd.
|
||||
* All rights reserved.
|
||||
*
|
||||
*/
|
||||
package com.mysema.codegen;
|
||||
|
||||
/**
|
||||
* @author tiwe
|
||||
*
|
||||
*/
|
||||
public final class Symbols {
|
||||
|
||||
public static final String ASSIGN = " = ";
|
||||
|
||||
public static final String COMMA = ", ";
|
||||
|
||||
public static final String DOT = ".";
|
||||
|
||||
public static final String DOT_CLASS = ".class";
|
||||
|
||||
public static final String EMPTY = "";
|
||||
|
||||
public static final String NEW = "new ";
|
||||
|
||||
public static final String NEWLINE = "\n";
|
||||
|
||||
public static final String QUOTE = "\"";
|
||||
|
||||
public static final String RETURN = "return ";
|
||||
|
||||
public static final String SEMICOLON = ";";
|
||||
|
||||
public static final String SERIAL = "serial";
|
||||
|
||||
public static final String SPACE = " ";
|
||||
|
||||
public static final String STAR = "*";
|
||||
|
||||
public static final String SUPER = "super";
|
||||
|
||||
public static final String THIS = "this";
|
||||
|
||||
public static final String UNCHECKED = "unchecked";
|
||||
|
||||
private Symbols(){}
|
||||
}
|
||||
61
src/test/java/com/mysema/codegen/JavaWriterTest.java
Normal file
61
src/test/java/com/mysema/codegen/JavaWriterTest.java
Normal file
@ -0,0 +1,61 @@
|
||||
package com.mysema.codegen;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.StringWriter;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
public class JavaWriterTest {
|
||||
|
||||
@Test
|
||||
public void testBasic() throws IOException {
|
||||
StringWriter w = new StringWriter();
|
||||
CodeWriter writer = new JavaWriter(w);
|
||||
writer.packageDecl("com.mysema.codegen");
|
||||
writer.imports(IOException.class, StringWriter.class, Test.class);
|
||||
writer.beginClass("JavaWriterTest");
|
||||
writer.annotation(Test.class);
|
||||
writer.beginPublicMethod("void", "test");
|
||||
writer.line("// TODO");
|
||||
writer.end();
|
||||
writer.end();
|
||||
System.out.println(w);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFields() throws IOException{
|
||||
StringWriter w = new StringWriter();
|
||||
CodeWriter writer = new JavaWriter(w);
|
||||
writer.beginClass("FieldTests");
|
||||
// private
|
||||
writer.privateField("String", "privateField");
|
||||
writer.privateStaticFinal("String", "privateStaticFinal", "\"val\"");
|
||||
// protected
|
||||
writer.protectedField("String","protectedField");
|
||||
// field
|
||||
writer.field("String","field");
|
||||
// public
|
||||
writer.publicField("String","publicField");
|
||||
writer.publicStaticFinal("String", "publicStaticFinal", "\"val\"");
|
||||
writer.end();
|
||||
System.out.println(w);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMethods() throws IOException{
|
||||
StringWriter w = new StringWriter();
|
||||
CodeWriter writer = new JavaWriter(w);
|
||||
writer.beginClass("MethodTests");
|
||||
// private
|
||||
|
||||
// protected
|
||||
|
||||
// method
|
||||
|
||||
// public
|
||||
|
||||
writer.end();
|
||||
System.out.println(w);
|
||||
}
|
||||
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user