]> source.dussan.org Git - archiva.git/commitdiff
Refactoring the repository content factory
authorMartin Stockhammer <martin_s@apache.org>
Wed, 1 Nov 2017 21:52:14 +0000 (22:52 +0100)
committerMartin Stockhammer <martin_s@apache.org>
Wed, 1 Nov 2017 21:52:14 +0000 (22:52 +0100)
Adding content provider service that creates repository content instances
remove direct access to the repository content instances.

42 files changed:
archiva-modules/archiva-base/archiva-consumers/archiva-consumer-archetype/src/main/resources/archetype-resources/src/test/resources/spring-context.xml
archiva-modules/archiva-base/archiva-consumers/archiva-core-consumers/src/test/java/org/apache/archiva/consumers/core/repository/AbstractRepositoryPurgeTest.java
archiva-modules/archiva-base/archiva-consumers/archiva-core-consumers/src/test/java/org/apache/archiva/repository/mock/ManagedRepositoryContentMock.java [deleted file]
archiva-modules/archiva-base/archiva-consumers/archiva-core-consumers/src/test/java/org/apache/archiva/repository/mock/RemoteRepositoryContentMock.java [deleted file]
archiva-modules/archiva-base/archiva-consumers/archiva-core-consumers/src/test/resources/spring-context-cleanup-released-snapshots.xml
archiva-modules/archiva-base/archiva-consumers/archiva-core-consumers/src/test/resources/spring-context.xml
archiva-modules/archiva-base/archiva-converter/src/main/java/org/apache/archiva/converter/legacy/LegacyConverterArtifactConsumer.java
archiva-modules/archiva-base/archiva-indexer/src/test/resources/spring-context.xml
archiva-modules/archiva-base/archiva-proxy/src/test/java/org/apache/archiva/proxy/AbstractProxyTestCase.java
archiva-modules/archiva-base/archiva-proxy/src/test/java/org/apache/archiva/proxy/HttpProxyTransferTest.java
archiva-modules/archiva-base/archiva-proxy/src/test/resources/spring-context.xml
archiva-modules/archiva-base/archiva-repository-admin/archiva-repository-admin-default/src/test/resources/spring-context.xml
archiva-modules/archiva-base/archiva-repository-layer/src/main/java/org/apache/archiva/repository/ManagedRepositoryContent.java
archiva-modules/archiva-base/archiva-repository-layer/src/main/java/org/apache/archiva/repository/RemoteRepositoryContent.java
archiva-modules/archiva-base/archiva-repository-layer/src/main/java/org/apache/archiva/repository/RepositoryContent.java [new file with mode: 0644]
archiva-modules/archiva-base/archiva-repository-layer/src/main/java/org/apache/archiva/repository/RepositoryContentFactory.java
archiva-modules/archiva-base/archiva-repository-layer/src/main/java/org/apache/archiva/repository/RepositoryContentProvider.java [new file with mode: 0644]
archiva-modules/archiva-base/archiva-repository-layer/src/main/java/org/apache/archiva/repository/RepositoryRegistry.java
archiva-modules/archiva-scheduler/archiva-scheduler-indexing/src/test/resources/spring-context.xml
archiva-modules/archiva-scheduler/archiva-scheduler-repository/src/test/resources/spring-context.xml
archiva-modules/archiva-web/archiva-rest/archiva-rest-services/src/test/resources/META-INF/spring-context-test.xml
archiva-modules/archiva-web/archiva-security/src/test/resources/spring-context.xml
archiva-modules/archiva-web/archiva-web-common/src/test/resources/spring-context-artifacts-download.xml
archiva-modules/archiva-web/archiva-web-common/src/test/resources/spring-context-merge-index-download.xml
archiva-modules/archiva-web/archiva-web-common/src/test/resources/spring-context-rss-servlet.xml
archiva-modules/archiva-web/archiva-web-common/src/test/resources/spring-context-test-common.xml
archiva-modules/archiva-web/archiva-web-common/src/test/resources/spring-context-with-jcr.xml
archiva-modules/archiva-web/archiva-webdav/src/test/java/org/apache/archiva/webdav/ArchivaDavResourceFactoryTest.java
archiva-modules/archiva-web/archiva-webdav/src/test/resources/spring-context-servlet-security-test.xml
archiva-modules/archiva-web/archiva-webdav/src/test/resources/spring-context.xml
archiva-modules/plugins/maven2-repository/src/main/java/org/apache/archiva/repository/content/maven2/AbstractDefaultRepositoryContent.java
archiva-modules/plugins/maven2-repository/src/main/java/org/apache/archiva/repository/content/maven2/ManagedDefaultRepositoryContent.java
archiva-modules/plugins/maven2-repository/src/main/java/org/apache/archiva/repository/content/maven2/MavenContentProvider.java [new file with mode: 0644]
archiva-modules/plugins/maven2-repository/src/main/java/org/apache/archiva/repository/content/maven2/RemoteDefaultRepositoryContent.java
archiva-modules/plugins/maven2-repository/src/test/java/org/apache/archiva/metadata/repository/storage/maven2/ManagedDefaultRepositoryContentTest.java
archiva-modules/plugins/maven2-repository/src/test/java/org/apache/archiva/metadata/repository/storage/maven2/RemoteDefaultRepositoryContentTest.java
archiva-modules/plugins/maven2-repository/src/test/java/org/apache/archiva/repository/AbstractRepositoryLayerTestCase.java
archiva-modules/plugins/maven2-repository/src/test/java/org/apache/archiva/repository/content/maven2/RepositoryRequestTest.java
archiva-modules/plugins/maven2-repository/src/test/java/org/apache/archiva/repository/metadata/MetadataToolsTest.java
archiva-modules/plugins/maven2-repository/src/test/resources/spring-context-no-mock-conf.xml
archiva-modules/plugins/maven2-repository/src/test/resources/spring-context-repo-request-test.xml
archiva-modules/plugins/maven2-repository/src/test/resources/spring-context.xml

index b5ff2155532976910f55723a4f5e88f7de3eb46f..56894fc5f773c61c4b55299637d055e96d4916ee 100644 (file)
   <mockito:mock id="mockManagedRepositoryAdmin" class="org.apache.archiva.admin.model.managed.ManagedRepositoryAdmin" />
   <mockito:mock id="mockRemoteRepositoryAdmin" class="org.apache.archiva.admin.model.remote.RemoteRepositoryAdmin" />
 
-  <context:component-scan base-package="org.apache.archiva.repository.mock,org.apache.archiva.repository.content.maven2,$package"/>
+  <context:component-scan base-package="org.apache.archiva.repository.mock,org.apache.archiva.repository.content.maven2"/>
 
-  <alias name="managedRepositoryContent#maven" alias="managedRepositoryContent#default" />
-  <alias name="remoteRepositoryContent#maven" alias="remoteRepositoryContent#default" />
   <alias name="mockRepositoryProvider" alias="mavenRepositoryProvider" />
 
   <alias alias="repositorySessionFactory#jcr" name="repositorySessionFactory#file" />
index b0e9a98985c22ac6f317bd7d41da05fdad55dfb0..d65d1a49123a8e53f8e9c4b55c7f25a0aee4dd82 100644 (file)
@@ -27,6 +27,7 @@ import org.apache.archiva.metadata.repository.storage.maven2.Maven2RepositoryPat
 import org.apache.archiva.repository.BasicManagedRepository;
 import org.apache.archiva.repository.ManagedRepositoryContent;
 import org.apache.archiva.repository.ReleaseScheme;
+import org.apache.archiva.repository.RepositoryContentProvider;
 import org.apache.archiva.repository.events.RepositoryListener;
 import org.apache.archiva.repository.features.ArtifactCleanupFeature;
 import org.apache.archiva.test.utils.ArchivaSpringJUnit4ClassRunner;
@@ -184,8 +185,9 @@ public abstract class AbstractRepositoryPurgeTest
     {
         if ( repo == null )
         {
-            repo = applicationContext.getBean( "managedRepositoryContent#default", ManagedRepositoryContent.class );
-            repo.setRepository( getRepoConfiguration( TEST_REPO_ID, TEST_REPO_NAME ) );
+            org.apache.archiva.repository.ManagedRepository repoCfg = getRepoConfiguration( TEST_REPO_ID, TEST_REPO_NAME );
+            RepositoryContentProvider provider = applicationContext.getBean( "repositoryContentProvider#maven", RepositoryContentProvider.class );
+            repo = provider.createManagedContent( repoCfg );
         }
 
         return repo;
diff --git a/archiva-modules/archiva-base/archiva-consumers/archiva-core-consumers/src/test/java/org/apache/archiva/repository/mock/ManagedRepositoryContentMock.java b/archiva-modules/archiva-base/archiva-consumers/archiva-core-consumers/src/test/java/org/apache/archiva/repository/mock/ManagedRepositoryContentMock.java
deleted file mode 100644 (file)
index 9a53bf2..0000000
+++ /dev/null
@@ -1,181 +0,0 @@
-package org.apache.archiva.repository.mock;
-
-/*
- * 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.archiva.model.ArchivaArtifact;
-import org.apache.archiva.model.ArtifactReference;
-import org.apache.archiva.model.ProjectReference;
-import org.apache.archiva.model.VersionedReference;
-import org.apache.archiva.repository.ContentNotFoundException;
-import org.apache.archiva.repository.ManagedRepository;
-import org.apache.archiva.repository.ManagedRepositoryContent;
-import org.apache.archiva.repository.RepositoryException;
-import org.apache.archiva.repository.layout.LayoutException;
-import org.springframework.stereotype.Service;
-
-import java.net.URI;
-import java.nio.file.Path;
-import java.nio.file.Paths;
-import java.util.Set;
-
-/**
- * @author Martin Stockhammer <martin_s@apache.org>
- */
-@Service("managedRepositoryContent#mock")
-public class ManagedRepositoryContentMock implements ManagedRepositoryContent
-{
-    private ManagedRepository repository;
-
-    @Override
-    public void deleteVersion( VersionedReference reference ) throws ContentNotFoundException
-    {
-
-    }
-
-    @Override
-    public void deleteArtifact( ArtifactReference artifactReference ) throws ContentNotFoundException
-    {
-
-    }
-
-    @Override
-    public void deleteGroupId( String groupId ) throws ContentNotFoundException
-    {
-
-    }
-
-    @Override
-    public void deleteProject( String namespace, String projectId ) throws RepositoryException
-    {
-
-    }
-
-    @Override
-    public String getId( )
-    {
-        return null;
-    }
-
-    @Override
-    public Set<ArtifactReference> getRelatedArtifacts( ArtifactReference reference ) throws ContentNotFoundException
-    {
-        return null;
-    }
-
-    @Override
-    public String getRepoRoot()
-    {
-        return convertUriToPath( repository.getLocation() );
-    }
-
-    private String convertUriToPath( URI uri ) {
-        if (uri.getScheme()==null) {
-            return Paths.get(uri.getPath()).toString();
-        } else if ("file".equals(uri.getScheme())) {
-            return Paths.get(uri).toString();
-        } else {
-            return uri.toString();
-        }
-    }
-
-    @Override
-    public ManagedRepository getRepository( )
-    {
-        return repository;
-    }
-
-    @Override
-    public Set<String> getVersions( ProjectReference reference ) throws ContentNotFoundException, LayoutException
-    {
-        return null;
-    }
-
-    @Override
-    public Set<String> getVersions( VersionedReference reference ) throws ContentNotFoundException
-    {
-        return null;
-    }
-
-    @Override
-    public boolean hasContent( ArtifactReference reference )
-    {
-        return false;
-    }
-
-    @Override
-    public boolean hasContent( ProjectReference reference )
-    {
-        return false;
-    }
-
-    @Override
-    public boolean hasContent( VersionedReference reference )
-    {
-        return false;
-    }
-
-    @Override
-    public void setRepository( ManagedRepository repo )
-    {
-        this.repository = repo;
-    }
-
-    @Override
-    public ArtifactReference toArtifactReference( String path ) throws LayoutException
-    {
-        return null;
-    }
-
-    @Override
-    public Path toFile( ArtifactReference reference )
-    {
-        return null;
-    }
-
-    @Override
-    public Path toFile( ArchivaArtifact reference )
-    {
-        return null;
-    }
-
-    @Override
-    public String toMetadataPath( ProjectReference reference )
-    {
-        return null;
-    }
-
-    @Override
-    public String toMetadataPath( VersionedReference reference )
-    {
-        return null;
-    }
-
-    @Override
-    public String toPath( ArtifactReference reference )
-    {
-        return null;
-    }
-
-    @Override
-    public String toPath( ArchivaArtifact reference )
-    {
-        return null;
-    }
-}
diff --git a/archiva-modules/archiva-base/archiva-consumers/archiva-core-consumers/src/test/java/org/apache/archiva/repository/mock/RemoteRepositoryContentMock.java b/archiva-modules/archiva-base/archiva-consumers/archiva-core-consumers/src/test/java/org/apache/archiva/repository/mock/RemoteRepositoryContentMock.java
deleted file mode 100644 (file)
index 238b0cf..0000000
+++ /dev/null
@@ -1,78 +0,0 @@
-package org.apache.archiva.repository.mock;
-
-/*
- * 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.archiva.model.ArtifactReference;
-import org.apache.archiva.model.RepositoryURL;
-import org.apache.archiva.repository.RemoteRepository;
-import org.apache.archiva.repository.RemoteRepositoryContent;
-import org.apache.archiva.repository.layout.LayoutException;
-import org.springframework.stereotype.Service;
-
-/**
- * @author Martin Stockhammer <martin_s@apache.org>
- */
-@Service("remoteRepositoryContent#mock")
-public class RemoteRepositoryContentMock implements RemoteRepositoryContent
-{
-    RemoteRepository repository;
-
-    @Override
-    public String getId( )
-    {
-        return null;
-    }
-
-    @Override
-    public RemoteRepository getRepository( )
-    {
-        return null;
-    }
-
-    @Override
-    public RepositoryURL getURL( )
-    {
-        return null;
-    }
-
-    @Override
-    public void setRepository( RemoteRepository repo )
-    {
-        this.repository = repo;
-    }
-
-    @Override
-    public ArtifactReference toArtifactReference( String path ) throws LayoutException
-    {
-        return null;
-    }
-
-    @Override
-    public String toPath( ArtifactReference reference )
-    {
-        return null;
-    }
-
-    @Override
-    public RepositoryURL toURL( ArtifactReference reference )
-    {
-        return null;
-    }
-}
index c6fa2a127de6d574e1fa71328ce1051e5519680b..5119c55e9e9393b23060503dd626b9cf752cc8b8 100644 (file)
@@ -32,9 +32,8 @@
   </bean>
   <alias name="archivaConfiguration#cleanup-released-snapshots" alias="archivaConfiguration"/>
   <alias name="archivaConfiguration#cleanup-released-snapshots" alias="archivaConfiguration#default"/>
-  <context:component-scan base-package="org.apache.archiva.repository.mock,org.apache.archiva.repository.content.maven2"/>
+  <context:component-scan base-package="org.apache.archiva.configuration,org.apache.archiva.repository.content.maven2"/>
 
-  <alias name="managedRepositoryContent#maven" alias="managedRepositoryContent#default" />
   <alias name="repositoryContentFactory#cleanup-released-snapshots" alias="repositoryContentFactory#default" />
 
 
index 360e20d92cd23ced4ad672e2c0bc75facbe3caf2..e63eb7af3775d5ecf30b88bdd833e16f91ecf714 100644 (file)
@@ -44,7 +44,6 @@
     </property>
   </bean>
 
-  <alias name="managedRepositoryContent#maven" alias="managedRepositoryContent#default" />
   <alias name="userConfiguration#redback" alias="userConfiguration#default"/>
 
   <!-- ***
index 7fb542eb106d2f267d312b2ac931c885b3046e1b..9cdde0adaa050f043fafaae1338450516962a99e 100644 (file)
@@ -21,11 +21,13 @@ package org.apache.archiva.converter.legacy;
 
 import org.apache.archiva.common.plexusbridge.PlexusSisuBridge;
 import org.apache.archiva.common.plexusbridge.PlexusSisuBridgeException;
+import org.apache.archiva.configuration.FileTypes;
 import org.apache.archiva.consumers.AbstractMonitoredConsumer;
 import org.apache.archiva.consumers.ConsumerException;
 import org.apache.archiva.consumers.KnownRepositoryContentConsumer;
 import org.apache.archiva.converter.artifact.ArtifactConversionException;
 import org.apache.archiva.converter.artifact.ArtifactConverter;
+import org.apache.archiva.metadata.repository.storage.maven2.ArtifactMappingProvider;
 import org.apache.archiva.model.ArtifactReference;
 import org.apache.archiva.repository.ManagedRepository;
 import org.apache.archiva.repository.ManagedRepositoryContent;
@@ -63,6 +65,12 @@ public class LegacyConverterArtifactConsumer
     @Named("artifactConverter#legacy-to-default")
     private ArtifactConverter artifactConverter;
 
+    @Inject
+    private List<? extends ArtifactMappingProvider> artifactMappingProviders;
+
+    @Inject
+    private FileTypes fileTypes;
+
     private ArtifactFactory artifactFactory;
 
     private ManagedRepositoryContent managedRepository;
@@ -88,7 +96,7 @@ public class LegacyConverterArtifactConsumer
     public void beginScan( org.apache.archiva.repository.ManagedRepository repository, Date whenGathered )
         throws ConsumerException
     {
-        this.managedRepository = new ManagedDefaultRepositoryContent();
+        this.managedRepository = new ManagedDefaultRepositoryContent(artifactMappingProviders, fileTypes);
         this.managedRepository.setRepository( repository );
     }
 
index 487790661845850cf30648b07899e1a802b10d40..e0bf5c41c680a462898ac48dc8cc08a757cfff7f 100644 (file)
        default-lazy-init="false">
 
   <context:annotation-config/>
-  <context:component-scan base-package="org.apache.archiva.repository.content.maven2" />
-
-  <alias name="managedRepositoryContent#maven" alias="managedRepositoryContent#default" />
-  <alias name="remoteRepositoryContent#maven" alias="remoteRepositoryContent#default" />
-
 
   <bean name="scheduler" class="org.apache.archiva.redback.components.scheduler.DefaultScheduler">
     <property name="properties">
index 2a43b862e5cd19ef9f0b88d9003454f9d6681451..c4bfff309a09c21e2ae8b683fbf27b49007fea1c 100644 (file)
@@ -36,6 +36,7 @@ import org.apache.archiva.policies.ReleasesPolicy;
 import org.apache.archiva.policies.SnapshotsPolicy;
 import org.apache.archiva.proxy.model.RepositoryProxyConnectors;
 import org.apache.archiva.repository.ManagedRepositoryContent;
+import org.apache.archiva.repository.RepositoryContentProvider;
 import org.apache.archiva.repository.RepositoryRegistry;
 import org.apache.archiva.repository.maven2.MavenManagedRepository;
 import org.apache.archiva.test.utils.ArchivaSpringJUnit4ClassRunner;
@@ -357,9 +358,9 @@ public abstract class AbstractProxyTestCase
         repo.setLocation( new URI(path) );
         repo.setLayout( layout );
 
+        RepositoryContentProvider provider = applicationContext.getBean( "repositoryContentProvider#maven", RepositoryContentProvider.class );
         ManagedRepositoryContent repoContent =
-            applicationContext.getBean( "managedRepositoryContent#" + layout, ManagedRepositoryContent.class );
-        repoContent.setRepository( repo );
+            provider.createManagedContent( repo );
         return repoContent;
     }
 
index 8b8d08e05c7593cf73931f9d3259343ffb1f4baf..3980d87c24b3813eba1174ff7ca805a18cf07571 100644 (file)
@@ -23,6 +23,7 @@ import org.apache.archiva.admin.model.beans.ManagedRepository;
 import org.apache.archiva.admin.model.managed.ManagedRepositoryAdmin;
 import org.apache.archiva.admin.repository.managed.DefaultManagedRepositoryAdmin;
 import org.apache.archiva.proxy.model.RepositoryProxyConnectors;
+import org.apache.archiva.repository.RepositoryContentProvider;
 import org.apache.archiva.repository.RepositoryRegistry;
 import org.apache.archiva.repository.maven2.MavenManagedRepository;
 import org.apache.commons.io.FileUtils;
@@ -126,10 +127,10 @@ public class HttpProxyTransferTest
         repo.setLocation( new URI(repoPath) );
         repo.setLayout( "default" );
 
+        RepositoryContentProvider provider = applicationContext.getBean( "repositoryContentProvider#maven", RepositoryContentProvider.class );
         ManagedRepositoryContent repoContent =
-            applicationContext.getBean( "managedRepositoryContent#default", ManagedRepositoryContent.class );
+            provider.createManagedContent( repo );
 
-        repoContent.setRepository( repo );
         managedDefaultRepository = repoContent;
 
         ( (DefaultManagedRepositoryAdmin) applicationContext.getBean(
index 6ec124f60cb66da500c0da409d035ced1e140e1a..baef8a5e41f614394006e8beaf40570da3c86607 100755 (executable)
@@ -28,9 +28,7 @@
        default-lazy-init="true">
 
   <context:annotation-config/>
-  <context:component-scan base-package="org.apache.archiva.metadata.repository,org.apache.archiva.repository.content.maven2,org.apache.archiva.proxy,org.apache.archiva.repository.mock"/>
-  <alias name="managedRepositoryContent#maven" alias="managedRepositoryContent#default" />
-  <alias name="remoteRepositoryContent#maven" alias="remoteRepositoryContent#default" />
+  <context:component-scan base-package="org.apache.archiva.metadata.repository,org.apache.archiva.proxy,org.apache.archiva.repository.mock"/>
   <alias name="mockRepositoryProvider" alias="mavenRepositoryProvider" />
 
   <alias name="archivaConfiguration#mock" alias="archivaConfiguration#default"/>
index a2670af4b3ddac759fa4779c6965e6b477ec0b73..dd261ebad51ee91349203af2d095acba0089d4ce 100644 (file)
@@ -33,9 +33,6 @@
   <context:annotation-config/>
   <context:component-scan base-package="org.apache.archiva.admin.mock,org.apache.archiva.repository.content.maven2"/>
 
-  <alias name="managedRepositoryContent#maven" alias="managedRepositoryContent#default" />
-  <alias name="remoteRepositoryContent#maven" alias="remoteRepositoryContent#default" />
-
   <bean name="scheduler" class="org.apache.archiva.redback.components.scheduler.DefaultScheduler">
     <property name="properties">
       <props>
index c209c38651e6d1bfed5fa3666e85496a7be2fabd..5baf32fdba9571898901bc177993303f883eadc2 100644 (file)
@@ -32,8 +32,11 @@ import java.util.Set;
  * ManagedRepositoryContent interface for interacting with a managed repository in an abstract way,
  * without the need for processing based on filesystem paths, or working with the database.
  */
-public interface ManagedRepositoryContent
+public interface ManagedRepositoryContent extends RepositoryContent
 {
+
+
+
     /**
      * Delete from the managed repository all files / directories associated with the
      * provided version reference.
@@ -117,7 +120,7 @@ public interface ManagedRepositoryContent
      *
      * @return the repository that is associated with this repository content.
      */
-    org.apache.archiva.repository.ManagedRepository getRepository();
+    ManagedRepository getRepository();
 
     /**
      * Given a specific {@link ProjectReference}, return the list of available versions for
@@ -179,17 +182,6 @@ public interface ManagedRepositoryContent
      */
     void setRepository( org.apache.archiva.repository.ManagedRepository repo );
 
-    /**
-     * Given a repository relative path to a filename, return the {@link VersionedReference} object suitable for the path.
-     *
-     * @param path the path relative to the repository base dir for the artifact.
-     * @return the {@link ArtifactReference} representing the path.  (or null if path cannot be converted to
-     *         a {@link ArtifactReference})
-     * @throws LayoutException if there was a problem converting the path to an artifact.
-     */
-    ArtifactReference toArtifactReference( String path )
-        throws LayoutException;
-
     /**
      * Given an {@link ArtifactReference}, return the file reference to the artifact.
      *
@@ -224,14 +216,6 @@ public interface ManagedRepositoryContent
      */
     String toMetadataPath( VersionedReference reference );
 
-    /**
-     * Given an {@link ArtifactReference}, return the relative path to the artifact.
-     *
-     * @param reference the artifact reference to use.
-     * @return the relative path to the artifact.
-     */
-    String toPath( ArtifactReference reference );
-
     /**
      * Given an {@link ArchivaArtifact}, return the relative path to the artifact.
      *
index 6745dd88ee64349cf72111be607148e4135d0ed0..7002d7ebeb622febdb2bd67f0e72eec4c5d45329 100644 (file)
@@ -29,7 +29,7 @@ import org.apache.archiva.repository.layout.LayoutException;
  *
  *
  */
-public interface RemoteRepositoryContent
+public interface RemoteRepositoryContent extends RepositoryContent
 {
     /**
      * <p>
@@ -73,25 +73,6 @@ public interface RemoteRepositoryContent
      */
     void setRepository( RemoteRepository repo );
 
-    /**
-     * Given a repository relative path to a filename, return the {@link org.apache.archiva.model.VersionedReference} object suitable for the path.
-     *
-     * @param path the path relative to the repository base dir for the artifact.
-     * @return the {@link ArtifactReference} representing the path.  (or null if path cannot be converted to
-     *         a {@link ArtifactReference})
-     * @throws LayoutException if there was a problem converting the path to an artifact.
-     */
-    ArtifactReference toArtifactReference( String path )
-        throws LayoutException;
-
-    /**
-     * Given an ArtifactReference, return the relative path to the artifact.
-     *
-     * @param reference the artifact reference to use.
-     * @return the relative path to the artifact.
-     */
-    String toPath( ArtifactReference reference );
-
     /**
      * Given an ArtifactReference, return the url to the artifact.
      *
diff --git a/archiva-modules/archiva-base/archiva-repository-layer/src/main/java/org/apache/archiva/repository/RepositoryContent.java b/archiva-modules/archiva-base/archiva-repository-layer/src/main/java/org/apache/archiva/repository/RepositoryContent.java
new file mode 100644 (file)
index 0000000..2ceedec
--- /dev/null
@@ -0,0 +1,52 @@
+package org.apache.archiva.repository;
+
+/*
+ * 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.archiva.model.ArtifactReference;
+import org.apache.archiva.model.VersionedReference;
+import org.apache.archiva.repository.layout.LayoutException;
+
+
+/**
+ * Common aspects of content provider interfaces
+ */
+public interface RepositoryContent
+{
+
+
+    /**
+     * Given a repository relative path to a filename, return the {@link VersionedReference} object suitable for the path.
+     *
+     * @param path the path relative to the repository base dir for the artifact.
+     * @return the {@link ArtifactReference} representing the path.  (or null if path cannot be converted to
+     *         a {@link ArtifactReference})
+     * @throws LayoutException if there was a problem converting the path to an artifact.
+     */
+    ArtifactReference toArtifactReference( String path )
+        throws LayoutException;
+
+    /**
+     * Given an {@link ArtifactReference}, return the relative path to the artifact.
+     *
+     * @param reference the artifact reference to use.
+     * @return the relative path to the artifact.
+     */
+    String toPath( ArtifactReference reference );
+}
index 55474585c753dc24611aa14bbb40f1266925ee7d..65d54e605e078a7f89f3ee58432f2e17906fd626 100644 (file)
@@ -30,6 +30,7 @@ import org.springframework.stereotype.Service;
 
 import javax.annotation.PostConstruct;
 import javax.inject.Inject;
+import java.util.List;
 import java.util.Map;
 import java.util.concurrent.ConcurrentHashMap;
 
@@ -49,6 +50,9 @@ public class RepositoryContentFactory
     @Inject
     private ApplicationContext applicationContext;
 
+    @Inject
+    private List<RepositoryContentProvider> repositoryContentProviders;
+
     private final Map<String, ManagedRepositoryContent> managedContentMap;
 
     private final Map<String, RemoteRepositoryContent> remoteContentMap;
@@ -69,7 +73,7 @@ public class RepositoryContentFactory
      * @throws RepositoryException         the repository content object cannot be loaded due to configuration issue.
      */
     public ManagedRepositoryContent getManagedRepositoryContent( String repoId )
-        throws RepositoryNotFoundException, RepositoryException
+        throws RepositoryException
     {
         ManagedRepositoryContent repo = managedContentMap.get( repoId );
 
@@ -85,33 +89,38 @@ public class RepositoryContentFactory
 
     }
 
-    public ManagedRepositoryContent getManagedRepositoryContent( ManagedRepositoryConfiguration repoConfig, org.apache.archiva.repository.ManagedRepository mRepo )
-        throws RepositoryNotFoundException, RepositoryException
+    private RepositoryContentProvider getProvider(final String layout, final RepositoryType repoType) throws RepositoryException
+    {
+        return repositoryContentProviders.stream().filter(p->p.supports( repoType ) && p.supportsLayout( layout )).
+            findFirst().orElseThrow( ( ) -> new RepositoryException( "Could not find content provider for repository type "+repoType+" and layout "+layout ) );
+    }
+
+    public ManagedRepositoryContent getManagedRepositoryContent( org.apache.archiva.repository.ManagedRepository mRepo )
+        throws RepositoryException
     {
-        ManagedRepositoryContent repo = managedContentMap.get( repoConfig.getId( ) );
+        final String id = mRepo.getId();
+        ManagedRepositoryContent content = managedContentMap.get( id );
 
-        if ( repo != null && repo.getRepository()==mRepo)
+        if ( content != null && content.getRepository()==mRepo)
         {
-            return repo;
+            return content;
         }
 
-        repo = applicationContext.getBean( "managedRepositoryContent#" + repoConfig.getLayout( ),
-            ManagedRepositoryContent.class );
-        repo.setRepository( mRepo );
-        ManagedRepositoryContent previousRepo = managedContentMap.put( repoConfig.getId( ), repo );
-        if (previousRepo!=null) {
-            ManagedRepository previousMRepo = previousRepo.getRepository( );
-            if (previousMRepo!=null && previousMRepo instanceof EditableManagedRepository) {
-                ((EditableManagedRepository)previousMRepo).setContent( null );
-            }
-            previousRepo.setRepository( null );
+        RepositoryContentProvider contentProvider = getProvider( mRepo.getLayout( ), mRepo.getType( ) );
+        content = contentProvider.createManagedContent( mRepo );
+        if (content==null) {
+            throw new RepositoryException( "Could not create repository content instance for "+mRepo.getId() );
+        }
+        ManagedRepositoryContent previousContent = managedContentMap.put( id, content );
+        if (previousContent!=null) {
+            previousContent.setRepository( null );
         }
 
-        return repo;
+        return content;
     }
 
     public RemoteRepositoryContent getRemoteRepositoryContent( String repoId )
-        throws RepositoryNotFoundException, RepositoryException
+        throws RepositoryException
     {
         RemoteRepositoryContent repo = remoteContentMap.get( repoId );
 
@@ -127,30 +136,27 @@ public class RepositoryContentFactory
 
     }
 
-    public RemoteRepositoryContent getRemoteRepositoryContent( RemoteRepositoryConfiguration repoConfig, RemoteRepository mRepo )
-        throws RepositoryNotFoundException, RepositoryException
+    public RemoteRepositoryContent getRemoteRepositoryContent( RemoteRepository mRepo )
+        throws RepositoryException
     {
-        RemoteRepositoryContent repo = remoteContentMap.get( repoConfig.getId( ) );
+        final String id = mRepo.getId();
+        RemoteRepositoryContent content = remoteContentMap.get( id );
 
-        if ( repo != null && repo.getRepository()==mRepo)
+        if ( content != null && content.getRepository()==mRepo)
         {
-            return repo;
+            return content;
         }
 
-        repo = applicationContext.getBean( "remoteRepositoryContent#" + repoConfig.getLayout( ),
-            RemoteRepositoryContent.class );
-        repo.setRepository( mRepo );
-        RemoteRepositoryContent previousRepo = remoteContentMap.put( repoConfig.getId( ), repo );
-        if (previousRepo!=null) {
-            RemoteRepository previousMRepo = previousRepo.getRepository( );
-            if (previousMRepo!=null && previousMRepo instanceof EditableRemoteRepository) {
-                ((EditableRemoteRepository)previousMRepo).setContent( null );
-            }
-            previousRepo.setRepository( null );
+        RepositoryContentProvider contentProvider = getProvider( mRepo.getLayout( ), mRepo.getType( ) );
+        content = contentProvider.createRemoteContent( mRepo );
+        if (content==null) {
+            throw new RepositoryException( "Could not create repository content instance for "+mRepo.getId() );
         }
-
-
-        return repo;
+        RemoteRepositoryContent previousContent = remoteContentMap.put( id, content );
+        if (previousContent!=null) {
+            previousContent.setRepository( null );
+        }
+        return content;
     }
 
 
@@ -199,4 +205,12 @@ public class RepositoryContentFactory
     {
         this.archivaConfiguration = archivaConfiguration;
     }
+
+    public void setRepositoryContentProviders(List<RepositoryContentProvider> providers) {
+        this.repositoryContentProviders = providers;
+    }
+
+    public List<RepositoryContentProvider> getRepositoryContentProviders() {
+        return repositoryContentProviders;
+    }
 }
diff --git a/archiva-modules/archiva-base/archiva-repository-layer/src/main/java/org/apache/archiva/repository/RepositoryContentProvider.java b/archiva-modules/archiva-base/archiva-repository-layer/src/main/java/org/apache/archiva/repository/RepositoryContentProvider.java
new file mode 100644 (file)
index 0000000..8234449
--- /dev/null
@@ -0,0 +1,82 @@
+package org.apache.archiva.repository;
+
+/*
+ * 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.util.Set;
+
+/**
+ * A repository content provider creates repository content instances for specific repository types.
+ */
+public interface RepositoryContentProvider
+{
+    /**
+     * Returns true, if this content object supports the given layout otherwise, false.
+     * @param layout the layout string
+     * @return true, if layout is supported, otherwise false.
+     */
+    boolean supportsLayout(String layout);
+
+    /**
+     * Returns the repository types, this content object can be used for.
+     *
+     * @return all supported repository types.
+     */
+    Set<RepositoryType> getSupportedRepositoryTypes();
+
+
+    /**
+     * Returns true, if this content object supports the given repository type.
+     *
+     * @param type the type to check.
+     * @return true, if the type is supported, otherwise false.
+     */
+    boolean supports(RepositoryType type);
+
+    /**
+     * Creates a new instance of RemoteRepositoryContent. The returned instance should be initialized
+     * from the given repository data.
+     *
+     * @param repository the repository
+     * @return a repository content instance
+     * @throws RepositoryException if the layout is not supported, or a error occured during initialization
+     */
+    RemoteRepositoryContent createRemoteContent(RemoteRepository repository) throws RepositoryException;
+
+    /**
+     * Creates a new instance of ManagedRepositoryContent.
+     *
+     * @param repository the repository
+     * @return a new instance
+     * @throws RepositoryException if the layout is not supported, or a error occured during initialization
+     */
+    ManagedRepositoryContent createManagedContent(ManagedRepository repository) throws RepositoryException;
+
+    /**
+     * Creates a generic content object.
+     *
+     * @param repository the repository
+     * @param clazz  the content class
+     * @param <T> the generic type of the content
+     * @param <V> the generic type of the repository (must correspond to the content class)
+     * @return a new instance
+     * @throws RepositoryException if the clazz, or layout is not supported, or something went wrong during initialization
+     */
+    <T extends RepositoryContent, V extends Repository> T createContent(Class<T> clazz, V repository) throws RepositoryException;
+}
index 385cd16a6495d4e8b7965399cd6e3bb0ee508f3c..e1d4787b8f30d572e5afeae6a408fce37cf1f000 100644 (file)
@@ -191,7 +191,7 @@ public class RepositoryRegistry implements ConfigurationListener {
         }
         if ( repo instanceof EditableManagedRepository && repo.getContent() == null)
         {
-            ( (EditableManagedRepository) repo ).setContent( repositoryContentFactory.getManagedRepositoryContent( cfg, repo ) );
+            ( (EditableManagedRepository) repo ).setContent( repositoryContentFactory.getManagedRepositoryContent( repo ) );
         }
     }
 
@@ -265,7 +265,7 @@ public class RepositoryRegistry implements ConfigurationListener {
     {
         if ( repo instanceof EditableRemoteRepository && repo.getContent() == null)
         {
-            ( (EditableRemoteRepository) repo ).setContent( repositoryContentFactory.getRemoteRepositoryContent( cfg, repo ) );
+            ( (EditableRemoteRepository) repo ).setContent( repositoryContentFactory.getRemoteRepositoryContent( repo ) );
         }
     }
 
index adec67c1fd58983cda87bf174b4441b32bf011cd..fc6f65a223f0a5a4ea261386fd2182c0d4302cc4 100644 (file)
@@ -27,9 +27,6 @@
 
   <context:component-scan base-package="org.apache.archiva.repository.content.maven2" />
 
-  <alias name="managedRepositoryContent#maven" alias="managedRepositoryContent#default" />
-  <alias name="remoteRepositoryContent#maven" alias="remoteRepositoryContent#default" />
-
   <bean name="scheduler" class="org.apache.archiva.redback.components.scheduler.DefaultScheduler">
     <property name="properties">
       <props>
index 4b4b0dfa6261b08a45ff20f0a08fa819adb74840..47127b63dbc4ad3054db73e9592535bf802018f3 100755 (executable)
        default-lazy-init="false">
 
   <context:annotation-config/>
-  <context:component-scan base-package="org.apache.archiva.metadata.repository,org.apache.archiva.repository.content.maven2"/>
-
-  <alias name="managedRepositoryContent#maven" alias="managedRepositoryContent#default" />
-  <alias name="remoteRepositoryContent#maven" alias="remoteRepositoryContent#default" />
 
   <bean name="managedRepoAdmin#test" class="org.apache.archiva.mock.MockManagedRepositoryAdmin">
     <property name="archivaConfiguration" ref="archivaConfiguration#test-repository-scanning"/>
index d77b8453a5505df27ba8e250018d097c2b114352..ebf958bfc4f02717d60c1242a35607bcf58537a4 100644 (file)
@@ -34,9 +34,6 @@
   <context:component-scan
       base-package="org.apache.archiva.redback.keys,org.apache.archiva.rest.services.utils,org.apache.archiva.repository.content.maven2"/>
   
-  <alias name="managedRepositoryContent#maven" alias="managedRepositoryContent#default" />
-  <alias name="remoteRepositoryContent#maven" alias="remoteRepositoryContent#default" />
-
   <bean name="scheduler" class="org.apache.archiva.redback.components.scheduler.DefaultScheduler">
     <property name="properties">
       <props>
index fcc22aeccce2cd6539a111f048b4baa3790f806c..696514868fb6ce9db6e6104b7df6e868aa5ad916 100644 (file)
@@ -27,9 +27,6 @@
             http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd"
        default-lazy-init="true">
 
-  <alias name="managedRepositoryContent#maven" alias="managedRepositoryContent#default" />
-  <alias name="remoteRepositoryContent#maven" alias="remoteRepositoryContent#default" />
-
   <bean name="securitySystem#testable" class="org.apache.archiva.redback.system.DefaultSecuritySystem">
     <property name="userManager" ref="userManager#memory"/>
     <property name="keyManager" ref="keyManager#memory"/>
index cdec7b4fe19858f8061db45c94c25fdc1f6006b2..570eeb588035f3157b39563acdf98d1af3b5ae9c 100644 (file)
 
   <context:property-placeholder system-properties-mode="OVERRIDE"/>
 
-  <context:component-scan base-package="org.apache.archiva.repository.content.maven2" />
-  
-  <alias name="managedRepositoryContent#maven" alias="managedRepositoryContent#default" />
-  <alias name="remoteRepositoryContent#maven" alias="remoteRepositoryContent#default" />
-
   <bean name="commons-configuration" class="org.apache.archiva.redback.components.registry.commons.CommonsConfigurationRegistry">
     <property name="properties">
       <value>
index 7388de11deddd3d562e7bbd24fbc19e254a85719..7a06a884d1a8c5e3c871a3ba1cf6676a44408d77 100644 (file)
        default-lazy-init="true">
 
   <context:property-placeholder system-properties-mode="OVERRIDE"/>
-  <context:component-scan base-package="org.apache.archiva.repository.content.maven2" />
-
-  <alias name="managedRepositoryContent#maven" alias="managedRepositoryContent#default" />
-  <alias name="remoteRepositoryContent#maven" alias="remoteRepositoryContent#default" />
 
 
   <bean name="commons-configuration" class="org.apache.archiva.redback.components.registry.commons.CommonsConfigurationRegistry">
index e35f0ac7aaa73973534b937ed1c6a5ec94924dfa..5f9f77153e7990b096db4ecbfffca611bf56eae8 100644 (file)
   <context:property-placeholder system-properties-mode="OVERRIDE"/>
 
   <context:annotation-config/>
-  <context:component-scan base-package="org.apache.archiva.webtest.memory,org.apache.archiva.repository.content.maven2"/>
-
-  <alias name="managedRepositoryContent#maven" alias="managedRepositoryContent#default" />
-  <alias name="remoteRepositoryContent#maven" alias="remoteRepositoryContent#default" />
-
+  <context:component-scan base-package="org.apache.archiva.webtest.memory"/>
 
   <alias name="repositorySessionFactory#test" alias="repositorySessionFactory"/>
 
index d7083d210dce04cc5ede4ca89d8c1c3f7c27d0a8..d62446b45286b0daa887fb98b1209dce779f60a5 100644 (file)
@@ -29,9 +29,7 @@
 
   <context:annotation-config/>
   <context:component-scan
-      base-package="org.apache.archiva.redback.keys,org.apache.archiva.rest.services.utils,org.apache.archiva.repository.content.maven2"/>
-  <alias name="managedRepositoryContent#maven" alias="managedRepositoryContent#default" />
-  <alias name="remoteRepositoryContent#maven" alias="remoteRepositoryContent#default" />
+      base-package="org.apache.archiva.redback.keys,org.apache.archiva.rest.services.utils"/>
 
   <bean name="scheduler" class="org.apache.archiva.redback.components.scheduler.DefaultScheduler">
     <property name="properties">
index 7eb96452ca133d8406656eaf8124ff666bf987c9..f29dbcb16dc2a23a9c8341a014a0486838aa7b8f 100644 (file)
   </bean>
   -->
 
-  <alias name="managedRepositoryContent#maven" alias="managedRepositoryContent#default" />
-  <alias name="remoteRepositoryContent#maven" alias="remoteRepositoryContent#default" />
-
-
   <alias name="repositorySessionFactory#jcr" alias="repositorySessionFactory"/>
 
   <bean name="TestRepositorySessionFactoryBean" class="org.apache.archiva.TestRepositorySessionFactoryBean">
index ba1fdebd8f76d41590311a9edf8208a98d8a9da0..1c56a04afbd5945652ec3340ec4969056d6b9b95 100644 (file)
@@ -31,13 +31,22 @@ import org.apache.archiva.common.plexusbridge.PlexusSisuBridge;
 import org.apache.archiva.common.plexusbridge.PlexusSisuBridgeException;
 import org.apache.archiva.configuration.ArchivaConfiguration;
 import org.apache.archiva.configuration.Configuration;
+import org.apache.archiva.configuration.FileTypes;
 import org.apache.archiva.configuration.RepositoryGroupConfiguration;
+import org.apache.archiva.metadata.repository.storage.maven2.ArtifactMappingProvider;
 import org.apache.archiva.proxy.DefaultRepositoryProxyConnectors;
 import org.apache.archiva.proxy.model.ProxyFetchResult;
 import org.apache.archiva.repository.EditableManagedRepository;
 import org.apache.archiva.repository.ManagedRepositoryContent;
+import org.apache.archiva.repository.RemoteRepository;
+import org.apache.archiva.repository.RemoteRepositoryContent;
+import org.apache.archiva.repository.Repository;
+import org.apache.archiva.repository.RepositoryContent;
 import org.apache.archiva.repository.RepositoryContentFactory;
+import org.apache.archiva.repository.RepositoryContentProvider;
+import org.apache.archiva.repository.RepositoryException;
 import org.apache.archiva.repository.RepositoryRegistry;
+import org.apache.archiva.repository.RepositoryType;
 import org.apache.archiva.repository.content.maven2.ManagedDefaultRepositoryContent;
 import org.apache.archiva.repository.content.maven2.RepositoryRequest;
 import org.apache.archiva.test.utils.ArchivaSpringJUnit4ClassRunner;
@@ -62,8 +71,10 @@ import java.io.IOException;
 import java.nio.file.Path;
 import java.nio.file.Paths;
 import java.util.ArrayList;
+import java.util.HashSet;
 import java.util.List;
 import java.util.Locale;
+import java.util.Set;
 
 import static org.easymock.EasyMock.*;
 
@@ -128,6 +139,12 @@ public class ArchivaDavResourceFactoryTest
     @Inject
     DefaultRepositoryGroupAdmin defaultRepositoryGroupAdmin;
 
+    @Inject
+    List<? extends ArtifactMappingProvider> artifactMappingProviders;
+
+    @Inject
+    FileTypes fileTypes;
+
 
     @Before
     @Override
@@ -215,7 +232,7 @@ public class ArchivaDavResourceFactoryTest
     private ManagedRepositoryContent createManagedRepositoryContent( String repoId )
         throws RepositoryAdminException
     {
-        ManagedRepositoryContent repoContent = new ManagedDefaultRepositoryContent();
+        ManagedRepositoryContent repoContent = new ManagedDefaultRepositoryContent(artifactMappingProviders, fileTypes);
         org.apache.archiva.repository.ManagedRepository repo = repositoryRegistry.getManagedRepository( repoId );
         repoContent.setRepository( repo );
         if (repo!=null && repo instanceof EditableManagedRepository)
@@ -225,6 +242,52 @@ public class ArchivaDavResourceFactoryTest
         return repoContent;
     }
 
+    private RepositoryContentProvider createRepositoryContentProvider(ManagedRepositoryContent content) {
+        Set<RepositoryType> TYPES = new HashSet<>(  );
+        TYPES.add(RepositoryType.MAVEN);
+        return new RepositoryContentProvider( )
+        {
+
+
+            @Override
+            public boolean supportsLayout( String layout )
+            {
+                return true;
+            }
+
+            @Override
+            public Set<RepositoryType> getSupportedRepositoryTypes( )
+            {
+                return TYPES;
+            }
+
+            @Override
+            public boolean supports( RepositoryType type )
+            {
+                return true;
+            }
+
+            @Override
+            public RemoteRepositoryContent createRemoteContent( RemoteRepository repository ) throws RepositoryException
+            {
+                return null;
+            }
+
+            @Override
+            public ManagedRepositoryContent createManagedContent( org.apache.archiva.repository.ManagedRepository repository ) throws RepositoryException
+            {
+                content.setRepository( repository );
+                return content;
+            }
+
+            @Override
+            public <T extends RepositoryContent, V extends Repository> T createContent( Class<T> clazz, V repository ) throws RepositoryException
+            {
+                return null;
+            }
+        };
+    }
+
     @After
     @Override
     public void tearDown()
@@ -580,7 +643,10 @@ public class ArchivaDavResourceFactoryTest
     {
         ManagedRepositoryContent legacyRepo = createManagedRepositoryContent( LEGACY_REPO );
         ConfigurableListableBeanFactory beanFactory = ((ConfigurableApplicationContext) applicationContext).getBeanFactory();
-        beanFactory.registerSingleton("managedRepositoryContent#legacy", legacyRepo);
+        RepositoryContentProvider provider = createRepositoryContentProvider(legacyRepo );
+        beanFactory.registerSingleton("repositoryContentProvider#legacy", provider);
+        RepositoryContentFactory repoContentFactory = applicationContext.getBean( "repositoryContentFactory#default", RepositoryContentFactory.class );
+        repoContentFactory.getRepositoryContentProviders().add(provider);
         defaultManagedRepositoryAdmin.addManagedRepository(
             createManagedRepository( LEGACY_REPO, Paths.get( "target/test-classes/" + LEGACY_REPO ).toString(),
                                      "legacy" ), false, null );
index 69381609910b0ecc389c77cc9fd7ada46d4fc272..9f38b827d6fff943bcf1b346b391660ecad59346 100644 (file)
 
   <context:annotation-config/>
   <context:component-scan
-      base-package="org.apache.archiva.redback.keys,org.apache.archiva.webdav,org.apache.archiva.metadata.repository,org.apache.archiva.webdav.util,org.apache.archiva.common.plexusbridge,org.apache.archiva.repository.content.maven2,org.apache.archiva.repository"/>
-
-  <alias name="managedRepositoryContent#maven" alias="managedRepositoryContent#default" />
-  <alias name="remoteRepositoryContent#maven" alias="remoteRepositoryContent#default" />
+      base-package="org.apache.archiva.redback.keys,org.apache.archiva.webdav,org.apache.archiva.metadata.repository,org.apache.archiva.webdav.util,org.apache.archiva.common.plexusbridge"/>
 
   <bean name="scheduler" class="org.apache.archiva.redback.components.scheduler.DefaultScheduler">
     <property name="properties">
index 28f59f75d94fb69ad9f4caf1035898bc1e4b87cc..fba97070505f82e97a82dff9d91050e2816dbd00 100644 (file)
   <context:property-placeholder system-properties-mode="OVERRIDE"/>
 
   <context:annotation-config/>
-  <context:component-scan base-package="org.apache.archiva.redback.keys,org.apache.archiva.webdav,org.apache.archiva.metadata.repository,org.apache.archiva.repository,org.apache.archiva.repository.content.maven2"/>
-
-  <alias name="managedRepositoryContent#maven" alias="managedRepositoryContent#default" />
-  <alias name="remoteRepositoryContent#maven" alias="remoteRepositoryContent#default" />
+  <context:component-scan base-package="org.apache.archiva.redback.keys,org.apache.archiva.webdav,org.apache.archiva.metadata.repository" />
 
   <bean name="scheduler" class="org.apache.archiva.redback.components.scheduler.DefaultScheduler">
     <property name="properties">
index 4f8b80cbd638c8d0cb88e69f7933cfaf4d0e8a23..a15b5d76c99edc9b3634aa0fb13248461282da1c 100644 (file)
@@ -20,6 +20,7 @@ package org.apache.archiva.repository.content.maven2;
  */
 
 import org.apache.archiva.common.utils.VersionUtil;
+import org.apache.archiva.configuration.FileTypes;
 import org.apache.archiva.metadata.repository.storage.RepositoryPathTranslator;
 import org.apache.archiva.metadata.repository.storage.maven2.ArtifactMappingProvider;
 import org.apache.archiva.metadata.repository.storage.maven2.Maven2RepositoryPathTranslator;
@@ -27,6 +28,7 @@ import org.apache.archiva.model.ArchivaArtifact;
 import org.apache.archiva.model.ArtifactReference;
 import org.apache.archiva.model.ProjectReference;
 import org.apache.archiva.model.VersionedReference;
+import org.apache.archiva.repository.RepositoryContent;
 import org.apache.archiva.repository.content.PathParser;
 import org.apache.archiva.repository.layout.LayoutException;
 import org.apache.commons.lang.StringUtils;
@@ -40,8 +42,10 @@ import java.util.List;
 /**
  * AbstractDefaultRepositoryContent - common methods for working with default (maven 2) layout.
  */
-public abstract class AbstractDefaultRepositoryContent
+public abstract class AbstractDefaultRepositoryContent implements RepositoryContent
 {
+
+
     protected Logger log = LoggerFactory.getLogger( getClass() );
 
     public static final String MAVEN_METADATA = "maven-metadata.xml";
@@ -56,16 +60,19 @@ public abstract class AbstractDefaultRepositoryContent
 
     private PathParser defaultPathParser = new DefaultPathParser();
 
+
+
     /**
      *
      */
-    @Inject
     protected List<? extends ArtifactMappingProvider> artifactMappingProviders;
 
-    @PostConstruct
-    protected void initialize()
-    {
-        // no op
+    AbstractDefaultRepositoryContent(List<? extends ArtifactMappingProvider> artifactMappingProviders) {
+        this.artifactMappingProviders = artifactMappingProviders;
+    }
+
+    public void setArtifactMappingProviders(List<? extends ArtifactMappingProvider> artifactMappingProviders) {
+        this.artifactMappingProviders = artifactMappingProviders;
     }
 
     public ArtifactReference toArtifactReference( String path )
index 298aa5d18c3d6475db3f42e83a5709deab012283..847dd7a6be7d589461949a8f3168bf24661bff6e 100644 (file)
@@ -21,6 +21,7 @@ package org.apache.archiva.repository.content.maven2;
 
 import org.apache.archiva.common.utils.PathUtil;
 import org.apache.archiva.configuration.FileTypes;
+import org.apache.archiva.metadata.repository.storage.maven2.ArtifactMappingProvider;
 import org.apache.archiva.metadata.repository.storage.maven2.DefaultArtifactMappingProvider;
 import org.apache.archiva.model.ArchivaArtifact;
 import org.apache.archiva.model.ArtifactReference;
@@ -31,11 +32,7 @@ import org.apache.archiva.repository.ManagedRepositoryContent;
 import org.apache.archiva.repository.RepositoryException;
 import org.apache.archiva.repository.layout.LayoutException;
 import org.apache.commons.lang.StringUtils;
-import org.springframework.context.annotation.Scope;
-import org.springframework.stereotype.Service;
 
-import javax.inject.Inject;
-import javax.inject.Named;
 import java.io.IOException;
 import java.net.URI;
 import java.nio.file.Files;
@@ -43,6 +40,7 @@ import java.nio.file.Path;
 import java.nio.file.Paths;
 import java.util.Collections;
 import java.util.HashSet;
+import java.util.List;
 import java.util.Objects;
 import java.util.Set;
 import java.util.stream.Collectors;
@@ -51,22 +49,29 @@ import java.util.stream.Stream;
 /**
  * ManagedDefaultRepositoryContent
  */
-@Service ("managedRepositoryContent#maven")
-@Scope ("prototype")
 public class ManagedDefaultRepositoryContent
     extends AbstractDefaultRepositoryContent
     implements ManagedRepositoryContent
 {
-    @Inject
-    @Named ( "fileTypes" )
+
     private FileTypes filetypes;
 
+    public void setFileTypes(FileTypes fileTypes) {
+        this.filetypes = fileTypes;
+    }
+
+
+
     private org.apache.archiva.repository.ManagedRepository repository;
 
-    public ManagedDefaultRepositoryContent()
+    public ManagedDefaultRepositoryContent(FileTypes fileTypes) {
+        super(Collections.singletonList( new DefaultArtifactMappingProvider() ));
+        setFileTypes( fileTypes );
+    }
+    public ManagedDefaultRepositoryContent( List<? extends ArtifactMappingProvider> artifactMappingProviders, FileTypes fileTypes )
     {
-        // default to use if there are none supplied as components
-        this.artifactMappingProviders = Collections.singletonList( new DefaultArtifactMappingProvider() );
+        super(artifactMappingProviders==null ? Collections.singletonList( new DefaultArtifactMappingProvider() ) : artifactMappingProviders);
+        setFileTypes( fileTypes );
     }
 
     @Override
diff --git a/archiva-modules/plugins/maven2-repository/src/main/java/org/apache/archiva/repository/content/maven2/MavenContentProvider.java b/archiva-modules/plugins/maven2-repository/src/main/java/org/apache/archiva/repository/content/maven2/MavenContentProvider.java
new file mode 100644 (file)
index 0000000..423c4b1
--- /dev/null
@@ -0,0 +1,123 @@
+package org.apache.archiva.repository.content.maven2;
+
+/*
+ * 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.archiva.configuration.FileTypes;
+import org.apache.archiva.metadata.repository.storage.maven2.ArtifactMappingProvider;
+import org.apache.archiva.repository.ManagedRepository;
+import org.apache.archiva.repository.ManagedRepositoryContent;
+import org.apache.archiva.repository.RemoteRepository;
+import org.apache.archiva.repository.RemoteRepositoryContent;
+import org.apache.archiva.repository.Repository;
+import org.apache.archiva.repository.RepositoryContent;
+import org.apache.archiva.repository.RepositoryContentProvider;
+import org.apache.archiva.repository.RepositoryException;
+import org.apache.archiva.repository.RepositoryType;
+import org.springframework.stereotype.Service;
+
+import javax.inject.Inject;
+import javax.inject.Named;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+/**
+ * Maven implementation of the repository content provider. Only default layout and
+ * maven repository types are supported.
+ */
+@Service("repositoryContentProvider#maven")
+public class MavenContentProvider implements RepositoryContentProvider
+{
+
+    @Inject
+    @Named( "fileTypes" )
+    private FileTypes filetypes;
+
+    @Inject
+    protected List<? extends ArtifactMappingProvider> artifactMappingProviders;
+
+
+    private static final Set<RepositoryType> REPOSITORY_TYPES = new HashSet<>(  );
+    static {
+        REPOSITORY_TYPES.add(RepositoryType.MAVEN);
+    }
+
+    @Override
+    public boolean supportsLayout( String layout )
+    {
+        return "default".equals( layout );
+    }
+
+    @Override
+    public Set<RepositoryType> getSupportedRepositoryTypes( )
+    {
+        return REPOSITORY_TYPES;
+    }
+
+    @Override
+    public boolean supports( RepositoryType type )
+    {
+        return type.equals( RepositoryType.MAVEN );
+    }
+
+    @Override
+    public RemoteRepositoryContent createRemoteContent( RemoteRepository repository ) throws RepositoryException
+    {
+        if (!supports( repository.getType() )) {
+            throw new RepositoryException( "Repository type "+repository.getType()+" is not supported by this implementation." );
+        }
+        if (!supportsLayout( repository.getLayout() )) {
+            throw new RepositoryException( "Repository layout "+repository.getLayout()+" is not supported by this implementation." );
+        }
+        RemoteDefaultRepositoryContent content = new RemoteDefaultRepositoryContent(artifactMappingProviders);
+        content.setRepository( repository );
+        return content;
+    }
+
+    @Override
+    public ManagedRepositoryContent createManagedContent( ManagedRepository repository ) throws RepositoryException
+    {
+        if (!supports( repository.getType() )) {
+            throw new RepositoryException( "Repository type "+repository.getType()+" is not supported by this implementation." );
+        }
+        if (!supportsLayout( repository.getLayout() )) {
+            throw new RepositoryException( "Repository layout "+repository.getLayout()+" is not supported by this implementation." );
+        }
+        ManagedDefaultRepositoryContent content = new ManagedDefaultRepositoryContent(artifactMappingProviders, filetypes);
+        content.setRepository( repository );
+        return content;
+    }
+
+    @Override
+    public <T extends RepositoryContent, V extends Repository> T createContent( Class<T> clazz, V repository ) throws RepositoryException
+    {
+        if (!supports( repository.getType() )) {
+            throw new RepositoryException( "Repository type "+repository.getType()+" is not supported by this implementation." );
+        }
+        if (repository instanceof ManagedRepository && ManagedRepositoryContent.class.isAssignableFrom( clazz ) ) {
+            return (T) this.createManagedContent( (ManagedRepository) repository );
+        } else if (repository instanceof RemoteRepository && RemoteRepository.class.isAssignableFrom( clazz )) {
+            return (T) this.createRemoteContent( (RemoteRepository) repository );
+        } else {
+            throw new RepositoryException( "Repository flavour is not supported: "+repository.getClass().getName() );
+        }
+    }
+
+}
index 2942c2348820dc3ba4eebcac430afd0cb18c8ec6..b9c2238fac76a098f7203e51ab970916a29355d5 100644 (file)
@@ -19,6 +19,7 @@ package org.apache.archiva.repository.content.maven2;
  * under the License.
  */
 
+import org.apache.archiva.metadata.repository.storage.maven2.ArtifactMappingProvider;
 import org.apache.archiva.model.ArtifactReference;
 import org.apache.archiva.model.RepositoryURL;
 import org.apache.archiva.repository.RemoteRepository;
@@ -27,17 +28,22 @@ import org.apache.archiva.repository.layout.LayoutException;
 import org.springframework.context.annotation.Scope;
 import org.springframework.stereotype.Service;
 
+import java.util.List;
+
 /**
  * RemoteDefaultRepositoryContent
  */
-@Service( "remoteRepositoryContent#maven" )
-@Scope( "prototype" )
 public class RemoteDefaultRepositoryContent
     extends AbstractDefaultRepositoryContent
     implements RemoteRepositoryContent
 {
     private RemoteRepository repository;
 
+
+    public RemoteDefaultRepositoryContent( List<? extends ArtifactMappingProvider> artifactMappingProviders ) {
+        super(artifactMappingProviders);
+    }
+
     @Override
     public String getId( )
     {
index 86749a224891b60daec194cc1501abf66f888102..41e62faa3debcc0e453d4d8c8a6130a6941cdb7d 100644 (file)
@@ -28,6 +28,7 @@ import org.apache.archiva.model.ProjectReference;
 import org.apache.archiva.model.VersionedReference;
 import org.apache.archiva.repository.EditableManagedRepository;
 import org.apache.archiva.repository.ManagedRepositoryContent;
+import org.apache.archiva.repository.content.maven2.ManagedDefaultRepositoryContent;
 import org.apache.archiva.repository.layout.LayoutException;
 import org.apache.archiva.repository.maven2.MavenManagedRepository;
 import org.junit.Before;
@@ -52,9 +53,7 @@ import static org.junit.Assert.fail;
 public class ManagedDefaultRepositoryContentTest
     extends AbstractDefaultRepositoryContentTestCase
 {
-    @Inject
-    @Named ( "managedRepositoryContent#default" )
-    private ManagedRepositoryContent repoContent;
+    private ManagedDefaultRepositoryContent repoContent;
 
     @Inject
     FileTypes fileTypes;
@@ -63,6 +62,9 @@ public class ManagedDefaultRepositoryContentTest
     @Named ( "archivaConfiguration#default" )
     ArchivaConfiguration archivaConfiguration;
 
+    @Inject
+    List<? extends ArtifactMappingProvider> artifactMappingProviders;
+
     @Before
     public void setUp()
         throws Exception
@@ -77,6 +79,7 @@ public class ManagedDefaultRepositoryContentTest
 
         fileTypes.afterConfigurationChange( null, "fileType", null );
 
+        repoContent = new ManagedDefaultRepositoryContent(artifactMappingProviders, fileTypes);
         //repoContent = (ManagedRepositoryContent) lookup( ManagedRepositoryContent.class, "default" );
         repoContent.setRepository( repository );
     }
index da3f4095f0a412a60ff9431b99835e3934d2e95a..0a1c03acfa73332a80eb5b8e8d55924e5668feea 100644 (file)
@@ -22,11 +22,13 @@ package org.apache.archiva.metadata.repository.storage.maven2;
 import org.apache.archiva.model.ArtifactReference;
 import org.apache.archiva.repository.RemoteRepository;
 import org.apache.archiva.repository.RemoteRepositoryContent;
+import org.apache.archiva.repository.content.maven2.RemoteDefaultRepositoryContent;
 import org.apache.archiva.repository.layout.LayoutException;
 import org.junit.Before;
 
 import javax.inject.Inject;
 import javax.inject.Named;
+import java.util.List;
 
 /**
  * RemoteDefaultRepositoryContentTest
@@ -34,8 +36,10 @@ import javax.inject.Named;
 public class RemoteDefaultRepositoryContentTest
     extends AbstractDefaultRepositoryContentTestCase
 {
+
     @Inject
-    @Named ( "remoteRepositoryContent#default" )
+    private List<? extends ArtifactMappingProvider> artifactMappingProviders;
+
     private RemoteRepositoryContent repoContent;
 
     @Before
@@ -45,6 +49,7 @@ public class RemoteDefaultRepositoryContentTest
         RemoteRepository repository =
             createRemoteRepository( "testRemoteRepo", "Unit Test Remote Repo", "http://repo1.maven.org/maven2/" );
 
+        repoContent = new RemoteDefaultRepositoryContent(artifactMappingProviders);
         //repoContent = (RemoteRepositoryContent) lookup( RemoteRepositoryContent.class, "default" );
         repoContent.setRepository( repository );
     }
index 1a6cf7cf9e5f8af6ae7192809b63b030c3a14330..98091f3f4f9fb34faf2765fd5e8b8d71160ae33c 100644 (file)
@@ -73,9 +73,9 @@ public abstract class AbstractRepositoryLayerTestCase
         repo.setLocation( location.toAbsolutePath().toUri() );
         repo.setLayout( layout );
 
+        RepositoryContentProvider provider = applicationContext.getBean( "repositoryContentProvider#maven", RepositoryContentProvider.class );
         ManagedRepositoryContent repoContent =
-            applicationContext.getBean( "managedRepositoryContent#" + layout, ManagedRepositoryContent.class );
-        repoContent.setRepository( repo );
+            provider.createManagedContent( repo );
 
         return repoContent;
     }
@@ -87,9 +87,9 @@ public abstract class AbstractRepositoryLayerTestCase
         repo.setLocation( new URI( url ) );
         repo.setLayout( layout );
 
+        RepositoryContentProvider provider = applicationContext.getBean( "repositoryContentProvider#maven", RepositoryContentProvider.class );
         RemoteRepositoryContent repoContent =
-            applicationContext.getBean( "remoteRepositoryContent#" + layout, RemoteRepositoryContent.class );
-        repoContent.setRepository( repo );
+            provider.createRemoteContent( repo );
 
         return repoContent;
     }
index 17068d642912da2f2b029866ce47bbf3b0b993a9..928482b187de2d17efe9cce7c97dbacf4e7149ca 100644 (file)
@@ -23,6 +23,7 @@ import org.apache.archiva.common.utils.FileUtils;
 import org.apache.archiva.configuration.ArchivaConfiguration;
 import org.apache.archiva.model.ArtifactReference;
 import org.apache.archiva.repository.ManagedRepositoryContent;
+import org.apache.archiva.repository.RepositoryContentProvider;
 import org.apache.archiva.repository.layout.LayoutException;
 import org.apache.archiva.repository.maven2.MavenManagedRepository;
 import org.apache.archiva.test.utils.ArchivaSpringJUnit4ClassRunner;
@@ -518,9 +519,10 @@ public class RepositoryRequestTest
         repo.setLocation( location.toAbsolutePath().toUri() );
         repo.setLayout( layout );
 
+        RepositoryContentProvider provider = applicationContext.getBean( "repositoryContentProvider#maven", RepositoryContentProvider.class );
+
         ManagedRepositoryContent repoContent =
-            applicationContext.getBean( "managedRepositoryContent#" + layout, ManagedRepositoryContent.class );
-        repoContent.setRepository( repo );
+            provider.createManagedContent( repo );
 
         return repoContent;
     }
index 45164862e220bfd3d08c2a9d42c4e989faeb4556..650f49fff7d71d78540c0a376bee2575845be440 100644 (file)
@@ -32,6 +32,7 @@ import org.apache.archiva.policies.SnapshotsPolicy;
 import org.apache.archiva.repository.AbstractRepositoryLayerTestCase;
 import org.apache.archiva.repository.ManagedRepositoryContent;
 import org.apache.archiva.repository.RemoteRepositoryContent;
+import org.apache.archiva.repository.RepositoryContentProvider;
 import org.apache.archiva.repository.layout.LayoutException;
 import org.apache.archiva.repository.maven2.MavenManagedRepository;
 import org.apache.commons.io.FileUtils;
@@ -365,9 +366,11 @@ public class MetadataToolsTest
 
         MavenManagedRepository repo =
             createRepository( "test-repo", "Test Repository: " + name.getMethodName(), repoRootDir );
+
+        RepositoryContentProvider provider = applicationContext.getBean( "repositoryContentProvider#maven", RepositoryContentProvider.class );
+
         ManagedRepositoryContent repoContent =
-            applicationContext.getBean( "managedRepositoryContent#default", ManagedRepositoryContent.class );
-        repoContent.setRepository( repo );
+            provider.createManagedContent( repo );
 
         Set<String> testedVersionSet = tools.gatherSnapshotVersions( repoContent, reference );
 
@@ -618,9 +621,10 @@ public class MetadataToolsTest
         MavenManagedRepository repoConfig =
             createRepository( "test-repo", "Test Repository: " + name.getMethodName(), repoRoot );
 
+        RepositoryContentProvider provider = applicationContext.getBean( "repositoryContentProvider#maven", RepositoryContentProvider.class );
+
         ManagedRepositoryContent repoContent =
-            applicationContext.getBean( "managedRepositoryContent#default", ManagedRepositoryContent.class );
-        repoContent.setRepository( repoConfig );
+            provider.createManagedContent( repoConfig );
         return repoContent;
     }
 
index 8b00cdcdf7cae64a3f286cee829fc3df32e0a0a4..b5de647ad38b40288853a190fa183be108ae6f16 100644 (file)
@@ -29,8 +29,6 @@
   <context:annotation-config/>
   <context:component-scan base-package="org.apache.archiva.metadata.repository.storage.maven2.conf,org.apache.archiva.repository.content.maven2"/>
 
-  <alias name="managedRepositoryContent#maven" alias="managedRepositoryContent#default" />
-  <alias name="remoteRepositoryContent#maven" alias="remoteRepositoryContent#default" />
 
 
 </beans>
\ No newline at end of file
index 1601f2ae4646c39a7f608d7f922b593f4d3f9011..3f28158ae1b6dcafebfdac0e1e1b4a2e0838b33d 100644 (file)
   <alias name="archivaConfiguration#repo-request-test" alias="archivaConfiguration#default"/>
   <alias name="archivaConfiguration#repo-request-test" alias="archivaConfiguration"/>
 
-  <alias name="managedRepositoryContent#maven" alias="managedRepositoryContent#default" />
-  <alias name="remoteRepositoryContent#maven" alias="remoteRepositoryContent#default" />
-
-
   <bean name="registry#configured" class="org.apache.archiva.redback.components.registry.commons.CommonsConfigurationRegistry">
     <property name="properties">
       <value>
index 5f445d75a7f00fd99e600dd22db16fab204cdb5a..197d7e409baf9eacedd9b7e1ed5cec1ec2355ec2 100644 (file)
@@ -33,7 +33,6 @@
 
   <alias name="archivaConfiguration#test" alias="archivaConfiguration#default"/>
   <alias name="archivaConfiguration#test" alias="archivaConfiguration"/>
-  <alias name="managedRepositoryContent#maven" alias="managedRepositoryContent#default" />
 
   <alias name="metadataResolver#test" alias="metadataResolver#default"/>
 </beans>
\ No newline at end of file