Implicit field/property access + refactor logging

git-svn-id: https://svn.apache.org/repos/asf/openjpa/trunk@772476 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Pinaki Poddar 2009-05-07 00:21:36 +00:00
parent 6759d41517
commit f0fb49b47c
3 changed files with 143 additions and 41 deletions

View File

@ -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);
}
}

View File

@ -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 <code>-Alog=TRACE|INFO|WARN|ERROR</code> 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);
}
}
}

View File

@ -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<TypeElement, Element> {
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<Element> 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<Element> getDefaultAccessPersistentMembers(TypeElement type) {
private Set<Element> getDefaultAccessPersistentMembers(TypeElement type,
int access) {
Set<Element> result = new HashSet<Element>();
List<? extends Element> allMembers = type.getEnclosedElements();
if (AccessCode.isField(access)) {
Set<VariableElement> allFields = (Set<VariableElement>)
filter(allMembers, fieldFilter, nonTransientFilter);
result.addAll(allFields);
} else {
Set<ExecutableElement> allMethods = (Set<ExecutableElement>)
filter(allMembers, methodFilter, nonTransientFilter);
Set<ExecutableElement> getters = filter(allMethods, getterFilter);
Set<ExecutableElement> setters = filter(allMethods, setterFilter);
getters = matchGetterAndSetter(getters, setters);
result.addAll(getters);
}
return result;
}
private int getImplicitAccessType(TypeElement type) {
List<? extends Element> allMembers = type.getEnclosedElements();
Set<VariableElement> allFields = (Set<VariableElement>)
filter(allMembers, fieldFilter, nonTransientFilter);
@ -168,9 +192,9 @@ public class SourceAnnotationHandler
filter(allMembers, methodFilter, nonTransientFilter);
Set<VariableElement> annotatedFields = filter(allFields,
annotatedFilter);
annotatedFilter);
Set<ExecutableElement> getters = filter(allMethods, getterFilter,
annotatedFilter);
annotatedFilter);
Set<ExecutableElement> 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<Element> merge(Set<? extends Element> a, Set<? extends Element> 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();