OPENJPA-1628,OPENJPA-1187,OPENJPA-1622: Use javac's -s option to control output rather than extraneous -Aout option

git-svn-id: https://svn.apache.org/repos/asf/openjpa/trunk@933342 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Pinaki Poddar 2010-04-12 18:12:49 +00:00
parent 0ca80f7f79
commit 85b89a8701
5 changed files with 28 additions and 197 deletions

View File

@ -20,14 +20,10 @@ package org.apache.openjpa.persistence.meta;
import static javax.lang.model.SourceVersion.RELEASE_6;
import java.io.File;
import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.URI;
import java.net.URL;
import java.util.Arrays;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.Map;
@ -47,11 +43,7 @@ import javax.lang.model.type.TypeMirror;
import javax.lang.model.util.Elements;
import javax.persistence.metamodel.StaticMetamodel;
import javax.tools.Diagnostic;
import javax.tools.JavaCompiler;
import javax.tools.JavaFileObject;
import javax.tools.StandardJavaFileManager;
import javax.tools.StandardLocation;
import javax.tools.ToolProvider;
import org.apache.openjpa.lib.util.Localizer;
import org.apache.openjpa.meta.MetaDataFactory;
@ -79,26 +71,16 @@ import org.apache.openjpa.persistence.util.SourceCode;
* <TABLE border="1">
* <TR><TD>-Alog={log level}<TD>The logging level. Default is <code>WARN</code>. Permissible values are
* <code>TRACE</code>, <code>INFO</code>, <code>WARN</code> or <code> ERROR</code>.
* <TR><TD>-Asource={n} <TD>Java source version of the generated code. Default is <code>6</code>.
* <TR><TD>-Anaming={class name} <TD>fully-qualified name of a class implementing
* <TR><TD>-Asource={n} <TD>Java source version of the generated code. Default is <code>6</code>.
* <TR><TD>-Anaming={class name} <TD>fully-qualified name of a class implementing
* <code>org.apache.openjpa.meta.MetaDataFactory</code> that determines
* the name of a meta-class given the name of the original persistent Java entity class. Defaults to
* <code>org.apache.openjpa.persistence.PersistenceMetaDataFactory</code> which appends a underscore character
* (<code>_</code>) to the original Java class name.
* <TR><TD>-Aheader={url} <TD>
* <TR><TD>-Aheader={url} <TD>
* A url whose content will appear as comment header to the generated file(s). Recognizes special value
* <code>ASL</code> for Apache Source License header as comment. By default adds a OpenJPA proprietary
* text.
* <TR><TD>-Aout={dir} <TD>
* A directory in the local file system. The generated files will be written <em>relative</em> to this directory
* according to the package structure i.e. if <code>dir</code> is specified as <code>/myproject/generated-src</code>
* then the generated source code will be written to <code>/myproject/generated-src/mypackage/MyEntity_.java</code>.
* If this option is not specified, then an attempt will be made to write the generated source file in the same
* directory of the source code of original class <code>mypackage.MyEntity</code>. The source code location for
* <code>mypackage.MyEntity</code> can only be determined for Sun JDK6 and <code>tools.jar</code> being available
* to the compiler classpath. If the source code location for the original class can not be determined, and the
* option is not specified, then the generated source code is written relative to the current directory according
* to the package structure.
* </TABLE>
* <br>
*
@ -112,18 +94,15 @@ import org.apache.openjpa.persistence.util.SourceCode;
"javax.persistence.Embeddable",
"javax.persistence.MappedSuperclass" })
@SupportedOptions({ "openjpa.log", "log",
"openjpa.out", "out",
"openjpa.source", "source",
"openjpa.naming", "naming",
"openjpa.header", "header",
"openjpa.generate"
"openjpa.source", "source",
"openjpa.naming", "naming",
"openjpa.header", "header",
"openjpa.generate"
})
@SupportedSourceVersion(RELEASE_6)
public class AnnotationProcessor6 extends AbstractProcessor {
private SourceAnnotationHandler handler;
private StandardJavaFileManager fileManager;
private boolean isUserSpecifiedOutputLocation;
private MetaDataFactory factory;
private int generatedSourceVersion = 6;
private CompileTimeLogger logger;
@ -212,7 +191,6 @@ public class AnnotationProcessor6 extends AbstractProcessor {
processingEnv.getMessager().printMessage(Diagnostic.Kind.NOTE, _loc.get("mmg-tool-banner").toString());
logger = new CompileTimeLogger(processingEnv, getOptionValue("openjpa.log", "log"));
setSourceVersion();
setFileManager();
setNamingPolicy();
setHeader();
handler = new SourceAnnotationHandler(processingEnv, logger);
@ -252,8 +230,7 @@ public class AnnotationProcessor6 extends AbstractProcessor {
annotate(source, originalClass);
TypeElement supCls = handler.getPersistentSupertype(e);
if (supCls != null) {
String superName = factory.getMetaModelClassName(
supCls.toString());
String superName = factory.getMetaModelClassName(supCls.toString());
source.getTopLevelClass().setSuper(superName);
}
try {
@ -376,54 +353,15 @@ public class AnnotationProcessor6 extends AbstractProcessor {
}
}
private void setFileManager() {
JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
fileManager = compiler.getStandardFileManager(null, null, null);
String outDir = getOptionValue("openjpa.out", "out");
if (outDir != null)
isUserSpecifiedOutputLocation = setSourceOutputDirectory(new File(outDir));
}
/**
* Creates a file where source code of the given metaClass will be written.
*
*/
private PrintWriter createSourceFile(String originalClass, String metaClass, TypeElement e)
throws IOException {
if (!isUserSpecifiedOutputLocation) {
setSourceOutputDirectory(OutputPath.getAbsoluteDirectory(processingEnv, e));
}
JavaFileObject javaFile = fileManager.getJavaFileForOutput(StandardLocation.SOURCE_OUTPUT,
metaClass, JavaFileObject.Kind.SOURCE,
null); // do not use sibling hint because of indeterminable behavior across JDK
JavaFileObject javaFile = processingEnv.getFiler().createSourceFile(metaClass, e);
logger.info(_loc.get("mmg-process", javaFile.toUri()));
OutputStream out = javaFile.openOutputStream();
PrintWriter writer = new PrintWriter(out);
return writer;
}
/**
* Sets the output directory for generated source files.
* Tries to create the directory structure if does not exist.
*
* @return true if the output has been set successfully.
*/
boolean setSourceOutputDirectory(File outDir) {
if (outDir == null)
return false;
if (!outDir.exists()) {
if (!outDir.mkdirs()) {
logger.warn(_loc.get("mmg-bad-out", outDir, StandardLocation.SOURCE_OUTPUT));
return false;
}
}
try {
fileManager.setLocation(StandardLocation.SOURCE_OUTPUT, Collections.singleton(outDir));
return true;
} catch (IOException e) {
logger.warn(_loc.get("mmg-bad-out", outDir, StandardLocation.SOURCE_OUTPUT));
return false;
}
return new PrintWriter(javaFile.openWriter());
}
/**
@ -437,97 +375,4 @@ public class AnnotationProcessor6 extends AbstractProcessor {
}
return null;
}
/**
* An utility class to determine the source file corresponding to a {@link TypeElement}.
* The utility uses Sun JDK internal API (com.sun.tools.*) and hence works reflectively
* to avoid compile-time dependency.
*
* @author Pinaki Poddar
*
*/
public static class OutputPath {
private static Class<?> trees = null;
static {
try {
trees = Class.forName("com.sun.source.util.Trees");
} catch (Throwable t) {
}
}
/**
* Gets the directory relative to the Java source file corresponding to the TypeElement.
*
* @return null if the com.sun.source.util.* package is not available or the given TypeElement
* does not correspond to a compilation unit associated to a source file.
*/
public static File getAbsoluteDirectory(ProcessingEnvironment env, TypeElement e) {
if (trees == null)
return null;
try {
// Trees root = Trees.instance(env);
Object root = trees.getMethod("instance", new Class[]{ProcessingEnvironment.class})
.invoke(null, env);
// TreePath path = root.getPath(e);
Object path = root.getClass().getMethod("getPath", new Class[]{Element.class})
.invoke(root, e);
// CompilationUnitTree unit = path.getCompilationUnit();
Object unit = path.getClass().getMethod("getCompilationUnit", (Class[])null)
.invoke(path, (Object[])null);
// JavaFileObject f = unit.getSourceFile();
JavaFileObject f = (JavaFileObject)unit.getClass().getMethod("getSourceFile", (Class[])null)
.invoke(unit, (Object[])null);
URI uri = f.toUri();
File dir = getParentFile(new File(uri.toURL().getPath()),
packageDepth(e.getQualifiedName().toString()));
return dir;
} catch (Throwable t) {
return null;
}
}
/**
* Gets the parent of the given file recursively traversing to given number of levels.
*/
public static File getParentFile(File f, int n) {
if (n < 0)
return f;
if (n == 0)
return f.getParentFile();
return getParentFile(f.getParentFile(), n-1);
}
public static int packageDepth(String s) {
String pkg = getPackageName(s);
if (pkg == null)
return 0;
int depth = 1;
int i = 0;
while ((i = pkg.indexOf('.')) != -1) {
depth++;
pkg = pkg.substring(i+1);
}
return depth;
}
public static String getPackageName(String s) {
if (s == null)
return null;
int i = s.lastIndexOf('.');
return (i == -1) ? null : s.substring(0, i);
}
public static String getSimpleName(String s) {
if (s == null)
return null;
int i = s.lastIndexOf('.');
return (i == -1) ? s : s.substring(i+1);
}
}
}

View File

@ -172,7 +172,9 @@ Annotation processor option <code>-Aopenjpa.generate=true</code> is specified.
<programlisting>
$ javac -classpath path/to/openjpa-all.jar -Aopenjpa.generate=true mypackage/MyEntity.java
</programlisting>
will generate source code for canonical meta-model class <code>mypackage.MyEntity_.java</code>.
will generate source code for canonical meta-model class <code>mypackage.MyEntity_</code>.
The source code is generated relative to the directory specified in <code>-s</code> option
of <code>javac</code> compiler and defaulted to the current directory.
</para>
<para>
@ -207,20 +209,6 @@ the name of a meta-class given the name of the original persistent Java entity c
By default, adds a OpenJPA proprietary text as comment block.
</para>
</listitem>
<listitem>
<para>
-Aout=dir : A directory in the local file system. The generated files will be written
<emphasis>relative</emphasis> to this directory according to the package structure i.e. if <code>dir</code>
is specified as <code>/myproject/generated-src</code> then the generated source code will be
written to <code>/myproject/generated-src/mypackage/MyEntity_.java</code>.
If this option is not specified, then an attempt will be made to write the generated source file
in the same directory of the source code of original class <code>mypackage.MyEntity</code>.
The source code location for <code>mypackage.MyEntity</code> can only be determined for Sun JDK6
and when <code>tools.jar</code> being available to the compiler classpath. If the source code
location for the original class can not be determined, and the option is not specified, then the
generated source code is written relative to the current directory according to the package structure.
</para>
</listitem>
</itemizedlist>
</para>
</section>

View File

@ -1,10 +1,10 @@
./openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/meta/ArrayMember.java
./openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/meta/Embed0.java
./openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/meta/Embed1.java
./openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/meta/ExplicitFieldAccess.java
./openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/meta/ExplicitFieldAccessMixed.java
./openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/meta/ExplicitPropertyAccess.java
./openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/meta/ExplicitPropertyAccessMixed.java
./openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/meta/ImplicitFieldAccessBase.java
./openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/meta/ImplicitFieldAccessMappedSuperclass.java
./openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/meta/ImplicitFieldAccessSubclass.java
../openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/meta/ArrayMember.java
../openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/meta/Embed0.java
../openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/meta/Embed1.java
../openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/meta/ExplicitFieldAccess.java
../openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/meta/ExplicitFieldAccessMixed.java
../openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/meta/ExplicitPropertyAccess.java
../openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/meta/ExplicitPropertyAccessMixed.java
../openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/meta/ImplicitFieldAccessBase.java
../openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/meta/ImplicitFieldAccessMappedSuperclass.java
../openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/meta/ImplicitFieldAccessSubclass.java

View File

@ -35,7 +35,6 @@
@rem ---------------------------------------------------------------------------
@echo off
setlocal
set JAVA_HOME=c:\java\jdk1.6.0_10
set JAVAC=%JAVA_HOME%\bin\javac
set M_REPO="C:\Documents and Settings\Administrator\.m2\repository"
@ -44,11 +43,11 @@ set VERSION=1.0-EA9-SNAPSHOT
set JPA_LIB=%M_REPO%\org\apache\geronimo\specs\%SPEC%\%VERSION%\%SPEC%-%VERSION%.jar
set CLASSPATH=%JPA_LIB%
set CLASSPATH=%CLASSPATH%;.\openjpa-lib\target\classes
set CLASSPATH=%CLASSPATH%;.\openjpa-persistence\src\main\resources
set CLASSPATH=%CLASSPATH%;.\openjpa-persistence\target\classes
set CLASSPATH=%CLASSPATH%;.\openjpa-kernel\target\classes
set CLASSPATH=%CLASSPATH%;..\openjpa\src\main\resources
set CLASSPATH=%CLASSPATH%;..\openjpa\target\classes
echo Using Java Compiler %JAVAC%
%JAVAC% -version
%JAVAC% -cp %CLASSPATH% @%1 @%2
endlocal

View File

@ -1,4 +1,3 @@
-processor org.apache.openjpa.persistence.meta.AnnotationProcessor6
-Aopenjpa.generate=true
-Alog=TRACE
-Aout=..\openjpa-persistence-jdbc\src\test\java\
-Asource=5