From f0fb49b47c9a9b1f9fbfcee3f35a074a8842fd17 Mon Sep 17 00:00:00 2001 From: Pinaki Poddar Date: Thu, 7 May 2009 00:21:36 +0000 Subject: [PATCH] Implicit field/property access + refactor logging git-svn-id: https://svn.apache.org/repos/asf/openjpa/trunk@772476 13f79535-47bb-0310-9956-ffa450edef68 --- .../meta/AnnotationProcessor6.java | 33 +++++--- .../persistence/meta/CompileTimeLogger.java | 76 +++++++++++++++++++ .../meta/SourceAnnotationHandler.java | 75 ++++++++++-------- 3 files changed, 143 insertions(+), 41 deletions(-) create mode 100644 openjpa-persistence/src/main/java/org/apache/openjpa/persistence/meta/CompileTimeLogger.java diff --git a/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/meta/AnnotationProcessor6.java b/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/meta/AnnotationProcessor6.java index 2eea489b6..96f41c9c4 100644 --- a/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/meta/AnnotationProcessor6.java +++ b/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/meta/AnnotationProcessor6.java @@ -2,10 +2,12 @@ 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.util.Arrays; +import java.util.Collections; import java.util.Date; import java.util.List; import java.util.Set; @@ -24,7 +26,11 @@ import javax.lang.model.type.TypeMirror; import javax.lang.model.util.Elements; import javax.persistence.metamodel.TypesafeMetamodel; 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.persistence.util.SourceCode; @@ -59,12 +65,12 @@ import org.apache.openjpa.persistence.util.SourceCode; "javax.persistence.Entity", "javax.persistence.Embeddable", "javax.persistence.MappedSuperclass" }) -@SupportedOptions( { "log" }) +@SupportedOptions( { "log", "out" }) @SupportedSourceVersion(RELEASE_6) public class AnnotationProcessor6 extends AbstractProcessor { private SourceAnnotationHandler handler; - + private CompileTimeLogger logger; private static Localizer _loc = Localizer.forPackage(AnnotationProcessor6.class); private static final String UNDERSCORE = "_"; @@ -143,6 +149,7 @@ public class AnnotationProcessor6 extends AbstractProcessor { super.init(processingEnv); processingEnv.getMessager().printMessage(Diagnostic.Kind.NOTE, _loc.get("mmg-tool-banner").getMessage()); + logger = new CompileTimeLogger(processingEnv); handler = new SourceAnnotationHandler(processingEnv); } @@ -248,17 +255,21 @@ public class AnnotationProcessor6 extends AbstractProcessor { private PrintWriter createSourceFile(String metaClass, TypeElement e) throws IOException { - Filer filer = processingEnv.getFiler(); - JavaFileObject javaFile = filer.createSourceFile(metaClass, e); - log(_loc.get("mmg-process", javaFile.toUri()).getMessage()); + JavaCompiler compiler = ToolProvider.getSystemJavaCompiler(); + StandardJavaFileManager mgr = compiler.getStandardFileManager(null, + null, null); + String srcOutput = processingEnv.getOptions().get("out"); + if (srcOutput != null) { + mgr.setLocation(StandardLocation.SOURCE_OUTPUT, + Collections.singletonList(new File(srcOutput))); + } + + JavaFileObject javaFile = mgr.getJavaFileForOutput( + StandardLocation.SOURCE_OUTPUT, + metaClass, JavaFileObject.Kind.SOURCE, null); + logger.info(_loc.get("mmg-process", javaFile.toUri()).getMessage()); OutputStream out = javaFile.openOutputStream(); PrintWriter writer = new PrintWriter(out); return writer; } - - private void log(String msg) { - if (!processingEnv.getOptions().containsKey("log")) - return; - processingEnv.getMessager().printMessage(Diagnostic.Kind.NOTE, msg); - } } diff --git a/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/meta/CompileTimeLogger.java b/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/meta/CompileTimeLogger.java new file mode 100644 index 000000000..ae59a744b --- /dev/null +++ b/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/meta/CompileTimeLogger.java @@ -0,0 +1,76 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.openjpa.persistence.meta; + +import javax.annotation.processing.Messager; +import javax.annotation.processing.ProcessingEnvironment; +import javax.tools.Diagnostic; + +/** + * Simple logger sets log level from javac compilers annotation processing + * options -Alog=TRACE|INFO|WARN|ERROR and uses the processing + * environment to determine the log output stream. + * + * @author Pinaki Poddar + * + */ +public class CompileTimeLogger { + private static enum Level {TRACE, INFO, WARN, ERROR}; + private int logLevel; + private Messager messager; + public CompileTimeLogger(ProcessingEnvironment env) { + String level = env.getOptions().get("log"); + if ("trace".equalsIgnoreCase(level)) + logLevel = Level.TRACE.ordinal(); + else if ("info".equalsIgnoreCase(level)) + logLevel = Level.INFO.ordinal(); + else if ("warn".equalsIgnoreCase(level)) + logLevel = Level.WARN.ordinal(); + else if ("error".equalsIgnoreCase(level)) + logLevel = Level.ERROR.ordinal(); + else { + logLevel = Level.INFO.ordinal(); + warn("mmg-bad-log"); + } + messager = env.getMessager(); + + } + + public void info(String message) { + log(Level.INFO, message, Diagnostic.Kind.NOTE); + } + + public void trace(String message) { + log(Level.TRACE, message, Diagnostic.Kind.NOTE); + } + + public void warn(String message) { + log(Level.WARN, message, Diagnostic.Kind.MANDATORY_WARNING); + } + + public void error(String message) { + log(Level.ERROR, message, Diagnostic.Kind.ERROR); + } + + private void log(Level level, String message, Diagnostic.Kind kind) { + if (logLevel <= level.ordinal()) { + messager.printMessage(kind, message); + } + } +} diff --git a/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/meta/SourceAnnotationHandler.java b/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/meta/SourceAnnotationHandler.java index 7fdea978a..711b70520 100644 --- a/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/meta/SourceAnnotationHandler.java +++ b/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/meta/SourceAnnotationHandler.java @@ -49,8 +49,8 @@ import javax.persistence.Embeddable; import javax.persistence.Entity; import javax.persistence.MappedSuperclass; import javax.persistence.Transient; -import javax.tools.Diagnostic; import org.apache.openjpa.lib.util.Localizer; +import org.apache.openjpa.meta.AccessCode; import org.apache.openjpa.util.UserException; /** @@ -65,7 +65,7 @@ public class SourceAnnotationHandler implements MetadataProcessor { private final ProcessingEnvironment processingEnv; - + private final CompileTimeLogger logger; /** * Set of Inclusion Filters based on member type, access type or transient * annotations. Used to determine the subset of available field/method that @@ -91,10 +91,16 @@ public class SourceAnnotationHandler public SourceAnnotationHandler(ProcessingEnvironment processingEnv) { super(); this.processingEnv = processingEnv; + this.logger = new CompileTimeLogger(processingEnv); } - public int determineTypeAccess(TypeElement t) { - return 0; + public int determineTypeAccess(TypeElement type) { + AccessType access = getExplicitAccessType(type); + boolean isExplicit = access != null; + return isExplicit ? access == AccessType.FIELD + ? AccessCode.EXPLICIT | AccessCode.FIELD + : AccessCode.EXPLICIT | AccessCode.PROPERTY + : getImplicitAccessType(type); } public int determineMemberAccess(Element m) { @@ -116,13 +122,13 @@ public class SourceAnnotationHandler */ public Set getPersistentMembers(TypeElement type) { - AccessType access = getExplicitAccessType(type); - boolean isExplicit = access != null; - - return isExplicit ? access == AccessType.FIELD - ? getFieldAccessPersistentMembers(type) - : getPropertyAccessPersistentMembers(type) - : getDefaultAccessPersistentMembers(type); + int access = determineTypeAccess(type); + if (AccessCode.isExplicit(access)) { + return AccessCode.isField(access) + ? getFieldAccessPersistentMembers(type) + : getPropertyAccessPersistentMembers(type); + } + return getDefaultAccessPersistentMembers(type, access); } /** @@ -159,8 +165,26 @@ public class SourceAnnotationHandler fieldAccessFilter), getters); } - private Set getDefaultAccessPersistentMembers(TypeElement type) { + private Set getDefaultAccessPersistentMembers(TypeElement type, + int access) { Set result = new HashSet(); + List allMembers = type.getEnclosedElements(); + if (AccessCode.isField(access)) { + Set allFields = (Set) + filter(allMembers, fieldFilter, nonTransientFilter); + result.addAll(allFields); + } else { + Set allMethods = (Set) + filter(allMembers, methodFilter, nonTransientFilter); + Set getters = filter(allMethods, getterFilter); + Set setters = filter(allMethods, setterFilter); + getters = matchGetterAndSetter(getters, setters); + result.addAll(getters); + } + return result; + } + + private int getImplicitAccessType(TypeElement type) { List allMembers = type.getEnclosedElements(); Set allFields = (Set) filter(allMembers, fieldFilter, nonTransientFilter); @@ -168,9 +192,9 @@ public class SourceAnnotationHandler filter(allMembers, methodFilter, nonTransientFilter); Set annotatedFields = filter(allFields, - annotatedFilter); + annotatedFilter); Set getters = filter(allMethods, getterFilter, - annotatedFilter); + annotatedFilter); Set setters = filter(allMethods, setterFilter); getters = matchGetterAndSetter(getters, setters); @@ -180,15 +204,16 @@ public class SourceAnnotationHandler if (isFieldAccess && isPropertyAccess) { throw new UserException(_loc.get("access-mixed", type, toString(annotatedFields), toString(getters))); - } + } if (isFieldAccess) { - result.addAll(annotatedFields); + return AccessCode.FIELD; } else if (isPropertyAccess) { - result.addAll(getters); + return AccessCode.PROPERTY; } else { - warn(_loc.get("access-none", type).toString()); + TypeElement superType = getPersistentSupertype(type); + return (superType == null) + ? AccessCode.FIELD : determineTypeAccess(superType); } - return result; } Set merge(Set a, Set b) { @@ -236,7 +261,7 @@ public class SourceAnnotationHandler break; } if (!matched) { - warn(_loc.get("getter-unmatched", getter, + logger.warn(_loc.get("getter-unmatched", getter, getter.getEnclosingElement()).toString()); unmatched.add(getter); } @@ -424,16 +449,6 @@ public class SourceAnnotationHandler .append(mirror.toString()).toString(); } - private void log(String msg) { - if (!processingEnv.getOptions().containsKey("log")) - return; - processingEnv.getMessager().printMessage(Diagnostic.Kind.NOTE, msg); - } - - private void warn(String msg) { - processingEnv.getMessager().printMessage(Diagnostic.Kind.WARNING, msg); - } - String getPersistentMemberName(Element e) { return isMethod(e) ? extractFieldName((ExecutableElement)e) : e.getSimpleName().toString();