diff --git a/tooling/metamodel-generator/src/main/docbook/en-US/master.xml b/tooling/metamodel-generator/src/main/docbook/en-US/master.xml index a84cbf0259..11e470eaaf 100644 --- a/tooling/metamodel-generator/src/main/docbook/en-US/master.xml +++ b/tooling/metamodel-generator/src/main/docbook/en-US/master.xml @@ -551,6 +551,17 @@ cq.where( cb.equal(itemNode.get(Item_.id), 5 ) ).distinct(true); ignore orm.xml and persistence.xml. + + + addGeneratedAnnotation + + if set to true the processor will + add the @Generated to the generated + Java source file. Per default this annotation is not + generated, because the code would not compile under JDK 5. If + you are using a JDK 6 you can force the generation of this + annotation using this flag. + diff --git a/tooling/metamodel-generator/src/main/java/org/hibernate/jpamodelgen/ClassWriter.java b/tooling/metamodel-generator/src/main/java/org/hibernate/jpamodelgen/ClassWriter.java index e9611f3ada..95fe22984a 100644 --- a/tooling/metamodel-generator/src/main/java/org/hibernate/jpamodelgen/ClassWriter.java +++ b/tooling/metamodel-generator/src/main/java/org/hibernate/jpamodelgen/ClassWriter.java @@ -24,6 +24,7 @@ import java.io.OutputStream; import java.io.PrintWriter; import java.io.StringWriter; import java.util.List; +import javax.annotation.Generated; import javax.annotation.processing.FilerException; import javax.lang.model.element.Element; import javax.lang.model.element.TypeElement; @@ -39,9 +40,9 @@ import org.hibernate.jpamodelgen.model.MetaEntity; /** * @author Emmanuel Bernard */ -public class ClassWriter { +public final class ClassWriter { - private ClassWriter(){ + private ClassWriter() { } public static void writeFile(MetaEntity entity, Context context) { @@ -91,8 +92,9 @@ public class ClassWriter { PrintWriter pw = null; try { pw = new PrintWriter( sw ); - // we cannot use add @Generated into the metamodel class since this would not work in a JDK 5 environment - //pw.println( "@" + entity.importType( Generated.class.getName() ) + "(\"JPA MetaModel for " + entity.getQualifiedName() + "\")" ); + if ( context.isAddGeneratedAnnotation() ) { + pw.println( "@" + entity.importType( Generated.class.getName() ) + "(\"JPA MetaModel for " + entity.getQualifiedName() + "\")" ); + } pw.println( "@" + entity.importType( "javax.persistence.metamodel.StaticMetamodel" ) + "(" + entity.getSimpleName() + ".class)" ); printClassDeclaration( entity, pw, context ); pw.println(); diff --git a/tooling/metamodel-generator/src/main/java/org/hibernate/jpamodelgen/Context.java b/tooling/metamodel-generator/src/main/java/org/hibernate/jpamodelgen/Context.java index ef02bf00ab..75d1fe5d10 100644 --- a/tooling/metamodel-generator/src/main/java/org/hibernate/jpamodelgen/Context.java +++ b/tooling/metamodel-generator/src/main/java/org/hibernate/jpamodelgen/Context.java @@ -60,9 +60,10 @@ public class Context { private final boolean logDebug; private final boolean lazyXmlParsing; private final String persistenceXmlLocation; - private final List ormXmlFiles; + private boolean isPersistenceUnitCompletelyXmlConfigured; + private boolean addGeneratedAnnotation; private AccessType persistenceUnitDefaultAccessType; public Context(ProcessingEnvironment pe) { @@ -101,6 +102,14 @@ public class Context { return pe; } + public boolean isAddGeneratedAnnotation() { + return addGeneratedAnnotation; + } + + public void setAddGeneratedAnnotation(boolean addGeneratedAnnotation) { + this.addGeneratedAnnotation = addGeneratedAnnotation; + } + public Elements getElementUtils() { return pe.getElementUtils(); } diff --git a/tooling/metamodel-generator/src/main/java/org/hibernate/jpamodelgen/JPAMetaModelEntityProcessor.java b/tooling/metamodel-generator/src/main/java/org/hibernate/jpamodelgen/JPAMetaModelEntityProcessor.java index 9c02bcb91a..cbb3363250 100644 --- a/tooling/metamodel-generator/src/main/java/org/hibernate/jpamodelgen/JPAMetaModelEntityProcessor.java +++ b/tooling/metamodel-generator/src/main/java/org/hibernate/jpamodelgen/JPAMetaModelEntityProcessor.java @@ -70,7 +70,8 @@ import static javax.lang.model.SourceVersion.RELEASE_6; JPAMetaModelEntityProcessor.PERSISTENCE_XML_OPTION, JPAMetaModelEntityProcessor.ORM_XML_OPTION, JPAMetaModelEntityProcessor.FULLY_ANNOTATION_CONFIGURED_OPTION, - JPAMetaModelEntityProcessor.LAZY_XML_PARSING + JPAMetaModelEntityProcessor.LAZY_XML_PARSING, + JPAMetaModelEntityProcessor.ADD_GENERATED_ANNOTATION }) public class JPAMetaModelEntityProcessor extends AbstractProcessor { public static final String DEBUG_OPTION = "debug"; @@ -78,6 +79,7 @@ public class JPAMetaModelEntityProcessor extends AbstractProcessor { public static final String ORM_XML_OPTION = "ormXmlList"; public static final String FULLY_ANNOTATION_CONFIGURED_OPTION = "fullyAnnotationConfigured"; public static final String LAZY_XML_PARSING = "lazyXmlParsing"; + public static final String ADD_GENERATED_ANNOTATION = "addGeneratedAnnotation"; private static final Boolean ALLOW_OTHER_PROCESSORS_TO_CLAIM_ANNOTATIONS = Boolean.FALSE; @@ -90,7 +92,11 @@ public class JPAMetaModelEntityProcessor extends AbstractProcessor { Diagnostic.Kind.NOTE, "Hibernate JPA 2 Static-Metamodel Generator " + Version.getVersionString() ); - String tmp = env.getOptions().get( JPAMetaModelEntityProcessor.FULLY_ANNOTATION_CONFIGURED_OPTION ); + String tmp = env.getOptions().get( JPAMetaModelEntityProcessor.ADD_GENERATED_ANNOTATION ); + boolean addGeneratedAnnotation = Boolean.parseBoolean( tmp ); + context.setAddGeneratedAnnotation( addGeneratedAnnotation ); + + tmp = env.getOptions().get( JPAMetaModelEntityProcessor.FULLY_ANNOTATION_CONFIGURED_OPTION ); boolean fullyAnnotationConfigured = Boolean.parseBoolean( tmp ); if ( !fullyAnnotationConfigured ) { diff --git a/tooling/metamodel-generator/src/test/java/org/hibernate/jpamodelgen/test/generatedannotation/GeneratedAnnotationTest.java b/tooling/metamodel-generator/src/test/java/org/hibernate/jpamodelgen/test/generatedannotation/GeneratedAnnotationTest.java new file mode 100644 index 0000000000..dda6061987 --- /dev/null +++ b/tooling/metamodel-generator/src/test/java/org/hibernate/jpamodelgen/test/generatedannotation/GeneratedAnnotationTest.java @@ -0,0 +1,48 @@ +/* + * JBoss, Home of Professional Open Source + * Copyright 2010, Red Hat Middleware LLC, and individual contributors + * by the @authors tag. See the copyright.txt in the distribution for a + * full listing of individual contributors. + * + * Licensed 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. + */ + +// $Id$ + +package org.hibernate.jpamodelgen.test.generatedannotation; + +import org.testng.annotations.Test; + +import org.hibernate.jpamodelgen.test.util.CompilationTest; + +import static org.hibernate.jpamodelgen.test.util.TestUtil.assertMetamodelClassGeneratedFor; +import static org.hibernate.jpamodelgen.test.util.TestUtil.getMetaModelSourceAsString; +import static org.testng.Assert.assertFalse; + +/** + * @author Hardy Ferentschik + */ +public class GeneratedAnnotationTest extends CompilationTest { + + @Test + public void testGeneratedAnnotationNotGenerated() { + assertMetamodelClassGeneratedFor( TestEntity.class ); + + // need to check the source because @Generated is not a runtime annotation + String metaModelSource = getMetaModelSourceAsString( TestEntity.class ); + assertFalse( metaModelSource.contains( "@Generated" ), "@Generated should not be added to the metamodel." ); + } + + @Override + protected String getPackageNameOfTestSources() { + return GeneratedAnnotationTest.class.getPackage().getName(); + } +} \ No newline at end of file diff --git a/tooling/metamodel-generator/src/test/java/org/hibernate/jpamodelgen/test/generatedannotation/GeneratedAnnotationTest2.java b/tooling/metamodel-generator/src/test/java/org/hibernate/jpamodelgen/test/generatedannotation/GeneratedAnnotationTest2.java new file mode 100644 index 0000000000..8dac48d90c --- /dev/null +++ b/tooling/metamodel-generator/src/test/java/org/hibernate/jpamodelgen/test/generatedannotation/GeneratedAnnotationTest2.java @@ -0,0 +1,62 @@ +/* + * JBoss, Home of Professional Open Source + * Copyright 2010, Red Hat Middleware LLC, and individual contributors + * by the @authors tag. See the copyright.txt in the distribution for a + * full listing of individual contributors. + * + * Licensed 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. + */ + +// $Id: GenericsTest.java 20721 2010-09-27 12:40:10Z hardy.ferentschik $ + +package org.hibernate.jpamodelgen.test.generatedannotation; + +import java.util.HashMap; +import java.util.Map; + +import org.testng.annotations.Test; + +import org.hibernate.jpamodelgen.JPAMetaModelEntityProcessor; +import org.hibernate.jpamodelgen.test.util.CompilationTest; + +import static org.hibernate.jpamodelgen.test.util.TestUtil.assertMetamodelClassGeneratedFor; +import static org.hibernate.jpamodelgen.test.util.TestUtil.getMetaModelSourceAsString; +import static org.testng.Assert.assertTrue; + +/** + * @author Hardy Ferentschik + */ +public class GeneratedAnnotationTest2 extends CompilationTest { + + @Test + public void testGeneratedAnnotationGenerated() { + assertMetamodelClassGeneratedFor( TestEntity.class ); + + // need to check the source because @Generated is not a runtime annotation + String metaModelSource = getMetaModelSourceAsString( TestEntity.class ); + assertTrue( metaModelSource.contains( "@Generated" ), "@Generated should be added to the metamodel." ); + } + + @Override + protected Map getProcessorOptions() { + Map properties = new HashMap(); + properties.put( + JPAMetaModelEntityProcessor.ADD_GENERATED_ANNOTATION, + "true" + ); + return properties; + } + + @Override + protected String getPackageNameOfTestSources() { + return GeneratedAnnotationTest2.class.getPackage().getName(); + } +} \ No newline at end of file diff --git a/tooling/metamodel-generator/src/test/java/org/hibernate/jpamodelgen/test/generatedannotation/TestEntity.java b/tooling/metamodel-generator/src/test/java/org/hibernate/jpamodelgen/test/generatedannotation/TestEntity.java new file mode 100644 index 0000000000..b9506cfd4b --- /dev/null +++ b/tooling/metamodel-generator/src/test/java/org/hibernate/jpamodelgen/test/generatedannotation/TestEntity.java @@ -0,0 +1,33 @@ +/* + * JBoss, Home of Professional Open Source + * Copyright 2010, Red Hat Middleware LLC, and individual contributors + * by the @authors tag. See the copyright.txt in the distribution for a + * full listing of individual contributors. + * + * Licensed 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. + */ + +// $Id:$ +package org.hibernate.jpamodelgen.test.generatedannotation; + +import javax.persistence.Entity; +import javax.persistence.Id; + +/** + * @author Hardy Ferentschik + */ +@Entity +public class TestEntity { + @Id + private long id; +} + + diff --git a/tooling/metamodel-generator/src/test/java/org/hibernate/jpamodelgen/test/util/TestUtil.java b/tooling/metamodel-generator/src/test/java/org/hibernate/jpamodelgen/test/util/TestUtil.java index 1a3018a38c..2ac9c05302 100644 --- a/tooling/metamodel-generator/src/test/java/org/hibernate/jpamodelgen/test/util/TestUtil.java +++ b/tooling/metamodel-generator/src/test/java/org/hibernate/jpamodelgen/test/util/TestUtil.java @@ -19,8 +19,11 @@ package org.hibernate.jpamodelgen.test.util; +import java.io.BufferedReader; import java.io.File; import java.io.FileFilter; +import java.io.FileReader; +import java.io.IOException; import java.lang.reflect.Field; import java.lang.reflect.GenericArrayType; import java.lang.reflect.ParameterizedType; @@ -76,6 +79,18 @@ public class TestUtil { } } + public static Class getMetamodelClassFor(Class entityClass) { + String entityModelClassName = entityClass.getName() + META_MODEL_CLASS_POSTFIX; + + try { + return Class.forName( entityModelClassName ); + } + catch ( ClassNotFoundException e ) { + fail( "Unable to load class " + entityModelClassName ); + return null; + } + } + /** * Asserts that a metamodel class for the specified class got generated. * @@ -92,14 +107,48 @@ public class TestUtil { } } - public static void assertNoSourceFileGeneratedFor(Class clazz) { - assertNotNull( clazz, "Class parameter cannot be null" ); + public static File getMetaModelSourceFileFor(Class clazz) { String metaModelClassName = clazz.getName() + META_MODEL_CLASS_POSTFIX; // generate the file name String fileName = metaModelClassName.replace( PACKAGE_SEPARATOR, PATH_SEPARATOR ); fileName = fileName.concat( ".java" ); - File sourceFile = new File( outBaseDir + PATH_SEPARATOR + fileName ); - assertFalse( sourceFile.exists(), "There should be no source file: " + fileName ); + return new File( outBaseDir + PATH_SEPARATOR + fileName ); + } + + public static String getMetaModelSourceAsString(Class clazz) { + File sourceFile = getMetaModelSourceFileFor( clazz ); + StringBuilder contents = new StringBuilder(); + + try { + BufferedReader input = new BufferedReader( new FileReader( sourceFile ) ); + try { + String line = null; //not declared within while loop + /* + * readLine is a bit quirky : + * it returns the content of a line MINUS the newline. + * it returns null only for the END of the stream. + * it returns an empty String if two newlines appear in a row. + */ + while ( ( line = input.readLine() ) != null ) { + contents.append( line ); + contents.append( System.getProperty( "line.separator" ) ); + } + } + finally { + input.close(); + } + } + catch ( IOException ex ) { + ex.printStackTrace(); + } + + return contents.toString(); + } + + public static void assertNoSourceFileGeneratedFor(Class clazz) { + assertNotNull( clazz, "Class parameter cannot be null" ); + File sourceFile = getMetaModelSourceFileFor( clazz ); + assertFalse( sourceFile.exists(), "There should be no source file: " + sourceFile.getName() ); } public static void assertAbsenceOfFieldInMetamodelFor(Class clazz, String fieldName) { @@ -165,14 +214,10 @@ public class TestUtil { } public static Field getFieldFromMetamodelFor(Class entityClass, String fieldName) { - String entityModelClassName = entityClass.getName() + META_MODEL_CLASS_POSTFIX; - Field field = null; + Class metaModelClass = getMetamodelClassFor( entityClass ); + Field field; try { - Class clazz = Class.forName( entityModelClassName ); - field = clazz.getField( fieldName ); - } - catch ( ClassNotFoundException e ) { - fail( "Unable to load class " + entityModelClassName ); + field = metaModelClass.getField( fieldName ); } catch ( NoSuchFieldException e ) { field = null;