Added groovy refactor experimentation
git-svn-id: https://svn.apache.org/repos/asf/maven/archetype/branches/archetype-refactor-groovy@757559 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/grarchetype-common/pom.xml b/grarchetype-common/pom.xml
new file mode 100644
index 0000000..4ff2115
--- /dev/null
+++ b/grarchetype-common/pom.xml
@@ -0,0 +1,295 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.apache.maven.grarchetype</groupId>
+ <artifactId>maven-grarchetype</artifactId>
+ <version>2.0-alpha-5-SNAPSHOT</version>
+ </parent>
+ <artifactId>grarchetype-common</artifactId>
+ <name>Maven GRArchetype Common</name>
+ <packaging>jar</packaging>
+ <dependencies>
+ <dependency>
+ <groupId>org.apache.maven</groupId>
+ <artifactId>maven-model</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.maven</groupId>
+ <artifactId>maven-project</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.maven</groupId>
+ <artifactId>maven-core</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.velocity</groupId>
+ <artifactId>velocity</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.codehaus.groovy</groupId>
+ <artifactId>groovy-all</artifactId>
+ <version>1.6.0</version>
+ <!--version>1.6-RC-2</version-->
+ </dependency>
+ <dependency>
+ <groupId>jdom</groupId>
+ <artifactId>jdom</artifactId>
+ <version>1.1</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.maven.shared</groupId>
+ <artifactId>maven-plugin-testing-harness</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.maven.wagon</groupId>
+ <artifactId>wagon-file</artifactId>
+ <version>1.0-beta-2</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.maven.wagon</groupId>
+ <artifactId>wagon-http</artifactId>
+ <version>1.0-beta-2</version><!-- with 1.0-beta-4 some tests fail -->
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.codehaus.cargo</groupId>
+ <artifactId>cargo-core-api-container</artifactId>
+ <version>1.0-alpha-6</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.codehaus.cargo</groupId>
+ <artifactId>cargo-core-api-util</artifactId>
+ <version>1.0-alpha-6</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.codehaus.cargo</groupId>
+ <artifactId>cargo-core-api-generic</artifactId>
+ <version>1.0-alpha-6</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.codehaus.cargo</groupId>
+ <artifactId>cargo-core-api-module</artifactId>
+ <version>1.0-alpha-6</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.codehaus.cargo</groupId>
+ <artifactId>cargo-core-container-jetty</artifactId>
+ <version>1.0-alpha-6</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.mortbay.jetty</groupId>
+ <artifactId>jetty</artifactId>
+ <version>6.1.11</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>${project.parent.groupId}</groupId>
+ <artifactId>grarchetype-repository</artifactId>
+ <version>${project.version}</version>
+ <type>war</type>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-surefire-plugin</artifactId>
+ <configuration>
+ <systemProperties>
+ <property>
+ <name>maven.home</name>
+ <value>${maven.home}</value>
+ </property>
+ </systemProperties>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.codehaus.modello</groupId>
+ <artifactId>modello-maven-plugin</artifactId>
+ <executions>
+ <execution>
+ <id>model</id>
+ <phase>generate-sources</phase>
+ <goals>
+ <goal>jdom-writer</goal>
+ </goals>
+ <configuration>
+ <model>src/main/mdo/maven.mdo</model>
+ <version>4.0.0</version>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <groupId>org.codehaus.groovy.maven</groupId>
+ <artifactId>gmaven-plugin</artifactId>
+ <version>1.0-rc-5</version>
+ <configuration>
+ <providerSelection>1.6</providerSelection>
+ <!--providerSelection>1.6</providerSelection-->
+ </configuration>
+ <executions>
+ <execution>
+ <id>generate-sources</id>
+ <phase>generate-sources</phase>
+ <goals>
+ <goal>generateStubs</goal>
+ </goals>
+ </execution>
+ <execution>
+ <id>compile</id>
+ <phase>compile</phase>
+ <goals>
+ <goal>compile</goal>
+ </goals>
+ </execution>
+ <execution>
+ <id>test-compile</id>
+ <phase>test-compile</phase>
+ <goals>
+ <goal>testCompile</goal>
+ </goals>
+ </execution>
+ <execution>
+ <id>prepareRepositories</id>
+ <phase>generate-test-resources</phase>
+ <goals>
+ <goal>execute</goal>
+ </goals>
+ <configuration>
+ <source>
+log.info "Preparing Repositories"
+def dir = "${project.basedir}/target/repositories"
+ant.delete dir: dir
+ant.mkdir dir: dir
+ant.copy( toDir: dir ) {
+ fileset dir: "${project.basedir}/src/test/repositories"
+}
+
+def prepareArchetype = { archetype, archetypeVersion ->
+ if( project.packaging != 'pom' ) {
+ log.info "Preparing ${archetype}-${archetypeVersion} archetype..."
+ dir = "${project.basedir}/target/repositories/central/archetypes/${archetype}/${archetypeVersion}"
+ ant.mkdir dir: dir
+ ant.jar destFile: "${dir}/${archetype}-${archetypeVersion}.jar", basedir: "${project.basedir}/src/test/archetypes/${archetype}"
+ }
+}
+prepareArchetype 'nested-complete-main', '1.0'
+prepareArchetype 'nested-complete-inner', '1.0'
+prepareArchetype 'nested-complete-innest', '1.0'
+
+prepareArchetype 'nested-missing-main', '1.0'
+prepareArchetype 'nested-missing-inner', '1.0'
+
+prepareArchetype 'basic', '1.0'
+prepareArchetype 'basic-with-parent', '1.0'
+prepareArchetype 'multi', '1.0'
+prepareArchetype 'multi-with-parent', '1.0'
+
+prepareArchetype 'old', '1.0'
+prepareArchetype 'nested-main', '1.0'
+prepareArchetype 'nested-inner', '1.0'
+prepareArchetype 'nested-innest', '1.0'
+prepareArchetype 'nested-partial', '1.0'
+ </source>
+ </configuration>
+ </execution>
+ <execution>
+ <id>prepareProjects</id>
+ <phase>generate-test-resources</phase>
+ <goals>
+ <goal>execute</goal>
+ </goals>
+ <configuration>
+ <source>
+log.info "Preparing projects..."
+def dir = "${project.basedir}/target/projects"
+ant.delete dir: dir
+ant.mkdir dir: dir
+ant.copy( toDir: dir ) {
+ fileset dir: "${project.basedir}/src/test/projects"
+}
+ </source>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <groupId>org.codehaus.plexus</groupId>
+ <artifactId>plexus-maven-plugin</artifactId>
+ <version>1.3.8</version>
+ <executions>
+ <execution>
+ <goals>
+ <goal>descriptor</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-dependency-plugin</artifactId>
+ <executions>
+ <execution>
+ <id>copy</id>
+ <phase>process-test-resources</phase>
+ <goals>
+ <goal>copy-dependencies</goal>
+ </goals>
+ <configuration>
+ <outputDirectory>${project.build.directory}/wars</outputDirectory>
+ <overWriteReleases>true</overWriteReleases>
+ <overWriteSnapshots>true</overWriteSnapshots>
+ <includeTypes>war</includeTypes>
+ <stripVersion>true</stripVersion>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </build>
+ <reporting>
+ <plugins>
+ <plugin>
+ <groupId>org.codehaus.mojo</groupId>
+ <artifactId>cobertura-maven-plugin</artifactId>
+ <version>2.2</version>
+ </plugin>
+ </plugins>
+ </reporting>
+
+ <profiles>
+ <profile>
+ <id>internal-catalog</id>
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-surefire-plugin</artifactId>
+ <configuration>
+ <includes>
+ <include>**/InternalCatalogFromWiki.java</include>
+ </includes>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+ </profile>
+ </profiles>
+</project>
diff --git a/grarchetype-common/src/main/groovy/groovy/xml/IndentedStreamingMarkupBuilder.groovy b/grarchetype-common/src/main/groovy/groovy/xml/IndentedStreamingMarkupBuilder.groovy
new file mode 100644
index 0000000..62882b4
--- /dev/null
+++ b/grarchetype-common/src/main/groovy/groovy/xml/IndentedStreamingMarkupBuilder.groovy
@@ -0,0 +1,172 @@
+package groovy.xml
+
+import groovy.xml.streamingmarkupsupport.AbstractStreamingBuilder
+import groovy.xml.streamingmarkupsupport.StreamingMarkupWriter
+import groovy.xml.streamingmarkupsupport.BaseMarkupBuilder
+
+class IndentedStreamingMarkupBuilder extends StreamingMarkupBuilder {
+ def tagIndentOffset = ' '
+ def attributeIndentOffest = ' '
+ private def tagIndentString = ''
+ private def attributeIndentString = attributeIndentOffest
+ private def tagIndentclosed = false
+
+ def pendingStack = []
+ def commentClosure = {doc, pendingNamespaces, namespaces, namespaceSpecificTags, prefix, attrs, body, out ->
+ out.unescaped() << "\n${tagIndentString}<!--"
+ out.escaped() << body
+ out.unescaped() << "${tagIndentString}-->"
+ }
+ def piClosure = {doc, pendingNamespaces, namespaces, namespaceSpecificTags, prefix, attrs, body, out ->
+ attrs.each {target, instruction ->
+ out.unescaped() << "\n${tagIndentString}<?"
+ if (instruction instanceof Map) {
+ out.unescaped() << target
+ instruction.each {name, value ->
+ if (value.toString().contains('"')) {
+ out.unescaped() << " $name='$value'"
+ } else {
+ out.unescaped() << " $name=\"$value\""
+ }
+ }
+ } else {
+ out.unescaped() << "$target $instruction"
+ }
+ out.unescaped() << "?>"
+ }
+ }
+ def declarationClosure = {doc, pendingNamespaces, namespaces, namespaceSpecificTags, prefix, attrs, body, out ->
+ out.unescaped() << '<?xml version="1.0"'
+ if (out.encodingKnown) out.escaped() << " encoding=\"${out.encoding}\""
+ out.unescaped() << '?>'
+ }
+ def noopClosure = {doc, pendingNamespaces, namespaces, namespaceSpecificTags, prefix, attrs, body, out ->
+ body.each {
+ if (it instanceof Closure) {
+ def body1 = it.clone()
+
+ body1.delegate = doc
+ body1(doc)
+ } else if (it instanceof Buildable) {
+ it.build(doc)
+ } else {
+ out.escaped() << it
+ }
+ }
+ }
+ def unescapedClosure = {doc, pendingNamespaces, namespaces, namespaceSpecificTags, prefix, attrs, body, out ->
+ out.unescaped() << body
+ }
+ def tagClosure = {tag, doc, pendingNamespaces, namespaces, namespaceSpecificTags, prefix, attrs, body, out ->
+ if (prefix != "") {
+ if (!(namespaces.containsKey(prefix) || pendingNamespaces.containsKey(prefix))) {
+ throw new GroovyRuntimeException("Namespace prefix: ${prefix} is not bound to a URI")
+ }
+
+ if (prefix != ":") tag = prefix + ":" + tag
+ }
+
+ out = out.unescaped() << "\n${tagIndentString}<${tag}"
+
+ attrs.each {key, value ->
+ if (key.contains('$')) {
+ def parts = key.tokenize('$')
+
+ if (namespaces.containsKey(parts[0]) || pendingNamespaces.containsKey(parts[0])) {
+ key = parts[0] + ":" + parts[1]
+ } else {
+ throw new GroovyRuntimeException("bad attribute namespace tag: ${parts[0]} in ${key}")
+ }
+ }
+
+ out << " ${key}='"
+ out.writingAttribute = true
+ "${value}".build(doc)
+ out.writingAttribute = false
+ out << "'"
+ }
+
+ def hiddenNamespaces = [:]
+
+ pendingNamespaces.each {key, value ->
+ hiddenNamespaces[key] = namespaces[key]
+ namespaces[key] = value
+ out << ((key == ":") ? " xmlns='" : " xmlns:${key}='")
+ out.writingAttribute = true
+ "${value}".build(doc)
+ out.writingAttribute = false
+ out << "'"
+ }
+
+ if (body == null) {
+ out << "/>"
+ } else {
+ out << ">"
+ tagIndentclosed = false
+ tagIndentString = tagIndentString + tagIndentOffset
+ attributeIndentString = tagIndentString + attributeIndentOffest
+
+ pendingStack.add pendingNamespaces.clone()
+ pendingNamespaces.clear()
+
+ body.each {
+ if (it instanceof Closure) {println"CLOSURE"
+ def body1 = it.clone()
+
+ body1.delegate = doc
+ body1(doc)
+ } else if (it instanceof Buildable) {println"BUILDABLE}"
+ it.build(doc)
+ } else {println"ESCAPED}"
+ out.escaped() << it
+ }
+ }
+
+ System.out.println"XXX ${tag} XX${body?.dump()}"
+ pendingNamespaces.clear()
+ pendingNamespaces.putAll pendingStack.pop()
+
+ tagIndentString = tagIndentString - tagIndentOffset
+ attributeIndentString = tagIndentString + attributeIndentOffest
+ out << "${tagIndentclosed?'\n'+tagIndentString:''}</${tag}>"
+ tagIndentclosed = true
+ }
+
+ hiddenNamespaces.each {key, value ->
+ if (value == null) {
+ namespaces.remove key
+ } else {
+ namespaces[key] = value
+ }
+ }
+ }
+
+ def builder = null
+
+ IndentedStreamingMarkupBuilder() {
+ specialTags.putAll(['yield': noopClosure,
+ 'yieldUnescaped': unescapedClosure,
+ 'xmlDeclaration': declarationClosure,
+ 'comment': commentClosure,
+ 'pi': piClosure])
+
+ def nsSpecificTags = [':': [tagClosure, tagClosure, [:]], // the default namespace
+ 'http://www.w3.org/XML/1998/namespace': [tagClosure, tagClosure, [:]],
+ 'http://www.codehaus.org/Groovy/markup/keywords': [badTagClosure, tagClosure, specialTags]]
+
+ this.builder = new BaseMarkupBuilder(nsSpecificTags)
+ }
+
+ def encoding = null
+
+ public bind(closure) {
+ def boundClosure = this.builder.bind(closure);
+ def enc = encoding; // take a snapshot of the encoding when the closure is bound to the builder
+
+ {out ->
+ out = new StreamingMarkupWriter(out, enc)
+ boundClosure.trigger = out
+ out.flush()
+ }.asWritable()
+ }
+}
diff --git a/grarchetype-common/src/main/groovy/org/apache/maven/archetype/Archetype.groovy b/grarchetype-common/src/main/groovy/org/apache/maven/archetype/Archetype.groovy
new file mode 100644
index 0000000..c73b212
--- /dev/null
+++ b/grarchetype-common/src/main/groovy/org/apache/maven/archetype/Archetype.groovy
@@ -0,0 +1,13 @@
+package org.apache.maven.archetype
+
+/**
+ *
+ * @author rafale
+ */
+interface Archetype {
+ String ROLE = 'org.apache.maven.archetype.Archetype'
+
+ ArchetypeGenerationResult generateProjectFromArchetype( ArchetypeGenerationRequest request )
+
+}
+
diff --git a/grarchetype-common/src/main/groovy/org/apache/maven/archetype/ArchetypeGenerationRequest.groovy b/grarchetype-common/src/main/groovy/org/apache/maven/archetype/ArchetypeGenerationRequest.groovy
new file mode 100644
index 0000000..18efd6d
--- /dev/null
+++ b/grarchetype-common/src/main/groovy/org/apache/maven/archetype/ArchetypeGenerationRequest.groovy
@@ -0,0 +1,22 @@
+package org.apache.maven.archetype
+
+/**
+ *
+ * @author rafale
+ */
+class ArchetypeGenerationRequest {
+ //- input properties
+ def repositories
+ def localRepository
+
+ def groupId
+ def artifactId
+ def version
+ def outputDirectory
+ def generationFilterProperties
+
+ //- calculed properties
+ def archetypeFile
+ def archetypes
+}
+
diff --git a/grarchetype-common/src/main/groovy/org/apache/maven/archetype/ArchetypeGenerationResult.groovy b/grarchetype-common/src/main/groovy/org/apache/maven/archetype/ArchetypeGenerationResult.groovy
new file mode 100644
index 0000000..717c91f
--- /dev/null
+++ b/grarchetype-common/src/main/groovy/org/apache/maven/archetype/ArchetypeGenerationResult.groovy
@@ -0,0 +1,10 @@
+package org.apache.maven.archetype
+
+/**
+ *
+ * @author rafale
+ */
+class ArchetypeGenerationResult {
+ def cause
+}
+
diff --git a/grarchetype-common/src/main/groovy/org/apache/maven/archetype/DefaultArchetype.groovy b/grarchetype-common/src/main/groovy/org/apache/maven/archetype/DefaultArchetype.groovy
new file mode 100644
index 0000000..7d00f18
--- /dev/null
+++ b/grarchetype-common/src/main/groovy/org/apache/maven/archetype/DefaultArchetype.groovy
@@ -0,0 +1,33 @@
+package org.apache.maven.archetype
+
+import org.codehaus.plexus.logging.AbstractLogEnabled
+import org.apache.maven.archetype.generator.ProjectGenerator
+
+/**
+ *
+ * @author rafale
+ * @plexus.component
+ */
+class DefaultArchetype
+extends AbstractLogEnabled
+implements Archetype {
+
+ /** @plexus.requirement */
+ private ProjectGenerator generator
+
+ ArchetypeGenerationResult generateProjectFromArchetype( ArchetypeGenerationRequest request ) {
+ logger.error "generateProjectFromArchetype $request"
+
+ ArchetypeGenerationResult result = new ArchetypeGenerationResult()
+
+ try {
+ generator.generateProject request
+ } catch( exception ) {
+ result.cause = exception
+ }
+
+ return result
+ }
+
+}
+
diff --git a/grarchetype-common/src/main/groovy/org/apache/maven/archetype/artifact/ArchetypeArtifactManager.groovy b/grarchetype-common/src/main/groovy/org/apache/maven/archetype/artifact/ArchetypeArtifactManager.groovy
new file mode 100644
index 0000000..7dce7b5
--- /dev/null
+++ b/grarchetype-common/src/main/groovy/org/apache/maven/archetype/artifact/ArchetypeArtifactManager.groovy
@@ -0,0 +1,26 @@
+package org.apache.maven.archetype.artifact
+import org.apache.maven.artifact.repository.ArtifactRepository
+import org.apache.maven.artifact.repository.ArtifactRepository
+
+/**
+ *
+ * @author rafale
+ */
+interface ArchetypeArtifactManager {
+ static String ROLE = 'org.apache.maven.archetype.artifact.ArchetypeArtifactManager'
+
+ static String ARCHETYPE_DESCRIPTOR = 'META-INF/maven/archetype-metadata.xml'
+ static String LEGACY_ARCHETYPE_DESCRIPTOR = 'META-INF/maven/archetype.xml'
+ static String OLD_LEGACY_ARCHETYPE_DESCRIPTOR = 'META-INF/archetype.xml'
+
+ def getFilesetArchetypeDescriptor( File archetypeFile )
+ def getFilesetArchetypeResources( File archetypeFile )
+ def getArchetypeZipFile( File archetypeFile )
+
+ def getArchetypeFile( String groupId, String artifactId, String version,
+ ArtifactRepository localRepository, List<ArtifactRepository> remoteRepository )
+ def isLegacyArchetype( File archetypeFile )
+
+ def getLegacyArchetypeDescriptor( File archetypeFile )
+}
+
diff --git a/grarchetype-common/src/main/groovy/org/apache/maven/archetype/artifact/DefaultArchetypeArtifactManager.groovy b/grarchetype-common/src/main/groovy/org/apache/maven/archetype/artifact/DefaultArchetypeArtifactManager.groovy
new file mode 100644
index 0000000..2519f5a
--- /dev/null
+++ b/grarchetype-common/src/main/groovy/org/apache/maven/archetype/artifact/DefaultArchetypeArtifactManager.groovy
@@ -0,0 +1,153 @@
+package org.apache.maven.archetype.artifact
+import java.util.zip.ZipFile
+import java.util.zip.ZipEntry
+import org.codehaus.plexus.logging.AbstractLogEnabled
+import org.apache.maven.artifact.factory.ArtifactFactory
+import org.apache.maven.artifact.resolver.ArtifactResolver
+import org.apache.maven.artifact.repository.ArtifactRepository
+import org.apache.maven.artifact.Artifact
+
+/**
+ *
+ * @author raphaelpieroni
+ * @plexus.component
+ */
+class DefaultArchetypeArtifactManager
+extends AbstractLogEnabled
+implements ArchetypeArtifactManager {
+
+ /**
+ * @plexus.requirement
+ */
+ ArtifactResolver artifactResolver
+
+ /**
+ * @plexus.requirement
+ */
+ ArtifactFactory artifactFactory
+
+ def getFilesetArchetypeDescriptor( File archetypeFile ) {
+ ZipFile zipFile = getArchetypeZipFile( archetypeFile )
+ ZipEntry entry = zipFile.getEntry( ARCHETYPE_DESCRIPTOR.replaceAll( File.separator, "/" ) )
+ if( !entry ) {
+ logger.debug "No found ${ARCHETYPE_DESCRIPTOR} retrying with windows path"
+ entry = zipFile.getEntry( ARCHETYPE_DESCRIPTOR.replaceAll( "/", File.separator ) )
+ }
+ if( !entry ) throw new IOException( "The ${ARCHETYPE_DESCRIPTOR} descriptor cannot be found." )
+
+ zipFile.getInputStream entry
+ }
+
+ def getFilesetArchetypeResources( File archetypeFile ) {
+ ZipFile zipFile = getArchetypeZipFile( archetypeFile )
+ zipFile.entries().findAll { entry ->
+ !entry.isDirectory() && entry.name.startsWith ( 'archetype-resources/' )
+ }.collect { entry ->
+ entry.name.replace 'archetype-resources/', ''
+ }
+ }
+
+ def getArchetypeZipFile( File archetypeFile ) {
+ logger.debug "Loading zip file ${archetypeFile.exists()} ${archetypeFile}"
+ new ZipFile( archetypeFile )
+ }
+
+
+ def getArchetypeFile( String groupId, String artifactId, String version,
+ ArtifactRepository localRepository, List<ArtifactRepository> remoteRepositories ) {
+
+ Artifact artifact = artifactFactory.createArtifact( groupId, artifactId, version,
+ Artifact.SCOPE_RUNTIME, 'jar' )
+ artifactResolver.resolve( artifact, remoteRepositories, localRepository )
+ artifact.file
+ }
+
+ def isLegacyArchetype( File archetypeFile ) {
+ ZipFile zipFile = getArchetypeZipFile( archetypeFile )
+
+ ZipEntry regularDescriptor = zipFile.getEntry( ARCHETYPE_DESCRIPTOR.replaceAll( File.separator, "/" ) )
+ if( !regularDescriptor ) {
+ regularDescriptor = zipFile.getEntry( ARCHETYPE_DESCRIPTOR.replaceAll( "/", File.separator ) )
+ }
+ if( regularDescriptor ) return false
+
+ ZipEntry legacyDescriptor = zipFile.getEntry( LEGACY_ARCHETYPE_DESCRIPTOR.replaceAll( File.separator, "/" ) )
+ if( !legacyDescriptor ) {
+ legacyDescriptor = zipFile.getEntry( LEGACY_ARCHETYPE_DESCRIPTOR.replaceAll( "/", File.separator ) )
+ }
+ if( !legacyDescriptor ) {
+ legacyDescriptor = zipFile.getEntry( OLD_LEGACY_ARCHETYPE_DESCRIPTOR.replaceAll( File.separator, "/" ) )
+ }
+ if( !legacyDescriptor ) {
+ legacyDescriptor = zipFile.getEntry( OLD_LEGACY_ARCHETYPE_DESCRIPTOR.replaceAll( "/", File.separator ) )
+ }
+ if( legacyDescriptor ) return true
+
+ return false
+ }
+
+ def getLegacyArchetypeDescriptor( File archetypeFile ) {
+ ZipFile zipFile = getArchetypeZipFile( archetypeFile )
+ ZipEntry entry = zipFile.getEntry( LEGACY_ARCHETYPE_DESCRIPTOR.replaceAll( File.separator, "/" ) )
+ if( !entry ) {
+ logger.debug "No found ${LEGACY_ARCHETYPE_DESCRIPTOR} retrying with windows path"
+ entry = zipFile.getEntry( LEGACY_ARCHETYPE_DESCRIPTOR.replaceAll( "/", File.separator ) )
+ }
+ if( !entry ) {
+ logger.debug "No found ${LEGACY_ARCHETYPE_DESCRIPTOR} retrying with ${OLD_LEGACY_ARCHETYPE_DESCRIPTOR}"
+ entry = zipFile.getEntry( OLD_LEGACY_ARCHETYPE_DESCRIPTOR.replaceAll( File.separator, "/" ) )
+ }
+ if( !entry ) {
+ logger.debug "No found ${OLD_LEGACY_ARCHETYPE_DESCRIPTOR} retrying with windows path"
+ entry = zipFile.getEntry( OLD_LEGACY_ARCHETYPE_DESCRIPTOR.replaceAll( "/", File.separator ) )
+ }
+
+ zipFile.getInputStream entry
+ }
+
+ def getNestedArchetypeFiles( archetype, localRepository, repositories, archetypeFileMap = [:] ) {
+ def archetypeFile = getArchetypeFile(
+ archetype.groupId, archetype.artifactId, archetype.version,
+ localRepository, repositories )
+ archetypeFileMap[(archetype)] = archetypeFile
+ if( !isLegacyArchetype( archetypeFile ) ) {
+ getNestedArchetypes( archetypeFile, localRepository, repositories ).each { nestedArchetype ->
+ getNestedArchetypeFiles( nestedArchetype, localRepository, repositories, archetypeFileMap )
+ }
+ }
+ return archetypeFileMap
+ }
+ def getNestedArchetypes( archetypeFile, localRepository, repositories ) {
+ logger.debug "Searching for nested archetype of ${archetypeFile}"
+ def descriptor = new XmlSlurper().parse( getFilesetArchetypeDescriptor( archetypeFile ) )
+ def nestedArchetypes = []
+ descriptor.modules.module.each {
+ if( it.@nested.toBoolean() ) {
+ logger.debug "Module ${it.@artifactId.toString()} is a nested archetype"
+ nestedArchetypes.add toDefinition( it )
+ } else {
+ logger.debug "Module ${it.@artifactId.toString()} is a regular module"
+ getInnerArchetypes it, nestedArchetypes, localRepository, repositories
+ }
+
+ }
+ return nestedArchetypes
+ }
+ void getInnerArchetypes( module, nestedArchetypes, localRepository, repositories ) {
+ module.modules.module.each {
+ if( it.@nested.toBoolean() ) {
+ logger.debug "Module ${it.@artifactId.toString()} is a nested archetype"
+ nestedArchetypes.add toDefinition( it )
+ } else {
+ logger.debug "Module ${it.@artifactId.toString()} is a regular module"
+ getInnerArchetypes it, nestedArchetypes, localRepository, repositories
+ }
+ }
+ }
+ def toDefinition( module ) {
+ [groupId:module.@archetypeGroupId.text().toString(),
+ artifactId:module.@archetypeArtifactId.text().toString(),
+ version:module.@archetypeVersion.text().toString()]
+ }
+}
+
diff --git a/grarchetype-common/src/main/groovy/org/apache/maven/archetype/catalog/ArchetypeCataloger.groovy b/grarchetype-common/src/main/groovy/org/apache/maven/archetype/catalog/ArchetypeCataloger.groovy
new file mode 100644
index 0000000..44c689f
--- /dev/null
+++ b/grarchetype-common/src/main/groovy/org/apache/maven/archetype/catalog/ArchetypeCataloger.groovy
@@ -0,0 +1,18 @@
+package org.apache.maven.archetype.catalog
+
+/**
+ *
+ * @author raphaelpieroni
+ */
+interface ArchetypeCataloger {
+ static String ROLE = 'org.apache.maven.archetype.catalog.ArchetypeCataloger'
+
+ def loadCatalog( String catalog )
+
+ def archetypeRecursivelyExists( archetype, archetypeDefinitions, localRepository, repositories )
+
+ def getArchetypesByCatalog( catalogs )
+
+ def searchArchetype( definition, archetypeCatalogs )
+}
+
diff --git a/grarchetype-common/src/main/groovy/org/apache/maven/archetype/catalog/DefaultArchetypeCataloger.groovy b/grarchetype-common/src/main/groovy/org/apache/maven/archetype/catalog/DefaultArchetypeCataloger.groovy
new file mode 100644
index 0000000..0615d1f
--- /dev/null
+++ b/grarchetype-common/src/main/groovy/org/apache/maven/archetype/catalog/DefaultArchetypeCataloger.groovy
@@ -0,0 +1,152 @@
+package org.apache.maven.archetype.catalog
+import org.codehaus.plexus.logging.AbstractLogEnabled
+import org.apache.maven.archetype.artifact.ArchetypeArtifactManager
+
+/**
+ *
+ * @author raphaelpieroni
+ * @plexus.component
+ */
+class DefaultArchetypeCataloger
+extends AbstractLogEnabled
+implements ArchetypeCataloger {
+
+ /** @plexus.requirement */
+ private ArchetypeArtifactManager artifactManager
+
+ def loadCatalog( String catalogName ) {
+ def catalog
+ switch( catalogName ) {
+ case "internal":
+ logger.info "Using internal catalog"
+ catalog = this.class.classLoader.getResourceAsStream( "archetype-catalog.xml" )
+ break
+
+ case "local":
+ logger.info "Using default local catalog"
+ catalog = new File( System.getProperty( "user.home" ), ".m2/archetype-catalog.xml" )
+ break
+
+ case "remote":
+ logger.info "Using default remote catalog"
+ catalog = "http://repo1.maven.org/maven2/archetype-catalog.xml"
+ break
+
+ case ~"file://.*":
+ logger.info "Using local catalog $catalogName"
+ break
+
+ case ~"https?://.*":
+ logger.info "Using remote catalog $catalogName"
+ catalog = catalogName
+ break
+
+ default: return null
+ }
+ if( !catalog ) {
+ logger.warn "Catalog $catalogName not found"
+ return null
+ }
+ try {
+ return new XmlSlurper().parse( catalog )
+ } catch( e ) {
+ logger.warn "Can not read catalog $catalogName: $e.message"
+ return
+ }
+ }
+
+
+ def archetypeRecursivelyExists( archetype, archetypeDefinitions, localRepository, repositories ) {
+ def archetypeFile
+ try {
+ archetypeFile = artifactManager.getArchetypeFile(
+ archetype.groupId, archetype.artifactId, archetype.version,
+ localRepository, repositories )
+ } catch( e ) {
+ logger.warn "Archetype ${archetype} not found", e
+ return false
+ }
+ if( artifactManager.isLegacyArchetype( archetypeFile ) ) {
+ return true
+ } else {
+ def recursivelyExists = true
+ getNestedArchetypes( archetypeFile, archetypeDefinitions, localRepository, repositories ).each { nestedArchetype ->
+ recursivelyExists = recursivelyExists &&
+ archetypeRecursivelyExists( nestedArchetype, archetypeDefinitions, localRepository, repositories )
+ }
+ return recursivelyExists
+ }
+ }
+ def getNestedArchetypes( archetypeFile, archetypeDefinitions, localRepository, repositories ) {
+ logger.debug "Searching for nested archetype of ${archetypeFile}"
+ def descriptor = new XmlSlurper().parse( artifactManager.getFilesetArchetypeDescriptor( archetypeFile ) )
+ def nestedArchetypes = []
+ descriptor.modules.module.each {
+ if( it.@nested.toBoolean() ) {
+ logger.debug "Module ${it.@artifactId.toString()} is a nested archetype"
+ nestedArchetypes.add toDefinition( it )
+ } else {
+ logger.debug "Module ${it.@artifactId.toString()} is a regular module"
+ getInnerArchetypes it, archetypeDefinitions, nestedArchetypes, localRepository, repositories
+ }
+
+ }
+ return nestedArchetypes
+ }
+ void getInnerArchetypes( module, archetypes, nestedArchetypes, localRepository, repositories ) {
+ module.modules.module.each {
+ if( it.@nested.toBoolean() ) {
+ logger.debug "Module ${it.@artifactId.toString()} is a nested archetype"
+ nestedArchetypes.add toDefinition( it )
+ } else {
+ logger.debug "Module ${it.@artifactId.toString()} is a regular module"
+ getInnerArchetypes it, archetypes, nestedArchetypes, localRepository, repositories
+ }
+ }
+ }
+ def getArchetypesByCatalog( catalogs ) {
+ if( !catalogs ) return null
+ def archetypes = [:]
+ catalogs.split( "," ).each { catalogName ->
+ def catalog = loadCatalog( catalogName )
+ if( !catalog ) {
+ logger.error "Unknown catalog $catalog"
+ return null
+ }
+ catalog.archetypes.archetype.each{
+ def archetype = [
+ catalog:catalogName,
+ groupId:it.groupId.text().toString(),
+ artifactId:it.artifactId.text().toString(),
+ version:it.version.text().toString(),
+ description:it.description.text().toString(),
+ repository:it.repository.text().toString()]
+ if( !archetype.repository && (catalogName =~ "(file|https?)://.*" ) ) archetype.repository = catalogName - "archetype-catalog.xml"
+
+ archetypes["${archetype.groupId}:${archetype.artifactId}:${archetype.version}".toString()] = archetype
+ }
+ }
+ return archetypes
+ }
+ def toDefinition( module ) {
+ [groupId:module.@archetypeGroupId.text().toString(),
+ artifactId:module.@archetypeArtifactId.text().toString(),
+ version:module.@archetypeVersion.text().toString()]
+ }
+ def searchArchetype( definition, archetypeCatalogs ) {
+ def archetype
+ archetypeCatalogs.each { key, value ->
+ if( !archetype &&
+ definition['groupId'] == value['groupId'] &&
+ definition['artifactId'] == value['artifactId'] &&
+ (definition['version'] ? definition['version'] == value['version'] : true) ) {
+ archetype = value
+ }
+ }
+ if( !archetype ) {
+ log.warn "Archetype ${definition} not found in any catalog"
+ }
+ return archetype
+ }
+}
+
diff --git a/grarchetype-common/src/main/groovy/org/apache/maven/archetype/file/ArchetypeFileResolver.groovy b/grarchetype-common/src/main/groovy/org/apache/maven/archetype/file/ArchetypeFileResolver.groovy
new file mode 100644
index 0000000..7d28b3a
--- /dev/null
+++ b/grarchetype-common/src/main/groovy/org/apache/maven/archetype/file/ArchetypeFileResolver.groovy
@@ -0,0 +1,13 @@
+package org.apache.maven.archetype.file
+
+/**
+ *
+ * @author rafale
+ */
+interface ArchetypeFileResolver {
+ static String ROLE = 'org.apache.maven.archetype.file.ArchetypeFileResolver'
+ def getFiles( moduleOffset, fileset, archetypeResources )
+ def getFile( moduleOffset, filesetDirectory, resource, archetypeZipFile )
+ def getResourcePath( moduleOffset, filesetDirectory, resource )
+}
+
diff --git a/grarchetype-common/src/main/groovy/org/apache/maven/archetype/file/DefaultArchetypeFileResolver.groovy b/grarchetype-common/src/main/groovy/org/apache/maven/archetype/file/DefaultArchetypeFileResolver.groovy
new file mode 100644
index 0000000..4c65c12
--- /dev/null
+++ b/grarchetype-common/src/main/groovy/org/apache/maven/archetype/file/DefaultArchetypeFileResolver.groovy
@@ -0,0 +1,43 @@
+package org.apache.maven.archetype.file
+import org.codehaus.plexus.logging.AbstractLogEnabled
+import java.util.zip.ZipEntry
+import org.apache.maven.archetype.util.Scanner
+
+/**
+ *
+ * @author rafale
+ * @plexus.component
+ */
+class DefaultArchetypeFileResolver
+extends AbstractLogEnabled
+implements ArchetypeFileResolver {
+
+ def getFiles( moduleOffset, fileset, archetypeResources ) {
+ def resourceStart = "${moduleOffset?moduleOffset+'/':''}${fileset.directory.text().toString()?fileset.directory.text().toString()+'/':''}"
+ def scanner = new Scanner( fileset:fileset )
+// logger.error"START=${resourceStart}"
+ archetypeResources.findAll{ resource ->
+ resource.startsWith resourceStart
+ }.collect{ resource ->
+ resource.replace resourceStart, ''
+ }.findAll{resource ->
+ scanner.match resource
+ }
+ }
+
+ def getFile( moduleOffset, filesetDirectory, resource, archetypeZipFile ) {
+ def resourceZipPath = getResourcePath( moduleOffset, filesetDirectory, resource )
+// logger.error"RES${resourceZipPath}}"
+ try {
+ ZipEntry entry = archetypeZipFile.getEntry( resourceZipPath )
+ return archetypeZipFile.getInputStream( entry )
+ } catch (e) {
+ logger.error "Can not find resource ${resourceZipPath} in archetype sip file"
+ }
+ }
+
+ def getResourcePath( moduleOffset, filesetDirectory, resource ) {
+ "archetype-resources/${moduleOffset?moduleOffset+'/':''}${filesetDirectory?filesetDirectory+'/':''}${resource}".toString()
+ }
+}
+
diff --git a/grarchetype-common/src/main/groovy/org/apache/maven/archetype/generator/AbstractFilesetArchetypeGenerator.groovy b/grarchetype-common/src/main/groovy/org/apache/maven/archetype/generator/AbstractFilesetArchetypeGenerator.groovy
new file mode 100644
index 0000000..b376ace
--- /dev/null
+++ b/grarchetype-common/src/main/groovy/org/apache/maven/archetype/generator/AbstractFilesetArchetypeGenerator.groovy
@@ -0,0 +1,359 @@
+package org.apache.maven.archetype.generator
+import org.apache.maven.archetype.ArchetypeGenerationRequest
+import org.apache.maven.archetype.artifact.ArchetypeArtifactManager
+import org.codehaus.plexus.logging.AbstractLogEnabled
+import groovy.text.SimpleTemplateEngine
+import org.apache.maven.archetype.file.ArchetypeFileResolver
+import groovy.xml.StreamingMarkupBuilder
+import groovy.xml.StreamingSAXBuilder
+import groovy.xml.MarkupBuilder
+import org.apache.maven.archetype.pom.PomManager
+import org.apache.maven.model.Model
+import org.apache.maven.model.Parent
+import org.gparallelizer.Asynchronizer
+import org.apache.velocity.runtime.log.LogChute
+import org.apache.velocity.runtime.RuntimeServices
+import org.apache.velocity.app.VelocityEngine
+import org.apache.velocity.VelocityContext
+
+/**
+ *
+ * @author raphaelpieroni
+ */
+abstract class AbstractFilesetArchetypeGenerator
+extends AbstractLogEnabled
+implements FilesetArchetypeGenerator, LogChute {
+
+ /** @plexus.requirement */
+ ArchetypeArtifactManager archetypeArtifactManager
+ /** @plexus.requirement */
+ ArchetypeFileResolver archetypeFileResolver
+ /** @plexus.requirement */
+ PomManager pomManager
+
+ def templateEngine = new SimpleTemplateEngine()
+
+ void generateProject( ArchetypeGenerationRequest request ){
+ def archetypeDescriptor = loadArchetypeDescriptor( request.archetypeFile )
+ def archetypeResources = archetypeArtifactManager.getFilesetArchetypeResources( request.archetypeFile )
+ def archetypeZipFile = archetypeArtifactManager.getArchetypeZipFile( request.archetypeFile )
+ def velocity = getVelocityEngine( request.archetypeFile )
+ def basedirPom = new File( request.outputDirectory, 'pom.xml' )
+ def filterProperties = prepareFilterProperties( request )
+
+logger.error"RESOURCES${archetypeResources}"
+logger.error"this=${this.dump()}"
+ if( !archetypeDescriptor.@partial.toBoolean() ) {
+ logger.info "Processing complete archetype: ${archetypeDescriptor.@name}"
+ def projectOutputDirectory = new File( request.outputDirectory, filterProperties.artifactId )
+
+ if( new File( projectOutputDirectory, 'pom.xml' ).exists() ) throw new Exception( "A project already exists in ${projectOutputDirectory}" )
+
+ def processRequest = [moduleOffset:'',
+ zipModuleOffset:'',
+ archetypeDescriptor:archetypeDescriptor,
+ filterProperties:filterProperties,
+ archetypeResources:archetypeResources,
+ archetypeZipFile:archetypeZipFile,
+ outputDirectory:projectOutputDirectory,
+ updirPom:basedirPom,
+ archetypes:request.archetypes,
+ velocity:velocity
+ ]
+ processProject processRequest
+ } else {
+logger.error "Processing partial archetype: ${archetypeDescriptor.@name} in ${request.outputDirectory}"
+
+ if( !basedirPom.exists() ) throw new Exception( "No project to modify in ${request.outputDirectory}" )
+
+ def processRequest = [moduleOffset:'',
+ zipModuleOffset:'',
+ archetypeDescriptor:archetypeDescriptor,
+ filterProperties:filterProperties,
+ archetypeResources:archetypeResources,
+ archetypeZipFile:archetypeZipFile,
+ outputDirectory:request.outputDirectory,
+ archetypes:request.archetypes,
+ velocity:velocity
+ ]
+ processPartialProject processRequest
+
+ }
+ }
+
+ abstract def loadArchetypeDescriptor( File archetypeFile )
+
+ def getVelocityEngine( File jarFile ){
+ def engine = new VelocityEngine()
+ engine.setProperty VelocityEngine.RUNTIME_LOG_LOGSYSTEM, this
+ engine.setProperty VelocityEngine.RESOURCE_LOADER, 'jar'
+ engine.setProperty 'jar.resource.loader.class', 'org.apache.velocity.runtime.resource.loader.JarResourceLoader'
+ engine.setProperty 'jar.resource.loader.path', "jar:file:${jarFile.path}".toString()
+ engine.init()
+ return engine
+ }
+ void init(RuntimeServices rsvc) {/*println"init ${rsvc}"*/}
+ void log(int level, String message) {/*println"log ${level} ${message}"*/}
+ void log(int level, String message, Throwable t) {/*println "log ${level} ${message} ${t}"*/}
+ boolean isLevelEnabled(int level) {/*println"isLevelEnabled ${level}";*/ return false }
+
+
+ def prepareFilterProperties( request ) {
+logger.error"props ${request.generationFilterProperties}"
+ def filters = request.generationFilterProperties
+ if( !filters.rootArtifactId ) {
+ filters.rootArtifactId = filters.artifactId
+ }
+ filters.upArtifactId = filters.artifactId
+ filters.'package' = filters.packageName
+
+ return filters
+ }
+
+ def processPartialProject( processRequest ) {
+ def pom = mergePom( processRequest )
+ processFilesets processRequest
+ processModules processRequest, pom
+ }
+
+ def processProject( processRequest ) {
+ processRequest.outputDirectory.mkdirs()
+ def pom = processPom( processRequest )
+ processFilesets processRequest
+ processModules processRequest, pom
+ }
+ def processModules( processRequest, pom ) {
+ def moduleOffset = processRequest.moduleOffset
+ def zipModuleOffset = processRequest.zipModuleOffset
+ def outputDirectory = processRequest.outputDirectory
+ def filterProperties = processRequest.filterProperties
+ def upArtifactId = processRequest.filterProperties.artifactId
+ processRequest.archetypeDescriptor.modules.module.each { module ->
+// println"${Thread.currentThread().name} ${module?.dump()}"
+ def artifactId = getOutputName( module.@artifactId.text(), processRequest.filterProperties )
+ def moduleRequest = processRequest.clone()
+ moduleRequest.moduleOffset = "${moduleOffset ? moduleOffset + '/' : ''}${artifactId}"
+ moduleRequest.zipModuleOffset = "${zipModuleOffset ? zipModuleOffset + '/' : ''}${module.@artifactId.text()}"
+ moduleRequest.outputDirectory = new File( outputDirectory, artifactId )
+ moduleRequest.archetypeDescriptor = module
+ moduleRequest.updirPom = pom
+// println"${Thread.currentThread().name} artifactId ${artifactId}"
+// println"${Thread.currentThread().name} moduleRequest.moduleOffset ${moduleRequest.moduleOffset}"
+// println"${Thread.currentThread().name} moduleRequest.outputDirectory ${moduleRequest.outputDirectory}"
+
+ def moduleFilter = filterProperties.clone()
+ moduleFilter.upArtifactId = upArtifactId
+ moduleFilter.artifactId = artifactId
+ moduleRequest.filterProperties = moduleFilter
+
+ if(!module.@nested.toBoolean()){
+ logger.warn "Processing module ${module.@artifactId.text()} in ${moduleRequest.outputDirectory}"
+ processProject moduleRequest
+ } else {
+ def archetype = processRequest.archetypes."${module.@archetypeGroupId.toString()}:${module.@archetypeArtifactId.toString()}:${module.@archetypeVersion.toString()}"
+
+ logger.warn"Processing nested archetype ${module.@archetypeArtifactId.toString()} in ${outputDirectory}"
+ def request = new ArchetypeGenerationRequest()
+ request.archetypes = moduleRequest.archetypes
+ request.archetypeFile = archetype.file
+ request.outputDirectory = outputDirectory
+ moduleRequest.filterProperties.remove 'upArtifactId'
+ moduleRequest.filterProperties.remove 'rootArtifactId'
+ request.generationFilterProperties = moduleRequest.filterProperties
+// request.archetypes = moduleRequest.archetypes
+// request.archetypes = moduleRequest.archetypes
+// request.archetypes = moduleRequest.archetypes
+ archetype.generator.generateProject request
+ }
+ }
+ }
+
+ def mergePom( processRequest ) {
+ def pomFile = new File( processRequest.outputDirectory, 'pom.xml' )
+ Model initialModel = pomManager.loadModel( pomFile )
+
+ StringWriter writer = new StringWriter()
+ processRequest.velocity.mergeTemplate( archetypeFileResolver.getResourcePath( processRequest.zipModuleOffset, '', 'pom.xml' ), new VelocityContext( processRequest.filterProperties ), writer )
+ def slurpedPom = new XmlSlurper().parseText( writer.toString() )
+//logger.error "${Thread.currentThread().name} INITIAL POM ${pomFile}"
+ def pomBuilder = new StreamingMarkupBuilder().bind {
+ mkp.xmlDeclaration()
+ mkp.declareNamespace '':'http://maven.apache.org/POM/4.0.0'
+ mkp.yield slurpedPom
+ }
+ Model newModel = pomManager.loadModel( pomBuilder.toString() )
+
+ pomManager.writeModel pomFile, pomManager.mergeModel( initialModel, newModel )
+
+ return pomFile
+ }
+
+ def processPom( processRequest ) {
+
+ def pomFile = new File( processRequest.outputDirectory, 'pom.xml' )
+//logger.error "${Thread.currentThread().name} Processing POM ${pomFile}"
+ pomFile.parentFile.mkdirs()
+ pomFile.withWriter {
+ it.write archetypeFileResolver.getFile(
+ processRequest.zipModuleOffset, '', 'pom.xml', processRequest.archetypeZipFile
+ ).newReader().text
+ }
+
+// def initialPomFile = archetypeFileResolver.getFile(
+// processRequest.zipModuleOffset, '', 'pom.xml', processRequest.archetypeZipFile
+// ).newReader()
+// def filteredPom = templateEngine.createTemplate( initialPomFile ).
+// make( processRequest.filterProperties )
+ StringWriter writer = new StringWriter()
+ processRequest.velocity.mergeTemplate( archetypeFileResolver.getResourcePath( processRequest.zipModuleOffset, '', 'pom.xml' ), new VelocityContext( processRequest.filterProperties ), writer )
+ def slurpedPom = new XmlSlurper().parseText( writer.toString() )
+//logger.error "${Thread.currentThread().name} INITIAL POM ${pomFile}"
+ def pomBuilder = new StreamingMarkupBuilder().bind {
+ mkp.xmlDeclaration()
+ mkp.declareNamespace '':'http://maven.apache.org/POM/4.0.0'
+ mkp.yield slurpedPom
+ }
+ Model newModel = pomManager.loadModel( pomBuilder.toString() )
+
+ if( processRequest.updirPom?.exists() ) {
+ Model parentModel = pomManager.loadModel( processRequest.updirPom )
+ if( !newModel.parent ) {
+ newModel.parent = new Parent()
+ newModel.parent.groupId = parentModel.groupId
+ newModel.parent.artifactId = parentModel.artifactId
+ newModel.parent.version = parentModel.version
+ }
+//logger.error "MODULES=${parentModel.modules}"
+ if( !parentModel.modules.contains(newModel.artifactId) ) {
+ parentModel.modules << newModel.artifactId
+ pomManager.writeModel processRequest.updirPom, parentModel
+ }
+ }
+
+ pomManager.writeModel pomFile, newModel
+
+ return pomFile
+ }
+
+
+ def processFilesets( processRequest ) {
+
+//logger.error "archetypeDescriptor ${processRequest.archetypeDescriptor.fileSets.dump()}"
+//logger.error "archetypeDescriptor ${processRequest.archetypeDescriptor.fileSets.fileSet.dump()}"
+
+// Asynchronizer.withAsynchronizer {
+ processRequest.archetypeDescriptor.fileSets.fileSet.each/*Async*/ { fileset ->
+//println"A"
+//logger.error"Thread ${Thread.currentThread().name}"
+// logger.error"A${fileset.@filtered.toBoolean()}"
+// logger.error"B${fileset.@packaged.toBoolean()}"
+// logger.error"C${fileset.directory}"
+// logger.error"D${fileset.includes.include.dump()}"
+
+ def filesetResources = archetypeFileResolver.getFiles(
+ processRequest.zipModuleOffset, fileset, processRequest.archetypeResources )
+//println"B"
+//logger.error "FILESET== ${filesetResources}"
+
+ def filesetRequest = processRequest.clone()
+ filesetRequest.filesetResources = filesetResources
+ filesetRequest.packaged = fileset.@packaged.toBoolean()
+ filesetRequest.filesetDirectory = fileset.directory.text().toString()
+ filesetRequest.engine = fileset.@engine?.toString()
+
+//println"C"
+ if( fileset.@filtered.toBoolean() )
+ processFileset filesetRequest
+ else
+ copyFileset filesetRequest
+ }
+// }
+ }
+
+ def processFileset( filesetRequest ) {
+
+println"\n\n\n\n\nD"
+logger.error "Processing Fileset ${filesetRequest.filesetDirectory}"
+// Asynchronizer.withAsynchronizer {
+ VelocityContext context
+ if( 'velocity' == filesetRequest.engine ) context = new VelocityContext( filesetRequest.filterProperties )
+
+ filesetRequest.filesetResources.each { resource ->
+println"E ${resource}"
+ def resourceFile = archetypeFileResolver.getFile(
+ filesetRequest.zipModuleOffset, filesetRequest.filesetDirectory, resource, filesetRequest.archetypeZipFile
+ ).newReader()
+ def text
+ if( 'groovy' == filesetRequest.engine ) {
+ text = templateEngine.createTemplate( resourceFile ).make( filesetRequest.filterProperties )
+println"F"
+ } else {
+ StringWriter writer = new StringWriter()
+ filesetRequest.velocity.mergeTemplate( archetypeFileResolver.getResourcePath( filesetRequest.zipModuleOffset, filesetRequest.filesetDirectory, resource ), context, writer )
+ text = writer.toString()
+println"G"
+ }
+ logger.error "RESULT=\n${text}"
+ def path = getPath( filesetRequest.moduleOffset,
+ filesetRequest.filesetDirectory,
+ filesetRequest.packaged,
+ filesetRequest.filterProperties,
+ resource )
+ def outName = getOutputName( path, filesetRequest.filterProperties )
+ //templateEngine.createTemplate( path ).make( filesetRequest.filterProperties )
+ def outputFile = new File( filesetRequest.outputDirectory, outName.toString() )
+ logger.error "outputFile=${outputFile}"
+ outputFile.parentFile.mkdirs()
+ outputFile.withWriter {
+ it.write text
+ }
+// }
+ }
+println"I"
+ }
+
+ def copyFileset( filesetRequest ) {
+
+//logger.error "Processing Fileset ${filesetRequest.filesetDirectory}"
+// Asynchronizer.withAsynchronizer {
+ filesetRequest.filesetResources.each { resource ->
+ def resourceFile = archetypeFileResolver.getFile(
+ filesetRequest.zipModuleOffset, filesetRequest.filesetDirectory, resource, filesetRequest.archetypeZipFile )
+ def path = getPath( filesetRequest.moduleOffset,
+ filesetRequest.filesetDirectory,
+ filesetRequest.packaged,
+ filesetRequest.filterProperties,
+ resource )
+ def outName = getOutputName( path, filesetRequest.filterProperties )
+ //templateEngine.createTemplate( path ).make( filesetRequest.filterProperties )
+ def outputFile = new File( filesetRequest.outputDirectory, outName.toString() )
+// logger.error "outputFile=${outputFile}"
+ outputFile.parentFile.mkdirs()
+ outputFile.withOutputStream {
+ it << resourceFile
+ }
+ }
+// }
+ }
+
+ def getPath( moduleOffset, filesetDirectory, packaged, filterProperties, resource ) {
+ def offset = moduleOffset ? moduleOffset + '/' : ''
+ def packageName = packaged ? filterProperties.packageName.replace( '.', '/' ) + '/' : ''
+ return "${offset}${filesetDirectory}/${packageName}${resource}"
+ }
+
+
+ def getOutputName( path, filterProperties ) {
+ def outputName = path.toString()
+ def log = "${Thread.currentThread().name} ${outputName}"
+ filterProperties.each { key, value ->
+ outputName = outputName.replaceAll( /\$\{${key}}/, value.toString() )
+ log+= " (${key}=${value.toString()})-> ${outputName}"
+ }
+// println "${log} = ${outputName}"
+ return outputName
+ }
+
+
+}
+
diff --git a/grarchetype-common/src/main/groovy/org/apache/maven/archetype/generator/DefaultFilesetArchetypeGenerator.groovy b/grarchetype-common/src/main/groovy/org/apache/maven/archetype/generator/DefaultFilesetArchetypeGenerator.groovy
new file mode 100644
index 0000000..7a3af88
--- /dev/null
+++ b/grarchetype-common/src/main/groovy/org/apache/maven/archetype/generator/DefaultFilesetArchetypeGenerator.groovy
@@ -0,0 +1,14 @@
+package org.apache.maven.archetype.generator
+
+/**
+ *
+ * @author rafale
+ * @plexus.component role-hint="fileset"
+ */
+class DefaultFilesetArchetypeGenerator
+extends AbstractFilesetArchetypeGenerator {
+ def loadArchetypeDescriptor( File archetypeFile ) {println"DefaultFilesetArchetypeGenerator ${archetypeFile}"
+ new XmlSlurper().parse( archetypeArtifactManager.getFilesetArchetypeDescriptor( archetypeFile ) )
+ }
+}
+
diff --git a/grarchetype-common/src/main/groovy/org/apache/maven/archetype/generator/DefaultProjectGenerator.groovy b/grarchetype-common/src/main/groovy/org/apache/maven/archetype/generator/DefaultProjectGenerator.groovy
new file mode 100644
index 0000000..635c44a
--- /dev/null
+++ b/grarchetype-common/src/main/groovy/org/apache/maven/archetype/generator/DefaultProjectGenerator.groovy
@@ -0,0 +1,100 @@
+package org.apache.maven.archetype.generator
+import org.codehaus.plexus.logging.AbstractLogEnabled
+import org.apache.maven.archetype.ArchetypeGenerationRequest
+import org.apache.maven.archetype.artifact.ArchetypeArtifactManager
+
+/**
+ *
+ * @author raphaelpieroni
+ * @plexus.component
+ */
+class DefaultProjectGenerator
+extends AbstractLogEnabled
+implements ProjectGenerator {
+
+ /** @plexus.requirement */
+ ArchetypeArtifactManager artifactManager
+
+ /** @plexus.requirement role-hint="fileset" */
+ FilesetArchetypeGenerator filesetGenerator
+
+ /** @plexus.requirement role-hint="legacy" */
+ FilesetArchetypeGenerator oldGenerator
+
+ void generateProject( ArchetypeGenerationRequest request ) {
+
+ def mainArchetypeName = "${request.groupId}:${request.artifactId}:${request.version}"
+ logger.info "Generating project from archetype ${mainArchetypeName} into directory ${request.outputDirectory}"
+
+ def mainArchetypeFile = artifactManager.getArchetypeFile(
+ request.groupId, request.artifactId, request.version,
+ request.localRepository, request.repositories )
+println"generateProject ${artifactManager.isLegacyArchetype( mainArchetypeFile )} ${mainArchetypeFile}"
+ if( artifactManager.isLegacyArchetype( mainArchetypeFile ) ) {
+ logger.info "Archetype ${mainArchetypeName} is a legacy archetype"
+ request.archetypeFile = mainArchetypeFile
+
+ oldGenerator.generateProject request
+
+ } else {
+ logger.info "Archetype ${mainArchetypeName} is a fileset archetype"
+ request.archetypeFile = mainArchetypeFile
+
+ def archetypes = [mainArchetypeName:[file:mainArchetypeFile, generator:filesetGenerator]]
+ getNestedArchetypes mainArchetypeFile, archetypes, request.localRepository, request.repositories
+ request.archetypes = archetypes
+
+ logger.info "Found ${archetypes.size()} archetypes to generate the project with"
+ filesetGenerator.generateProject request
+ }
+ }
+
+ void getNestedArchetypes( archetypeFile, archetypes, localRepository, repositories ) {
+ logger.info "Searching for nested archetype of ${archetypeFile}"
+ def descriptor = new XmlSlurper().parse( artifactManager.getFilesetArchetypeDescriptor( archetypeFile ) )
+ def nestedArchetypes = []
+ descriptor.modules.module.each {
+ if( it.@nested.toBoolean() ) {
+ logger.info "Module ${it.@artifactId.toString()} is a nested archetype"
+ addArchetype it, archetypes, nestedArchetypes, localRepository, repositories
+ } else {
+ logger.info "Module ${it.@artifactId.toString()} is a regular module"
+ getInnerArchetypes it, archetypes, nestedArchetypes, localRepository, repositories
+ }
+ }
+ nestedArchetypes.each { nestedFile ->
+ getNestedArchetypes nestedFile, archetypes, localRepository, repositories
+ }
+ }
+
+ void getInnerArchetypes( module, archetypes, nestedArchetypes, localRepository, repositories ) {
+ module.modules.module.each {
+ if( it.@nested.toBoolean() ) {
+ logger.info "Module ${it.@artifactId.toString()} is a nested archetype"
+ addArchetype it, archetypes, nestedArchetypes, localRepository, repositories
+ } else {
+ logger.info "Module ${it.@artifactId.toString()} is a regular module"
+ getInnerArchetypes it, archetypes, nestedArchetypes, localRepository, repositories
+ }
+ }
+ }
+
+ void addArchetype( module, archetypes, nestedArchetypes, localRepository, repositories ) {
+ def moduleFile = artifactManager.getArchetypeFile(
+ module.@archetypeGroupId.toString(),
+ module.@archetypeArtifactId.toString(),
+ module.@archetypeVersion.toString(),
+ localRepository, repositories )
+ def archetypeName = "${module.@archetypeGroupId.toString()}:${module.@archetypeArtifactId.toString()}:${module.@archetypeVersion.toString()}"
+
+ if( artifactManager.isLegacyArchetype( moduleFile ) ) {
+ logger.info "Nested Archetype ${archetypeName} is a legacy archetype"
+ archetypes."${archetypeName}" = [file:moduleFile, generator:oldGenerator]
+ } else {
+ logger.info "Nested Archetype ${archetypeName} is a fileset archetype"
+ archetypes."${archetypeName}" = [file:moduleFile, generator:filesetGenerator]
+ nestedArchetypes << moduleFile
+ }
+ }
+}
+
diff --git a/grarchetype-common/src/main/groovy/org/apache/maven/archetype/generator/FilesetArchetypeGenerator.groovy b/grarchetype-common/src/main/groovy/org/apache/maven/archetype/generator/FilesetArchetypeGenerator.groovy
new file mode 100644
index 0000000..1a51781
--- /dev/null
+++ b/grarchetype-common/src/main/groovy/org/apache/maven/archetype/generator/FilesetArchetypeGenerator.groovy
@@ -0,0 +1,14 @@
+package org.apache.maven.archetype.generator
+import org.apache.maven.archetype.ArchetypeGenerationRequest
+
+/**
+ *
+ * @author rafale
+ */
+interface FilesetArchetypeGenerator {
+ static String ROLE = 'org.apache.maven.archetype.generator.FilesetArchetypeGenerator'
+
+ void generateProject( ArchetypeGenerationRequest request )
+
+}
+
diff --git a/grarchetype-common/src/main/groovy/org/apache/maven/archetype/generator/LegacyGenerator.groovy b/grarchetype-common/src/main/groovy/org/apache/maven/archetype/generator/LegacyGenerator.groovy
new file mode 100644
index 0000000..3bac602
--- /dev/null
+++ b/grarchetype-common/src/main/groovy/org/apache/maven/archetype/generator/LegacyGenerator.groovy
@@ -0,0 +1,85 @@
+package org.apache.maven.archetype.generator
+import groovy.xml.MarkupBuilder
+
+/**
+ *
+ * @author raphaelpieroni
+ * @plexus.component role-hint="legacy"
+ */
+class LegacyGenerator
+extends AbstractFilesetArchetypeGenerator {
+ def loadArchetypeDescriptor( File archetypeFile ) {println"LegacyGenerator ${archetypeFile}"
+ def oldDescriptor = new XmlSlurper().parse( archetypeArtifactManager.getLegacyArchetypeDescriptor( archetypeFile ) )
+
+ def filesetDescriptor = new StringWriter()
+ def filesetDescriptorBuilder = new MarkupBuilder( filesetDescriptor )
+
+ filesetDescriptorBuilder.'archetype-descriptor'( name:oldDescriptor.id.toString(), partial:getPartial(oldDescriptor) ) {
+ fileSets {
+ oldDescriptor?.sources?.source.each { source ->
+ fileSet( engine:'velocity', packaged:true, filtered:true ) {
+ directory getSourceDirectory( source.toString() )
+ includes {
+ include getSourcePath( source.toString() )
+ }
+ }
+ }
+ oldDescriptor?.testSources?.source.each { source ->
+ fileSet( engine:'velocity', packaged:true, filtered:true ) {
+ directory getSourceDirectory( source.toString() )
+ includes {
+ include getSourcePath( source.toString() )
+ }
+ }
+ }
+ oldDescriptor?.resources?.resource.each { resource ->
+ fileSet( engine:'velocity', packaged:false, filtered:getFiltered( resource?.@filtered.toString() ) ) {
+ directory getResourceDirectory( resource.toString() )
+ includes {
+ include getResourcePath( resource.toString() )
+ }
+ }
+ }
+ oldDescriptor?.siteResources?.resource.each { resource ->
+ fileSet( engine:'velocity', packaged:false, filtered:getFiltered( resource?.@filtered.toString() ) ) {
+ directory getResourceDirectory( resource.toString() )
+ includes {
+ include getResourcePath( resource.toString() )
+ }
+ }
+ }
+ }
+ }
+
+// filesetDescriptor = filesetDescriptor.toString()
+ logger.error"Using translated descriptor ${filesetDescriptor.toString()}"
+
+ new XmlSlurper().parseText( filesetDescriptor.toString() )
+ }
+
+ def getPartial( oldDescriptor ) {
+ if(oldDescriptor.allowPartial.toString()) return oldDescriptor.allowPartial.toString()
+ return false
+ }
+
+ def getSourceDirectory( source ) {
+ source.substring 0, source.lastIndexOf( 'java/' ) + 4
+ }
+
+ def getResourceDirectory( source ) {
+ source.substring 0, source.lastIndexOf( '/' )
+ }
+
+ def getSourcePath( source ) {
+ source.substring source.lastIndexOf( 'java/' ) + 5
+ }
+
+ def getResourcePath( source ) {
+ source.substring source.lastIndexOf( '/' ) + 1
+ }
+
+ def getFiltered( filtered ) {
+ filtered ? filtered : true
+ }
+}
+
diff --git a/grarchetype-common/src/main/groovy/org/apache/maven/archetype/generator/ProjectGenerator.groovy b/grarchetype-common/src/main/groovy/org/apache/maven/archetype/generator/ProjectGenerator.groovy
new file mode 100644
index 0000000..5763fac
--- /dev/null
+++ b/grarchetype-common/src/main/groovy/org/apache/maven/archetype/generator/ProjectGenerator.groovy
@@ -0,0 +1,14 @@
+package org.apache.maven.archetype.generator
+import org.apache.maven.archetype.ArchetypeGenerationRequest
+
+/**
+ *
+ * @author raphaelpieroni
+ */
+interface ProjectGenerator {
+ static String ROLE = 'org.apache.maven.archetype.generator.ProjectGenerator'
+
+ void generateProject( ArchetypeGenerationRequest request )
+
+}
+
diff --git a/grarchetype-common/src/main/groovy/org/apache/maven/archetype/pom/DefaultPomManager.groovy b/grarchetype-common/src/main/groovy/org/apache/maven/archetype/pom/DefaultPomManager.groovy
new file mode 100644
index 0000000..61e28f5
--- /dev/null
+++ b/grarchetype-common/src/main/groovy/org/apache/maven/archetype/pom/DefaultPomManager.groovy
@@ -0,0 +1,265 @@
+package org.apache.maven.archetype.pom
+import org.codehaus.plexus.logging.AbstractLogEnabled
+import org.apache.maven.model.io.xpp3.MavenXpp3Reader
+import org.apache.maven.model.Model
+import org.jdom.input.SAXBuilder
+import org.jdom.Document
+import org.jdom.output.Format
+import org.apache.maven.model.io.jdom.MavenJDOMWriter
+import org.apache.maven.model.Build
+import org.apache.maven.model.Reporting
+import org.apache.maven.model.ModelBase
+import org.apache.maven.model.DependencyManagement
+
+/**
+ *
+ * @author rafale
+ * @plexus.component
+ */
+class DefaultPomManager extends AbstractLogEnabled implements PomManager {
+
+ def loadModel( File pomFile ) {
+ def model
+ pomFile.newReader( "UTF-8" ).withReader {
+ model = new MavenXpp3Reader().read( it, false )
+ }
+ return model
+ }
+
+ def loadModel(String pomString){
+ def model
+ new StringReader( pomString ).withReader {
+ model = new MavenXpp3Reader().read( it, false )
+ }
+ return model
+ }
+
+ void writeModel( File pomFile, Model newModel ) {
+ def pomDocument
+ pomFile.newInputStream().withStream {
+ pomDocument = new SAXBuilder().build( it )
+ }
+
+ def encoding = newModel.modelEncoding?: 'UTF-8'
+ pomFile.newWriter( encoding ).withWriter {
+ new MavenJDOMWriter().write( newModel, pomDocument, it, Format.rawFormat.setEncoding( encoding ) )
+ }
+ }
+
+ def mergeModel( Model initialModel, Model addedModel ) {
+
+ println"merge "+initialModel?.dependencies.dump()
+ println"mergeX "+initialModel?.properties.dump()
+
+
+// // Potential merging
+//
+// initialModel.getModelEncoding (); // keep initial
+// initialModel.getModelVersion (); // keep initial
+//
+// initialModel.getGroupId (); // keep initial
+// initialModel.getArtifactId (); // keep initial
+// initialModel.getVersion (); // keep initial
+// initialModel.getParent (); // keep initial
+//
+// initialModel.getId (); // keep initial
+// initialModel.getName (); // keep initial
+// initialModel.getInceptionYear (); // keep initial
+// initialModel.getDescription (); // keep initial
+// initialModel.getUrl (); // keep initial
+// initialModel.getLicenses (); // keep initial
+// initialModel.getProperties (); // merged
+ mergeProperties initialModel, addedModel
+//
+// initialModel.getOrganization (); // keep initial
+// initialModel.getMailingLists (); // keep initial
+// initialModel.getContributors (); // keep initial
+// initialModel.getDevelopers (); // keep initial
+//
+// initialModel.getScm (); // keep initial
+// initialModel.getCiManagement (); // keep initial
+// initialModel.getDistributionManagement (); // keep initial
+// initialModel.getIssueManagement (); // keep initial
+//
+// initialModel.getPackaging (); // keep initial
+// initialModel.getDependencies (); // merged
+ mergeDependencies initialModel, addedModel
+// initialModel.getDependencyManagement (); // merged
+ mergeDependencyManagement initialModel, addedModel
+// initialModel.getPrerequisites ().getMaven (); // keep initial
+// initialModel.getPrerequisites ().getModelEncoding (); // keep initial
+//
+// initialModel.getModules (); // keep initial
+// initialModel.getRepositories (); // merged
+ mergeRepositories initialModel, addedModel
+// initialModel.getPluginRepositories (); // merged
+ mergePluginRepositories initialModel, addedModel
+//
+// initialModel.getBuild ().getDefaultGoal (); // keep initial
+// initialModel.getBuild ().getFinalName (); // keep initial
+// initialModel.getBuild ().getModelEncoding (); // keep initial
+// initialModel.getBuild ().getFilters ();
+// initialModel.getBuild ().getDirectory (); // keep initial
+// initialModel.getBuild ().getOutputDirectory (); // keep initial
+// initialModel.getBuild ().getSourceDirectory (); // keep initial
+//////// initialModel.getBuild ().getResources ();
+// initialModel.getBuild ().getScriptSourceDirectory (); // keep initial
+// initialModel.getBuild ().getTestOutputDirectory (); // keep initial
+//////// initialModel.getBuild ().getTestResources ();
+// initialModel.getBuild ().getTestSourceDirectory (); // keep initial
+//////// initialModel.getBuild ().getExtensions ();
+// initialModel.getBuild ().getPluginsAsMap (); // merged
+ mergeBuildPlugins initialModel, addedModel
+// initialModel.getBuild ().getPluginManagement (); // merged
+ mergeBuildPluginManagement initialModel, addedModel
+//
+// initialModel.getReporting ().getModelEncoding (); // keep initial
+// initialModel.getReporting ().getOutputDirectory (); // keep initial
+// initialModel.getReporting ().getReportPluginsAsMap (); // merged
+ mergeReportPlugins initialModel, addedModel
+
+//////// initialModel.getProfiles ();
+
+ return initialModel
+ }
+
+ def mergeProperties( Model initialModel, Model addedModel ) {
+ if( !addedModel.properties || !addedModel.properties.size() == 0 ) return
+ if( !initialModel.properties ) initialModel.properties = addedModel.properties
+ else {
+ addedModel.properties.each { key, value ->
+ if( initialModel.properties.containsKey( key ) ) {
+ logger.warn "property $key not over written"
+ } else {
+ initialModel.properties[key] = value
+ }
+ }
+ }
+ }
+
+ def mergeDependencies( Model initialModel, Model addedModel ) {
+ if( !addedModel.dependencies || addedModel.dependencies.size() == 0 ) return
+ if( !initialModel.dependencies ) initialModel.dependencies = addedModel.dependencies
+ else {
+ def initialDependencies = getDependencyMap( initialModel.dependencies )
+ getDependencyMap( addedModel.dependencies ).each { key, dependency ->
+ if( initialDependencies.containsKey( key ) ) {
+ logger.warn "dependency $key not over written"
+ } else {
+ initialModel.dependencies.add dependency
+ }
+ }
+ }
+ }
+ def getDependencyMap( dependencies ) {
+ def map = [:]
+ dependencies.each {
+ map."${it.groupId}:${it.artifactId}" = it
+ }
+ return map
+ }
+
+ def mergeDependencyManagement( Model initialModel, Model addedModel ) {
+ if( !addedModel.dependencyManagement ||
+ !addedModel.dependencyManagement.dependencies ||
+ addedModel.dependencyManagement.dependencies.size() == 0 ) return
+ if( !initialModel.dependencyManagement ) initialModel.dependencyManagement = new DependencyManagement()
+ if( !initialModel.dependencyManagement.dependencies ) initialModel.dependencyManagement.dependencies = addedModel.dependencyManagement.dependencies
+ else {
+ def initialDependencies = getDependencyMap( initialModel.dependencyManagement.dependencies )
+ getDependencyMap( addedModel.dependencyManagement.dependencies ).each { key, dependency ->
+ if( initialDependencies.containsKey( key ) ) {
+ logger.warn "dependency $key in dependencyManagement not over written"
+ } else {
+ initialModel.dependencyManagement.dependencies.add dependency
+ }
+ }
+ }
+ }
+
+ def mergeRepositories( Model initialModel, Model addedModel ) {
+ if( !addedModel.repositories || addedModel.repositories.size() == 0 ) return
+ if( !initialModel.repositories ) initialModel.repositories = addedModel.repositories
+ else {
+ def initialRepositories = getRepositoryMap( initialModel.repositories )
+ getRepositoryMap( addedModel.repositories ).each { key, repository ->
+ if( initialRepositories.containsKey( key ) ) {
+ logger.warn "repository $key not over written"
+ } else {
+ initialModel.repositories.add repository
+ }
+ }
+ }
+ }
+ def getRepositoryMap( repositories ) {
+ def map = [:]
+ repositories.each {
+ map."${it.id}" = it
+ }
+ return map
+ }
+
+ def mergePluginRepositories( Model initialModel, Model addedModel ) {
+ if( !addedModel.pluginRepositories || addedModel.pluginRepositories.size() == 0 ) return
+ if( !initialModel.pluginRepositories ) initialModel.pluginRepositories = addedModel.pluginRepositories
+ else {
+ def initialPluginRepositories = getRepositoryMap( initialModel.pluginRepositories )
+ getRepositoryMap( addedModel.pluginRepositories ).each { key, pluginRepository ->
+ if( initialPluginRepositories.containsKey( key ) ) {
+ logger.warn "pluginRepository $key not over written"
+ } else {
+ initialModel.pluginRepositories.add pluginRepository
+ }
+ }
+ }
+ }
+
+ def mergeBuildPlugins( Model initialModel, Model addedModel ) {
+ if( !addedModel.build ) return
+ if( !addedModel.build.pluginsAsMap || addedModel.build.pluginsAsMap.size() == 0 ) return
+ if( !initialModel.build ) initialModel.build = new Build()
+ def initialPlugins = initialModel.build?.pluginsAsMap?:[:]
+ addedModel.build.pluginsAsMap.each { key, plugin ->
+ if( initialPlugins.containsKey( key ) ) {
+ logger.warn "plugin $key not over written"
+ } else {
+ initialModel.build.addPlugin plugin
+ }
+ }
+ }
+
+ def mergeBuildPluginManagement( Model initialModel, Model addedModel ) {
+ if( !addedModel.build ) return
+ if( !addedModel.build.pluginManagement ) return
+ if( !addedModel.build.pluginManagement.plugins || addedModel.build.pluginManagement.plugins.size() == 0 ) return
+ if( !initialModel.build ) initialModel.build = new Build()
+ if( !initialModel.build.pluginManagement ) initialModel.build.pluginManagement = addedModel.build.pluginManagement
+ else {
+ def initialPlugins = getDependencyMap( initialModel.build.pluginManagement.plugins )
+ getDependencyMap( addedModel.build.pluginManagement.plugins ).each { key, plugin ->
+ if( initialPlugins.containsKey( key ) ) {
+ logger.warn "plugin $key in pluginManagement not over written"
+ } else {
+ initialModel.build.pluginManagement.plugins.add plugin
+ }
+ }
+ }
+
+ }
+
+ def mergeReportPlugins( Model initialModel, Model addedModel ) {
+ if( !addedModel.reporting ) return
+ if( !addedModel.reporting.reportPluginsAsMap || addedModel.reporting.reportPluginsAsMap.size() == 0 ) return
+ if( !initialModel.reporting ) initialModel.reporting = new Reporting()
+ def initialReportPlugins = initialModel.reporting.reportPluginsAsMap?:[:]
+
+ addedModel.reporting.reportPluginsAsMap.each { key, plugin ->
+ if( initialReportPlugins.containsKey( key ) ) {
+ logger.warn "report plugin $key not over written"
+ } else {
+ initialModel.reporting.addPlugin plugin
+ }
+ }
+ }
+}
+
diff --git a/grarchetype-common/src/main/groovy/org/apache/maven/archetype/pom/PomManager.groovy b/grarchetype-common/src/main/groovy/org/apache/maven/archetype/pom/PomManager.groovy
new file mode 100644
index 0000000..300ec47
--- /dev/null
+++ b/grarchetype-common/src/main/groovy/org/apache/maven/archetype/pom/PomManager.groovy
@@ -0,0 +1,16 @@
+package org.apache.maven.archetype.pom
+import org.apache.maven.model.Model
+
+/**
+ *
+ * @author rafale
+ */
+interface PomManager {
+ String ROLE = 'org.apache.maven.archetype.pom.PomManager'
+
+ def loadModel( File pomFile )
+ def loadModel( String pomString )
+ void writeModel( File pomFile, Model newModel )
+ def mergeModel( Model initialModel, Model addedModel )
+}
+
diff --git a/grarchetype-common/src/main/groovy/org/apache/maven/archetype/util/DefaultRepositoryCreator.groovy b/grarchetype-common/src/main/groovy/org/apache/maven/archetype/util/DefaultRepositoryCreator.groovy
new file mode 100644
index 0000000..19244c6
--- /dev/null
+++ b/grarchetype-common/src/main/groovy/org/apache/maven/archetype/util/DefaultRepositoryCreator.groovy
@@ -0,0 +1,52 @@
+/*
+ * Copyright 2009 raphaelpieroni.
+ *
+ * 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.
+ * under the License.
+ */
+
+package org.apache.maven.archetype.util
+import org.apache.maven.artifact.repository.ArtifactRepositoryFactory
+import org.apache.maven.artifact.repository.ArtifactRepositoryPolicy
+import org.codehaus.plexus.logging.AbstractLogEnabled
+import org.apache.maven.artifact.repository.layout.ArtifactRepositoryLayout
+import org.apache.maven.artifact.repository.DefaultArtifactRepository
+
+/**
+ *
+ * @author raphaelpieroni
+ * @plexus.component
+ */
+class DefaultRepositoryCreator
+extends AbstractLogEnabled
+implements RepositoryCreator{
+
+ /** @plexus.requirement */
+ private ArtifactRepositoryFactory artifactRepositoryFactory
+
+ /** @plexus.requirement roleHint="default" */
+ private ArtifactRepositoryLayout defaultArtifactRepositoryLayout
+
+ def createRepository( String repository ) {
+ String updatePolicyFlag = ArtifactRepositoryPolicy.UPDATE_POLICY_ALWAYS
+ String checksumPolicyFlag = ArtifactRepositoryPolicy.CHECKSUM_POLICY_WARN
+ return artifactRepositoryFactory.createArtifactRepository(
+ "archetype-repository",
+ repository,
+ defaultArtifactRepositoryLayout,
+ new ArtifactRepositoryPolicy( true, updatePolicyFlag, checksumPolicyFlag ),
+ new ArtifactRepositoryPolicy( true, updatePolicyFlag, checksumPolicyFlag )
+ )
+ }
+}
+
diff --git a/grarchetype-common/src/main/groovy/org/apache/maven/archetype/util/RepositoryCreator.groovy b/grarchetype-common/src/main/groovy/org/apache/maven/archetype/util/RepositoryCreator.groovy
new file mode 100644
index 0000000..2d9d50a
--- /dev/null
+++ b/grarchetype-common/src/main/groovy/org/apache/maven/archetype/util/RepositoryCreator.groovy
@@ -0,0 +1,12 @@
+package org.apache.maven.archetype.util
+
+/**
+ *
+ * @author raphaelpieroni
+ */
+interface RepositoryCreator {
+ static String ROLE = 'org.apache.maven.archetype.util.RepositoryCreator'
+
+ def createRepository( String repository )
+}
+
diff --git a/grarchetype-common/src/main/groovy/org/apache/maven/archetype/util/Scanner.groovy b/grarchetype-common/src/main/groovy/org/apache/maven/archetype/util/Scanner.groovy
new file mode 100644
index 0000000..35cd4d2
--- /dev/null
+++ b/grarchetype-common/src/main/groovy/org/apache/maven/archetype/util/Scanner.groovy
@@ -0,0 +1,31 @@
+package org.apache.maven.archetype.util
+import org.codehaus.plexus.util.SelectorUtils
+
+/**
+ *
+ * @author rafale
+ */
+class Scanner {
+ def fileset
+
+ def match( path ) {
+ included( path ) && !excluded( path )
+ }
+ def included( path ) {
+ matchPatterns( path, fileset.includes.include )
+ }
+ def excluded( path ) {
+ matchPatterns( path, fileset.excludes.exclude )
+ }
+ def matchPatterns( path, patterns ) {
+ def found = false
+ patterns.each{ pattern ->
+ found = found || matchPattern( path, pattern.text().toString() )
+ }
+ return found
+ }
+ def matchPattern( path, pattern ) {
+ SelectorUtils.matchPath pattern, path, true
+ }
+}
+
diff --git a/grarchetype-common/src/main/groovy/org/gparallelizer/AsyncException.groovy b/grarchetype-common/src/main/groovy/org/gparallelizer/AsyncException.groovy
new file mode 100644
index 0000000..c58a9dc
--- /dev/null
+++ b/grarchetype-common/src/main/groovy/org/gparallelizer/AsyncException.groovy
@@ -0,0 +1,44 @@
+package org.gparallelizer
+
+import java.util.List
+
+/**
+ * This class wraps multiple exception, which occured in concurrently run code inside one of the <i>AsyncInvokerUtil</i> methods.
+ * @see AsyncInvokerUtil
+ *
+ * @author Vaclav Pech
+ * Date: Nov 17, 2008
+ */
+public class AsyncException extends RuntimeException {
+ final List<Throwable> concurrentExceptions
+
+ public AsyncException(String message, List<Throwable> concurrentExceptions) {
+ super(message)
+ this.concurrentExceptions = concurrentExceptions
+ }
+
+ public List<Throwable> getConcurrentExceptions() {
+ return concurrentExceptions
+ }
+
+ @Override
+ public String getMessage() {
+ return "${super.getMessage()} ${buildMessage()}"
+ }
+
+ @Override
+ public String toString() {
+ return buildMessage()
+ }
+
+ private String buildMessage() {
+ final StringBuilder sb = new StringBuilder()
+ sb.append("${Thread.currentThread().name} AsyncException")
+ sb.append("{concurrentExceptions=").append("[\n")
+ concurrentExceptions.each {
+ sb.append(it.toString()).append("\n")
+ }
+ sb.append("]}")
+ return sb.toString()
+ }
+}
diff --git a/grarchetype-common/src/main/groovy/org/gparallelizer/AsyncInvokerUtil.groovy b/grarchetype-common/src/main/groovy/org/gparallelizer/AsyncInvokerUtil.groovy
new file mode 100644
index 0000000..11ebd1b
--- /dev/null
+++ b/grarchetype-common/src/main/groovy/org/gparallelizer/AsyncInvokerUtil.groovy
@@ -0,0 +1,253 @@
+package org.gparallelizer
+
+import java.util.concurrent.Callable
+import java.util.concurrent.CountDownLatch
+import java.util.concurrent.ExecutorService
+import java.util.concurrent.Future
+import java.util.concurrent.atomic.AtomicBoolean
+import java.lang.Thread.UncaughtExceptionHandler
+
+/**
+ * This class forms the core of the DSL initialized by <i>Asynchronizer</i>. The static methods of <i>AsyncInvokerUtil</i>
+ * get attached to their first arguments (the Groovy Category mechanism) and can be then invoked as if they were part of
+ * the argument classes.
+ * @see org.gparallelizer.Asynchronizer
+ *
+ * @author Vaclav Pech
+ * Date: Oct 23, 2008
+ */
+public class AsyncInvokerUtil {
+ /**
+ * Shedules the supplied closure for processing in the underlying thread pool.
+ */
+ private static Future callAsync(Closure task) {
+ final ExecutorService pool = Asynchronizer.retrieveCurrentPool()
+ if (!pool) throw new IllegalStateException("No ExecutorService available for the current thread.")
+ return pool.submit(task as Callable)
+ }
+
+ /**
+ * Calls a closure in a separate thread supplying the given arguments, returning a future for the potential return value,
+ */
+ public static Future callAsync(Closure cl, Object ... args) {
+ callAsync {cl(args)}
+ }
+
+ /**
+ * Submits the task for asynchronous processing returning the Future received from the executor service.
+ * Allows for the followitn syntax:
+ * <pre>
+ * executorService << {println 'Inside parallel task'}* </pre>
+ */
+ public static Future leftShift(ExecutorService executorService, Closure task) {
+ return executorService.submit(task as Callable)
+ }
+
+ /**
+ * Creates an asynchronous variant of the supplied closure, which, when invoked returns a future for the potential return value
+ */
+ public static Closure async(Closure cl) {
+ return {Object ... args -> callAsync(cl, args)}
+ }
+
+ /**
+ * Starts multiple closures in separate threads, collecting their return values
+ * If an exception is thrown from the closure when called on any of the collection's elements,
+ * it will be rethrown in the calling thread when it calls the Future.get() method.
+ * @throws AsyncException If any of the collection's elements causes the closure to throw an exception. The original exceptions will be stored in the AsyncException's concurrentExceptions field.
+ */
+ public static List<Object> doInParallel(Closure ... closures) {
+ return processResult(executeInParallel(closures))
+ }
+
+ /**
+ * Starts multiple closures in separate threads, collecting Futures for their return values
+ * If an exception is thrown from the closure when called on any of the collection's elements,
+ * it will be rethrown in the calling thread when it calls the Future.get() method.
+ */
+ public static List<Future<Object>> executeInParallel(Closure ... closures) {
+ Asynchronizer.withAsynchronizer(closures.size()) {ExecutorService executorService ->
+ List<Future<Object>> result = closures.collect {cl ->
+ return executorService.submit({
+ return cl.call()
+ } as Callable<Object>)
+ }
+ return result
+ }
+ }
+
+ /**
+ * Starts multiple closures in separate threads, using a new thread for the startup.
+ * If any of the collection's elements causes the closure to throw an exception, an AsyncException is reported using System.err.
+ * The original exceptions will be stored in the AsyncException's concurrentExceptions field.
+ */
+ public static void startInParallel(Closure ... closures) {
+ startInParallel(createDefaultUncaughtExceptionHandler(), closures)
+ }
+
+ /**
+ * Starts multiple closures in separate threads, using a new thread for the startup.
+ * If any of the collection's elements causes the closure to throw an exception, an AsyncException is reported to the supplied instance of UncaughtExceptionHandler.
+ * The original exceptions will be stored in the AsyncException's concurrentExceptions field.
+ * @return The thread that submits the closures to the thread executor service so that the caller can take ownership of it and e.g. call <i>join()</i> on it to wait for all the closures to finish processing.
+ */
+ public static Thread startInParallel(java.lang.Thread.UncaughtExceptionHandler uncaughtExceptionHandler, Closure ... closures) {
+ final Thread thread = new Thread({
+ doInParallel(closures)
+ } as Runnable)
+ thread.daemon = false
+ thread.uncaughtExceptionHandler = uncaughtExceptionHandler
+ thread.start()
+ return thread
+ }
+
+ /**
+ * Iterates over a collection/object with the <i>each()</i> method using an asynchronous variant of the supplied closure
+ * to evaluate each collection's element. A CountDownLatch is used to make the calling thread wait for all the results.
+ * After this method returns, all the closures have been finished and all the potential shared resources have been updated
+ * by the threads.
+ * It's important to protect any shared resources used by the supplied closure from race conditions caused by multi-threaded access.
+ * Example:
+ * Asynchronizer.withAsynchronizer(5) {ExecutorService service ->
+ * def result = Collections.synchronizedSet(new HashSet())
+ * service.eachAsync([1, 2, 3, 4, 5]) {Number number -> result.add(number * 10)}* assertEquals(new HashSet([10, 20, 30, 40, 50]), result)
+ *}* Note that the <i>result</i> variable is synchronized to prevent race conditions between multiple threads.
+ * Alternatively a DSL can be used to simplify the code. All collections/objects within the <i>withAsynchronizer</i> block
+ * have a new <i>eachAsync(Closure cl)</i> method, which delegates to the <i>AsyncInvokerUtil</i> class.
+ * Asynchronizer.withAsynchronizer(5) {ExecutorService service ->
+ * def result = Collections.synchronizedSet(new HashSet())
+ * [1, 2, 3, 4, 5].eachAsync { Number number -> result.add(number * 10) }* assertEquals(new HashSet([10, 20, 30, 40, 50]), result)
+ *}* @throws AsyncException If any of the collection's elements causes the closure to throw an exception. The original exceptions will be stored in the AsyncException's concurrentExceptions field.
+ */
+ public static def eachAsync(Object collection, Closure cl) {
+ final CountDownLatch latch = new CountDownLatch(collection.size());
+ final List<Throwable> exceptions = Collections.synchronizedList(new ArrayList<Throwable>())
+
+ def result = collection.each(async({Object ... args ->
+ try {
+ cl(args)
+ } catch (Throwable e) {
+ exceptions.add(e)
+ } finally {
+ latch.countDown()
+ }
+ }))
+ latch.await()
+ if (!exceptions.empty) throw new AsyncException("Some asynchronous operations failed. ${exceptions}", exceptions)
+ else return result
+ }
+
+ /**
+ * Iterates over a collection/object with the <i>collect()</i> method using an asynchronous variant of the supplied closure
+ * to evaluate each collection's element.
+ * After this method returns, all the closures have been finished and the caller can safely use the result.
+ * It's important to protect any shared resources used by the supplied closure from race conditions caused by multi-threaded access.
+ * Asynchronizer.withAsynchronizer(5) {ExecutorService service ->
+ * def result = service.collectAsync([1, 2, 3, 4, 5]){Number number -> number * 10}* assertEquals(new HashSet([10, 20, 30, 40, 50]), new HashSet((Collection)result))
+ *}*
+ * Alternatively a DSL can be used to simplify the code. All collections/objects within the <i>withAsynchronizer</i> block
+ * have a new <i>collectAsync(Closure cl)</i> method, which delegates to the <i>AsyncInvokerUtil</i> class.
+ * Asynchronizer.withAsynchronizer(5) {ExecutorService service ->
+ * def result = [1, 2, 3, 4, 5].collectAsync{Number number -> number * 10}* assertEquals(new HashSet([10, 20, 30, 40, 50]), new HashSet((Collection)result))
+ *}* @throws AsyncException If any of the collection's elements causes the closure to throw an exception. The original exceptions will be stored in the AsyncException's concurrentExceptions field.
+ */
+ public static def collectAsync(Object collection, Closure cl) {
+ return processResult(collection.collect(async(cl)))
+ }
+
+ /**
+ * Performs the <i>findAll()</i> operation using an asynchronous variant of the supplied closure
+ * to evaluate each collection's/object's element.
+ * After this method returns, all the closures have been finished and the caller can safely use the result.
+ * It's important to protect any shared resources used by the supplied closure from race conditions caused by multi-threaded access.
+ * Asynchronizer.withAsynchronizer(5) {ExecutorService service ->
+ * def result = service.findAllAsync([1, 2, 3, 4, 5]){Number number -> number > 2}* assertEquals(new HashSet([3, 4, 5]), new HashSet((Collection)result))
+ *}*
+ * Alternatively a DSL can be used to simplify the code. All collections/objects within the <i>withAsynchronizer</i> block
+ * have a new <i>findAllAsync(Closure cl)</i> method, which delegates to the <i>AsyncInvokerUtil</i> class.
+ * Asynchronizer.withAsynchronizer(5) {ExecutorService service ->
+ * def result = [1, 2, 3, 4, 5].findAllAsync{Number number -> number > 2}* assertEquals(new HashSet([3, 4, 5]), new HashSet((Collection)result))
+ *}* @throws AsyncException If any of the collection's elements causes the closure to throw an exception. The original exceptions will be stored in the AsyncException's concurrentExceptions field.
+ */
+ public static def findAllAsync(Object collection, Closure cl) {
+ collectAsync(collection, {if (cl(it)) return it else return null}).findAll {it != null}
+ }
+
+ /**
+ * Performs the <i>find()</i> operation using an asynchronous variant of the supplied closure
+ * to evaluate each collection's/object's element.
+ * After this method returns, all the closures have been finished and the caller can safely use the result.
+ * It's important to protect any shared resources used by the supplied closure from race conditions caused by multi-threaded access.
+ * Asynchronizer.withAsynchronizer(5) {ExecutorService service ->
+ * def result = service.findAsync([1, 2, 3, 4, 5]){Number number -> number > 2}* assert result in [3, 4, 5]
+ *}*
+ * Alternatively a DSL can be used to simplify the code. All collections/objects within the <i>withAsynchronizer</i> block
+ * have a new <i>findAllAsync(Closure cl)</i> method, which delegates to the <i>AsyncInvokerUtil</i> class.
+ * Asynchronizer.withAsynchronizer(5) {ExecutorService service ->
+ * def result = [1, 2, 3, 4, 5].findAsync{Number number -> number > 2}* assert result in [3, 4, 5]
+ *}* @throws AsyncException If any of the collection's elements causes the closure to throw an exception. The original exceptions will be stored in the AsyncException's concurrentExceptions field.
+ */
+ public static def findAsync(Object collection, Closure cl) {
+ collectAsync(collection, {if (cl(it)) return it else return null}).find {it != null}
+ }
+
+ /**
+ * Performs the <i>all()</i> operation using an asynchronous variant of the supplied closure
+ * to evaluate each collection's/object's element.
+ * After this method returns, all the closures have been finished and the caller can safely use the result.
+ * It's important to protect any shared resources used by the supplied closure from race conditions caused by multi-threaded access.
+ * Asynchronizer.withAsynchronizer(5) {ExecutorService service ->
+ * assert service.allAsync([1, 2, 3, 4, 5]){Number number -> number > 0}* assert !service.allAsync([1, 2, 3, 4, 5]){Number number -> number > 2}*}*
+ * Alternatively a DSL can be used to simplify the code. All collections/objects within the <i>withAsynchronizer</i> block
+ * have a new <i>findAllAsync(Closure cl)</i> method, which delegates to the <i>AsyncInvokerUtil</i> class.
+ * Asynchronizer.withAsynchronizer(5) {ExecutorService service ->
+ * assert [1, 2, 3, 4, 5].allAsync{Number number -> number > 0}* assert ![1, 2, 3, 4, 5].allAsync{Number number -> number > 2}*}* @throws AsyncException If any of the collection's elements causes the closure to throw an exception. The original exceptions will be stored in the AsyncException's concurrentExceptions field.
+ */
+ public static boolean allAsync(Object collection, Closure cl) {
+ final AtomicBoolean flag = new AtomicBoolean(true)
+ eachAsync(collection, {value -> if (!cl(value)) flag.set(false)})
+ return flag.get()
+ }
+
+
+ /**
+ * Performs the <i>any()</i> operation using an asynchronous variant of the supplied closure
+ * to evaluate each collection's/object's element.
+ * After this method returns, all the closures have been finished and the caller can safely use the result.
+ * It's important to protect any shared resources used by the supplied closure from race conditions caused by multi-threaded access.
+ * Asynchronizer.withAsynchronizer(5) {ExecutorService service ->
+ * assert service.anyAsync([1, 2, 3, 4, 5]){Number number -> number > 2}* assert !service.anyAsync([1, 2, 3, 4, 5]){Number number -> number > 6}*}*
+ * Alternatively a DSL can be used to simplify the code. All collections/objects within the <i>withAsynchronizer</i> block
+ * have a new <i>findAllAsync(Closure cl)</i> method, which delegates to the <i>AsyncInvokerUtil</i> class.
+ * Asynchronizer.withAsynchronizer(5) {ExecutorService service ->
+ * assert [1, 2, 3, 4, 5].anyAsync{Number number -> number > 2}* assert ![1, 2, 3, 4, 5].anyAsync{Number number -> number > 6}*}* @throws AsyncException If any of the collection's elements causes the closure to throw an exception. The original exceptions will be stored in the AsyncException's concurrentExceptions field.
+ */
+ public static boolean anyAsync(Object collection, Closure cl) {
+ final AtomicBoolean flag = new AtomicBoolean(false)
+ eachAsync(collection, {if (cl(it)) flag.set(true)})
+ return flag.get()
+ }
+
+ private static List<Object> processResult(List<Future<Object>> futures) {
+ final List<Throwable> exceptions = Collections.synchronizedList(new ArrayList<Throwable>())
+
+ final List<Object> result = futures.collect {
+ try {
+ return it.get()
+ } catch (Throwable e) {
+ exceptions.add(e)
+ return e
+ }
+ }
+
+ if (!exceptions.empty) throw new AsyncException("Some asynchronous operations failed. ${exceptions}", exceptions)
+ else return result
+ }
+
+ private static UncaughtExceptionHandler createDefaultUncaughtExceptionHandler() {
+ return {Thread failedThread, Throwable throwable ->
+ System.err.println "Error processing background thread ${failedThread.name}: ${throwable.message}"
+ throwable.printStackTrace(System.err)
+ } as UncaughtExceptionHandler
+ }
+}
diff --git a/grarchetype-common/src/main/groovy/org/gparallelizer/Asynchronizer.groovy b/grarchetype-common/src/main/groovy/org/gparallelizer/Asynchronizer.groovy
new file mode 100644
index 0000000..61c70dc
--- /dev/null
+++ b/grarchetype-common/src/main/groovy/org/gparallelizer/Asynchronizer.groovy
@@ -0,0 +1,197 @@
+package org.gparallelizer
+
+import java.util.concurrent.ExecutorService
+import java.util.concurrent.Executors
+import java.util.concurrent.ThreadFactory
+import java.util.concurrent.TimeUnit
+
+/**
+ * Enables a ExecutorService-based DSL on closures, objects and collections.
+ * E.g.
+ * Asynchronizer.withAsynchronizer(5) {ExecutorService service ->
+ * Collection<Future> result = [1, 2, 3, 4, 5].collect({it * 10}.async())
+ * assertEquals(new HashSet([10, 20, 30, 40, 50]), new HashSet((Collection)result*.get()))
+ * }
+ *
+ * Asynchronizer.withAsynchronizer(5) {ExecutorService service ->
+ * def result = [1, 2, 3, 4, 5].findAsync{Number number -> number > 2}
+ * assert result in [3, 4, 5]
+ * }
+ *
+ * @author Vaclav Pech
+ * Date: Oct 23, 2008
+ */
+class Asynchronizer {
+
+ private static ThreadLocal<ExecutorService> currentInvoker=new ThreadLocal<ExecutorService>()
+
+ protected static ExecutorService retrieveCurrentPool() {
+ currentInvoker.get()
+ }
+
+ private static createPool() {
+ return createPool(Runtime.getRuntime().availableProcessors() + 1)
+ }
+
+ private static createPool(int poolSize) {
+ return createPool(poolSize, createDefaultThreadFactory())
+ }
+
+ private static createPool(int poolSize, ThreadFactory threadFactory) {
+ if (!(poolSize in 1..Integer.MAX_VALUE)) throw new IllegalArgumentException("Invalid value $poolSize for the pool size has been specified. Please supply a positive int number.")
+ if (!threadFactory) throw new IllegalArgumentException("No value specified for threadFactory.")
+ return Executors.newFixedThreadPool(poolSize, threadFactory)
+ }
+
+ private static ThreadFactory createDefaultThreadFactory() {
+ return {Runnable runnable ->
+ final Thread thread = new Thread(runnable)
+ thread.daemon = false
+ return thread
+ } as ThreadFactory
+ }
+
+ /**
+ * Creates a new instance of <i>ExecutorService</i>, binds it to the current thread, enables the ExecutorService DSL
+ * and runs the supplied closure.
+ * Within the supplied code block the <i>ExecutorService</i> is available as the only parameter, objects have been
+ * enhanced with the <i>eachAsync()</i>, <i>collectAsync()</i> and other methods from the <i>AsyncInvokerUtil</i>
+ * category class as well as closures can be turned into asynchronous ones by calling the <i>async()</i> method on them.
+ * E.g. <i>closure,async</i> returns a new closure, which, when run will schedule the original closure
+ * for processing in the pool.
+ * Calling <i>images.eachAsync{processImage(it}}</i> will call the potentially long-lasting <i>processImage()</i>
+ * operation on each image in the <i>images</i> collection in parallel.
+ * <pre>
+ * def result = new ConcurrentSkipListSet()
+ * Asynchronizer.withAsynchronizer(5) {ExecutorService service ->
+ * [1, 2, 3, 4, 5].eachAsync{Number number -> result.add(number * 10)}
+ * assertEquals(new HashSet([10, 20, 30, 40, 50]), result)
+ * }
+ * </pre>
+ * @param cl The block of code to invoke with the DSL enabled
+ */
+ public static withAsynchronizer(Closure cl) {
+ return withAsynchronizer(3, cl)
+ }
+
+ /**
+ * Creates a new instance of <i>ExecutorService</i>, binds it to the current thread, enables the ExecutorService DSL
+ * and runs the supplied closure.
+ * Within the supplied code block the <i>ExecutorService</i> is available as the only parameter, objects have been
+ * enhanced with the <i>eachAsync()</i>, <i>collectAsync()</i> and other methods from the <i>AsyncInvokerUtil</i>
+ * category class as well as closures can be turned into asynchronous ones by calling the <i>async()</i> method on them.
+ * E.g. <i>closure,async</i> returns a new closure, which, when run will schedule the original closure
+ * for processing in the pool.
+ * Calling <i>images.eachAsync{processImage(it}}</i> will call the potentially long-lasting <i>processImage()</i>
+ * operation on each image in the <i>images</i> collection in parallel.
+ * <pre>
+ * def result = new ConcurrentSkipListSet()
+ * Asynchronizer.withAsynchronizer(5) {ExecutorService service ->
+ * [1, 2, 3, 4, 5].eachAsync{Number number -> result.add(number * 10)}
+ * assertEquals(new HashSet([10, 20, 30, 40, 50]), result)
+ * }
+ * </pre>
+ * @param numberOfThreads Number of threads in the newly created thread pool
+ * @param cl The block of code to invoke with the DSL enabled
+ */
+ public static withAsynchronizer(int numberOfThreads, Closure cl) {
+ return withAsynchronizer(numberOfThreads, createDefaultThreadFactory(), cl)
+ }
+
+ /**
+ * Creates a new instance of <i>ExecutorService</i>, binds it to the current thread, enables the ExecutorService DSL
+ * and runs the supplied closure.
+ * Within the supplied code block the <i>ExecutorService</i> is available as the only parameter, objects have been
+ * enhanced with the <i>eachAsync()</i>, <i>collectAsync()</i> and other methods from the <i>AsyncInvokerUtil</i>
+ * category class as well as closures can be turned into asynchronous ones by calling the <i>async()</i> method on them.
+ * E.g. <i>closure,async</i> returns a new closure, which, when run will schedule the original closure
+ * for processing in the pool.
+ * Calling <i>images.eachAsync{processImage(it}}</i> will call the potentially long-lasting <i>processImage()</i>
+ * operation on each image in the <i>images</i> collection in parallel.
+ * <pre>
+ * def result = new ConcurrentSkipListSet()
+ * Asynchronizer.withAsynchronizer(5) {ExecutorService service ->
+ * [1, 2, 3, 4, 5].eachAsync{Number number -> result.add(number * 10)}
+ * assertEquals(new HashSet([10, 20, 30, 40, 50]), result)
+ * }
+ * </pre>
+ * @param numberOfThreads Number of threads in the newly created thread pool
+ * @param threadFactory Factory for threads in the pool
+ * @param cl The block of code to invoke with the DSL enabled
+ */
+ public static withAsynchronizer(int numberOfThreads, ThreadFactory threadFactory, Closure cl) {
+ final ExecutorService pool = createPool(numberOfThreads, threadFactory)
+ try {
+ return withExistingAsynchronizer(pool, cl)
+ } finally {
+ pool.shutdown()
+ pool.awaitTermination(Long.MAX_VALUE, TimeUnit.MILLISECONDS)
+ }
+ }
+
+ /**
+ * Creates a new instance of <i>ExecutorService</i>, binds it to the current thread, enables the ExecutorService DSL
+ * and runs the supplied closure.
+ * Within the supplied code block the <i>ExecutorService</i> is available as the only parameter, objects have been
+ * enhanced with the <i>eachAsync()</i>, <i>collectAsync()</i> and other methods from the <i>AsyncInvokerUtil</i>
+ * category class as well as closures can be turned into asynchronous ones by calling the <i>async()</i> method on them.
+ * E.g. <i>closure,async</i> returns a new closure, which, when run will schedule the original closure
+ * for processing in the pool.
+ * Calling <i>images.eachAsync{processImage(it}}</i> will call the potentially long-lasting <i>processImage()</i>
+ * operation on each image in the <i>images</i> collection in parallel.
+ * <pre>
+ * def result = new ConcurrentSkipListSet()
+ * Asynchronizer.withAsynchronizer(5) {ExecutorService service ->
+ * [1, 2, 3, 4, 5].eachAsync{Number number -> result.add(number * 10)}
+ * assertEquals(new HashSet([10, 20, 30, 40, 50]), result)
+ * }
+ * </pre>
+ * @param pool The <i>ExecutorService</i> to use, the service will not be shutdown after this method returns
+ */
+ public static withExistingAsynchronizer(ExecutorService pool, Closure cl) {
+ currentInvoker.set(pool)
+ def result=null
+ try {
+ use(AsyncInvokerUtil) {
+ result = cl(pool)
+ }
+ } finally {
+ currentInvoker.remove()
+ }
+ return result
+ }
+
+ /**
+ * Enhanced the Object's meta-class with the <i>withAsynchronizer</i> and <i>withExistingAsynchronizer</i> methods,
+ * which call apropriate static methods on the <I>Asynchronizer</i> class. So the DSL can be then wrapped like this:
+ * <pre>
+ * Asynchronizer.initializeDSL()
+ * ...
+ * withAsynchronizer {* assert ([2, 4, 6, 8, 10] == [1, 2, 3, 4, 5].collectAsync {it * 2})
+ * assert [1, 2, 3, 4, 5].allAsync {it > 0}* assert [1, 2, 3, 4, 5].findAsync{Number number -> number > 2} in [3, 4, 5]
+ * ...
+ *}* </pre>
+ */
+ public static void initializeDSL () {
+ Object.metaClass {
+ withAsynchronizer = {Closure cl ->
+ Asynchronizer.withAsynchronizer cl
+ }
+
+ withAsynchronizer = {int numberOfThreads, Closure cl ->
+ Asynchronizer.withAsynchronizer numberOfThreads, cl
+ }
+
+ withAsynchronizer = {int numberOfThreads, ThreadFactory threadFactory, Closure cl ->
+ Asynchronizer.withAsynchronizer numberOfThreads, threadFactory, cl
+ }
+
+ withExistingAsynchronizer = {ExecutorService pool, Closure cl ->
+ Asynchronizer.withExistingAsynchronizer pool, cl
+ }
+ }
+ }
+
+ //todo allow for destroying the DSL
+}
+
diff --git a/grarchetype-common/src/main/mdo/maven.mdo b/grarchetype-common/src/main/mdo/maven.mdo
new file mode 100644
index 0000000..8c52cef
--- /dev/null
+++ b/grarchetype-common/src/main/mdo/maven.mdo
@@ -0,0 +1,2980 @@
+<?xml version="1.0"?>
+
+<!--
+ |
+ | o add specification element to a field, this would be more a technical description of
+ | what is allowed in the field.
+ |
+ | o validators: there could be several levels of validation. Simple type validation could
+ | be done with a regex, but we need inter-field validation and rules which could be
+ | dealt with by something like drools.
+ |
+ | o i18n: would be good to be able to have names/descriptions/specifications
+ | in as many languages as possible.
+ |
+ | o annotation mechanism so that changes to the model can be accurately tracked.
+ |
+ | o need to clean up all the descriptions, matching anything to the current project-descriptor.xml file and
+ | improving on that
+ |
+ | o use enums where appropriate (eg dependency scope)
+ |
+ | o a number of elements have a grouId/artifactId and sometimes version. It would be good to have them all extend one
+ | definition of these types
+ |
+ -->
+<model>
+ <id>maven</id>
+ <name>Maven</name>
+ <description><![CDATA[
+ <p>This is a reference for the Maven project descriptor used in Maven.</p>
+ <p>An XSD is available at:</p>
+ <ul>
+ <li><a href="http://maven.apache.org/maven-v3_0_0.xsd">http://maven.apache.org/maven-v3_0_0.xsd</a> for Maven 1.1.</li>
+ <li><a href="http://maven.apache.org/maven-v4_0_0.xsd">http://maven.apache.org/maven-v4_0_0.xsd</a> for Maven 2.0.</li>
+ </ul>
+ ]]></description>
+ <defaults>
+ <default>
+ <key>package</key>
+ <value>org.apache.maven.model</value>
+ </default>
+ </defaults>
+ <classes>
+ <class rootElement="true" xml.tagName="project">
+ <name>Model</name>
+ <superClass>ModelBase</superClass>
+ <description><![CDATA[
+ The <code><project></code> element is the root of the descriptor.
+ The following table lists all of the possible child elements.
+ ]]></description>
+ <version>3.0.0+</version>
+ <fields>
+ <field>
+ <name>extend</name>
+ <version>3.0.0</version>
+ <description><![CDATA[
+ The location of the parent project, if one exists. Values from the
+ parent project will be the default for this project if they are
+ left unspecified. The path may be absolute, or relative to the
+ current <code>project.xml</code> file. For example,
+ <code><extend>${basedir}/../project.xml</extend></code>.
+ ]]></description>
+ <type>String</type>
+ </field>
+ <field>
+ <name>parent</name>
+ <version>4.0.0</version>
+ <description><![CDATA[
+ The location of the parent project, if one exists. Values from the
+ parent project will be the default for this project if they are
+ left unspecified. The location is given as a group ID, artifact ID and version.
+ ]]></description>
+ <association>
+ <type>Parent</type>
+ </association>
+ <comment></comment>
+ </field>
+ <field>
+ <name>modelVersion</name>
+ <version>4.0.0</version>
+ <required>true</required>
+ <description><![CDATA[Declares to which version of project descriptor this POM conforms.]]></description>
+ <type>String</type>
+ </field>
+ <field>
+ <name>pomVersion</name>
+ <version>3.0.0</version>
+ <required>true</required>
+ <type>String</type>
+ <description>
+ <![CDATA[Declares to which version of project descriptor this POM conforms. The only valid value is <code>3</code>.]]></description>
+ </field>
+ <field>
+ <name>groupId</name>
+ <version>3.0.0+</version>
+ <required>true</required>
+ <description><![CDATA[
+ A universally unique identifier for a project. It is normal to
+ use a fully-qualified package name to distinguish it from other projects with a similar name
+ (eg. <code>org.apache.maven</code>).
+ ]]></description>
+ <type>String</type>
+ </field>
+ <field>
+ <name>artifactId</name>
+ <version>3.0.0+</version>
+ <required>true</required>
+ <description><![CDATA[
+ The identifier for this artifact that is unique within the group given by the group ID.
+ An artifact is something that is either produced or used by a project. Examples of artifacts produced by
+ Maven for a project include: JARs, source and binary distributions, and WARs.
+ ]]></description>
+ <type>String</type>
+ </field>
+ <field>
+ <name>id</name>
+ <version>3.0.0</version>
+ <required>true</required>
+ <description><![CDATA[
+ <b>Deprecated</b>. When used, this sets both the <code>groupId</code> and <code>artifactId</code> elements
+ if they were previously empty.
+ ]]></description>
+ <type>String</type>
+ </field>
+ <field>
+ <name>packaging</name>
+ <version>4.0.0</version>
+ <description><![CDATA[
+ The type of artifact this project produces, for example <code>jar</code>
+ <code>war</code>
+ <code>ear</code>
+ <code>pom</code>.
+ Plugins can create their own packaging, and
+ therefore their own packaging types,
+ so this list does not contain all possible types.
+ ]]></description>
+ <type>String</type>
+ <defaultValue>jar</defaultValue>
+ </field>
+ <field>
+ <name>name</name>
+ <version>3.0.0+</version>
+ <required>true</required>
+ <description><![CDATA[
+ The full name of the project.
+ ]]></description>
+ <type>String</type>
+ </field>
+ <field>
+ <name>currentVersion</name>
+ <description><![CDATA[
+ The current version of the artifact produced by this project.
+ ]]></description>
+ <version>3.0.0</version>
+ <required>true</required>
+ <type>String</type>
+ </field>
+ <field>
+ <name>version</name>
+ <version>4.0.0</version>
+ <required>true</required>
+ <description><![CDATA[
+ The current version of the artifact produced by this project.
+ ]]></description>
+ <type>String</type>
+ </field>
+ <field>
+ <name>shortDescription</name>
+ <version>3.0.0</version>
+ <description><![CDATA[
+ A short description of the project. The short description should be
+ limited to a single line.
+ ]]></description>
+ <type>String</type>
+ </field>
+ <field>
+ <name>description</name>
+ <version>3.0.0+</version>
+ <description><![CDATA[
+ A detailed description of the project, used by Maven whenever it needs to describe the project,
+ such as on the web site. While this element can be specified as CDATA to enable
+ the use of HTML tags within the description, it is discouraged to allow plain text representation.
+ If you need to modify the index page of the generated web site, you are able to specify your own instead
+ of adjusting this text.
+ ]]></description>
+ <type>String</type>
+ </field>
+ <field>
+ <name>url</name>
+ <version>3.0.0+</version>
+ <description><![CDATA[
+ The URL to the project's homepage.
+ ]]></description>
+ <type>String</type>
+ </field>
+ <field>
+ <name>logo</name>
+ <version>3.0.0</version>
+ <description><![CDATA[
+ The URL of the project's logo image. This can be an URL relative
+ to the base directory of the generated web site,
+ (e.g., <code>/images/project-logo.png</code>) or an absolute URL
+ (e.g., <code>http://my.corp/project-logo.png</code>). This is used
+ when generating the project documentation.
+ ]]></description>
+ <type>String</type>
+ </field>
+ <field>
+ <name>prerequisites</name>
+ <version>4.0.0</version>
+ <description>
+ Describes the prerequisites in the build environment for this project.
+ </description>
+ <association>
+ <type>Prerequisites</type>
+ </association>
+ </field>
+ <field>
+ <name>issueTrackingUrl</name>
+ <version>3.0.0</version>
+ <description><![CDATA[
+ The URL of the project's issue tracking system.
+ ]]></description>
+ <type>String</type>
+ </field>
+ <field>
+ <name>issueManagement</name>
+ <version>4.0.0</version>
+ <description><![CDATA[The project's issue management system information.]]></description>
+ <association>
+ <type>IssueManagement</type>
+ </association>
+ </field>
+ <field>
+ <name>ciManagement</name>
+ <version>4.0.0</version>
+ <description><![CDATA[The project's continuous integration information.]]></description>
+ <association>
+ <type>CiManagement</type>
+ </association>
+ </field>
+ <field>
+ <name>inceptionYear</name>
+ <version>3.0.0+</version>
+ <required>true</required>
+ <description><![CDATA[
+ The year of the project's inception, specified with 4 digits.
+ This value is used when generating copyright notices as well as being informational.
+ ]]></description>
+ <type>String</type>
+ </field>
+ <field>
+ <name>gumpRepositoryId</name>
+ <version>3.0.0</version>
+ <description><![CDATA[
+ This is the repository identifier in Gump that this project is part of.
+ ]]></description>
+ <type>String</type>
+ </field>
+ <field>
+ <name>siteAddress</name>
+ <version>3.0.0</version>
+ <description><![CDATA[
+ The hostname of the web server that hosts the project's web site. This is used when the web site is
+ deployed.
+ ]]></description>
+ <type>String</type>
+ </field>
+ <field>
+ <name>siteDirectory</name>
+ <version>3.0.0</version>
+ <description><![CDATA[
+ The directory on the web server where the public web site
+ for this project resides. This is used when the web site is deployed.
+ ]]></description>
+ <type>String</type>
+ </field>
+ <field>
+ <name>distributionSite</name>
+ <version>3.0.0</version>
+ <description><![CDATA[
+ The server where the final distributions will be published. This is used when the
+ distributions are deployed. If this isn't defined, the central repository is used instead as
+ determined by <code>maven.repo.central</code> and <code>maven.repo.central.directory</code>.
+ ]]></description>
+ <type>String</type>
+ </field>
+ <field>
+ <name>distributionDirectory</name>
+ <version>3.0.0</version>
+ <description><![CDATA[
+ The directory on the web server where the final distributions will be published. This is used when the
+ distributions are deployed.
+ ]]></description>
+ <type>String</type>
+ </field>
+ <field>
+ <name>mailingLists</name>
+ <version>3.0.0+</version>
+ <description><![CDATA[
+ Contains information about a project's mailing lists.
+ ]]></description>
+ <association>
+ <type>MailingList</type>
+ <multiplicity>*</multiplicity>
+ </association>
+ </field>
+ <field>
+ <name>developers</name>
+ <version>3.0.0+</version>
+ <description><![CDATA[
+ Describes the committers of a project.
+ ]]></description>
+ <association>
+ <type>Developer</type>
+ <multiplicity>*</multiplicity>
+ </association>
+ </field>
+ <field>
+ <name>contributors</name>
+ <version>3.0.0+</version>
+ <description><![CDATA[
+ Describes the contributors to a project that are not yet committers.
+ ]]></description>
+ <association>
+ <type>Contributor</type>
+ <multiplicity>*</multiplicity>
+ </association>
+ </field>
+ <field>
+ <name>licenses</name>
+ <version>3.0.0+</version>
+ <description><![CDATA[
+ This element describes all of the licenses for this project.
+ Each license is described by a <code>license</code> element, which
+ is then described by additional elements.
+ Projects should only list the license(s) that applies to the project
+ and not the licenses that apply to dependencies.
+ If multiple licenses are listed, it is assumed that the user can select any of them, not that they
+ must accept all.
+ ]]></description>
+ <association>
+ <type>License</type>
+ <multiplicity>*</multiplicity>
+ </association>
+ </field>
+ <field>
+ <name>versions</name>
+ <version>3.0.0</version>
+ <description><![CDATA[
+ Contains information on previous versions of the project.
+ ]]></description>
+ <association>
+ <type>Version</type>
+ <multiplicity>*</multiplicity>
+ </association>
+ </field>
+ <field>
+ <name>branches</name>
+ <version>3.0.0</version>
+ <description><![CDATA[
+ Contains information on SCM branches of the project.
+ ]]></description>
+ <association>
+ <type>Branch</type>
+ <multiplicity>*</multiplicity>
+ </association>
+ </field>
+ <field>
+ <name>packageGroups</name>
+ <version>3.0.0</version>
+ <description><![CDATA[Package groups required for complete javadocs.]]></description>
+ <association>
+ <type>PackageGroup</type>
+ <multiplicity>*</multiplicity>
+ </association>
+ </field>
+ <field>
+ <name>reports</name>
+ <version>3.0.0</version>
+ <description><![CDATA[
+ This element includes the specification of reports to be
+ included in a Maven-generated site. These reports will be run
+ when a user executes <code>maven site</code>. All of the
+ reports will be included in the navigation bar for browsing in
+ the order they are specified.
+ ]]></description>
+ <association>
+ <type>String</type>
+ <multiplicity>*</multiplicity>
+ </association>
+ </field>
+ <field>
+ <name>scm</name>
+ <version>4.0.0</version>
+ <description>
+ <![CDATA[Specification for the SCM used by the project, such as CVS, Subversion, etc.]]></description>
+ <association>
+ <type>Scm</type>
+ </association>
+ </field>
+ <field>
+ <name>repository</name>
+ <version>3.0.0</version>
+ <description>
+ <![CDATA[Specification for the SCM used by the project, such as CVS, Subversion, etc.]]></description>
+ <association>
+ <type>Repository</type>
+ </association>
+ </field>
+ <field>
+ <name>organization</name>
+ <version>3.0.0+</version>
+ <description><![CDATA[
+ This element describes various attributes of the organization to
+ which the project belongs. These attributes are utilized when
+ documentation is created (for copyright notices and links).
+ ]]></description>
+ <alias>organisation</alias>
+ <association>
+ <type>Organization</type>
+ </association>
+ </field>
+ <field>
+ <name>properties</name>
+ <version>3.0.0</version>
+ <description><![CDATA[
+ Project properties that will be used by various plugins. The format is <code><name>value</name></code>.
+ ]]></description>
+ <type>Properties</type>
+ <association xml.mapStyle="inline">
+ <type>String</type>
+ <multiplicity>*</multiplicity>
+ </association>
+ </field>
+ <field xml.tagName="package">
+ <name>packageName</name>
+ <version>3.0.0</version>
+ <type>String</type>
+ <description><![CDATA[
+ The Java package name of the project. This value is used
+ when generating JavaDoc.
+ ]]></description>
+ </field>
+ <field>
+ <name>build</name>
+ <version>3.0.0+</version>
+ <required>true</required>
+ <description><![CDATA[Information required to build the project.]]></description>
+ <association>
+ <type>Build</type>
+ </association>
+ </field>
+ <field>
+ <name>profiles</name>
+ <version>4.0.0</version>
+ <description><![CDATA[
+ A listing of project-local build profiles which will modify the build process when activated.
+ ]]></description>
+ <association>
+ <type>Profile</type>
+ <multiplicity>*</multiplicity>
+ </association>
+ </field>
+ </fields>
+ <codeSegments>
+ <codeSegment>
+ <version>3.0.0</version>
+ <code><![CDATA[
+ public void setVersion(String version)
+ {
+ this.currentVersion = version;
+ }
+
+ public String getVersion()
+ {
+ return currentVersion;
+ }
+
+ /* We need this because we can't use package as a field name.*/
+ public void setPackage(String packageName)
+ {
+ this.packageName = packageName;
+ }
+
+ public String getPackage()
+ {
+ return packageName;
+ }
+ ]]></code>
+ </codeSegment>
+ <codeSegment>
+ <version>4.0.0</version>
+ <code><![CDATA[
+ public String getId()
+ {
+ StringBuffer id = new StringBuffer();
+
+ id.append( getGroupId() );
+ id.append( ":" );
+ id.append( getArtifactId() );
+ id.append( ":" );
+ id.append( getPackaging() );
+ id.append( ":" );
+ id.append( getVersion() );
+
+ return id.toString();
+ }
+ ]]></code>
+ </codeSegment>
+ </codeSegments>
+ </class>
+ <class>
+ <name>ModelBase</name>
+ <version>3.0.0+</version>
+ <fields>
+ <field>
+ <name>modules</name>
+ <version>4.0.0</version>
+ <description>
+ The modules (sometimes called subprojects) to build as a part of this project.
+ Each module listed is a relative path to the directory containing the module.
+ </description>
+ <association>
+ <type>String</type>
+ <multiplicity>*</multiplicity>
+ </association>
+ </field>
+ <field>
+ <name>repositories</name>
+ <version>4.0.0</version>
+ <description><![CDATA[The lists of the remote repositories for discovering dependencies and
+ extensions.]]></description>
+ <association>
+ <type>Repository</type>
+ <multiplicity>*</multiplicity>
+ </association>
+ </field>
+ <field>
+ <name>pluginRepositories</name>
+ <version>4.0.0</version>
+ <description>
+ <![CDATA[The lists of the remote repositories for discovering plugins for builds and reports.]]></description>
+ <association>
+ <type>Repository</type>
+ <multiplicity>*</multiplicity>
+ </association>
+ </field>
+ <field>
+ <name>dependencies</name>
+ <version>3.0.0+</version>
+ <description><![CDATA[
+ This element describes all of the dependencies associated with a
+ project.
+ These dependencies are used to construct a classpath for your
+ project during the build process. They are automatically downloaded from the
+ repositories defined in this project.
+ See <a href="http://maven.apache.org/guides/introduction/introduction-to-dependency-mechanism.html">the
+ dependency mechanism</a> for more information.
+ ]]></description>
+ <association>
+ <type>Dependency</type>
+ <multiplicity>*</multiplicity>
+ </association>
+ </field>
+ <field>
+ <name>reports</name>
+ <version>4.0.0</version>
+ <description><![CDATA[
+ <b>Deprecated</b>. Now ignored by Maven.
+ ]]></description>
+ <type>DOM</type>
+ </field>
+ <field>
+ <name>reporting</name>
+ <version>4.0.0</version>
+ <description><![CDATA[
+ This element includes the specification of report plugins to use to generate the reports on the
+ Maven-generated site. These reports will be run when a user executes <code>mvn site</code>. All of the
+ reports will be included in the navigation bar for browsing.
+ ]]></description>
+ <association>
+ <type>Reporting</type>
+ </association>
+ </field>
+ <field>
+ <name>dependencyManagement</name>
+ <version>4.0.0</version>
+ <required>false</required>
+ <description><![CDATA[
+ Default dependency information for projects that inherit from
+ this one. The dependencies in this section are not immediately resolved.
+ Instead, when a POM derived from this one declares a dependency
+ described by a matching groupId and artifactId, the version and other values from this
+ section are used for that dependency if they were not already specified.
+ ]]></description>
+ <association>
+ <type>DependencyManagement</type>
+ </association>
+ </field>
+ <field>
+ <name>distributionManagement</name>
+ <version>4.0.0</version>
+ <description><![CDATA[Distribution information for a project that enables deployment of the site
+ and artifacts to remote web servers and repositories respectively.]]></description>
+ <association>
+ <type>DistributionManagement</type>
+ </association>
+ </field>
+ <field>
+ <name>properties</name>
+ <version>4.0.0</version>
+ <description><![CDATA[
+ Properties that can be used throughout the POM as a substitution, and are used as filters in resources
+ if enabled. The format is <code><name>value</name></code>.
+ ]]></description>
+ <type>Properties</type>
+ <association xml.mapStyle="inline">
+ <type>String</type>
+ <multiplicity>*</multiplicity>
+ </association>
+ </field>
+ </fields>
+ </class>
+ <class>
+ <name>Branch</name>
+ <version>3.0.0</version>
+ <description><![CDATA[
+ Contains information on the SCM branches of the project.
+ ]]></description>
+ <fields>
+ <field>
+ <name>tag</name>
+ <version>3.0.0</version>
+ <required>true</required>
+ <description><![CDATA[
+ The branch tag in the version control system (e.g. cvs) used by the
+ project for the source code associated with this branch of the
+ project.
+ ]]></description>
+ <type>String</type>
+ </field>
+ </fields>
+ </class>
+ <class>
+ <name>PluginContainer</name>
+ <version>3.0.0+</version>
+ <fields>
+ <field>
+ <name>plugins</name>
+ <version>4.0.0</version>
+ <description>
+ The list of plugins to use.
+ </description>
+ <association>
+ <type>Plugin</type>
+ <multiplicity>*</multiplicity>
+ </association>
+ </field>
+ </fields>
+ <codeSegments>
+ <codeSegment>
+ <version>4.0.0</version>
+ <code><![CDATA[
+ java.util.Map pluginMap;
+
+ public void flushPluginMap()
+ {
+ this.pluginMap = null;
+ }
+
+ public java.util.Map getPluginsAsMap()
+ {
+ if ( pluginMap == null )
+ {
+ pluginMap = new java.util.HashMap();
+ if ( plugins != null )
+ {
+ for ( java.util.Iterator it = plugins.iterator(); it.hasNext(); )
+ {
+ Plugin plugin = (Plugin) it.next();
+ pluginMap.put( plugin.getKey(), plugin );
+ }
+ }
+ }
+ return pluginMap;
+ }
+ ]]></code>
+ </codeSegment>
+ </codeSegments>
+ </class>
+ <class>
+ <name>PluginConfiguration</name>
+ <version>3.0.0+</version>
+ <superClass>PluginContainer</superClass>
+ <fields>
+ <!-- [ jdcasey:06-Mar-2005 ] Added to handle version management, etc. for
+ | plugins to be used in sub-projects. -->
+ <field>
+ <name>pluginManagement</name>
+ <version>4.0.0</version>
+ <required>false</required>
+ <description><![CDATA[
+ Default plugin information to be made available for reference by
+ projects derived from this one. This plugin configuration will not
+ be resolved or bound to the lifecycle unless referenced. Any local
+ configuration for a given plugin will override the plugin's entire
+ definition here.
+ ]]></description>
+ <association>
+ <type>PluginManagement</type>
+ </association>
+ </field>
+ </fields>
+ </class>
+ <class>
+ <name>BuildBase</name>
+ <version>3.0.0+</version>
+ <superClass>PluginConfiguration</superClass>
+ <fields>
+ <field>
+ <name>defaultGoal</name>
+ <version>3.0.0+</version>
+ <description><![CDATA[
+ The default goal (or phase in Maven 2) to execute when none is specified for the project.
+ ]]></description>
+ <type>String</type>
+ </field>
+ <field>
+ <name>resources</name>
+ <version>3.0.0+</version>
+ <description><![CDATA[
+ This element describes all of the classpath resources such as properties files associated with a
+ project. These resources are often included in the final package.
+ ]]></description>
+ <association>
+ <type>Resource</type>
+ <multiplicity>*</multiplicity>
+ </association>
+ </field>
+ <field>
+ <name>testResources</name>
+ <version>4.0.0</version>
+ <description><![CDATA[
+ This element describes all of the classpath resources such as properties files associated with a
+ project's unit tests.
+ ]]></description>
+ <association>
+ <type>Resource</type>
+ <multiplicity>*</multiplicity>
+ </association>
+ </field>
+ <field>
+ <name>directory</name>
+ <version>4.0.0</version>
+ <description><![CDATA[
+ The directory where all files generated by the build are placed.
+ ]]></description>
+ <type>String</type>
+ </field>
+ <field>
+ <name>finalName</name>
+ <version>4.0.0</version>
+ <description><![CDATA[
+ The filename (excluding the extension, and with no path information) that the produced artifact
+ will be called. The default value is <code>${artifactId}-${version}</code>.
+ ]]></description>
+ <type>String</type>
+ </field>
+ <field>
+ <name>filters</name>
+ <version>4.0.0</version>
+ <description><![CDATA[
+ The list of filter properties files that are used when filtering is enabled.
+ ]]></description>
+ <association>
+ <type>String</type>
+ <multiplicity>*</multiplicity>
+ </association>
+ </field>
+ </fields>
+ </class>
+ <class>
+ <name>Build</name>
+ <version>3.0.0+</version>
+ <superClass>BuildBase</superClass>
+ <fields>
+ <field>
+ <name>nagEmailAddress</name>
+ <version>3.0.0</version>
+ <description><![CDATA[
+ An address to which notifications regarding the status of builds
+ for this project can be sent. This is intended for use by tools
+ which do unattended builds, for example those providing for
+ continuous integration.
+ ]]></description>
+ <type>String</type>
+ </field>
+ <field>
+ <name>sourceDirectory</name>
+ <version>3.0.0+</version>
+ <required>true</required>
+ <description><![CDATA[
+ This element specifies a directory containing the source
+ of the project. The generated build system will compile
+ the source in this directory when the project is built.
+ The path given is relative to the project descriptor.
+ ]]></description>
+ <type>String</type>
+ </field>
+ <field>
+ <name>scriptSourceDirectory</name>
+ <version>4.0.0</version>
+ <required>true</required>
+ <description><![CDATA[
+ This element specifies a directory containing the script sources
+ of the project. This directory is meant to be different from the
+ sourceDirectory, in that its contents will be copied to the output
+ directory in most cases (since scripts are interpreted rather than
+ compiled).
+ ]]></description>
+ <type>String</type>
+ </field>
+ <field>
+ <name>unitTestSourceDirectory</name>
+ <version>3.0.0</version>
+ <required>true</required>
+ <description><![CDATA[
+ This element specifies a directory containing the unit test
+ source of the project. The generated build system will
+ compile these directories when the project is being tested.
+ The path given is relative to the project descriptor.
+ ]]></description>
+ <type>String</type>
+ </field>
+ <field>
+ <name>testSourceDirectory</name>
+ <version>4.0.0</version>
+ <required>true</required>
+ <description><![CDATA[
+ This element specifies a directory containing the unit test
+ source of the project. The generated build system will
+ compile these directories when the project is being tested.
+ The path given is relative to the project descriptor.
+ ]]></description>
+ <type>String</type>
+ </field>
+ <field>
+ <name>aspectSourceDirectory</name>
+ <version>3.0.0</version>
+ <description><![CDATA[
+ This element specifies a directory containing Aspect
+ sources of the project. The generated build system will
+ compile the Aspects in this directory when the project is
+ built if Aspects have been enabled.
+ The path given is relative to the project descriptor.
+ ]]></description>
+ <type>String</type>
+ </field>
+ <field>
+ <name>integrationUnitTestSourceDirectory</name>
+ <version>3.0.0</version>
+ <description><![CDATA[
+ This element specifies a directory containing integration test
+ sources of the project. This element is not known to be used.
+ ]]></description>
+ <type>String</type>
+ </field>
+ <field>
+ <name>sourceModifications</name>
+ <version>3.0.0</version>
+ <required>true</required>
+ <description><![CDATA[
+ This element describes all of the sourceModifications associated
+ with a project. These modifications are used
+ to exclude or include various source depending on the environment
+ the build is running in.
+ ]]></description>
+ <association>
+ <type>SourceModification</type>
+ <multiplicity>*</multiplicity>
+ </association>
+ </field>
+ <field>
+ <name>unitTest</name>
+ <version>3.0.0</version>
+ <required>true</required>
+ <description><![CDATA[
+ This element specifies unit tests associated with the project.
+ ]]></description>
+ <defaultValue>new UnitTest()</defaultValue>
+ <association>
+ <type>UnitTest</type>
+ </association>
+ </field>
+ <field>
+ <name>outputDirectory</name>
+ <version>4.0.0</version>
+ <description><![CDATA[
+ The directory where compiled application classes are placed.
+ ]]></description>
+ <type>String</type>
+ </field>
+ <field>
+ <name>testOutputDirectory</name>
+ <version>4.0.0</version>
+ <description><![CDATA[
+ The directory where compiled test classes are placed.
+ ]]></description>
+ <type>String</type>
+ </field>
+ <field>
+ <name>extensions</name>
+ <version>4.0.0</version>
+ <description>A set of build extensions to use from this project.</description>
+ <association>
+ <type>Extension</type>
+ <multiplicity>*</multiplicity>
+ </association>
+ </field>
+ </fields>
+ </class>
+ <class>
+ <name>CiManagement</name>
+ <version>4.0.0</version>
+ <fields>
+ <field>
+ <name>system</name>
+ <version>4.0.0</version>
+ <description>
+ <![CDATA[The name of the continuous integration system, e.g. <code>continuum</code>.]]></description>
+ <type>String</type>
+ </field>
+ <field>
+ <name>url</name>
+ <version>4.0.0</version>
+ <description>
+ <![CDATA[URL for the continuous integration system used by the project if it has a web interface.]]></description>
+ <type>String</type>
+ </field>
+ <field>
+ <name>notifiers</name>
+ <version>4.0.0</version>
+ <description><![CDATA[
+ Configuration for notifying developers/users when a build is
+ unsuccessful, including user information and notification mode.
+ ]]></description>
+ <association>
+ <multiplicity>*</multiplicity>
+ <type>Notifier</type>
+ </association>
+ </field>
+ </fields>
+ </class>
+ <class>
+ <name>Notifier</name>
+ <description>
+ Configures one method for notifying users/developers when a build breaks.
+ </description>
+ <version>4.0.0</version>
+ <fields>
+ <field>
+ <name>type</name>
+ <version>4.0.0</version>
+ <defaultValue>mail</defaultValue>
+ <type>String</type>
+ <description>The mechanism used to deliver notifications.</description>
+ </field>
+ <field>
+ <name>sendOnError</name>
+ <version>4.0.0</version>
+ <defaultValue>true</defaultValue>
+ <type>boolean</type>
+ <description>Whether to send notifications on error.</description>
+ </field>
+ <field>
+ <name>sendOnFailure</name>
+ <version>4.0.0</version>
+ <defaultValue>true</defaultValue>
+ <type>boolean</type>
+ <description>Whether to send notifications on failure.</description>
+ </field>
+ <field>
+ <name>sendOnSuccess</name>
+ <version>4.0.0</version>
+ <defaultValue>true</defaultValue>
+ <type>boolean</type>
+ <description>Whether to send notifications on success.</description>
+ </field>
+ <field>
+ <name>sendOnWarning</name>
+ <version>4.0.0</version>
+ <defaultValue>true</defaultValue>
+ <type>boolean</type>
+ <description>Whether to send notifications on warning.</description>
+ </field>
+ <!-- TODO: Remove it after continuum alpha-3 release -->
+ <field>
+ <name>address</name>
+ <version>4.0.0</version>
+ <type>String</type>
+ <description><![CDATA[
+ <b>Deprecated</b>. Where to send the notification to - eg email address.
+ ]]></description>
+ </field>
+ <field>
+ <name>configuration</name>
+ <description>Extended configuration specific to this notifier goes here.</description>
+ <type>Properties</type>
+ <association xml.mapStyle="inline">
+ <type>String</type>
+ <multiplicity>*</multiplicity>
+ </association>
+ </field>
+ </fields>
+ </class>
+ <class>
+ <name>Contributor</name>
+ <description>
+ Description of a person who has contributed to the project, but who does
+ not have commit privileges. Usually, these contributions come in the
+ form of patches submitted.
+ </description>
+ <version>3.0.0+</version>
+ <fields>
+ <field>
+ <name>name</name>
+ <version>3.0.0+</version>
+ <description><![CDATA[The full name of the contributor.]]></description>
+ <type>String</type>
+ </field>
+ <field>
+ <name>email</name>
+ <version>3.0.0+</version>
+ <description><![CDATA[The email address of the contributor.]]></description>
+ <type>String</type>
+ </field>
+ <field>
+ <name>url</name>
+ <version>3.0.0+</version>
+ <description><![CDATA[The URL for the homepage of the contributor.]]></description>
+ <type>String</type>
+ </field>
+ <!-- TODO: should this just be a single Organization element -->
+ <field>
+ <name>organization</name>
+ <alias>organisation</alias>
+ <version>3.0.0+</version>
+ <description><![CDATA[The organization to which the contributor belongs.]]></description>
+ <type>String</type>
+ </field>
+ <field>
+ <name>organizationUrl</name>
+ <alias>organisationUrl</alias>
+ <version>3.0.0+</version>
+ <description><![CDATA[The URL of the organization.]]></description>
+ <type>String</type>
+ </field>
+ <field>
+ <name>roles</name>
+ <version>3.0.0+</version>
+ <description><![CDATA[
+ The roles the contributor plays in the project. Each role is
+ described by a <code>role</code> element, the body of which is a
+ role name. This can also be used to describe the contribution.
+ ]]></description>
+ <association>
+ <type>String</type>
+ <multiplicity>*</multiplicity>
+ </association>
+ </field>
+ <field>
+ <name>timezone</name>
+ <version>3.0.0+</version>
+ <description><![CDATA[
+ The timezone the contributor is in. This is a number in the range -11 to 12.
+ ]]></description>
+ <type>String</type>
+ </field>
+ <field>
+ <name>properties</name>
+ <version>3.0.0+</version>
+ <description><![CDATA[
+ Properties about the contributor, such as an instant messenger handle.
+ ]]></description>
+ <type>Properties</type>
+ <association xml.mapStyle="inline">
+ <type>String</type>
+ <multiplicity>*</multiplicity>
+ </association>
+ </field>
+ </fields>
+ </class>
+ <class>
+ <name>Dependency</name>
+ <version>3.0.0+</version>
+ <fields>
+ <field>
+ <name>id</name>
+ <version>3.0.0</version>
+ <required>true</required>
+ <description><![CDATA[
+ <strong>Deprecated</strong>. Please use <code>groupId</code> and
+ <code>artifactId</code> together instead.
+ ]]></description>
+ <type>String</type>
+ </field>
+ <field>
+ <name>groupId</name>
+ <version>3.0.0+</version>
+ <required>true</required>
+ <description><![CDATA[
+ The project group that produced the dependency, e.g.
+ <code>org.apache.maven</code>.
+ ]]></description>
+ <type>String</type>
+ </field>
+ <field>
+ <name>artifactId</name>
+ <version>3.0.0+</version>
+ <required>true</required>
+ <description><![CDATA[
+ The unique id for an artifact produced by the project group, e.g.
+ <code>maven-artifact</code>.
+ ]]></description>
+ <type>String</type>
+ </field>
+ <field>
+ <name>version</name>
+ <version>3.0.0+</version>
+ <description><![CDATA[
+ The version of the dependency, e.g. <code>3.2.1</code>. In Maven 2, this can also be
+ specified as a range of versions.
+ ]]></description>
+ <type>String</type>
+ </field>
+ <field>
+ <name>url</name>
+ <version>3.0.0</version>
+ <description><![CDATA[
+ This url will be provided to the user if the jar file cannot be downloaded
+ from the central repository.
+ ]]></description>
+ <type>String</type>
+ </field>
+ <field>
+ <name>jar</name>
+ <version>3.0.0</version>
+ <description><![CDATA[
+ Literal name of the artifact in the repository. Used to override the calculated artifact name.
+ ]]></description>
+ <type>String</type>
+ </field>
+ <field>
+ <name>type</name>
+ <version>3.0.0</version>
+ <description><![CDATA[
+ The type of dependency. This defaults to <code>jar</code>. While it usually represents the extension on
+ the filename of the dependency, that is not always the case.
+ Some examples are <code>jar</code>, <code>war</code>, and <code>plugin</code>.
+ A dependency of type <code>plugin</code> is loaded as a Maven plugin and not added to the project
+ build classpath.
+ ]]></description>
+ <type>String</type>
+ <defaultValue>jar</defaultValue>
+ </field>
+ <field>
+ <name>type</name>
+ <version>4.0.0</version>
+ <description><![CDATA[
+ The type of dependency. This defaults to <code>jar</code>. While it usually represents the extension on
+ the filename of the dependency, that is not always the case. A type can be mapped to a different
+ extension and a classifier.
+ The type often correspongs to the packaging used, though this is also not always the case.
+ Some examples are <code>jar</code>, <code>war</code>, <code>ejb-client</code> and <code>test-jar</code>.
+ New types can be defined by plugins that set
+ <code>extensions</code> to <code>true</code>, so this is not a complete list.
+ ]]></description>
+ <type>String</type>
+ <defaultValue>jar</defaultValue>
+ </field>
+ <field>
+ <name>classifier</name>
+ <version>4.0.0</version>
+ <description><![CDATA[
+ The classifier of the dependency. This allows distinguishing two artifacts that belong to the same POM but
+ were built differently, and is appended to the filename after the version. For example,
+ <code>jdk14</code> and <code>jdk15</code>.
+ ]]></description>
+ <type>String</type>
+ <required>false</required>
+ </field>
+ <field>
+ <name>properties</name>
+ <version>3.0.0</version>
+ <description><![CDATA[
+ Properties about the dependency. Various plugins allow you to
+ mark dependencies with properties. For example the war plugin looks for a
+ <code>war.bundle</code> property, and if found will include the
+ dependency in <code>WEB-INF/lib</code>.
+ ]]></description>
+ <type>Properties</type>
+ <association xml.mapStyle="inline">
+ <type>String</type>
+ <multiplicity>*</multiplicity>
+ </association>
+ </field>
+ <field>
+ <name>scope</name>
+ <version>4.0.0</version>
+ <description><![CDATA[
+ The scope of the dependency - <code>compile</code>, <code>runtime</code>, <code>test</code>,
+ <code>system</code>, and <code>provided</code>. Used to
+ calculate the various classpaths used for compilation, testing, and so on. It also assists in determining
+ which artifacts to include in a distribution of this project. For more information, see
+ <a href="http://maven.apache.org/guides/introduction/introduction-to-dependency-mechanism.html">the
+ dependency mechanism</a>.]]>
+ </description>
+ <type>String</type>
+ <!-- This default has to be enforced at the maven-artifact layer, to allow
+ | injection of defaults from <dependencyManagement/>.
+ | TODO: how can we document it?
+ |-->
+ <!-- defaultValue>compile</defaultValue -->
+ </field>
+ <field>
+ <name>systemPath</name>
+ <version>4.0.0</version>
+ <description><![CDATA[
+ FOR SYSTEM SCOPE ONLY. Note that use of this property is <b>discouraged</b> and may be replaced in later
+ versions. This specifies the path on the filesystem for this dependency.
+ Requires an absolute path for the value, not relative.
+ Use a property that gives the machine specific absolute path,
+ e.g. <code>${java.home}</code>.
+ ]]></description>
+ <type>String</type>
+ </field>
+ <field>
+ <name>exclusions</name>
+ <version>4.0.0</version>
+ <description>
+ Lists a set of artifacts that should be excluded from this dependency's artifact list when it comes to
+ calculating transitive dependencies.
+ </description>
+ <association>
+ <type>Exclusion</type>
+ <multiplicity>*</multiplicity>
+ </association>
+ </field>
+ <field>
+ <name>optional</name>
+ <version>4.0.0</version>
+ <description>
+ Indicates the dependency is optional for use of this library. While the version of the dependency will be
+ taken into account for dependency calculation if the library is used elsewhere, it will not be passed on
+ transitively.
+ </description>
+ <type>boolean</type>
+ <defaultValue>false</defaultValue>
+ </field>
+ </fields>
+ <codeSegments>
+ <codeSegment>
+ <version>3.0.0</version>
+ <code><![CDATA[
+ public String toString()
+ {
+ return groupId + "/" + type + "s:" + artifactId + "-" + version;
+ }
+ ]]></code>
+ </codeSegment>
+ <codeSegment>
+ <version>4.0.0</version>
+ <code><![CDATA[
+ public String toString()
+ {
+ return "Dependency {groupId=" + groupId + ", artifactId=" + artifactId + ", version=" + version + ", type=" + type + "}";
+ }
+ ]]></code>
+ </codeSegment>
+ <codeSegment>
+ <version>4.0.0</version>
+ <code><![CDATA[
+ public String getManagementKey()
+ {
+ return groupId + ":" + artifactId + ":" + type + (classifier != null ? ":" + classifier : "");
+ }
+ ]]></code>
+ </codeSegment>
+ <codeSegment>
+ <version>3.0.0</version>
+ <code><![CDATA[
+ public String getKey()
+ {
+ return getId() + ":" + getType();
+ }
+
+ public String getArtifactDirectory()
+ {
+ return getGroupId();
+ }
+
+ public String getArtifact()
+ {
+ // If the jar name has been explicty set then use that. This
+ // is when the <jar/> element is explicity used in the POM.
+ if ( getJar() != null)
+ {
+ return getJar();
+ }
+
+ String artifact;
+
+ if ("ejb-client".equals(getType())) {
+ artifact = getArtifactId() + "-" + getVersion() + "-client." + getExtension();
+ } else {
+ artifact = getArtifactId() + "-" + getVersion() + "." + getExtension();
+ }
+
+ return artifact;
+ }
+
+ public String getTypeDirectory()
+ {
+ String path;
+ if (getType().equals("ejb-client")) {
+ path = "ejbs";
+ } else {
+ path = getType() + "s";
+ }
+ return path;
+ }
+
+ public String getExtension()
+ {
+ if ("ejb".equals(getType()) || "ejb-client".equals(getType()) || "plugin".equals(getType()) || "aspect".equals(getType()) || "uberjar".equals(getType())) return "jar";
+ return getType();
+ }
+
+ public boolean isAddedToClasspath()
+ {
+ return ("jar".equals(getType()) || "ejb".equals(getType()) || "ejb-client".equals(getType()) || "sar".equals(getType()));
+ }
+
+ public boolean isPlugin()
+ {
+ return ("plugin".equals(getType()));
+ }
+
+ public String getProperty( String property )
+ {
+ return getProperties().getProperty( property );
+ }
+
+ public boolean equals( Object o )
+ {
+ if ( this == o )
+ {
+ return true;
+ }
+
+ if ( !( o instanceof Dependency ) )
+ {
+ return false;
+ }
+
+ Dependency d = (Dependency) o;
+ return getId().equals( d.getId() );
+ }
+
+ public int hashCode()
+ {
+ return getId().hashCode();
+ }
+ ]]></code>
+ </codeSegment>
+ </codeSegments>
+ </class>
+ <class>
+ <superClass>Contributor</superClass>
+ <name>Developer</name>
+ <description><![CDATA[
+ Information about one of the committers on this project.
+ ]]></description>
+ <version>3.0.0+</version>
+ <fields>
+ <field>
+ <name>id</name>
+ <version>3.0.0+</version>
+ <description><![CDATA[The unique ID of the developer in the SCM.]]></description>
+ <type>String</type>
+ </field>
+ </fields>
+ </class>
+ <class>
+ <name>Exclusion</name>
+ <version>4.0.0</version>
+ <fields>
+ <field>
+ <name>artifactId</name>
+ <version>4.0.0</version>
+ <description><![CDATA[The artifact ID of the project to exclude.]]></description>
+ <type>String</type>
+ <required>true</required>
+ </field>
+ <field>
+ <name>groupId</name>
+ <version>4.0.0</version>
+ <description><![CDATA[The group ID of the project to exclude.]]></description>
+ <type>String</type>
+ <required>true</required>
+ </field>
+ </fields>
+ </class>
+ <class>
+ <name>IssueManagement</name>
+ <description>
+ Information about the issue tracking (or bug tracking) system used to manage this project.
+ </description>
+ <version>4.0.0</version>
+ <fields>
+ <field>
+ <name>system</name>
+ <version>4.0.0</version>
+ <description><![CDATA[The name of the issue management system, e.g. Bugzilla]]></description>
+ <type>String</type>
+ </field>
+ <field>
+ <name>url</name>
+ <version>4.0.0</version>
+ <description><![CDATA[URL for the issue management system used by the project.]]></description>
+ <type>String</type>
+ </field>
+ </fields>
+ </class>
+ <class>
+ <name>DistributionManagement</name>
+ <version>4.0.0</version>
+ <description><![CDATA[
+ This elements describes all that pertains to distribution for a project.
+ It is primarily used for deployment of artifacts and the site
+ produced by the build.
+ ]]></description>
+ <fields>
+ <field>
+ <name>repository</name>
+ <version>4.0.0</version>
+ <description><![CDATA[
+ Information needed to deploy the artifacts generated by the project to a remote repository.
+ ]]></description>
+ <association>
+ <type>DeploymentRepository</type>
+ </association>
+ </field>
+ <field>
+ <name>snapshotRepository</name>
+ <version>4.0.0</version>
+ <description><![CDATA[
+ Where to deploy snapshots of artifacts to. If not given, it defaults to the <code>repository</code> element.
+ ]]></description>
+ <association>
+ <type>DeploymentRepository</type>
+ </association>
+ </field>
+ <field>
+ <name>site</name>
+ <description><![CDATA[
+ Information needed for deploying the web site of the project.
+ ]]></description>
+ <version>4.0.0</version>
+ <association>
+ <type>Site</type>
+ </association>
+ </field>
+ <field>
+ <name>downloadUrl</name>
+ <version>4.0.0+</version>
+ <description><![CDATA[
+ The URL of the project's download page. If not given users will be referred to the homepage given by
+ <code>url</code>. This is given to assist in locating artifacts that are not in the repository due to
+ licensing restrictions.
+ ]]></description>
+ <type>String</type>
+ </field>
+ <field>
+ <name>relocation</name>
+ <version>4.0.0</version>
+ <description>
+ Relocation information of the artifact if it has been moved to a new group ID and/or artifact ID.
+ </description>
+ <association>
+ <type>Relocation</type>
+ </association>
+ </field>
+ <field>
+ <name>status</name>
+ <version>4.0.0</version>
+ <description><![CDATA[
+ Gives the status of this artifact in the remote repository. This must not be set in your local
+ project, as it is updated by tools placing it in the reposiory. Valid values are: <code>none</code> (default),
+ <code>converted</code> (repository manager converted this from an Maven 1 POM), <code>partner</code>
+ (directly synced from a partner Maven 2 repository), <code>deployed</code> (was deployed from a Maven 2
+ instance), <code>verified</code> (has been hand verified as correct and final).
+ ]]></description>
+ <required>false</required>
+ <type>String</type>
+ </field>
+ </fields>
+ </class>
+ <class>
+ <name>License</name>
+ <description><![CDATA[
+ Describes the licenses for this project. This is used to generate
+ the license page of the project's web site, as well as being taken into consideration in other reporting and
+ validation. The licenses listed for the project are that of the project itself, and not of dependencies.
+ ]]></description>
+ <version>3.0.0+</version>
+ <fields>
+ <field>
+ <name>name</name>
+ <version>3.0.0+</version>
+ <description><![CDATA[The full legal name of the license.]]></description>
+ <type>String</type>
+ </field>
+ <field>
+ <name>url</name>
+ <version>3.0.0+</version>
+ <description><![CDATA[The official url for the license text.]]></description>
+ <type>String</type>
+ </field>
+ <field>
+ <name>distribution</name>
+ <version>3.0.0+</version>
+ <description><![CDATA[
+ The primary method by which this project may be distributed.
+ <dl>
+ <dt>repo</dt>
+ <dd>may be downloaded from the Maven repository</dd>
+ <dt>manual</dt>
+ <dd>user must manually download and install the dependency.</dd>
+ </dl>
+ ]]></description>
+ <type>String</type>
+ </field>
+ <field>
+ <name>comments</name>
+ <description>
+ Addendum information pertaining to this license.
+ </description>
+ <version>3.0.0+</version>
+ <type>String</type>
+ </field>
+ </fields>
+ </class>
+ <class>
+ <name>MailingList</name>
+ <version>3.0.0+</version>
+ <description><![CDATA[
+ This element describes all of the mailing lists associated with
+ a project. The auto-generated site references this information.
+ ]]></description>
+ <fields>
+ <field>
+ <name>name</name>
+ <version>3.0.0+</version>
+ <description><![CDATA[The name of the mailing list.]]></description>
+ <type>String</type>
+ </field>
+ <field>
+ <name>subscribe</name>
+ <version>3.0.0+</version>
+ <description><![CDATA[
+ The email address or link that can be used to subscribe to the mailing list.
+ If this is an email address, a
+ <code>mailto:</code> link will automatically be created when
+ the documentation is created.
+ ]]></description>
+ <type>String</type>
+ </field>
+ <field>
+ <name>unsubscribe</name>
+ <version>3.0.0+</version>
+ <description><![CDATA[
+ The email address or link that can be used to unsubscribe to
+ the mailing list. If this is an email address, a
+ <code>mailto:</code> link will automatically be created
+ when the documentation is created.
+ ]]></description>
+ <type>String</type>
+ </field>
+ <field>
+ <name>post</name>
+ <version>3.0.0+</version>
+ <description><![CDATA[
+ The email address or link that can be used to post to
+ the mailing list. If this is an email address, a
+ <code>mailto:</code> link will automatically be created
+ when the documentation is created.
+ ]]></description>
+ <type>String</type>
+ </field>
+ <field>
+ <name>archive</name>
+ <version>3.0.0+</version>
+ <description><![CDATA[
+ The link to a URL where you can browse the mailing list archive.
+ ]]></description>
+ <type>String</type>
+ </field>
+ <field>
+ <name>otherArchives</name>
+ <version>3.0.0+</version>
+ <description><![CDATA[
+ The link to alternate URLs where you can browse the list archive.
+ ]]></description>
+ <association>
+ <type>String</type>
+ <multiplicity>*</multiplicity>
+ </association>
+ </field>
+ </fields>
+ <comment>
+ We could probably have a specific element for a dev mailing list for
+ things like CI, and maybe even a specific element for the user and scm
+ mailing lists. Then leave the more lose structure for any other type
+ of mailing list.
+ </comment>
+ </class>
+ <class>
+ <name>Organization</name>
+ <description>Specifies the organization that produces this project.</description>
+ <version>3.0.0+</version>
+ <fields>
+ <field>
+ <name>name</name>
+ <version>3.0.0+</version>
+ <description><![CDATA[The full name of the organization.]]></description>
+ <type>String</type>
+ </field>
+ <field>
+ <name>url</name>
+ <version>3.0.0+</version>
+ <description><![CDATA[The URL to the organization's home page.]]></description>
+ <type>String</type>
+ </field>
+ <field>
+ <name>logo</name>
+ <version>3.0.0</version>
+ <description><![CDATA[
+ The URL to the organization's logo image. This can be an URL relative
+ to the base directory of the generated web site,
+ (e.g., <code>/images/org-logo.png</code>) or an absolute URL
+ (e.g., <code>http://my.corp/logo.png</code>). This value is used
+ when generating the project documentation.
+ ]]></description>
+ <type>String</type>
+ </field>
+ </fields>
+ </class>
+ <class>
+ <name>PackageGroup</name>
+ <version>3.0.0</version>
+ <description>A JavaDoc package group.</description>
+ <fields>
+ <field>
+ <name>title</name>
+ <version>3.0.0</version>
+ <description><![CDATA[The title to use for the package group.]]></description>
+ <type>String</type>
+ </field>
+ <field>
+ <name>packages</name>
+ <version>3.0.0</version>
+ <description><![CDATA[The packages in the group]]></description>
+ <type>String</type>
+ </field>
+ </fields>
+ </class>
+ <class>
+ <name>PatternSet</name>
+ <version>3.0.0+</version>
+ <fields>
+ <field>
+ <name>includes</name>
+ <version>3.0.0+</version>
+ <description><![CDATA[A list of patterns to include, e.g. <code>**/*.xml</code>.]]></description>
+ <association>
+ <type>String</type>
+ <multiplicity>*</multiplicity>
+ </association>
+ </field>
+ <field>
+ <name>excludes</name>
+ <version>3.0.0+</version>
+ <description><![CDATA[A list of patterns to exclude, e.g. <code>**/*.xml</code>]]></description>
+ <association>
+ <type>String</type>
+ <multiplicity>*</multiplicity>
+ </association>
+ </field>
+ </fields>
+ </class>
+ <class>
+ <name>Parent</name>
+ <version>4.0.0</version>
+ <fields>
+ <field>
+ <name>artifactId</name>
+ <version>4.0.0</version>
+ <description><![CDATA[The artifact id of the parent project to inherit from.]]></description>
+ <required>true</required>
+ <type>String</type>
+ </field>
+ <field>
+ <name>groupId</name>
+ <version>4.0.0</version>
+ <description><![CDATA[The group id of the parent project to inherit from.]]></description>
+ <required>true</required>
+ <type>String</type>
+ </field>
+ <field>
+ <name>version</name>
+ <version>4.0.0</version>
+ <description><![CDATA[The version of the parent project to inherit.]]></description>
+ <type>String</type>
+ </field>
+ <field>
+ <name>relativePath</name>
+ <version>4.0.0</version>
+ <description><![CDATA[
+ The relative path of the parent <code>pom.xml</code> file within the check out.
+ The default value is <code>../pom.xml</code>.
+ Maven looks for the parent pom first in the reactor of currently building projects, then in this location on
+ the filesystem, then the local repository, and lastly in the remote repo.
+ <code>relativePath</code> allows you to select a different location,
+ for example when your structure is flat, or deeper without an intermediate parent pom.
+ However, the group ID, artifact ID and version are still required,
+ and must match the file in the location given or it will revert to the repository for the POM.
+ This feature is only for enhancing the development in a local checkout of that project.
+ ]]></description>
+ <type>String</type>
+ <defaultValue>../pom.xml</defaultValue>
+ </field>
+ </fields>
+ <codeSegments>
+ <codeSegment>
+ <version>4.0.0</version>
+ <code><![CDATA[
+ public String getId()
+ {
+ StringBuffer id = new StringBuffer();
+
+ id.append( getGroupId() );
+ id.append( ":" );
+ id.append( getArtifactId() );
+ id.append( ":" );
+ // id.append( getPackaging() );
+ id.append( ":" );
+ id.append( getVersion() );
+
+ return id.toString();
+ }
+ ]]></code>
+ </codeSegment>
+ </codeSegments>
+
+ </class>
+ <class>
+ <name>Repository</name>
+ <version>3.0.0</version>
+ <fields>
+ <field>
+ <name>connection</name>
+ <version>3.0.0</version>
+ <description><![CDATA[
+ The source control management system URL
+ that describes the repository and how to connect to the
+ repository. For more information, see the
+ <a href="http://maven.apache.org/scm/scm-url-format.html">URL format</a>
+ and <a href="http://maven.apache.org/scm/scms-overview.html">list of supported SCMs</a>.
+ This connection is read-only.
+ ]]></description>
+ <type>String</type>
+ </field>
+ <field>
+ <name>developerConnection</name>
+ <version>3.0.0</version>
+ <description><![CDATA[
+ Just like <code>connection</code>, but for developers, i.e. this scm connection
+ will not be read only.
+ ]]></description>
+ <type>String</type>
+ </field>
+ <field>
+ <name>url</name>
+ <version>3.0.0</version>
+ <description>
+ <![CDATA[The URL to the project's browsable SCM repository, such as ViewVC or Fisheye.]]></description>
+ <type>String</type>
+ </field>
+ </fields>
+ </class>
+ <class>
+ <name>Scm</name>
+ <version>4.0.0</version>
+ <fields>
+ <field>
+ <name>connection</name>
+ <version>4.0.0</version>
+ <description><![CDATA[
+ The source control management system URL
+ that describes the repository and how to connect to the
+ repository. For more information, see the
+ <a href="http://maven.apache.org/scm/scm-url-format.html">URL format</a>
+ and <a href="http://maven.apache.org/scm/scms-overview.html">list of supported SCMs</a>.
+ This connection is read-only.
+ ]]></description>
+ <type>String</type>
+ </field>
+ <field>
+ <name>developerConnection</name>
+ <version>4.0.0</version>
+ <description><![CDATA[
+ Just like <code>connection</code>, but for developers, i.e. this scm connection
+ will not be read only.
+ ]]></description>
+ <type>String</type>
+ </field>
+ <field>
+ <name>tag</name>
+ <version>4.0.0</version>
+ <description><![CDATA[
+ The tag of current code. By default, it's set to HEAD during development.
+ ]]></description>
+ <type>String</type>
+ <defaultValue>HEAD</defaultValue>
+ </field>
+ <field>
+ <name>url</name>
+ <version>4.0.0</version>
+ <description>
+ <![CDATA[The URL to the project's browsable SCM repository, such as ViewVC or Fisheye.]]></description>
+ <type>String</type>
+ </field>
+ </fields>
+ </class>
+ <class>
+ <name>FileSet</name>
+ <version>3.0.0+</version>
+ <superClass>PatternSet</superClass>
+ <fields>
+ <field>
+ <name>directory</name>
+ <version>3.0.0+</version>
+ <description><![CDATA[
+ Describe the directory where the resources are stored.
+ The path is relative to the POM.
+ ]]></description>
+ <type>String</type>
+ </field>
+ </fields>
+ </class>
+ <class>
+ <name>Resource</name>
+ <description><![CDATA[
+ This element describes all of the classpath resources associated with a project or
+ unit tests.
+ ]]></description>
+ <version>3.0.0+</version>
+ <superClass>FileSet</superClass>
+ <fields>
+ <field>
+ <name>targetPath</name>
+ <version>3.0.0+</version>
+ <description><![CDATA[
+ Describe the resource target path. For example, if you want that
+ resource to appear in a specific package
+ (<code>org.apache.maven.messages</code>), you must specify this
+ element with this value: <code>org/apache/maven/messages</code>.
+ This is not required if you simply put the resources in that directory structure at the source, however.
+ ]]></description>
+ <type>String</type>
+ </field>
+ <field>
+ <name>filtering</name>
+ <version>3.0.0+</version>
+ <description><![CDATA[
+ Whether resources are filtered to replace tokens with parameterised values or not.
+ The values are taken from the <code>properties</code> element and from the properties in the files listed
+ in the <code>filters</code> element.
+ ]]></description>
+ <type>boolean</type>
+ <defaultValue>false</defaultValue>
+ </field>
+ </fields>
+ </class>
+ <class>
+ <name>SourceModification</name>
+ <description><![CDATA[
+ This element describes all of the source modifications associated with a
+ project. These modifications are used
+ to exclude or include various source depending on the environment
+ the build is running in.
+ ]]></description>
+ <version>3.0.0</version>
+ <superClass>FileSet</superClass>
+ <fields>
+ <field>
+ <name>className</name>
+ <version>3.0.0</version>
+ <description><![CDATA[
+ If the class with this name can <strong>not</strong> be
+ loaded, then the includes and excludes specified below
+ will be applied to the contents of the <code>sourceDirectory</code>.
+ ]]></description>
+ <type>String</type>
+ </field>
+ <field>
+ <name>property</name>
+ <version>3.0.0</version>
+ <description><![CDATA[
+ If the property with this name is <strong>not</strong> set,
+ then the includes and excludes specified below
+ will be applied to the contents of the <code>sourceDirectory</code>.
+ ]]></description>
+ <type>String</type>
+ </field>
+ </fields>
+ </class>
+ <class>
+ <name>UnitTest</name>
+ <version>3.0.0</version>
+ <superClass>PatternSet</superClass>
+ <fields>
+ <field>
+ <name>resources</name>
+ <version>3.0.0</version>
+ <description><![CDATA[The classpath resources to use when executing the unit tests.]]></description>
+ <association>
+ <type>Resource</type>
+ <multiplicity>*</multiplicity>
+ </association>
+ </field>
+ </fields>
+ </class>
+ <class>
+ <name>Version</name>
+ <version>3.0.0</version>
+ <description><![CDATA[
+ This element describes each of the previous versions of the
+ project. Each version is described by a <code>version</code>
+ element
+ ]]></description>
+ <fields>
+ <field>
+ <name>name</name>
+ <version>3.0.0</version>
+ <description><![CDATA[
+ The external version number under which this release was distributed. Examples include:
+ <code>1.0</code>,
+ <code>1.1-alpha1</code>,
+ <code>1.2-beta</code>,
+ <code>1.3.2</code> etc.
+ ]]></description>
+ <type>String</type>
+ </field>
+ <field>
+ <name>tag</name>
+ <version>3.0.0</version>
+ <description><![CDATA[
+ The name given in the SCM (e.g. CVS) used by the project for the source
+ code associated with this version of the project.
+ ]]></description>
+ <type>String</type>
+ </field>
+ <field>
+ <name>id</name>
+ <version>3.0.0</version>
+ <description><![CDATA[
+ A unique identifier for a version. This is usually identical to the name.
+ </a> builds.
+ ]]></description>
+ <type>String</type>
+ </field>
+ </fields>
+ <codeSegments>
+ <codeSegment>
+ <version>3.0.0</version>
+ <code><![CDATA[
+ public String toString()
+ {
+ return getId();
+ }
+ ]]></code>
+ </codeSegment>
+ </codeSegments>
+ </class>
+
+ <class>
+ <name>RepositoryBase</name>
+ <version>4.0.0</version>
+ <description><![CDATA[
+ A repository contains the information needed
+ for establishing connections with remote repoistory.
+ ]]></description>
+ <fields>
+ <field>
+ <name>id</name>
+ <version>4.0.0</version>
+ <description><![CDATA[
+ A unique identifier for a repository. This is used to match the repository to configuration in
+ the <code>settings.xml</code> file, for example.
+ ]]></description>
+ <type>String</type>
+ </field>
+ <field>
+ <name>name</name>
+ <version>4.0.0</version>
+ <description><![CDATA[
+ Human readable name of the repository.
+ ]]></description>
+ <type>String</type>
+ </field>
+ <field>
+ <name>url</name>
+ <version>4.0.0</version>
+ <description><![CDATA[
+ The url of the repository, in the form <code>protocol://hostname/path</code>.
+ ]]></description>
+ <type>String</type>
+ </field>
+ <field>
+ <name>layout</name>
+ <version>4.0.0</version>
+ <description><![CDATA[
+ The type of layout this repository uses for locating and storing artifacts - can be <code>legacy</code> or
+ <code>default</code>.
+ ]]></description>
+ <type>String</type>
+ <defaultValue>default</defaultValue>
+ </field>
+ </fields>
+ <codeSegments>
+ <codeSegment>
+ <version>4.0.0</version>
+ <code><![CDATA[
+ public boolean equals( Object obj )
+ {
+ RepositoryBase other = (RepositoryBase) obj;
+
+ boolean retValue = false;
+
+ if ( id != null )
+ {
+ retValue = id.equals( other.id );
+ }
+
+ return retValue;
+ }
+ ]]></code>
+ </codeSegment>
+ </codeSegments>
+ </class>
+
+ <class>
+ <name>Repository</name>
+ <superClass>RepositoryBase</superClass>
+ <version>4.0.0</version>
+ <description>
+ A repository contains the information needed for establishing connections with remote repoistory.
+ </description>
+ <fields>
+ <field>
+ <name>releases</name>
+ <version>4.0.0</version>
+ <description>How to handle downloading of releases from this repository.</description>
+ <association>
+ <type>RepositoryPolicy</type>
+ </association>
+ </field>
+ <field>
+ <name>snapshots</name>
+ <version>4.0.0</version>
+ <description>How to handle downloading of snapshots from this repository.</description>
+ <association>
+ <type>RepositoryPolicy</type>
+ </association>
+ </field>
+ </fields>
+ <!-- TODO:prevent modello generation of an incorrect equals method. Could be avoided by using <identity/> tags to mark ID as the only identity field -->
+ <codeSegments>
+ <codeSegment>
+ <version>4.0.0</version>
+ <code><![CDATA[
+ public boolean equals( Object obj )
+ {
+ return super.equals( obj );
+ }
+ ]]></code>
+ </codeSegment>
+ </codeSegments>
+ </class>
+
+ <class>
+ <name>DeploymentRepository</name>
+ <superClass>RepositoryBase</superClass>
+ <version>4.0.0</version>
+ <description>
+ Repository contains the information needed for deploying to the remote repoistory.
+ </description>
+ <fields>
+ <field>
+ <name>uniqueVersion</name>
+ <description>Whether to assign snapshots a unique version comprised of the timestamp and build number, or to
+ use the same version each time</description>
+ <type>boolean</type>
+ <defaultValue>true</defaultValue>
+ <version>4.0.0</version>
+ </field>
+ </fields>
+ <!-- TODO:prevent modello generation of an incorrect equals method. Could be avoided by using <identity/> tags to mark ID as the only identity field -->
+ <codeSegments>
+ <codeSegment>
+ <version>4.0.0</version>
+ <code><![CDATA[
+ public boolean equals( Object obj )
+ {
+ return super.equals( obj );
+ }
+ ]]></code>
+ </codeSegment>
+ </codeSegments>
+ </class>
+
+ <class>
+ <name>RepositoryPolicy</name>
+ <version>4.0.0</version>
+ <description>Download policy</description>
+ <fields>
+ <field>
+ <name>enabled</name>
+ <version>4.0.0</version>
+ <description>Whether to use this repository for downloading this type of artifact.</description>
+ <type>boolean</type>
+ <defaultValue>true</defaultValue>
+ </field>
+ <field>
+ <name>updatePolicy</name>
+ <version>4.0.0</version>
+ <description><![CDATA[
+ The frequency for downloading updates - can be
+ <code>always,</code>
+ <code>daily</code>
+ (default),
+ <code>interval:XXX</code>
+ (in minutes) or
+ <code>never</code>
+ (only if it doesn't exist locally).
+ ]]></description>
+ <type>String</type>
+ </field>
+ <field>
+ <name>checksumPolicy</name>
+ <version>4.0.0</version>
+ <description><![CDATA[
+ What to do when verification of an artifact checksum fails. Valid values are
+ <code>ignore</code>
+ ,
+ <code>fail</code>
+ or
+ <code>warn</code>
+ (the default).
+ ]]></description>
+ <type>String</type>
+ </field>
+ </fields>
+ </class>
+
+ <!--@todo find better solution for management of site deployments -->
+ <class>
+ <name>Site</name>
+ <version>4.0.0</version>
+ <description><![CDATA[
+ Contains the information needed for deploying websites.
+ ]]></description>
+ <fields>
+ <field>
+ <name>id</name>
+ <version>4.0.0</version>
+ <description><![CDATA[
+ A unique identifier for a deployment locataion. This is used to match the site to configuration in
+ the <code>settings.xml</code> file, for example.
+ ]]></description>
+ <type>String</type>
+ </field>
+ <field>
+ <name>name</name>
+ <version>4.0.0</version>
+ <description><![CDATA[
+ Human readable name of the deployment location.
+ ]]></description>
+ <type>String</type>
+ </field>
+ <field>
+ <name>url</name>
+ <version>4.0.0</version>
+ <description><![CDATA[
+ The url of the location where website is deployed, in the form <code>protocol://hostname/path</code>.
+ ]]></description>
+ <type>String</type>
+ </field>
+ </fields>
+ </class>
+
+ <class>
+ <name>ConfigurationContainer</name>
+ <version>4.0.0</version>
+ <fields>
+ <field>
+ <name>inherited</name>
+ <version>4.0.0</version>
+ <description>
+ <![CDATA[Whether any configuration should be propagated to child POMs.]]></description>
+ <type>String</type>
+ </field>
+ <field>
+ <name>configuration</name>
+ <type>DOM</type>
+ </field>
+ </fields>
+ <codeSegments>
+ <codeSegment>
+ <version>4.0.0</version>
+ <code><![CDATA[
+ private boolean inheritanceApplied = true;
+
+ public void unsetInheritanceApplied()
+ {
+ this.inheritanceApplied = false;
+ }
+
+ public boolean isInheritanceApplied()
+ {
+ return inheritanceApplied;
+ }
+ ]]></code>
+ </codeSegment>
+ </codeSegments>
+ </class>
+ <class>
+ <name>Plugin</name>
+ <version>4.0.0</version>
+ <superClass>ConfigurationContainer</superClass>
+ <fields>
+ <field>
+ <name>groupId</name>
+ <description>The group ID of the plugin in the repository.</description>
+ <version>4.0.0</version>
+ <type>String</type>
+ <required>true</required>
+ <defaultValue>org.apache.maven.plugins</defaultValue>
+ </field>
+ <field>
+ <name>artifactId</name>
+ <description>The artifact ID of the plugin in the repository.</description>
+ <version>4.0.0</version>
+ <type>String</type>
+ <required>true</required>
+ </field>
+ <field>
+ <name>version</name>
+ <version>4.0.0</version>
+ <required>true</required>
+ <description><![CDATA[The version (or valid range of verisons) of the plugin to be used.]]></description>
+ <type>String</type>
+ </field>
+ <field>
+ <name>extensions</name>
+ <version>4.0.0</version>
+ <type>boolean</type>
+ <description>Whether to load Maven extensions (such as packaging and type handlers) from this
+ plugin. For performance reasons, this should only be enabled when necessary.</description>
+ <defaultValue>false</defaultValue>
+ </field>
+ <field>
+ <name>executions</name>
+ <version>4.0.0</version>
+ <description>Multiple specifications of a set of goals to execute during the build lifecycle, each having
+ (possibly) different
+ configuration.</description>
+ <association>
+ <type>PluginExecution</type>
+ <multiplicity>*</multiplicity>
+ </association>
+ </field>
+ <field>
+ <name>dependencies</name>
+ <description>Additional dependencies that this project needs to introduce to the plugin's
+ classloader.</description>
+ <version>4.0.0</version>
+ <association>
+ <type>Dependency</type>
+ <multiplicity>*</multiplicity>
+ </association>
+ </field>
+ <field>
+ <name>goals</name>
+ <version>4.0.0</version>
+ <description><![CDATA[
+ <b>Deprecated</b>. Unused by Maven.
+ ]]></description>
+ <type>DOM</type>
+ </field>
+ </fields>
+ <codeSegments>
+ <codeSegment>
+ <version>4.0.0</version>
+ <code><![CDATA[
+ private java.util.Map executionMap = null;
+
+ public void flushExecutionMap()
+ {
+ this.executionMap = null;
+ }
+
+ public java.util.Map getExecutionsAsMap()
+ {
+ if ( executionMap == null )
+ {
+ executionMap = new java.util.HashMap();
+ if ( getExecutions() != null )
+ {
+ for ( java.util.Iterator i = getExecutions().iterator(); i.hasNext(); )
+ {
+ PluginExecution exec = (PluginExecution) i.next();
+
+ if ( executionMap.containsKey( exec.getId() ) )
+ {
+ throw new IllegalStateException( "You cannot have two plugin executions with the same (or missing) <id/> elements.\nOffending execution\n\nId: \'" + exec.getId() + "\'\nPlugin:\'" + getKey() + "\'\n\n" );
+ }
+
+ executionMap.put( exec.getId(), exec );
+ }
+ }
+ }
+
+ return executionMap;
+ }
+
+ public String getKey()
+ {
+ return constructKey( groupId, artifactId );
+ }
+
+ public static String constructKey( String groupId, String artifactId )
+ {
+ return groupId + ":" + artifactId;
+ }
+ ]]></code>
+ </codeSegment>
+ </codeSegments>
+ </class>
+ <class>
+ <name>PluginExecution</name>
+ <version>4.0.0</version>
+ <superClass>ConfigurationContainer</superClass>
+ <fields>
+ <field>
+ <name>id</name>
+ <version>4.0.0</version>
+ <required>true</required>
+ <type>String</type>
+ <defaultValue>default</defaultValue>
+ <description>The identifier of this execution for labelling the goals during the build, and for matching
+ exections to merge during inheritance.</description>
+ </field>
+ <field>
+ <name>phase</name>
+ <version>4.0.0</version>
+ <type>String</type>
+ <description>The build lifecycle phase to bind the goals in this execution to. If omitted, the goals will
+ be bound to the default specified in their metadata.</description>
+ </field>
+ <field>
+ <name>goals</name>
+ <version>4.0.0</version>
+ <description>The goals to execute with the given configuration.</description>
+ <association>
+ <type>String</type>
+ <multiplicity>*</multiplicity>
+ </association>
+ </field>
+ </fields>
+ <codeSegments>
+ <codeSegment>
+ <version>4.0.0</version>
+ <code><![CDATA[
+ public static final String DEFAULT_EXECUTION_ID = "default";
+ ]]></code>
+ </codeSegment>
+ </codeSegments>
+ </class>
+ <class>
+ <name>DependencyManagement</name>
+ <version>4.0.0</version>
+ <description>
+ Section for management of default dependency information for use in a group of POMs.
+ </description>
+ <fields>
+ <field>
+ <name>dependencies</name>
+ <version>4.0.0</version>
+ <description>
+ The dependencies specified here are not used until they
+ are referenced in a POM within the group. This allows the
+ specification of a "standard" version for a particular
+ dependency.
+ </description>
+ <association>
+ <type>Dependency</type>
+ <multiplicity>*</multiplicity>
+ </association>
+ </field>
+ </fields>
+ </class>
+ <class>
+ <name>PluginManagement</name>
+ <version>4.0.0</version>
+ <superClass>PluginContainer</superClass>
+ <description>
+ Section for management of default plugin information for use in a group of POMs.
+ </description>
+ </class>
+ <class>
+ <name>Reporting</name>
+ <version>4.0.0</version>
+ <description>Section for management of reports and their configuration.</description>
+ <fields>
+ <field>
+ <name>excludeDefaults</name>
+ <version>4.0.0</version>
+ <type>boolean</type>
+ <description>If true, then the default reports are not included in the site generation. This includes the
+ reports in the "Project Info" menu.</description>
+ <defaultValue>false</defaultValue>
+ </field>
+ <field>
+ <name>outputDirectory</name>
+ <version>4.0.0</version>
+ <type>String</type>
+ <description><![CDATA[
+ Where to store all of the generated reports. The default is
+ <code>${project.build.directory}/site</code>
+ .
+ ]]></description>
+ <!-- TODO: why isn't default set here? -->
+ </field>
+ <field>
+ <name>plugins</name>
+ <version>4.0.0</version>
+ <description>The reporting plugins to use and their configuration.</description>
+ <association>
+ <type>ReportPlugin</type>
+ <multiplicity>*</multiplicity>
+ </association>
+ </field>
+ </fields>
+ <codeSegments>
+ <codeSegment>
+ <version>4.0.0</version>
+ <code><![CDATA[
+ java.util.Map reportPluginMap;
+
+ public void flushReportPluginMap()
+ {
+ this.reportPluginMap = null;
+ }
+
+ public java.util.Map getReportPluginsAsMap()
+ {
+ if ( reportPluginMap == null )
+ {
+ reportPluginMap = new java.util.HashMap();
+ if ( getPlugins() != null )
+ {
+ for ( java.util.Iterator it = getPlugins().iterator(); it.hasNext(); )
+ {
+ ReportPlugin reportPlugin = (ReportPlugin) it.next();
+ reportPluginMap.put( reportPlugin.getKey(), reportPlugin );
+ }
+ }
+ }
+ return reportPluginMap;
+ }
+ ]]></code>
+ </codeSegment>
+ </codeSegments>
+ </class>
+ <!-- Profile support -->
+ <class>
+ <name>Profile</name>
+ <superClass>ModelBase</superClass>
+ <version>4.0.0</version>
+ <description><![CDATA[
+ Modifications to the build process which is activated based on environmental parameters or command line arguments.
+ ]]></description>
+ <fields>
+ <field>
+ <name>id</name>
+ <required>true</required>
+ <version>4.0.0</version>
+ <type>String</type>
+ <description>The identifier of this build profile. This used both for command line activation, and identifies
+ identical profiles to merge with during inheritance.</description>
+ </field>
+ <field>
+ <name>activation</name>
+ <version>4.0.0</version>
+ <description><![CDATA[The conditional logic which will automatically
+ trigger the inclusion of this profile.]]></description>
+ <association>
+ <type>Activation</type>
+ </association>
+ </field>
+ <field xml.tagName="build">
+ <name>build</name>
+ <version>4.0.0</version>
+ <required>true</required>
+ <description><![CDATA[Information required to build the project.]]></description>
+ <association>
+ <type>BuildBase</type>
+ </association>
+ </field>
+ </fields>
+ <codeSegments>
+ <codeSegment>
+ <version>4.0.0</version>
+ <code><![CDATA[
+ // We don't want this to be parseable...it's sort of 'hidden'
+ // default source for this profile is in the pom itself.
+ private String source = "pom";
+
+ public void setSource( String source )
+ {
+ this.source = source;
+ }
+
+ public String getSource()
+ {
+ return source;
+ }
+
+ public String toString()
+ {
+ return "Profile {id: " + getId() + ", source: " + getSource() + "}";
+ }
+ ]]></code>
+ </codeSegment>
+ </codeSegments>
+ </class>
+ <class>
+ <name>Activation</name>
+ <version>4.0.0</version>
+ <description><![CDATA[
+ The conditions within the build runtime environment which will trigger
+ the automatic inclusion of the build profile.
+ ]]></description>
+ <fields>
+ <field>
+ <name>activeByDefault</name>
+ <version>4.0.0</version>
+ <type>boolean</type>
+ <description>Flag specifying whether this profile is active by default.</description>
+ </field>
+ <field>
+ <name>jdk</name>
+ <version>4.0.0</version>
+ <type>String</type>
+ <description><![CDATA[
+ Specifies that this profile will be activated when a matching JDK is detected. For example, <code>1.4</code>
+ only activates on JDKs versioned 1.4, while <code>!1.4</code> matches any JDK that is not version 1.4.
+ ]]></description>
+ </field>
+ <field>
+ <name>os</name>
+ <version>4.0.0</version>
+ <description><![CDATA[
+ Specifies that this profile will be activated when matching operating system attributes are detected.
+ ]]></description>
+ <association>
+ <type>ActivationOS</type>
+ </association>
+ </field>
+ <field>
+ <name>property</name>
+ <version>4.0.0</version>
+ <description><![CDATA[
+ Specifies that this profile will be activated when this system property is specified.
+ ]]></description>
+ <association>
+ <type>ActivationProperty</type>
+ </association>
+ </field>
+ <field>
+ <name>file</name>
+ <version>4.0.0</version>
+ <description><![CDATA[
+ Specifies that this profile will be activated based on existence of a file.
+ ]]></description>
+ <association>
+ <type>ActivationFile</type>
+ </association>
+ </field>
+ </fields>
+ </class>
+ <class>
+ <name>ActivationProperty</name>
+ <version>4.0.0</version>
+ <description><![CDATA[
+ This is the property specification used to activate a profile. If the value field is empty,
+ then the existence of the named property will activate the profile, otherwise it does a case-sensitive
+ match against the property value as well.
+ ]]></description>
+ <fields>
+ <field>
+ <name>name</name>
+ <version>4.0.0</version>
+ <type>String</type>
+ <required>true</required>
+ <description>The name of the property to be used to activate a profile.</description>
+ </field>
+ <field>
+ <name>value</name>
+ <version>4.0.0</version>
+ <type>String</type>
+ <description>The value of the property required to activate a profile.</description>
+ </field>
+ </fields>
+ </class>
+ <class>
+ <name>ActivationOS</name>
+ <version>4.0.0</version>
+ <description><![CDATA[
+ This is an activator which will detect an operating system's attributes in order to activate
+ its profile.
+ ]]></description>
+ <fields>
+ <field>
+ <name>name</name>
+ <version>4.0.0</version>
+ <type>String</type>
+ <description><![CDATA[The name of the operating system to be used to activate the profile. This must be an exact match
+ of the <code>${os.name}</code> Java property, such as <code>Windows XP</code>.]]></description>
+ </field>
+ <field>
+ <name>family</name>
+ <version>4.0.0</version>
+ <type>String</type>
+ <description>
+ <![CDATA[The general family of the OS to be used to activate the profile, such as <code>windows</code> or <code>unix</code>.]]></description>
+ </field>
+ <field>
+ <name>arch</name>
+ <version>4.0.0</version>
+ <type>String</type>
+ <description>The architecture of the operating system to be used to activate the profile.</description>
+ </field>
+ <field>
+ <name>version</name>
+ <version>4.0.0</version>
+ <type>String</type>
+ <description>The version of the operating system to be used to activate the profile.</description>
+ </field>
+ </fields>
+ </class>
+ <class>
+ <name>ActivationFile</name>
+ <version>4.0.0</version>
+ <description><![CDATA[
+ This is the file specification used to activate the profile. The missing value will be the location
+ of a file that needs to exist, and if it doesn't the profile will be activated. On the other hand exists will test
+ for the existence of the file and if it is there the profile will be activated.
+ ]]></description>
+ <fields>
+ <field>
+ <name>missing</name>
+ <version>4.0.0</version>
+ <type>String</type>
+ <description>The name of the file that must be missing to activate the profile.</description>
+ </field>
+ <field>
+ <name>exists</name>
+ <version>4.0.0</version>
+ <type>String</type>
+ <description>The name of the file that must exist to activate the profile.</description>
+ </field>
+ </fields>
+ </class>
+ <!-- /BuildProfile support -->
+ <class xml.tagName="plugin">
+ <name>ReportPlugin</name>
+ <version>4.0.0</version>
+ <fields>
+ <field>
+ <name>groupId</name>
+ <version>4.0.0</version>
+ <type>String</type>
+ <required>true</required>
+ <defaultValue>org.apache.maven.plugins</defaultValue>
+ <description>The group ID of the reporting plugin in the repository.</description>
+ </field>
+ <field>
+ <name>artifactId</name>
+ <version>4.0.0</version>
+ <type>String</type>
+ <required>true</required>
+ <description>The artifact ID of the reporting plugin in the repository.</description>
+ </field>
+ <field>
+ <name>version</name>
+ <version>4.0.0</version>
+ <description><![CDATA[The version of the reporting plugin to be used.]]></description>
+ <type>String</type>
+ </field>
+ <field>
+ <name>inherited</name>
+ <version>4.0.0</version>
+ <type>String</type>
+ <description>Whether the configuration in this plugin should be made available to projects that
+ inherit from this one.</description>
+ </field>
+ <field>
+ <name>configuration</name>
+ <version>4.0.0</version>
+ <type>DOM</type>
+ <description>The configuration of the reporting plugin.</description>
+ </field>
+ <field>
+ <name>reportSets</name>
+ <version>4.0.0</version>
+ <description><![CDATA[Multiple specifications of a set of reports, each having (possibly) different
+ configuration. This is the reporting parallel to an <code>execution</code> in the build.]]></description>
+ <association>
+ <type>ReportSet</type>
+ <multiplicity>*</multiplicity>
+ </association>
+ </field>
+ </fields>
+ <codeSegments>
+ <codeSegment>
+ <version>4.0.0</version>
+ <code><![CDATA[
+ private java.util.Map reportSetMap = null;
+
+ public void flushReportSetMap()
+ {
+ this.reportSetMap = null;
+ }
+
+ public java.util.Map getReportSetsAsMap()
+ {
+ if ( reportSetMap == null )
+ {
+ reportSetMap = new java.util.HashMap();
+ if ( getReportSets() != null )
+ {
+ for ( java.util.Iterator i = getReportSets().iterator(); i.hasNext(); )
+ {
+ ReportSet reportSet = (ReportSet) i.next();
+ reportSetMap.put( reportSet.getId(), reportSet );
+ }
+ }
+ }
+
+ return reportSetMap;
+ }
+
+ public String getKey()
+ {
+ return constructKey( groupId, artifactId );
+ }
+
+ public static String constructKey( String groupId, String artifactId )
+ {
+ return groupId + ":" + artifactId;
+ }
+
+ private boolean inheritanceApplied = true;
+
+ public void unsetInheritanceApplied()
+ {
+ this.inheritanceApplied = false;
+ }
+
+ public boolean isInheritanceApplied()
+ {
+ return inheritanceApplied;
+ }
+ ]]></code>
+ </codeSegment>
+ </codeSegments>
+ </class>
+ <class>
+ <name>ReportSet</name>
+ <version>4.0.0</version>
+ <description>Represents a set of reports and configuration to be used to generate them.</description>
+ <fields>
+ <field>
+ <name>id</name>
+ <type>String</type>
+ <required>true</required>
+ <description>The unique id for this report set, to be used during POM inheritance.</description>
+ <defaultValue>default</defaultValue>
+ </field>
+ <field>
+ <name>configuration</name>
+ <version>4.0.0</version>
+ <description>Configuration of the report to be used when generating this set.</description>
+ <type>DOM</type>
+ </field>
+ <field>
+ <name>inherited</name>
+ <version>4.0.0</version>
+ <type>String</type>
+ <description>
+ <![CDATA[Whether any configuration should be propagated to child POMs.]]></description>
+ </field>
+ <field>
+ <name>reports</name>
+ <version>4.0.0</version>
+ <required>true</required>
+ <description><![CDATA[
+ The list of reports from this plugin which should be generated from this set.
+ ]]></description>
+ <association>
+ <type>String</type>
+ <multiplicity>*</multiplicity>
+ </association>
+ </field>
+ </fields>
+ <codeSegments>
+ <codeSegment>
+ <version>4.0.0</version>
+ <code><![CDATA[
+ private boolean inheritanceApplied = true;
+
+ public void unsetInheritanceApplied()
+ {
+ this.inheritanceApplied = false;
+ }
+
+ public boolean isInheritanceApplied()
+ {
+ return inheritanceApplied;
+ }
+ ]]></code>
+ </codeSegment>
+ </codeSegments>
+ </class>
+ <class>
+ <name>Prerequisites</name>
+ <version>4.0.0</version>
+ <description>Describes the prerequisites a project can have.</description>
+ <fields>
+ <field>
+ <name>maven</name>
+ <version>4.0.0</version>
+ <type>String</type>
+ <defaultValue>2.0</defaultValue>
+ <description>The minimum version of Maven required to build the project, or to use this plugin.</description>
+ <required>false</required>
+ </field>
+ </fields>
+ </class>
+ <class>
+ <name>Relocation</name>
+ <version>4.0.0</version>
+ <description>Describes where an artifact has moved to. If any of the values are omitted, it is assumed to be the
+ same as it was before.</description>
+ <fields>
+ <field>
+ <name>groupId</name>
+ <version>4.0.0</version>
+ <description>The group ID the artifact has moved to.</description>
+ <type>String</type>
+ </field>
+ <field>
+ <name>artifactId</name>
+ <version>4.0.0</version>
+ <description>The new artifact ID of the artifact.</description>
+ <type>String</type>
+ </field>
+ <field>
+ <name>version</name>
+ <version>4.0.0</version>
+ <description>The new version of the artifact.</description>
+ <type>String</type>
+ </field>
+ <field>
+ <name>message</name>
+ <version>4.0.0</version>
+ <description>An additional message to show the user about the move, such as the reason.</description>
+ <type>String</type>
+ </field>
+ </fields>
+ </class>
+ <class>
+ <name>Extension</name>
+ <version>4.0.0</version>
+ <description>Describes a build extension to utilise.</description>
+ <fields>
+ <field>
+ <name>groupId</name>
+ <version>4.0.0</version>
+ <description>The group ID of the extension's artifact.</description>
+ <required>true</required>
+ <type>String</type>
+ </field>
+ <field>
+ <name>artifactId</name>
+ <version>4.0.0</version>
+ <description>The artifact ID of the extension.</description>
+ <required>true</required>
+ <type>String</type>
+ </field>
+ <field>
+ <name>version</name>
+ <version>4.0.0</version>
+ <description>The version of the extension.</description>
+ <type>String</type>
+ </field>
+ </fields>
+ <codeSegments>
+ <codeSegment>
+ <version>4.0.0</version>
+ <code><![CDATA[
+ public boolean equals( Object o )
+ {
+ if ( this == o )
+ {
+ return true;
+ }
+
+ if ( !( o instanceof Extension ) )
+ {
+ return false;
+ }
+
+ Extension e = (Extension) o;
+
+ if ( !e.getArtifactId().equals( getArtifactId() ) )
+ {
+ return false;
+ }
+ else if ( !e.getGroupId().equals( getGroupId() ) )
+ {
+ return false;
+ }
+ else if ( e.getVersion() != null ? !e.getVersion().equals( getVersion() ) : getVersion() != null )
+ {
+ return false;
+ }
+ return true;
+ }
+
+ public int hashCode()
+ {
+ int result = 17;
+ result = 37 * result + getArtifactId().hashCode();
+ result = 37 * result + getGroupId().hashCode();
+ result = 37 * result + getVersion() != null ? getVersion().hashCode() : 0;
+ return result;
+ }
+ ]]></code>
+ </codeSegment>
+ </codeSegments>
+ </class>
+ </classes>
+</model>
+
diff --git a/grarchetype-common/src/main/resources/archetype-catalog.xml b/grarchetype-common/src/main/resources/archetype-catalog.xml
new file mode 100644
index 0000000..19198bf
--- /dev/null
+++ b/grarchetype-common/src/main/resources/archetype-catalog.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<archetype-catalog>
+ <archetypes>
+ <archetype>
+ <groupId>org.apache.maven.archetypes</groupId>
+ <artifactId>maven-archetype-quickstart</artifactId>
+ <version>RELEASE</version>
+ <description></description>
+ </archetype>
+ <archetype>
+ <groupId>org.codehaus.groovy.maven.archetypes</groupId>
+ <artifactId>gmaven-archetype-basic</artifactId>
+ <version>1.0-rc-3</version>
+ <description>Groovy basic archetype</description>
+ </archetype>
+ <archetype>
+ <groupId>org.codehaus.groovy.maven.archetypes</groupId>
+ <artifactId>gmaven-archetype-basic</artifactId>
+ <version>1.0-rc-4</version>
+ <description>Groovy basic archetype</description>
+ </archetype>
+ </archetypes>
+</archetype-catalog>
\ No newline at end of file
diff --git a/grarchetype-common/src/test/archetypes/basic-with-parent/META-INF/maven/archetype-metadata.xml b/grarchetype-common/src/test/archetypes/basic-with-parent/META-INF/maven/archetype-metadata.xml
new file mode 100644
index 0000000..5288eec
--- /dev/null
+++ b/grarchetype-common/src/test/archetypes/basic-with-parent/META-INF/maven/archetype-metadata.xml
@@ -0,0 +1,44 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ 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.
+ -->
+<archetype-descriptor name="basic-with-parent" partial="false" >
+
+ <requiredProperties>
+ <requiredProperty key="propertyWithDefault">
+ <defaultValue>default-value</defaultValue>
+ </requiredProperty>
+ <requiredProperty key="propertyWithoutDefault"/>
+ </requiredProperties>
+
+ <fileSets>
+ <fileSet filtered="true" packaged="true" engine="groovy">
+ <directory>src/main/java</directory>
+ <includes>
+ <include>**/*.java</include>
+ </includes>
+ </fileSet>
+ <fileSet filtered="false" packaged="false">
+ <directory>src/main/resources</directory>
+ <includes>
+ <include>**/*.png</include>
+ </includes>
+ </fileSet>
+ </fileSets>
+
+</archetype-descriptor>
diff --git a/grarchetype-common/src/test/archetypes/basic-with-parent/archetype-resources/pom.xml b/grarchetype-common/src/test/archetypes/basic-with-parent/archetype-resources/pom.xml
new file mode 100644
index 0000000..be4d42a
--- /dev/null
+++ b/grarchetype-common/src/test/archetypes/basic-with-parent/archetype-resources/pom.xml
@@ -0,0 +1,51 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ 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.
+ -->
+<project
+ xmlns="http://maven.apache.org/POM/4.0.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.apache.maven.archetype.test</groupId>
+ <artifactId>parent-doesnt-exist</artifactId>
+ <version>99.9</version>
+ </parent>
+
+ <groupId>${groupId}</groupId>
+ <artifactId>${artifactId}</artifactId>
+ <version>${version}</version>
+
+ <name>Maven archetype Test</name>
+ <packaging>jar</packaging>
+
+ <properties>
+ <junit.version>3.8.2</junit.version>
+ <anotherProperty><![CDATA[Some CDATA Content]]></anotherProperty>
+ </properties>
+ <dependencies>
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <version>\${junit.version}</version>
+ </dependency>
+ </dependencies>
+</project>
\ No newline at end of file
diff --git a/grarchetype-common/src/test/archetypes/basic-with-parent/archetype-resources/src/main/java/App.java b/grarchetype-common/src/test/archetypes/basic-with-parent/archetype-resources/src/main/java/App.java
new file mode 100644
index 0000000..7eaed48
--- /dev/null
+++ b/grarchetype-common/src/test/archetypes/basic-with-parent/archetype-resources/src/main/java/App.java
@@ -0,0 +1,17 @@
+package ${packageName};
+
+public class App {
+/*
+groupId = ${groupId}
+artifactId = ${artifactId}
+version = ${version}
+package = ${packageName}
+propertyWithDefault = ${propertyWithDefault}
+propertyWithoutDefault = ${propertyWithoutDefault}
+
+packageReplaced = ${packageName.replace('.', '/')}
+packageReplaced2 = <%=packageName.replace('.', '/')%>
+ignoredDollar = \${packageName.replace('.', '/')}
+ignoredInferior = ${'<'}%=packageName.replace('.', '/')%>
+*/
+}
diff --git a/grarchetype-common/src/test/archetypes/basic-with-parent/archetype-resources/src/main/resources/images/foo.png b/grarchetype-common/src/test/archetypes/basic-with-parent/archetype-resources/src/main/resources/images/foo.png
new file mode 100644
index 0000000..fe930bd
--- /dev/null
+++ b/grarchetype-common/src/test/archetypes/basic-with-parent/archetype-resources/src/main/resources/images/foo.png
@@ -0,0 +1,13 @@
+/*
+groupId = ${groupId}
+artifactId = ${artifactId}
+version = ${version}
+package = ${packageName}
+propertyWithDefault = ${propertyWithDefault}
+propertyWithoutDefault = ${propertyWithoutDefault}
+
+packageReplaced = ${packageName.replace('.', '/')}
+packageReplaced2 = <%=packageName.replace('.', '/')%>
+ignoredDollar = \${packageName.replace('.', '/')}
+ignoredInferior = ${'<'}%=packageName.replace('.', '/')%>
+*/
\ No newline at end of file
diff --git a/grarchetype-common/src/test/archetypes/basic/META-INF/maven/archetype-metadata.xml b/grarchetype-common/src/test/archetypes/basic/META-INF/maven/archetype-metadata.xml
new file mode 100644
index 0000000..91bcbf8
--- /dev/null
+++ b/grarchetype-common/src/test/archetypes/basic/META-INF/maven/archetype-metadata.xml
@@ -0,0 +1,44 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ 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.
+ -->
+<archetype-descriptor name="basic" partial="false" >
+
+ <requiredProperties>
+ <requiredProperty key="propertyWithDefault">
+ <defaultValue>default-value</defaultValue>
+ </requiredProperty>
+ <requiredProperty key="propertyWithoutDefault"/>
+ </requiredProperties>
+
+ <fileSets>
+ <fileSet filtered="true" packaged="true" engine="groovy">
+ <directory>src/main/java</directory>
+ <includes>
+ <include>**/*.java</include>
+ </includes>
+ </fileSet>
+ <fileSet filtered="false" packaged="false">
+ <directory>src/main/resources</directory>
+ <includes>
+ <include>**/*.png</include>
+ </includes>
+ </fileSet>
+ </fileSets>
+
+</archetype-descriptor>
diff --git a/grarchetype-common/src/test/archetypes/basic/archetype-resources/pom.xml b/grarchetype-common/src/test/archetypes/basic/archetype-resources/pom.xml
new file mode 100644
index 0000000..d765392
--- /dev/null
+++ b/grarchetype-common/src/test/archetypes/basic/archetype-resources/pom.xml
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ 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.
+ -->
+<project
+ xmlns="http://maven.apache.org/POM/4.0.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+
+ <modelVersion>4.0.0</modelVersion>
+
+ <groupId>${groupId}</groupId>
+ <artifactId>${artifactId}</artifactId>
+ <version>${version}</version>
+
+ <name>Maven archetype Test</name>
+ <packaging>jar</packaging>
+
+ <properties>
+ <junit.version>3.8.2</junit.version>
+ <anotherProperty><![CDATA[Some CDATA Content]]></anotherProperty>
+ </properties>
+ <dependencies>
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <version>\${junit.version}</version>
+ </dependency>
+ </dependencies>
+</project>
\ No newline at end of file
diff --git a/grarchetype-common/src/test/archetypes/basic/archetype-resources/src/main/java/App.java b/grarchetype-common/src/test/archetypes/basic/archetype-resources/src/main/java/App.java
new file mode 100644
index 0000000..7eaed48
--- /dev/null
+++ b/grarchetype-common/src/test/archetypes/basic/archetype-resources/src/main/java/App.java
@@ -0,0 +1,17 @@
+package ${packageName};
+
+public class App {
+/*
+groupId = ${groupId}
+artifactId = ${artifactId}
+version = ${version}
+package = ${packageName}
+propertyWithDefault = ${propertyWithDefault}
+propertyWithoutDefault = ${propertyWithoutDefault}
+
+packageReplaced = ${packageName.replace('.', '/')}
+packageReplaced2 = <%=packageName.replace('.', '/')%>
+ignoredDollar = \${packageName.replace('.', '/')}
+ignoredInferior = ${'<'}%=packageName.replace('.', '/')%>
+*/
+}
diff --git a/grarchetype-common/src/test/archetypes/basic/archetype-resources/src/main/resources/images/foo.png b/grarchetype-common/src/test/archetypes/basic/archetype-resources/src/main/resources/images/foo.png
new file mode 100644
index 0000000..fe930bd
--- /dev/null
+++ b/grarchetype-common/src/test/archetypes/basic/archetype-resources/src/main/resources/images/foo.png
@@ -0,0 +1,13 @@
+/*
+groupId = ${groupId}
+artifactId = ${artifactId}
+version = ${version}
+package = ${packageName}
+propertyWithDefault = ${propertyWithDefault}
+propertyWithoutDefault = ${propertyWithoutDefault}
+
+packageReplaced = ${packageName.replace('.', '/')}
+packageReplaced2 = <%=packageName.replace('.', '/')%>
+ignoredDollar = \${packageName.replace('.', '/')}
+ignoredInferior = ${'<'}%=packageName.replace('.', '/')%>
+*/
\ No newline at end of file
diff --git a/grarchetype-common/src/test/archetypes/multi-with-parent/META-INF/maven/archetype-metadata.xml b/grarchetype-common/src/test/archetypes/multi-with-parent/META-INF/maven/archetype-metadata.xml
new file mode 100644
index 0000000..b99ff01
--- /dev/null
+++ b/grarchetype-common/src/test/archetypes/multi-with-parent/META-INF/maven/archetype-metadata.xml
@@ -0,0 +1,49 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ 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.
+ -->
+<archetype-descriptor name="multi-with-parent" partial="false" >
+
+ <requiredProperties>
+ <requiredProperty key="propertyWithDefault">
+ <defaultValue>default-value</defaultValue>
+ </requiredProperty>
+ <requiredProperty key="propertyWithoutDefault"/>
+ </requiredProperties>
+
+ <fileSets/>
+
+ <modules>
+ <module artifactId="${ignoredProperty}" />
+ <module artifactId="${rootArtifactId}-a" />
+ <module artifactId="${rootArtifactId}-b" />
+ <module artifactId="${rootArtifactId}-c">
+ <modules>
+ <module artifactId="${rootArtifactId}-d" />
+ <module artifactId="${rootArtifactId}-e">
+ <modules>
+ <module artifactId="${rootArtifactId}-f" />
+ <module artifactId="${rootArtifactId}-g" />
+ <module artifactId="${upArtifactId}-h" />
+ </modules>
+ </module>
+ </modules>
+ </module>
+ </modules>
+
+</archetype-descriptor>
diff --git "a/grarchetype-common/src/test/archetypes/multi-with-parent/archetype-resources/$\173ignoredProperty\175/pom.xml" "b/grarchetype-common/src/test/archetypes/multi-with-parent/archetype-resources/$\173ignoredProperty\175/pom.xml"
new file mode 100644
index 0000000..f8bb6b3
--- /dev/null
+++ "b/grarchetype-common/src/test/archetypes/multi-with-parent/archetype-resources/$\173ignoredProperty\175/pom.xml"
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project
+ xmlns="http://maven.apache.org/POM/4.0.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>${groupId}</groupId>
+ <artifactId>${upArtifactId}</artifactId>
+ <version>${version}</version>
+ </parent>
+
+ <artifactId>${artifactId}</artifactId>
+ <version>${version}</version>
+
+ <packaging>jar</packaging>
+
+ <properties>
+ <replace>
+ artifactId = ${artifactId}
+ rootArtifactId = ${rootArtifactId}
+ upArtifactId = ${upArtifactId}
+ </replace>
+ </properties>
+</project>
\ No newline at end of file
diff --git "a/grarchetype-common/src/test/archetypes/multi-with-parent/archetype-resources/$\173rootArtifactId\175-a/pom.xml" "b/grarchetype-common/src/test/archetypes/multi-with-parent/archetype-resources/$\173rootArtifactId\175-a/pom.xml"
new file mode 100644
index 0000000..f8bb6b3
--- /dev/null
+++ "b/grarchetype-common/src/test/archetypes/multi-with-parent/archetype-resources/$\173rootArtifactId\175-a/pom.xml"
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project
+ xmlns="http://maven.apache.org/POM/4.0.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>${groupId}</groupId>
+ <artifactId>${upArtifactId}</artifactId>
+ <version>${version}</version>
+ </parent>
+
+ <artifactId>${artifactId}</artifactId>
+ <version>${version}</version>
+
+ <packaging>jar</packaging>
+
+ <properties>
+ <replace>
+ artifactId = ${artifactId}
+ rootArtifactId = ${rootArtifactId}
+ upArtifactId = ${upArtifactId}
+ </replace>
+ </properties>
+</project>
\ No newline at end of file
diff --git "a/grarchetype-common/src/test/archetypes/multi-with-parent/archetype-resources/$\173rootArtifactId\175-b/pom.xml" "b/grarchetype-common/src/test/archetypes/multi-with-parent/archetype-resources/$\173rootArtifactId\175-b/pom.xml"
new file mode 100644
index 0000000..9a59f03
--- /dev/null
+++ "b/grarchetype-common/src/test/archetypes/multi-with-parent/archetype-resources/$\173rootArtifactId\175-b/pom.xml"
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project
+ xmlns="http://maven.apache.org/POM/4.0.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>${groupId}</groupId>
+ <artifactId>${upArtifactId}</artifactId>
+ <version>${version}</version>
+ </parent>
+
+ <artifactId>${artifactId}</artifactId>
+ <version>${version}</version>
+
+ <packaging>jar</packaging>
+
+ <dependencies>
+ <dependency>
+ <groupId>${groupId}</groupId>
+ <artifactId>${rootArtifactId}-a</artifactId>
+ <version>${version}</version>
+ </dependency>
+ </dependencies>
+
+ <properties>
+ <replace>
+ artifactId = ${artifactId}
+ rootArtifactId = ${rootArtifactId}
+ upArtifactId = ${upArtifactId}
+ </replace>
+ </properties>
+</project>
\ No newline at end of file
diff --git "a/grarchetype-common/src/test/archetypes/multi-with-parent/archetype-resources/$\173rootArtifactId\175-c/$\173rootArtifactId\175-d/pom.xml" "b/grarchetype-common/src/test/archetypes/multi-with-parent/archetype-resources/$\173rootArtifactId\175-c/$\173rootArtifactId\175-d/pom.xml"
new file mode 100644
index 0000000..b111bb3
--- /dev/null
+++ "b/grarchetype-common/src/test/archetypes/multi-with-parent/archetype-resources/$\173rootArtifactId\175-c/$\173rootArtifactId\175-d/pom.xml"
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project
+ xmlns="http://maven.apache.org/POM/4.0.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>${groupId}</groupId>
+ <artifactId>${upArtifactId}</artifactId>
+ <version>${version}</version>
+ </parent>
+
+ <artifactId>${artifactId}</artifactId>
+ <version>${version}</version>
+
+ <packaging>jar</packaging>
+
+ <dependencies>
+ <dependency>
+ <groupId>${groupId}</groupId>
+ <artifactId>${rootArtifactId}-b</artifactId>
+ <version>${version}</version>
+ </dependency>
+ </dependencies>
+
+ <properties>
+ <replace>
+ artifactId = ${artifactId}
+ rootArtifactId = ${rootArtifactId}
+ upArtifactId = ${upArtifactId}
+ </replace>
+ </properties>
+</project>
\ No newline at end of file
diff --git "a/grarchetype-common/src/test/archetypes/multi-with-parent/archetype-resources/$\173rootArtifactId\175-c/$\173rootArtifactId\175-e/$\173rootArtifactId\175-f/pom.xml" "b/grarchetype-common/src/test/archetypes/multi-with-parent/archetype-resources/$\173rootArtifactId\175-c/$\173rootArtifactId\175-e/$\173rootArtifactId\175-f/pom.xml"
new file mode 100644
index 0000000..7b015df
--- /dev/null
+++ "b/grarchetype-common/src/test/archetypes/multi-with-parent/archetype-resources/$\173rootArtifactId\175-c/$\173rootArtifactId\175-e/$\173rootArtifactId\175-f/pom.xml"
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project
+ xmlns="http://maven.apache.org/POM/4.0.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>${groupId}</groupId>
+ <artifactId>${upArtifactId}</artifactId>
+ <version>${version}</version>
+ </parent>
+
+ <artifactId>${artifactId}</artifactId>
+ <version>${version}</version>
+
+ <packaging>jar</packaging>
+
+ <dependencies>
+ <dependency>
+ <groupId>${groupId}</groupId>
+ <artifactId>${rootArtifactId}-d</artifactId>
+ <version>${version}</version>
+ </dependency>
+ </dependencies>
+
+ <properties>
+ <replace>
+ artifactId = ${artifactId}
+ rootArtifactId = ${rootArtifactId}
+ upArtifactId = ${upArtifactId}
+ </replace>
+ </properties>
+</project>
\ No newline at end of file
diff --git "a/grarchetype-common/src/test/archetypes/multi-with-parent/archetype-resources/$\173rootArtifactId\175-c/$\173rootArtifactId\175-e/$\173rootArtifactId\175-g/pom.xml" "b/grarchetype-common/src/test/archetypes/multi-with-parent/archetype-resources/$\173rootArtifactId\175-c/$\173rootArtifactId\175-e/$\173rootArtifactId\175-g/pom.xml"
new file mode 100644
index 0000000..24d44bd
--- /dev/null
+++ "b/grarchetype-common/src/test/archetypes/multi-with-parent/archetype-resources/$\173rootArtifactId\175-c/$\173rootArtifactId\175-e/$\173rootArtifactId\175-g/pom.xml"
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project
+ xmlns="http://maven.apache.org/POM/4.0.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>${groupId}</groupId>
+ <artifactId>${upArtifactId}</artifactId>
+ <version>${version}</version>
+ </parent>
+
+ <artifactId>${artifactId}</artifactId>
+ <version>${version}</version>
+
+ <packaging>jar</packaging>
+
+ <dependencies>
+ <dependency>
+ <groupId>${groupId}</groupId>
+ <artifactId>${rootArtifactId}-f</artifactId>
+ <version>${version}</version>
+ </dependency>
+ </dependencies>
+
+ <properties>
+ <replace>
+ artifactId = ${artifactId}
+ rootArtifactId = ${rootArtifactId}
+ upArtifactId = ${upArtifactId}
+ </replace>
+ </properties>
+</project>
\ No newline at end of file
diff --git "a/grarchetype-common/src/test/archetypes/multi-with-parent/archetype-resources/$\173rootArtifactId\175-c/$\173rootArtifactId\175-e/$\173upArtifactId\175-h/pom.xml" "b/grarchetype-common/src/test/archetypes/multi-with-parent/archetype-resources/$\173rootArtifactId\175-c/$\173rootArtifactId\175-e/$\173upArtifactId\175-h/pom.xml"
new file mode 100644
index 0000000..f1fae43
--- /dev/null
+++ "b/grarchetype-common/src/test/archetypes/multi-with-parent/archetype-resources/$\173rootArtifactId\175-c/$\173rootArtifactId\175-e/$\173upArtifactId\175-h/pom.xml"
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project
+ xmlns="http://maven.apache.org/POM/4.0.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>${groupId}</groupId>
+ <artifactId>${upArtifactId}</artifactId>
+ <version>${version}</version>
+ </parent>
+
+ <artifactId>${artifactId}</artifactId>
+ <version>${version}</version>
+
+ <packaging>jar</packaging>
+
+ <dependencies>
+ <dependency>
+ <groupId>${groupId}</groupId>
+ <artifactId>${rootArtifactId}-g</artifactId>
+ <version>${version}</version>
+ </dependency>
+ </dependencies>
+
+ <properties>
+ <replace>
+ artifactId = ${artifactId}
+ rootArtifactId = ${rootArtifactId}
+ upArtifactId = ${upArtifactId}
+ </replace>
+ </properties>
+</project>
\ No newline at end of file
diff --git "a/grarchetype-common/src/test/archetypes/multi-with-parent/archetype-resources/$\173rootArtifactId\175-c/$\173rootArtifactId\175-e/pom.xml" "b/grarchetype-common/src/test/archetypes/multi-with-parent/archetype-resources/$\173rootArtifactId\175-c/$\173rootArtifactId\175-e/pom.xml"
new file mode 100644
index 0000000..7416da5
--- /dev/null
+++ "b/grarchetype-common/src/test/archetypes/multi-with-parent/archetype-resources/$\173rootArtifactId\175-c/$\173rootArtifactId\175-e/pom.xml"
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project
+ xmlns="http://maven.apache.org/POM/4.0.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>${groupId}</groupId>
+ <artifactId>${upArtifactId}</artifactId>
+ <version>${version}</version>
+ </parent>
+
+ <artifactId>${artifactId}</artifactId>
+ <version>${version}</version>
+
+ <packaging>pom</packaging>
+
+ <modules>
+ <module>${rootArtifactId}-f</module>
+ <module>${rootArtifactId}-g</module>
+ <module>${upArtifactId}-h</module>
+ </modules>
+
+ <properties>
+ <replace>
+ artifactId = ${artifactId}
+ rootArtifactId = ${rootArtifactId}
+ upArtifactId = ${upArtifactId}
+ </replace>
+ </properties>
+</project>
\ No newline at end of file
diff --git "a/grarchetype-common/src/test/archetypes/multi-with-parent/archetype-resources/$\173rootArtifactId\175-c/pom.xml" "b/grarchetype-common/src/test/archetypes/multi-with-parent/archetype-resources/$\173rootArtifactId\175-c/pom.xml"
new file mode 100644
index 0000000..7ddd96d
--- /dev/null
+++ "b/grarchetype-common/src/test/archetypes/multi-with-parent/archetype-resources/$\173rootArtifactId\175-c/pom.xml"
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project
+ xmlns="http://maven.apache.org/POM/4.0.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>${groupId}</groupId>
+ <artifactId>${upArtifactId}</artifactId>
+ <version>${version}</version>
+ </parent>
+
+ <artifactId>${artifactId}</artifactId>
+ <version>${version}</version>
+
+ <packaging>pom</packaging>
+
+ <modules>
+ <module>${rootArtifactId}-d</module>
+ <module>${rootArtifactId}-e</module>
+ </modules>
+
+ <properties>
+ <replace>
+ artifactId = ${artifactId}
+ rootArtifactId = ${rootArtifactId}
+ upArtifactId = ${upArtifactId}
+ </replace>
+ </properties>
+</project>
\ No newline at end of file
diff --git a/grarchetype-common/src/test/archetypes/multi-with-parent/archetype-resources/pom.xml b/grarchetype-common/src/test/archetypes/multi-with-parent/archetype-resources/pom.xml
new file mode 100644
index 0000000..e3c34e8
--- /dev/null
+++ b/grarchetype-common/src/test/archetypes/multi-with-parent/archetype-resources/pom.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project
+ xmlns="http://maven.apache.org/POM/4.0.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.apache.maven.archetype.test</groupId>
+ <artifactId>parent-doesnt-exist</artifactId>
+ <version>99.9</version>
+ </parent>
+
+ <groupId>${groupId}</groupId>
+ <artifactId>${artifactId}</artifactId>
+ <version>${version}</version>
+
+ <packaging>pom</packaging>
+
+ <modules>
+ <module>${rootArtifactId}-a</module>
+ <module>${rootArtifactId}-b</module>
+ <module>${rootArtifactId}-c</module>
+ </modules>
+
+ <properties>
+ <replace>
+ artifactId = ${artifactId}
+ rootArtifactId = ${rootArtifactId}
+ upArtifactId = ${upArtifactId}
+ </replace>
+ </properties>
+</project>
\ No newline at end of file
diff --git a/grarchetype-common/src/test/archetypes/multi/META-INF/maven/archetype-metadata.xml b/grarchetype-common/src/test/archetypes/multi/META-INF/maven/archetype-metadata.xml
new file mode 100644
index 0000000..e947a25
--- /dev/null
+++ b/grarchetype-common/src/test/archetypes/multi/META-INF/maven/archetype-metadata.xml
@@ -0,0 +1,49 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ 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.
+ -->
+<archetype-descriptor name="multi" partial="false" >
+
+ <requiredProperties>
+ <requiredProperty key="propertyWithDefault">
+ <defaultValue>default-value</defaultValue>
+ </requiredProperty>
+ <requiredProperty key="propertyWithoutDefault"/>
+ </requiredProperties>
+
+ <fileSets/>
+
+ <modules>
+ <module artifactId="${ignoredProperty}" />
+ <module artifactId="${rootArtifactId}-a" />
+ <module artifactId="${rootArtifactId}-b" />
+ <module artifactId="${rootArtifactId}-c">
+ <modules>
+ <module artifactId="${rootArtifactId}-d" />
+ <module artifactId="${rootArtifactId}-e">
+ <modules>
+ <module artifactId="${rootArtifactId}-f" />
+ <module artifactId="${rootArtifactId}-g" />
+ <module artifactId="${upArtifactId}-h" />
+ </modules>
+ </module>
+ </modules>
+ </module>
+ </modules>
+
+</archetype-descriptor>
diff --git "a/grarchetype-common/src/test/archetypes/multi/archetype-resources/$\173ignoredProperty\175/pom.xml" "b/grarchetype-common/src/test/archetypes/multi/archetype-resources/$\173ignoredProperty\175/pom.xml"
new file mode 100644
index 0000000..f8bb6b3
--- /dev/null
+++ "b/grarchetype-common/src/test/archetypes/multi/archetype-resources/$\173ignoredProperty\175/pom.xml"
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project
+ xmlns="http://maven.apache.org/POM/4.0.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>${groupId}</groupId>
+ <artifactId>${upArtifactId}</artifactId>
+ <version>${version}</version>
+ </parent>
+
+ <artifactId>${artifactId}</artifactId>
+ <version>${version}</version>
+
+ <packaging>jar</packaging>
+
+ <properties>
+ <replace>
+ artifactId = ${artifactId}
+ rootArtifactId = ${rootArtifactId}
+ upArtifactId = ${upArtifactId}
+ </replace>
+ </properties>
+</project>
\ No newline at end of file
diff --git "a/grarchetype-common/src/test/archetypes/multi/archetype-resources/$\173rootArtifactId\175-a/pom.xml" "b/grarchetype-common/src/test/archetypes/multi/archetype-resources/$\173rootArtifactId\175-a/pom.xml"
new file mode 100644
index 0000000..f8bb6b3
--- /dev/null
+++ "b/grarchetype-common/src/test/archetypes/multi/archetype-resources/$\173rootArtifactId\175-a/pom.xml"
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project
+ xmlns="http://maven.apache.org/POM/4.0.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>${groupId}</groupId>
+ <artifactId>${upArtifactId}</artifactId>
+ <version>${version}</version>
+ </parent>
+
+ <artifactId>${artifactId}</artifactId>
+ <version>${version}</version>
+
+ <packaging>jar</packaging>
+
+ <properties>
+ <replace>
+ artifactId = ${artifactId}
+ rootArtifactId = ${rootArtifactId}
+ upArtifactId = ${upArtifactId}
+ </replace>
+ </properties>
+</project>
\ No newline at end of file
diff --git "a/grarchetype-common/src/test/archetypes/multi/archetype-resources/$\173rootArtifactId\175-b/pom.xml" "b/grarchetype-common/src/test/archetypes/multi/archetype-resources/$\173rootArtifactId\175-b/pom.xml"
new file mode 100644
index 0000000..9a59f03
--- /dev/null
+++ "b/grarchetype-common/src/test/archetypes/multi/archetype-resources/$\173rootArtifactId\175-b/pom.xml"
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project
+ xmlns="http://maven.apache.org/POM/4.0.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>${groupId}</groupId>
+ <artifactId>${upArtifactId}</artifactId>
+ <version>${version}</version>
+ </parent>
+
+ <artifactId>${artifactId}</artifactId>
+ <version>${version}</version>
+
+ <packaging>jar</packaging>
+
+ <dependencies>
+ <dependency>
+ <groupId>${groupId}</groupId>
+ <artifactId>${rootArtifactId}-a</artifactId>
+ <version>${version}</version>
+ </dependency>
+ </dependencies>
+
+ <properties>
+ <replace>
+ artifactId = ${artifactId}
+ rootArtifactId = ${rootArtifactId}
+ upArtifactId = ${upArtifactId}
+ </replace>
+ </properties>
+</project>
\ No newline at end of file
diff --git "a/grarchetype-common/src/test/archetypes/multi/archetype-resources/$\173rootArtifactId\175-c/$\173rootArtifactId\175-d/pom.xml" "b/grarchetype-common/src/test/archetypes/multi/archetype-resources/$\173rootArtifactId\175-c/$\173rootArtifactId\175-d/pom.xml"
new file mode 100644
index 0000000..b111bb3
--- /dev/null
+++ "b/grarchetype-common/src/test/archetypes/multi/archetype-resources/$\173rootArtifactId\175-c/$\173rootArtifactId\175-d/pom.xml"
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project
+ xmlns="http://maven.apache.org/POM/4.0.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>${groupId}</groupId>
+ <artifactId>${upArtifactId}</artifactId>
+ <version>${version}</version>
+ </parent>
+
+ <artifactId>${artifactId}</artifactId>
+ <version>${version}</version>
+
+ <packaging>jar</packaging>
+
+ <dependencies>
+ <dependency>
+ <groupId>${groupId}</groupId>
+ <artifactId>${rootArtifactId}-b</artifactId>
+ <version>${version}</version>
+ </dependency>
+ </dependencies>
+
+ <properties>
+ <replace>
+ artifactId = ${artifactId}
+ rootArtifactId = ${rootArtifactId}
+ upArtifactId = ${upArtifactId}
+ </replace>
+ </properties>
+</project>
\ No newline at end of file
diff --git "a/grarchetype-common/src/test/archetypes/multi/archetype-resources/$\173rootArtifactId\175-c/$\173rootArtifactId\175-e/$\173rootArtifactId\175-f/pom.xml" "b/grarchetype-common/src/test/archetypes/multi/archetype-resources/$\173rootArtifactId\175-c/$\173rootArtifactId\175-e/$\173rootArtifactId\175-f/pom.xml"
new file mode 100644
index 0000000..7b015df
--- /dev/null
+++ "b/grarchetype-common/src/test/archetypes/multi/archetype-resources/$\173rootArtifactId\175-c/$\173rootArtifactId\175-e/$\173rootArtifactId\175-f/pom.xml"
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project
+ xmlns="http://maven.apache.org/POM/4.0.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>${groupId}</groupId>
+ <artifactId>${upArtifactId}</artifactId>
+ <version>${version}</version>
+ </parent>
+
+ <artifactId>${artifactId}</artifactId>
+ <version>${version}</version>
+
+ <packaging>jar</packaging>
+
+ <dependencies>
+ <dependency>
+ <groupId>${groupId}</groupId>
+ <artifactId>${rootArtifactId}-d</artifactId>
+ <version>${version}</version>
+ </dependency>
+ </dependencies>
+
+ <properties>
+ <replace>
+ artifactId = ${artifactId}
+ rootArtifactId = ${rootArtifactId}
+ upArtifactId = ${upArtifactId}
+ </replace>
+ </properties>
+</project>
\ No newline at end of file
diff --git "a/grarchetype-common/src/test/archetypes/multi/archetype-resources/$\173rootArtifactId\175-c/$\173rootArtifactId\175-e/$\173rootArtifactId\175-g/pom.xml" "b/grarchetype-common/src/test/archetypes/multi/archetype-resources/$\173rootArtifactId\175-c/$\173rootArtifactId\175-e/$\173rootArtifactId\175-g/pom.xml"
new file mode 100644
index 0000000..24d44bd
--- /dev/null
+++ "b/grarchetype-common/src/test/archetypes/multi/archetype-resources/$\173rootArtifactId\175-c/$\173rootArtifactId\175-e/$\173rootArtifactId\175-g/pom.xml"
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project
+ xmlns="http://maven.apache.org/POM/4.0.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>${groupId}</groupId>
+ <artifactId>${upArtifactId}</artifactId>
+ <version>${version}</version>
+ </parent>
+
+ <artifactId>${artifactId}</artifactId>
+ <version>${version}</version>
+
+ <packaging>jar</packaging>
+
+ <dependencies>
+ <dependency>
+ <groupId>${groupId}</groupId>
+ <artifactId>${rootArtifactId}-f</artifactId>
+ <version>${version}</version>
+ </dependency>
+ </dependencies>
+
+ <properties>
+ <replace>
+ artifactId = ${artifactId}
+ rootArtifactId = ${rootArtifactId}
+ upArtifactId = ${upArtifactId}
+ </replace>
+ </properties>
+</project>
\ No newline at end of file
diff --git "a/grarchetype-common/src/test/archetypes/multi/archetype-resources/$\173rootArtifactId\175-c/$\173rootArtifactId\175-e/$\173upArtifactId\175-h/pom.xml" "b/grarchetype-common/src/test/archetypes/multi/archetype-resources/$\173rootArtifactId\175-c/$\173rootArtifactId\175-e/$\173upArtifactId\175-h/pom.xml"
new file mode 100644
index 0000000..f1fae43
--- /dev/null
+++ "b/grarchetype-common/src/test/archetypes/multi/archetype-resources/$\173rootArtifactId\175-c/$\173rootArtifactId\175-e/$\173upArtifactId\175-h/pom.xml"
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project
+ xmlns="http://maven.apache.org/POM/4.0.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>${groupId}</groupId>
+ <artifactId>${upArtifactId}</artifactId>
+ <version>${version}</version>
+ </parent>
+
+ <artifactId>${artifactId}</artifactId>
+ <version>${version}</version>
+
+ <packaging>jar</packaging>
+
+ <dependencies>
+ <dependency>
+ <groupId>${groupId}</groupId>
+ <artifactId>${rootArtifactId}-g</artifactId>
+ <version>${version}</version>
+ </dependency>
+ </dependencies>
+
+ <properties>
+ <replace>
+ artifactId = ${artifactId}
+ rootArtifactId = ${rootArtifactId}
+ upArtifactId = ${upArtifactId}
+ </replace>
+ </properties>
+</project>
\ No newline at end of file
diff --git "a/grarchetype-common/src/test/archetypes/multi/archetype-resources/$\173rootArtifactId\175-c/$\173rootArtifactId\175-e/pom.xml" "b/grarchetype-common/src/test/archetypes/multi/archetype-resources/$\173rootArtifactId\175-c/$\173rootArtifactId\175-e/pom.xml"
new file mode 100644
index 0000000..7416da5
--- /dev/null
+++ "b/grarchetype-common/src/test/archetypes/multi/archetype-resources/$\173rootArtifactId\175-c/$\173rootArtifactId\175-e/pom.xml"
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project
+ xmlns="http://maven.apache.org/POM/4.0.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>${groupId}</groupId>
+ <artifactId>${upArtifactId}</artifactId>
+ <version>${version}</version>
+ </parent>
+
+ <artifactId>${artifactId}</artifactId>
+ <version>${version}</version>
+
+ <packaging>pom</packaging>
+
+ <modules>
+ <module>${rootArtifactId}-f</module>
+ <module>${rootArtifactId}-g</module>
+ <module>${upArtifactId}-h</module>
+ </modules>
+
+ <properties>
+ <replace>
+ artifactId = ${artifactId}
+ rootArtifactId = ${rootArtifactId}
+ upArtifactId = ${upArtifactId}
+ </replace>
+ </properties>
+</project>
\ No newline at end of file
diff --git "a/grarchetype-common/src/test/archetypes/multi/archetype-resources/$\173rootArtifactId\175-c/pom.xml" "b/grarchetype-common/src/test/archetypes/multi/archetype-resources/$\173rootArtifactId\175-c/pom.xml"
new file mode 100644
index 0000000..7ddd96d
--- /dev/null
+++ "b/grarchetype-common/src/test/archetypes/multi/archetype-resources/$\173rootArtifactId\175-c/pom.xml"
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project
+ xmlns="http://maven.apache.org/POM/4.0.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>${groupId}</groupId>
+ <artifactId>${upArtifactId}</artifactId>
+ <version>${version}</version>
+ </parent>
+
+ <artifactId>${artifactId}</artifactId>
+ <version>${version}</version>
+
+ <packaging>pom</packaging>
+
+ <modules>
+ <module>${rootArtifactId}-d</module>
+ <module>${rootArtifactId}-e</module>
+ </modules>
+
+ <properties>
+ <replace>
+ artifactId = ${artifactId}
+ rootArtifactId = ${rootArtifactId}
+ upArtifactId = ${upArtifactId}
+ </replace>
+ </properties>
+</project>
\ No newline at end of file
diff --git a/grarchetype-common/src/test/archetypes/multi/archetype-resources/pom.xml b/grarchetype-common/src/test/archetypes/multi/archetype-resources/pom.xml
new file mode 100644
index 0000000..0ea5926
--- /dev/null
+++ b/grarchetype-common/src/test/archetypes/multi/archetype-resources/pom.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project
+ xmlns="http://maven.apache.org/POM/4.0.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <groupId>${groupId}</groupId>
+ <artifactId>${artifactId}</artifactId>
+ <version>${version}</version>
+
+ <packaging>pom</packaging>
+
+ <modules>
+ <module>${rootArtifactId}-a</module>
+ <module>${rootArtifactId}-b</module>
+ <module>${rootArtifactId}-c</module>
+ </modules>
+
+ <properties>
+ <replace>
+ artifactId = ${artifactId}
+ rootArtifactId = ${rootArtifactId}
+ upArtifactId = ${upArtifactId}
+ </replace>
+ </properties>
+</project>
\ No newline at end of file
diff --git a/grarchetype-common/src/test/archetypes/nested-complete-inner/META-INF/maven/archetype-metadata.xml b/grarchetype-common/src/test/archetypes/nested-complete-inner/META-INF/maven/archetype-metadata.xml
new file mode 100644
index 0000000..1042ef8
--- /dev/null
+++ b/grarchetype-common/src/test/archetypes/nested-complete-inner/META-INF/maven/archetype-metadata.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ 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.
+ -->
+<archetype-descriptor name="nested-complete-inner" partial="false" >
+
+ <requiredProperties/>
+
+ <fileSets/>
+
+ <modules>
+ <module artifactId="${rootArtifactId}-innest" nested="true" archetypeGroupId="archetypes" archetypeArtifactId="nested-complete-innest" archetypeVersion="1.0" />
+ </modules>
+
+</archetype-descriptor>
diff --git a/grarchetype-common/src/test/archetypes/nested-complete-innest/META-INF/maven/archetype-metadata.xml b/grarchetype-common/src/test/archetypes/nested-complete-innest/META-INF/maven/archetype-metadata.xml
new file mode 100644
index 0000000..2a17d82
--- /dev/null
+++ b/grarchetype-common/src/test/archetypes/nested-complete-innest/META-INF/maven/archetype-metadata.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ 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.
+ -->
+<archetype-descriptor name="nested-complete-innest" partial="false" >
+
+ <requiredProperties/>
+
+ <fileSets/>
+
+ <modules/>
+
+</archetype-descriptor>
diff --git a/grarchetype-common/src/test/archetypes/nested-complete-main/META-INF/maven/archetype-metadata.xml b/grarchetype-common/src/test/archetypes/nested-complete-main/META-INF/maven/archetype-metadata.xml
new file mode 100644
index 0000000..50083ff
--- /dev/null
+++ b/grarchetype-common/src/test/archetypes/nested-complete-main/META-INF/maven/archetype-metadata.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ 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.
+ -->
+<archetype-descriptor name="nested-complete-main" partial="false" >
+
+ <requiredProperties/>
+
+ <fileSets/>
+
+ <modules>
+ <module artifactId="${rootArtifactId}-inner" nested="true" archetypeGroupId="archetypes" archetypeArtifactId="nested-complete-inner" archetypeVersion="1.0" />
+ </modules>
+
+</archetype-descriptor>
diff --git a/grarchetype-common/src/test/archetypes/nested-inner/META-INF/maven/archetype-metadata.xml b/grarchetype-common/src/test/archetypes/nested-inner/META-INF/maven/archetype-metadata.xml
new file mode 100644
index 0000000..f8be233
--- /dev/null
+++ b/grarchetype-common/src/test/archetypes/nested-inner/META-INF/maven/archetype-metadata.xml
@@ -0,0 +1,46 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ 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.
+ -->
+<archetype-descriptor name="nested-inner" partial="false" >
+
+ <requiredProperties>
+ <requiredProperty key="XXX">
+ <defaultValue>default-value</defaultValue>
+ </requiredProperty>
+ <requiredProperty key="XXX"/>
+ </requiredProperties>
+
+ <fileSets/>
+
+ <modules>
+ <module artifactId="${rootArtifactId}-n-innest" nested="true" archetypeGroupId="archetypes" archetypeArtifactId="nested-innest" archetypeVersion="1.0" />
+ <module artifactId="${rootArtifactId}-n-old" nested="true" archetypeGroupId="archetypes" archetypeArtifactId="old" archetypeVersion="1.0" />
+ <module artifactId="${rootArtifactId}-inner">
+ <modules>
+ <module artifactId="${rootArtifactId}-n2-innest" nested="true" archetypeGroupId="archetypes" archetypeArtifactId="nested-innest" archetypeVersion="1.0" />
+ <module artifactId="${rootArtifactId}-innest" >
+ <modules>
+ <module artifactId="${rootArtifactId}-innest" nested="true" archetypeGroupId="archetypes" archetypeArtifactId="nested-partial" archetypeVersion="1.0" />
+ </modules>
+ </module>
+ </modules>
+ </module>
+ </modules>
+
+</archetype-descriptor>
diff --git "a/grarchetype-common/src/test/archetypes/nested-inner/archetype-resources/$\173rootArtifactId\175-inner/$\173rootArtifactId\175-innest/pom.xml" "b/grarchetype-common/src/test/archetypes/nested-inner/archetype-resources/$\173rootArtifactId\175-inner/$\173rootArtifactId\175-innest/pom.xml"
new file mode 100644
index 0000000..603e269
--- /dev/null
+++ "b/grarchetype-common/src/test/archetypes/nested-inner/archetype-resources/$\173rootArtifactId\175-inner/$\173rootArtifactId\175-innest/pom.xml"
@@ -0,0 +1,94 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project
+ xmlns="http://maven.apache.org/POM/4.0.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>${groupId}</groupId>
+ <artifactId>${upArtifactId}</artifactId>
+ <version>${version}</version>
+ </parent>
+
+ <artifactId>${artifactId}</artifactId>
+ <version>${version}</version>
+
+ <packaging>jar</packaging>
+
+ <reporting>
+ <outputDirectory>initial directory</outputDirectory>
+ <excludeDefaults>initial excluded</excludeDefaults>
+ <plugins>
+ <plugin>
+ <groupId>archetypes</groupId>
+ <artifactId>plugin-merged</artifactId>
+ <version>1</version>
+ </plugin>
+ <plugin>
+ <groupId>archetypes</groupId>
+ <artifactId>plugin-in-initial</artifactId>
+ <version>1</version>
+ </plugin>
+ </plugins>
+ </reporting>
+
+ <dependencyManagement>
+ <dependencies>
+ <dependency>
+ <groupId>archetypes</groupId>
+ <artifactId>only-in-initial</artifactId>
+ <version>1.0</version>
+ </dependency>
+ <dependency>
+ <groupId>archetypes</groupId>
+ <artifactId>merged</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>archetypes</groupId>
+ <artifactId>overrided</artifactId>
+ <version>1.0</version>
+ </dependency>
+ </dependencies>
+ </dependencyManagement>
+
+
+ <repositories>
+ <repository>
+ <id>repository-in-initial</id>
+ <layout>default</layout>
+ <name>repository-in-initial</name>
+ <url>http://host:1</url>
+ </repository>
+ <repository>
+ <id>repository-merged</id>
+ <layout>default</layout>
+ <name>repository-merged</name>
+ <url>http://host:1</url>
+ </repository>
+ </repositories>
+ <pluginRepositories>
+ <pluginRepository>
+ <id>repository-in-initial</id>
+ <layout>default</layout>
+ <name>repository-in-initial</name>
+ <url>http://host:1</url>
+ </pluginRepository>
+ <pluginRepository>
+ <id>repository-merged</id>
+ <layout>default</layout>
+ <name>repository-merged</name>
+ <url>http://host:1</url>
+ </pluginRepository>
+ </pluginRepositories>
+
+ <properties>
+ <replace>
+ artifactId = ${artifactId}
+ rootArtifactId = ${rootArtifactId}
+ upArtifactId = ${upArtifactId}
+ </replace>
+ <merged-property>1</merged-property>
+ <initial-property>1</initial-property>
+ </properties>
+</project>
\ No newline at end of file
diff --git "a/grarchetype-common/src/test/archetypes/nested-inner/archetype-resources/$\173rootArtifactId\175-inner/pom.xml" "b/grarchetype-common/src/test/archetypes/nested-inner/archetype-resources/$\173rootArtifactId\175-inner/pom.xml"
new file mode 100644
index 0000000..d384ab0
--- /dev/null
+++ "b/grarchetype-common/src/test/archetypes/nested-inner/archetype-resources/$\173rootArtifactId\175-inner/pom.xml"
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project
+ xmlns="http://maven.apache.org/POM/4.0.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>${groupId}</groupId>
+ <artifactId>${upArtifactId}</artifactId>
+ <version>${version}</version>
+ </parent>
+
+ <artifactId>${artifactId}</artifactId>
+ <version>${version}</version>
+
+ <packaging>pom</packaging>
+
+ <properties>
+ <replace>
+ artifactId = ${artifactId}
+ rootArtifactId = ${rootArtifactId}
+ upArtifactId = ${upArtifactId}
+ </replace>
+ </properties>
+</project>
\ No newline at end of file
diff --git a/grarchetype-common/src/test/archetypes/nested-inner/archetype-resources/pom.xml b/grarchetype-common/src/test/archetypes/nested-inner/archetype-resources/pom.xml
new file mode 100644
index 0000000..53ba21b
--- /dev/null
+++ b/grarchetype-common/src/test/archetypes/nested-inner/archetype-resources/pom.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project
+ xmlns="http://maven.apache.org/POM/4.0.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <groupId>${groupId}</groupId>
+ <artifactId>${artifactId}</artifactId>
+ <version>${version}</version>
+
+ <packaging>pom</packaging>
+
+ <modules>
+ <module>${rootArtifactId}-inner</module>
+ </modules>
+
+ <properties>
+ <replace>
+ artifactId = ${artifactId}
+ rootArtifactId = ${rootArtifactId}
+ upArtifactId = ${upArtifactId}
+ </replace>
+ </properties>
+</project>
\ No newline at end of file
diff --git a/grarchetype-common/src/test/archetypes/nested-innest/META-INF/maven/archetype-metadata.xml b/grarchetype-common/src/test/archetypes/nested-innest/META-INF/maven/archetype-metadata.xml
new file mode 100644
index 0000000..a1931ae
--- /dev/null
+++ b/grarchetype-common/src/test/archetypes/nested-innest/META-INF/maven/archetype-metadata.xml
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ 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.
+ -->
+<archetype-descriptor name="nested-innest" partial="false" >
+
+ <requiredProperties>
+ <requiredProperty key="XXX">
+ <defaultValue>default-value</defaultValue>
+ </requiredProperty>
+ <requiredProperty key="XXX"/>
+ </requiredProperties>
+
+ <fileSets/>
+
+ <modules>
+ <module artifactId="${rootArtifactId}-inner">
+ <modules>
+ <module artifactId="${rootArtifactId}-innest" />
+ </modules>
+ </module>
+ </modules>
+
+</archetype-descriptor>
diff --git "a/grarchetype-common/src/test/archetypes/nested-innest/archetype-resources/$\173rootArtifactId\175-inner/$\173rootArtifactId\175-innest/pom.xml" "b/grarchetype-common/src/test/archetypes/nested-innest/archetype-resources/$\173rootArtifactId\175-inner/$\173rootArtifactId\175-innest/pom.xml"
new file mode 100644
index 0000000..f8bb6b3
--- /dev/null
+++ "b/grarchetype-common/src/test/archetypes/nested-innest/archetype-resources/$\173rootArtifactId\175-inner/$\173rootArtifactId\175-innest/pom.xml"
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project
+ xmlns="http://maven.apache.org/POM/4.0.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>${groupId}</groupId>
+ <artifactId>${upArtifactId}</artifactId>
+ <version>${version}</version>
+ </parent>
+
+ <artifactId>${artifactId}</artifactId>
+ <version>${version}</version>
+
+ <packaging>jar</packaging>
+
+ <properties>
+ <replace>
+ artifactId = ${artifactId}
+ rootArtifactId = ${rootArtifactId}
+ upArtifactId = ${upArtifactId}
+ </replace>
+ </properties>
+</project>
\ No newline at end of file
diff --git "a/grarchetype-common/src/test/archetypes/nested-innest/archetype-resources/$\173rootArtifactId\175-inner/pom.xml" "b/grarchetype-common/src/test/archetypes/nested-innest/archetype-resources/$\173rootArtifactId\175-inner/pom.xml"
new file mode 100644
index 0000000..f8bb6b3
--- /dev/null
+++ "b/grarchetype-common/src/test/archetypes/nested-innest/archetype-resources/$\173rootArtifactId\175-inner/pom.xml"
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project
+ xmlns="http://maven.apache.org/POM/4.0.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>${groupId}</groupId>
+ <artifactId>${upArtifactId}</artifactId>
+ <version>${version}</version>
+ </parent>
+
+ <artifactId>${artifactId}</artifactId>
+ <version>${version}</version>
+
+ <packaging>jar</packaging>
+
+ <properties>
+ <replace>
+ artifactId = ${artifactId}
+ rootArtifactId = ${rootArtifactId}
+ upArtifactId = ${upArtifactId}
+ </replace>
+ </properties>
+</project>
\ No newline at end of file
diff --git a/grarchetype-common/src/test/archetypes/nested-innest/archetype-resources/pom.xml b/grarchetype-common/src/test/archetypes/nested-innest/archetype-resources/pom.xml
new file mode 100644
index 0000000..0ea5926
--- /dev/null
+++ b/grarchetype-common/src/test/archetypes/nested-innest/archetype-resources/pom.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project
+ xmlns="http://maven.apache.org/POM/4.0.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <groupId>${groupId}</groupId>
+ <artifactId>${artifactId}</artifactId>
+ <version>${version}</version>
+
+ <packaging>pom</packaging>
+
+ <modules>
+ <module>${rootArtifactId}-a</module>
+ <module>${rootArtifactId}-b</module>
+ <module>${rootArtifactId}-c</module>
+ </modules>
+
+ <properties>
+ <replace>
+ artifactId = ${artifactId}
+ rootArtifactId = ${rootArtifactId}
+ upArtifactId = ${upArtifactId}
+ </replace>
+ </properties>
+</project>
\ No newline at end of file
diff --git a/grarchetype-common/src/test/archetypes/nested-main/META-INF/maven/archetype-metadata.xml b/grarchetype-common/src/test/archetypes/nested-main/META-INF/maven/archetype-metadata.xml
new file mode 100644
index 0000000..5597767
--- /dev/null
+++ b/grarchetype-common/src/test/archetypes/nested-main/META-INF/maven/archetype-metadata.xml
@@ -0,0 +1,47 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ 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.
+ -->
+<archetype-descriptor name="nested-main" partial="false" >
+
+ <requiredProperties>
+ <requiredProperty key="XXX">
+ <defaultValue>default-value</defaultValue>
+ </requiredProperty>
+ <requiredProperty key="XXX"/>
+ </requiredProperties>
+
+ <fileSets/>
+
+ <modules>
+ <module artifactId="${rootArtifactId}-n-inner" nested="true" archetypeGroupId="archetypes" archetypeArtifactId="nested-inner" archetypeVersion="1.0" />
+ <module artifactId="${rootArtifactId}-n2-inner" nested="true" archetypeGroupId="archetypes" archetypeArtifactId="nested-inner" archetypeVersion="1.0" />
+ <module artifactId="${rootArtifactId}-n-old" nested="true" archetypeGroupId="archetypes" archetypeArtifactId="old" archetypeVersion="1.0" />
+ <module artifactId="${rootArtifactId}-inner">
+ <modules>
+ <module artifactId="${rootArtifactId}-n-innest" nested="true" archetypeGroupId="archetypes" archetypeArtifactId="nested-inner" archetypeVersion="1.0" />
+ <module artifactId="${rootArtifactId}-innest">
+ <modules>
+ <module artifactId="${rootArtifactId}-innest" nested="true" archetypeGroupId="archetypes" archetypeArtifactId="nested-partial" archetypeVersion="1.0" />
+ </modules>
+ </module>
+ </modules>
+ </module>
+ </modules>
+
+</archetype-descriptor>
diff --git "a/grarchetype-common/src/test/archetypes/nested-main/archetype-resources/$\173rootArtifactId\175-inner/$\173rootArtifactId\175-innest/pom.xml" "b/grarchetype-common/src/test/archetypes/nested-main/archetype-resources/$\173rootArtifactId\175-inner/$\173rootArtifactId\175-innest/pom.xml"
new file mode 100644
index 0000000..774fd22
--- /dev/null
+++ "b/grarchetype-common/src/test/archetypes/nested-main/archetype-resources/$\173rootArtifactId\175-inner/$\173rootArtifactId\175-innest/pom.xml"
@@ -0,0 +1,71 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project
+ xmlns="http://maven.apache.org/POM/4.0.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>${groupId}</groupId>
+ <artifactId>${upArtifactId}</artifactId>
+ <version>${version}</version>
+ </parent>
+
+ <artifactId>${artifactId}</artifactId>
+ <version>${version}</version>
+
+ <packaging>jar</packaging>
+
+ <properties>
+ <replace>
+ artifactId = ${artifactId}
+ rootArtifactId = ${rootArtifactId}
+ upArtifactId = ${upArtifactId}
+ </replace>
+ </properties>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>archetypes</groupId>
+ <artifactId>plugin-in-initial</artifactId>
+ <version>1</version>
+ </plugin>
+ <plugin>
+ <groupId>archetypes</groupId>
+ <artifactId>plugin-merged</artifactId>
+ </plugin>
+ </plugins>
+ <pluginManagement>
+ <plugins>
+ <plugin>
+ <groupId>archetypes</groupId>
+ <artifactId>plugin-in-initial</artifactId>
+ <version>1</version>
+ </plugin>
+ <plugin>
+ <groupId>archetypes</groupId>
+ <artifactId>plugin-merged</artifactId>
+ <version>1</version>
+ </plugin>
+ </plugins>
+ </pluginManagement>
+ </build>
+
+ <dependencies>
+ <dependency>
+ <groupId>archetypes</groupId>
+ <artifactId>only-in-initial</artifactId>
+ <version>1.0</version>
+ </dependency>
+ <dependency>
+ <groupId>archetypes</groupId>
+ <artifactId>merged</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>archetypes</groupId>
+ <artifactId>overrided</artifactId>
+ <version>1.0</version>
+ </dependency>
+ </dependencies>
+</project>
\ No newline at end of file
diff --git "a/grarchetype-common/src/test/archetypes/nested-main/archetype-resources/$\173rootArtifactId\175-inner/pom.xml" "b/grarchetype-common/src/test/archetypes/nested-main/archetype-resources/$\173rootArtifactId\175-inner/pom.xml"
new file mode 100644
index 0000000..d384ab0
--- /dev/null
+++ "b/grarchetype-common/src/test/archetypes/nested-main/archetype-resources/$\173rootArtifactId\175-inner/pom.xml"
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project
+ xmlns="http://maven.apache.org/POM/4.0.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>${groupId}</groupId>
+ <artifactId>${upArtifactId}</artifactId>
+ <version>${version}</version>
+ </parent>
+
+ <artifactId>${artifactId}</artifactId>
+ <version>${version}</version>
+
+ <packaging>pom</packaging>
+
+ <properties>
+ <replace>
+ artifactId = ${artifactId}
+ rootArtifactId = ${rootArtifactId}
+ upArtifactId = ${upArtifactId}
+ </replace>
+ </properties>
+</project>
\ No newline at end of file
diff --git a/grarchetype-common/src/test/archetypes/nested-main/archetype-resources/pom.xml b/grarchetype-common/src/test/archetypes/nested-main/archetype-resources/pom.xml
new file mode 100644
index 0000000..53ba21b
--- /dev/null
+++ b/grarchetype-common/src/test/archetypes/nested-main/archetype-resources/pom.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project
+ xmlns="http://maven.apache.org/POM/4.0.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <groupId>${groupId}</groupId>
+ <artifactId>${artifactId}</artifactId>
+ <version>${version}</version>
+
+ <packaging>pom</packaging>
+
+ <modules>
+ <module>${rootArtifactId}-inner</module>
+ </modules>
+
+ <properties>
+ <replace>
+ artifactId = ${artifactId}
+ rootArtifactId = ${rootArtifactId}
+ upArtifactId = ${upArtifactId}
+ </replace>
+ </properties>
+</project>
\ No newline at end of file
diff --git a/grarchetype-common/src/test/archetypes/nested-missing-inner/META-INF/maven/archetype-metadata.xml b/grarchetype-common/src/test/archetypes/nested-missing-inner/META-INF/maven/archetype-metadata.xml
new file mode 100644
index 0000000..28dbc2a
--- /dev/null
+++ b/grarchetype-common/src/test/archetypes/nested-missing-inner/META-INF/maven/archetype-metadata.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ 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.
+ -->
+<archetype-descriptor name="nested-missing-inner" partial="false" >
+
+ <requiredProperties/>
+
+ <fileSets/>
+
+ <modules>
+ <module artifactId="${rootArtifactId}-inner">
+ <modules>
+ <module artifactId="${rootArtifactId}-innest" nested="true" archetypeGroupId="archetypes" archetypeArtifactId="nested-missing-innest" archetypeVersion="1.0" />
+ </modules>
+ </module>
+ </modules>
+
+</archetype-descriptor>
diff --git a/grarchetype-common/src/test/archetypes/nested-missing-main/META-INF/maven/archetype-metadata.xml b/grarchetype-common/src/test/archetypes/nested-missing-main/META-INF/maven/archetype-metadata.xml
new file mode 100644
index 0000000..9fe075c
--- /dev/null
+++ b/grarchetype-common/src/test/archetypes/nested-missing-main/META-INF/maven/archetype-metadata.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ 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.
+ -->
+<archetype-descriptor name="nested-missing-main" partial="false" >
+
+ <requiredProperties/>
+
+ <fileSets/>
+
+ <modules>
+ <module artifactId="${rootArtifactId}-inner">
+ <modules>
+ <module artifactId="${rootArtifactId}-innest" nested="true" archetypeGroupId="archetypes" archetypeArtifactId="nested-missing-inner" archetypeVersion="1.0" />
+ </modules>
+ </module>
+ </modules>
+
+</archetype-descriptor>
diff --git a/grarchetype-common/src/test/archetypes/nested-partial/META-INF/maven/archetype-metadata.xml b/grarchetype-common/src/test/archetypes/nested-partial/META-INF/maven/archetype-metadata.xml
new file mode 100644
index 0000000..f312c8f
--- /dev/null
+++ b/grarchetype-common/src/test/archetypes/nested-partial/META-INF/maven/archetype-metadata.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ 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.
+ -->
+<archetype-descriptor name="nested-partial" partial="true" >
+
+ <requiredProperties>
+ <requiredProperty key="XXX">
+ <defaultValue>default-value</defaultValue>
+ </requiredProperty>
+ <requiredProperty key="XXX"/>
+ </requiredProperties>
+
+ <fileSets/>
+
+ <modules/>
+
+</archetype-descriptor>
diff --git "a/grarchetype-common/src/test/archetypes/nested-partial/archetype-resources/$\173rootArtifactId\175-a/pom.xml" "b/grarchetype-common/src/test/archetypes/nested-partial/archetype-resources/$\173rootArtifactId\175-a/pom.xml"
new file mode 100644
index 0000000..f8bb6b3
--- /dev/null
+++ "b/grarchetype-common/src/test/archetypes/nested-partial/archetype-resources/$\173rootArtifactId\175-a/pom.xml"
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project
+ xmlns="http://maven.apache.org/POM/4.0.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>${groupId}</groupId>
+ <artifactId>${upArtifactId}</artifactId>
+ <version>${version}</version>
+ </parent>
+
+ <artifactId>${artifactId}</artifactId>
+ <version>${version}</version>
+
+ <packaging>jar</packaging>
+
+ <properties>
+ <replace>
+ artifactId = ${artifactId}
+ rootArtifactId = ${rootArtifactId}
+ upArtifactId = ${upArtifactId}
+ </replace>
+ </properties>
+</project>
\ No newline at end of file
diff --git a/grarchetype-common/src/test/archetypes/nested-partial/archetype-resources/pom.xml b/grarchetype-common/src/test/archetypes/nested-partial/archetype-resources/pom.xml
new file mode 100644
index 0000000..7bf630e
--- /dev/null
+++ b/grarchetype-common/src/test/archetypes/nested-partial/archetype-resources/pom.xml
@@ -0,0 +1,143 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project
+ xmlns="http://maven.apache.org/POM/4.0.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <groupId>${groupId}</groupId>
+ <artifactId>${artifactId}</artifactId>
+ <version>${version}</version>
+
+ <packaging>pom</packaging>
+
+ <modules>
+ <module>${rootArtifactId}-a</module>
+ <module>${rootArtifactId}-b</module>
+ <module>${rootArtifactId}-c</module>
+ </modules>
+
+ <build>
+ <defaultGoal>package</defaultGoal>
+ <plugins>
+ <plugin>
+ <groupId>archetypes</groupId>
+ <artifactId>plugin-merged</artifactId>
+ <version>2</version>
+ </plugin>
+ <plugin>
+ <groupId>archetypes</groupId>
+ <artifactId>plugin-in-partial</artifactId>
+ <version>2</version>
+ </plugin>
+ </plugins>
+ <pluginManagement>
+ <plugins>
+ <plugin>
+ <groupId>archetypes</groupId>
+ <artifactId>plugin-merged</artifactId>
+ <version>2</version>
+ </plugin>
+ <plugin>
+ <groupId>archetypes</groupId>
+ <artifactId>plugin-in-partial</artifactId>
+ <version>2</version>
+ </plugin>
+ </plugins>
+ </pluginManagement>
+ </build>
+
+ <reporting>
+ <outputDirectory>partial directory</outputDirectory>
+ <excludeDefaults>partial excluded</excludeDefaults>
+ <plugins>
+ <plugin>
+ <groupId>archetypes</groupId>
+ <artifactId>plugin-merged</artifactId>
+ <version>2</version>
+ </plugin>
+ <plugin>
+ <groupId>archetypes</groupId>
+ <artifactId>plugin-in-partial</artifactId>
+ <version>2</version>
+ </plugin>
+ </plugins>
+ </reporting>
+
+ <dependencies>
+ <dependency>
+ <groupId>archetypes</groupId>
+ <artifactId>only-in-partial</artifactId>
+ <version>2.0</version>
+ </dependency>
+ <dependency>
+ <groupId>archetypes</groupId>
+ <artifactId>merged</artifactId>
+ <version>2.0</version>
+ </dependency>
+ <dependency>
+ <groupId>archetypes</groupId>
+ <artifactId>overrided</artifactId>
+ <version>2.0</version>
+ </dependency>
+ </dependencies>
+
+ <dependencyManagement>
+ <dependencies>
+ <dependency>
+ <groupId>archetypes</groupId>
+ <artifactId>only-in-partial</artifactId>
+ <version>2.0</version>
+ </dependency>
+ <dependency>
+ <groupId>archetypes</groupId>
+ <artifactId>merged</artifactId>
+ <version>2.0</version>
+ </dependency>
+ <dependency>
+ <groupId>archetypes</groupId>
+ <artifactId>overrided</artifactId>
+ <version>2.0</version>
+ </dependency>
+ </dependencies>
+ </dependencyManagement>
+
+ <repositories>
+ <repository>
+ <id>repository-in-partial</id>
+ <layout>legacy</layout>
+ <name>repository-in-partial</name>
+ <url>http://host:2</url>
+ </repository>
+ <repository>
+ <id>repository-merged</id>
+ <layout>legacy</layout>
+ <name>repository-merged</name>
+ <url>http://host:2</url>
+ </repository>
+ </repositories>
+ <pluginRepositories>
+ <pluginRepository>
+ <id>repository-in-partial</id>
+ <layout>legacy</layout>
+ <name>repository-in-partial</name>
+ <url>http://host:2</url>
+ </pluginRepository>
+ <pluginRepository>
+ <id>repository-merged</id>
+ <layout>legacy</layout>
+ <name>repository-merged</name>
+ <url>http://host:2</url>
+ </pluginRepository>
+ </pluginRepositories>
+
+ <properties>
+ <replace>
+ artifactId = ${artifactId}
+ rootArtifactId = ${rootArtifactId}
+ upArtifactId = ${upArtifactId}
+ </replace>
+ <partial-property>2</partial-property>
+ <merged-property>2</merged-property>
+ </properties>
+</project>
\ No newline at end of file
diff --git a/grarchetype-common/src/test/archetypes/old/META-INF/archetype.xml b/grarchetype-common/src/test/archetypes/old/META-INF/archetype.xml
new file mode 100644
index 0000000..d620e84
--- /dev/null
+++ b/grarchetype-common/src/test/archetypes/old/META-INF/archetype.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ 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.
+ -->
+<archetype>
+ <id>old</id>
+ <sources>
+ <source>src/main/java/App.java</source>
+ </sources>
+ <resources>
+ <resource>src/main/resources/App.properties</resource>
+ </resources>
+ <siteResources>
+ <resource>src/site/site.xml</resource>
+ </siteResources>
+</archetype>
diff --git a/grarchetype-common/src/test/archetypes/old/archetype-resources/pom.xml b/grarchetype-common/src/test/archetypes/old/archetype-resources/pom.xml
new file mode 100644
index 0000000..f17b333
--- /dev/null
+++ b/grarchetype-common/src/test/archetypes/old/archetype-resources/pom.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ 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.
+ -->
+<project
+ xmlns="http://maven.apache.org/POM/4.0.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+
+ <modelVersion>4.0.0</modelVersion>
+
+ <groupId>${groupId}</groupId>
+ <artifactId>${artifactId}</artifactId>
+ <version>${version}</version>
+
+ <name>Maven archetype Test Old archetype</name>
+ <packaging>jar</packaging>
+
+</project>
\ No newline at end of file
diff --git a/grarchetype-common/src/test/archetypes/old/archetype-resources/src/main/java/App.java b/grarchetype-common/src/test/archetypes/old/archetype-resources/src/main/java/App.java
new file mode 100644
index 0000000..454754f
--- /dev/null
+++ b/grarchetype-common/src/test/archetypes/old/archetype-resources/src/main/java/App.java
@@ -0,0 +1,4 @@
+groupId=${groupId}
+artifactId=${artifactId}
+version=${version}
+package=${packageName}
diff --git a/grarchetype-common/src/test/archetypes/old/archetype-resources/src/main/resources/App.properties b/grarchetype-common/src/test/archetypes/old/archetype-resources/src/main/resources/App.properties
new file mode 100644
index 0000000..454754f
--- /dev/null
+++ b/grarchetype-common/src/test/archetypes/old/archetype-resources/src/main/resources/App.properties
@@ -0,0 +1,4 @@
+groupId=${groupId}
+artifactId=${artifactId}
+version=${version}
+package=${packageName}
diff --git a/grarchetype-common/src/test/archetypes/old/archetype-resources/src/site/site.xml b/grarchetype-common/src/test/archetypes/old/archetype-resources/src/site/site.xml
new file mode 100644
index 0000000..454754f
--- /dev/null
+++ b/grarchetype-common/src/test/archetypes/old/archetype-resources/src/site/site.xml
@@ -0,0 +1,4 @@
+groupId=${groupId}
+artifactId=${artifactId}
+version=${version}
+package=${packageName}
diff --git a/grarchetype-common/src/test/groovy/org/apache/maven/archetype/catalog/DefaultArchetypeCatalogerTest.groovy b/grarchetype-common/src/test/groovy/org/apache/maven/archetype/catalog/DefaultArchetypeCatalogerTest.groovy
new file mode 100644
index 0000000..42a2b84
--- /dev/null
+++ b/grarchetype-common/src/test/groovy/org/apache/maven/archetype/catalog/DefaultArchetypeCatalogerTest.groovy
@@ -0,0 +1,104 @@
+package org.apache.maven.archetype.catalog
+import org.junit.Test
+import static org.junit.Assert.*
+import org.codehaus.plexus.PlexusTestCase
+import org.apache.maven.plugin.testing.AbstractMojoTestCase
+import org.apache.maven.archetype.ArchetypeGenerationRequest
+import org.apache.maven.archetype.ArchetypeGenerationResult
+import org.apache.maven.archetype.generator.DefaultProjectGenerator
+import org.apache.maven.archetype.pom.PomManager
+import org.apache.maven.archetype.util.RepositoryCreator
+import org.codehaus.cargo.container.jetty.Jetty6xEmbeddedLocalContainer
+import org.codehaus.cargo.container.jetty.Jetty6xEmbeddedStandaloneLocalConfiguration
+import org.codehaus.cargo.generic.deployable.DefaultDeployableFactory
+import org.codehaus.cargo.container.jetty.Jetty6xEmbeddedLocalDeployer
+import org.codehaus.cargo.container.deployer.URLDeployableMonitor
+import org.codehaus.cargo.container.property.ServletPropertySet
+import org.codehaus.cargo.container.deployable.DeployableType
+import org.apache.maven.artifact.repository.ArtifactRepository
+
+/**
+ *
+ * @author raphaelpieroni
+ */
+class DefaultArchetypeCatalogerTest extends AbstractMojoTestCase {
+ Jetty6xEmbeddedLocalContainer jettyContainer
+ def archetypeCataloger
+ def repositoryCreator
+
+ void setUp() {
+ super.setUp()
+ archetypeCataloger = lookup( ArchetypeCataloger.ROLE )
+ repositoryCreator = lookup( RepositoryCreator.ROLE )
+
+ // Start Cargo
+
+ def configuration =
+ new Jetty6xEmbeddedStandaloneLocalConfiguration( "target/repository-webapp" )
+ configuration.setProperty ServletPropertySet.PORT, "18881"
+
+ System.setProperty "org.apache.maven.archetype.reporitory.directory",
+ getTestPath( "target/repositories/" )
+ jettyContainer = new Jetty6xEmbeddedLocalContainer( configuration )
+ jettyContainer.timeout = 180000L
+ jettyContainer.start()
+
+ def factory = new DefaultDeployableFactory()
+ def war = factory.createDeployable( jettyContainer.id,
+ "target/wars/grarchetype-repository.war",
+ DeployableType.WAR )
+
+ war.context = "/"
+
+ def deployer = new Jetty6xEmbeddedLocalDeployer( jettyContainer )
+ deployer.deploy war,
+ new URLDeployableMonitor( new URL( "http://localhost:18881/central/archetype-catalog.xml" ) )
+ deployer.start war
+ }
+ void tearDown() {
+ super.tearDown()
+ // Stop Cargo
+ jettyContainer.stop()
+ }
+
+ @Test void test_getArchetypesByCatalog() {
+ println "getArchetypesByCatalog"
+
+ assertNull archetypeCataloger.getArchetypesByCatalog("")
+ assertEquals 3, archetypeCataloger.getArchetypesByCatalog("internal").size()
+// assertEquals 9, archetypeCataloger.getArchetypesByCatalog("http://localhost:18881/central").size()
+// assertEquals 5, archetypeCataloger.getArchetypesByCatalog("https://aze").host.size()
+// assertEquals 3, archetypeCataloger.getArchetypesByCatalog("file://aze").path.size()
+// assertEquals 1, archetypeCataloger.getArchetypesByCatalog("local").local.size()
+// assertEquals 2, archetypeCataloger.getArchetypesByCatalog("remote").remote.size()
+ }
+
+ @Test void test_archetypeRecursivelyExists() {
+ println "archetypeRecursivelyExists"
+
+ def archetypeDefinitions = archetypeCataloger.getArchetypesByCatalog( "http://localhost:18881/central/archetype-catalog.xml" )
+ assert archetypeDefinitions
+ println"archetypeDefinitions${archetypeDefinitions.dump()}"
+ def archetype = archetypeCataloger.searchArchetype( [groupId:"archetypes", artifactId:"nested-complete-main", version:"1.0"], archetypeDefinitions )
+ assert archetype
+ println"archetype${archetype.dump()}"
+ def localRepository = repositoryCreator.createRepository( "${getBasedir()}/target/repositories/local".toString() )
+ def centralRepository = repositoryCreator.createRepository( "http://localhost:18881/central" )
+ assertTrue archetypeCataloger.archetypeRecursivelyExists( archetype, archetypeDefinitions, localRepository, [centralRepository] )
+ }
+
+ @Test void test_archetypeRecursivelyExists_missing() {
+ println "archetypeRecursivelyExists_missing"
+
+ def archetypeDefinitions = archetypeCataloger.getArchetypesByCatalog( "http://localhost:18881/central/archetype-catalog.xml" )
+ assert archetypeDefinitions
+ println"archetypeDefinitions${archetypeDefinitions.dump()}"
+ def archetype = archetypeCataloger.searchArchetype( [groupId:"archetypes", artifactId:"nested-missing-main", version:"1.0"], archetypeDefinitions )
+ assert archetype
+ println"archetype${archetype.dump()}"
+ def localRepository = repositoryCreator.createRepository( "${getBasedir()}/target/repositories/local".toString() )
+ def centralRepository = repositoryCreator.createRepository( "http://localhost:18881/central" )
+ assertFalse archetypeCataloger.archetypeRecursivelyExists( archetype, archetypeDefinitions, localRepository, [centralRepository] )
+ }
+}
+
diff --git a/grarchetype-common/src/test/groovy/org/apache/maven/archetype/file/DefaultArchetypeFileResolverTest.groovy b/grarchetype-common/src/test/groovy/org/apache/maven/archetype/file/DefaultArchetypeFileResolverTest.groovy
new file mode 100644
index 0000000..dfd347c
--- /dev/null
+++ b/grarchetype-common/src/test/groovy/org/apache/maven/archetype/file/DefaultArchetypeFileResolverTest.groovy
@@ -0,0 +1,76 @@
+package org.apache.maven.archetype.file
+import org.apache.maven.plugin.testing.AbstractMojoTestCase
+
+import org.junit.Test
+import static org.junit.Assert.*
+/**
+ *
+ * @author rafale
+ */
+class DefaultArchetypeFileResolverTest extends AbstractMojoTestCase {
+
+ void setUp(){
+ super.setUp()
+ archetypeResources = [
+ 'pom.xml',
+ 'sub/pom.xml',
+ 'sub/inner/deep/pom.xml',
+ 'src/main/java/App.java',
+ 'src/main/java/foo/Foo.java',
+ 'src/test/resources/images/logo.png',
+ 'src/test/resources/images/logo-big.png',
+ 'sub/src/main/webapp/WEB-INF/web.xml',
+ 'sub/inner/deep/src/main/groovy/bar/Bar.groovy']
+ resolver = lookup( DefaultArchetypeFileResolver.ROLE )
+ }
+ void tearDown(){super.tearDown()}
+
+ def resolver
+ def archetypeResources
+
+ @Test
+ void test_resolveRootModule(){
+ assertEquals 'RootModule', ['foo/Foo.java'],
+ resolver.getFiles( '', new XmlSlurper().parseText(
+"""
+<fileset>
+ <directory>src/main/java</directory>
+ <includes>
+ <include>**/*.java</include>
+ </includes>
+ <excludes>
+ <exclude>*.java</exclude>
+ </excludes>
+</fileset>
+""" ), archetypeResources )
+ }
+
+ @Test
+ void test_resolveSubModule(){
+ assertEquals 'SubModule', ['WEB-INF/web.xml'],
+ resolver.getFiles( 'sub', new XmlSlurper().parseText(
+"""
+<fileset>
+ <directory>src/main/webapp</directory>
+ <includes>
+ <include>**/*.xml</include>
+ </includes>
+</fileset>
+""" ), archetypeResources )
+ }
+
+ @Test
+ void test_resolveDeepModule(){
+ assertEquals 'DeepModule', ['bar/Bar.groovy'],
+ resolver.getFiles( 'sub/inner/deep', new XmlSlurper().parseText(
+"""
+<fileset>
+ <directory>src/main/groovy</directory>
+ <includes>
+ <include>**/*.groovy</include>
+ </includes>
+</fileset>
+""" ), archetypeResources )
+ }
+}
+
diff --git a/grarchetype-common/src/test/groovy/org/apache/maven/archetype/generator/DefaultArchetypefilesetGeneratorTest.groovy b/grarchetype-common/src/test/groovy/org/apache/maven/archetype/generator/DefaultArchetypefilesetGeneratorTest.groovy
new file mode 100644
index 0000000..3042340
--- /dev/null
+++ b/grarchetype-common/src/test/groovy/org/apache/maven/archetype/generator/DefaultArchetypefilesetGeneratorTest.groovy
@@ -0,0 +1,279 @@
+package org.apache.maven.archetype.generator
+
+import org.junit.Test
+import static org.junit.Assert.*
+import org.apache.maven.archetype.ArchetypeGenerationRequest
+import org.apache.maven.archetype.ArchetypeGenerationResult
+import org.apache.maven.archetype.generator.DefaultFilesetArchetypeGenerator
+import org.apache.maven.archetype.pom.PomManager
+import org.apache.maven.artifact.repository.DefaultArtifactRepository
+import org.apache.maven.artifact.repository.layout.DefaultRepositoryLayout
+
+import org.codehaus.plexus.PlexusTestCase
+import org.apache.maven.plugin.testing.AbstractMojoTestCase
+import org.codehaus.plexus.util.FileUtils
+
+
+/**
+ *
+ * @author rafale
+ */
+class DefaultArchetypeFilesetGeneratorTest extends AbstractMojoTestCase {
+ def project
+ def archetypeFile
+ def outputDirectory
+ def projectDirectory
+ def generator
+ def generationRequest
+ def pomManager
+
+ void setUp() {
+ super.setUp()
+ generator = lookup(FilesetArchetypeGenerator.ROLE, 'fileset')
+ pomManager = lookup(PomManager.ROLE)
+ }
+
+ void tearDown() {super.tearDown()}
+
+ @Test void test_generateMonoModuleProjectWithNoParent() {
+ println 'generateMonoModuleProjectWithNoParent'
+ prepareTest project: 'generateMonoModuleProjectWithNoParent', artifactId: 'file-value', archetype: 'basic'
+ generationRequest = new ArchetypeGenerationRequest(
+ archetypeFile: archetypeFile,
+ outputDirectory: outputDirectory,
+ generationFilterProperties: [
+ groupId: 'file-value',
+ artifactId: 'file-value',
+ version: 'file-value',
+ packageName: 'file.value.package',
+ propertyWithDefault: 'file-value',
+ propertyWithoutDefault: 'file-value'] as Properties
+ )
+ generator.generateProject generationRequest
+
+ assertTemplateContent 'src/main/java/file/value/package/App.java'
+ assertCopyContent 'src/main/resources/images/foo.png'
+ def pom = pomManager.loadModel(new File(projectDirectory, 'pom.xml'))
+ assertEquals 'file-value', pom.groupId
+ assertEquals 'file-value', pom.artifactId
+ assertEquals 'file-value', pom.version
+ }
+
+ @Test void test_generateMonoModuleProjectParentFromArchetype() {
+ println 'generateMonoModuleProjectParentFromArchetype'
+ prepareTest project: 'generateMonoModuleProjectParentFromArchetype', artifactId: 'file-value', archetype: 'basic-with-parent'
+ generationRequest = new ArchetypeGenerationRequest(
+ archetypeFile: archetypeFile,
+ outputDirectory: outputDirectory,
+ generationFilterProperties: [
+ groupId: 'file-value',
+ artifactId: 'file-value',
+ version: 'file-value',
+ packageName: 'file.value.package',
+ propertyWithDefault: 'file-value',
+ propertyWithoutDefault: 'file-value'] as Properties
+ )
+ generator.generateProject generationRequest
+
+ assertTemplateContent 'src/main/java/file/value/package/App.java'
+ assertCopyContent 'src/main/resources/images/foo.png'
+ def pom = pomManager.loadModel(new File(projectDirectory, 'pom.xml'))
+ assertNotNull pom.parent
+ assertEquals 'parent-doesnt-exist', pom.parent.artifactId
+ assertEquals 'file-value', pom.groupId
+ assertEquals 'file-value', pom.artifactId
+ assertEquals 'file-value', pom.version
+ def parentPom = pomManager.loadModel(new File(outputDirectory, 'pom.xml'))
+ assertEquals 1, parentPom.modules.size()
+ }
+
+ @Test void test_generateMonoModuleProjectParentFromDirectory() {
+ println 'generateMonoModuleProjectParentFromDirectory'
+ prepareTest project: 'generateMonoModuleProjectParentFromDirectory', artifactId: 'file-value', archetype: 'basic'
+ generationRequest = new ArchetypeGenerationRequest(
+ archetypeFile: archetypeFile,
+ outputDirectory: outputDirectory,
+ generationFilterProperties: [
+ groupId: 'file-value',
+ artifactId: 'file-value',
+ version: 'file-value',
+ packageName: 'file.value.package',
+ propertyWithDefault: 'file-value',
+ propertyWithoutDefault: 'file-value'] as Properties
+ )
+ generator.generateProject generationRequest
+
+ assertTemplateContent 'src/main/java/file/value/package/App.java'
+ assertCopyContent 'src/main/resources/images/foo.png'
+ def pom = pomManager.loadModel(new File(projectDirectory, 'pom.xml'))
+ assertNotNull pom.parent
+ assertEquals 'generateMonoModuleProjectParentFromDirectory', pom.parent.artifactId
+ assertEquals 'file-value', pom.groupId
+ assertEquals 'file-value', pom.artifactId
+ assertEquals 'file-value', pom.version
+ def parentPom = pomManager.loadModel(new File(outputDirectory, 'pom.xml'))
+ assertEquals 1, parentPom.modules.size()
+ }
+
+ @Test void test_generateMultiModuleProjectWithNoParent() {
+ println 'generateMultiModuleProjectWithNoParent'
+ prepareTest project: 'generateMultiModuleProjectWithNoParent', artifactId: 'foobar', archetype: 'multi'
+ generationRequest = new ArchetypeGenerationRequest(
+ archetypeFile: archetypeFile,
+ outputDirectory: outputDirectory,
+ generationFilterProperties: [
+ groupId: 'file-value',
+ artifactId: 'foobar',
+ version: 'file-value',
+ packageName: 'file.value.package',
+ propertyWithDefault: 'file-value',
+ propertyWithoutDefault: 'file-value'] as Properties
+ )
+ generator.generateProject generationRequest
+
+ def pom = pomManager.loadModel(new File(projectDirectory, 'pom.xml'))
+ assertEquals 'file-value', pom.groupId
+ assertEquals 'foobar', pom.artifactId
+ assertEquals 'file-value', pom.version
+
+ def innestPom = pomManager.loadModel(new File(projectDirectory, "foobar-c/foobar-e/foobar-c-h/pom.xml"))
+ assertEquals 'file-value', innestPom.parent.groupId
+ assertEquals 'foobar-e', innestPom.parent.artifactId
+ assertEquals 'foobar-c-h', innestPom.artifactId
+ assertEquals 'file-value', innestPom.version
+ }
+
+ @Test void test_generateMultiModuleProjectWithParentFromArchetype() {
+ println 'generateMultiModuleProjectWithParentFromArchetype'
+ prepareTest project: 'generateMultiModuleProjectWithParentFromArchetype', artifactId: 'foobar', archetype: 'multi-with-parent'
+ generationRequest = new ArchetypeGenerationRequest(
+ archetypeFile: archetypeFile,
+ outputDirectory: outputDirectory,
+ generationFilterProperties: [
+ groupId: 'file-value',
+ artifactId: 'foobar',
+ version: 'file-value',
+ packageName: 'file.value.package',
+ propertyWithDefault: 'file-value',
+ propertyWithoutDefault: 'file-value'] as Properties
+ )
+ generator.generateProject generationRequest
+
+ def pom = pomManager.loadModel(new File(projectDirectory, 'pom.xml'))
+ assertNotNull pom.parent
+ assertEquals 'parent-doesnt-exist', pom.parent.artifactId
+ assertEquals 'file-value', pom.groupId
+ assertEquals 'foobar', pom.artifactId
+ assertEquals 'file-value', pom.version
+ def parentPom = pomManager.loadModel(new File(outputDirectory, 'pom.xml'))
+ assertEquals 1, parentPom.modules.size
+
+ def innestPom = pomManager.loadModel(new File(projectDirectory, "foobar-c/foobar-e/foobar-c-h/pom.xml"))
+ assertEquals 'file-value', innestPom.parent.groupId
+ assertEquals 'foobar-e', innestPom.parent.artifactId
+ assertEquals 'foobar-c-h', innestPom.artifactId
+ assertEquals 'file-value', innestPom.version
+ }
+
+ @Test void test_generateMultiModuleProjectWithParentFromDirectory() {
+ println 'generateMultiModuleProjectWithParentFromDirectory'
+ prepareTest project: 'generateMultiModuleProjectWithParentFromDirectory', artifactId: 'foobar', archetype: 'multi'
+ generationRequest = new ArchetypeGenerationRequest(
+ archetypeFile: archetypeFile,
+ outputDirectory: outputDirectory,
+ generationFilterProperties: [
+ groupId: 'file-value',
+ artifactId: 'foobar',
+ version: 'file-value',
+ packageName: 'file.value.package',
+ propertyWithDefault: 'file-value',
+ propertyWithoutDefault: 'file-value'] as Properties
+ )
+ generator.generateProject generationRequest
+
+ def pom = pomManager.loadModel(new File(projectDirectory, 'pom.xml'))
+ assertNotNull pom.parent
+ assertEquals 'generateMultiModuleProjectWithParentFromDirectory', pom.parent.artifactId
+ assertEquals 'file-value', pom.groupId
+ assertEquals 'foobar', pom.artifactId
+ assertEquals 'file-value', pom.version
+ def parentPom = pomManager.loadModel(new File(outputDirectory, 'pom.xml'))
+ assertEquals 1, parentPom.modules.size()
+
+ def innestPom = pomManager.loadModel(new File(projectDirectory, "foobar-c/foobar-e/foobar-c-h/pom.xml"))
+ assertEquals 'file-value', innestPom.parent.groupId
+ assertEquals 'foobar-e', innestPom.parent.artifactId
+ assertEquals 'foobar-c-h', innestPom.artifactId
+ assertEquals 'file-value', innestPom.version
+ }
+
+ private void prepareTest(args) {
+ project = args.project
+ outputDirectory = "${basedir}/target/projects/$project"
+ projectDirectory = new File(outputDirectory, args.artifactId)
+ assertDeleted projectDirectory
+ archetypeFile = new File("${basedir}/target/repositories/central/archetypes/${args.archetype}/1.0/${args.archetype}-1.0.jar")
+ }
+
+ private void assertDeleted(file) {
+ if (file.exists()) {
+ if (file.isDirectory()) {
+ try {
+ FileUtils.deleteDirectory file
+ } catch (IOException e) {
+ fail "Unable to delete directory:$file:${e.getLocalizedMessage()}"
+ }
+ }
+ } else {
+ try {
+ FileUtils.forceDelete file
+ } catch (IOException e) {
+ fail "Unable to delete file:$file:${e.getLocalizedMessage()}"
+ e.printStackTrace()
+ }
+ }
+ if (file.exists()) {
+ fail "File not deleted:$file"
+ }
+ }
+
+ private def loadProperties(template) {
+ def templateFile = new File(projectDirectory, template)
+ if (!templateFile.exists()) fail "Missing File:$templateFile"
+
+ Properties properties = new Properties()
+ properties.load new FileInputStream(templateFile)
+ return properties
+ }
+
+ private void assertTemplateContent(template) {
+ Properties properties = loadProperties(template)
+ assertEquals "file-value", properties["groupId"]
+ assertEquals "file-value", properties["artifactId"]
+ assertEquals "file-value", properties["version"]
+ assertEquals "file.value.package", properties["package"]
+ assertEquals "file-value", properties["propertyWithDefault"]
+ assertEquals "file-value", properties["propertyWithoutDefault"]
+
+ assertEquals "file/value/package", properties["packageReplaced"]
+ assertEquals "file/value/package", properties["packageReplaced2"]
+ assertEquals '${packageName.replace(\'.\', \'/\')}', properties["ignoredDollar"]
+ assertEquals "<%=packageName.replace('.', '/')%>", properties["ignoredInferior"]
+ }
+
+ private void assertCopyContent(template) {
+ Properties properties = loadProperties(template)
+ assertEquals '${groupId}', properties["groupId"]
+ assertEquals '${artifactId}', properties["artifactId"]
+ assertEquals '${version}', properties["version"]
+ assertEquals '${packageName}', properties["package"]
+ assertEquals '${propertyWithDefault}', properties["propertyWithDefault"]
+ assertEquals '${propertyWithoutDefault}', properties["propertyWithoutDefault"]
+
+ assertEquals '${packageName.replace(\'.\', \'/\')}', properties["packageReplaced"]
+ assertEquals "<%=packageName.replace('.', '/')%>", properties["packageReplaced2"]
+ assertEquals '${packageName.replace(\'.\', \'/\')}', properties["ignoredDollar"]
+ assertEquals '${\'<\'}%=packageName.replace(\'.\', \'/\')%>', properties["ignoredInferior"]
+ }
+}
+
diff --git a/grarchetype-common/src/test/groovy/org/apache/maven/archetype/generator/DefaultProjectGeneratorTest.groovy b/grarchetype-common/src/test/groovy/org/apache/maven/archetype/generator/DefaultProjectGeneratorTest.groovy
new file mode 100644
index 0000000..3597a98
--- /dev/null
+++ b/grarchetype-common/src/test/groovy/org/apache/maven/archetype/generator/DefaultProjectGeneratorTest.groovy
@@ -0,0 +1,234 @@
+package org.apache.maven.archetype.generator
+
+import org.junit.Test
+import static org.junit.Assert.*
+import org.codehaus.plexus.PlexusTestCase
+import org.apache.maven.plugin.testing.AbstractMojoTestCase
+import org.codehaus.plexus.util.FileUtils
+import org.apache.maven.archetype.ArchetypeGenerationRequest
+import org.apache.maven.archetype.ArchetypeGenerationResult
+import org.apache.maven.archetype.generator.DefaultProjectGenerator
+import org.apache.maven.archetype.pom.PomManager
+import org.apache.maven.artifact.repository.ArtifactRepositoryPolicy
+import org.apache.maven.artifact.repository.ArtifactRepositoryFactory
+import org.apache.maven.artifact.repository.layout.ArtifactRepositoryLayout
+
+/**
+ *
+ * @author raphaelpieroni
+ */
+class DefaultProjectGeneratorTest extends AbstractMojoTestCase {
+ def generator
+ def pomManager
+ def generationRequest
+ def project
+ def outputDirectory
+ def projectDirectory
+ def artifactRepositoryFactory
+ def localRepository
+ def remoteRepostories
+ def defaultArtifactRepositoryLayout
+ void setUp() {
+ super.setUp()
+ generator = lookup( ProjectGenerator.ROLE )
+ pomManager = lookup( PomManager.ROLE )
+ artifactRepositoryFactory = lookup( ArtifactRepositoryFactory.ROLE )
+ defaultArtifactRepositoryLayout = lookup( ArtifactRepositoryLayout.ROLE )
+ }
+ void tearDown() {super.tearDown()}
+
+ @Test void test_generateNestedArchetypeSimple() {
+ println'generateNestedArchetypeSimple'
+ prepareTest project:'generateNestedArchetypeSimple', artifactId:'artifact'
+
+ generationRequest = new ArchetypeGenerationRequest(
+ groupId:'archetypes',
+ artifactId:'nested-main',
+ version:'1.0',
+ outputDirectory:outputDirectory,
+ generationFilterProperties:[
+ groupId:'file-value',
+ artifactId:'artifact',
+ version:'file-value',
+ packageName:'file.value.package',
+ propertyWithDefault:'file-value',
+ propertyWithoutDefault:'file-value'] as Properties,
+ localRepository:localRepository,
+ repositories:remoteRepostories
+ )
+ generator.generateProject generationRequest
+
+
+ //CORE
+ def artifact = loadModel( 'pom.xml' )
+ // assert no parent, modules, content
+ assertParent artifact, null
+ assertDefinition artifact, [groupId:'file-value', artifactId:'artifact', version:'file-value']
+ assertModules artifact, ['artifact-n-inner', 'artifact-n2-inner', 'artifact-n-old', 'artifact-inner']
+
+ def artifact_n_inner = loadModel( '/artifact-n-inner/pom.xml' )
+ // assert parent, modules, content
+ assertParent artifact_n_inner, [groupId:'file-value', artifactId:'artifact', version:'file-value']
+ assertDefinition artifact_n_inner, [groupId:'file-value', artifactId:'artifact-n-inner', version:'file-value']
+ assertModules artifact_n_inner, ['artifact-n-inner-n-innest', 'artifact-n-inner-n-old', 'artifact-n-inner-inner']
+
+ def artifact_n2_inner = loadModel( '/artifact-n2-inner/pom.xml' )
+ // assert parent, modules, content
+ assertParent artifact_n2_inner, [groupId:'file-value', artifactId:'artifact', version:'file-value']
+ assertDefinition artifact_n2_inner, [groupId:'file-value', artifactId:'artifact-n2-inner', version:'file-value']
+ assertModules artifact_n2_inner, ['artifact-n2-inner-n-innest', 'artifact-n2-inner-n-old', 'artifact-n2-inner-inner']
+
+ def artifact_n_old = loadModel( '/artifact-n-old/pom.xml' )
+ // assert parent, content
+ assertParent artifact_n_old, [groupId:'file-value', artifactId:'artifact', version:'file-value']
+ assertDefinition artifact_n_old, [groupId:'file-value', artifactId:'artifact-n-old', version:'file-value']
+ assertModules artifact_n_old, null
+
+ def artifact_inner = loadModel( '/artifact-inner/pom.xml' )
+ // assert parent, modules, content
+ assertParent artifact_inner, [groupId:'file-value', artifactId:'artifact', version:'file-value']
+ assertDefinition artifact_inner, [groupId:null, artifactId:'artifact-inner', version:'file-value']
+ assertModules artifact_inner, ['artifact-n-innest', 'artifact-innest']
+
+ def artifact_n_innest = loadModel( '/artifact-inner/artifact-n-innest/pom.xml' )
+ // assert parent, modules, content
+ assertParent artifact_n_innest, [groupId:'file-value', artifactId:'artifact-inner', version:'file-value']
+ assertDefinition artifact_n_innest, [groupId:'file-value', artifactId:'artifact-n-innest', version:'file-value']
+ assertModules artifact_n_innest, ['artifact-n-innest-inner', 'artifact-n-innest-n-innest', 'artifact-n-innest-n-old']
+
+ def artifact_innest = loadModel( '/artifact-inner/artifact-innest/pom.xml' )
+ // assert parent, content, partial
+ assertParent artifact_innest, [groupId:'file-value', artifactId:'artifact-inner', version:'file-value']
+ assertDefinition artifact_innest, [groupId:null, artifactId:'artifact-innest', version:'file-value']
+ assertModules artifact_innest, null
+
+
+
+
+ //NESTED FIRST LEVEL
+ def artifact_n_inner_n_innest = loadModel( '/artifact-n-inner/artifact-n-inner-n-innest/pom.xml' )
+ // assert parent, modules, content
+ def artifact_n_inner_n_old = loadModel( '/artifact-n-inner/artifact-n-inner-n-old/pom.xml' )
+ // assert parent, content
+ def artifact_n_inner_inner = loadModel( '/artifact-n-inner/artifact-n-inner-inner/pom.xml' )
+ // assert parent, modules, content
+ def artifact_n_inner_n2_innest = loadModel( '/artifact-n-inner/artifact-n-inner-inner/artifact-n-inner-n2-innest/pom.xml' )
+ // assert parent, modules, content
+ def artifact_n_inner_innest = loadModel( '/artifact-n-inner/artifact-n-inner-inner/artifact-n-inner-innest/pom.xml' )
+ // assert parent, content, partial
+
+ def artifact_n2_inner_n_innest = loadModel( '/artifact-n2-inner/artifact-n2-inner-n-innest/pom.xml' )
+ // assert parent, modules, content
+ def artifact_n2_inner_n_old = loadModel( '/artifact-n2-inner/artifact-n2-inner-n-old/pom.xml' )
+ // assert parent, content
+ def artifact_n2_inner_inner = loadModel( '/artifact-n2-inner/artifact-n2-inner-inner/pom.xml' )
+ // assert parent, modules, content
+ def artifact_n2_inner_n2_innest = loadModel( '/artifact-n2-inner/artifact-n2-inner-inner/artifact-n2-inner-n2-innest/pom.xml' )
+ // assert parent, modules, content
+ def artifact_n2_inner_innest = loadModel( '/artifact-n2-inner/artifact-n2-inner-inner/artifact-n2-inner-innest/pom.xml' )
+ // assert parent, content, partial
+
+ def artifact_n_innest_n_innest = loadModel( '/artifact-inner/artifact-n-innest/artifact-n-innest-n-innest/pom.xml' )
+ // assert parent, modules, content
+ def artifact_n_innest_n_old = loadModel( '/artifact-inner/artifact-n-innest/artifact-n-innest-n-old/pom.xml' )
+ // assert parent, content
+ def artifact_n_innest_inner = loadModel( '/artifact-inner/artifact-n-innest/artifact-n-innest-inner/pom.xml' )
+ // assert parent, modules, content
+ def artifact_n_innest_n2_innest = loadModel( '/artifact-inner/artifact-n-innest/artifact-n-innest-inner/artifact-n-innest-n2-innest/pom.xml' )
+ // assert parent, modules, content
+ def artifact_n_innest_innest = loadModel( '/artifact-inner/artifact-n-innest/artifact-n-innest-inner/artifact-n-innest-innest/pom.xml' )
+ // assert parent, content, partial
+
+
+
+
+// fail 'NO ASSERT YET'
+
+
+
+ }
+
+
+ private void assertModules( pom, expectedModules ) {
+ println"POM=${pom?.modules?.dump()}"
+ println"EXP=${expectedModules?.dump()}"
+
+ if( !expectedModules ) {
+ assertTrue !pom.modules
+ return
+ }
+ if( !pom.modules ) fail 'When modules provided, pom should have modules'
+ assertEquals expectedModules.size(), pom.modules.size()
+ expectedModules.each{
+ assertTrue pom.modules.contains( it )
+ }
+ }
+ private void assertDefinition( pom, expected ) {
+ if( !expected ) fail 'expected should be provided'
+ assertEquals expected.groupId, pom.groupId
+ assertEquals expected.artifactId, pom.artifactId
+ assertEquals expected.version, pom.version
+ }
+ private void assertParent( pom, expectedParent ) {
+ if( !expectedParent ) assertTrue !pom.parent ; return
+ if( !pom.parent ) fail 'When parent provided, pom should have parent'
+ assertEquals expectedParent.groupId, pom.parent.groupId
+ assertEquals expectedParent.artifactId, pom.parent.artifactId
+ assertEquals expectedParent.version, pom.parent.version
+ }
+ private def loadModel( pom ) {
+ pomManager.loadModel( new File( projectDirectory, pom ) )
+ }
+ private void prepareTest( args ) {
+ project = args.project
+ outputDirectory = "${basedir}/target/projects/${project}"
+ projectDirectory = new File( outputDirectory, args.artifactId )
+
+ localRepository = createRepository( "file://${basedir}/target/repositories/local/${project}", 'local' )
+ remoteRepostories = [createRepository( "file://${basedir}/target/repositories/central", 'central' )]
+ new File( "${basedir}/target/repositories/local/${project}" ).mkdirs()
+
+ assertDeleted projectDirectory
+ }
+ private void assertDeleted( file ) {
+ if ( file.exists() ) {
+ if ( file.isDirectory() ) {
+ try {
+ FileUtils.deleteDirectory file
+ } catch ( IOException e ) {
+ fail "Unable to delete directory:$file:${e.getLocalizedMessage()}"
+ }
+ }
+ } else {
+ try {
+ FileUtils.forceDelete file
+ } catch ( IOException e ) {
+ fail "Unable to delete file:$file:${e.getLocalizedMessage()}"
+ e.printStackTrace()
+ }
+ }
+ if ( file.exists() ) {
+ fail "File not deleted:$file"
+ }
+ }
+ private def createRepository( url, repositoryId ) {
+
+ def updatePolicyFlag = ArtifactRepositoryPolicy.UPDATE_POLICY_ALWAYS
+ def checksumPolicyFlag = ArtifactRepositoryPolicy.CHECKSUM_POLICY_WARN
+
+ def snapshotsPolicy = new ArtifactRepositoryPolicy( true, updatePolicyFlag, checksumPolicyFlag )
+ def releasesPolicy = new ArtifactRepositoryPolicy( true, updatePolicyFlag, checksumPolicyFlag )
+
+ def repo =
+ artifactRepositoryFactory.createArtifactRepository(
+ repositoryId,
+ url,
+ defaultArtifactRepositoryLayout,
+ snapshotsPolicy,
+ releasesPolicy
+ )
+
+ return repo
+ }
+}
+
diff --git a/grarchetype-common/src/test/groovy/org/apache/maven/archetype/util/ScannerTest.groovy b/grarchetype-common/src/test/groovy/org/apache/maven/archetype/util/ScannerTest.groovy
new file mode 100644
index 0000000..1354c81
--- /dev/null
+++ b/grarchetype-common/src/test/groovy/org/apache/maven/archetype/util/ScannerTest.groovy
@@ -0,0 +1,65 @@
+package org.apache.maven.archetype.util
+
+import org.junit.Test
+import static org.junit.Assert.*
+
+
+/**
+ *
+ * @author rafale
+ */
+class ScannerTest {
+// def scanner = new Scanner( fileset:fileset )
+ @Test
+ void test_includeAll() {
+ def scanner = new Scanner( fileset: new XmlSlurper().parseText(
+"""
+<fileset>
+ <includes>
+ <include>**/*</include>
+ </includes>
+</fileset>
+""" ) )
+ assertTrue scanner.match( 'App.java' )
+ assertTrue scanner.match( 'foo/bar/baz/App.java' )
+ assertTrue scanner.match( 'App.properties' )
+ assertTrue scanner.match( 'foo/bar/baz/App.properties' )
+ }
+
+ @Test
+ void test_includeJavaBar() {
+ def scanner = new Scanner( fileset: new XmlSlurper().parseText(
+"""
+<fileset>
+ <includes>
+ <include>**/*.java</include>
+ <include>**/bar/**/*</include>
+ </includes>
+</fileset>
+""" ) )
+ assertTrue scanner.match( 'App.java' )
+ assertTrue scanner.match( 'foo/bar/baz/App.java' )
+ assertFalse scanner.match( 'App.properties' )
+ assertTrue scanner.match( 'foo/bar/baz/App.properties' )
+ }
+
+ @Test
+ void test_includeJavaExcludeBar() {
+ def scanner = new Scanner( fileset: new XmlSlurper().parseText(
+"""
+<fileset>
+ <includes>
+ <include>**/*.java</include>
+ </includes>
+ <excludes>
+ <exclude>**/bar/**/*</exclude>
+ </excludes>
+</fileset>
+""" ) )
+ assertTrue scanner.match( 'App.java' )
+ assertFalse scanner.match( 'foo/bar/baz/App.java' )
+ assertFalse scanner.match( 'App.properties' )
+ assertFalse scanner.match( 'foo/bar/baz/App.properties' )
+ }
+}
+
diff --git a/grarchetype-common/src/test/pom.xml b/grarchetype-common/src/test/pom.xml
new file mode 100644
index 0000000..8965774
--- /dev/null
+++ b/grarchetype-common/src/test/pom.xml
@@ -0,0 +1,9 @@
+
+<project schemaLocation='http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd'>
+ <tag0:modelVersion xmlns:tag0='http://maven.apache.org/POM/4.0.0'>4.0.0</tag0:modelVersion>
+ <tag0:groupId xmlns:tag0='http://maven.apache.org/POM/4.0.0'>${groupId}</tag0:groupId>
+ <tag0:artifactId xmlns:tag0='http://maven.apache.org/POM/4.0.0'>${artifactId}</tag0:artifactId>
+ <tag0:version xmlns:tag0='http://maven.apache.org/POM/4.0.0'>${version}</tag0:version>
+ <tag0:name xmlns:tag0='http://maven.apache.org/POM/4.0.0'>Maven archetype Test</tag0:name>
+ <tag0:packaging xmlns:tag0='http://maven.apache.org/POM/4.0.0'>jar</tag0:packaging>
+</project>
\ No newline at end of file
diff --git a/grarchetype-common/src/test/projects/generateMonoModuleProjectParentFromArchetype/pom.xml b/grarchetype-common/src/test/projects/generateMonoModuleProjectParentFromArchetype/pom.xml
new file mode 100644
index 0000000..d3690ec
--- /dev/null
+++ b/grarchetype-common/src/test/projects/generateMonoModuleProjectParentFromArchetype/pom.xml
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+
+ <modelVersion>4.0.0</modelVersion>
+
+ <groupId>org.apache.maven.grarchetype.test</groupId>
+ <artifactId>generateMonoModuleProjectParentFromArchetype</artifactId>
+ <version>1.5</version>
+ <packaging>pom</packaging>
+
+</project>
diff --git a/grarchetype-common/src/test/projects/generateMonoModuleProjectParentFromDirectory/pom.xml b/grarchetype-common/src/test/projects/generateMonoModuleProjectParentFromDirectory/pom.xml
new file mode 100644
index 0000000..a9d3a30
--- /dev/null
+++ b/grarchetype-common/src/test/projects/generateMonoModuleProjectParentFromDirectory/pom.xml
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+
+ <modelVersion>4.0.0</modelVersion>
+
+ <groupId>org.apache.maven.grarchetype.test</groupId>
+ <artifactId>generateMonoModuleProjectParentFromDirectory</artifactId>
+ <version>1.5</version>
+ <packaging>pom</packaging>
+
+</project>
diff --git a/grarchetype-common/src/test/projects/generateMultiModuleProjectWithParentFromArchetype/pom.xml b/grarchetype-common/src/test/projects/generateMultiModuleProjectWithParentFromArchetype/pom.xml
new file mode 100644
index 0000000..a95a1de
--- /dev/null
+++ b/grarchetype-common/src/test/projects/generateMultiModuleProjectWithParentFromArchetype/pom.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <groupId>org.apache.maven.grarchetype.test</groupId>
+ <artifactId>generateMultiModuleProjectWithParentFromArchetype</artifactId>
+ <version>1.5</version>
+ <packaging>pom</packaging>
+</project>
\ No newline at end of file
diff --git a/grarchetype-common/src/test/projects/generateMultiModuleProjectWithParentFromDirectory/pom.xml b/grarchetype-common/src/test/projects/generateMultiModuleProjectWithParentFromDirectory/pom.xml
new file mode 100644
index 0000000..02b9aed
--- /dev/null
+++ b/grarchetype-common/src/test/projects/generateMultiModuleProjectWithParentFromDirectory/pom.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <groupId>org.apache.maven.grarchetype.test</groupId>
+ <artifactId>generateMultiModuleProjectWithParentFromDirectory</artifactId>
+ <version>1.5</version>
+ <packaging>pom</packaging>
+</project>
\ No newline at end of file
diff --git a/grarchetype-common/src/test/repositories/central/archetype-catalog.xml b/grarchetype-common/src/test/repositories/central/archetype-catalog.xml
new file mode 100644
index 0000000..a727e71
--- /dev/null
+++ b/grarchetype-common/src/test/repositories/central/archetype-catalog.xml
@@ -0,0 +1,53 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<archetype-catalog>
+ <archetypes>
+ <archetype>
+ <groupId>archetypes</groupId>
+ <artifactId>single-version</artifactId>
+ <version>RELEASE</version>
+ <description></description>
+ </archetype>
+ <archetype>
+ <groupId>archetypes</groupId>
+ <artifactId>multi-version</artifactId>
+ <version>1</version>
+ </archetype>
+ <archetype>
+ <groupId>archetypes</groupId>
+ <artifactId>multi-version</artifactId>
+ <version>2</version>
+ </archetype>
+ <archetype>
+ <groupId>archetypes</groupId>
+ <artifactId>multi-version</artifactId>
+ <version>3</version>
+ </archetype>
+
+ <archetype>
+ <groupId>archetypes</groupId>
+ <artifactId>nested-complete-main</artifactId>
+ <version>1.0</version>
+ </archetype>
+ <archetype>
+ <groupId>archetypes</groupId>
+ <artifactId>nested-complete-inner</artifactId>
+ <version>1.0</version>
+ </archetype>
+ <archetype>
+ <groupId>archetypes</groupId>
+ <artifactId>nested-complete-innest</artifactId>
+ <version>1.0</version>
+ </archetype>
+
+ <archetype>
+ <groupId>archetypes</groupId>
+ <artifactId>nested-missing-main</artifactId>
+ <version>1.0</version>
+ </archetype>
+ <archetype>
+ <groupId>archetypes</groupId>
+ <artifactId>nested-missing-inner</artifactId>
+ <version>1.0</version>
+ </archetype>
+ </archetypes>
+</archetype-catalog>
\ No newline at end of file
diff --git a/grarchetype-common/src/test/repositories/local/dummy b/grarchetype-common/src/test/repositories/local/dummy
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/grarchetype-common/src/test/repositories/local/dummy
diff --git a/grarchetype-plugin/pom.xml b/grarchetype-plugin/pom.xml
new file mode 100644
index 0000000..723d220
--- /dev/null
+++ b/grarchetype-plugin/pom.xml
@@ -0,0 +1,266 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.apache.maven.grarchetype</groupId>
+ <artifactId>maven-grarchetype</artifactId>
+ <version>2.0-alpha-5-SNAPSHOT</version>
+ </parent>
+
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-grarchetype-plugin</artifactId>
+
+ <name>Maven GRArchetype Plugin</name>
+ <url>http://maven.apache.org/plugins/maven-archetype-plugin</url>
+ <packaging>maven-plugin</packaging>
+
+ <prerequisites>
+ <maven>${mavenVersion}</maven>
+ </prerequisites>
+
+ <scm>
+ <connection>scm:svn:http://svn.apache.org/repos/asf/maven/archetype/trunk/archetype-plugin</connection>
+ <developerConnection>scm:svn:https://svn.apache.org/repos/asf/maven/archetype/trunk/archetype-plugin</developerConnection>
+ <url>http://svn.apache.org/viewvc/maven/archetype/trunk/archetype-plugin</url>
+ </scm>
+
+
+ <dependencies>
+ <dependency>
+ <groupId>org.apache.maven.grarchetype</groupId>
+ <artifactId>grarchetype-common</artifactId>
+ <version>2.0-alpha-5-SNAPSHOT</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.maven</groupId>
+ <artifactId>maven-plugin-api</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.maven</groupId>
+ <artifactId>maven-project</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.maven</groupId>
+ <artifactId>maven-core</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.codehaus.groovy</groupId>
+ <artifactId>groovy-all</artifactId>
+ <version>1.6.0</version>
+ </dependency>
+ <!--dependency>
+ <groupId>org.codehaus.groovy.maven</groupId>
+ <artifactId>gmaven-mojo</artifactId>
+ <version>1.0-rc-4</version>
+ </dependency-->
+ <dependency>
+ <groupId>org.apache.maven.shared</groupId>
+ <artifactId>maven-plugin-testing-harness</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.maven.wagon</groupId>
+ <artifactId>wagon-file</artifactId>
+ <version>1.0-beta-2</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.maven.wagon</groupId>
+ <artifactId>wagon-http</artifactId>
+ <version>1.0-beta-2</version><!-- with 1.0-beta-4 some tests fail -->
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.codehaus.cargo</groupId>
+ <artifactId>cargo-core-api-container</artifactId>
+ <version>1.0-alpha-6</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.codehaus.cargo</groupId>
+ <artifactId>cargo-core-api-util</artifactId>
+ <version>1.0-alpha-6</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.codehaus.cargo</groupId>
+ <artifactId>cargo-core-api-generic</artifactId>
+ <version>1.0-alpha-6</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.codehaus.cargo</groupId>
+ <artifactId>cargo-core-api-module</artifactId>
+ <version>1.0-alpha-6</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.codehaus.cargo</groupId>
+ <artifactId>cargo-core-container-jetty</artifactId>
+ <version>1.0-alpha-6</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.mortbay.jetty</groupId>
+ <artifactId>jetty</artifactId>
+ <version>6.1.11</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>${project.parent.groupId}</groupId>
+ <artifactId>grarchetype-repository</artifactId>
+ <version>${project.version}</version>
+ <type>war</type>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-plugin-plugin</artifactId>
+ <version>2.4.3</version>
+ <configuration>
+ <goalPrefix>grarchetype</goalPrefix>
+ <updateReleaseInfo>true</updateReleaseInfo>
+ </configuration>
+ <executions>
+ <execution>
+ <id>generated-descriptor</id>
+ <goals>
+ <goal>descriptor</goal>
+ </goals>
+ <phase>compile</phase>
+ </execution>
+ <execution>
+ <id>generated-helpmojo</id>
+ <goals>
+ <goal>helpmojo</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-surefire-plugin</artifactId>
+ <configuration>
+ <systemProperties>
+ <property>
+ <name>maven.home</name>
+ <value>${maven.home}</value>
+ </property>
+ </systemProperties>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.codehaus.groovy.maven</groupId>
+ <artifactId>gmaven-plugin</artifactId>
+ <version>1.0-rc-5</version>
+ <configuration>
+ <providerSelection>1.6</providerSelection>
+ </configuration>
+ <executions>
+ <execution>
+ <id>generate-sources</id>
+ <phase>generate-sources</phase>
+ <goals>
+ <goal>generateStubs</goal>
+ </goals>
+ </execution>
+ <execution>
+ <id>compile</id>
+ <phase>compile</phase>
+ <goals>
+ <goal>compile</goal>
+ </goals>
+ </execution>
+ <execution>
+ <id>test-compile</id>
+ <phase>test-compile</phase>
+ <goals>
+ <goal>testCompile</goal>
+ </goals>
+ </execution>
+ <execution>
+ <id>prepareRepositories</id>
+ <phase>generate-test-resources</phase>
+ <goals>
+ <goal>execute</goal>
+ </goals>
+ <configuration>
+ <source>
+log.info "Preparing Repositories"
+def dir = "${project.basedir}/target/repositories"
+ant.delete dir: dir
+ant.mkdir dir: dir
+ant.copy( toDir: dir ) {
+ fileset dir: "${project.basedir}/src/test/repositories"
+}
+
+def prepareArchetype = { archetype, archetypeVersion ->
+ if( project.packaging != 'pom' ) {
+ log.info "Preparing ${archetype}-${archetypeVersion} archetype..."
+ dir = "${project.basedir}/target/repositories/central/archetypes/${archetype}/${archetypeVersion}"
+ ant.mkdir dir: dir
+ ant.jar destFile: "${dir}/${archetype}-${archetypeVersion}.jar", basedir: "${project.basedir}/src/test/archetypes/${archetype}"
+ }
+}
+prepareArchetype 'nested-properties-main', '1.0'
+prepareArchetype 'nested-properties-inner', '1.0'
+prepareArchetype 'nested-properties-innest', '1.0'
+
+prepareArchetype 'old', '1.0'
+ </source>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-dependency-plugin</artifactId>
+ <executions>
+ <execution>
+ <id>copy</id>
+ <phase>process-test-resources</phase>
+ <goals>
+ <goal>copy-dependencies</goal>
+ </goals>
+ <configuration>
+ <outputDirectory>${project.build.directory}/wars</outputDirectory>
+ <overWriteReleases>true</overWriteReleases>
+ <overWriteSnapshots>true</overWriteSnapshots>
+ <includeTypes>war</includeTypes>
+ <stripVersion>true</stripVersion>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </build>
+
+ <reporting>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-plugin-plugin</artifactId>
+ <version>2.4.3</version>
+ <reportSets>
+ <reportSet>
+ <reports>
+ <report>report</report>
+ </reports>
+ </reportSet>
+ </reportSets>
+ </plugin>
+ </plugins>
+ </reporting>
+
+</project>
diff --git a/grarchetype-plugin/src/main/groovy/org/apache/maven/archetype/mojos/CreateProjectFromArchetypeMojo.groovy b/grarchetype-plugin/src/main/groovy/org/apache/maven/archetype/mojos/CreateProjectFromArchetypeMojo.groovy
new file mode 100644
index 0000000..b4818c2
--- /dev/null
+++ b/grarchetype-plugin/src/main/groovy/org/apache/maven/archetype/mojos/CreateProjectFromArchetypeMojo.groovy
@@ -0,0 +1,125 @@
+package org.apache.maven.archetype.mojos
+import org.apache.maven.plugin.AbstractMojo
+import org.apache.maven.plugin.ContextEnabled
+import org.apache.maven.plugin.MojoExecutionException
+import org.apache.maven.plugin.MojoFailureException
+import org.apache.maven.archetype.Archetype
+import org.apache.maven.archetype.ArchetypeGenerationRequest
+
+import org.apache.maven.execution.MavenSession
+import org.apache.maven.archetype.ui.ArchetypeSelector
+import org.apache.maven.archetype.ui.ArchetypeGenerationConfigurator
+
+/**
+ *
+ * @author rafale
+ * @requiresProject false
+ * @goal generate
+ */
+class CreateProjectFromArchetypeMojo
+extends AbstractMojo
+implements ContextEnabled {
+
+ /** @component */
+ private Archetype archetype
+ /** @component */
+ private ArchetypeSelector selector
+ /** @component */
+ private ArchetypeGenerationConfigurator configurator
+
+
+ /**
+ * The archetype's artifactId.
+ *
+ * @parameter expression="${archetypeArtifactId}"
+ */
+ private String archetypeArtifactId
+
+ /**
+ * The archetype's groupId.
+ *
+ * @parameter expression="${archetypeGroupId}"
+ */
+ private String archetypeGroupId
+
+ /**
+ * The archetype's version.
+ *
+ * @parameter expression="${archetypeVersion}"
+ */
+ private String archetypeVersion
+
+ /**
+ * The archetype's catalogs.
+ * It is a comma separated list of catalogs.
+ * Catalogs use scheme:
+ * - 'file://...' with archetype-catalog.xml automatically appended when defining a directory
+ * - 'http://...' with archetype-catalog.xml always appended
+ * - 'local' which is the shortcut for 'file://~/.m2/archetype-catalog.xml'
+ * - 'remote' which is the shortcut for 'http://repo1.maven.org/maven2'
+ * - 'internal' which is an internal catalog
+ *
+ * @parameter expression="${archetypeCatalog}" default-value="internal,local"
+ */
+ private String archetypeCatalog
+
+ /**
+ * User settings use to check the interactiveMode.
+ *
+ * @parameter expression="${interactiveMode}" default-value="${settings.interactiveMode}"
+ * @required
+ */
+ private Boolean interactiveMode
+
+ /** @parameter expression="${basedir}" */
+ private File basedir
+
+ /**
+ * @parameter expression="${session}"
+ * @readonly
+ */
+ MavenSession session
+
+ public void execute()
+ throws MojoExecutionException, MojoFailureException {
+
+ println"\n\n session ${session.dump()}"
+ println"\n\n container ${session.container.dump()}"
+ println"\n\n currentProject ${session.currentProject.dump()}"
+ println"\n\n eventDispatcher ${session.eventDispatcher.dump()}"
+ println"\n\n executionProperties ${session.executionProperties.dump()}"
+ println"\n\n executionRootDir ${session.executionRootDir.dump()}"
+ println"\n\n goals ${session.goals.dump()}"
+ println"\n\n localRepository ${session.localRepository.dump()}"
+ println"\n\n reactorManager ${session.reactorManager.dump()}"
+ println"\n\n settings ${session.settings.dump()}"
+ println"\n\n startTime ${session.startTime.dump()}"
+ println"\n\n usingPOMsFromFilesystem ${session.usingPOMsFromFilesystem.dump()}"
+// println"session ${session.dump()}"
+// println"session ${session.dump()}"
+// println"session ${session.dump()}"
+// println"session ${session.dump()}"
+// println"session ${session.dump()}"
+
+
+ def request = new ArchetypeGenerationRequest(
+ groupId : archetypeGroupId,
+ artifactId : archetypeArtifactId,
+ version : archetypeVersion,
+ outputDirectory : basedir.absolutePath,
+ repositories : session.currentProject.remoteArtifactRepositories,
+ localRepository : session.localRepository
+ )
+ selector.selectArchetype request, interactiveMode, archetypeCatalog
+ configurator.configureArchetype request, interactiveMode, session.executionProperties
+
+ def result = archetype.generateProjectFromArchetype( request )
+
+
+ println "RESULT=${result?.dump()}"
+ result?.cause?.printStackTrace()
+
+ }
+
+}
+
diff --git a/grarchetype-plugin/src/main/groovy/org/apache/maven/archetype/ui/ArchetypeGenerationConfigurator.groovy b/grarchetype-plugin/src/main/groovy/org/apache/maven/archetype/ui/ArchetypeGenerationConfigurator.groovy
new file mode 100644
index 0000000..8f11f0a
--- /dev/null
+++ b/grarchetype-plugin/src/main/groovy/org/apache/maven/archetype/ui/ArchetypeGenerationConfigurator.groovy
@@ -0,0 +1,13 @@
+package org.apache.maven.archetype.ui
+
+/**
+ *
+ * @author raphaelpieroni
+ */
+interface ArchetypeGenerationConfigurator {
+ String ROLE = 'org.apache.maven.archetype.ui.ArchetypeGenerationConfigurator'
+
+ void configureArchetype( request, interactiveMode, executionProperties )
+
+}
+
diff --git a/grarchetype-plugin/src/main/groovy/org/apache/maven/archetype/ui/ArchetypePrompter.groovy b/grarchetype-plugin/src/main/groovy/org/apache/maven/archetype/ui/ArchetypePrompter.groovy
new file mode 100644
index 0000000..660692c
--- /dev/null
+++ b/grarchetype-plugin/src/main/groovy/org/apache/maven/archetype/ui/ArchetypePrompter.groovy
@@ -0,0 +1,135 @@
+package org.apache.maven.archetype.ui
+
+import java.io.IOException
+import java.util.List
+import org.codehaus.plexus.components.interactivity.InputHandler
+import org.codehaus.plexus.components.interactivity.OutputHandler
+import org.codehaus.plexus.components.interactivity.Prompter
+import org.codehaus.plexus.components.interactivity.PrompterException
+import org.codehaus.plexus.util.StringUtils
+
+/**
+ *
+ * @author raphaelpieroni
+ * @plexus.component role-hint="archetype"
+ */
+public class ArchetypePrompter implements Prompter {
+
+ /**
+ * @plexus.requirement
+ */
+ private OutputHandler outputHandler
+
+ /**
+ * @plexus.requirement
+ */
+ private InputHandler inputHandler
+
+ public String prompt( String message )
+ throws PrompterException {
+ try {
+ writePrompt message
+ } catch ( IOException e ) {
+ throw new PrompterException( "Failed to present prompt", e )
+ }
+
+ try {
+ return inputHandler.readLine()
+ } catch ( IOException e ) {
+ throw new PrompterException( "Failed to read user response", e )
+ }
+ }
+
+ public String prompt( String message, String defaultReply )
+ throws PrompterException {
+ try {
+ writePrompt( formatMessage( message, null, defaultReply ) )
+ } catch ( IOException e ) {
+ throw new PrompterException( "Failed to present prompt", e )
+ }
+
+ try {
+ def line = inputHandler.readLine()
+ if ( StringUtils.isEmpty( line ) ) {
+ line = defaultReply
+ }
+
+ return line
+ } catch ( IOException e ) {
+ throw new PrompterException( "Failed to read user response", e )
+ }
+ }
+
+ public String prompt( String message, List possibleValues, String defaultReply )
+ throws PrompterException {
+ String formattedMessage = formatMessage( message, possibleValues, defaultReply )
+
+ String line
+
+ while ( !line || !possibleValues.contains( line ) ) {
+ try {
+ writePrompt formattedMessage
+ } catch ( IOException e ) {
+ throw new PrompterException( "Failed to present prompt", e )
+ }
+
+ try {
+ line = inputHandler.readLine()
+ } catch ( IOException e ) {
+ throw new PrompterException( "Failed to read user response", e )
+ }
+
+ if ( StringUtils.isEmpty( line ) ) {
+ line = defaultReply
+ }
+
+ if ( !line && !possibleValues.contains( line ) ) {
+ try {
+ outputHandler.writeLine "Invalid selection."
+ } catch ( IOException e ) {
+ throw new PrompterException( "Failed to present feedback", e )
+ }
+ }
+ }
+
+ return line
+ }
+
+ public String prompt( String message, List possibleValues )
+ throws PrompterException {
+ return prompt( message, possibleValues, null )
+ }
+
+ public String promptForPassword( String message )
+ throws PrompterException {
+ try {
+ writePrompt message
+ } catch ( IOException e ) {
+ throw new PrompterException( "Failed to present prompt", e )
+ }
+
+ try {
+ return inputHandler.readPassword()
+ } catch ( IOException e ) {
+ throw new PrompterException( "Failed to read user response", e )
+ }
+ }
+
+ private String formatMessage( String message, List possibleValues, String defaultReply ) {
+ "$message${defaultReply?:''}"
+ }
+
+ private void writePrompt( String message )
+ throws IOException {
+ outputHandler.write message + ": "
+ }
+
+ public void showMessage( String message )
+ throws PrompterException {
+ try {
+ writePrompt message
+ } catch ( IOException e ) {
+ throw new PrompterException( "Failed to present prompt", e )
+ }
+ }
+}
diff --git a/grarchetype-plugin/src/main/groovy/org/apache/maven/archetype/ui/ArchetypeSelector.groovy b/grarchetype-plugin/src/main/groovy/org/apache/maven/archetype/ui/ArchetypeSelector.groovy
new file mode 100644
index 0000000..3b2ba35
--- /dev/null
+++ b/grarchetype-plugin/src/main/groovy/org/apache/maven/archetype/ui/ArchetypeSelector.groovy
@@ -0,0 +1,13 @@
+package org.apache.maven.archetype.ui
+import org.apache.maven.archetype.ArchetypeGenerationRequest
+
+/**
+ *
+ * @author raphaelpieroni
+ */
+interface ArchetypeSelector {
+ String ROLE = 'org.apache.maven.archetype.ui.ArchetypeSelector'
+
+ void selectArchetype( ArchetypeGenerationRequest request, Boolean interactiveMode, String catalogs )
+}
+
diff --git a/grarchetype-plugin/src/main/groovy/org/apache/maven/archetype/ui/DefaultArchetypeGenerationConfigurator.groovy b/grarchetype-plugin/src/main/groovy/org/apache/maven/archetype/ui/DefaultArchetypeGenerationConfigurator.groovy
new file mode 100644
index 0000000..fd78773
--- /dev/null
+++ b/grarchetype-plugin/src/main/groovy/org/apache/maven/archetype/ui/DefaultArchetypeGenerationConfigurator.groovy
@@ -0,0 +1,187 @@
+package org.apache.maven.archetype.ui
+import org.codehaus.plexus.logging.AbstractLogEnabled
+import org.apache.maven.archetype.artifact.ArchetypeArtifactManager
+import org.codehaus.plexus.components.interactivity.Prompter
+import org.codehaus.plexus.util.StringUtils
+
+/**
+ *
+ * @author raphaelpieroni
+ * @plexus.component
+ */
+class DefaultArchetypeGenerationConfigurator
+extends AbstractLogEnabled
+implements ArchetypeGenerationConfigurator {
+
+ /** @plexus.requirement */
+ private ArchetypeArtifactManager artifactManager
+
+ /** @plexus.requirement */
+ private Prompter prompter
+
+ void configureArchetype( request, interactiveMode, executionProperties ) {
+ def requiredProperties = loadRequiredProperties( request )
+ applyIncomingProperties requiredProperties, executionProperties
+// applyDefaultValues requiredProperties
+
+ if( !interactiveMode ) {
+ if( !configured( requiredProperties ) ) {
+ describeMissingProperties requiredProperties
+ throw new Exception( "There is some missing properties" )
+ }
+ } else {
+ def confirmed = false
+ while( !confirmed ){
+ if( !configured( requiredProperties ) ) {
+ askForUnconfiguredProperties requiredProperties
+ }
+ if( askForConfirmation( request, requiredProperties ) ) {
+ confirmed = true
+ } else {
+ resetConfiguredValues requiredProperties
+ applyIncomingProperties requiredProperties, executionProperties
+ }
+ }
+ }
+ applyProperties requiredProperties, request
+ }
+ def loadRequiredProperties( request ) {
+ def unsorted = [:]
+ def compareProperty = { left, right ->
+ def leftDefault = unsorted[left]?.defaultValue
+ def rightDefault = unsorted[right]?.defaultValue
+ if( leftDefault?.indexOf( "\${$right}" ) ) return 1
+ if( rightDefault?.indexOf( "\${$left}" ) ) return -1
+ return comparePropertyName( left, right )
+ }
+ def requiredProperties = new TreeMap([compare:compareProperty] as Comparator)
+ def archetypeFileMap = artifactManager.getNestedArchetypeFiles(
+ [groupId:request.groupId, artifactId:request.artifactId, version:request.version],
+ request.localRepository, request.repositories )
+ archetypeFileMap.each { key, archetypeFile ->
+ if( !artifactManager.isLegacyArchetype( archetypeFile ) ) {
+ def descriptor = new XmlSlurper().parse( artifactManager.getFilesetArchetypeDescriptor( archetypeFile ) )
+ descriptor.requiredProperties.requiredProperty.each {
+ def requiredProperty = [name:it.@key.toString(), archetype:key]
+ if( it.defaultValue.text().toString() ) requiredProperty.defaultValue = it.defaultValue.text().toString()
+ if( requiredProperty.defaultValue ) requiredProperty.value = requiredProperty.defaultValue
+ else requiredProperty.defaultValue = null
+ if( it.description.text().toString() ) {
+ requiredProperty.description = it.description.text().toString()
+ } else {
+ requiredProperty.description = requiredProperty.name
+ }
+ unsorted[requiredProperty.name] = requiredProperty
+ requiredProperties[requiredProperty.name] = requiredProperty
+ }
+ }
+ }
+ if( !requiredProperties.containsKey( "groupId" ) ) {
+ def requiredProperty = [name:"groupId", description:"", archetype:request, defaultValue:null]
+ unsorted[requiredProperty.name] = requiredProperty
+ requiredProperties[requiredProperty.name] = requiredProperty
+ }
+ if( !requiredProperties.containsKey( "artfactId" ) ) {
+ def requiredProperty = [name:"artifactId", description:"", archetype:request, defaultValue:null]
+ unsorted[requiredProperty.name] = requiredProperty
+ requiredProperties[requiredProperty.name] = requiredProperty
+ }
+ if( !requiredProperties.containsKey( "version" ) ) {
+ def requiredProperty = [name:"version", description:"", archetype:request, defaultValue:null]
+ unsorted[requiredProperty.name] = requiredProperty
+ requiredProperties[requiredProperty.name] = requiredProperty
+ }
+ if( !requiredProperties.containsKey( "packageName" ) ) { // package if no package name defined
+ def requiredProperty = [name:"packageName", description:"", archetype:request, defaultValue:'${groupId}']
+ unsorted[requiredProperty.name] = requiredProperty
+ requiredProperties[requiredProperty.name] = requiredProperty
+ }
+ if( !requiredProperties.containsKey( "package" ) ) {
+ def requiredProperty = [name:"package", description:"", archetype:request, defaultValue:
+ requiredProperties["packageName"]?.value?:requiredProperties["packageName"]?.defaultValue?:'${groupId}']
+ unsorted[requiredProperty.name] = requiredProperty
+ requiredProperties[requiredProperty.name] = requiredProperty
+ }
+ unsorted["packageName"] = null //package removed in favor of packageName
+ unsorted.remove "packageName" //package removed in favor of packageName
+ requiredProperties["packageName"] = null //package removed in favor of packageName
+ requiredProperties.remove "packageName"//package removed in favor of packageName
+println"DDD ${requiredProperties?.keySet()}"
+ return requiredProperties
+ }
+ def comparePropertyName( left, right ){
+ if( "groupId" == left ) return -1
+ if( "groupId" == right ) return 1
+ if( "artifactId" == left ) return -1
+ if( "artifactId" == right ) return 1
+ if( "version" == left ) return -1
+ if( "version" == right ) return 1
+ if( "package" == left ) return -1
+ if( "package" == right ) return 1
+ return left.compareTo( right )
+ }
+ def applyIncomingProperties( requiredProperties, executionProperties ) {
+ requiredProperties.each { key, property ->
+ if( executionProperties.containsKey( key ) ) {
+ property.value = executionProperties[key]
+ }
+ }
+ }
+ def configured( requiredProperties ) {
+ def configured = true
+ requiredProperties.each { key, property ->
+ if( !property?.value ) configured = false
+ }
+ return configured
+ }
+ def describeMissingProperties( requiredProperties ) {
+ requiredProperties.each { key, property ->
+ if( !property.value ) logger.warn "Property '${key}' is missing. Add -D${key}=someValue"
+ }
+ }
+ def askForUnconfiguredProperties( requiredProperties ) {
+ requiredProperties.each { key, property ->
+ if( !property.value ) {
+ property.value = askForUnconfiguredProperty( key, property.description, getDefaultValue( property.defaultValue, requiredProperties ) )
+ }
+ }
+ }
+ def getDefaultValue( initialDefault, requiredProperties ) {
+ String defaultValue = initialDefault
+ requiredProperties.each { key, property ->
+ defaultValue = StringUtils.replace( defaultValue, '${' + key + '}', property.value )
+ }
+ return defaultValue
+ }
+ def askForUnconfiguredProperty( name, description, defaultValue ) {
+ def query = "Define value for property '$name${description ? '(' + description + ')' : ''}': "
+ if ( defaultValue ) {
+ return prompter.prompt( query, defaultValue )
+ } else {
+ return prompter.prompt( query )
+ }
+ }
+ def askForConfirmation( request, requiredProperties ) {
+ def query = "Confirm properties configuration:\n"
+ requiredProperties.each { key, property ->
+ query += "$key: ${property.value}\n"
+ }
+ return "Y" == prompter.prompt( query, "Y" ).toString().toUpperCase()
+ }
+ def applyDefaultValues( requiredProperties ) {
+//dont reset default!!!
+ }
+ def resetConfiguredValues( requiredProperties ) {
+ requiredProperties.each { key, property ->
+ property.value = null
+ }
+ }
+ def applyProperties( requiredProperties, request ) {
+ def requestProperties = [:]
+ requiredProperties.each { key, property ->
+ if(key == 'package') key = 'packageName'
+ requestProperties[key] = property.value
+ }
+ request.generationFilterProperties = requestProperties as Properties
+ }
+}
diff --git a/grarchetype-plugin/src/main/groovy/org/apache/maven/archetype/ui/DefaultArchetypeSelector.groovy b/grarchetype-plugin/src/main/groovy/org/apache/maven/archetype/ui/DefaultArchetypeSelector.groovy
new file mode 100644
index 0000000..7b4657d
--- /dev/null
+++ b/grarchetype-plugin/src/main/groovy/org/apache/maven/archetype/ui/DefaultArchetypeSelector.groovy
@@ -0,0 +1,146 @@
+package org.apache.maven.archetype.ui
+import org.apache.maven.archetype.ArchetypeGenerationRequest
+import org.apache.maven.archetype.catalog.ArchetypeCataloger
+import org.codehaus.plexus.logging.AbstractLogEnabled
+import org.codehaus.plexus.components.interactivity.Prompter
+import org.apache.maven.artifact.repository.ArtifactRepositoryPolicy
+import org.apache.maven.artifact.repository.ArtifactRepositoryFactory
+import org.apache.maven.artifact.repository.layout.ArtifactRepositoryLayout
+import org.apache.maven.artifact.repository.DefaultArtifactRepository
+import org.apache.maven.archetype.util.RepositoryCreator
+
+/**
+ *
+ * @author raphaelpieroni
+ * @plexus.component
+ */
+class DefaultArchetypeSelector
+extends AbstractLogEnabled
+implements ArchetypeSelector {
+ static DEFAULT_ARCHETYPE = [groupId:"org.apache.maven.archetypes", artifactId:"maven-archetype-quickstart"]
+
+ /** @plexus.requirement */
+ private RepositoryCreator repositoryCreator
+
+ /** @plexus.requirement */
+ private ArchetypeCataloger archetypeCataloger
+
+ /** @plexus.requirement role-hint="archetype" */
+ private Prompter prompter
+
+ void selectArchetype( ArchetypeGenerationRequest request, Boolean interactiveMode, String catalogs ) {
+ def definition = [groupId:request.groupId, artifactId:request.artifactId, version:request.version]
+
+ def archetypeCatalogs = archetypeCataloger.getArchetypesByCatalog( catalogs )
+ def catalogArchetype
+ def repositories = request.repositories.clone()
+
+ if( archetypeDefined( definition ) ) {
+ catalogArchetype = archetypeCataloger.searchArchetype( definition, archetypeCatalogs )
+ if( catalogArchetype ) repositories.add repositoryCreator.createRepository( catalogArchetype.repository )
+ if( archetypeCataloger.archetypeRecursivelyExists( catalogArchetype, archetypeCatalogs, request.localRepository, repositories ) ) {
+ request.repositories = repositories
+ logger.info "Using defined archetype $definition"
+ return
+ } else {
+ logger.error "Defined archetype $definition not found"
+ throw new RuntimeException( "Defined archetype $definition not found" )
+ }
+ } else if( !interactiveMode ) {
+ catalogArchetype = archetypeCataloger.searchArchetype( DEFAULT_ARCHETYPE, archetypeCatalogs )
+ if( catalogArchetype ) repositories.add repositoryCreator.createRepository( catalogArchetype.repository )
+ if( archetypeCataloger.archetypeRecursivelyExists( catalogArchetype, archetypeCatalogs, request.localRepository, request.repositories ) ) {
+ request.repositories = repositories
+ def archetype = archetypeCataloger.searchArchetype( catalogArchetype, archetypeCatalogs )
+ request.groupId = archetype.groupId
+ request.artifactId = archetype.artifactId
+ request.version = archetype.version
+ logger.info "Using default archetype $DEFAULT_ARCHETYPE"
+ return
+ } else {
+ logger.error "Default archetype $DEFAULT_ARCHETYPE not found"
+ throw new RuntimeException( "Default archetype $DEFAULT_ARCHETYPE not found" )
+ }
+ } else {
+ catalogArchetype = askForDefinition( archetypeCatalogs )
+ if( catalogArchetype ) repositories.add repositoryCreator.createRepository( catalogArchetype.repository )
+ if( archetypeCataloger.archetypeRecursivelyExists( catalogArchetype, archetypeCatalogs, request.localRepository, request.repositories ) ) {
+ request.repositories = repositories
+ def archetype = archetypeCataloger.searchArchetype( catalogArchetype, archetypeCatalogs )
+ request.groupId = archetype.groupId
+ request.artifactId = archetype.artifactId
+ request.version = archetype.version
+ logger.info "Using selected archetype $catalogArchetype"
+ return
+ } else {
+ logger.error "Selected archetype $catalogArchetype not found"
+ throw new RuntimeException( "Selected archetype $catalogArchetype not found" )
+ }
+ }
+ }
+
+ def archetypeDefined( definition ) {
+ return definition?.groupId && definition?.artifactId && definition?.version
+ }
+ def askForDefinition( archetypeCatalogs ) {
+ def chooseArchetypeQuery = "Choose archetype:\n"
+ def chooseArchetypeList =[]
+ def archetypeAnswerMap = [:]
+ def archetypeReverseAnswerMap = [:]
+ def archetypeVersions
+ def counter = 1
+ def defaultArchetype = 0
+ archetypeCatalogs.each { key, archetype ->
+ def archetypeKey = "${archetype.groupId}:${archetype.artifactId}".toString()
+ def answerKey = "$counter".toString()
+ if( archetypeReverseAnswerMap.containsKey( archetypeKey ) ) {
+ archetypeVersions = archetypeAnswerMap[ archetypeReverseAnswerMap[archetypeKey] ]
+ } else {
+ archetypeVersions = []
+ archetypeAnswerMap[answerKey] = archetypeVersions
+ chooseArchetypeQuery += "$answerKey:${archetype.catalog} -> ${archetype.artifactId} (${archetype.description})\n"
+ chooseArchetypeList.add answerKey
+ if( archetypeKey == DEFAULT_ARCHETYPE ) {
+ defaultArchetype = answerKey
+ }
+ archetypeReverseAnswerMap[archetypeKey] = answerKey
+ counter ++
+ }
+ archetypeVersions.add archetype
+ }
+ chooseArchetypeQuery += "choose a number: "
+
+ def chooseArchetypeAnswer
+ if( !defaultArchetype ) {
+ chooseArchetypeAnswer = prompter.prompt( chooseArchetypeQuery, chooseArchetypeList )
+ } else {
+ chooseArchetypeAnswer = prompter.prompt( chooseArchetypeQuery, chooseArchetypeList, defaultArchetype )
+ }
+
+ archetypeVersions = archetypeAnswerMap[chooseArchetypeAnswer]
+ if( archetypeVersions.size() == 1 ) {
+ return archetypeVersions[0]
+ } else {
+ return askForVersion( archetypeVersions )
+ }
+ }
+ def askForVersion( archetypes )
+ {
+ def chooseVersionQuery = "Choose version: \n"
+ List chooseVersionList = []
+ def versionAnswerMap = [:]
+
+ def counter = 1
+ archetypes.each { archetype ->
+ def answerKey = "$counter".toString()
+ versionAnswerMap.put answerKey, archetype
+ chooseVersionList.add answerKey
+ chooseVersionQuery += "$counter: ${archetype.version}\n"
+ counter++
+ }
+ chooseVersionQuery += "Choose a number: "
+
+ return versionAnswerMap[prompter.prompt( chooseVersionQuery, chooseVersionList )]
+ }
+}
+
diff --git a/grarchetype-plugin/src/test/archetypes/nested-properties-inner/META-INF/maven/archetype-metadata.xml b/grarchetype-plugin/src/test/archetypes/nested-properties-inner/META-INF/maven/archetype-metadata.xml
new file mode 100644
index 0000000..559226d
--- /dev/null
+++ b/grarchetype-plugin/src/test/archetypes/nested-properties-inner/META-INF/maven/archetype-metadata.xml
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ 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.
+ -->
+<archetype-descriptor name="nested-properties-inner" partial="false" >
+
+ <requiredProperties>
+ <requiredProperty key="innerDefault">
+ <defaultValue>1</defaultValue>
+ <description>1</description>
+ </requiredProperty>
+ <requiredProperty key="innerNoDefault">
+ <description>1</description>
+ </requiredProperty>
+ <requiredProperty key="innerNoNothing"/>
+ </requiredProperties>
+
+ <fileSets/>
+
+ <modules>
+ <module artifactId="${rootArtifactId}-innest" nested="true" archetypeGroupId="archetypes" archetypeArtifactId="nested-properties-innest" archetypeVersion="1.0" />
+ </modules>
+
+</archetype-descriptor>
diff --git a/grarchetype-plugin/src/test/archetypes/nested-properties-innest/META-INF/maven/archetype-metadata.xml b/grarchetype-plugin/src/test/archetypes/nested-properties-innest/META-INF/maven/archetype-metadata.xml
new file mode 100644
index 0000000..e50ac10
--- /dev/null
+++ b/grarchetype-plugin/src/test/archetypes/nested-properties-innest/META-INF/maven/archetype-metadata.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ 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.
+ -->
+<archetype-descriptor name="nested-properties-innest" partial="false" >
+
+ <requiredProperties>
+ <requiredProperty key="innestDefault">
+ <defaultValue>1</defaultValue>
+ <description>1</description>
+ </requiredProperty>
+ <requiredProperty key="innestNoDefault">
+ <description>1</description>
+ </requiredProperty>
+ <requiredProperty key="innestNoNothing"/>
+ </requiredProperties>
+
+ <fileSets/>
+
+ <modules/>
+
+</archetype-descriptor>
diff --git a/grarchetype-plugin/src/test/archetypes/nested-properties-main/META-INF/maven/archetype-metadata.xml b/grarchetype-plugin/src/test/archetypes/nested-properties-main/META-INF/maven/archetype-metadata.xml
new file mode 100644
index 0000000..bab9c5b
--- /dev/null
+++ b/grarchetype-plugin/src/test/archetypes/nested-properties-main/META-INF/maven/archetype-metadata.xml
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ 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.
+ -->
+<archetype-descriptor name="nested-properties-main" partial="false" >
+
+ <requiredProperties>
+ <requiredProperty key="mainDefault">
+ <defaultValue>1</defaultValue>
+ <description>1</description>
+ </requiredProperty>
+ <requiredProperty key="aPropertyWithInner">
+ <defaultValue>${mainNoDefault}</defaultValue>
+ <description>1</description>
+ </requiredProperty>
+ <requiredProperty key="mainNoDefault">
+ <description>1</description>
+ </requiredProperty>
+ <requiredProperty key="mainNoNothing"/>
+ </requiredProperties>
+
+ <fileSets/>
+
+ <modules>
+ <module artifactId="${rootArtifactId}-inner" nested="true" archetypeGroupId="archetypes" archetypeArtifactId="nested-properties-inner" archetypeVersion="1.0" />
+ </modules>
+
+</archetype-descriptor>
diff --git a/grarchetype-plugin/src/test/archetypes/old/META-INF/archetype.xml b/grarchetype-plugin/src/test/archetypes/old/META-INF/archetype.xml
new file mode 100644
index 0000000..d620e84
--- /dev/null
+++ b/grarchetype-plugin/src/test/archetypes/old/META-INF/archetype.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ 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.
+ -->
+<archetype>
+ <id>old</id>
+ <sources>
+ <source>src/main/java/App.java</source>
+ </sources>
+ <resources>
+ <resource>src/main/resources/App.properties</resource>
+ </resources>
+ <siteResources>
+ <resource>src/site/site.xml</resource>
+ </siteResources>
+</archetype>
diff --git a/grarchetype-plugin/src/test/archetypes/old/archetype-resources/pom.xml b/grarchetype-plugin/src/test/archetypes/old/archetype-resources/pom.xml
new file mode 100644
index 0000000..f17b333
--- /dev/null
+++ b/grarchetype-plugin/src/test/archetypes/old/archetype-resources/pom.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ 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.
+ -->
+<project
+ xmlns="http://maven.apache.org/POM/4.0.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+
+ <modelVersion>4.0.0</modelVersion>
+
+ <groupId>${groupId}</groupId>
+ <artifactId>${artifactId}</artifactId>
+ <version>${version}</version>
+
+ <name>Maven archetype Test Old archetype</name>
+ <packaging>jar</packaging>
+
+</project>
\ No newline at end of file
diff --git a/grarchetype-plugin/src/test/archetypes/old/archetype-resources/src/main/java/App.java b/grarchetype-plugin/src/test/archetypes/old/archetype-resources/src/main/java/App.java
new file mode 100644
index 0000000..454754f
--- /dev/null
+++ b/grarchetype-plugin/src/test/archetypes/old/archetype-resources/src/main/java/App.java
@@ -0,0 +1,4 @@
+groupId=${groupId}
+artifactId=${artifactId}
+version=${version}
+package=${packageName}
diff --git a/grarchetype-plugin/src/test/archetypes/old/archetype-resources/src/main/resources/App.properties b/grarchetype-plugin/src/test/archetypes/old/archetype-resources/src/main/resources/App.properties
new file mode 100644
index 0000000..454754f
--- /dev/null
+++ b/grarchetype-plugin/src/test/archetypes/old/archetype-resources/src/main/resources/App.properties
@@ -0,0 +1,4 @@
+groupId=${groupId}
+artifactId=${artifactId}
+version=${version}
+package=${packageName}
diff --git a/grarchetype-plugin/src/test/archetypes/old/archetype-resources/src/site/site.xml b/grarchetype-plugin/src/test/archetypes/old/archetype-resources/src/site/site.xml
new file mode 100644
index 0000000..d0c8d1b
--- /dev/null
+++ b/grarchetype-plugin/src/test/archetypes/old/archetype-resources/src/site/site.xml
@@ -0,0 +1,4 @@
+groupId=${groupId}
+ artifactId=${artifactId}
+ version=${version}
+ package=${packageName}
diff --git a/grarchetype-plugin/src/test/groovy/org/apache/maven/archetype/ui/DefaultArchetypeGenerationConfiguratorTest.groovy b/grarchetype-plugin/src/test/groovy/org/apache/maven/archetype/ui/DefaultArchetypeGenerationConfiguratorTest.groovy
new file mode 100644
index 0000000..72e0853
--- /dev/null
+++ b/grarchetype-plugin/src/test/groovy/org/apache/maven/archetype/ui/DefaultArchetypeGenerationConfiguratorTest.groovy
@@ -0,0 +1,88 @@
+/*
+ * Copyright 2009 raphaelpieroni.
+ *
+ * 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.
+ * under the License.
+ */
+
+package org.apache.maven.archetype.ui
+import org.apache.maven.plugin.testing.AbstractMojoTestCase
+import org.codehaus.cargo.container.jetty.Jetty6xEmbeddedLocalContainer
+import org.codehaus.cargo.container.jetty.Jetty6xEmbeddedStandaloneLocalConfiguration
+import org.codehaus.cargo.generic.deployable.DefaultDeployableFactory
+import org.codehaus.cargo.container.jetty.Jetty6xEmbeddedLocalDeployer
+import org.codehaus.cargo.container.deployer.URLDeployableMonitor
+import org.codehaus.cargo.container.property.ServletPropertySet
+import org.codehaus.cargo.container.deployable.DeployableType
+import org.apache.maven.artifact.repository.ArtifactRepository
+import org.apache.maven.archetype.util.RepositoryCreator
+
+/**
+ *
+ * @author raphaelpieroni
+ */
+class DefaultArchetypeGenerationConfiguratorTest extends AbstractMojoTestCase {
+ def generator
+ def repositoryCreator
+ Jetty6xEmbeddedLocalContainer jettyContainer
+
+ void setUp() {
+ super.setUp()
+ generator = lookup( ArchetypeGenerationConfigurator.ROLE )
+ repositoryCreator = lookup( RepositoryCreator.ROLE )
+
+ // Start Cargo
+
+ def configuration =
+ new Jetty6xEmbeddedStandaloneLocalConfiguration( "target/repository-webapp" )
+ configuration.setProperty ServletPropertySet.PORT, "18881"
+
+ System.setProperty "org.apache.maven.archetype.reporitory.directory",
+ getTestPath( "target/repositories/" )
+ jettyContainer = new Jetty6xEmbeddedLocalContainer( configuration )
+ jettyContainer.timeout = 180000L
+ jettyContainer.start()
+
+ def factory = new DefaultDeployableFactory()
+ def war = factory.createDeployable( jettyContainer.id,
+ "target/wars/grarchetype-repository.war",
+ DeployableType.WAR )
+
+ war.context = "/"
+
+ def deployer = new Jetty6xEmbeddedLocalDeployer( jettyContainer )
+ deployer.deploy war,
+ new URLDeployableMonitor( new URL( "http://localhost:18881/central/archetype-catalog.xml" ) )
+ deployer.start war
+ }
+ void tearDown() {
+ super.tearDown()
+ // Stop Cargo
+ jettyContainer.stop()
+ }
+
+ void test_loadRequiredProperties(){
+ println'archetypeDefined'
+
+ println"REPO=${getBasedir()}/target/repositories/local"
+ def localRepository = repositoryCreator.createRepository( "file://${getBasedir()}/target/repositories/local".toString() )
+ def centralRepository = repositoryCreator.createRepository( "http://localhost:18881/central" )
+
+ def properties = generator.loadRequiredProperties(
+ [groupId:'archetypes', artifactId:'nested-properties-main', version:'1.0', localRepository:localRepository, repositories:[centralRepository]])
+ assertEquals 14, properties.size()
+
+ }
+
+}
+
diff --git a/grarchetype-plugin/src/test/groovy/org/apache/maven/archetype/ui/DefaultArchetypeSelectorTest.groovy b/grarchetype-plugin/src/test/groovy/org/apache/maven/archetype/ui/DefaultArchetypeSelectorTest.groovy
new file mode 100644
index 0000000..b6b991d
--- /dev/null
+++ b/grarchetype-plugin/src/test/groovy/org/apache/maven/archetype/ui/DefaultArchetypeSelectorTest.groovy
@@ -0,0 +1,38 @@
+package org.apache.maven.archetype.ui
+import org.junit.Test
+import static org.junit.Assert.*
+import org.codehaus.plexus.PlexusTestCase
+import org.apache.maven.plugin.testing.AbstractMojoTestCase
+
+/**
+ *
+ * @author raphaelpieroni
+ */
+class DefaultArchetypeSelectorTest extends AbstractMojoTestCase {
+ def selector
+
+ void setUp() {
+ super.setUp()
+ selector = lookup( ArchetypeSelector.ROLE )
+ }
+ void tearDown() {
+ super.tearDown()
+ }
+
+
+ @Test void test_archetypeDefined() {
+ println'archetypeDefined'
+
+ assertFalse selector.archetypeDefined([])
+ assertFalse selector.archetypeDefined([groupId:null, artifactId:null, version:null])
+ assertFalse selector.archetypeDefined([groupId:"archetypes", artifactId:null, version:null])
+ assertFalse selector.archetypeDefined([groupId:null, artifactId:"archetype", version:null])
+ assertFalse selector.archetypeDefined([groupId:null, artifactId:null, version:"1.0"])
+ assertFalse selector.archetypeDefined([groupId:"archetypes", artifactId:"archetype", version:null])
+ assertFalse selector.archetypeDefined([groupId:null, artifactId:"archetype", version:"1.0"])
+ assertFalse selector.archetypeDefined([groupId:"archetypes", artifactId:null, version:"1.0"])
+ assertTrue selector.archetypeDefined([groupId:"archetypes", artifactId:"archetype", version:"1.0"])
+ }
+
+}
+
diff --git a/grarchetype-plugin/src/test/repositories/central/archetype-catalog.xml b/grarchetype-plugin/src/test/repositories/central/archetype-catalog.xml
new file mode 100644
index 0000000..6ade27d
--- /dev/null
+++ b/grarchetype-plugin/src/test/repositories/central/archetype-catalog.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<archetype-catalog>
+ <archetypes>
+ <archetype>
+ <groupId>archetypes</groupId>
+ <artifactId>nested-properties-main</artifactId>
+ <version>1.0</version>
+ </archetype>
+ <archetype>
+ <groupId>archetypes</groupId>
+ <artifactId>nested-properties-inner</artifactId>
+ <version>1.0</version>
+ </archetype>
+ <archetype>
+ <groupId>archetypes</groupId>
+ <artifactId>nested-properties-innest</artifactId>
+ <version>1.0</version>
+ </archetype>
+ </archetypes>
+</archetype-catalog>
\ No newline at end of file
diff --git a/grarchetype-plugin/src/test/repositories/local/dummy b/grarchetype-plugin/src/test/repositories/local/dummy
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/grarchetype-plugin/src/test/repositories/local/dummy
diff --git a/grarchetype-testing/grarchetype-repository/pom.xml b/grarchetype-testing/grarchetype-repository/pom.xml
new file mode 100644
index 0000000..77deeb4
--- /dev/null
+++ b/grarchetype-testing/grarchetype-repository/pom.xml
@@ -0,0 +1,72 @@
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <artifactId>grarchetype-testing</artifactId>
+ <groupId>org.apache.maven.grarchetype</groupId>
+ <version>2.0-alpha-5-SNAPSHOT</version>
+ </parent>
+
+ <artifactId>grarchetype-repository</artifactId>
+
+ <name>Maven GrArchetype Webapp Repository</name>
+ <packaging>war</packaging>
+
+ <dependencies>
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>javax.servlet</groupId>
+ <artifactId>servlet-api</artifactId>
+ <version>2.4</version>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.mortbay.jetty</groupId>
+ <artifactId>jetty-util</artifactId>
+ <version>6.1.11</version>
+ <scope>compile</scope>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <!-- Add this in settings to use No authentication is made
+ <proxies>
+ <proxy>
+ <active>true</active>
+ <id>jetty</id>
+ <host>localhost</host>
+ <port>8080</port>
+ <protocol>http</protocol>
+ </proxy>
+ </proxies>
+ -->
+ <groupId>org.mortbay.jetty</groupId>
+ <artifactId>maven-jetty-plugin</artifactId>
+ <configuration>
+ <connectors>
+ <connector implementation="org.mortbay.jetty.nio.SelectChannelConnector">
+ <port>18882</port>
+ <maxIdleTime>60000</maxIdleTime>
+ </connector>
+ </connectors>
+ <webAppConfig>
+ <contextPath>/</contextPath>
+ </webAppConfig>
+ <systemProperties>
+ <systemProperty>
+ <name>org.apache.maven.archetype.reporitory.directory</name>
+ <value>${project.basedir}/target/repository</value>
+ </systemProperty>
+ </systemProperties>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+</project>
\ No newline at end of file
diff --git a/grarchetype-testing/grarchetype-repository/src/main/java/org/apache/maven/archetype/repository/RepositoryServlet.java b/grarchetype-testing/grarchetype-repository/src/main/java/org/apache/maven/archetype/repository/RepositoryServlet.java
new file mode 100644
index 0000000..f588d7e
--- /dev/null
+++ b/grarchetype-testing/grarchetype-repository/src/main/java/org/apache/maven/archetype/repository/RepositoryServlet.java
@@ -0,0 +1,257 @@
+/*
+ * Copyright 2007 rafale.
+ *
+ * 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.
+ * under the License.
+ */
+package org.apache.maven.archetype.repository;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import javax.servlet.ServletConfig;
+import javax.servlet.ServletContext;
+import javax.servlet.ServletException;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import org.mortbay.util.IO;
+import org.mortbay.util.StringUtil;
+
+/**
+ *
+ * @author rafale
+ */
+public class RepositoryServlet
+ extends HttpServlet
+{
+ private ServletConfig config;
+
+ private ServletContext context;
+
+ /* (non-Javadoc)
+ * @see javax.servlet.Servlet#init(javax.servlet.ServletConfig)
+ */
+ public void init( ServletConfig config ) throws ServletException
+ {
+ this.config = config;
+ this.context = config.getServletContext( );
+ }
+
+ /* (non-Javadoc)
+ * @see javax.servlet.Servlet#getServletConfig()
+ */
+ public ServletConfig getServletConfig( )
+ {
+ return config;
+ }
+
+ /* (non-Javadoc)
+ * @see javax.servlet.Servlet#service(javax.servlet.ServletRequest, javax.servlet.ServletResponse)
+ */
+ public void service( ServletRequest req, ServletResponse res ) throws ServletException
+ {
+ HttpServletRequest request = (HttpServletRequest) req;
+ HttpServletResponse response = (HttpServletResponse) res;
+
+ response.setHeader( "Date", null );
+ response.setHeader( "Server", null );
+
+
+ log( "Requested file = " + request.getRequestURI( ) );
+ System.err.println( "Requested file = " + request.getRequestURI( ) );
+ String filePath =
+ System.getProperty( "org.apache.maven.archetype.reporitory.directory" ).trim( ) + "/" +
+ request.getRequestURI( );
+ filePath = StringUtil.replace(filePath, "\\", File.separator);
+ filePath = StringUtil.replace(filePath, File.separator, "/");
+ filePath=filePath.replaceAll("/repo/", "/");
+ filePath=filePath.replaceAll("//", "/");
+ filePath=filePath.replaceAll("//", "/");
+ filePath=filePath.replaceAll("//", "/");
+ filePath = StringUtil.replace(filePath, "/", File.separator);
+ log( "Complete file path = " + filePath );
+ System.err.println( "Complete file path = " + filePath );
+
+ String method = request.getMethod( );
+
+ if ( "GET".equalsIgnoreCase( method ) )
+ {
+ log( "Getting file" );
+ System.err.println( "Getting file" );
+ try
+ {
+ File requestedFile = new File( filePath );
+
+ InputStream is = new FileInputStream( requestedFile );
+
+ if ( is != null )
+ {
+ IO.copy( is, response.getOutputStream( ) );
+ response.setStatus( HttpServletResponse.SC_OK );
+ log( "File sent" );
+ System.err.println( "File sent" );
+ }
+ else
+ {
+ log( "Can not send file no content" );
+ System.err.println( "Can not send file no content" );
+ }
+ }
+ catch ( FileNotFoundException fileNotFoundException )
+ {
+ response.setStatus( HttpServletResponse.SC_NOT_FOUND );
+ log( "Requested file not found ", fileNotFoundException );
+ System.err.println( "Requested file not found "+ fileNotFoundException );
+ fileNotFoundException.printStackTrace(System.err);
+ }
+ catch ( IOException iOException )
+ {
+ response.setStatus( HttpServletResponse.SC_INTERNAL_SERVER_ERROR );
+ log( "Can not send file", iOException );
+ System.err.println( "Can not send file"+ iOException );
+ iOException.printStackTrace(System.err);
+ }
+ }
+ else if ( "PUT".equalsIgnoreCase( method ) )
+ {
+ log( "Putting file" );
+ System.err.println( "Putting file" );
+ File uploadedFile = new File( filePath );
+ if ( uploadedFile.exists( ) )
+ {
+ uploadedFile.delete( );
+ log( "Removed old file" );
+ System.err.println( "Removed old file" );
+ }
+ else if ( !uploadedFile.getParentFile( ).exists( ) )
+ {
+ uploadedFile.getParentFile( ).mkdirs( );
+ log( "Created directory " + uploadedFile.getParent( ) );
+ System.err.println( "Created directory " + uploadedFile.getParent( ) );
+ }
+
+ try
+ {
+ FileWriter fw = new FileWriter( uploadedFile );
+ IO.copy( request.getReader( ), fw );
+ response.setStatus( HttpServletResponse.SC_OK );
+ log( "File copied" );
+ System.err.println( "File copied" );
+ }
+ catch ( IOException iOException )
+ {
+
+ response.setStatus( HttpServletResponse.SC_INTERNAL_SERVER_ERROR );
+ log( "Can not send file", iOException );
+ System.err.println( "Can not send file"+ iOException );
+ iOException.printStackTrace(System.err);
+ }
+ }
+ else
+ {
+ response.setStatus( HttpServletResponse.SC_INTERNAL_SERVER_ERROR );
+ try
+ {
+ log( "Method " + request.getMethod( ) );
+ log( "ContextPath " + request.getContextPath( ) );
+ log( "QueryString" + request.getQueryString( ) );
+ log( "PathInfo " + request.getPathInfo( ) );
+ log( "ServletPath " + request.getServletPath( ) );
+ log( "AttributeNames " + request.getAttributeNames( ).toString( ) );
+ log( "HeaderNames " + request.getHeaderNames( ).toString( ) );
+ log( "RequestURL " + request.getRequestURL( ).toString( ) );
+ log( "ParameterNames " + request.getParameterNames( ).toString( ) );
+ StringWriter w = new StringWriter( );
+ IO.copy( request.getReader( ), w );
+ log( "Content " + w.toString( ) );
+
+
+// System.err.println( "Method " + request.getMethod( ) );
+// System.err.println( "ContextPath " + request.getContextPath( ) );
+// System.err.println( "QueryString" + request.getQueryString( ) );
+// System.err.println( "PathInfo " + request.getPathInfo( ) );
+// System.err.println( "ServletPath " + request.getServletPath( ) );
+// System.err.println( "AttributeNames " + request.getAttributeNames( ).toString( ) );
+// System.err.println( "HeaderNames " + request.getHeaderNames( ).toString( ) );
+// System.err.println( "RequestURL " + request.getRequestURL( ).toString( ) );
+// System.err.println( "ParameterNames " + request.getParameterNames( ).toString( ) );
+// System.err.println( "Content " + w.toString( ) );
+ }
+ catch ( IOException iOException )
+ {
+ log( "Error in unnknown method", iOException );
+ System.err.println( "Error in unnknown method"+ iOException );
+ iOException.printStackTrace(System.err);
+ }
+ }
+ }
+
+ /* (non-Javadoc)
+ * @see javax.servlet.Servlet#getServletInfo()
+ */
+ public String getServletInfo( )
+ {
+ return "Repository Servlet";
+ }
+
+ /* (non-Javadoc)
+ * @see javax.servlet.Servlet#destroy()
+ */
+ public void destroy( )
+ {
+ }
+
+ /**
+ * Processes requests for both HTTP <code>GET</code> and <code>POST</code> methods.
+ * @param request servlet request
+ * @param response servlet response
+ */
+ protected void processRequest( HttpServletRequest request,
+ HttpServletResponse response ) throws ServletException, IOException
+ {
+ response.setContentType( "text/html;charset=UTF-8" );
+ PrintWriter out = response.getWriter( );
+ try
+ {
+ /* TODO output your page here
+ out.println("<html>");
+ out.println("<head>");
+ out.println("<title>Servlet RepositoryServlet</title>");
+ out.println("</head>");
+ out.println("<body>");
+ out.println("<h1>Servlet RepositoryServlet at " + request.getContextPath () + "</h1>");
+ out.println("</body>");
+ out.println("</html>");
+ */
+ }
+ finally
+ {
+ out.close( );
+ }
+ }
+
+ public String getServletName()
+ {
+ return "Repository Servlet";
+ }
+
+
+}
\ No newline at end of file
diff --git a/grarchetype-testing/grarchetype-repository/src/main/webapp/WEB-INF/web.xml b/grarchetype-testing/grarchetype-repository/src/main/webapp/WEB-INF/web.xml
new file mode 100644
index 0000000..ca53ef8
--- /dev/null
+++ b/grarchetype-testing/grarchetype-repository/src/main/webapp/WEB-INF/web.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<web-app version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
+ <display-name>Archetype Repository Web Application</display-name>
+ <servlet>
+ <servlet-name>RepositoryServlet</servlet-name>
+ <servlet-class>org.apache.maven.archetype.repository.RepositoryServlet</servlet-class>
+ </servlet>
+ <servlet-mapping>
+ <servlet-name>RepositoryServlet</servlet-name>
+ <url-pattern>/*</url-pattern>
+ </servlet-mapping>
+</web-app>
diff --git a/grarchetype-testing/pom.xml b/grarchetype-testing/pom.xml
new file mode 100644
index 0000000..86a2d6a
--- /dev/null
+++ b/grarchetype-testing/pom.xml
@@ -0,0 +1,21 @@
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.apache.maven.grarchetype</groupId>
+ <artifactId>maven-grarchetype</artifactId>
+ <version>2.0-alpha-5-SNAPSHOT</version>
+ </parent>
+
+ <artifactId>grarchetype-testing</artifactId>
+
+ <packaging>pom</packaging>
+ <name>Maven GrArchetype Testing </name>
+
+ <modules>
+ <!--module>grarchetype-proxy</module-->
+ <module>grarchetype-repository</module>
+ </modules>
+
+</project>
\ No newline at end of file
diff --git a/pom.xml b/pom.xml
new file mode 100644
index 0000000..de7e97f
--- /dev/null
+++ b/pom.xml
@@ -0,0 +1,257 @@
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.apache.maven</groupId>
+ <artifactId>maven-parent</artifactId>
+ <version>9</version>
+ <relativePath>../pom/maven/pom.xml</relativePath>
+ </parent>
+
+ <groupId>org.apache.maven.grarchetype</groupId>
+ <artifactId>maven-grarchetype</artifactId>
+ <version>2.0-alpha-5-SNAPSHOT</version>
+
+ <name>Maven GrArchetype</name>
+ <packaging>pom</packaging>
+
+ <modules>
+ <module>grarchetype-testing</module>
+ <module>grarchetype-common</module>
+ <module>grarchetype-plugin</module>
+ <!--module>grarchetype-packaging</module-->
+ </modules>
+
+ <properties>
+ <netbeans.hint.useExternalMaven>true</netbeans.hint.useExternalMaven>
+ </properties>
+
+ <licenses>
+ <license>
+ <name>The Apache Software License, Version 2.0</name>
+ <url>http://www.apache.org/licenses/LICENSE-2.0.txt</url>
+ <distribution>repo</distribution>
+ </license>
+ </licenses>
+ <issueManagement>
+ <system>jira</system>
+ <url>http://jira.codehaus.org/browse/ARCHETYPE</url>
+ </issueManagement>
+ <inceptionYear>2008</inceptionYear>
+
+ <dependencyManagement>
+ <dependencies>
+ <dependency>
+ <groupId>org.apache.maven.grarchetype</groupId>
+ <artifactId>grarchetype-common</artifactId>
+ <version>2.0-alpha-5-SNAPSHOT</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.maven</groupId>
+ <artifactId>maven-plugin-api</artifactId>
+ <version>${mavenVersion}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.maven</groupId>
+ <artifactId>maven-model</artifactId>
+ <version>${mavenVersion}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.velocity</groupId>
+ <artifactId>velocity</artifactId>
+ <version>1.6.1</version>
+ </dependency>
+ <!--dependency>
+ <groupId>org.apache.maven.shared</groupId>
+ <artifactId>maven-invoker</artifactId>
+ <version>2.0.10</version>
+ </dependency>
+ <dependency>
+ <groupId>org.codehaus.plexus</groupId>
+ <artifactId>plexus-utils</artifactId>
+ <version>1.5.6</version>
+ </dependency>
+ <dependency>
+ <groupId>org.codehaus.plexus</groupId>
+ <artifactId>plexus-interactivity-api</artifactId>
+ <version>1.0-alpha-5</version>
+ </dependency>
+ <dependency>
+ <groupId>org.codehaus.plexus</groupId>
+ <artifactId>plexus-velocity</artifactId>
+ <version>1.1.3</version><!- with 1.1.4 1.1.5 1.1.6 1.1.7 tests fail ->
+ <exclusions>
+ <exclusion>
+ <groupId>velocity</groupId>
+ <artifactId>velocity</artifactId>
+ </exclusion>
+ <exclusion>
+ <groupId>velocity</groupId>
+ <artifactId>velocity-api</artifactId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+ <dependency>
+ <groupId>commons-io</groupId>
+ <artifactId>commons-io</artifactId>
+ <version>1.4</version>
+ </dependency>
+ <dependency>
+ <groupId>commons-collections</groupId>
+ <artifactId>commons-collections</artifactId>
+ <version>3.2.1</version>
+ </dependency-->
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <version>4.5</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.maven.shared</groupId>
+ <artifactId>maven-plugin-testing-harness</artifactId>
+ <version>1.1</version>
+ <scope>test</scope>
+ </dependency>
+ <!--dependency>
+ <groupId>org.apache.maven.wagon</groupId>
+ <artifactId>wagon-file</artifactId>
+ <version>1.0-beta-2</version><!- with 1.0-beta-3 1.0-beta-4 all tests fail ->
+ <scope>test</scope>
+ </dependency-->
+ </dependencies>
+ </dependencyManagement>
+
+ <profiles>
+ <profile>
+ <id>maven2.0</id>
+ <activation>
+ <activeByDefault>true</activeByDefault>
+ </activation>
+ <properties>
+ <mavenVersion>2.0.10</mavenVersion>
+ </properties>
+ <dependencyManagement>
+ <dependencies>
+ <dependency>
+ <groupId>org.apache.maven</groupId>
+ <artifactId>maven-project</artifactId>
+ <version>${mavenVersion}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.maven</groupId>
+ <artifactId>maven-core</artifactId>
+ <version>${mavenVersion}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.codehaus.plexus</groupId>
+ <artifactId>plexus-container-default</artifactId>
+ <version>1.0-alpha-9-stable-1</version>
+ </dependency>
+ </dependencies>
+ </dependencyManagement>
+ </profile>
+ </profiles>
+
+ <scm>
+ <connection>scm:svn:http://svn.apache.org/repos/asf/maven/grarchetype/trunk</connection>
+ <developerConnection>scm:svn:https://svn.apache.org/repos/asf/maven/grarchetype/trunk</developerConnection>
+ <url>http://svn.apache.org/viewcvs.cgi/maven/grarchetype/trunk</url>
+ </scm>
+
+ <build>
+ <pluginManagement>
+ <plugins>
+ <plugin>
+ <artifactId>maven-release-plugin</artifactId>
+ <configuration>
+ <tagBase>https://svn.apache.org/repos/asf/maven/archetype/tags</tagBase>
+ <preparationGoals>clean install</preparationGoals>
+ </configuration>
+ </plugin>
+ <plugin>
+ <artifactId>maven-surefire-plugin</artifactId>
+ <version>2.4.3</version>
+ </plugin>
+ <plugin>
+ <artifactId>maven-clean-plugin</artifactId>
+ <version>2.3</version>
+ </plugin>
+ <plugin>
+ <artifactId>maven-gpg-plugin</artifactId>
+ <version>1.0-alpha-4</version>
+ </plugin>
+ <plugin>
+ <artifactId>maven-javadoc-plugin</artifactId>
+ <version>2.5</version>
+ </plugin>
+ <plugin>
+ <artifactId>maven-deploy-plugin</artifactId>
+ <version>2.4</version>
+ </plugin>
+ <plugin>
+ <artifactId>maven-compiler-plugin</artifactId>
+ <version>2.0.2</version>
+ </plugin>
+ <plugin>
+ <artifactId>maven-install-plugin</artifactId>
+ <version>2.2</version>
+ </plugin>
+ <plugin>
+ <artifactId>maven-site-plugin</artifactId>
+ <version>2.0-beta-7</version>
+ </plugin>
+ <plugin>
+ <artifactId>maven-source-plugin</artifactId>
+ <version>2.0.4</version>
+ </plugin>
+ <plugin>
+ <artifactId>maven-resources-plugin</artifactId>
+ <version>2.3</version>
+ </plugin>
+ <plugin>
+ <artifactId>maven-antrun-plugin</artifactId>
+ <version>1.3</version>
+ </plugin>
+ <plugin>
+ <artifactId>maven-dependency-plugin</artifactId>
+ <version>2.1</version>
+ </plugin>
+ <plugin>
+ <artifactId>maven-plugin-plugin</artifactId>
+ <version>2.4.3</version>
+ </plugin>
+ <plugin>
+ <artifactId>maven-war-plugin</artifactId>
+ <version>2.1-alpha-2</version>
+ </plugin>
+ <plugin>
+ <groupId>org.mortbay.jetty</groupId>
+ <artifactId>maven-jetty-plugin</artifactId>
+ <version>6.1.9</version>
+ </plugin>
+ </plugins>
+ </pluginManagement>
+ <plugins>
+ <plugin>
+ <artifactId>maven-compiler-plugin</artifactId>
+ <configuration>
+ <source>1.5</source>
+ <target>1.5</target>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.codehaus.plexus</groupId>
+ <artifactId>plexus-maven-plugin</artifactId>
+ <version>1.3.8</version>
+ <executions>
+ <execution>
+ <goals>
+ <goal>descriptor</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </build>
+</project>