aboutsummaryrefslogtreecommitdiffstats
path: root/archiva-common/src/main
diff options
context:
space:
mode:
authorJoakim Erdfelt <joakime@apache.org>2007-02-23 19:05:21 +0000
committerJoakim Erdfelt <joakime@apache.org>2007-02-23 19:05:21 +0000
commitdee0d5a300ee0ba0240efc1277428b52cdcec9e0 (patch)
tree0f4c8d3b8b8b0468deac3c8851380a68bfa1744e /archiva-common/src/main
parent2b50a18d22ef8972d241f54c20a131e05a584ac4 (diff)
downloadarchiva-dee0d5a300ee0ba0240efc1277428b52cdcec9e0.tar.gz
archiva-dee0d5a300ee0ba0240efc1277428b52cdcec9e0.zip
Merge from archiva-MRM-239 branch to trunk. r506385:HEAD
git-svn-id: https://svn.apache.org/repos/asf/maven/archiva/trunk@511053 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'archiva-common/src/main')
-rw-r--r--archiva-common/src/main/java/org/apache/maven/archiva/common/ArchivaException.java40
-rw-r--r--archiva-common/src/main/java/org/apache/maven/archiva/common/artifact/builder/AbstractLayoutArtifactBuilder.java55
-rw-r--r--archiva-common/src/main/java/org/apache/maven/archiva/common/artifact/builder/BuilderException.java43
-rw-r--r--archiva-common/src/main/java/org/apache/maven/archiva/common/artifact/builder/DefaultLayoutArtifactBuilder.java218
-rw-r--r--archiva-common/src/main/java/org/apache/maven/archiva/common/artifact/builder/LayoutArtifactBuilder.java36
-rw-r--r--archiva-common/src/main/java/org/apache/maven/archiva/common/artifact/builder/LegacyLayoutArtifactBuilder.java303
-rw-r--r--archiva-common/src/main/java/org/apache/maven/archiva/common/artifact/managed/ManagedArtifact.java76
-rw-r--r--archiva-common/src/main/java/org/apache/maven/archiva/common/artifact/managed/ManagedArtifactTypes.java81
-rw-r--r--archiva-common/src/main/java/org/apache/maven/archiva/common/artifact/managed/ManagedEjbArtifact.java49
-rw-r--r--archiva-common/src/main/java/org/apache/maven/archiva/common/artifact/managed/ManagedJavaArtifact.java62
-rw-r--r--archiva-common/src/main/java/org/apache/maven/archiva/common/consumers/AbstractConsumer.java66
-rw-r--r--archiva-common/src/main/java/org/apache/maven/archiva/common/consumers/Consumer.java90
-rw-r--r--archiva-common/src/main/java/org/apache/maven/archiva/common/consumers/ConsumerException.java52
-rw-r--r--archiva-common/src/main/java/org/apache/maven/archiva/common/consumers/ConsumerFactory.java70
-rw-r--r--archiva-common/src/main/java/org/apache/maven/archiva/common/consumers/GenericArtifactConsumer.java130
-rw-r--r--archiva-common/src/main/java/org/apache/maven/archiva/common/consumers/GenericModelConsumer.java98
-rw-r--r--archiva-common/src/main/java/org/apache/maven/archiva/common/consumers/GenericRepositoryMetadataConsumer.java231
-rw-r--r--archiva-common/src/main/java/org/apache/maven/archiva/common/utils/BaseFile.java105
-rw-r--r--archiva-common/src/main/java/org/apache/maven/archiva/common/utils/PathUtil.java56
19 files changed, 1861 insertions, 0 deletions
diff --git a/archiva-common/src/main/java/org/apache/maven/archiva/common/ArchivaException.java b/archiva-common/src/main/java/org/apache/maven/archiva/common/ArchivaException.java
new file mode 100644
index 000000000..c807d70c4
--- /dev/null
+++ b/archiva-common/src/main/java/org/apache/maven/archiva/common/ArchivaException.java
@@ -0,0 +1,40 @@
+package org.apache.maven.archiva.common;
+
+/*
+ * 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.
+ */
+
+/**
+ * ArchivaException
+ *
+ * @author <a href="mailto:joakim@erdfelt.com">Joakim Erdfelt</a>
+ * @version $Id$
+ */
+public class ArchivaException
+ extends Exception
+{
+ public ArchivaException( String message, Throwable cause )
+ {
+ super( message, cause );
+ }
+
+ public ArchivaException( String message )
+ {
+ super( message );
+ }
+}
diff --git a/archiva-common/src/main/java/org/apache/maven/archiva/common/artifact/builder/AbstractLayoutArtifactBuilder.java b/archiva-common/src/main/java/org/apache/maven/archiva/common/artifact/builder/AbstractLayoutArtifactBuilder.java
new file mode 100644
index 000000000..b77826ad1
--- /dev/null
+++ b/archiva-common/src/main/java/org/apache/maven/archiva/common/artifact/builder/AbstractLayoutArtifactBuilder.java
@@ -0,0 +1,55 @@
+package org.apache.maven.archiva.common.artifact.builder;
+
+/*
+ * 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.
+ */
+
+import org.apache.maven.artifact.factory.ArtifactFactory;
+
+/**
+ * AbstractLayoutArtifactBuilder
+ *
+ * @author <a href="mailto:joakime@apache.org">Joakim Erdfelt</a>
+ * @version $Id$
+ */
+public abstract class AbstractLayoutArtifactBuilder
+ implements LayoutArtifactBuilder
+{
+ /**
+ * @plexus.requirement
+ */
+ protected ArtifactFactory artifactFactory;
+
+ /**
+ * Constructor used by plexus
+ */
+ public AbstractLayoutArtifactBuilder()
+ {
+
+ }
+
+ /**
+ * Constructor used by manual process.
+ *
+ * @param artifactFactory the artifact factory to use.
+ */
+ public AbstractLayoutArtifactBuilder( ArtifactFactory artifactFactory )
+ {
+ this.artifactFactory = artifactFactory;
+ }
+}
diff --git a/archiva-common/src/main/java/org/apache/maven/archiva/common/artifact/builder/BuilderException.java b/archiva-common/src/main/java/org/apache/maven/archiva/common/artifact/builder/BuilderException.java
new file mode 100644
index 000000000..0845dc750
--- /dev/null
+++ b/archiva-common/src/main/java/org/apache/maven/archiva/common/artifact/builder/BuilderException.java
@@ -0,0 +1,43 @@
+package org.apache.maven.archiva.common.artifact.builder;
+
+/*
+ * 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.
+ */
+
+import org.apache.maven.archiva.common.ArchivaException;
+
+/**
+ * BuilderException - used to indicate a problem during the building of an object from file.
+ *
+ * @author <a href="mailto:joakime@apache.org">Joakim Erdfelt</a>
+ * @version $Id$
+ */
+public class BuilderException
+ extends ArchivaException
+{
+
+ public BuilderException( String message, Throwable cause )
+ {
+ super( message, cause );
+ }
+
+ public BuilderException( String message )
+ {
+ super( message );
+ }
+}
diff --git a/archiva-common/src/main/java/org/apache/maven/archiva/common/artifact/builder/DefaultLayoutArtifactBuilder.java b/archiva-common/src/main/java/org/apache/maven/archiva/common/artifact/builder/DefaultLayoutArtifactBuilder.java
new file mode 100644
index 000000000..bfee01508
--- /dev/null
+++ b/archiva-common/src/main/java/org/apache/maven/archiva/common/artifact/builder/DefaultLayoutArtifactBuilder.java
@@ -0,0 +1,218 @@
+package org.apache.maven.archiva.common.artifact.builder;
+
+/*
+ * 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.
+ */
+
+import org.apache.maven.artifact.Artifact;
+import org.apache.maven.artifact.factory.ArtifactFactory;
+import org.codehaus.plexus.util.StringUtils;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.StringTokenizer;
+
+/**
+ * DefaultLayoutArtifactBuilder - artifact builder for default layout repositories.
+ *
+ * @author <a href="mailto:brett@apache.org">Brett Porter</a>
+ * @author <a href="mailto:joakime@apache.org">Joakim Erdfelt</a>
+ * @version $Id$
+ *
+ * @plexus.component role="org.apache.maven.archiva.common.artifact.builder.LayoutArtifactBuilder"
+ * role-hint="default"
+ */
+public class DefaultLayoutArtifactBuilder
+ extends AbstractLayoutArtifactBuilder
+ implements LayoutArtifactBuilder
+{
+ public DefaultLayoutArtifactBuilder()
+ {
+ super();
+ }
+
+ public DefaultLayoutArtifactBuilder( ArtifactFactory artifactFactory )
+ {
+ super( artifactFactory );
+ }
+
+ public Artifact build( String pathToArtifact )
+ throws BuilderException
+ {
+ if( artifactFactory == null )
+ {
+ throw new IllegalStateException( "Unable to build artifact with a null artifactFactory." );
+ }
+
+ List pathParts = new ArrayList();
+ StringTokenizer st = new StringTokenizer( pathToArtifact, "/\\" );
+ while ( st.hasMoreTokens() )
+ {
+ pathParts.add( st.nextToken() );
+ }
+
+ Collections.reverse( pathParts );
+
+ Artifact artifact;
+ if ( pathParts.size() >= 4 )
+ {
+ // maven 2.x path
+
+ // the actual artifact filename.
+ String filename = (String) pathParts.remove( 0 );
+
+ // the next one is the version.
+ String version = (String) pathParts.remove( 0 );
+
+ // the next one is the artifactId.
+ String artifactId = (String) pathParts.remove( 0 );
+
+ // the remaining are the groupId.
+ Collections.reverse( pathParts );
+ String groupId = StringUtils.join( pathParts.iterator(), "." );
+
+ String remainingFilename = filename;
+ if ( remainingFilename.startsWith( artifactId + "-" ) )
+ {
+ remainingFilename = remainingFilename.substring( artifactId.length() + 1 );
+
+ String classifier = null;
+
+ // TODO: use artifact handler, share with legacy discoverer
+ String type;
+ if ( remainingFilename.endsWith( ".tar.gz" ) )
+ {
+ type = "distribution-tgz";
+ remainingFilename = remainingFilename
+ .substring( 0, remainingFilename.length() - ".tar.gz".length() );
+ }
+ else if ( remainingFilename.endsWith( ".zip" ) )
+ {
+ type = "distribution-zip";
+ remainingFilename = remainingFilename.substring( 0, remainingFilename.length() - ".zip".length() );
+ }
+ else if ( remainingFilename.endsWith( "-test-sources.jar" ) )
+ {
+ type = "java-source";
+ classifier = "test-sources";
+ remainingFilename = remainingFilename.substring( 0, remainingFilename.length()
+ - "-test-sources.jar".length() );
+ }
+ else if ( remainingFilename.endsWith( "-sources.jar" ) )
+ {
+ type = "java-source";
+ classifier = "sources";
+ remainingFilename = remainingFilename.substring( 0, remainingFilename.length()
+ - "-sources.jar".length() );
+ }
+ else
+ {
+ int index = remainingFilename.lastIndexOf( "." );
+ if ( index >= 0 )
+ {
+ type = remainingFilename.substring( index + 1 );
+ remainingFilename = remainingFilename.substring( 0, index );
+ }
+ else
+ {
+ throw new BuilderException( "Path filename does not have an extension." );
+ }
+ }
+
+ Artifact result;
+ if ( classifier == null )
+ {
+ result = artifactFactory
+ .createArtifact( groupId, artifactId, version, Artifact.SCOPE_RUNTIME, type );
+ }
+ else
+ {
+ result = artifactFactory.createArtifactWithClassifier( groupId, artifactId, version, type,
+ classifier );
+ }
+
+ if ( result.isSnapshot() )
+ {
+ // version is *-SNAPSHOT, filename is *-yyyyMMdd.hhmmss-b
+ int classifierIndex = remainingFilename.indexOf( '-', version.length() + 8 );
+ if ( classifierIndex >= 0 )
+ {
+ classifier = remainingFilename.substring( classifierIndex + 1 );
+ remainingFilename = remainingFilename.substring( 0, classifierIndex );
+ result = artifactFactory.createArtifactWithClassifier( groupId, artifactId, remainingFilename,
+ type, classifier );
+ }
+ else
+ {
+ result = artifactFactory.createArtifact( groupId, artifactId, remainingFilename,
+ Artifact.SCOPE_RUNTIME, type );
+ }
+
+ // poor encapsulation requires we do this to populate base version
+ if ( !result.isSnapshot() )
+ {
+ throw new BuilderException( "Failed to create a snapshot artifact: " + result );
+ }
+ else if ( !result.getBaseVersion().equals( version ) )
+ {
+ throw new BuilderException(
+ "Built snapshot artifact base version does not match path version: "
+ + result.getBaseVersion() + "; should have been version: "
+ + version );
+ }
+ else
+ {
+ artifact = result;
+ }
+ }
+ else if ( !remainingFilename.startsWith( version ) )
+ {
+ throw new BuilderException( "Built artifact version does not match path version" );
+ }
+ else if ( !remainingFilename.equals( version ) )
+ {
+ if ( remainingFilename.charAt( version.length() ) == '-' )
+ {
+ classifier = remainingFilename.substring( version.length() + 1 );
+ artifact = artifactFactory.createArtifactWithClassifier( groupId, artifactId, version, type,
+ classifier );
+ }
+ else
+ {
+ throw new BuilderException( "Path version does not corresspond to an artifact version" );
+ }
+ }
+ else
+ {
+ artifact = result;
+ }
+ }
+ else
+ {
+ throw new BuilderException( "Path filename does not correspond to an artifact." );
+ }
+ }
+ else
+ {
+ throw new BuilderException( "Path is too short to build an artifact from." );
+ }
+
+ return artifact;
+ }
+}
diff --git a/archiva-common/src/main/java/org/apache/maven/archiva/common/artifact/builder/LayoutArtifactBuilder.java b/archiva-common/src/main/java/org/apache/maven/archiva/common/artifact/builder/LayoutArtifactBuilder.java
new file mode 100644
index 000000000..494a4a7c1
--- /dev/null
+++ b/archiva-common/src/main/java/org/apache/maven/archiva/common/artifact/builder/LayoutArtifactBuilder.java
@@ -0,0 +1,36 @@
+package org.apache.maven.archiva.common.artifact.builder;
+
+/*
+ * 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.
+ */
+
+import org.apache.maven.artifact.Artifact;
+import org.apache.maven.artifact.repository.layout.ArtifactRepositoryLayout;
+
+/**
+ * LayoutArtifactBuilder
+ *
+ * @author <a href="mailto:joakime@apache.org">Joakim Erdfelt</a>
+ * @version $Id$
+ *
+ * @todo this concept should really exist inside of the {@link ArtifactRepositoryLayout} object in maven itself.
+ */
+public interface LayoutArtifactBuilder
+{
+ public Artifact build( String pathToArtifact ) throws BuilderException;
+}
diff --git a/archiva-common/src/main/java/org/apache/maven/archiva/common/artifact/builder/LegacyLayoutArtifactBuilder.java b/archiva-common/src/main/java/org/apache/maven/archiva/common/artifact/builder/LegacyLayoutArtifactBuilder.java
new file mode 100644
index 000000000..e3436e966
--- /dev/null
+++ b/archiva-common/src/main/java/org/apache/maven/archiva/common/artifact/builder/LegacyLayoutArtifactBuilder.java
@@ -0,0 +1,303 @@
+package org.apache.maven.archiva.common.artifact.builder;
+
+/*
+ * 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.
+ */
+
+import org.apache.maven.artifact.Artifact;
+import org.apache.maven.artifact.factory.ArtifactFactory;
+
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.StringTokenizer;
+
+/**
+ * LegacyLayoutArtifactBuilder
+ *
+ * @author <a href="mailto:joakime@apache.org">Joakim Erdfelt</a>
+ * @version $Id$
+ *
+ * @plexus.component role="org.apache.maven.archiva.common.artifact.builder.LayoutArtifactBuilder"
+ * role-hint="legacy"
+ */
+public class LegacyLayoutArtifactBuilder
+ extends AbstractLayoutArtifactBuilder
+ implements LayoutArtifactBuilder
+{
+ public LegacyLayoutArtifactBuilder()
+ {
+ super();
+ }
+
+ public LegacyLayoutArtifactBuilder( ArtifactFactory artifactFactory )
+ {
+ super( artifactFactory );
+ }
+
+ public Artifact build( String pathToArtifact )
+ throws BuilderException
+ {
+ if( artifactFactory == null )
+ {
+ throw new IllegalStateException( "Unable to build legacy artifact with a null artifactFactory." );
+ }
+
+ StringTokenizer tokens = new StringTokenizer( pathToArtifact, "/\\" );
+
+ Artifact result;
+
+ int numberOfTokens = tokens.countTokens();
+
+ if ( numberOfTokens == 3 )
+ {
+ String groupId = tokens.nextToken();
+
+ String type = tokens.nextToken();
+
+ if ( type.endsWith( "s" ) )
+ {
+ type = type.substring( 0, type.length() - 1 );
+
+ // contains artifactId, version, classifier, and extension.
+ String avceGlob = tokens.nextToken();
+
+ //noinspection CollectionDeclaredAsConcreteClass
+ LinkedList avceTokenList = new LinkedList();
+
+ StringTokenizer avceTokenizer = new StringTokenizer( avceGlob, "-" );
+ while ( avceTokenizer.hasMoreTokens() )
+ {
+ avceTokenList.addLast( avceTokenizer.nextToken() );
+ }
+
+ String lastAvceToken = (String) avceTokenList.removeLast();
+
+ // TODO: share with other discoverer, use artifact handlers instead
+ if ( lastAvceToken.endsWith( ".tar.gz" ) )
+ {
+ type = "distribution-tgz";
+
+ lastAvceToken = lastAvceToken.substring( 0, lastAvceToken.length() - ".tar.gz".length() );
+
+ avceTokenList.addLast( lastAvceToken );
+ }
+ else if ( lastAvceToken.endsWith( "sources.jar" ) )
+ {
+ type = "java-source";
+
+ lastAvceToken = lastAvceToken.substring( 0, lastAvceToken.length() - ".jar".length() );
+
+ avceTokenList.addLast( lastAvceToken );
+ }
+ else if ( lastAvceToken.endsWith( "javadoc.jar" ) )
+ {
+ type = "javadoc.jar";
+
+ lastAvceToken = lastAvceToken.substring( 0, lastAvceToken.length() - ".jar".length() );
+
+ avceTokenList.addLast( lastAvceToken );
+ }
+ else if ( lastAvceToken.endsWith( ".zip" ) )
+ {
+ type = "distribution-zip";
+
+ lastAvceToken = lastAvceToken.substring( 0, lastAvceToken.length() - ".zip".length() );
+
+ avceTokenList.addLast( lastAvceToken );
+ }
+ else
+ {
+ int extPos = lastAvceToken.lastIndexOf( '.' );
+
+ if ( extPos > 0 )
+ {
+ String ext = lastAvceToken.substring( extPos + 1 );
+ if ( type.equals( ext ) || "plugin".equals( type ) )
+ {
+ lastAvceToken = lastAvceToken.substring( 0, extPos );
+
+ avceTokenList.addLast( lastAvceToken );
+ }
+ else
+ {
+ throw new BuilderException( "Path type does not match the extension" );
+ }
+ }
+ else
+ {
+ throw new BuilderException( "Path filename does not have an extension" );
+ }
+ }
+
+ // let's discover the version, and whatever's leftover will be either
+ // a classifier, or part of the artifactId, depending on position.
+ // Since version is at the end, we have to move in from the back.
+ Collections.reverse( avceTokenList );
+
+ // TODO: this is obscene - surely a better way?
+ String validVersionParts = "([Dd][Ee][Vv][_.0-9]*)|" + "([Ss][Nn][Aa][Pp][Ss][Hh][Oo][Tt])|"
+ + "([0-9][_.0-9a-zA-Z]*)|" + "([Gg]?[_.0-9ab]*([Pp][Rr][Ee]|[Rr][Cc]|[Gg]|[Mm])[_.0-9]*)|"
+ + "([Aa][Ll][Pp][Hh][Aa][_.0-9]*)|" + "([Bb][Ee][Tt][Aa][_.0-9]*)|" + "([Rr][Cc][_.0-9]*)|"
+ + "([Tt][Ee][Ss][Tt][_.0-9]*)|" + "([Dd][Ee][Bb][Uu][Gg][_.0-9]*)|"
+ + "([Uu][Nn][Oo][Ff][Ff][Ii][Cc][Ii][Aa][Ll][_.0-9]*)|" + "([Cc][Uu][Rr][Rr][Ee][Nn][Tt])|"
+ + "([Ll][Aa][Tt][Ee][Ss][Tt])|" + "([Ff][Cc][Ss])|" + "([Rr][Ee][Ll][Ee][Aa][Ss][Ee][_.0-9]*)|"
+ + "([Nn][Ii][Gg][Hh][Tt][Ll][Yy])|" + "[Ff][Ii][Nn][Aa][Ll]|" + "([AaBb][_.0-9]*)";
+
+ StringBuffer classifierBuffer = new StringBuffer();
+ StringBuffer versionBuffer = new StringBuffer();
+
+ boolean firstVersionTokenEncountered = false;
+ boolean firstToken = true;
+
+ int tokensIterated = 0;
+ for ( Iterator it = avceTokenList.iterator(); it.hasNext(); )
+ {
+ String token = (String) it.next();
+
+ boolean tokenIsVersionPart = token.matches( validVersionParts );
+
+ StringBuffer bufferToUpdate;
+
+ // NOTE: logic in code is reversed, since we're peeling off the back
+ // Any token after the last versionPart will be in the classifier.
+ // Any token UP TO first non-versionPart is part of the version.
+ if ( !tokenIsVersionPart )
+ {
+ if ( firstVersionTokenEncountered )
+ {
+ //noinspection BreakStatement
+ break;
+ }
+ else
+ {
+ bufferToUpdate = classifierBuffer;
+ }
+ }
+ else
+ {
+ firstVersionTokenEncountered = true;
+
+ bufferToUpdate = versionBuffer;
+ }
+
+ if ( firstToken )
+ {
+ firstToken = false;
+ }
+ else
+ {
+ bufferToUpdate.insert( 0, '-' );
+ }
+
+ bufferToUpdate.insert( 0, token );
+
+ tokensIterated++;
+ }
+
+ // Now, restore the proper ordering so we can build the artifactId.
+ Collections.reverse( avceTokenList );
+
+ // if we didn't find a version, then punt. Use the last token
+ // as the version, and set the classifier empty.
+ if ( versionBuffer.length() < 1 )
+ {
+ if ( avceTokenList.size() > 1 )
+ {
+ int lastIdx = avceTokenList.size() - 1;
+
+ versionBuffer.append( avceTokenList.get( lastIdx ) );
+ avceTokenList.remove( lastIdx );
+ }
+
+ classifierBuffer.setLength( 0 );
+ }
+ else
+ {
+ // if everything is kosher, then pop off all the classifier and
+ // version tokens, leaving the naked artifact id in the list.
+ avceTokenList = new LinkedList( avceTokenList.subList( 0, avceTokenList.size() - tokensIterated ) );
+ }
+
+ StringBuffer artifactIdBuffer = new StringBuffer();
+
+ firstToken = true;
+ for ( Iterator it = avceTokenList.iterator(); it.hasNext(); )
+ {
+ String token = (String) it.next();
+
+ if ( firstToken )
+ {
+ firstToken = false;
+ }
+ else
+ {
+ artifactIdBuffer.append( '-' );
+ }
+
+ artifactIdBuffer.append( token );
+ }
+
+ String artifactId = artifactIdBuffer.toString();
+
+ if ( artifactId.length() > 0 )
+ {
+ int lastVersionCharIdx = versionBuffer.length() - 1;
+ if ( lastVersionCharIdx > -1 && versionBuffer.charAt( lastVersionCharIdx ) == '-' )
+ {
+ versionBuffer.setLength( lastVersionCharIdx );
+ }
+
+ String version = versionBuffer.toString();
+
+ if ( version.length() > 0 )
+ {
+ if ( classifierBuffer.length() > 0 )
+ {
+ result = artifactFactory.createArtifactWithClassifier( groupId, artifactId, version, type,
+ classifierBuffer.toString() );
+ }
+ else
+ {
+ result = artifactFactory.createArtifact( groupId, artifactId, version,
+ Artifact.SCOPE_RUNTIME, type );
+ }
+ }
+ else
+ {
+ throw new BuilderException( "Path filename version is empty" );
+ }
+ }
+ else
+ {
+ throw new BuilderException( "Path filename artifactId is empty" );
+ }
+ }
+ else
+ {
+ throw new BuilderException( "Path artifact type does not corresspond to an artifact type" );
+ }
+ }
+ else
+ {
+ throw new BuilderException( "Path does not match a legacy repository path for an artifact" );
+ }
+
+ return result;
+ }
+}
diff --git a/archiva-common/src/main/java/org/apache/maven/archiva/common/artifact/managed/ManagedArtifact.java b/archiva-common/src/main/java/org/apache/maven/archiva/common/artifact/managed/ManagedArtifact.java
new file mode 100644
index 000000000..8e3c67838
--- /dev/null
+++ b/archiva-common/src/main/java/org/apache/maven/archiva/common/artifact/managed/ManagedArtifact.java
@@ -0,0 +1,76 @@
+package org.apache.maven.archiva.common.artifact.managed;
+
+/*
+ * 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.
+ */
+
+import org.apache.maven.artifact.Artifact;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * ManagedArtifact
+ *
+ * @author <a href="mailto:joakime@apache.org">Joakim Erdfelt</a>
+ * @version $Id$
+ */
+public class ManagedArtifact
+{
+ private String repositoryId;
+
+ private Artifact artifact;
+
+ private String path;
+
+ protected Map attached;
+
+ public ManagedArtifact( String repoId, Artifact artifact, String path )
+ {
+ super();
+ this.repositoryId = repoId;
+ this.artifact = artifact;
+ this.path = path;
+ this.attached = new HashMap();
+ }
+
+ public Artifact getArtifact()
+ {
+ return artifact;
+ }
+
+ public String getPath()
+ {
+ return path;
+ }
+
+ public String getRepositoryId()
+ {
+ return repositoryId;
+ }
+
+ public Map getAttached()
+ {
+ return attached;
+ }
+
+ public void setAttached( Map attached )
+ {
+ this.attached = attached;
+ }
+}
diff --git a/archiva-common/src/main/java/org/apache/maven/archiva/common/artifact/managed/ManagedArtifactTypes.java b/archiva-common/src/main/java/org/apache/maven/archiva/common/artifact/managed/ManagedArtifactTypes.java
new file mode 100644
index 000000000..b653d160a
--- /dev/null
+++ b/archiva-common/src/main/java/org/apache/maven/archiva/common/artifact/managed/ManagedArtifactTypes.java
@@ -0,0 +1,81 @@
+package org.apache.maven.archiva.common.artifact.managed;
+
+/*
+ * 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.
+ */
+
+import org.apache.commons.lang.StringUtils;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * ManagedArtifactTypes - provides place to test an unknown artifact type.
+ *
+ * @author <a href="mailto:joakime@apache.org">Joakim Erdfelt</a>
+ * @version $Id$
+ */
+public class ManagedArtifactTypes
+{
+ public static final int GENERIC = 0;
+
+ public static final int JAVA = 1;
+
+ public static final int EJB = 2;
+
+ private static List javaArtifacts;
+
+ private static List ejbArtifacts;
+
+ static
+ {
+ javaArtifacts = new ArrayList();
+ javaArtifacts.add( "jar" );
+ javaArtifacts.add( "war" );
+ javaArtifacts.add( "sar" );
+ javaArtifacts.add( "rar" );
+ javaArtifacts.add( "ear" );
+
+ ejbArtifacts = new ArrayList();
+ ejbArtifacts.add( "ejb" );
+ ejbArtifacts.add( "ejb-client" );
+ }
+
+ public static int whichType( String type )
+ {
+ if ( StringUtils.isBlank( type ) )
+ {
+ // TODO: is an empty type even possible?
+ return GENERIC;
+ }
+
+ type = type.toLowerCase();
+
+ if ( ejbArtifacts.contains( type ) )
+ {
+ return EJB;
+ }
+
+ if ( javaArtifacts.contains( type ) )
+ {
+ return JAVA;
+ }
+
+ return GENERIC;
+ }
+}
diff --git a/archiva-common/src/main/java/org/apache/maven/archiva/common/artifact/managed/ManagedEjbArtifact.java b/archiva-common/src/main/java/org/apache/maven/archiva/common/artifact/managed/ManagedEjbArtifact.java
new file mode 100644
index 000000000..1759df2db
--- /dev/null
+++ b/archiva-common/src/main/java/org/apache/maven/archiva/common/artifact/managed/ManagedEjbArtifact.java
@@ -0,0 +1,49 @@
+package org.apache.maven.archiva.common.artifact.managed;
+
+/*
+ * 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.
+ */
+
+import org.apache.maven.artifact.Artifact;
+
+/**
+ * ManagedEjbArtifact - adds the ability to reference the ejb-client jar too.
+ *
+ * @author <a href="mailto:joakime@apache.org">Joakim Erdfelt</a>
+ * @version $Id$
+ */
+public class ManagedEjbArtifact
+ extends ManagedJavaArtifact
+{
+ public static final String CLIENT = "client";
+
+ public ManagedEjbArtifact( String repoId, Artifact artifact, String path )
+ {
+ super( repoId, artifact, path );
+ }
+
+ public String getClientPath()
+ {
+ return (String) super.attached.get( CLIENT );
+ }
+
+ public void setClientPath( String clientPath )
+ {
+ super.attached.put( CLIENT, clientPath );
+ }
+}
diff --git a/archiva-common/src/main/java/org/apache/maven/archiva/common/artifact/managed/ManagedJavaArtifact.java b/archiva-common/src/main/java/org/apache/maven/archiva/common/artifact/managed/ManagedJavaArtifact.java
new file mode 100644
index 000000000..203234b06
--- /dev/null
+++ b/archiva-common/src/main/java/org/apache/maven/archiva/common/artifact/managed/ManagedJavaArtifact.java
@@ -0,0 +1,62 @@
+package org.apache.maven.archiva.common.artifact.managed;
+
+/*
+ * 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.
+ */
+
+import org.apache.maven.artifact.Artifact;
+
+/**
+ * ManagedJavaArtifact - a ManagedArtifact with optional javadoc and source
+ * reference jars.
+ *
+ * @author <a href="mailto:joakime@apache.org">Joakim Erdfelt</a>
+ * @version $Id$
+ */
+public class ManagedJavaArtifact
+ extends ManagedArtifact
+{
+ public static final String JAVADOC = "javadoc";
+
+ public static final String SOURCES = "sources";
+
+ public ManagedJavaArtifact( String repoId, Artifact artifact, String path )
+ {
+ super( repoId, artifact, path );
+ }
+
+ public String getJavadocPath()
+ {
+ return (String) super.attached.get( JAVADOC );
+ }
+
+ public void setJavadocPath( String javadocPath )
+ {
+ super.attached.put( JAVADOC, javadocPath );
+ }
+
+ public String getSourcesPath()
+ {
+ return (String) super.attached.get( SOURCES );
+ }
+
+ public void setSourcesPath( String sourcesPath )
+ {
+ super.attached.put( SOURCES, sourcesPath );
+ }
+}
diff --git a/archiva-common/src/main/java/org/apache/maven/archiva/common/consumers/AbstractConsumer.java b/archiva-common/src/main/java/org/apache/maven/archiva/common/consumers/AbstractConsumer.java
new file mode 100644
index 000000000..603434630
--- /dev/null
+++ b/archiva-common/src/main/java/org/apache/maven/archiva/common/consumers/AbstractConsumer.java
@@ -0,0 +1,66 @@
+package org.apache.maven.archiva.common.consumers;
+
+/*
+ * 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.
+ */
+
+import org.apache.maven.artifact.factory.ArtifactFactory;
+import org.apache.maven.artifact.repository.ArtifactRepository;
+import org.codehaus.plexus.logging.AbstractLogEnabled;
+
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * AbstractDiscovererConsumer
+ *
+ * @author <a href="mailto:joakime@apache.org">Joakim Erdfelt</a>
+ * @version $Id$
+ */
+public abstract class AbstractConsumer
+ extends AbstractLogEnabled
+ implements Consumer
+{
+ /**
+ * @plexus.requirement
+ */
+ protected ArtifactFactory artifactFactory;
+
+ protected ArtifactRepository repository;
+
+ protected AbstractConsumer()
+ {
+ /* do nothing */
+ }
+
+ public List getExcludePatterns()
+ {
+ return Collections.EMPTY_LIST;
+ }
+
+ public boolean init( ArtifactRepository repository )
+ {
+ this.repository = repository;
+ return isEnabled();
+ }
+
+ protected boolean isEnabled()
+ {
+ return true;
+ }
+}
diff --git a/archiva-common/src/main/java/org/apache/maven/archiva/common/consumers/Consumer.java b/archiva-common/src/main/java/org/apache/maven/archiva/common/consumers/Consumer.java
new file mode 100644
index 000000000..fad6f2fa8
--- /dev/null
+++ b/archiva-common/src/main/java/org/apache/maven/archiva/common/consumers/Consumer.java
@@ -0,0 +1,90 @@
+package org.apache.maven.archiva.common.consumers;
+
+/*
+ * 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.
+ */
+
+import org.apache.maven.archiva.common.utils.BaseFile;
+import org.apache.maven.artifact.repository.ArtifactRepository;
+
+import java.util.List;
+
+/**
+ * DiscovererConsumer
+ *
+ * @author <a href="mailto:joakime@apache.org">Joakim Erdfelt</a>
+ * @version $Id$
+ */
+public interface Consumer
+{
+ public static final String ROLE = Consumer.class.getName();
+
+ /**
+ * This is the human readable name for the discoverer.
+ *
+ * @return the human readable discoverer name.
+ */
+ public String getName();
+
+ /**
+ * This is used to initialize any internals in the consumer before it is used.
+ *
+ * This method is called by the internals of archiva and is not meant to be used by other developers.
+ * This method is called once per repository.
+ *
+ * @param repository the repository to initialize the consumer against.
+ * @return true if the repository is valid for this consumer. false will result in consumer being disabled
+ * for the provided repository.
+ */
+ public boolean init( ArtifactRepository repository );
+
+ /**
+ * Get the List of excluded file patterns for this consumer.
+ *
+ * @return the list of excluded file patterns for this consumer.
+ */
+ public List getExcludePatterns();
+
+ /**
+ * Get the List of included file patterns for this consumer.
+ *
+ * @return the list of included file patterns for this consumer.
+ */
+ public List getIncludePatterns();
+
+ /**
+ * Called by archiva framework to indicate that there is a file suitable for consuming,
+ * This method will only be called if the {@link #init(ArtifactRepository)} and {@link #getExcludePatterns()}
+ * and {@link #getIncludePatterns()} all pass for this consumer.
+ *
+ * @param file the file to process.
+ * @throws ConsumerException if there was a problem processing this file.
+ */
+ public void processFile( BaseFile file ) throws ConsumerException;
+
+ /**
+ * Called by archiva framework to indicate that there has been a problem detected
+ * on a specific file.
+ *
+ * NOTE: It is very possible for 1 file to have more than 1 problem associated with it.
+ *
+ * @param file the file to process.
+ * @param message the message describing the problem.
+ */
+ public void processFileProblem( BaseFile file, String message );
+}
diff --git a/archiva-common/src/main/java/org/apache/maven/archiva/common/consumers/ConsumerException.java b/archiva-common/src/main/java/org/apache/maven/archiva/common/consumers/ConsumerException.java
new file mode 100644
index 000000000..0c4c6451a
--- /dev/null
+++ b/archiva-common/src/main/java/org/apache/maven/archiva/common/consumers/ConsumerException.java
@@ -0,0 +1,52 @@
+package org.apache.maven.archiva.common.consumers;
+
+/*
+ * 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.
+ */
+
+import org.apache.maven.archiva.common.ArchivaException;
+import org.apache.maven.archiva.common.utils.BaseFile;
+
+/**
+ * ConsumerException - details about the failure of a consumer.
+ *
+ * @author <a href="mailto:joakim@erdfelt.com">Joakim Erdfelt</a>
+ * @version $Id$
+ */
+public class ConsumerException
+ extends ArchivaException
+{
+ private BaseFile file;
+
+ public ConsumerException( BaseFile file, String message, Throwable cause )
+ {
+ super( message, cause );
+ this.file = file;
+ }
+
+ public ConsumerException( BaseFile file, String message )
+ {
+ super( message );
+ this.file = file;
+ }
+
+ public BaseFile getFile()
+ {
+ return file;
+ }
+}
diff --git a/archiva-common/src/main/java/org/apache/maven/archiva/common/consumers/ConsumerFactory.java b/archiva-common/src/main/java/org/apache/maven/archiva/common/consumers/ConsumerFactory.java
new file mode 100644
index 000000000..2b2343c0f
--- /dev/null
+++ b/archiva-common/src/main/java/org/apache/maven/archiva/common/consumers/ConsumerFactory.java
@@ -0,0 +1,70 @@
+package org.apache.maven.archiva.common.consumers;
+
+/*
+ * 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.
+ */
+
+import org.codehaus.plexus.PlexusConstants;
+import org.codehaus.plexus.PlexusContainer;
+import org.codehaus.plexus.context.Context;
+import org.codehaus.plexus.context.ContextException;
+import org.codehaus.plexus.logging.AbstractLogEnabled;
+import org.codehaus.plexus.personality.plexus.lifecycle.phase.Contextualizable;
+
+/**
+ * DiscovererConsumerFactory - factory for consumers.
+ *
+ * @author <a href="mailto:joakim@erdfelt.com">Joakim Erdfelt</a>
+ * @version $Id$
+ * @plexus.component role="org.apache.maven.archiva.common.consumers.ConsumerFactory"
+ */
+public class ConsumerFactory
+ extends AbstractLogEnabled
+ implements Contextualizable
+{
+ public static final String ROLE = ConsumerFactory.class.getName();
+
+ private PlexusContainer container;
+
+ public Consumer createConsumer( String name )
+ throws ConsumerException
+ {
+ getLogger().info( "Attempting to create consumer [" + name + "]" );
+
+ Consumer consumer;
+ try
+ {
+ consumer = (Consumer) container.lookup( Consumer.ROLE, container.getLookupRealm() );
+ }
+ catch ( Throwable t )
+ {
+ String emsg = "Unable to create consumer [" + name + "]: " + t.getMessage();
+ getLogger().warn( t.getMessage(), t );
+ throw new ConsumerException( null, emsg, t );
+ }
+
+ getLogger().info( "Created consumer [" + name + "|" + consumer.getName() + "]" );
+ return consumer;
+ }
+
+ public void contextualize( Context context )
+ throws ContextException
+ {
+ container = (PlexusContainer) context.get( PlexusConstants.PLEXUS_KEY );
+ }
+}
diff --git a/archiva-common/src/main/java/org/apache/maven/archiva/common/consumers/GenericArtifactConsumer.java b/archiva-common/src/main/java/org/apache/maven/archiva/common/consumers/GenericArtifactConsumer.java
new file mode 100644
index 000000000..c9e5437b7
--- /dev/null
+++ b/archiva-common/src/main/java/org/apache/maven/archiva/common/consumers/GenericArtifactConsumer.java
@@ -0,0 +1,130 @@
+package org.apache.maven.archiva.common.consumers;
+
+/*
+ * 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.
+ */
+
+import org.apache.maven.archiva.common.artifact.builder.BuilderException;
+import org.apache.maven.archiva.common.artifact.builder.DefaultLayoutArtifactBuilder;
+import org.apache.maven.archiva.common.artifact.builder.LayoutArtifactBuilder;
+import org.apache.maven.archiva.common.artifact.builder.LegacyLayoutArtifactBuilder;
+import org.apache.maven.archiva.common.utils.BaseFile;
+import org.apache.maven.artifact.Artifact;
+import org.apache.maven.artifact.repository.ArtifactRepository;
+import org.apache.maven.artifact.repository.layout.ArtifactRepositoryLayout;
+import org.apache.maven.artifact.repository.layout.DefaultRepositoryLayout;
+import org.apache.maven.artifact.repository.layout.LegacyRepositoryLayout;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * DefaultArtifactConsumer
+ *
+ * @author <a href="mailto:joakime@apache.org">Joakim Erdfelt</a>
+ * @version $Id$
+ */
+public abstract class GenericArtifactConsumer
+ extends AbstractConsumer
+ implements Consumer
+{
+ public abstract void processArtifact( Artifact artifact, BaseFile file );
+
+ private Map artifactBuilders = new HashMap();
+
+ private static final List includePatterns;
+
+ static
+ {
+ includePatterns = new ArrayList();
+ includePatterns.add( "**/*.pom" );
+ includePatterns.add( "**/*.jar" );
+ includePatterns.add( "**/*.war" );
+ includePatterns.add( "**/*.ear" );
+ includePatterns.add( "**/*.sar" );
+ includePatterns.add( "**/*.zip" );
+ includePatterns.add( "**/*.gz" );
+ includePatterns.add( "**/*.bz2" );
+ }
+
+ private String layoutId = "default";
+
+ public boolean init( ArtifactRepository repository )
+ {
+ this.artifactBuilders.clear();
+ this.artifactBuilders.put( "default", new DefaultLayoutArtifactBuilder( artifactFactory ) );
+ this.artifactBuilders.put( "legacy", new LegacyLayoutArtifactBuilder( artifactFactory ) );
+
+ if ( repository.getLayout() instanceof LegacyRepositoryLayout )
+ {
+ this.layoutId = "legacy";
+ }
+
+ return super.init( repository );
+ }
+
+ public List getIncludePatterns()
+ {
+ return includePatterns;
+ }
+
+ public boolean isEnabled()
+ {
+ ArtifactRepositoryLayout layout = repository.getLayout();
+ return ( layout instanceof DefaultRepositoryLayout ) || ( layout instanceof LegacyRepositoryLayout );
+ }
+
+ public void processFile( BaseFile file )
+ throws ConsumerException
+ {
+ if ( file.length() <= 0 )
+ {
+ processFileProblem( file, "File is empty." );
+ }
+
+ if ( !file.canRead() )
+ {
+ processFileProblem( file, "Not allowed to read file due to permission settings on file." );
+ }
+
+ try
+ {
+ Artifact artifact = buildArtifact( file );
+
+ processArtifact( artifact, file );
+ }
+ catch ( BuilderException e )
+ {
+ throw new ConsumerException( file, e.getMessage(), e );
+ }
+ }
+
+ private Artifact buildArtifact( BaseFile file )
+ throws BuilderException
+ {
+ LayoutArtifactBuilder builder = (LayoutArtifactBuilder) artifactBuilders.get( layoutId );
+
+ Artifact artifact = builder.build( file.getRelativePath() );
+ artifact.setRepository( repository );
+ artifact.setFile( file );
+
+ return artifact;
+ }
+}
diff --git a/archiva-common/src/main/java/org/apache/maven/archiva/common/consumers/GenericModelConsumer.java b/archiva-common/src/main/java/org/apache/maven/archiva/common/consumers/GenericModelConsumer.java
new file mode 100644
index 000000000..efcd7af64
--- /dev/null
+++ b/archiva-common/src/main/java/org/apache/maven/archiva/common/consumers/GenericModelConsumer.java
@@ -0,0 +1,98 @@
+package org.apache.maven.archiva.common.consumers;
+
+/*
+ * 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.
+ */
+
+import org.apache.maven.archiva.common.utils.BaseFile;
+import org.apache.maven.model.Model;
+import org.apache.maven.model.io.xpp3.MavenXpp3Reader;
+import org.codehaus.plexus.util.IOUtil;
+import org.codehaus.plexus.util.xml.pull.XmlPullParserException;
+
+import java.io.FileReader;
+import java.io.IOException;
+import java.io.Reader;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * GenericModelConsumer - consumer for pom files.
+ *
+ * @author <a href="mailto:joakime@apache.org">Joakim Erdfelt</a>
+ * @version $Id$
+ */
+public abstract class GenericModelConsumer
+ extends AbstractConsumer
+ implements Consumer
+{
+ public abstract void processModel( Model model, BaseFile file );
+
+ private static final List includePatterns;
+
+ static
+ {
+ includePatterns = new ArrayList();
+ includePatterns.add( "**/*.pom" );
+ }
+
+ public List getIncludePatterns()
+ {
+ return includePatterns;
+ }
+
+ public boolean isEnabled()
+ {
+ return true;
+ }
+
+ public void processFile( BaseFile file )
+ throws ConsumerException
+ {
+ Model model = buildModel( file );
+ processModel( model, file );
+ }
+
+ private Model buildModel( BaseFile file )
+ throws ConsumerException
+ {
+ Model model;
+ Reader reader = null;
+ try
+ {
+ reader = new FileReader( file );
+ MavenXpp3Reader modelReader = new MavenXpp3Reader();
+
+ model = modelReader.read( reader );
+ }
+ catch ( XmlPullParserException e )
+ {
+ throw new ConsumerException( file, "Error parsing metadata file: " + e.getMessage(), e );
+ }
+ catch ( IOException e )
+ {
+ throw new ConsumerException( file, "Error reading metadata file: " + e.getMessage(), e );
+ }
+ finally
+ {
+ IOUtil.close( reader );
+ }
+
+ return model;
+ }
+}
diff --git a/archiva-common/src/main/java/org/apache/maven/archiva/common/consumers/GenericRepositoryMetadataConsumer.java b/archiva-common/src/main/java/org/apache/maven/archiva/common/consumers/GenericRepositoryMetadataConsumer.java
new file mode 100644
index 000000000..1f4433c49
--- /dev/null
+++ b/archiva-common/src/main/java/org/apache/maven/archiva/common/consumers/GenericRepositoryMetadataConsumer.java
@@ -0,0 +1,231 @@
+package org.apache.maven.archiva.common.consumers;
+
+/*
+ * 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.
+ */
+
+import org.apache.commons.lang.StringUtils;
+import org.apache.maven.archiva.common.utils.BaseFile;
+import org.apache.maven.artifact.Artifact;
+import org.apache.maven.artifact.repository.layout.ArtifactRepositoryLayout;
+import org.apache.maven.artifact.repository.layout.DefaultRepositoryLayout;
+import org.apache.maven.artifact.repository.metadata.ArtifactRepositoryMetadata;
+import org.apache.maven.artifact.repository.metadata.GroupRepositoryMetadata;
+import org.apache.maven.artifact.repository.metadata.Metadata;
+import org.apache.maven.artifact.repository.metadata.RepositoryMetadata;
+import org.apache.maven.artifact.repository.metadata.SnapshotArtifactRepositoryMetadata;
+import org.apache.maven.artifact.repository.metadata.io.xpp3.MetadataXpp3Reader;
+import org.codehaus.plexus.util.IOUtil;
+import org.codehaus.plexus.util.xml.pull.XmlPullParserException;
+
+import java.io.FileReader;
+import java.io.IOException;
+import java.io.Reader;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.List;
+import java.util.StringTokenizer;
+
+/**
+ * GenericRepositoryMetadataConsumer - Consume any maven-metadata.xml files as {@link RepositoryMetadata} objects.
+ *
+ * @author <a href="mailto:joakime@apache.org">Joakim Erdfelt</a>
+ * @version $Id$
+ */
+public abstract class GenericRepositoryMetadataConsumer
+ extends AbstractConsumer
+ implements Consumer
+{
+ public abstract void processRepositoryMetadata( RepositoryMetadata metadata, BaseFile file );
+
+ private static final List includePatterns;
+
+ static
+ {
+ includePatterns = new ArrayList();
+ includePatterns.add( "**/maven-metadata.xml" );
+ }
+
+ public List getIncludePatterns()
+ {
+ return includePatterns;
+ }
+
+ public boolean isEnabled()
+ {
+ // the RepositoryMetadata objects only exist in 'default' layout repositories.
+ ArtifactRepositoryLayout layout = repository.getLayout();
+ return ( layout instanceof DefaultRepositoryLayout );
+ }
+
+ public void processFile( BaseFile file )
+ throws ConsumerException
+ {
+ if ( file.length() <= 0 )
+ {
+ throw new ConsumerException( file, "File is empty." );
+ }
+
+ if ( !file.canRead() )
+ {
+ throw new ConsumerException( file, "Not allowed to read file due to permission settings on file." );
+ }
+
+ RepositoryMetadata metadata = buildMetadata( file );
+ processRepositoryMetadata( metadata, file );
+ }
+
+ private RepositoryMetadata buildMetadata( BaseFile metadataFile )
+ throws ConsumerException
+ {
+ Metadata m;
+ Reader reader = null;
+ try
+ {
+ reader = new FileReader( metadataFile );
+ MetadataXpp3Reader metadataReader = new MetadataXpp3Reader();
+
+ m = metadataReader.read( reader );
+ }
+ catch ( XmlPullParserException e )
+ {
+ throw new ConsumerException( metadataFile, "Error parsing metadata file: " + e.getMessage(), e );
+ }
+ catch ( IOException e )
+ {
+ throw new ConsumerException( metadataFile, "Error reading metadata file: " + e.getMessage(), e );
+ }
+ finally
+ {
+ IOUtil.close( reader );
+ }
+
+ RepositoryMetadata repositoryMetadata = buildMetadata( m, metadataFile );
+
+ if ( repositoryMetadata == null )
+ {
+ throw new ConsumerException( metadataFile, "Unable to build a repository metadata from path." );
+ }
+
+ return repositoryMetadata;
+ }
+
+ /**
+ * Builds a RepositoryMetadata object from a Metadata object and its path.
+ *
+ * @param m Metadata
+ * @param metadataFile file information
+ * @return RepositoryMetadata if the parameters represent one; null if not
+ * @throws ConsumerException
+ */
+ private RepositoryMetadata buildMetadata( Metadata m, BaseFile metadataFile )
+ throws ConsumerException
+ {
+ if ( artifactFactory == null )
+ {
+ throw new IllegalStateException( "Unable to build metadata with a null artifactFactory." );
+ }
+
+ String metaGroupId = m.getGroupId();
+ String metaArtifactId = m.getArtifactId();
+ String metaVersion = m.getVersion();
+
+ // check if the groupId, artifactId and version is in the
+ // metadataPath
+ // parse the path, in reverse order
+ List pathParts = new ArrayList();
+ StringTokenizer st = new StringTokenizer( metadataFile.getRelativePath(), "/\\" );
+ while ( st.hasMoreTokens() )
+ {
+ pathParts.add( st.nextToken() );
+ }
+
+ Collections.reverse( pathParts );
+ // remove the metadata file
+ pathParts.remove( 0 );
+ Iterator it = pathParts.iterator();
+ String tmpDir = (String) it.next();
+
+ Artifact artifact = null;
+ if ( StringUtils.isNotEmpty( metaVersion ) )
+ {
+ artifact = artifactFactory.createProjectArtifact( metaGroupId, metaArtifactId, metaVersion );
+ }
+
+ // snapshotMetadata
+ RepositoryMetadata metadata = null;
+ if ( tmpDir != null && tmpDir.equals( metaVersion ) )
+ {
+ if ( artifact != null )
+ {
+ metadata = new SnapshotArtifactRepositoryMetadata( artifact );
+ }
+ }
+ else if ( tmpDir != null && tmpDir.equals( metaArtifactId ) )
+ {
+ // artifactMetadata
+ if ( artifact != null )
+ {
+ metadata = new ArtifactRepositoryMetadata( artifact );
+ }
+ else
+ {
+ artifact = artifactFactory.createProjectArtifact( metaGroupId, metaArtifactId, "1.0" );
+ metadata = new ArtifactRepositoryMetadata( artifact );
+ }
+ }
+ else
+ {
+ String groupDir = "";
+ int ctr = 0;
+ for ( it = pathParts.iterator(); it.hasNext(); )
+ {
+ String path = (String) it.next();
+ if ( ctr == 0 )
+ {
+ groupDir = path;
+ }
+ else
+ {
+ groupDir = path + "." + groupDir;
+ }
+ ctr++;
+ }
+
+ // groupMetadata
+ if ( metaGroupId != null && metaGroupId.equals( groupDir ) )
+ {
+ metadata = new GroupRepositoryMetadata( metaGroupId );
+ }
+ else
+ {
+ /* If we reached this point, we have some bad metadata.
+ * We have a metadata file, with values for groupId / artifactId / version.
+ * But the information it is providing does not exist relative to the file location.
+ *
+ * See ${basedir}/src/test/repository/javax/maven-metadata.xml for example
+ */
+ throw new ConsumerException( metadataFile,
+ "Contents of metadata are not appropriate for its location on disk." );
+ }
+ }
+
+ return metadata;
+ }
+}
diff --git a/archiva-common/src/main/java/org/apache/maven/archiva/common/utils/BaseFile.java b/archiva-common/src/main/java/org/apache/maven/archiva/common/utils/BaseFile.java
new file mode 100644
index 000000000..a4b83db7e
--- /dev/null
+++ b/archiva-common/src/main/java/org/apache/maven/archiva/common/utils/BaseFile.java
@@ -0,0 +1,105 @@
+package org.apache.maven.archiva.common.utils;
+
+/*
+ * 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.
+ */
+
+import java.io.File;
+import java.net.URI;
+
+/**
+ * BaseFile - convenient File object that tracks the Base Directory and can provide relative path values
+ * for the file object based on that Base Directory value.
+ *
+ * @author <a href="mailto:joakim@erdfelt.com">Joakim Erdfelt</a>
+ * @version $Id$
+ */
+public class BaseFile
+ extends File
+{
+ private File baseDir;
+
+ public BaseFile( File pathFile )
+ {
+ this( pathFile.getAbsolutePath() );
+ }
+
+ public BaseFile( File repoDir, File pathFile )
+ {
+ this( repoDir, PathUtil.getRelative( repoDir.getAbsolutePath(), pathFile ) );
+ }
+
+ public BaseFile( File parent, String child )
+ {
+ super( parent, child );
+ this.baseDir = parent;
+ }
+
+ public BaseFile( String pathname )
+ {
+ super( pathname );
+
+ // Calculate the top level directory.
+
+ File parent = this;
+ while ( parent.getParentFile() != null )
+ {
+ parent = parent.getParentFile();
+ }
+
+ this.baseDir = parent;
+ }
+
+ public BaseFile( String repoDir, File pathFile )
+ {
+ this( new File( repoDir ), pathFile );
+ }
+
+ public BaseFile( String parent, String child )
+ {
+ super( parent, child );
+ this.baseDir = new File( parent );
+ }
+
+ public BaseFile( URI uri )
+ {
+ super( uri ); // only to satisfy java compiler.
+ throw new IllegalStateException( "The " + BaseFile.class.getName()
+ + " object does not support URI construction." );
+ }
+
+ public File getBaseDir()
+ {
+ return baseDir;
+ }
+
+ public String getRelativePath()
+ {
+ return PathUtil.getRelative( this.baseDir.getAbsolutePath(), this );
+ }
+
+ public void setBaseDir( File baseDir )
+ {
+ this.baseDir = baseDir;
+ }
+
+ public void setBaseDir( String repoDir )
+ {
+ setBaseDir( new File( repoDir ) );
+ }
+}
diff --git a/archiva-common/src/main/java/org/apache/maven/archiva/common/utils/PathUtil.java b/archiva-common/src/main/java/org/apache/maven/archiva/common/utils/PathUtil.java
new file mode 100644
index 000000000..25df4254a
--- /dev/null
+++ b/archiva-common/src/main/java/org/apache/maven/archiva/common/utils/PathUtil.java
@@ -0,0 +1,56 @@
+package org.apache.maven.archiva.common.utils;
+
+/*
+ * 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.
+ */
+
+import java.io.File;
+
+/**
+ * PathUtil - simple utility methods for path manipulation.
+ *
+ * @author <a href="mailto:joakime@apache.org">Joakim Erdfelt</a>
+ * @version $Id$
+ */
+public class PathUtil
+{
+ public static String getRelative( String basedir, File file )
+ {
+ return getRelative( basedir, file.getAbsolutePath() );
+ }
+
+ public static String getRelative( String basedir, String child )
+ {
+ if ( child.startsWith( basedir ) )
+ {
+ // simple solution.
+ return child.substring( basedir.length() + 1 );
+ }
+
+ String absoluteBasedir = new File( basedir ).getAbsolutePath();
+ if ( child.startsWith( absoluteBasedir ) )
+ {
+ // resolved basedir solution.
+ return child.substring( absoluteBasedir.length() + 1 );
+ }
+
+ // File is not within basedir.
+ throw new IllegalStateException( "Unable to obtain relative path of file " + child
+ + ", it is not within basedir " + basedir + "." );
+ }
+}