diff --git a/processor/src/main/java/org/mapstruct/ap/MappingProcessor.java b/processor/src/main/java/org/mapstruct/ap/MappingProcessor.java index 09002a382..4938bd804 100644 --- a/processor/src/main/java/org/mapstruct/ap/MappingProcessor.java +++ b/processor/src/main/java/org/mapstruct/ap/MappingProcessor.java @@ -83,6 +83,7 @@ import org.mapstruct.ap.util.AnnotationProcessingException; @SupportedAnnotationTypes("org.mapstruct.Mapper") @SupportedOptions({ MappingProcessor.SUPPRESS_GENERATOR_TIMESTAMP, + MappingProcessor.SUPPRESS_GENERATOR_VERSION_INFO_COMMENT, MappingProcessor.UNMAPPED_TARGET_POLICY, MappingProcessor.DEFAULT_COMPONENT_MODEL }) @@ -94,6 +95,8 @@ public class MappingProcessor extends AbstractProcessor { private static final boolean ANNOTATIONS_CLAIMED_EXCLUSIVELY = false; protected static final String SUPPRESS_GENERATOR_TIMESTAMP = "mapstruct.suppressGeneratorTimestamp"; + protected static final String SUPPRESS_GENERATOR_VERSION_INFO_COMMENT = + "mapstruct.suppressGeneratorVersionInfoComment"; protected static final String UNMAPPED_TARGET_POLICY = "mapstruct.unmappedTargetPolicy"; protected static final String DEFAULT_COMPONENT_MODEL = "mapstruct.defaultComponentModel"; @@ -111,6 +114,7 @@ public class MappingProcessor extends AbstractProcessor { return new Options( Boolean.valueOf( processingEnv.getOptions().get( SUPPRESS_GENERATOR_TIMESTAMP ) ), + Boolean.valueOf( processingEnv.getOptions().get( SUPPRESS_GENERATOR_VERSION_INFO_COMMENT ) ), unmappedTargetPolicy != null ? ReportingPolicy.valueOf( unmappedTargetPolicy ) : null, processingEnv.getOptions().get( DEFAULT_COMPONENT_MODEL ) ); diff --git a/processor/src/main/java/org/mapstruct/ap/model/Decorator.java b/processor/src/main/java/org/mapstruct/ap/model/Decorator.java index 42caa9982..4671c2e96 100644 --- a/processor/src/main/java/org/mapstruct/ap/model/Decorator.java +++ b/processor/src/main/java/org/mapstruct/ap/model/Decorator.java @@ -21,14 +21,18 @@ package org.mapstruct.ap.model; import java.util.Arrays; import java.util.List; import java.util.TreeSet; + import javax.lang.model.element.ElementKind; import javax.lang.model.element.TypeElement; import javax.lang.model.util.Elements; + import org.mapstruct.ap.model.common.Accessibility; import org.mapstruct.ap.model.common.ModelElement; import org.mapstruct.ap.model.common.Type; import org.mapstruct.ap.model.common.TypeFactory; +import org.mapstruct.ap.option.Options; import org.mapstruct.ap.prism.DecoratedWithPrism; +import org.mapstruct.ap.version.VersionInformation; /** * Represents a decorator applied to a generated mapper type. @@ -41,7 +45,7 @@ public class Decorator extends GeneratedType { private Decorator(TypeFactory typeFactory, String packageName, String name, String superClassName, String interfaceName, List methods, List fields, - boolean suppressGeneratorTimestamp, Accessibility accessibility ) { + Options options, VersionInformation versionInformation, Accessibility accessibility) { super( typeFactory, packageName, @@ -50,7 +54,8 @@ public class Decorator extends GeneratedType { interfaceName, methods, fields, - suppressGeneratorTimestamp, + options, + versionInformation, accessibility, new TreeSet() ); @@ -58,8 +63,8 @@ public class Decorator extends GeneratedType { public static Decorator getInstance(Elements elementUtils, TypeFactory typeFactory, TypeElement mapperElement, DecoratedWithPrism decoratorPrism, List methods, - boolean hasDelegateConstructor, - boolean suppressGeneratorTimestamp) { + boolean hasDelegateConstructor, Options options, + VersionInformation versionInformation) { Type decoratorType = typeFactory.getType( decoratorPrism.value() ); return new Decorator( @@ -77,7 +82,8 @@ public class Decorator extends GeneratedType { hasDelegateConstructor ) ), - suppressGeneratorTimestamp, + options, + versionInformation, Accessibility.fromModifiers( mapperElement.getModifiers() ) ); } diff --git a/processor/src/main/java/org/mapstruct/ap/model/GeneratedType.java b/processor/src/main/java/org/mapstruct/ap/model/GeneratedType.java index 766cf7725..d6d896bbd 100644 --- a/processor/src/main/java/org/mapstruct/ap/model/GeneratedType.java +++ b/processor/src/main/java/org/mapstruct/ap/model/GeneratedType.java @@ -18,21 +18,20 @@ */ package org.mapstruct.ap.model; -import java.io.IOException; -import java.net.URL; import java.util.ArrayList; import java.util.Collection; -import java.util.Enumeration; import java.util.List; import java.util.SortedSet; import java.util.TreeSet; -import java.util.jar.Manifest; + import javax.annotation.Generated; import org.mapstruct.ap.model.common.Accessibility; import org.mapstruct.ap.model.common.ModelElement; import org.mapstruct.ap.model.common.Type; import org.mapstruct.ap.model.common.TypeFactory; +import org.mapstruct.ap.option.Options; +import org.mapstruct.ap.version.VersionInformation; /** * A type generated by MapStruct, e.g. representing a mapper type. @@ -41,9 +40,6 @@ import org.mapstruct.ap.model.common.TypeFactory; */ public abstract class GeneratedType extends ModelElement { - private static final String COMMENT_TAG = "Implementation-Version"; - private static final String COMMENTS = initComment(); - private final String packageName; private final String name; private final String superClassName; @@ -55,6 +51,8 @@ public abstract class GeneratedType extends ModelElement { private final SortedSet extraImportedTypes; private final boolean suppressGeneratorTimestamp; + private final boolean suppressGeneratorVersionComment; + private final VersionInformation versionInformation; private final Accessibility accessibility; /** @@ -62,11 +60,13 @@ public abstract class GeneratedType extends ModelElement { */ private final Type generatedType; + // CHECKSTYLE:OFF protected GeneratedType(TypeFactory typeFactory, String packageName, String name, String superClassName, String interfaceName, List methods, List fields, - boolean suppressGeneratorTimestamp, + Options options, + VersionInformation versionInformation, Accessibility accessibility, SortedSet extraImportedTypes) { this.packageName = packageName; @@ -79,12 +79,16 @@ public abstract class GeneratedType extends ModelElement { this.methods = methods; this.fields = fields; - this.suppressGeneratorTimestamp = suppressGeneratorTimestamp; + this.suppressGeneratorTimestamp = options.isSuppressGeneratorTimestamp(); + this.suppressGeneratorVersionComment = options.isSuppressGeneratorVersionComment(); + this.versionInformation = versionInformation; this.accessibility = accessibility; this.generatedType = typeFactory.getType( Generated.class ); } + // CHECKSTYLE:ON + public String getPackageName() { return packageName; } @@ -121,12 +125,16 @@ public abstract class GeneratedType extends ModelElement { return suppressGeneratorTimestamp; } - public Accessibility getAccessibility() { - return accessibility; + public boolean isSuppressGeneratorVersionComment() { + return suppressGeneratorVersionComment; } - public String getComments() { - return COMMENTS; + public VersionInformation getVersionInformation() { + return versionInformation; + } + + public Accessibility getAccessibility() { + return accessibility; } @Override @@ -179,23 +187,4 @@ public abstract class GeneratedType extends ModelElement { addWithDependents( collection, type ); } } - - private static String initComment() { - String result = null; - try { - Enumeration resources = GeneratedType.class.getClassLoader().getResources( "META-INF/MANIFEST.MF" ); - while ( resources.hasMoreElements() ) { - Manifest manifest = new Manifest( resources.nextElement().openStream() ); - String resultValue = manifest.getMainAttributes().getValue( COMMENT_TAG ); - if (resultValue != null ) { - result = COMMENT_TAG + ": " + resultValue; - break; - } - } - } - catch ( IOException ex ) { - return result; - } - return result; - } } diff --git a/processor/src/main/java/org/mapstruct/ap/model/Mapper.java b/processor/src/main/java/org/mapstruct/ap/model/Mapper.java index 59241f092..a898849f0 100644 --- a/processor/src/main/java/org/mapstruct/ap/model/Mapper.java +++ b/processor/src/main/java/org/mapstruct/ap/model/Mapper.java @@ -20,12 +20,16 @@ package org.mapstruct.ap.model; import java.util.List; import java.util.SortedSet; + import javax.lang.model.element.ElementKind; import javax.lang.model.element.TypeElement; import javax.lang.model.util.Elements; + import org.mapstruct.ap.model.common.Accessibility; import org.mapstruct.ap.model.common.Type; import org.mapstruct.ap.model.common.TypeFactory; +import org.mapstruct.ap.option.Options; +import org.mapstruct.ap.version.VersionInformation; /** * Represents a type implementing a mapper interface (annotated with {@code @Mapper}). This is the root object of the @@ -41,10 +45,11 @@ public class Mapper extends GeneratedType { private final List referencedMappers; private final Decorator decorator; - //CHECKSTYLE:OFF + @SuppressWarnings( "checkstyle:parameternumber" ) private Mapper(TypeFactory typeFactory, String packageName, String name, String superClassName, - String interfaceName, List methods, boolean suppressGeneratorTimestamp, - Accessibility accessibility, List referencedMappers, Decorator decorator, + String interfaceName, List methods, Options options, + VersionInformation versionInformation, Accessibility accessibility, + List referencedMappers, Decorator decorator, SortedSet extraImportedTypes ) { super( @@ -55,7 +60,8 @@ public class Mapper extends GeneratedType { interfaceName, methods, referencedMappers, - suppressGeneratorTimestamp, + options, + versionInformation, accessibility, extraImportedTypes ); @@ -73,7 +79,8 @@ public class Mapper extends GeneratedType { private SortedSet extraImportedTypes; private Elements elementUtils; - private boolean suppressGeneratorTimestamp; + private Options options; + private VersionInformation versionInformation; private Decorator decorator; public Builder element(TypeElement element) { @@ -91,8 +98,13 @@ public class Mapper extends GeneratedType { return this; } - public Builder suppressGeneratorTimestamp(boolean suppressGeneratorTimestamp) { - this.suppressGeneratorTimestamp = suppressGeneratorTimestamp; + public Builder options(Options options) { + this.options = options; + return this; + } + + public Builder versionInformation(VersionInformation versionInformation) { + this.versionInformation = versionInformation; return this; } @@ -127,7 +139,8 @@ public class Mapper extends GeneratedType { element.getKind() != ElementKind.INTERFACE ? element.getSimpleName().toString() : null, element.getKind() == ElementKind.INTERFACE ? element.getSimpleName().toString() : null, mappingMethods, - suppressGeneratorTimestamp, + options, + versionInformation, Accessibility.fromModifiers( element.getModifiers() ), mapperReferences, decorator, diff --git a/processor/src/main/java/org/mapstruct/ap/option/Options.java b/processor/src/main/java/org/mapstruct/ap/option/Options.java index 82401cdcc..10087b54a 100644 --- a/processor/src/main/java/org/mapstruct/ap/option/Options.java +++ b/processor/src/main/java/org/mapstruct/ap/option/Options.java @@ -27,12 +27,15 @@ package org.mapstruct.ap.option; */ public class Options { private final boolean suppressGeneratorTimestamp; + private final boolean suppressGeneratorVersionComment; private final ReportingPolicy unmappedTargetPolicy; private final String defaultComponentModel; - public Options(boolean suppressGeneratorTimestamp, ReportingPolicy unmappedTargetPolicy, + public Options(boolean suppressGeneratorTimestamp, boolean suppressGeneratorVersionComment, + ReportingPolicy unmappedTargetPolicy, String defaultComponentModel) { this.suppressGeneratorTimestamp = suppressGeneratorTimestamp; + this.suppressGeneratorVersionComment = suppressGeneratorVersionComment; this.unmappedTargetPolicy = unmappedTargetPolicy; this.defaultComponentModel = defaultComponentModel; } @@ -41,6 +44,10 @@ public class Options { return suppressGeneratorTimestamp; } + public boolean isSuppressGeneratorVersionComment() { + return suppressGeneratorVersionComment; + } + public ReportingPolicy getUnmappedTargetPolicy() { return unmappedTargetPolicy; } diff --git a/processor/src/main/java/org/mapstruct/ap/processor/DefaultModelElementProcessorContext.java b/processor/src/main/java/org/mapstruct/ap/processor/DefaultModelElementProcessorContext.java index abdc7858c..0523344fa 100644 --- a/processor/src/main/java/org/mapstruct/ap/processor/DefaultModelElementProcessorContext.java +++ b/processor/src/main/java/org/mapstruct/ap/processor/DefaultModelElementProcessorContext.java @@ -30,18 +30,21 @@ import javax.tools.Diagnostic.Kind; import org.mapstruct.ap.model.common.TypeFactory; import org.mapstruct.ap.option.Options; +import org.mapstruct.ap.processor.ModelElementProcessor.ProcessorContext; +import org.mapstruct.ap.version.VersionInformation; /** * Default implementation of the processor context. * * @author Gunnar Morling */ -public class DefaultModelElementProcessorContext implements ModelElementProcessor.ProcessorContext { +public class DefaultModelElementProcessorContext implements ProcessorContext { private final ProcessingEnvironment processingEnvironment; private final DelegatingMessager messager; private final Options options; private final TypeFactory typeFactory; + private final VersionInformation versionInformation; public DefaultModelElementProcessorContext(ProcessingEnvironment processingEnvironment, Options options) { this.processingEnvironment = processingEnvironment; @@ -51,6 +54,7 @@ public class DefaultModelElementProcessorContext implements ModelElementProcesso processingEnvironment.getTypeUtils() ); this.options = options; + this.versionInformation = DefaultVersionInformation.fromProcessingEnvironment( processingEnvironment ); } @Override @@ -83,6 +87,11 @@ public class DefaultModelElementProcessorContext implements ModelElementProcesso return options; } + @Override + public VersionInformation getVersionInformation() { + return versionInformation; + } + @Override public boolean isErroneous() { return messager.isErroneous(); diff --git a/processor/src/main/java/org/mapstruct/ap/processor/DefaultVersionInformation.java b/processor/src/main/java/org/mapstruct/ap/processor/DefaultVersionInformation.java new file mode 100644 index 000000000..8ef26e8cf --- /dev/null +++ b/processor/src/main/java/org/mapstruct/ap/processor/DefaultVersionInformation.java @@ -0,0 +1,199 @@ +/** + * Copyright 2012-2015 Gunnar Morling (http://www.gunnarmorling.de/) + * and/or other contributors as indicated by the @authors tag. See the + * copyright.txt file in the distribution for a full listing of all + * 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. + */ +package org.mapstruct.ap.processor; + +import java.io.IOException; +import java.net.MalformedURLException; +import java.net.URL; +import java.util.jar.Manifest; + +import javax.annotation.processing.ProcessingEnvironment; + +import org.mapstruct.ap.version.VersionInformation; + +/** + * Provides information about the processor version and the processor context implementation version. + *

+ * Separated into an interface and this implementation to avoid cyclic dependencies between the processor package and + * the model package. + * + * @author Andreas Gudian + */ +public class DefaultVersionInformation implements VersionInformation { + private static final String JAVAC_PE_CLASS = "com.sun.tools.javac.processing.JavacProcessingEnvironment"; + private static final String JDT_IDE_PE_CLASS = + "org.eclipse.jdt.internal.apt.pluggable.core.dispatch.IdeBuildProcessingEnvImpl"; + private static final String JDT_BATCH_PE_CLASS = + "org.eclipse.jdt.internal.compiler.apt.dispatch.BatchProcessingEnvImpl"; + + private static final String MAP_STRUCT_VERSION = initMapStructVersion(); + + private final String runtimeVersion; + private final String runtimeVendor; + private final String compiler; + + DefaultVersionInformation(String runtimeVersion, String runtimeVendor, String compiler) { + this.runtimeVersion = runtimeVersion; + this.runtimeVendor = runtimeVendor; + this.compiler = compiler; + } + + @Override + public String getRuntimeVersion() { + return this.runtimeVersion; + } + + @Override + public String getRuntimeVendor() { + return this.runtimeVendor; + } + + @Override + public String getMapStructVersion() { + return MAP_STRUCT_VERSION; + } + + @Override + public String getCompiler() { + return this.compiler; + } + + static DefaultVersionInformation fromProcessingEnvironment(ProcessingEnvironment processingEnv) { + String runtimeVersion = System.getProperty( "java.version" ); + String runtimeVendor = System.getProperty( "java.vendor" ); + + String compiler = getCompiler( processingEnv ); + + return new DefaultVersionInformation( runtimeVersion, runtimeVendor, compiler ); + } + + private static String getCompiler(ProcessingEnvironment processingEnv) { + String className = processingEnv.getClass().getName(); + + if ( className.equals( JAVAC_PE_CLASS ) ) { + return "javac"; + } + + if ( className.equals( JDT_IDE_PE_CLASS ) ) { + // the processing environment for the IDE integrated APT is in a different bundle than the APT classes + return "Eclipse JDT (IDE) " + getLibraryName( processingEnv.getTypeUtils().getClass(), true ); + } + + if ( className.equals( JDT_BATCH_PE_CLASS ) ) { + return "Eclipse JDT (Batch) " + getLibraryName( processingEnv.getClass(), true ); + } + + return processingEnv.getClass().getSimpleName() + " from " + getLibraryName( processingEnv.getClass(), false ); + } + + private static String getLibraryName(Class clazz, boolean preferVersionOnly) { + String classFileName = asClassFileName( clazz.getName() ); + URL resource = clazz.getClassLoader().getResource( classFileName ); + + Manifest manifest = openManifest( classFileName, resource ); + if ( preferVersionOnly && manifest != null ) { + String version = manifest.getMainAttributes().getValue( "Bundle-Version" ); + + if ( version != null ) { + return version; + } + } + + if ( "jar".equals( resource.getProtocol() ) ) { + return extractJarFileName( resource.getFile() ); + } + else if ( "jrt".equals( resource.getProtocol() ) ) { + return extractJrtModuleName( resource ); + } + else if ( "bundleresource".equals( resource.getProtocol() ) && manifest != null ) { + return extractBundleName( manifest ); + } + + return resource.toExternalForm(); + } + + private static Manifest openManifest(String classFileName, URL resource) { + try { + URL manifestUrl = createManifestUrl( classFileName, resource ); + return new Manifest( manifestUrl.openStream() ); + } + catch ( IOException e ) { + return null; + } + } + + private static String extractBundleName(Manifest manifest) { + String version = manifest.getMainAttributes().getValue( "Bundle-Version" ); + String symbolicName = manifest.getMainAttributes().getValue( "Bundle-SymbolicName" ); + int semicolon = symbolicName.indexOf( ';' ); + if ( semicolon > 0 ) { + symbolicName = symbolicName.substring( 0, semicolon ); + } + + return symbolicName + "_" + version; + } + + private static String extractJrtModuleName(URL resource) { + // JDK 9 style, e.g. jrt:/jdk.compiler/com/sun/tools/javac/processing/JavacProcessingEnvironment.class + int moduleNameSeparator = resource.getFile().indexOf( '/', 1 ); + if ( moduleNameSeparator > 1 ) { + return resource.getFile().substring( 1, moduleNameSeparator ); + } + return resource.toExternalForm(); + } + + private static URL createManifestUrl(String classFileName, URL resource) throws MalformedURLException { + String classUrlString = resource.toExternalForm(); + String baseFileUrl = classUrlString.substring( 0, classUrlString.length() - classFileName.length() ); + return new URL( baseFileUrl + "META-INF/MANIFEST.MF" ); + } + + private static String asClassFileName(String className) { + return className.replace( '.', '/' ) + ".class"; + } + + private static String extractJarFileName(String file) { + int excl = file.indexOf( '!' ); + + if ( excl > 0 ) { + String fullFileName = file.substring( 0, excl ); + // it's an URL, so it's not the system path separator char: + int lastPathSep = fullFileName.lastIndexOf( '/' ); + if ( lastPathSep > 0 && lastPathSep < fullFileName.length() ) { + return fullFileName.substring( lastPathSep + 1 ); + } + } + + return file; + } + + private static String initMapStructVersion() { + String classFileName = asClassFileName( DefaultVersionInformation.class.getName() ); + URL resource = DefaultVersionInformation.class.getClassLoader().getResource( classFileName ); + Manifest manifest = openManifest( classFileName, resource ); + + if ( null != manifest ) { + String version = manifest.getMainAttributes().getValue( "Implementation-Version" ); + if ( version != null ) { + return version; + } + } + return ""; + } +} diff --git a/processor/src/main/java/org/mapstruct/ap/processor/MapperCreationProcessor.java b/processor/src/main/java/org/mapstruct/ap/processor/MapperCreationProcessor.java index 1d814abbe..faad6ad4b 100644 --- a/processor/src/main/java/org/mapstruct/ap/processor/MapperCreationProcessor.java +++ b/processor/src/main/java/org/mapstruct/ap/processor/MapperCreationProcessor.java @@ -23,6 +23,7 @@ import java.util.LinkedList; import java.util.List; import java.util.SortedSet; import java.util.TreeSet; + import javax.annotation.processing.Messager; import javax.lang.model.element.ExecutableElement; import javax.lang.model.element.TypeElement; @@ -56,6 +57,7 @@ import org.mapstruct.ap.prism.MapperPrism; import org.mapstruct.ap.processor.creation.MappingResolverImpl; import org.mapstruct.ap.util.MapperConfig; import org.mapstruct.ap.util.Strings; +import org.mapstruct.ap.version.VersionInformation; /** * A {@link ModelElementProcessor} which creates a {@link Mapper} from the given @@ -69,6 +71,7 @@ public class MapperCreationProcessor implements ModelElementProcessor mapperReferences = initReferencedMappers( mapperTypeElement ); @@ -140,7 +144,8 @@ public class MapperCreationProcessor implements ModelElementProcessor { Options getOptions(); + VersionInformation getVersionInformation(); + /** * Whether the currently processed mapper type is erroneous which is the * case if at least one diagnostic with {@link Kind#ERROR} is reported diff --git a/processor/src/main/java/org/mapstruct/ap/version/VersionInformation.java b/processor/src/main/java/org/mapstruct/ap/version/VersionInformation.java new file mode 100644 index 000000000..edc77c781 --- /dev/null +++ b/processor/src/main/java/org/mapstruct/ap/version/VersionInformation.java @@ -0,0 +1,31 @@ +/** + * Copyright 2012-2015 Gunnar Morling (http://www.gunnarmorling.de/) + * and/or other contributors as indicated by the @authors tag. See the + * copyright.txt file in the distribution for a full listing of all + * 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. + */ +package org.mapstruct.ap.version; + +/** + * Provides information about the processor version and the processor context implementation version + * + * @author Andreas Gudian + */ +public interface VersionInformation { + String getRuntimeVersion(); + String getRuntimeVendor(); + String getMapStructVersion(); + String getCompiler(); +} diff --git a/processor/src/main/java/org/mapstruct/ap/version/package-info.java b/processor/src/main/java/org/mapstruct/ap/version/package-info.java new file mode 100644 index 000000000..3c9dc94c8 --- /dev/null +++ b/processor/src/main/java/org/mapstruct/ap/version/package-info.java @@ -0,0 +1,24 @@ +/** + * Copyright 2012-2015 Gunnar Morling (http://www.gunnarmorling.de/) + * and/or other contributors as indicated by the @authors tag. See the + * copyright.txt file in the distribution for a full listing of all + * 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. + */ +/** + *

+ * Provides various version information + *

+ */ +package org.mapstruct.ap.version; diff --git a/processor/src/main/resources/org.mapstruct.ap.model.GeneratedType.ftl b/processor/src/main/resources/org.mapstruct.ap.model.GeneratedType.ftl index a3b384f08..d46306e85 100644 --- a/processor/src/main/resources/org.mapstruct.ap.model.GeneratedType.ftl +++ b/processor/src/main/resources/org.mapstruct.ap.model.GeneratedType.ftl @@ -26,8 +26,8 @@ import ${importedType.importName}; @Generated( value = "org.mapstruct.ap.MappingProcessor"<#if suppressGeneratorTimestamp == false>, - date = "${.now?string("yyyy-MM-dd'T'HH:mm:ssZ")}"<#if comments??>, - comments = "${comments}" + date = "${.now?string("yyyy-MM-dd'T'HH:mm:ssZ")}"<#if suppressGeneratorVersionComment == false>, + comments = "version: ${versionInformation.mapStructVersion}, compiler: ${versionInformation.compiler}, environment: Java ${versionInformation.runtimeVersion} (${versionInformation.runtimeVendor})" ) <#list annotations as annotation> <#nt><@includeModel object=annotation/> diff --git a/processor/src/test/java/org/mapstruct/ap/test/versioninfo/SimpleMapper.java b/processor/src/test/java/org/mapstruct/ap/test/versioninfo/SimpleMapper.java new file mode 100644 index 000000000..117ff6fa8 --- /dev/null +++ b/processor/src/test/java/org/mapstruct/ap/test/versioninfo/SimpleMapper.java @@ -0,0 +1,30 @@ +/** + * Copyright 2012-2015 Gunnar Morling (http://www.gunnarmorling.de/) + * and/or other contributors as indicated by the @authors tag. See the + * copyright.txt file in the distribution for a full listing of all + * 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. + */ +package org.mapstruct.ap.test.versioninfo; + +import org.mapstruct.Mapper; + +/** + * @author Andreas Gudian + * + */ +@Mapper +public interface SimpleMapper { + Object toObject(Object object); +} diff --git a/processor/src/test/java/org/mapstruct/ap/test/versioninfo/VersionInfoTest.java b/processor/src/test/java/org/mapstruct/ap/test/versioninfo/VersionInfoTest.java new file mode 100644 index 000000000..2832d00c4 --- /dev/null +++ b/processor/src/test/java/org/mapstruct/ap/test/versioninfo/VersionInfoTest.java @@ -0,0 +1,72 @@ +/** + * Copyright 2012-2015 Gunnar Morling (http://www.gunnarmorling.de/) + * and/or other contributors as indicated by the @authors tag. See the + * copyright.txt file in the distribution for a full listing of all + * 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. + */ +package org.mapstruct.ap.test.versioninfo; + +import org.junit.Rule; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mapstruct.ap.testutil.IssueKey; +import org.mapstruct.ap.testutil.WithClasses; +import org.mapstruct.ap.testutil.compilation.annotation.ProcessorOption; +import org.mapstruct.ap.testutil.compilation.annotation.ProcessorOptions; +import org.mapstruct.ap.testutil.runner.AnnotationProcessorTestRunner; +import org.mapstruct.ap.testutil.runner.GeneratedSource; + +/** + * @author Andreas Gudian + * + */ +@RunWith( AnnotationProcessorTestRunner.class ) +@IssueKey( "424" ) +@WithClasses( SimpleMapper.class ) +public class VersionInfoTest { + private final GeneratedSource generatedSource = new GeneratedSource(); + + @Rule + public GeneratedSource getGeneratedSource() { + return generatedSource; + } + + @Test + @ProcessorOption( name = "mapstruct.suppressGeneratorVersionInfoComment", value = "true" ) + public void includesNoComment() { + generatedSource.forMapper( SimpleMapper.class ).content() + .contains( "date = \"" ) + .doesNotContain( "comments = \"version: " ); + } + + @Test + @ProcessorOptions( { + @ProcessorOption( name = "mapstruct.suppressGeneratorVersionInfoComment", value = "true" ), + @ProcessorOption( name = "mapstruct.suppressGeneratorTimestamp", value = "true" ) + } ) + public void includesNoCommentAndNoTimestamp() { + generatedSource.forMapper( SimpleMapper.class ).content() + .doesNotContain( "date = \"" ) + .doesNotContain( "comments = \"version: " ); + } + + @Test + public void includesCommentAndTimestamp() { + generatedSource.forMapper( SimpleMapper.class ).content() + .contains( "date = \"" ) + .contains( "comments = \"version: " ); + } + +}