You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@archiva.apache.org by ma...@apache.org on 2017/11/08 22:57:11 UTC

[3/4] archiva git commit: Rearranging modules and adding indexer api

http://git-wip-us.apache.org/repos/asf/archiva/blob/e2cdbc2b/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/indexer/search/SearchFields.java
----------------------------------------------------------------------
diff --git a/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/indexer/search/SearchFields.java b/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/indexer/search/SearchFields.java
new file mode 100644
index 0000000..e5844a7
--- /dev/null
+++ b/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/indexer/search/SearchFields.java
@@ -0,0 +1,324 @@
+package org.apache.archiva.indexer.search;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/*
+ * 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.
+ */
+
+public class SearchFields
+{
+    /**
+     * groupId
+     */
+    private String groupId;
+
+    /**
+     * artifactId
+     */
+    private String artifactId;
+
+    /**
+     * version
+     */
+    private String version;
+
+    /**
+     * packaging (jar, war, pom, etc.)
+     */
+    private String packaging;
+
+    /**
+     * class name or package name
+     */
+    private String className;
+
+    /**
+     * repositories
+     */
+    private List<String> repositories = new ArrayList<>();
+
+
+    /**
+     * contains osgi metadata Bundle-Version if available
+     *
+     * @since 1.4-M1
+     */
+    private String bundleVersion;
+
+    /**
+     * contains osgi metadata Bundle-SymbolicName if available
+     *
+     * @since 1.4-M1
+     */
+    private String bundleSymbolicName;
+
+    /**
+     * contains osgi metadata Export-Package if available
+     *
+     * @since 1.4-M1
+     */
+    private String bundleExportPackage;
+
+    /**
+     * contains osgi metadata import package if available
+     *
+     * @since 1.4-M1
+     */
+    private String bundleImportPackage;
+
+    /**
+     * contains osgi metadata name if available
+     *
+     * @since 1.4-M1
+     */
+    private String bundleName;
+
+    /**
+     * contains osgi metadata Export-Service if available
+     *
+     * @since 1.4-M1
+     */
+    private String bundleExportService;
+
+
+    /**
+     * contains osgi metadata Require-Bundle if available
+     *
+     * @since 1.4-M3
+     */
+    private String bundleRequireBundle;
+
+    /**
+     * not return artifact with file extension pom
+     *
+     * @since 1.4-M2
+     */
+    private boolean includePomArtifacts = false;
+
+    private String classifier;
+
+    /**
+     * we use exact String matching search
+     *
+     * @since 2.1.0
+     */
+    private boolean exactSearch = false;
+
+    public SearchFields()
+    {
+        // no op
+    }
+
+    public SearchFields( String groupId, String artifactId, String version, String packaging, String className,
+                         List<String> repositories )
+    {
+        this.groupId = groupId;
+        this.artifactId = artifactId;
+        this.version = version;
+        this.packaging = packaging;
+        this.className = className;
+        this.repositories = repositories;
+    }
+
+    public String getGroupId()
+    {
+        return groupId;
+    }
+
+    public void setGroupId( String groupId )
+    {
+        this.groupId = groupId;
+    }
+
+    public String getArtifactId()
+    {
+        return artifactId;
+    }
+
+    public void setArtifactId( String artifactId )
+    {
+        this.artifactId = artifactId;
+    }
+
+    public String getVersion()
+    {
+        return version;
+    }
+
+    public void setVersion( String version )
+    {
+        this.version = version;
+    }
+
+    public String getPackaging()
+    {
+        return packaging;
+    }
+
+    public void setPackaging( String packaging )
+    {
+        this.packaging = packaging;
+    }
+
+    public String getClassName()
+    {
+        return className;
+    }
+
+    public void setClassName( String className )
+    {
+        this.className = className;
+    }
+
+    public List<String> getRepositories()
+    {
+        return repositories;
+    }
+
+    public void setRepositories( List<String> repositories )
+    {
+        this.repositories = repositories;
+    }
+
+
+    public String getBundleVersion()
+    {
+        return bundleVersion;
+    }
+
+    public void setBundleVersion( String bundleVersion )
+    {
+        this.bundleVersion = bundleVersion;
+    }
+
+    public String getBundleSymbolicName()
+    {
+        return bundleSymbolicName;
+    }
+
+    public void setBundleSymbolicName( String bundleSymbolicName )
+    {
+        this.bundleSymbolicName = bundleSymbolicName;
+    }
+
+    public String getBundleExportPackage()
+    {
+        return bundleExportPackage;
+    }
+
+    public void setBundleExportPackage( String bundleExportPackage )
+    {
+        this.bundleExportPackage = bundleExportPackage;
+    }
+
+    public String getBundleExportService()
+    {
+        return bundleExportService;
+    }
+
+    public void setBundleExportService( String bundleExportService )
+    {
+        this.bundleExportService = bundleExportService;
+    }
+
+    public String getClassifier()
+    {
+        return classifier;
+    }
+
+    public void setClassifier( String classifier )
+    {
+        this.classifier = classifier;
+    }
+
+    public String getBundleImportPackage()
+    {
+        return bundleImportPackage;
+    }
+
+    public void setBundleImportPackage( String bundleImportPackage )
+    {
+        this.bundleImportPackage = bundleImportPackage;
+    }
+
+    public String getBundleName()
+    {
+        return bundleName;
+    }
+
+    public void setBundleName( String bundleName )
+    {
+        this.bundleName = bundleName;
+    }
+
+    public boolean isIncludePomArtifacts()
+    {
+        return includePomArtifacts;
+    }
+
+    public void setIncludePomArtifacts( boolean includePomArtifacts )
+    {
+        this.includePomArtifacts = includePomArtifacts;
+    }
+
+    public String getBundleRequireBundle()
+    {
+        return bundleRequireBundle;
+    }
+
+    public void setBundleRequireBundle( String bundleRequireBundle )
+    {
+        this.bundleRequireBundle = bundleRequireBundle;
+    }
+
+    public boolean isExactSearch()
+    {
+        return exactSearch;
+    }
+
+    public void setExactSearch( boolean exactSearch )
+    {
+        this.exactSearch = exactSearch;
+    }
+
+    @Override
+    public String toString()
+    {
+        final StringBuilder sb = new StringBuilder();
+        sb.append( "SearchFields" );
+        sb.append( "{groupId='" ).append( groupId ).append( '\'' );
+        sb.append( ", artifactId='" ).append( artifactId ).append( '\'' );
+        sb.append( ", version='" ).append( version ).append( '\'' );
+        sb.append( ", packaging='" ).append( packaging ).append( '\'' );
+        sb.append( ", className='" ).append( className ).append( '\'' );
+        sb.append( ", repositories=" ).append( repositories );
+        sb.append( ", bundleVersion='" ).append( bundleVersion ).append( '\'' );
+        sb.append( ", bundleSymbolicName='" ).append( bundleSymbolicName ).append( '\'' );
+        sb.append( ", bundleExportPackage='" ).append( bundleExportPackage ).append( '\'' );
+        sb.append( ", bundleImportPackage='" ).append( bundleImportPackage ).append( '\'' );
+        sb.append( ", bundleName='" ).append( bundleName ).append( '\'' );
+        sb.append( ", bundleExportService='" ).append( bundleExportService ).append( '\'' );
+        sb.append( ", bundleRequireBundle='" ).append( bundleRequireBundle ).append( '\'' );
+        sb.append( ", includePomArtifacts=" ).append( includePomArtifacts );
+        sb.append( ", classifier='" ).append( classifier ).append( '\'' );
+        sb.append( '}' );
+        return sb.toString();
+    }
+}

http://git-wip-us.apache.org/repos/asf/archiva/blob/e2cdbc2b/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/indexer/search/SearchResultHit.java
----------------------------------------------------------------------
diff --git a/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/indexer/search/SearchResultHit.java b/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/indexer/search/SearchResultHit.java
new file mode 100644
index 0000000..a493431
--- /dev/null
+++ b/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/indexer/search/SearchResultHit.java
@@ -0,0 +1,435 @@
+package org.apache.archiva.indexer.search;
+
+/*
+ * 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.ArrayList;
+import java.util.List;
+
+/**
+ * SearchResultHit
+ *
+ */
+public class SearchResultHit
+{
+    // The (optional) context for this result.
+    private String context;
+
+    // Basic hit, direct to non-artifact resource.
+    private String url;
+
+    // Advanced hit, reference to groupId.
+    private String groupId;
+
+    //  Advanced hit, reference to artifactId.
+    private String artifactId;
+
+    private String repositoryId = "";
+
+    private List<String> versions = new ArrayList<>();
+
+    private String packaging;
+
+    /**
+     * Plugin goal prefix (only if packaging is "maven-plugin")
+     */
+    private String prefix;
+
+    /**
+     * Plugin goals (only if packaging is "maven-plugin")
+     */
+    private List<String> goals;
+
+    /**
+     * contains osgi metadata Bundle-Version if available
+     *
+     * @since 1.4-M1
+     */
+    private String bundleVersion;
+
+    /**
+     * contains osgi metadata Bundle-SymbolicName if available
+     *
+     * @since 1.4-M1
+     */
+    private String bundleSymbolicName;
+
+    /**
+     * contains osgi metadata Export-Package if available
+     *
+     * @since 1.4-M1
+     */
+    private String bundleExportPackage;
+
+    /**
+     * contains osgi metadata Export-Service if available
+     *
+     * @since 1.4-M1
+     */
+    private String bundleExportService;
+
+    /**
+     * contains osgi metadata Bundle-Description if available
+     *
+     * @since 1.4-M1
+     */
+    private String bundleDescription;
+
+    /**
+     * contains osgi metadata Bundle-Name if available
+     *
+     * @since 1.4-M1
+     */
+    private String bundleName;
+
+    /**
+     * contains osgi metadata Bundle-License if available
+     *
+     * @since 1.4-M1
+     */
+    private String bundleLicense;
+
+    /**
+     * contains osgi metadata Bundle-DocURL if available
+     *
+     * @since 1.4-M1
+     */
+    private String bundleDocUrl;
+
+    /**
+     * contains osgi metadata Import-Package if available
+     *
+     * @since 1.4-M1
+     */
+    private String bundleImportPackage;
+
+    /**
+     * contains osgi metadata Require-Bundle if available
+     *
+     * @since 1.4-M1
+     */
+    private String bundleRequireBundle;
+
+    private String classifier;
+
+    /**
+     * file extension of the search result
+     * @since 1.4-M2
+     */
+    private String fileExtension;
+
+    public String getContext()
+    {
+        return context;
+    }
+
+    public void setContext( String context )
+    {
+        this.context = context;
+    }
+
+    public String getUrl()
+    {
+        return url;
+    }
+
+    public void setUrl( String url )
+    {
+        this.url = url;
+    }
+
+    public String getUrlFilename()
+    {
+        return this.url.substring( this.url.lastIndexOf( '/' ) );
+    }
+
+    public String getArtifactId()
+    {
+        return artifactId;
+    }
+
+    public void setArtifactId( String artifactId )
+    {
+        this.artifactId = artifactId;
+    }
+
+    public String getGroupId()
+    {
+        return groupId;
+    }
+
+    public void setGroupId( String groupId )
+    {
+        this.groupId = groupId;
+    }
+
+    public List<String> getVersions()
+    {
+        return versions;
+    }
+
+    public void setVersions( List<String> versions )
+    {
+        this.versions = versions;
+    }
+
+    public String getRepositoryId()
+    {
+        return repositoryId;
+    }
+
+    public void setRepositoryId( String repositoryId )
+    {
+        this.repositoryId = repositoryId;
+    }
+
+    public void addVersion( String version )
+    {
+        versions.add( version );
+    }
+
+    public String getBundleVersion()
+    {
+        return bundleVersion;
+    }
+
+    public void setBundleVersion( String bundleVersion )
+    {
+        this.bundleVersion = bundleVersion;
+    }
+
+    public String getBundleSymbolicName()
+    {
+        return bundleSymbolicName;
+    }
+
+    public void setBundleSymbolicName( String bundleSymbolicName )
+    {
+        this.bundleSymbolicName = bundleSymbolicName;
+    }
+
+    public String getBundleExportPackage()
+    {
+        return bundleExportPackage;
+    }
+
+    public void setBundleExportPackage( String bundleExportPackage )
+    {
+        this.bundleExportPackage = bundleExportPackage;
+    }
+
+    public String getBundleExportService()
+    {
+        return bundleExportService;
+    }
+
+    public void setBundleExportService( String bundleExportService )
+    {
+        this.bundleExportService = bundleExportService;
+    }
+
+    public String getPrefix()
+    {
+        return prefix;
+    }
+
+    public void setPrefix( String prefix )
+    {
+        this.prefix = prefix;
+    }
+
+    public List<String> getGoals()
+    {
+        return goals;
+    }
+
+    public void setGoals( List<String> goals )
+    {
+        this.goals = goals;
+    }
+
+    public String getBundleDescription()
+    {
+        return bundleDescription;
+    }
+
+    public void setBundleDescription( String bundleDescription )
+    {
+        this.bundleDescription = bundleDescription;
+    }
+
+    public String getBundleName()
+    {
+        return bundleName;
+    }
+
+    public void setBundleName( String bundleName )
+    {
+        this.bundleName = bundleName;
+    }
+
+    public String getBundleLicense()
+    {
+        return bundleLicense;
+    }
+
+    public void setBundleLicense( String bundleLicense )
+    {
+        this.bundleLicense = bundleLicense;
+    }
+
+    public String getBundleDocUrl()
+    {
+        return bundleDocUrl;
+    }
+
+    public void setBundleDocUrl( String bundleDocUrl )
+    {
+        this.bundleDocUrl = bundleDocUrl;
+    }
+
+    public String getBundleImportPackage()
+    {
+        return bundleImportPackage;
+    }
+
+    public void setBundleImportPackage( String bundleImportPackage )
+    {
+        this.bundleImportPackage = bundleImportPackage;
+    }
+
+    public String getBundleRequireBundle()
+    {
+        return bundleRequireBundle;
+    }
+
+    public void setBundleRequireBundle( String bundleRequireBundle )
+    {
+        this.bundleRequireBundle = bundleRequireBundle;
+    }
+
+    public String getPackaging()
+    {
+        return packaging;
+    }
+
+    public void setPackaging( String packaging )
+    {
+        this.packaging = packaging;
+    }
+
+    public String getType()
+    {
+        return getPackaging();
+    }
+
+    public String getClassifier()
+    {
+        return classifier;
+    }
+
+    public void setClassifier( String classifier )
+    {
+        this.classifier = classifier;
+    }
+
+    public String getFileExtension()
+    {
+        return fileExtension;
+    }
+
+    public void setFileExtension( String fileExtension )
+    {
+        this.fileExtension = fileExtension;
+    }
+
+    @Override
+    public String toString()
+    {
+        final StringBuilder sb = new StringBuilder();
+        sb.append( "SearchResultHit" );
+        sb.append( "{context='" ).append( context ).append( '\'' );
+        sb.append( ", url='" ).append( url ).append( '\'' );
+        sb.append( ", groupId='" ).append( groupId ).append( '\'' );
+        sb.append( ", artifactId='" ).append( artifactId ).append( '\'' );
+        sb.append( ", repositoryId='" ).append( repositoryId ).append( '\'' );
+        sb.append( ", versions=" ).append( versions );
+        sb.append( ", packaging='" ).append( packaging ).append( '\'' );
+        sb.append( ", prefix='" ).append( prefix ).append( '\'' );
+        sb.append( ", goals=" ).append( goals );
+        sb.append( ", bundleVersion='" ).append( bundleVersion ).append( '\'' );
+        sb.append( ", bundleSymbolicName='" ).append( bundleSymbolicName ).append( '\'' );
+        sb.append( ", bundleExportPackage='" ).append( bundleExportPackage ).append( '\'' );
+        sb.append( ", bundleExportService='" ).append( bundleExportService ).append( '\'' );
+        sb.append( ", bundleDescription='" ).append( bundleDescription ).append( '\'' );
+        sb.append( ", bundleName='" ).append( bundleName ).append( '\'' );
+        sb.append( ", bundleLicense='" ).append( bundleLicense ).append( '\'' );
+        sb.append( ", bundleDocUrl='" ).append( bundleDocUrl ).append( '\'' );
+        sb.append( ", bundleImportPackage='" ).append( bundleImportPackage ).append( '\'' );
+        sb.append( ", bundleRequireBundle='" ).append( bundleRequireBundle ).append( '\'' );
+        sb.append( ", classifier='" ).append( classifier ).append( '\'' );
+        sb.append( ", fileExtension='" ).append( fileExtension ).append( '\'' );
+        sb.append( '}' );
+        return sb.toString();
+    }
+
+    @Override
+    public boolean equals( Object o )
+    {
+        if ( this == o )
+        {
+            return true;
+        }
+        if ( o == null || getClass() != o.getClass() )
+        {
+            return false;
+        }
+
+        SearchResultHit that = (SearchResultHit) o;
+
+        if ( artifactId != null ? !artifactId.equals( that.artifactId ) : that.artifactId != null )
+        {
+            return false;
+        }
+        if ( classifier != null ? !classifier.equals( that.classifier ) : that.classifier != null )
+        {
+            return false;
+        }
+        if ( groupId != null ? !groupId.equals( that.groupId ) : that.groupId != null )
+        {
+            return false;
+        }
+        if ( packaging != null ? !packaging.equals( that.packaging ) : that.packaging != null )
+        {
+            return false;
+        }
+
+        return true;
+    }
+
+    @Override
+    public int hashCode()
+    {
+        int result = groupId != null ? groupId.hashCode() : 0;
+        result = 31 * result + ( artifactId != null ? artifactId.hashCode() : 0 );
+        result = 31 * result + ( packaging != null ? packaging.hashCode() : 0 );
+        result = 31 * result + ( classifier != null ? classifier.hashCode() : 0 );
+        return result;
+    }
+}

http://git-wip-us.apache.org/repos/asf/archiva/blob/e2cdbc2b/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/indexer/search/SearchResultLimits.java
----------------------------------------------------------------------
diff --git a/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/indexer/search/SearchResultLimits.java b/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/indexer/search/SearchResultLimits.java
new file mode 100644
index 0000000..967ecc5
--- /dev/null
+++ b/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/indexer/search/SearchResultLimits.java
@@ -0,0 +1,87 @@
+package org.apache.archiva.indexer.search;
+
+/*
+ * 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.
+ */
+
+/**
+ * SearchResultLimits - used to provide the search some limits on how the results are returned.
+ * This can provide paging for the result
+ */
+public class SearchResultLimits
+{
+    /**
+     * Constant to use for {@link #setSelectedPage(int)} to indicate a desire to get ALL PAGES.
+     * USE WITH CAUTION!!
+     */
+    public static final int ALL_PAGES = ( -1 );
+
+    private int pageSize = 30;
+
+    private int selectedPage = 0;
+
+    /**
+     * @param selectedPage page selected use -1 for all pages
+     */
+    public SearchResultLimits( int selectedPage )
+    {
+        this.selectedPage = selectedPage;
+    }
+
+    /**
+     * @param pageSize     number of groupId:artifact per page
+     * @param selectedPage page selected use -1 for all pages
+     * @since 1.4-M4
+     */
+    public SearchResultLimits( int pageSize, int selectedPage )
+    {
+        this.pageSize = pageSize;
+        this.selectedPage = selectedPage;
+    }
+
+    public int getPageSize()
+    {
+        return pageSize;
+    }
+
+    /**
+     * Set page size for maximum # of hits to return per page.
+     *
+     * @param pageSize size of page by # of hits.
+     */
+    public void setPageSize( int pageSize )
+    {
+        this.pageSize = pageSize;
+    }
+
+    public int getSelectedPage()
+    {
+        return selectedPage;
+    }
+
+    public void setSelectedPage( int selectedPage )
+    {
+        this.selectedPage = selectedPage;
+    }
+
+    @Override
+    public String toString()
+    {
+        return "SearchResultLimits{" + "pageSize=" + pageSize + ", selectedPage=" + selectedPage + '}';
+    }
+}

http://git-wip-us.apache.org/repos/asf/archiva/blob/e2cdbc2b/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/indexer/search/SearchResults.java
----------------------------------------------------------------------
diff --git a/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/indexer/search/SearchResults.java b/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/indexer/search/SearchResults.java
new file mode 100644
index 0000000..9dc650f
--- /dev/null
+++ b/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/indexer/search/SearchResults.java
@@ -0,0 +1,148 @@
+package org.apache.archiva.indexer.search;
+
+/*
+ * 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.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+
+/**
+ * SearchResults
+ *
+ */
+public class SearchResults
+{
+    private Map<String, SearchResultHit> hits = new HashMap<>();
+
+    private int totalHits;
+
+    private int totalHitsMapSize;
+
+    private int returnedHitsCount;
+
+    private SearchResultLimits limits;
+
+    public SearchResults()
+    {
+        /* do nothing */
+    }
+
+    // for new RepositorySearch
+    public void addHit( String id, SearchResultHit hit )
+    {
+        hits.put( id, hit );
+    }
+
+    /**
+     * Get the list of {@link SearchResultHit} objects.
+     *
+     * @return the list of {@link SearchResultHit} objects.
+     */
+    public List<SearchResultHit> getHits()
+    {
+        return new ArrayList<>( hits.values() );
+    }
+
+    /**
+     * see SearchUtil on how to generate the key
+     *
+     * @param key
+     * @return
+     */
+    public SearchResultHit getSearchResultHit( String key )
+    {
+        return hits.get( key );
+    }
+
+    public Map<String, SearchResultHit> getHitsMap()
+    {
+        return hits;
+    }
+
+    public boolean isEmpty()
+    {
+        return hits.isEmpty();
+    }
+
+    public SearchResultLimits getLimits()
+    {
+        return limits;
+    }
+
+    public void setLimits( SearchResultLimits limits )
+    {
+        this.limits = limits;
+    }
+
+    public int getTotalHits()
+    {
+        return totalHits;
+    }
+
+    public void setTotalHits( int totalHits )
+    {
+        this.totalHits = totalHits;
+    }
+
+    /**
+     * @return
+     * @since 1.4-M1
+     */
+    public int getReturnedHitsCount()
+    {
+        return returnedHitsCount;
+    }
+
+    /**
+     * @param returnedHitsCount
+     * @since 1.4-M1
+     */
+    public void setReturnedHitsCount( int returnedHitsCount )
+    {
+        this.returnedHitsCount = returnedHitsCount;
+    }
+
+    /**
+     * @return
+     * @since 1.4-M1
+     */
+    public int getTotalHitsMapSize()
+    {
+        return totalHitsMapSize;
+    }
+
+    /**
+     * @param totalHitsMapSize
+     * @since 1.4-M1
+     */
+    public void setTotalHitsMapSize( int totalHitsMapSize )
+    {
+        this.totalHitsMapSize = totalHitsMapSize;
+    }
+
+    @Override
+    public String toString()
+    {
+        return "SearchResults{" + "hits=" + hits + ", totalHits=" + totalHits + ", returnedHitsCount="
+            + returnedHitsCount + ", limits=" + limits + '}';
+    }
+}

http://git-wip-us.apache.org/repos/asf/archiva/blob/e2cdbc2b/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/indexer/util/SearchUtil.java
----------------------------------------------------------------------
diff --git a/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/indexer/util/SearchUtil.java b/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/indexer/util/SearchUtil.java
new file mode 100644
index 0000000..0a0c922
--- /dev/null
+++ b/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/indexer/util/SearchUtil.java
@@ -0,0 +1,36 @@
+package org.apache.archiva.indexer.util;
+
+/*
+ * 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;
+
+/**
+ * SearchUtil - utility class for search.
+ */
+public class SearchUtil
+{
+    public static String getHitId( String groupId, String artifactId, String classifier, String packaging )
+    {
+        return ( StringUtils.isBlank( groupId ) ? "" : StringUtils.trim( groupId ) ) + ":" //
+            + ( StringUtils.isBlank( artifactId ) ? "" : StringUtils.trim( artifactId ) ) + ":" //
+            + ( StringUtils.isBlank( classifier ) ? "" : StringUtils.trim( classifier ) ) + ":" //
+            + ( StringUtils.isBlank( packaging ) ? "" : StringUtils.trim( packaging ) );
+    }
+}

http://git-wip-us.apache.org/repos/asf/archiva/blob/e2cdbc2b/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/ContentNotFoundException.java
----------------------------------------------------------------------
diff --git a/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/ContentNotFoundException.java b/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/ContentNotFoundException.java
new file mode 100644
index 0000000..7579deb
--- /dev/null
+++ b/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/ContentNotFoundException.java
@@ -0,0 +1,50 @@
+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.
+ */
+
+/**
+ * ContentNotFoundException is thrown in response for requests for content that is not the repository. 
+ *
+ *
+ */
+public class ContentNotFoundException
+    extends RepositoryException
+{
+
+    public ContentNotFoundException()
+    {
+        super();
+    }
+
+    public ContentNotFoundException( String message, Throwable cause )
+    {
+        super( message, cause );
+    }
+
+    public ContentNotFoundException( String message )
+    {
+        super( message );
+    }
+
+    public ContentNotFoundException( Throwable cause )
+    {
+        super( cause );
+    }
+}

http://git-wip-us.apache.org/repos/asf/archiva/blob/e2cdbc2b/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/EditableManagedRepository.java
----------------------------------------------------------------------
diff --git a/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/EditableManagedRepository.java b/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/EditableManagedRepository.java
new file mode 100644
index 0000000..4596201
--- /dev/null
+++ b/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/EditableManagedRepository.java
@@ -0,0 +1,56 @@
+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.
+ */
+
+/**
+ * The editable part of a managed repository.
+ */
+public interface EditableManagedRepository extends EditableRepository, ManagedRepository
+{
+    /**
+     * If true, the repository blocks redeployments of artifacts with the same version.
+     * @param blocksRedeployment The flag for blocking redeployments.
+     */
+    void setBlocksRedeployment(boolean blocksRedeployment);
+
+    /**
+     * Sets the content
+     * @param content
+     */
+    void setContent(ManagedRepositoryContent content);
+
+    /**
+     * Adds an active release scheme. Release schemes may be combined.
+     * @param scheme the scheme to add.
+     */
+    void addActiveReleaseScheme(ReleaseScheme scheme);
+
+    /**
+     * Removes an active release scheme from the set.
+     * @param scheme the scheme to remove.
+     */
+    void removeActiveReleaseScheme(ReleaseScheme scheme);
+
+    /**
+     * Clears all active release schemes.
+     */
+    void clearActiveReleaseSchemes();
+
+}

http://git-wip-us.apache.org/repos/asf/archiva/blob/e2cdbc2b/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/EditableRemoteRepository.java
----------------------------------------------------------------------
diff --git a/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/EditableRemoteRepository.java b/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/EditableRemoteRepository.java
new file mode 100644
index 0000000..f8a054f
--- /dev/null
+++ b/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/EditableRemoteRepository.java
@@ -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.time.Duration;
+import java.util.Map;
+
+/**
+ * The editable part of a remote repository
+ */
+public interface EditableRemoteRepository extends EditableRepository, RemoteRepository
+{
+
+    /**
+     * Sets the login credentials for login to the remote repository.
+     * @param credentials
+     */
+    void setCredentials(RepositoryCredentials credentials);
+
+    /**
+     * Sets the path relative to the root url of the repository that should be used to check
+     * the availability of the repository.
+     *
+     * @param path The path string.
+     */
+    void setCheckPath(String path);
+
+    /**
+     * Sets additional parameters to be used to access the remote repository.
+     * @param params A map of parameters, may not be null.
+     */
+    void setExtraParameters(Map<String,String> params);
+
+    /**
+     * Adds an additional parameter.
+     * @param key The key of the parameter
+     * @param value The value of the parameter
+     */
+    void addExtraParameter(String key, String value);
+
+    /**
+     * Sets the extra headers, that are added to the requests to the remote repository.
+     */
+    void setExtraHeaders(Map<String,String> headers);
+
+    /**
+     * Adds an extra header.
+     * @param header The header name
+     * @param value The header value
+     */
+    void addExtraHeader(String header, String value);
+
+    /**
+     * Sets the timeout for requests to the remote repository.
+     *
+     * @param duration The amount of time, after that the request is aborted.
+     */
+    void setTimeout(Duration duration);
+
+    /**
+     * Sets the content.
+     * @param content
+     */
+    void setContent(RemoteRepositoryContent content);
+}

http://git-wip-us.apache.org/repos/asf/archiva/blob/e2cdbc2b/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/EditableRepository.java
----------------------------------------------------------------------
diff --git a/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/EditableRepository.java b/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/EditableRepository.java
new file mode 100644
index 0000000..b275492
--- /dev/null
+++ b/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/EditableRepository.java
@@ -0,0 +1,124 @@
+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.net.URI;
+import java.util.Locale;
+
+/**
+ * This is the editable part of a repository.
+ * Normally a repository should also implement this interface but it is not
+ * required.
+ *
+ * Capabilities and features are a integral part of the implementation and not
+ * provided here by the interface.
+ * Feature setting methods are provided by the features itself.
+ *
+ */
+public interface EditableRepository extends Repository
+{
+
+    /**
+     * Returns the primary locale used for setting the default values for
+     * name and description.
+     *
+     * @return The locale used for name and description when they are not set
+     */
+    Locale getPrimaryLocale();
+
+    /**
+     * Sets the name for the given locale
+     *
+     * @param locale the locale for which the name is set
+     * @param name The name value in the language that matches the locale
+     */
+    void setName( Locale locale, String name);
+
+    /**
+     * Sets the description for the given locale
+     *
+     * @param locale the locale for which the description is set
+     * @param description The description in the language that matches the locale.
+     */
+    void setDescription(Locale locale, String description);
+
+    /**
+     * Sets the location of the repository. May be a URI that is suitable for the
+     * repository implementation. Not all implementations will accept the same URI schemes.
+     * @param location the location URI
+     * @throws UnsupportedURIException if the URI scheme is not supported by the repository type.
+     */
+    void setLocation(URI location) throws UnsupportedURIException;
+
+    /**
+     * Sets the base uri for relative location uris.
+     *
+     * @param baseUri
+     */
+    void setBaseUri(URI baseUri);
+
+    /**
+     * Adds a failover location for the repository.
+     *
+     * @param location The location that should be used as failover.
+     * @throws UnsupportedURIException if the URI scheme is not supported by the repository type.
+     */
+    void addFailoverLocation(URI location) throws UnsupportedURIException;
+
+    /**
+     * Removes a failover location from the set.
+     *
+     * @param location the location uri to remove
+     */
+    void removeFailoverLocation(URI location);
+
+    /**
+     * Clears the failover location set.
+     */
+    void clearFailoverLocations();
+
+    /**
+     * Sets the flag for scanning the repository. If true, the repository will be scanned.
+     * You have to set the scheduling times, if you set this to true.
+     *
+     * @param scanned if true, the repository is scanned regulary.
+     */
+    void setScanned(boolean scanned);
+
+    /**
+     * Sets the scheduling definition, that defines the times, when the regular repository
+     * jobs are started. The <code>cronExpression</code> must be a valid
+     * quartz cron definition.
+     *
+     * @See http://www.quartz-scheduler.org/api/2.2.1/org/quartz/CronExpression.html
+     *
+     * @param cronExpression the cron expression.
+     * @throws IllegalArgumentException if the cron expression is not valid.
+     */
+    void setSchedulingDefinition(String cronExpression) throws IllegalArgumentException;
+
+    /**
+     * Sets the layout string.
+     * @param layout
+     */
+    void setLayout(String layout);
+
+
+}

http://git-wip-us.apache.org/repos/asf/archiva/blob/e2cdbc2b/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/LayoutException.java
----------------------------------------------------------------------
diff --git a/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/LayoutException.java b/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/LayoutException.java
new file mode 100644
index 0000000..f106937
--- /dev/null
+++ b/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/LayoutException.java
@@ -0,0 +1,40 @@
+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.common.ArchivaException;
+
+/**
+ * LayoutException 
+ *
+ *
+ */
+public class LayoutException extends ArchivaException
+{
+    public LayoutException( String message, Throwable cause )
+    {
+        super( message, cause );
+    }
+
+    public LayoutException( String message )
+    {
+        super( message );
+    }
+}

http://git-wip-us.apache.org/repos/asf/archiva/blob/e2cdbc2b/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/ManagedRepository.java
----------------------------------------------------------------------
diff --git a/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/ManagedRepository.java b/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/ManagedRepository.java
new file mode 100644
index 0000000..550a9ce
--- /dev/null
+++ b/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/ManagedRepository.java
@@ -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.indexer.ArchivaIndexingContext;
+
+import java.util.Set;
+
+/**
+ * Represents a managed repository, that is readable and writable.
+ */
+public interface ManagedRepository extends Repository {
+
+    /**
+     * Returns the interface to access the contents of this repository.
+     *
+     * @return The repository content.
+     */
+    ManagedRepositoryContent getContent();
+
+    /**
+     * Returns true, if repeated deployments of the same artifact with the same version throws exceptions.
+     * @return
+     */
+    boolean blocksRedeployments();
+
+    /**
+     * Returns the release schemes that are active by this repository. E.g. for maven repositories
+     * this may either be a release repository, a snapshot repository or a combined repository.
+     * @return
+     */
+    Set<ReleaseScheme> getActiveReleaseSchemes();
+
+}

http://git-wip-us.apache.org/repos/asf/archiva/blob/e2cdbc2b/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/ManagedRepositoryContent.java
----------------------------------------------------------------------
diff --git a/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/ManagedRepositoryContent.java b/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/ManagedRepositoryContent.java
new file mode 100644
index 0000000..bf47b47
--- /dev/null
+++ b/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/ManagedRepositoryContent.java
@@ -0,0 +1,225 @@
+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.ArchivaArtifact;
+import org.apache.archiva.model.ArtifactReference;
+import org.apache.archiva.model.ProjectReference;
+import org.apache.archiva.model.VersionedReference;
+
+import java.nio.file.Path;
+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 extends RepositoryContent
+{
+
+
+
+    /**
+     * Delete from the managed repository all files / directories associated with the
+     * provided version reference.
+     *
+     * @param reference the version reference to delete.
+     * @throws ContentNotFoundException
+     */
+    void deleteVersion( VersionedReference reference )
+        throws ContentNotFoundException;
+
+    /**
+     * delete a specified artifact from the repository
+     *
+     * @param artifactReference
+     * @throws ContentNotFoundException
+     */
+    void deleteArtifact( ArtifactReference artifactReference )
+        throws ContentNotFoundException;
+
+    /**
+     * @param groupId
+     * @throws ContentNotFoundException
+     * @since 1.4-M3
+     */
+    void deleteGroupId( String groupId )
+        throws ContentNotFoundException;
+
+    /**
+     *
+     * @param namespace groupId for maven
+     * @param projectId artifactId for maven
+     * @throws ContentNotFoundException
+     */
+    void deleteProject( String namespace, String projectId )
+        throws RepositoryException;
+
+    /**
+     * <p>
+     * Convenience method to get the repository id.
+     * </p>
+     * <p>
+     * Equivalent to calling <code>.getRepository().getId()</code>
+     * </p>
+     *
+     * @return the repository id.
+     */
+    String getId();
+
+    /**
+     * <p>
+     * Gather up the list of related artifacts to the ArtifactReference provided.
+     * This typically inclues the pom files, and those things with
+     * classifiers (such as doc, source code, test libs, etc...)
+     * </p>
+     * <p>
+     * <strong>NOTE:</strong> Some layouts (such as maven 1 "legacy") are not compatible with this query.
+     * </p>
+     *
+     * @param reference the reference to work off of.
+     * @return the set of ArtifactReferences for related artifacts.
+     * @throws ContentNotFoundException if the initial artifact reference does not exist within the repository.
+     */
+    Set<ArtifactReference> getRelatedArtifacts( ArtifactReference reference )
+        throws ContentNotFoundException;
+
+    /**
+     * <p>
+     * Convenience method to get the repository (on disk) root directory.
+     * </p>
+     * <p>
+     * Equivalent to calling <code>.getRepository().getLocation()</code>
+     * </p>
+     *
+     * @return the repository (on disk) root directory.
+     */
+    String getRepoRoot();
+
+    /**
+     * Get the repository configuration associated with this
+     * repository content.
+     *
+     * @return the repository that is associated with this repository content.
+     */
+    ManagedRepository getRepository();
+
+    /**
+     * Given a specific {@link ProjectReference}, return the list of available versions for
+     * that project reference.
+     *
+     * @param reference the project reference to work off of.
+     * @return the list of versions found for that project reference.
+     * @throws ContentNotFoundException if the project reference does nto exist within the repository.
+     * @throws LayoutException
+     */
+    Set<String> getVersions( ProjectReference reference )
+        throws ContentNotFoundException, LayoutException;
+
+    /**
+     * <p>
+     * Given a specific {@link VersionedReference}, return the list of available versions for that
+     * versioned reference.
+     * </p>
+     * <p>
+     * <strong>NOTE:</strong> This is really only useful when working with SNAPSHOTs.
+     * </p>
+     *
+     * @param reference the versioned reference to work off of.
+     * @return the set of versions found.
+     * @throws ContentNotFoundException if the versioned reference does not exist within the repository.
+     */
+    Set<String> getVersions( VersionedReference reference )
+        throws ContentNotFoundException;
+
+    /**
+     * Determines if the artifact referenced exists in the repository.
+     *
+     * @param reference the artifact reference to check for.
+     * @return true if the artifact referenced exists.
+     */
+    boolean hasContent( ArtifactReference reference );
+
+    /**
+     * Determines if the project referenced exists in the repository.
+     *
+     * @param reference the project reference to check for.
+     * @return true it the project referenced exists.
+     */
+    boolean hasContent( ProjectReference reference );
+
+    /**
+     * Determines if the version reference exists in the repository.
+     *
+     * @param reference the version reference to check for.
+     * @return true if the version referenced exists.
+     */
+    boolean hasContent( VersionedReference reference );
+
+    /**
+     * Set the repository configuration to associate with this
+     * repository content.
+     *
+     * @param repo the repository to associate with this repository content.
+     */
+    void setRepository( org.apache.archiva.repository.ManagedRepository repo );
+
+    /**
+     * Given an {@link ArtifactReference}, return the file reference to the artifact.
+     *
+     * @param reference the artifact reference to use.
+     * @return the relative path to the artifact.
+     */
+    Path toFile( ArtifactReference reference );
+
+    /**
+     * Given an {@link ArchivaArtifact}, return the file reference to the artifact.
+     *
+     * @param reference the archiva artifact to use.
+     * @return the relative path to the artifact.
+     */
+    Path toFile( ArchivaArtifact reference );
+
+    /**
+     * Given a {@link ProjectReference}, return the path to the metadata for
+     * the project.
+     *
+     * @param reference the reference to use.
+     * @return the path to the metadata file, or null if no metadata is appropriate.
+     */
+    String toMetadataPath( ProjectReference reference );
+
+    /**
+     * Given a {@link VersionedReference}, return the path to the metadata for
+     * the specific version of the project.
+     *
+     * @param reference the reference to use.
+     * @return the path to the metadata file, or null if no metadata is appropriate.
+     */
+    String toMetadataPath( VersionedReference reference );
+
+    /**
+     * Given an {@link ArchivaArtifact}, return the relative path to the artifact.
+     *
+     * @param reference the archiva artifact to use.
+     * @return the relative path to the artifact.
+     */
+    String toPath( ArchivaArtifact reference );
+}

http://git-wip-us.apache.org/repos/asf/archiva/blob/e2cdbc2b/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/ReleaseScheme.java
----------------------------------------------------------------------
diff --git a/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/ReleaseScheme.java b/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/ReleaseScheme.java
new file mode 100644
index 0000000..0868d35
--- /dev/null
+++ b/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/ReleaseScheme.java
@@ -0,0 +1,27 @@
+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.
+ */
+
+/**
+ * Repository release schemes that change the handling of artifacts
+ */
+public enum ReleaseScheme {
+    RELEASE,SNAPSHOT
+}

http://git-wip-us.apache.org/repos/asf/archiva/blob/e2cdbc2b/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/RemoteRepository.java
----------------------------------------------------------------------
diff --git a/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/RemoteRepository.java b/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/RemoteRepository.java
new file mode 100644
index 0000000..5a7c1e8
--- /dev/null
+++ b/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/RemoteRepository.java
@@ -0,0 +1,73 @@
+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.time.Duration;
+import java.util.Map;
+
+/**
+ * This represents a repository that is not fully managed by archiva. Its some kind of proxy that
+ * forwards requests to the remote repository and is able to cache artifacts locally.
+ */
+public interface RemoteRepository extends Repository {
+
+    /**
+     * Returns the interface to access the content of the repository.
+     * @return
+     */
+    RemoteRepositoryContent getContent();
+
+    /**
+     * Returns the credentials used to login to the remote repository.
+     * @return the credentials, null if not set.
+     */
+    RepositoryCredentials getLoginCredentials();
+
+    /**
+     * Returns the path relative to the root url of the repository that should be used
+     * to check the availability of the repository.
+     * @return The check path, null if not set.
+     */
+    String getCheckPath();
+
+
+    /**
+     * Returns additional parameters, that are used for accessing the remote repository.
+     * @return A map of key, value pairs.
+     */
+    Map<String,String> getExtraParameters();
+
+
+    /**
+     * Returns extra headers that are added to the request to the remote repository.
+     * @return
+     */
+    Map<String,String> getExtraHeaders();
+
+    /**
+     * Returns the time duration, after that the request is aborted and a error is returned, if the remote repository
+     * does not respond.
+     * @return The timeout.
+     */
+    Duration getTimeout();
+
+
+}

http://git-wip-us.apache.org/repos/asf/archiva/blob/e2cdbc2b/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/RemoteRepositoryContent.java
----------------------------------------------------------------------
diff --git a/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/RemoteRepositoryContent.java b/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/RemoteRepositoryContent.java
new file mode 100644
index 0000000..246e334
--- /dev/null
+++ b/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/RemoteRepositoryContent.java
@@ -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 org.apache.archiva.model.ArtifactReference;
+import org.apache.archiva.model.RepositoryURL;
+
+/**
+ * RemoteRepositoryContent interface for interacting with a remote repository in an abstract way, 
+ * without the need for processing based on URLs, or working with the database. 
+ *
+ *
+ */
+public interface RemoteRepositoryContent extends RepositoryContent
+{
+    /**
+     * <p>
+     * Convenience method to get the repository id.
+     * </p>
+     * 
+     * <p>
+     * Equivalent to calling <code>.getRepository().getId()</code>
+     * </p>
+     * 
+     * @return the repository id.
+     */
+    String getId();
+
+    /**
+     * Get the repository configuration associated with this
+     * repository content.
+     * 
+     * @return the repository that is associated with this repository content.
+     */
+    RemoteRepository getRepository();
+
+    /**
+     * <p>
+     * Convenience method to get the repository url.
+     * </p>
+     * 
+     * <p>
+     * Equivalent to calling <code>new RepositoryURL( this.getRepository().getUrl() )</code>
+     * </p>
+     * 
+     * @return the repository url.
+     */
+    RepositoryURL getURL();
+
+    /**
+     * Set the repository configuration to associate with this
+     * repository content.
+     * 
+     * @param repo the repository to associate with this repository content.
+     */
+    void setRepository( RemoteRepository repo );
+
+    /**
+     * Given an ArtifactReference, return the url to the artifact.
+     *
+     * @param reference the artifact reference to use.
+     * @return the relative path to the artifact.
+     */
+    RepositoryURL toURL( ArtifactReference reference );
+}

http://git-wip-us.apache.org/repos/asf/archiva/blob/e2cdbc2b/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/Repository.java
----------------------------------------------------------------------
diff --git a/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/Repository.java b/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/Repository.java
new file mode 100644
index 0000000..1c101ee
--- /dev/null
+++ b/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/Repository.java
@@ -0,0 +1,169 @@
+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.indexer.ArchivaIndexingContext;
+import org.apache.archiva.repository.features.RepositoryFeature;
+
+import java.net.URI;
+import java.util.List;
+import java.util.Locale;
+import java.util.Set;
+
+/**
+ *
+ * Base interface for repositories.
+ *
+ * Created by Martin Stockhammer on 21.09.17.
+ */
+public interface Repository {
+
+    /**
+     * Return the identifier of the repository. Repository identifier should be unique at least
+     * for the same type.
+     * @return The identifier.
+     */
+    String getId();
+
+    /**
+     * This is the display name of the repository. This string is presented in the user interface.
+     *
+     * @return The display name of the repository
+     */
+    String getName();
+
+    /**
+     * Returns the name in the given locale.
+     * @param locale
+     * @return
+     */
+    String getName(Locale locale);
+
+    /**
+     * Returns a description of this repository.
+     * @return The description.
+     */
+    String getDescription();
+
+    /**
+     * Returns the description for the given locale.
+     * @param locale
+     * @return
+     */
+    String getDescription(Locale locale);
+
+    /**
+     * This identifies the type of repository. Archiva does only support certain types of repositories.
+     *
+     * @return A unique identifier for the repository type.
+     */
+    RepositoryType getType();
+
+
+    /**
+     * Returns the location of this repository. For local repositories this might be a file URI, for
+     * remote repositories a http URL or some very repository specific schemes.
+     * Each repository has only one unique location.
+     *
+     * @return The repository location.
+     */
+    URI getLocation();
+
+    /**
+     * This returns the absolute location uri of this repository. Some repository locations may be relative to
+     * the base repository directory or uri. This returns the absolute path of the repository.
+     * If the location is absolute already this method returns the same URI as getLocation().
+     *
+     * @return the absolute uri of the location.
+     */
+    URI getAbsoluteLocation();
+
+    /**
+     * A repository may allow additional locations that can be used, if the primary location is not available.
+     * @return
+     */
+    Set<URI> getFailoverLocations();
+
+    /**
+     * True, if this repository is scanned regularly.
+     */
+    boolean isScanned();
+
+    /**
+     * Returns the definition, when the repository jobs are executed.
+     * This must return a valid a cron string.
+     *
+     * @See http://www.quartz-scheduler.org/api/2.2.1/org/quartz/CronExpression.html
+     *
+     * @return
+     */
+    String getSchedulingDefinition();
+
+    /**
+     * Returns true, if this repository has a index available
+     * @return
+     */
+    boolean hasIndex();
+
+    /**
+     * Returns a layout definition. The returned string may be implementation specific and is not
+     * standardized.
+     *
+     * @return
+     */
+    String getLayout();
+
+
+    /**
+     * Returns the capabilities of the repository implementation.
+     * @return
+     */
+    RepositoryCapabilities getCapabilities();
+
+
+    /**
+     * Extension method that allows to provide different features that are not supported by all
+     * repository types.
+     *
+     * @param clazz The feature class that is requested
+     * @param <T> This is the class of the feature
+     * @return The feature implementation for this repository instance, if it is supported
+     * @throws UnsupportedFeatureException if the feature is not supported by this repository type
+     */
+    <T extends RepositoryFeature<T>> RepositoryFeature<T> getFeature(Class<T> clazz) throws UnsupportedFeatureException;
+
+
+    /**
+     * Returns true, if the requested feature is supported by this repository.
+     *
+     * @param clazz The requested feature class
+     * @param <T> The requested feature class
+     * @return True, if the feature is supported, otherwise false.
+     */
+    <T extends RepositoryFeature<T>> boolean supportsFeature(Class<T> clazz);
+
+
+    /**
+     * Returns a indexing context.
+     * @return
+     * @throws UnsupportedOperationException
+     */
+    ArchivaIndexingContext getIndexingContext();
+}

http://git-wip-us.apache.org/repos/asf/archiva/blob/e2cdbc2b/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/RepositoryCapabilities.java
----------------------------------------------------------------------
diff --git a/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/RepositoryCapabilities.java b/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/RepositoryCapabilities.java
new file mode 100644
index 0000000..525d521
--- /dev/null
+++ b/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/RepositoryCapabilities.java
@@ -0,0 +1,99 @@
+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;
+
+/**
+ * Describe the capabilities a repository implementation supports.
+ */
+public interface RepositoryCapabilities {
+
+    /**
+     * Returns true, if this repository has a mechanism for indexes
+     * @return true, if this repository is indexable, otherwise false.
+     */
+    default boolean isIndexable() {
+        return true;
+    }
+
+    /**
+     * Returns true, if this repository type is storing its artifacts on the filesystem.
+     * @return true, if this is a file based repository, otherwise false.
+     */
+    default boolean isFileBased() {
+        return true;
+    }
+
+    /**
+     * Returns true, if this repository allows to block redeployments to prevent overriding
+     * released artifacts
+     * @return true, if this repo can block redeployments, otherwise false.
+     */
+    default boolean canBlockRedeployments() {
+        return true;
+    }
+
+    /**
+     * Returns true, if the artifacts can be scanned for metadata retrieval or maintenance tasks
+     * @return true, if this repository can be scanned regularily, otherwise false.
+     */
+    default boolean isScannable() {
+        return true;
+    }
+
+    /**
+     * Returns true, if this repository can use failover repository urls
+     * @return true, if there is a failover mechanism for repository access, otherwise false.
+     */
+    default boolean allowsFailover() {
+        return false;
+    }
+
+    /**
+     * Returns the release schemes this repository type can handle
+     */
+    Set<ReleaseScheme> supportedReleaseSchemes();
+
+    /**
+     * Returns the layouts this repository type can provide
+     * @return The list of layouts supported by this repository.
+     */
+    Set<String> supportedLayouts();
+
+    /**
+     * Returns additional capabilities, that this repository type implements.
+     * @return A list of custom capabilities.
+     */
+    Set<String> customCapabilities();
+
+    /**
+     * Returns the supported features this repository type supports. This method returns
+     * string that corresponds to fully qualified class names.
+     * We use string representation to allow implementations provide their own feature
+     * implementations if necessary and to avoid class errors.
+     *
+     * @return The list of supported features as string values.
+     */
+    Set<String> supportedFeatures();
+
+
+}

http://git-wip-us.apache.org/repos/asf/archiva/blob/e2cdbc2b/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/RepositoryContent.java
----------------------------------------------------------------------
diff --git a/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/RepositoryContent.java b/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/RepositoryContent.java
new file mode 100644
index 0000000..d959a86
--- /dev/null
+++ b/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/RepositoryContent.java
@@ -0,0 +1,51 @@
+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;
+
+
+/**
+ * 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 );
+}

http://git-wip-us.apache.org/repos/asf/archiva/blob/e2cdbc2b/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/RepositoryContentFactory.java
----------------------------------------------------------------------
diff --git a/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/RepositoryContentFactory.java b/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/RepositoryContentFactory.java
new file mode 100644
index 0000000..65d54e6
--- /dev/null
+++ b/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/RepositoryContentFactory.java
@@ -0,0 +1,216 @@
+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.configuration.ArchivaConfiguration;
+import org.apache.archiva.configuration.ConfigurationNames;
+import org.apache.archiva.configuration.ManagedRepositoryConfiguration;
+import org.apache.archiva.configuration.RemoteRepositoryConfiguration;
+import org.apache.archiva.redback.components.registry.Registry;
+import org.apache.archiva.redback.components.registry.RegistryListener;
+import org.springframework.context.ApplicationContext;
+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;
+
+/**
+ * RepositoryContentRequest
+ */
+@Service( "repositoryContentFactory#default" )
+public class RepositoryContentFactory
+    implements RegistryListener
+{
+    /**
+     *
+     */
+    @Inject
+    private ArchivaConfiguration archivaConfiguration;
+
+    @Inject
+    private ApplicationContext applicationContext;
+
+    @Inject
+    private List<RepositoryContentProvider> repositoryContentProviders;
+
+    private final Map<String, ManagedRepositoryContent> managedContentMap;
+
+    private final Map<String, RemoteRepositoryContent> remoteContentMap;
+
+
+    public RepositoryContentFactory( )
+    {
+        managedContentMap = new ConcurrentHashMap<String, ManagedRepositoryContent>( );
+        remoteContentMap = new ConcurrentHashMap<String, RemoteRepositoryContent>( );
+    }
+
+    /**
+     * Get the ManagedRepositoryContent object for the repository Id specified.
+     *
+     * @param repoId the repository id to fetch.
+     * @return the ManagedRepositoryContent object associated with the repository id.
+     * @throws RepositoryNotFoundException if the repository id does not exist within the configuration.
+     * @throws RepositoryException         the repository content object cannot be loaded due to configuration issue.
+     */
+    public ManagedRepositoryContent getManagedRepositoryContent( String repoId )
+        throws RepositoryException
+    {
+        ManagedRepositoryContent repo = managedContentMap.get( repoId );
+
+        if ( repo != null )
+        {
+            return repo;
+        }
+        else
+        {
+            throw new RepositoryNotFoundException(
+                "Unable to find managed repository configuration for id " + repoId );
+        }
+
+    }
+
+    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
+    {
+        final String id = mRepo.getId();
+        ManagedRepositoryContent content = managedContentMap.get( id );
+
+        if ( content != null && content.getRepository()==mRepo)
+        {
+            return content;
+        }
+
+        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 content;
+    }
+
+    public RemoteRepositoryContent getRemoteRepositoryContent( String repoId )
+        throws RepositoryException
+    {
+        RemoteRepositoryContent repo = remoteContentMap.get( repoId );
+
+        if ( repo != null )
+        {
+            return repo;
+        }
+        else
+        {
+            throw new RepositoryNotFoundException(
+                "Unable to find remote repository configuration for id:" + repoId );
+        }
+
+    }
+
+    public RemoteRepositoryContent getRemoteRepositoryContent( RemoteRepository mRepo )
+        throws RepositoryException
+    {
+        final String id = mRepo.getId();
+        RemoteRepositoryContent content = remoteContentMap.get( id );
+
+        if ( content != null && content.getRepository()==mRepo)
+        {
+            return content;
+        }
+
+        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() );
+        }
+        RemoteRepositoryContent previousContent = remoteContentMap.put( id, content );
+        if (previousContent!=null) {
+            previousContent.setRepository( null );
+        }
+        return content;
+    }
+
+
+    @Override
+    public void afterConfigurationChange( Registry registry, String propertyName, Object propertyValue )
+    {
+        if ( ConfigurationNames.isManagedRepositories( propertyName ) || ConfigurationNames.isRemoteRepositories(
+            propertyName ) )
+        {
+            initMaps( );
+        }
+    }
+
+    @Override
+    public void beforeConfigurationChange( Registry registry, String propertyName, Object propertyValue )
+    {
+        /* do nothing */
+    }
+
+    @PostConstruct
+    public void initialize( )
+    {
+        archivaConfiguration.addChangeListener( this );
+    }
+
+    private void initMaps( )
+    {
+        // olamy we use concurent so no need of synchronize
+        //synchronized ( managedContentMap )
+        //{
+        managedContentMap.clear( );
+        //}
+
+        //synchronized ( remoteContentMap )
+        //{
+        remoteContentMap.clear( );
+        //}
+    }
+
+    public ArchivaConfiguration getArchivaConfiguration( )
+    {
+        return archivaConfiguration;
+    }
+
+    public void setArchivaConfiguration( ArchivaConfiguration archivaConfiguration )
+    {
+        this.archivaConfiguration = archivaConfiguration;
+    }
+
+    public void setRepositoryContentProviders(List<RepositoryContentProvider> providers) {
+        this.repositoryContentProviders = providers;
+    }
+
+    public List<RepositoryContentProvider> getRepositoryContentProviders() {
+        return repositoryContentProviders;
+    }
+}

http://git-wip-us.apache.org/repos/asf/archiva/blob/e2cdbc2b/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/RepositoryContentProvider.java
----------------------------------------------------------------------
diff --git a/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/RepositoryContentProvider.java b/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/RepositoryContentProvider.java
new file mode 100644
index 0000000..8234449
--- /dev/null
+++ b/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/RepositoryContentProvider.java
@@ -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;
+}