mirror of https://github.com/apache/openjpa.git
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:
parent
6759d41517
commit
f0fb49b47c
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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();
|
||||
|
|
Loading…
Reference in New Issue