summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMaria Odea B. Ching <oching@apache.org>2008-07-16 09:42:37 +0000
committerMaria Odea B. Ching <oching@apache.org>2008-07-16 09:42:37 +0000
commitb3e2ecd39c190116624010587d78de9071008516 (patch)
tree35d9da2e8be3c020433e6b496b14fc8b9d5b6e36
parent089c79af8f5d7f78bc098de6fcdaa24caa09ea1d (diff)
parent207ada84a3b989aa61223d4dc152b1bf20bc1d3a (diff)
downloadarchiva-b3e2ecd39c190116624010587d78de9071008516.tar.gz
archiva-b3e2ecd39c190116624010587d78de9071008516.zip
[maven-release-plugin] copy for tag archiva-1.1archiva-1.1
git-svn-id: https://svn.apache.org/repos/asf/archiva/tags/archiva-1.1@677214 13f79535-47bb-0310-9956-ffa450edef68
-rw-r--r--archiva-docs/src/site/apt/release-notes.apt22
-rw-r--r--archiva-jetty/src/main/conf/jetty.xml11
-rw-r--r--archiva-modules/archiva-base/archiva-consumers/archiva-lucene-consumers/pom.xml7
-rw-r--r--archiva-modules/archiva-base/archiva-consumers/archiva-lucene-consumers/src/main/java/org/apache/maven/archiva/consumers/lucene/IndexContentConsumer.java11
-rw-r--r--archiva-modules/archiva-base/archiva-consumers/archiva-lucene-consumers/src/main/java/org/apache/maven/archiva/consumers/lucene/IndexJavaPublicMethodsConsumer.java191
-rw-r--r--archiva-modules/archiva-base/archiva-consumers/archiva-lucene-consumers/src/test/java/org/apache/maven/archiva/consumers/lucene/IndexJavaPublicMethodsConsumerTest.java124
-rw-r--r--archiva-modules/archiva-base/archiva-consumers/archiva-lucene-consumers/src/test/java/org/apache/maven/archiva/consumers/lucene/IndexJavaPublicMethodsCrossRepositorySearch.java191
-rw-r--r--archiva-modules/archiva-base/archiva-consumers/archiva-lucene-consumers/src/test/resources/org/apache/maven/archiva/consumers/lucene/IndexJavaPublicMethodsConsumerTest.xml64
-rw-r--r--archiva-modules/archiva-base/archiva-consumers/archiva-lucene-consumers/src/test/resources/test-repo/org/apache/archiva/archiva-index-methods-jar-test/1.0/archiva-index-methods-jar-test-1.0.jarbin0 -> 4460 bytes
-rw-r--r--archiva-modules/archiva-base/archiva-consumers/archiva-lucene-consumers/src/test/resources/test-repo/org/apache/archiva/archiva-index-methods-jar-test/1.0/pom.xml18
-rw-r--r--archiva-modules/archiva-base/archiva-indexer/src/main/java/org/apache/maven/archiva/indexer/bytecode/BytecodeRecord.java18
-rw-r--r--archiva-modules/archiva-base/archiva-indexer/src/main/java/org/apache/maven/archiva/indexer/filecontent/FileContentRecord.java2
-rw-r--r--archiva-modules/archiva-base/archiva-indexer/src/main/java/org/apache/maven/archiva/indexer/search/CrossRepositorySearch.java13
-rw-r--r--archiva-modules/archiva-base/archiva-indexer/src/main/java/org/apache/maven/archiva/indexer/search/DefaultCrossRepositorySearch.java61
-rw-r--r--archiva-modules/archiva-base/archiva-indexer/src/main/java/org/apache/maven/archiva/indexer/search/SearchResultHit.java12
-rw-r--r--archiva-modules/archiva-base/archiva-indexer/src/main/java/org/apache/maven/archiva/indexer/search/SearchResults.java1
-rw-r--r--archiva-modules/archiva-base/archiva-indexer/src/test/java/org/apache/maven/archiva/indexer/search/DefaultCrossRepositorySearchTest.java57
-rw-r--r--archiva-modules/archiva-base/archiva-proxy/src/main/java/org/apache/maven/archiva/proxy/DefaultRepositoryProxyConnectors.java39
-rw-r--r--archiva-modules/archiva-base/archiva-proxy/src/test/java/org/apache/maven/archiva/proxy/AbstractProxyTestCase.java20
-rw-r--r--archiva-modules/archiva-base/archiva-proxy/src/test/java/org/apache/maven/archiva/proxy/CacheFailuresTransferTest.java21
-rw-r--r--archiva-modules/archiva-base/archiva-proxy/src/test/java/org/apache/maven/archiva/proxy/ErrorHandlingTest.java2
-rw-r--r--archiva-modules/archiva-web/archiva-webapp/src/main/java/org/apache/maven/archiva/web/action/SearchAction.java129
-rw-r--r--archiva-modules/archiva-web/archiva-webapp/src/main/webapp/WEB-INF/jsp/admin/proxyConnectors.jsp18
-rw-r--r--archiva-modules/archiva-web/archiva-webapp/src/main/webapp/WEB-INF/jsp/include/quickSearchForm.jspf2
-rw-r--r--archiva-modules/archiva-web/archiva-webapp/src/main/webapp/WEB-INF/jsp/results.jsp102
-rw-r--r--archiva-modules/archiva-web/archiva-webapp/src/main/webapp/WEB-INF/tags/showArtifactLink.tag7
-rw-r--r--archiva-modules/archiva-web/archiva-webapp/src/main/webapp/images/icon_next_page.gifbin0 -> 315 bytes
-rw-r--r--archiva-modules/archiva-web/archiva-webapp/src/main/webapp/images/icon_next_page_disabled.gifbin0 -> 80 bytes
-rw-r--r--archiva-modules/archiva-web/archiva-webapp/src/main/webapp/images/icon_prev_page.gifbin0 -> 317 bytes
-rw-r--r--archiva-modules/archiva-web/archiva-webapp/src/main/webapp/images/icon_prev_page_disabled.gifbin0 -> 73 bytes
-rw-r--r--archiva-modules/archiva-web/archiva-webdav/src/main/java/org/apache/maven/archiva/webdav/ArchivaDavResourceFactory.java333
-rw-r--r--archiva-modules/archiva-web/archiva-webdav/src/main/java/org/apache/maven/archiva/webdav/RepositoryServlet.java8
-rw-r--r--archiva-modules/archiva-web/archiva-webdav/src/test/java/org/apache/maven/archiva/webdav/RepositoryServletRepositoryGroupTest.java74
-rw-r--r--archiva-modules/archiva-web/archiva-webdav/src/test/resources/org/apache/maven/archiva/webdav/RepositoryServletTest.xml14
-rw-r--r--pom.xml11
35 files changed, 1389 insertions, 194 deletions
diff --git a/archiva-docs/src/site/apt/release-notes.apt b/archiva-docs/src/site/apt/release-notes.apt
index 55f9bef7e..aae94d0d7 100644
--- a/archiva-docs/src/site/apt/release-notes.apt
+++ b/archiva-docs/src/site/apt/release-notes.apt
@@ -65,6 +65,8 @@ Release Notes for Archiva 1.1
* [MRM-801] - Create documentation for virtual repositories
+ * [MRM-861] - Paginate Search Results page
+
** Bug
* [MRM-234] - Moving files between repos through webdav doesn't work
@@ -75,6 +77,8 @@ Release Notes for Archiva 1.1
* [MRM-538] - Browse > Info not synchronised with updated POM contents
+ * [MRM-550] - proxy connectors - move up/down should not show when it's not possible
+
* [MRM-584] - Newly created user cannot login
* [MRM-597] - Cannot run Archiva as another user because su is run with option "-" (--login)
@@ -93,6 +97,8 @@ Release Notes for Archiva 1.1
* [MRM-638] - some developer reports are appearing in the archiva-docs module and need to be disabled
+ * [MRM-650] - Deleted metadata files still appear in search results
+
* [MRM-652] - Invalid html links in "webdav" directory browsing
* [MRM-653] - WebDAV deploy fails with error
@@ -175,6 +181,14 @@ Release Notes for Archiva 1.1
* [MRM-867] - 500 on HEAD method
+ * [MRM-869] - many empty folders created in managed repos with proxy connectors when used in a group
+
+ * [MRM-870] - addRepositoryToGroup.action => AbstractMethodError on DeferredDocumentImpl.getXmlStandalone()
+
+ * [MRM-871] - jetty.host and jetty.port properties are set by default in jetty.xml preventing user from using other hostname if user is not aware of these properties
+
+ * [MRM-872] - empty metadatas frmo a repository group
+
** Improvement
* [MRM-591] - Reports should show from which repository the defective artifact was found.
@@ -187,6 +201,8 @@ Release Notes for Archiva 1.1
* [MRM-678] - 404 errors on proxies should be cached
+ * [MRM-737] - Don't list metadata files in the search results
+
* [MRM-752] - Trim URL in Remote Repositories
* [MRM-760] - set JSW to auto-restart if it crashes or hangs
@@ -217,10 +233,14 @@ Release Notes for Archiva 1.1
* [MRM-694] - Virtual repositories or repository grouping
+ * [MRM-730] - Index/Search by class, method or package name
+
* [MRM-751] - Support database connection pooling
* [MRM-774] - Support inclusion of pom file when deploying an artifact via the web upload form
+ * [MRM-864] - Searching within search results
+
** Task
* [MRM-677] - Upgrade archiva to the latest redback (1.0.1)
@@ -230,7 +250,7 @@ Release Notes for Archiva 1.1
* [MRM-708] - Migrate from Plexus Logging to Slf4J
* [MRM-754] - Update the screenshots in the docs
-
+
* Changes in Archiva 1.0.2
** Bug
diff --git a/archiva-jetty/src/main/conf/jetty.xml b/archiva-jetty/src/main/conf/jetty.xml
index 5a106f08e..53a600fd8 100644
--- a/archiva-jetty/src/main/conf/jetty.xml
+++ b/archiva-jetty/src/main/conf/jetty.xml
@@ -50,17 +50,6 @@
-->
</Set>
-
- <Call class="java.lang.System" name="setProperty">
- <Arg>jetty.port</Arg>
- <Arg>8080</Arg>
- </Call>
-
- <Call class="java.lang.System" name="setProperty">
- <Arg>jetty.host</Arg>
- <Arg>localhost</Arg>
- </Call>
-
<!-- =========================================================== -->
<!-- Set connectors -->
<!-- =========================================================== -->
diff --git a/archiva-modules/archiva-base/archiva-consumers/archiva-lucene-consumers/pom.xml b/archiva-modules/archiva-base/archiva-consumers/archiva-lucene-consumers/pom.xml
index 100605093..14de945ce 100644
--- a/archiva-modules/archiva-base/archiva-consumers/archiva-lucene-consumers/pom.xml
+++ b/archiva-modules/archiva-base/archiva-consumers/archiva-lucene-consumers/pom.xml
@@ -49,6 +49,11 @@
<groupId>org.codehaus.plexus</groupId>
<artifactId>plexus-spring</artifactId>
<scope>test</scope>
- </dependency>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.bcel</groupId>
+ <artifactId>bcel</artifactId>
+ <version>5.2</version>
+ </dependency>
</dependencies>
</project>
diff --git a/archiva-modules/archiva-base/archiva-consumers/archiva-lucene-consumers/src/main/java/org/apache/maven/archiva/consumers/lucene/IndexContentConsumer.java b/archiva-modules/archiva-base/archiva-consumers/archiva-lucene-consumers/src/main/java/org/apache/maven/archiva/consumers/lucene/IndexContentConsumer.java
index 26d0cca6c..77fab6ea4 100644
--- a/archiva-modules/archiva-base/archiva-consumers/archiva-lucene-consumers/src/main/java/org/apache/maven/archiva/consumers/lucene/IndexContentConsumer.java
+++ b/archiva-modules/archiva-base/archiva-consumers/archiva-lucene-consumers/src/main/java/org/apache/maven/archiva/consumers/lucene/IndexContentConsumer.java
@@ -36,10 +36,13 @@ import org.apache.maven.archiva.repository.ManagedRepositoryContent;
import org.apache.maven.archiva.repository.RepositoryContentFactory;
import org.apache.maven.archiva.repository.RepositoryException;
import org.apache.maven.archiva.repository.layout.LayoutException;
+import org.apache.maven.archiva.repository.metadata.MetadataTools;
import org.codehaus.plexus.personality.plexus.lifecycle.phase.Initializable;
import org.codehaus.plexus.personality.plexus.lifecycle.phase.InitializationException;
import org.codehaus.plexus.registry.Registry;
import org.codehaus.plexus.registry.RegistryListener;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
import java.io.File;
import java.io.IOException;
@@ -60,6 +63,8 @@ public class IndexContentConsumer
extends AbstractMonitoredConsumer
implements KnownRepositoryContentConsumer, RegistryListener, Initializable
{
+ private Logger log = LoggerFactory.getLogger( IndexContentConsumer.class );
+
private static final String READ_CONTENT = "read_content";
private static final String INDEX_ERROR = "indexing_error";
@@ -147,6 +152,12 @@ public class IndexContentConsumer
public void processFile( String path )
throws ConsumerException
{
+ if ( path.endsWith( "/" + MetadataTools.MAVEN_METADATA ) )
+ {
+ log.debug( "File is a metadata file. Not indexing." );
+ return;
+ }
+
FileContentRecord record = new FileContentRecord();
try
{
diff --git a/archiva-modules/archiva-base/archiva-consumers/archiva-lucene-consumers/src/main/java/org/apache/maven/archiva/consumers/lucene/IndexJavaPublicMethodsConsumer.java b/archiva-modules/archiva-base/archiva-consumers/archiva-lucene-consumers/src/main/java/org/apache/maven/archiva/consumers/lucene/IndexJavaPublicMethodsConsumer.java
index 9f04c61d7..755755225 100644
--- a/archiva-modules/archiva-base/archiva-consumers/archiva-lucene-consumers/src/main/java/org/apache/maven/archiva/consumers/lucene/IndexJavaPublicMethodsConsumer.java
+++ b/archiva-modules/archiva-base/archiva-consumers/archiva-lucene-consumers/src/main/java/org/apache/maven/archiva/consumers/lucene/IndexJavaPublicMethodsConsumer.java
@@ -22,14 +22,34 @@ package org.apache.maven.archiva.consumers.lucene;
import org.apache.maven.archiva.consumers.AbstractMonitoredConsumer;
import org.apache.maven.archiva.consumers.ConsumerException;
import org.apache.maven.archiva.consumers.DatabaseUnprocessedArtifactConsumer;
+import org.apache.maven.archiva.indexer.RepositoryContentIndex;
+import org.apache.maven.archiva.indexer.RepositoryContentIndexFactory;
+import org.apache.maven.archiva.indexer.RepositoryIndexException;
+import org.apache.maven.archiva.indexer.bytecode.BytecodeRecord;
import org.apache.maven.archiva.model.ArchivaArtifact;
+import org.apache.maven.archiva.repository.ManagedRepositoryContent;
+import org.apache.maven.archiva.repository.RepositoryContentFactory;
+import org.apache.maven.archiva.repository.RepositoryException;
+import com.sun.org.apache.bcel.internal.classfile.ClassParser;
+import com.sun.org.apache.bcel.internal.classfile.JavaClass;
+import com.sun.org.apache.bcel.internal.classfile.Method;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Enumeration;
+import java.util.HashMap;
import java.util.List;
+import java.util.Map;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipFile;
/**
* IndexJavaPublicMethodsConsumer
*
* @author <a href="mailto:joakime@apache.org">Joakim Erdfelt</a>
+ * <a href="mailto:oching@apache.org">Maria Odea Ching</a>
* @version $Id$
*
* @plexus.component role="org.apache.maven.archiva.consumers.DatabaseUnprocessedArtifactConsumer"
@@ -49,11 +69,40 @@ public class IndexJavaPublicMethodsConsumer
* @plexus.configuration default-value="Index the java public methods for Full Text Search."
*/
private String description;
+
+ /**
+ * @plexus.requirement role-hint="lucene"
+ */
+ private RepositoryContentIndexFactory repoIndexFactory;
+
+ /**
+ * @plexus.requirement
+ */
+ private RepositoryContentFactory repoFactory;
+
+ private static final String CLASSES = "classes";
+
+ private static final String METHODS = "methods";
+
+ private List<String> includes = new ArrayList<String>();
+ public IndexJavaPublicMethodsConsumer()
+ {
+ includes.add( "jar" );
+ includes.add( "war" );
+ includes.add( "ear" );
+ includes.add( "zip" );
+ includes.add( "tar.gz" );
+ includes.add( "tar.bz2" );
+ includes.add( "car" );
+ includes.add( "sar" );
+ includes.add( "mar" );
+ includes.add( "rar" );
+ }
+
public void beginScan()
{
- // TODO Auto-generated method stub
-
+ // TODO Auto-generated method stubx
}
public void completeScan()
@@ -63,16 +112,58 @@ public class IndexJavaPublicMethodsConsumer
}
public List<String> getIncludedTypes()
- {
- // TODO Auto-generated method stub
- return null;
+ {
+ return includes;
}
public void processArchivaArtifact( ArchivaArtifact artifact )
throws ConsumerException
- {
- // TODO Auto-generated method stub
-
+ {
+ try
+ {
+ ManagedRepositoryContent repoContent =
+ repoFactory.getManagedRepositoryContent( artifact.getModel().getRepositoryId() );
+ File file = new File( repoContent.getRepoRoot(), repoContent.toPath( artifact ) );
+
+ if( file.getAbsolutePath().endsWith( ".jar" ) || file.getAbsolutePath().endsWith( ".war" ) ||
+ file.getAbsolutePath().endsWith( ".ear" ) || file.getAbsolutePath().endsWith( ".zip" ) ||
+ file.getAbsolutePath().endsWith( ".tar.gz" ) || file.getAbsolutePath().endsWith( ".tar.bz2" ) ||
+ file.getAbsolutePath().endsWith( ".car" ) || file.getAbsolutePath().endsWith( ".sar" ) ||
+ file.getAbsolutePath().endsWith( ".mar" ) || file.getAbsolutePath().endsWith( ".rar" ) )
+ {
+
+ if( file.exists() )
+ {
+ List<String> files = readFilesInArchive( file );
+ Map<String, List<String>> mapOfClassesAndMethods =
+ getPublicClassesAndMethodsFromFiles( file.getAbsolutePath(), files );
+
+ // NOTE: what about public variables? should these be indexed too?
+ RepositoryContentIndex bytecodeIndex = repoIndexFactory.createBytecodeIndex( repoContent.getRepository() );
+
+ BytecodeRecord bytecodeRecord = new BytecodeRecord();
+ bytecodeRecord.setFilename( file.getName() );
+ bytecodeRecord.setClasses( mapOfClassesAndMethods.get( CLASSES ) );
+ bytecodeRecord.setFiles( files );
+ bytecodeRecord.setMethods( mapOfClassesAndMethods.get( METHODS ) );
+ bytecodeRecord.setArtifact( artifact );
+ bytecodeRecord.setRepositoryId( artifact.getModel().getRepositoryId() );
+ bytecodeIndex.modifyRecord( bytecodeRecord );
+ }
+ }
+ }
+ catch ( RepositoryException e )
+ {
+ throw new ConsumerException( "Can't run index cleanup consumer: " + e.getMessage() );
+ }
+ catch ( RepositoryIndexException e )
+ {
+ throw new ConsumerException( "Error encountered while adding artifact to index: " + e.getMessage() );
+ }
+ catch ( IOException e )
+ {
+ throw new ConsumerException( "Error encountered while getting file contents: " + e.getMessage() );
+ }
}
public String getDescription()
@@ -89,5 +180,89 @@ public class IndexJavaPublicMethodsConsumer
{
return false;
}
+
+ private List<String> readFilesInArchive( File file )
+ throws IOException
+ {
+ ZipFile zipFile = new ZipFile( file );
+ List<String> files;
+
+ try
+ {
+ files = new ArrayList<String>( zipFile.size() );
+ for ( Enumeration entries = zipFile.entries(); entries.hasMoreElements(); )
+ {
+ ZipEntry entry = (ZipEntry) entries.nextElement();
+ files.add( entry.getName() );
+ }
+ }
+ finally
+ {
+ closeQuietly( zipFile );
+ }
+ return files;
+ }
+
+ private void closeQuietly( ZipFile zipFile )
+ {
+ try
+ {
+ if ( zipFile != null )
+ {
+ zipFile.close();
+ }
+ }
+ catch ( IOException e )
+ {
+ // ignored
+ }
+ }
+
+ private static boolean isClass( String name )
+ {
+ return name.endsWith( ".class" ) && name.lastIndexOf( "$" ) < 0;
+ }
+
+ private Map<String, List<String>> getPublicClassesAndMethodsFromFiles( String zipFile, List<String> files )
+ {
+ Map<String, List<String>> map = new HashMap<String, List<String>>();
+ List<String> methods = new ArrayList<String>();
+ List<String> classes = new ArrayList<String>();
+
+ for( String file : files )
+ {
+ if( isClass( file ) )
+ {
+ try
+ {
+ ClassParser parser = new ClassParser( zipFile, file );
+ JavaClass javaClass = parser.parse();
+
+ if( javaClass.isPublic() )
+ {
+ classes.add( javaClass.getClassName() );
+ }
+
+ Method[] methodsArr = javaClass.getMethods();
+ for( Method method : methodsArr )
+ {
+ if( method.isPublic() )
+ {
+ methods.add( method.getName() );
+ }
+ }
+ }
+ catch ( IOException e )
+ {
+ // ignore
+ }
+ }
+ }
+
+ map.put( CLASSES, classes );
+ map.put( METHODS, methods );
+
+ return map;
+ }
}
diff --git a/archiva-modules/archiva-base/archiva-consumers/archiva-lucene-consumers/src/test/java/org/apache/maven/archiva/consumers/lucene/IndexJavaPublicMethodsConsumerTest.java b/archiva-modules/archiva-base/archiva-consumers/archiva-lucene-consumers/src/test/java/org/apache/maven/archiva/consumers/lucene/IndexJavaPublicMethodsConsumerTest.java
new file mode 100644
index 000000000..83ae9588b
--- /dev/null
+++ b/archiva-modules/archiva-base/archiva-consumers/archiva-lucene-consumers/src/test/java/org/apache/maven/archiva/consumers/lucene/IndexJavaPublicMethodsConsumerTest.java
@@ -0,0 +1,124 @@
+package org.apache.maven.archiva.consumers.lucene;
+
+/*
+ * 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;
+
+import org.apache.maven.archiva.configuration.ArchivaConfiguration;
+import org.apache.maven.archiva.configuration.Configuration;
+import org.apache.maven.archiva.configuration.ManagedRepositoryConfiguration;
+import org.apache.maven.archiva.consumers.DatabaseUnprocessedArtifactConsumer;
+import org.apache.maven.archiva.indexer.RepositoryContentIndexFactory;
+import org.apache.maven.archiva.indexer.search.SearchResultLimits;
+import org.apache.maven.archiva.indexer.search.SearchResults;
+import org.apache.maven.archiva.model.ArchivaArtifact;
+import org.apache.maven.archiva.model.ArchivaArtifactModel;
+import org.codehaus.plexus.spring.PlexusInSpringTestCase;
+
+/**
+ *
+ * @author <a href="mailto:oching@apache.org">Maria Odea Ching</a>
+ * @version
+ *
+ */
+public class IndexJavaPublicMethodsConsumerTest
+ extends PlexusInSpringTestCase
+{
+ DatabaseUnprocessedArtifactConsumer indexMethodsConsumer;
+
+ IndexJavaPublicMethodsCrossRepositorySearch searcher;
+
+ private RepositoryContentIndexFactory indexFactory;
+
+ public void setUp()
+ throws Exception
+ {
+ super.setUp();
+ indexMethodsConsumer =
+ (DatabaseUnprocessedArtifactConsumer) lookup( DatabaseUnprocessedArtifactConsumer.class,
+ "index-public-methods" );
+
+ ManagedRepositoryConfiguration config = new ManagedRepositoryConfiguration();
+ config.setId( "test-repo" );
+ config.setLayout( "default" );
+ config.setLocation( getBasedir() + "/target/test-classes/test-repo" );
+ config.setName( "Test Repository" );
+
+ addRepoToConfiguration( "index-public-methods", config );
+
+ indexFactory = (RepositoryContentIndexFactory) lookup (RepositoryContentIndexFactory.class, "lucene" );
+ searcher = new IndexJavaPublicMethodsCrossRepositorySearch( config, indexFactory );
+ }
+
+ private void addRepoToConfiguration( String configHint, ManagedRepositoryConfiguration repoConfiguration )
+ throws Exception
+ {
+ ArchivaConfiguration archivaConfiguration =
+ (ArchivaConfiguration) lookup( ArchivaConfiguration.class, configHint );
+ Configuration configuration = archivaConfiguration.getConfiguration();
+ configuration.removeManagedRepository( configuration.findManagedRepositoryById( repoConfiguration.getId() ) );
+ configuration.addManagedRepository( repoConfiguration );
+ }
+
+ public void testJarPublicMethods()
+ throws Exception
+ {
+ ArchivaArtifact artifact =
+ createArtifact( "org.apache.archiva", "archiva-index-methods-jar-test", "1.0", "jar" );
+ indexMethodsConsumer.processArchivaArtifact( artifact );
+
+ List<String> selectedRepos = new ArrayList<String>();
+ selectedRepos.add( "test-repo" );
+
+ // search for class names
+ SearchResults results = searcher.searchForBytecode( "", selectedRepos, "FirstPackageApp", new SearchResultLimits( 0 ) );
+ assertEquals( 1, results.getTotalHits() );
+
+ results = searcher.searchForBytecode( "", selectedRepos, "SecondPackageApp", new SearchResultLimits( 0 ) );
+ assertEquals( 1, results.getTotalHits() );
+
+ // search for public methods
+ results = searcher.searchForBytecode( "", selectedRepos, "appMethodOne", new SearchResultLimits( 0 ) );
+ assertEquals( 1, results.getTotalHits() );
+
+ // should return only the overridding public method in SecondPackageApp
+ results = searcher.searchForBytecode( "", selectedRepos, "protectedMethod", new SearchResultLimits( 0 ) );
+ assertEquals( 1, results.getTotalHits() );
+
+ // should not return any private methods
+ results = searcher.searchForBytecode( "", selectedRepos, "privMethod", new SearchResultLimits( 0 ) );
+ assertEquals( 0, results.getTotalHits() );
+
+ // test for public variables?
+ }
+
+ private ArchivaArtifact createArtifact( String groupId, String artifactId, String version, String type )
+ {
+ ArchivaArtifactModel model = new ArchivaArtifactModel();
+ model.setGroupId( groupId );
+ model.setArtifactId( artifactId );
+ model.setVersion( version );
+ model.setType( type );
+ model.setRepositoryId( "test-repo" );
+
+ return new ArchivaArtifact( model );
+ }
+}
diff --git a/archiva-modules/archiva-base/archiva-consumers/archiva-lucene-consumers/src/test/java/org/apache/maven/archiva/consumers/lucene/IndexJavaPublicMethodsCrossRepositorySearch.java b/archiva-modules/archiva-base/archiva-consumers/archiva-lucene-consumers/src/test/java/org/apache/maven/archiva/consumers/lucene/IndexJavaPublicMethodsCrossRepositorySearch.java
new file mode 100644
index 000000000..ea9f13311
--- /dev/null
+++ b/archiva-modules/archiva-base/archiva-consumers/archiva-lucene-consumers/src/test/java/org/apache/maven/archiva/consumers/lucene/IndexJavaPublicMethodsCrossRepositorySearch.java
@@ -0,0 +1,191 @@
+package org.apache.maven.archiva.consumers.lucene;
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.lucene.document.Document;
+import org.apache.lucene.queryParser.ParseException;
+import org.apache.lucene.queryParser.QueryParser;
+import org.apache.lucene.search.Hits;
+import org.apache.lucene.search.MultiSearcher;
+import org.apache.lucene.search.Searchable;
+import org.apache.maven.archiva.configuration.ManagedRepositoryConfiguration;
+import org.apache.maven.archiva.indexer.RepositoryContentIndex;
+import org.apache.maven.archiva.indexer.RepositoryContentIndexFactory;
+import org.apache.maven.archiva.indexer.RepositoryIndexSearchException;
+import org.apache.maven.archiva.indexer.bytecode.BytecodeHandlers;
+import org.apache.maven.archiva.indexer.lucene.LuceneEntryConverter;
+import org.apache.maven.archiva.indexer.lucene.LuceneQuery;
+import org.apache.maven.archiva.indexer.lucene.LuceneRepositoryContentRecord;
+import org.apache.maven.archiva.indexer.search.SearchResultLimits;
+import org.apache.maven.archiva.indexer.search.SearchResults;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Searcher used for testing purposes only.
+ *
+ * @author <a href="mailto:oching@apache.org">Maria Odea Ching</a>
+ * @version
+ */
+public class IndexJavaPublicMethodsCrossRepositorySearch
+{
+ private Logger log = LoggerFactory.getLogger( IndexJavaPublicMethodsCrossRepositorySearch.class );
+
+ private ManagedRepositoryConfiguration localIndexedRepo;
+
+ private RepositoryContentIndexFactory indexFactory;
+
+ public IndexJavaPublicMethodsCrossRepositorySearch( ManagedRepositoryConfiguration localIndexedRepo, RepositoryContentIndexFactory indexFactory )
+ {
+ this.localIndexedRepo = localIndexedRepo;
+ this.indexFactory = indexFactory;
+ }
+
+ public SearchResults searchForBytecode( String principal, List<String> selectedRepos, String term,
+ SearchResultLimits limits ) throws ParseException
+ {
+ List<RepositoryContentIndex> indexes = new ArrayList<RepositoryContentIndex>();
+ indexes.add( indexFactory.createBytecodeIndex( localIndexedRepo ) );
+
+ QueryParser parser = new BytecodeHandlers().getQueryParser();
+ LuceneQuery query = new LuceneQuery( parser.parse( term ) );
+ SearchResults results = searchAll( query, limits, indexes );
+ results.getRepositories().add( localIndexedRepo );
+
+ return results;
+ }
+
+ private SearchResults searchAll( LuceneQuery luceneQuery, SearchResultLimits limits, List<RepositoryContentIndex> indexes )
+ {
+ org.apache.lucene.search.Query specificQuery = luceneQuery.getLuceneQuery();
+
+ SearchResults results = new SearchResults();
+
+ if ( indexes.isEmpty() )
+ {
+ // No point going any further.
+ return results;
+ }
+
+ // Setup the converter
+ LuceneEntryConverter converter = null;
+ RepositoryContentIndex index = indexes.get( 0 );
+ converter = index.getEntryConverter();
+
+ // Process indexes into an array of Searchables.
+ List<Searchable> searchableList = toSearchables( indexes );
+
+ Searchable searchables[] = new Searchable[searchableList.size()];
+ searchableList.toArray( searchables );
+
+ MultiSearcher searcher = null;
+
+ try
+ {
+ // Create a multi-searcher for looking up the information.
+ searcher = new MultiSearcher( searchables );
+
+ // Perform the search.
+ Hits hits = searcher.search( specificQuery );
+
+ int hitCount = hits.length();
+
+ // Now process the limits.
+ results.setLimits( limits );
+ results.setTotalHits( hitCount );
+
+ int fetchCount = limits.getPageSize();
+ int offset = ( limits.getSelectedPage() * limits.getPageSize() );
+
+ if ( limits.getSelectedPage() == SearchResultLimits.ALL_PAGES )
+ {
+ fetchCount = hitCount;
+ offset = 0;
+ }
+
+ // Goto offset.
+ if ( offset < hitCount )
+ {
+ // only process if the offset is within the hit count.
+ for ( int i = 0; i <= fetchCount; i++ )
+ {
+ // Stop fetching if we are past the total # of available hits.
+ if ( offset + i >= hitCount )
+ {
+ break;
+ }
+
+ try
+ {
+ Document doc = hits.doc( offset + i );
+ LuceneRepositoryContentRecord record = converter.convert( doc );
+ results.addHit( record );
+ }
+ catch ( java.text.ParseException e )
+ {
+ log.error( e.getMessage() );
+ }
+ }
+ }
+
+ }
+ catch ( IOException e )
+ {
+ log.error( e.getMessage() );
+ }
+ finally
+ {
+ try
+ {
+ if ( searcher != null )
+ {
+ searcher.close();
+ }
+ }
+ catch ( IOException ie )
+ {
+ log.error( ie.getMessage() );
+ }
+ }
+
+ return results;
+ }
+
+ private List<Searchable> toSearchables( List<RepositoryContentIndex> indexes )
+ {
+ List<Searchable> searchableList = new ArrayList<Searchable>();
+ for ( RepositoryContentIndex contentIndex : indexes )
+ {
+ try
+ {
+ searchableList.add( contentIndex.getSearchable() );
+ }
+ catch ( RepositoryIndexSearchException e )
+ {
+ log.error( e.getMessage() );
+ }
+ }
+ return searchableList;
+ }
+}
diff --git a/archiva-modules/archiva-base/archiva-consumers/archiva-lucene-consumers/src/test/resources/org/apache/maven/archiva/consumers/lucene/IndexJavaPublicMethodsConsumerTest.xml b/archiva-modules/archiva-base/archiva-consumers/archiva-lucene-consumers/src/test/resources/org/apache/maven/archiva/consumers/lucene/IndexJavaPublicMethodsConsumerTest.xml
new file mode 100644
index 000000000..93f760b56
--- /dev/null
+++ b/archiva-modules/archiva-base/archiva-consumers/archiva-lucene-consumers/src/test/resources/org/apache/maven/archiva/consumers/lucene/IndexJavaPublicMethodsConsumerTest.xml
@@ -0,0 +1,64 @@
+<component-set>
+ <components>
+<!-- for testing repo purge using retention count -->
+ <component>
+ <role>org.apache.maven.archiva.consumers.DatabaseUnprocessedArtifactConsumer</role>
+ <role-hint>index-public-methods</role-hint>
+ <implementation>org.apache.maven.archiva.consumers.lucene.IndexJavaPublicMethodsConsumer</implementation>
+ <requirements>
+ <requirement>
+ <role>org.apache.maven.archiva.repository.RepositoryContentFactory</role>
+ <role-hint>index-public-methods</role-hint>
+ </requirement>
+ <requirement>
+ <role>org.apache.maven.archiva.indexer.RepositoryContentIndexFactory</role>
+ <role-hint>lucene</role-hint>
+ <field-name>repoIndexFactory</field-name>
+ </requirement>
+ </requirements>
+ </component>
+ <component>
+ <role>org.apache.maven.archiva.repository.RepositoryContentFactory</role>
+ <role-hint>index-public-methods</role-hint>
+ <implementation>org.apache.maven.archiva.repository.RepositoryContentFactory</implementation>
+ <description>RepositoryContentRequest</description>
+ <requirements>
+ <requirement>
+ <role>org.apache.maven.archiva.configuration.ArchivaConfiguration</role>
+ <role-hint>index-public-methods</role-hint>
+ <field-name>archivaConfiguration</field-name>
+ </requirement>
+ </requirements>
+ </component>
+ <component>
+ <role>org.apache.maven.archiva.configuration.ArchivaConfiguration</role>
+ <role-hint>index-public-methods</role-hint>
+ <implementation>org.apache.maven.archiva.configuration.DefaultArchivaConfiguration</implementation>
+ <requirements>
+ <requirement>
+ <role>org.codehaus.plexus.registry.Registry</role>
+ <role-hint>index-public-methods</role-hint>
+ </requirement>
+ <requirement>
+ <role>org.apache.maven.archiva.policies.PreDownloadPolicy</role>
+ <field-name>prePolicies</field-name>
+ </requirement>
+ <requirement>
+ <role>org.apache.maven.archiva.policies.PostDownloadPolicy</role>
+ <field-name>postPolicies</field-name>
+ </requirement>
+ </requirements>
+ </component>
+ <component>
+ <role>org.codehaus.plexus.registry.Registry</role>
+ <role-hint>index-public-methods</role-hint>
+ <implementation>org.codehaus.plexus.registry.commons.CommonsConfigurationRegistry</implementation>
+ <configuration>
+ <properties>
+ <xml fileName="${basedir}/src/test/conf/repository-manager.xml"
+ config-name="org.apache.maven.archiva" config-at="org.apache.maven.archiva"/>
+ </properties>
+ </configuration>
+ </component>
+ </components>
+</component-set> \ No newline at end of file
diff --git a/archiva-modules/archiva-base/archiva-consumers/archiva-lucene-consumers/src/test/resources/test-repo/org/apache/archiva/archiva-index-methods-jar-test/1.0/archiva-index-methods-jar-test-1.0.jar b/archiva-modules/archiva-base/archiva-consumers/archiva-lucene-consumers/src/test/resources/test-repo/org/apache/archiva/archiva-index-methods-jar-test/1.0/archiva-index-methods-jar-test-1.0.jar
new file mode 100644
index 000000000..cc03dacc1
--- /dev/null
+++ b/archiva-modules/archiva-base/archiva-consumers/archiva-lucene-consumers/src/test/resources/test-repo/org/apache/archiva/archiva-index-methods-jar-test/1.0/archiva-index-methods-jar-test-1.0.jar
Binary files differ
diff --git a/archiva-modules/archiva-base/archiva-consumers/archiva-lucene-consumers/src/test/resources/test-repo/org/apache/archiva/archiva-index-methods-jar-test/1.0/pom.xml b/archiva-modules/archiva-base/archiva-consumers/archiva-lucene-consumers/src/test/resources/test-repo/org/apache/archiva/archiva-index-methods-jar-test/1.0/pom.xml
new file mode 100644
index 000000000..e7bf54bda
--- /dev/null
+++ b/archiva-modules/archiva-base/archiva-consumers/archiva-lucene-consumers/src/test/resources/test-repo/org/apache/archiva/archiva-index-methods-jar-test/1.0/pom.xml
@@ -0,0 +1,18 @@
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <groupId>org.apache.archiva</groupId>
+ <artifactId>archiva-index-methods-jar-test</artifactId>
+ <packaging>jar</packaging>
+ <version>1.0</version>
+ <name>archiva-index-methods-jar-test</name>
+ <url>http://maven.apache.org</url>
+ <dependencies>
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <version>3.8.1</version>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+</project>
diff --git a/archiva-modules/archiva-base/archiva-indexer/src/main/java/org/apache/maven/archiva/indexer/bytecode/BytecodeRecord.java b/archiva-modules/archiva-base/archiva-indexer/src/main/java/org/apache/maven/archiva/indexer/bytecode/BytecodeRecord.java
index 1cb7422a9..888067da5 100644
--- a/archiva-modules/archiva-base/archiva-indexer/src/main/java/org/apache/maven/archiva/indexer/bytecode/BytecodeRecord.java
+++ b/archiva-modules/archiva-base/archiva-indexer/src/main/java/org/apache/maven/archiva/indexer/bytecode/BytecodeRecord.java
@@ -39,28 +39,28 @@ public class BytecodeRecord
private String filename;
- private List classes;
+ private List<String> classes;
- private List methods;
+ private List<String> methods;
- private List files;
+ private List<String> files;
public ArchivaArtifact getArtifact()
{
return artifact;
}
- public List getClasses()
+ public List<String> getClasses()
{
return classes;
}
- public List getFiles()
+ public List<String> getFiles()
{
return files;
}
- public List getMethods()
+ public List<String> getMethods()
{
return methods;
}
@@ -92,17 +92,17 @@ public class BytecodeRecord
this.artifact = artifact;
}
- public void setClasses( List classes )
+ public void setClasses( List<String> classes )
{
this.classes = classes;
}
- public void setFiles( List files )
+ public void setFiles( List<String> files )
{
this.files = files;
}
- public void setMethods( List methods )
+ public void setMethods( List<String> methods )
{
this.methods = methods;
}
diff --git a/archiva-modules/archiva-base/archiva-indexer/src/main/java/org/apache/maven/archiva/indexer/filecontent/FileContentRecord.java b/archiva-modules/archiva-base/archiva-indexer/src/main/java/org/apache/maven/archiva/indexer/filecontent/FileContentRecord.java
index 7b1365b23..af039c8c7 100644
--- a/archiva-modules/archiva-base/archiva-indexer/src/main/java/org/apache/maven/archiva/indexer/filecontent/FileContentRecord.java
+++ b/archiva-modules/archiva-base/archiva-indexer/src/main/java/org/apache/maven/archiva/indexer/filecontent/FileContentRecord.java
@@ -64,7 +64,7 @@ public class FileContentRecord
public String getPrimaryKey()
{
- return filename;
+ return repositoryId + ":" + filename;
}
public int hashCode()
diff --git a/archiva-modules/archiva-base/archiva-indexer/src/main/java/org/apache/maven/archiva/indexer/search/CrossRepositorySearch.java b/archiva-modules/archiva-base/archiva-indexer/src/main/java/org/apache/maven/archiva/indexer/search/CrossRepositorySearch.java
index 73c8cf61a..63e21151c 100644
--- a/archiva-modules/archiva-base/archiva-indexer/src/main/java/org/apache/maven/archiva/indexer/search/CrossRepositorySearch.java
+++ b/archiva-modules/archiva-base/archiva-indexer/src/main/java/org/apache/maven/archiva/indexer/search/CrossRepositorySearch.java
@@ -40,6 +40,19 @@ public interface CrossRepositorySearch
public SearchResults searchForTerm( String principal, List<String> selectedRepos, String term, SearchResultLimits limits );
/**
+ * Search for a specific term from the previous search results.
+ *
+ * @param principal the user doing the search.
+ * @param selectedRepos the repositories to search from.
+ * @param term the term to search for.
+ * @param limits the limits to apply to the search results.
+ * @param previousSearchTerms the list of the previous search terms.
+ * @return the results
+ */
+ public SearchResults searchForTerm( String principal, List<String> selectedRepos, String term,
+ SearchResultLimits limits, List<String> previousSearchTerms );
+
+ /**
* Search for the specific bytecode across all repositories.
*
* @param term the term to search for.
diff --git a/archiva-modules/archiva-base/archiva-indexer/src/main/java/org/apache/maven/archiva/indexer/search/DefaultCrossRepositorySearch.java b/archiva-modules/archiva-base/archiva-indexer/src/main/java/org/apache/maven/archiva/indexer/search/DefaultCrossRepositorySearch.java
index 98490ebe4..8565acc46 100644
--- a/archiva-modules/archiva-base/archiva-indexer/src/main/java/org/apache/maven/archiva/indexer/search/DefaultCrossRepositorySearch.java
+++ b/archiva-modules/archiva-base/archiva-indexer/src/main/java/org/apache/maven/archiva/indexer/search/DefaultCrossRepositorySearch.java
@@ -27,8 +27,12 @@ import org.apache.lucene.document.Document;
import org.apache.lucene.queryParser.MultiFieldQueryParser;
import org.apache.lucene.queryParser.ParseException;
import org.apache.lucene.queryParser.QueryParser;
+import org.apache.lucene.search.BooleanClause;
+import org.apache.lucene.search.BooleanQuery;
+import org.apache.lucene.search.Filter;
import org.apache.lucene.search.Hits;
import org.apache.lucene.search.MultiSearcher;
+import org.apache.lucene.search.QueryWrapperFilter;
import org.apache.lucene.search.Searchable;
import org.apache.maven.archiva.configuration.ArchivaConfiguration;
import org.apache.maven.archiva.configuration.ConfigurationNames;
@@ -84,7 +88,7 @@ public class DefaultCrossRepositorySearch
QueryParser parser = new MultiFieldQueryParser( new String[]{HashcodesKeys.MD5, HashcodesKeys.SHA1},
new HashcodesHandlers().getAnalyzer() );
LuceneQuery query = new LuceneQuery( parser.parse( checksum ) );
- SearchResults results = searchAll( query, limits, indexes );
+ SearchResults results = searchAll( query, limits, indexes, null );
results.getRepositories().addAll( this.localIndexedRepositories );
return results;
@@ -100,13 +104,13 @@ public class DefaultCrossRepositorySearch
public SearchResults searchForBytecode( String principal, List<String> selectedRepos, String term, SearchResultLimits limits )
{
- List<RepositoryContentIndex> indexes = getHashcodeIndexes( principal, selectedRepos );
+ List<RepositoryContentIndex> indexes = getBytecodeIndexes( principal, selectedRepos );
try
{
QueryParser parser = new BytecodeHandlers().getQueryParser();
LuceneQuery query = new LuceneQuery( parser.parse( term ) );
- SearchResults results = searchAll( query, limits, indexes );
+ SearchResults results = searchAll( query, limits, indexes, null );
results.getRepositories().addAll( this.localIndexedRepositories );
return results;
@@ -120,17 +124,44 @@ public class DefaultCrossRepositorySearch
return new SearchResults();
}
+
public SearchResults searchForTerm( String principal, List<String> selectedRepos, String term, SearchResultLimits limits )
{
+ return searchForTerm( principal, selectedRepos, term, limits, null );
+ }
+
+ public SearchResults searchForTerm( String principal, List<String> selectedRepos, String term,
+ SearchResultLimits limits, List<String> previousSearchTerms )
+ {
List<RepositoryContentIndex> indexes = getFileContentIndexes( principal, selectedRepos );
+ List<RepositoryContentIndex> bytecodeIndices = getBytecodeIndexes( principal, selectedRepos );
+ indexes.addAll( bytecodeIndices );
try
{
QueryParser parser = new FileContentHandlers().getQueryParser();
- LuceneQuery query = new LuceneQuery( parser.parse( term ) );
- SearchResults results = searchAll( query, limits, indexes );
+ LuceneQuery query = null;
+ SearchResults results = null;
+ if( previousSearchTerms == null || previousSearchTerms.isEmpty() )
+ {
+ query = new LuceneQuery( parser.parse( term ) );
+ results = searchAll( query, limits, indexes, null );
+ }
+ else
+ {
+ // AND the previous search terms
+ BooleanQuery booleanQuery = new BooleanQuery();
+ for( String previousSearchTerm : previousSearchTerms )
+ {
+ booleanQuery.add( parser.parse( previousSearchTerm ), BooleanClause.Occur.MUST );
+ }
+
+ query = new LuceneQuery( booleanQuery );
+ Filter filter = new QueryWrapperFilter( parser.parse( term ) );
+ results = searchAll( query, limits, indexes, filter );
+ }
results.getRepositories().addAll( this.localIndexedRepositories );
-
+
return results;
}
catch ( ParseException e )
@@ -139,10 +170,10 @@ public class DefaultCrossRepositorySearch
}
// empty results.
- return new SearchResults();
+ return new SearchResults();
}
-
- private SearchResults searchAll( LuceneQuery luceneQuery, SearchResultLimits limits, List<RepositoryContentIndex> indexes )
+
+ private SearchResults searchAll( LuceneQuery luceneQuery, SearchResultLimits limits, List<RepositoryContentIndex> indexes, Filter filter )
{
org.apache.lucene.search.Query specificQuery = luceneQuery.getLuceneQuery();
@@ -173,7 +204,15 @@ public class DefaultCrossRepositorySearch
searcher = new MultiSearcher( searchables );
// Perform the search.
- Hits hits = searcher.search( specificQuery );
+ Hits hits = null;
+ if( filter != null )
+ {
+ hits = searcher.search( specificQuery, filter );
+ }
+ else
+ {
+ hits = searcher.search( specificQuery );
+ }
int hitCount = hits.length();
@@ -194,7 +233,7 @@ public class DefaultCrossRepositorySearch
if ( offset < hitCount )
{
// only process if the offset is within the hit count.
- for ( int i = 0; i <= fetchCount; i++ )
+ for ( int i = 0; i < fetchCount; i++ )
{
// Stop fetching if we are past the total # of available hits.
if ( offset + i >= hitCount )
diff --git a/archiva-modules/archiva-base/archiva-indexer/src/main/java/org/apache/maven/archiva/indexer/search/SearchResultHit.java b/archiva-modules/archiva-base/archiva-indexer/src/main/java/org/apache/maven/archiva/indexer/search/SearchResultHit.java
index 1d2f74437..2933fae8e 100644
--- a/archiva-modules/archiva-base/archiva-indexer/src/main/java/org/apache/maven/archiva/indexer/search/SearchResultHit.java
+++ b/archiva-modules/archiva-base/archiva-indexer/src/main/java/org/apache/maven/archiva/indexer/search/SearchResultHit.java
@@ -46,6 +46,8 @@ public class SearchResultHit
private String artifactId;
private String version = "";
+
+ private String repositoryId = "";
// Advanced hit, if artifact, all versions of artifact
private List artifacts = new ArrayList();
@@ -138,4 +140,14 @@ public class SearchResultHit
{
return versions;
}
+
+ public String getRepositoryId()
+ {
+ return repositoryId;
+ }
+
+ public void setRepositoryId( String repositoryId )
+ {
+ this.repositoryId = repositoryId;
+ }
}
diff --git a/archiva-modules/archiva-base/archiva-indexer/src/main/java/org/apache/maven/archiva/indexer/search/SearchResults.java b/archiva-modules/archiva-base/archiva-indexer/src/main/java/org/apache/maven/archiva/indexer/search/SearchResults.java
index 6e2f8fa80..6465814c3 100644
--- a/archiva-modules/archiva-base/archiva-indexer/src/main/java/org/apache/maven/archiva/indexer/search/SearchResults.java
+++ b/archiva-modules/archiva-base/archiva-indexer/src/main/java/org/apache/maven/archiva/indexer/search/SearchResults.java
@@ -126,6 +126,7 @@ public class SearchResults
// Only need to worry about this hit if it is truely new.
hit = new SearchResultHit();
+ hit.setRepositoryId( filecontent.getRepositoryId() );
hit.setUrl( filecontent.getRepositoryId() + "/" + filecontent.getFilename() );
hit.setContext( null ); // TODO: handle context + highlight later.
diff --git a/archiva-modules/archiva-base/archiva-indexer/src/test/java/org/apache/maven/archiva/indexer/search/DefaultCrossRepositorySearchTest.java b/archiva-modules/archiva-base/archiva-indexer/src/test/java/org/apache/maven/archiva/indexer/search/DefaultCrossRepositorySearchTest.java
index a503d6f8b..576b54481 100644
--- a/archiva-modules/archiva-base/archiva-indexer/src/test/java/org/apache/maven/archiva/indexer/search/DefaultCrossRepositorySearchTest.java
+++ b/archiva-modules/archiva-base/archiva-indexer/src/test/java/org/apache/maven/archiva/indexer/search/DefaultCrossRepositorySearchTest.java
@@ -140,7 +140,7 @@ public class DefaultCrossRepositorySearchTest
"org","org2","org3","org4","org5","org6","org7"
};
- assertSearchResults( expectedRepos, expectedResults, search, "org" );
+ assertSearchResults( expectedRepos, expectedResults, search, "org", null );
}
public void testSearchTerm_Junit()
@@ -156,7 +156,7 @@ public class DefaultCrossRepositorySearchTest
"junit","junit2","junit3"
};
- assertSearchResults( expectedRepos, expectedResults, search, "junit" );
+ assertSearchResults( expectedRepos, expectedResults, search, "junit", null );
}
public void testSearchInvalidTerm()
@@ -172,10 +172,49 @@ public class DefaultCrossRepositorySearchTest
// Nothing.
};
- assertSearchResults( expectedRepos, expectedResults, search, "monosodium" );
+ assertSearchResults( expectedRepos, expectedResults, search, "monosodium", null );
}
- private void assertSearchResults( String expectedRepos[], String expectedResults[], CrossRepositorySearch search, String term )
+ public void testSearchWithinSearchResults()
+ throws Exception
+ {
+ CrossRepositorySearch search = lookupCrossRepositorySearch();
+
+ String expectedRepos[] = new String[] {
+ TEST_DEFAULT_REPO_ID
+ };
+
+ String expectedResults[] = new String[] {
+ "org","org2","org3","org4","org5","org6","org7"
+ };
+
+ // first search
+ assertSearchResults( expectedRepos, expectedResults, search, "org", null );
+
+ List<String> previousSearchTerms = new ArrayList<String>();
+ previousSearchTerms.add( "org" );
+ String secondSearchExpectedResults[] = new String[] {
+ "org.apache.maven.archiva.record", "org.apache.maven.archiva.record2",
+ "org.apache.maven.archiva.record3", "org.apache.maven.archiva.record4",
+ "org.apache.maven.archiva.record5", "org.apache.maven.archiva.record6",
+ "org.apache.maven.archiva.record7"
+ };
+
+ //second search
+ assertSearchResults( expectedRepos, secondSearchExpectedResults, search, "org.apache.maven.archiva.record",
+ previousSearchTerms );
+
+ previousSearchTerms.add( "org.apache.maven.archiva.record" );
+ String thirdSearchExpectedResults[] = new String[] {
+ "junit", "junit2", "junit3"
+ };
+
+ //third search
+ assertSearchResults( expectedRepos, thirdSearchExpectedResults, search, "junit", previousSearchTerms );
+ }
+
+ private void assertSearchResults( String expectedRepos[], String expectedResults[], CrossRepositorySearch search,
+ String term, List<String> previousSearchTerms )
throws Exception
{
SearchResultLimits limits = new SearchResultLimits( 0 );
@@ -184,7 +223,15 @@ public class DefaultCrossRepositorySearchTest
List<String> selectedRepos = new ArrayList<String>();
selectedRepos.addAll( Arrays.asList( expectedRepos ) );
- SearchResults results = search.searchForTerm( "guest", selectedRepos, term, limits );
+ SearchResults results = null;
+ if( previousSearchTerms == null )
+ {
+ results = search.searchForTerm( "guest", selectedRepos, term, limits );
+ }
+ else
+ {
+ results = search.searchForTerm( "guest", selectedRepos, term, limits, previousSearchTerms );
+ }
assertNotNull( "Search Results should not be null.", results );
assertEquals( "Repository Hits", expectedRepos.length, results.getRepositories().size() );
diff --git a/archiva-modules/archiva-base/archiva-proxy/src/main/java/org/apache/maven/archiva/proxy/DefaultRepositoryProxyConnectors.java b/archiva-modules/archiva-base/archiva-proxy/src/main/java/org/apache/maven/archiva/proxy/DefaultRepositoryProxyConnectors.java
index 398734973..c2937fe3e 100644
--- a/archiva-modules/archiva-base/archiva-proxy/src/main/java/org/apache/maven/archiva/proxy/DefaultRepositoryProxyConnectors.java
+++ b/archiva-modules/archiva-base/archiva-proxy/src/main/java/org/apache/maven/archiva/proxy/DefaultRepositoryProxyConnectors.java
@@ -88,7 +88,7 @@ public class DefaultRepositoryProxyConnectors
implements RepositoryProxyConnectors, RegistryListener, Initializable
{
private Logger log = LoggerFactory.getLogger( DefaultRepositoryProxyConnectors.class );
-
+
/**
* @plexus.requirement
*/
@@ -169,7 +169,7 @@ public class DefaultRepositoryProxyConnectors
try
{
File downloadedFile =
- transferFile( connector, targetRepository, targetPath, localFile, requestProperties );
+ transferFile( connector, targetRepository, targetPath, repository, localFile, requestProperties );
if ( fileExists( downloadedFile ) )
{
@@ -230,7 +230,7 @@ public class DefaultRepositoryProxyConnectors
try
{
- transferFile( connector, targetRepository, targetPath, localRepoFile, requestProperties );
+ transferFile( connector, targetRepository, targetPath, repository, localRepoFile, requestProperties );
if ( hasBeenUpdated( localRepoFile, originalMetadataTimestamp ) )
{
@@ -348,7 +348,7 @@ public class DefaultRepositoryProxyConnectors
long originalMetadataTimestamp = getLastModified( localRepoFile );
try
{
- transferFile( connector, targetRepository, targetPath, localRepoFile, requestProperties );
+ transferFile( connector, targetRepository, targetPath, repository, localRepoFile, requestProperties );
if ( hasBeenUpdated( localRepoFile, originalMetadataTimestamp ) )
{
@@ -487,6 +487,7 @@ public class DefaultRepositoryProxyConnectors
* @param connector the connector configuration to use.
* @param remoteRepository the remote repository get the resource from.
* @param remotePath the path in the remote repository to the resource to get.
+ * @param repository the managed repository that will hold the file
* @param localFile the local file to place the downloaded resource into
* @param requestProperties the request properties to utilize for policy handling.
* @return the local file that was downloaded, or null if not downloaded.
@@ -496,7 +497,7 @@ public class DefaultRepositoryProxyConnectors
* @throws ProxyException if transfer was unsuccessful.
*/
private File transferFile( ProxyConnector connector, RemoteRepositoryContent remoteRepository, String remotePath,
- File localFile, Properties requestProperties )
+ ManagedRepositoryContent repository, File localFile, Properties requestProperties )
throws ProxyException, NotModifiedException
{
String url = remoteRepository.getURL().getUrl();
@@ -560,10 +561,10 @@ public class DefaultRepositoryProxyConnectors
boolean connected = connectToRepository( connector, wagon, remoteRepository );
if ( connected )
{
- localFile = transferSimpleFile( wagon, remoteRepository, remotePath, localFile );
+ localFile = transferSimpleFile( wagon, remoteRepository, remotePath, repository, localFile );
- transferChecksum( wagon, remoteRepository, remotePath, localFile, ".sha1" );
- transferChecksum( wagon, remoteRepository, remotePath, localFile, ".md5" );
+ transferChecksum( wagon, remoteRepository, remotePath, repository, localFile, ".sha1" );
+ transferChecksum( wagon, remoteRepository, remotePath, repository, localFile, ".md5" );
}
}
catch ( NotFoundException e )
@@ -627,12 +628,13 @@ public class DefaultRepositoryProxyConnectors
* @param wagon the wagon instance (should already be connected) to use.
* @param remoteRepository the remote repository to transfer from.
* @param remotePath the remote path to the resource to get.
+ * @param repository the managed repository that will hold the file
* @param localFile the local file that should contain the downloaded contents
* @param type the type of checksum to transfer (example: ".md5" or ".sha1")
* @throws ProxyException if copying the downloaded file into place did not succeed.
*/
private void transferChecksum( Wagon wagon, RemoteRepositoryContent remoteRepository, String remotePath,
- File localFile, String type )
+ ManagedRepositoryContent repository, File localFile, String type )
throws ProxyException
{
String url = remoteRepository.getURL().getUrl() + remotePath;
@@ -646,7 +648,7 @@ public class DefaultRepositoryProxyConnectors
try
{
File hashFile = new File( localFile.getAbsolutePath() + type );
- transferSimpleFile( wagon, remoteRepository, remotePath + type, hashFile );
+ transferSimpleFile( wagon, remoteRepository, remotePath + type, repository, hashFile );
log.debug( "Checksum" + type + " Downloaded: " + hashFile );
}
catch ( NotFoundException e )
@@ -675,13 +677,14 @@ public class DefaultRepositoryProxyConnectors
* @param wagon the wagon instance to use.
* @param remoteRepository the remote repository to use
* @param remotePath the remote path to attempt to get
+ * @param repository the managed repository that will hold the file
* @param localFile the local file to save to
* @return The local file that was transfered.
* @throws ProxyException if there was a problem moving the downloaded file into place.
* @throws WagonException if there was a problem tranfering the file.
*/
private File transferSimpleFile( Wagon wagon, RemoteRepositoryContent remoteRepository, String remotePath,
- File localFile )
+ ManagedRepositoryContent repository, File localFile )
throws ProxyException
{
assert ( remotePath != null );
@@ -691,9 +694,8 @@ public class DefaultRepositoryProxyConnectors
try
{
- localFile.getParentFile().mkdirs();
- temp = File.createTempFile(localFile.getName() + ".", null, localFile.getParentFile());
-
+ temp = File.createTempFile(localFile.getName() + ".", null, new File( repository.getRepoRoot() ));
+
boolean success = false;
if ( !localFile.exists() )
@@ -849,6 +851,7 @@ public class DefaultRepositoryProxyConnectors
throw new ProxyException( "Unable to overwrite existing target file: " + target.getAbsolutePath() );
}
+ target.getParentFile().mkdirs();
if ( !temp.renameTo( target ) )
{
log.warn( "Unable to rename tmp file to its final name... resorting to copy command." );
@@ -1004,15 +1007,15 @@ public class DefaultRepositoryProxyConnectors
{
/* do nothing */
}
-
+
private void logProcess( String managedRepoId, String resource, String event )
{
-
+
}
-
+
private void logRejection( String managedRepoId, String remoteRepoId, String resource, String reason )
{
-
+
}
private void initConnectorsAndNetworkProxies()
diff --git a/archiva-modules/archiva-base/archiva-proxy/src/test/java/org/apache/maven/archiva/proxy/AbstractProxyTestCase.java b/archiva-modules/archiva-base/archiva-proxy/src/test/java/org/apache/maven/archiva/proxy/AbstractProxyTestCase.java
index db4a91dc2..e71ea65b0 100644
--- a/archiva-modules/archiva-base/archiva-proxy/src/test/java/org/apache/maven/archiva/proxy/AbstractProxyTestCase.java
+++ b/archiva-modules/archiva-base/archiva-proxy/src/test/java/org/apache/maven/archiva/proxy/AbstractProxyTestCase.java
@@ -88,7 +88,7 @@ public abstract class AbstractProxyTestCase
protected static final String REPOPATH_LEGACY_MANAGED = "src/test/repositories/legacy-managed";
protected static final String REPOPATH_LEGACY_MANAGED_TARGET = "target/test-repository/legacy-managed";
-
+
protected static final ArgumentsMatcher customWagonGetIfNewerMatcher = new ArgumentsMatcher() {
public boolean matches(Object[] expected, Object[] actual) {
@@ -103,10 +103,10 @@ public abstract class AbstractProxyTestCase
return ArrayUtils.toString(arguments);
}
};
-
+
protected static final ArgumentsMatcher customWagonGetMatcher = new ArgumentsMatcher() {
- public boolean matches(Object[] expected, Object[] actual)
+ public boolean matches(Object[] expected, Object[] actual)
{
if (expected.length == 2 && actual.length == 2)
{
@@ -114,23 +114,23 @@ public abstract class AbstractProxyTestCase
{
return true;
}
-
+
if (expected[0] == null)
{
return actual[0] == null;
}
-
+
if (actual[0] == null)
{
return expected[0] == null;
}
-
+
return expected[0].equals(actual[0]);
}
return false;
}
- public String toString(Object[] arguments)
+ public String toString(Object[] arguments)
{
return ArrayUtils.toString(arguments);
}
@@ -540,6 +540,9 @@ public abstract class AbstractProxyTestCase
FileUtils.deleteDirectory( destDir );
}
+ // Make the destination dir.
+ destDir.mkdirs();
+
// Test the source dir.
if ( !sourceDir.exists() )
{
@@ -555,9 +558,6 @@ public abstract class AbstractProxyTestCase
fail( "Unable to setup testable managed repository, source is not a directory: " + sourceDir );
}
- // Make the destination dir.
- destDir.mkdirs();
-
// Copy directory structure.
copyDirectoryStructure( sourceDir, destDir );
}
diff --git a/archiva-modules/archiva-base/archiva-proxy/src/test/java/org/apache/maven/archiva/proxy/CacheFailuresTransferTest.java b/archiva-modules/archiva-base/archiva-proxy/src/test/java/org/apache/maven/archiva/proxy/CacheFailuresTransferTest.java
index 70aec32fc..119211d6c 100644
--- a/archiva-modules/archiva-base/archiva-proxy/src/test/java/org/apache/maven/archiva/proxy/CacheFailuresTransferTest.java
+++ b/archiva-modules/archiva-base/archiva-proxy/src/test/java/org/apache/maven/archiva/proxy/CacheFailuresTransferTest.java
@@ -63,11 +63,11 @@ public class CacheFailuresTransferTest
SnapshotsPolicy.ALWAYS, CachedFailuresPolicy.YES );
saveConnector( ID_DEFAULT_MANAGED, "badproxied2", ChecksumPolicy.FIX, ReleasesPolicy.ALWAYS,
SnapshotsPolicy.ALWAYS, CachedFailuresPolicy.YES );
-
+
wagonMock.get( path, new File( expectedFile.getParentFile(), expectedFile.getName() + ".tmp" ) );
-
+
wagonMockControl.setMatcher(customWagonGetMatcher);
-
+
wagonMockControl.setThrowable( new ResourceDoesNotExistException( "resource does not exist." ), 2 );
wagonMockControl.replay();
@@ -75,11 +75,11 @@ public class CacheFailuresTransferTest
File downloadedFile = proxyHandler.fetchFromProxies( managedDefaultRepository, artifact );
wagonMockControl.verify();
-
- // Second attempt to download same artifact use cache
+
+ // Second attempt to download same artifact use cache
wagonMockControl.reset();
wagonMockControl.replay();
- downloadedFile = proxyHandler.fetchFromProxies( managedDefaultRepository, artifact );
+ downloadedFile = proxyHandler.fetchFromProxies( managedDefaultRepository, artifact );
wagonMockControl.verify();
assertNotDownloaded( downloadedFile );
@@ -108,7 +108,7 @@ public class CacheFailuresTransferTest
SnapshotsPolicy.ALWAYS, CachedFailuresPolicy.NO );
wagonMock.get( path, new File( expectedFile.getParentFile(), expectedFile.getName() + ".tmp" ) );
-
+
wagonMockControl.setMatcher(customWagonGetMatcher);
wagonMockControl.setThrowable( new ResourceDoesNotExistException( "resource does not exist." ), 2 );
@@ -118,15 +118,15 @@ public class CacheFailuresTransferTest
wagonMockControl.verify();
- // Second attempt to download same artifact DOES NOT use cache
+ // Second attempt to download same artifact DOES NOT use cache
wagonMockControl.reset();
wagonMock.get( path, new File( expectedFile.getParentFile(), expectedFile.getName() + ".tmp" ) );
-
+
wagonMockControl.setMatcher(customWagonGetMatcher);
wagonMockControl.setThrowable( new ResourceDoesNotExistException( "resource does not exist." ), 2 );
wagonMockControl.replay();
- downloadedFile = proxyHandler.fetchFromProxies( managedDefaultRepository, artifact );
+ downloadedFile = proxyHandler.fetchFromProxies( managedDefaultRepository, artifact );
wagonMockControl.verify();
@@ -138,6 +138,7 @@ public class CacheFailuresTransferTest
throws Exception
{
String path = "org/apache/maven/test/get-in-second-proxy/1.0/get-in-second-proxy-1.0.jar";
+ setupTestableManagedRepository( path );
File expectedFile = new File( managedDefaultDir, path );
ArtifactReference artifact = managedDefaultRepository.toArtifactReference( path );
diff --git a/archiva-modules/archiva-base/archiva-proxy/src/test/java/org/apache/maven/archiva/proxy/ErrorHandlingTest.java b/archiva-modules/archiva-base/archiva-proxy/src/test/java/org/apache/maven/archiva/proxy/ErrorHandlingTest.java
index c0c60a720..4b96766c7 100644
--- a/archiva-modules/archiva-base/archiva-proxy/src/test/java/org/apache/maven/archiva/proxy/ErrorHandlingTest.java
+++ b/archiva-modules/archiva-base/archiva-proxy/src/test/java/org/apache/maven/archiva/proxy/ErrorHandlingTest.java
@@ -551,7 +551,7 @@ public class ErrorHandlingTest
private File createExpectedTempFile( File expectedFile )
{
- return new File( expectedFile.getParentFile(), expectedFile.getName() + ".tmp" ).getAbsoluteFile();
+ return new File( managedDefaultDir, expectedFile.getName() + ".tmp" ).getAbsoluteFile();
}
private void confirmSingleFailure( String path, String id )
diff --git a/archiva-modules/archiva-web/archiva-webapp/src/main/java/org/apache/maven/archiva/web/action/SearchAction.java b/archiva-modules/archiva-web/archiva-webapp/src/main/java/org/apache/maven/archiva/web/action/SearchAction.java
index 6e91a5799..92b203c84 100644
--- a/archiva-modules/archiva-web/archiva-webapp/src/main/java/org/apache/maven/archiva/web/action/SearchAction.java
+++ b/archiva-modules/archiva-web/archiva-webapp/src/main/java/org/apache/maven/archiva/web/action/SearchAction.java
@@ -20,6 +20,7 @@ package org.apache.maven.archiva.web.action;
*/
import java.net.MalformedURLException;
+import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
@@ -34,8 +35,11 @@ import org.apache.maven.archiva.indexer.RepositoryIndexSearchException;
import org.apache.maven.archiva.indexer.search.CrossRepositorySearch;
import org.apache.maven.archiva.indexer.search.SearchResultLimits;
import org.apache.maven.archiva.indexer.search.SearchResults;
-import org.apache.maven.archiva.security.*;
+import org.apache.maven.archiva.security.AccessDeniedException;
+import org.apache.maven.archiva.security.ArchivaSecurityException;
import org.apache.maven.archiva.security.ArchivaXworkUser;
+import org.apache.maven.archiva.security.PrincipalNotFoundException;
+import org.apache.maven.archiva.security.UserRepositories;
import org.codehaus.plexus.xwork.action.PlexusActionSupport;
/**
@@ -45,7 +49,7 @@ import org.codehaus.plexus.xwork.action.PlexusActionSupport;
*/
public class SearchAction
extends PlexusActionSupport
-{
+{
/**
* Query string.
*/
@@ -76,6 +80,16 @@ public class SearchAction
private static final String ARTIFACT = "artifact";
private List databaseResults;
+
+ private int currentPage = 0;
+
+ private int totalPages;
+
+ private boolean searchResultsOnly;
+
+ private String completeQueryString;
+
+ private static final String COMPLETE_QUERY_STRING_SEPARATOR = ";";
public String quickSearch()
throws MalformedURLException, RepositoryIndexException, RepositoryIndexSearchException
@@ -87,8 +101,8 @@ public class SearchAction
*/
assert q != null && q.length() != 0;
-
- SearchResultLimits limits = new SearchResultLimits( 0 );
+
+ SearchResultLimits limits = new SearchResultLimits( currentPage );
List<String> selectedRepos = getObservableRepos();
if ( CollectionUtils.isEmpty( selectedRepos ) )
@@ -96,14 +110,28 @@ public class SearchAction
return GlobalResults.ACCESS_TO_NO_REPOS;
}
- results = crossRepoSearch.searchForTerm( getPrincipal(), selectedRepos, q, limits );
-
+ if( searchResultsOnly && !completeQueryString.equals( "" ) )
+ {
+ results = crossRepoSearch.searchForTerm( getPrincipal(), selectedRepos, q, limits, parseCompleteQueryString() );
+ }
+ else
+ {
+ completeQueryString = "";
+ results = crossRepoSearch.searchForTerm( getPrincipal(), selectedRepos, q, limits );
+ }
+
if ( results.isEmpty() )
{
addActionError( "No results found" );
return INPUT;
}
-
+
+ totalPages = results.getTotalHits() / limits.getPageSize();
+
+ if( (results.getTotalHits() % limits.getPageSize()) != 0 )
+ {
+ totalPages = totalPages + 1;
+ }
// TODO: filter / combine the artifacts by version? (is that even possible with non-artifact hits?)
/* I don't think that we should, as I expect us to utilize the 'score' system in lucene in
@@ -112,7 +140,12 @@ public class SearchAction
* to result in a higher score.
* - Joakim
*/
-
+
+ if( !isEqualToPreviousSearchTerm( q ) )
+ {
+ buildCompleteQueryString( q );
+ }
+
return SUCCESS;
}
@@ -178,6 +211,46 @@ public class SearchAction
return Collections.emptyList();
}
+ private void buildCompleteQueryString( String searchTerm )
+ {
+ if( searchTerm.indexOf( COMPLETE_QUERY_STRING_SEPARATOR ) != -1 )
+ {
+ searchTerm = StringUtils.remove( searchTerm, COMPLETE_QUERY_STRING_SEPARATOR );
+ }
+
+ if( completeQueryString == null || "".equals( completeQueryString ) )
+ {
+ completeQueryString = searchTerm;
+ }
+ else
+ {
+ completeQueryString = completeQueryString + COMPLETE_QUERY_STRING_SEPARATOR + searchTerm;
+ }
+ }
+
+ private List<String> parseCompleteQueryString()
+ {
+ List<String> parsedCompleteQueryString = new ArrayList<String>();
+ String[] parsed = StringUtils.split( completeQueryString, COMPLETE_QUERY_STRING_SEPARATOR );
+ CollectionUtils.addAll( parsedCompleteQueryString, parsed );
+
+ return parsedCompleteQueryString;
+ }
+
+ private boolean isEqualToPreviousSearchTerm( String searchTerm )
+ {
+ if( !"".equals( completeQueryString ) )
+ {
+ String[] parsed = StringUtils.split( completeQueryString, COMPLETE_QUERY_STRING_SEPARATOR );
+ if( StringUtils.equalsIgnoreCase( searchTerm, parsed[ parsed.length - 1 ] ) )
+ {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
public String getQ()
{
return q;
@@ -197,4 +270,44 @@ public class SearchAction
{
return databaseResults;
}
+
+ public void setCurrentPage( int page )
+ {
+ this.currentPage = page;
+ }
+
+ public int getCurrentPage()
+ {
+ return currentPage;
+ }
+
+ public int getTotalPages()
+ {
+ return totalPages;
+ }
+
+ public void setTotalPages( int totalPages )
+ {
+ this.totalPages = totalPages;
+ }
+
+ public boolean isSearchResultsOnly()
+ {
+ return searchResultsOnly;
+ }
+
+ public void setSearchResultsOnly( boolean searchResultsOnly )
+ {
+ this.searchResultsOnly = searchResultsOnly;
+ }
+
+ public String getCompleteQueryString()
+ {
+ return completeQueryString;
+ }
+
+ public void setCompleteQueryString( String completeQueryString )
+ {
+ this.completeQueryString = completeQueryString;
+ }
}
diff --git a/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/WEB-INF/jsp/admin/proxyConnectors.jsp b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/WEB-INF/jsp/admin/proxyConnectors.jsp
index f334d4da1..f3362bc29 100644
--- a/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/WEB-INF/jsp/admin/proxyConnectors.jsp
+++ b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/WEB-INF/jsp/admin/proxyConnectors.jsp
@@ -73,6 +73,8 @@
<p class="name">${repoMap[repository.key].name}</p>
</div>
+ <c:set var="numberOfRepos" value="${fn:length(repository.value)}" />
+
<c:forEach items="${repository.value}" var="connector" varStatus="pc">
<c:choose>
@@ -103,12 +105,16 @@
<ww:param name="source" value="%{'${connector.sourceRepoId}'}"/>
<ww:param name="target" value="%{'${connector.targetRepoId}'}"/>
</ww:url>
- <ww:a href="%{sortUpProxyConnectorUrl}" cssClass="up" title="Move Proxy Connector Up">
- <img src="${iconUpUrl}"/>
- </ww:a>
- <ww:a href="%{sortDownProxyConnectorUrl}" cssClass="down" title="Move Proxy Connector Down">
- <img src="${iconDownUrl}"/>
- </ww:a>
+ <c:if test="${pc.count > 1}">
+ <ww:a href="%{sortUpProxyConnectorUrl}" cssClass="up" title="Move Proxy Connector Up">
+ <img src="${iconUpUrl}"/>
+ </ww:a>
+ </c:if>
+ <c:if test="${pc.count < numberOfRepos}">
+ <ww:a href="%{sortDownProxyConnectorUrl}" cssClass="down" title="Move Proxy Connector Down">
+ <img src="${iconDownUrl}"/>
+ </ww:a>
+ </c:if>
<ww:a href="%{editProxyConnectorUrl}" cssClass="edit" title="Edit Proxy Connector">
<img src="${iconEditUrl}"/>
</ww:a>
diff --git a/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/WEB-INF/jsp/include/quickSearchForm.jspf b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/WEB-INF/jsp/include/quickSearchForm.jspf
index 7db37265b..71ef30ae4 100644
--- a/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/WEB-INF/jsp/include/quickSearchForm.jspf
+++ b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/WEB-INF/jsp/include/quickSearchForm.jspf
@@ -22,6 +22,8 @@
<div id="searchBox">
<ww:form method="get" action="quickSearch" validate="true">
<ww:textfield label="Search for" size="50" name="q"/>
+ <ww:checkbox label="Search Results Only" name="searchResultsOnly"/>
+ <ww:hidden name="completeQueryString" value="${completeQueryString}"/>
<ww:submit label="Go!"/>
</ww:form>
diff --git a/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/WEB-INF/jsp/results.jsp b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/WEB-INF/jsp/results.jsp
index 3367c299f..685f24cfe 100644
--- a/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/WEB-INF/jsp/results.jsp
+++ b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/WEB-INF/jsp/results.jsp
@@ -32,6 +32,11 @@
<h1>Search</h1>
+<c:url var="imgNextPageUrl" value="/images/icon_next_page.gif"/>
+<c:url var="imgPrevPageUrl" value="/images/icon_prev_page.gif"/>
+<c:url var="imgPrevPageDisabledUrl" value="/images/icon_prev_page_disabled.gif"/>
+<c:url var="imgNextPageDisabledUrl" value="/images/icon_next_page_disabled.gif"/>
+
<div id="contentArea">
<div id="searchBox">
<%@ include file="/WEB-INF/jsp/include/quickSearchForm.jspf" %>
@@ -44,13 +49,104 @@
<%-- search was made from the indices --%>
<c:when test="${databaseResults == null}">
- <p>Hits: ${fn:length(results.hits)} of ${results.totalHits}</p>
-
+ <c:set var="hitsNum">${fn:length(results.hits) + (currentPage * results.limits.pageSize)}</c:set>
+ <c:choose>
+ <c:when test="${results.totalHits > results.limits.pageSize}">
+ <p>Hits: ${(hitsNum - results.limits.pageSize) + 1} to ${hitsNum} of ${results.totalHits}</p>
+ </c:when>
+ <c:otherwise>
+ <p>Hits: 1 to ${hitsNum} of ${results.totalHits}</p>
+ </c:otherwise>
+ </c:choose>
<c:choose>
<c:when test="${empty results.hits}">
<p>No results</p>
</c:when>
<c:otherwise>
+
+ <%-- Pagination start --%>
+ <p>
+ <%-- Prev & Next icons --%>
+ <c:set var="prevPageUrl">
+ <ww:url action="quickSearch" namespace="/">
+ <ww:param name="q" value="%{'${q}'}"/>
+ <ww:param name="currentPage" value="%{'${currentPage - 1}'}"/>
+ </ww:url>
+ </c:set>
+ <c:set var="nextPageUrl">
+ <ww:url action="quickSearch" namespace="/">
+ <ww:param name="q" value="%{'${q}'}"/>
+ <ww:param name="currentPage" value="%{'${currentPage + 1}'}"/>
+ </ww:url>
+ </c:set>
+
+ <c:choose>
+ <c:when test="${currentPage == 0}">
+ <img src="${imgPrevPageDisabledUrl}"/>
+ </c:when>
+ <c:otherwise>
+ <a href="${prevPageUrl}">
+ <img src="${imgPrevPageUrl}"/>
+ </a>
+ </c:otherwise>
+ </c:choose>
+
+ <%-- Google-style pagination --%>
+ <c:choose>
+ <c:when test="${totalPages > 11}">
+ <c:choose>
+ <c:when test="${(currentPage - 5) < 0}">
+ <c:set var="beginVal">0</c:set>
+ <c:set var="endVal">10</c:set>
+ </c:when>
+ <c:when test="${(currentPage + 5) > (totalPages - 1)}">
+ <c:set var="beginVal">${(totalPages -1) - 10}</c:set>
+ <c:set var="endVal">${totalPages - 1}</c:set>
+ </c:when>
+ <c:otherwise>
+ <c:set var="beginVal">${currentPage - 5}</c:set>
+ <c:set var="endVal">${currentPage + 5}</c:set>
+ </c:otherwise>
+ </c:choose>
+ </c:when>
+ <c:otherwise>
+ <c:set var="beginVal">0</c:set>
+ <c:set var="endVal">${totalPages - 1}</c:set>
+ </c:otherwise>
+ </c:choose>
+
+ <c:forEach var="i" begin="${beginVal}" end="${endVal}">
+ <c:choose>
+ <c:when test="${i != currentPage}">
+ <c:set var="specificPageUrl">
+ <ww:url action="quickSearch" namespace="/">
+ <ww:param name="q" value="%{'${q}'}"/>
+ <ww:param name="currentPage" value="%{'${i}'}"/>
+ <ww:param name="searchResultsOnly" value="%{'${searchResultsOnly}'}"/>
+ <ww:param name="completeQueryString" value="%{'${completeQueryString}'}"/>
+ </ww:url>
+ </c:set>
+ <a href="${specificPageUrl}">${i + 1}</a>
+ </c:when>
+ <c:otherwise>
+ <b>${i + 1}</b>
+ </c:otherwise>
+ </c:choose>
+ </c:forEach>
+
+ <c:choose>
+ <c:when test="${currentPage == (totalPages - 1)}">
+ <img src="${imgNextPageDisabledUrl}"/>
+ </c:when>
+ <c:otherwise>
+ <a href="${nextPageUrl}">
+ <img src="${imgNextPageUrl}"/>
+ </a>
+ </c:otherwise>
+ </c:choose>
+ </p>
+ <%-- Pagination end --%>
+
<c:forEach items="${results.hits}" var="record" varStatus="i">
<c:choose>
<c:when test="${not empty (record.groupId)}">
@@ -60,7 +156,7 @@
</h3>
<p>
<my:showArtifactLink groupId="${record.groupId}" artifactId="${record.artifactId}"
- version="${record.version}" versions="${record.versions}"/>
+ version="${record.version}" versions="${record.versions}" repositoryId="${record.repositoryId}"/>
</p>
</c:when>
<c:otherwise>
diff --git a/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/WEB-INF/tags/showArtifactLink.tag b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/WEB-INF/tags/showArtifactLink.tag
index 65dde0745..ba4558adc 100644
--- a/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/WEB-INF/tags/showArtifactLink.tag
+++ b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/WEB-INF/tags/showArtifactLink.tag
@@ -27,11 +27,14 @@
<%@ attribute name="classifier" %>
<%@ attribute name="scope" %>
<%@ attribute name="versions" type="java.util.List" %>
+<%@ attribute name="repositoryId" %>
<span class="artifact-link">
+ <a href="${pageContext.request.contextPath}/repository/${repositoryId}">${repositoryId}</a>
+ <strong> : </strong>
<archiva:groupIdLink var="${groupId}" includeTop="false" />
- <c:if test="${!empty(artifactId)}">
+ <c:if test="${!empty(artifactId)}">
<c:set var="url">
<ww:url action="browseArtifact" namespace="/">
<ww:param name="groupId" value="%{'${groupId}'}"/>
@@ -73,5 +76,5 @@
</c:if>
<c:if test="${!empty(classifier)}">
| <strong>Classifier:</strong> ${classifier}
- </c:if>
+ </c:if>
</span>
diff --git a/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/images/icon_next_page.gif b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/images/icon_next_page.gif
new file mode 100644
index 000000000..7c5b30758
--- /dev/null
+++ b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/images/icon_next_page.gif
Binary files differ
diff --git a/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/images/icon_next_page_disabled.gif b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/images/icon_next_page_disabled.gif
new file mode 100644
index 000000000..99c292f62
--- /dev/null
+++ b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/images/icon_next_page_disabled.gif
Binary files differ
diff --git a/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/images/icon_prev_page.gif b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/images/icon_prev_page.gif
new file mode 100644
index 000000000..a051fa1f3
--- /dev/null
+++ b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/images/icon_prev_page.gif
Binary files differ
diff --git a/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/images/icon_prev_page_disabled.gif b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/images/icon_prev_page_disabled.gif
new file mode 100644
index 000000000..79c241b37
--- /dev/null
+++ b/archiva-modules/archiva-web/archiva-webapp/src/main/webapp/images/icon_prev_page_disabled.gif
Binary files differ
diff --git a/archiva-modules/archiva-web/archiva-webdav/src/main/java/org/apache/maven/archiva/webdav/ArchivaDavResourceFactory.java b/archiva-modules/archiva-web/archiva-webdav/src/main/java/org/apache/maven/archiva/webdav/ArchivaDavResourceFactory.java
index 5e926ceed..39e21c38f 100644
--- a/archiva-modules/archiva-web/archiva-webdav/src/main/java/org/apache/maven/archiva/webdav/ArchivaDavResourceFactory.java
+++ b/archiva-modules/archiva-web/archiva-webdav/src/main/java/org/apache/maven/archiva/webdav/ArchivaDavResourceFactory.java
@@ -30,6 +30,7 @@ import java.util.Map;
import javax.servlet.http.HttpServletResponse;
+import org.apache.commons.io.FileUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.jackrabbit.webdav.DavException;
import org.apache.jackrabbit.webdav.DavResource;
@@ -43,6 +44,7 @@ import org.apache.jackrabbit.webdav.lock.SimpleLockManager;
import org.apache.maven.archiva.common.utils.PathUtil;
import org.apache.maven.archiva.configuration.ArchivaConfiguration;
import org.apache.maven.archiva.configuration.RepositoryGroupConfiguration;
+import org.apache.maven.archiva.model.ArchivaRepositoryMetadata;
import org.apache.maven.archiva.model.ArtifactReference;
import org.apache.maven.archiva.model.ProjectReference;
import org.apache.maven.archiva.model.VersionedReference;
@@ -59,6 +61,9 @@ import org.apache.maven.archiva.repository.content.RepositoryRequest;
import org.apache.maven.archiva.repository.layout.LayoutException;
import org.apache.maven.archiva.repository.metadata.MetadataTools;
import org.apache.maven.archiva.repository.metadata.RepositoryMetadataException;
+import org.apache.maven.archiva.repository.metadata.RepositoryMetadataMerge;
+import org.apache.maven.archiva.repository.metadata.RepositoryMetadataReader;
+import org.apache.maven.archiva.repository.metadata.RepositoryMetadataWriter;
import org.apache.maven.archiva.repository.scanner.RepositoryContentConsumers;
import org.apache.maven.archiva.security.ArchivaXworkUser;
import org.apache.maven.archiva.security.ServletAuthenticator;
@@ -69,6 +74,9 @@ import org.apache.maven.model.DistributionManagement;
import org.apache.maven.model.Model;
import org.apache.maven.model.Relocation;
import org.apache.maven.model.io.xpp3.MavenXpp3Reader;
+import org.codehaus.plexus.digest.ChecksumFile;
+import org.codehaus.plexus.digest.Digester;
+import org.codehaus.plexus.digest.DigesterException;
import org.codehaus.plexus.redback.authentication.AuthenticationException;
import org.codehaus.plexus.redback.authentication.AuthenticationResult;
import org.codehaus.plexus.redback.authorization.AuthorizationException;
@@ -90,11 +98,11 @@ import com.opensymphony.xwork.ActionContext;
*/
public class ArchivaDavResourceFactory
implements DavResourceFactory, Auditable
-{
+{
private static final String PROXIED_SUFFIX = " (proxied)";
private static final String HTTP_PUT_METHOD = "PUT";
-
+
private Logger log = LoggerFactory.getLogger( ArchivaDavResourceFactory.class );
/**
@@ -131,7 +139,7 @@ public class ArchivaDavResourceFactory
* @plexus.requirement
*/
private ArchivaConfiguration archivaConfiguration;
-
+
/**
* @plexus.requirement
*/
@@ -141,59 +149,76 @@ public class ArchivaDavResourceFactory
* @plexus.requirement role-hint="basic"
*/
private HttpAuthenticator httpAuth;
-
-
+
/**
* Lock Manager - use simple implementation from JackRabbit
*/
private final LockManager lockManager = new SimpleLockManager();
- /** @plexus.requirement */
+ /**
+ * @plexus.requirement
+ */
private RepositoryContentConsumers consumers;
+ /**
+ * @plexus.requirement
+ */
+ private ChecksumFile checksum;
+
+ /**
+ * @plexus.requirement role-hint="sha1"
+ */
+ private Digester digestSha1;
+
+ /**
+ * @plexus.requirement role-hint="md5";
+ */
+ private Digester digestMd5;
+
public DavResource createResource( final DavResourceLocator locator, final DavServletRequest request,
final DavServletResponse response )
throws DavException
- {
+ {
checkLocatorIsInstanceOfRepositoryLocator( locator );
ArchivaDavResourceLocator archivaLocator = (ArchivaDavResourceLocator) locator;
-
+
RepositoryGroupConfiguration repoGroupConfig =
archivaConfiguration.getConfiguration().getRepositoryGroupsAsMap().get( archivaLocator.getRepositoryId() );
List<String> repositories = new ArrayList<String>();
boolean isGet = WebdavMethodUtil.isReadMethod( request.getMethod() );
boolean isPut = WebdavMethodUtil.isWriteMethod( request.getMethod() );
-
+
if ( repoGroupConfig != null )
- {
+ {
if( WebdavMethodUtil.isWriteMethod( request.getMethod() ) )
{
throw new DavException( HttpServletResponse.SC_METHOD_NOT_ALLOWED,
"Write method not allowed for repository groups." );
}
repositories.addAll( repoGroupConfig.getRepositories() );
-
+
// handle browse requests for virtual repos
- if ( RepositoryPathUtil.getLogicalResource( locator.getResourcePath() ).endsWith( "/" ) )
- {
- return getResource( request, repositories, archivaLocator );
- }
+ if ( RepositoryPathUtil.getLogicalResource( locator.getResourcePath() ).endsWith( "/" ) )
+ {
+ return getResource( request, repositories, archivaLocator );
+ }
}
else
{
repositories.add( archivaLocator.getRepositoryId() );
}
-
+
//MRM-419 - Windows Webdav support. Should not 404 if there is no content.
if (StringUtils.isEmpty(archivaLocator.getRepositoryId()))
{
throw new DavException(HttpServletResponse.SC_NO_CONTENT);
}
- DavResource resource = null;
+ List<DavResource> availableResources = new ArrayList<DavResource>();
+ List<String> resourcesInAbsolutePath = new ArrayList<String>();
DavException e = null;
-
+
for ( String repositoryId : repositories )
{
ManagedRepositoryContent managedRepository = null;
@@ -207,7 +232,9 @@ public class ArchivaDavResourceFactory
throw new DavException( HttpServletResponse.SC_NOT_FOUND, "Invalid managed repository <" +
repositoryId + ">" );
}
-
+
+ DavResource resource = null;
+
if ( !locator.getResourcePath().startsWith( ArchivaDavResource.HIDDEN_PATH_PREFIX ) )
{
if ( managedRepository != null )
@@ -215,42 +242,37 @@ public class ArchivaDavResourceFactory
try
{
if( isAuthorized( request, repositoryId ) )
- {
+ {
LogicalResource logicalResource =
new LogicalResource( RepositoryPathUtil.getLogicalResource( locator.getResourcePath() ) );
-
+
if ( isGet )
{
resource = doGet( managedRepository, request, archivaLocator, logicalResource );
}
-
+
if ( isPut )
{
resource = doPut( managedRepository, request, archivaLocator, logicalResource );
}
}
}
- catch ( DavException de )
- {
+ catch ( DavException de )
+ {
e = de;
continue;
}
-
+
if( resource == null )
{
e = new DavException( HttpServletResponse.SC_NOT_FOUND, "Resource does not exist" );
}
else
- {
- setHeaders(response, locator, resource );
+ {
+ availableResources.add( resource );
- // compatibility with MRM-440 to ensure browsing the repository works ok
- if ( resource.isCollection() && !request.getRequestURI().endsWith("/" ) )
- {
- throw new BrowserRedirectException( resource.getHref() );
- }
- resource.addLockManager(lockManager);
- return resource;
+ String logicalResource = RepositoryPathUtil.getLogicalResource( locator.getResourcePath() );
+ resourcesInAbsolutePath.add( managedRepository.getRepoRoot() + logicalResource );
}
}
else
@@ -258,14 +280,112 @@ public class ArchivaDavResourceFactory
e = new DavException( HttpServletResponse.SC_NOT_FOUND, "Repository does not exist" );
}
}
+ }
+
+ if ( availableResources.isEmpty() )
+ {
+ throw e;
+ }
+
+ String requestedResource = request.getRequestURI();
+
+ // MRM-872 : merge all available metadata
+ // merge metadata only when requested via the repo group
+ if ( ( repositoryRequest.isMetadata( requestedResource ) || ( requestedResource.endsWith( "metadata.xml.sha1" ) || requestedResource.endsWith( "metadata.xml.md5" ) ) ) &&
+ repoGroupConfig != null )
+ {
+ // this should only be at the project level not version level!
+ if( isProjectReference( requestedResource ) )
+ {
+ String artifactId = StringUtils.substringBeforeLast( requestedResource.replace( '\\', '/' ), "/" );
+ artifactId = StringUtils.substringAfterLast( artifactId, "/" );
+
+ ArchivaDavResource res = ( ArchivaDavResource ) availableResources.get( 0 );
+ String filePath = StringUtils.substringBeforeLast( res.getLocalResource().getAbsolutePath().replace( '\\', '/' ), "/" );
+ filePath = filePath + "/maven-metadata-" + repoGroupConfig.getId() + ".xml";
+
+ // for MRM-872 handle checksums of the merged metadata files
+ if( repositoryRequest.isSupportFile( requestedResource ) )
+ {
+ File metadataChecksum = new File( filePath + "."
+ + StringUtils.substringAfterLast( requestedResource, "." ) );
+ if( metadataChecksum.exists() )
+ {
+ LogicalResource logicalResource =
+ new LogicalResource( RepositoryPathUtil.getLogicalResource( locator.getResourcePath() ) );
+
+ ArchivaDavResource metadataChecksumResource =
+ new ArchivaDavResource( metadataChecksum.getAbsolutePath(), logicalResource.getPath(), null,
+ request.getRemoteAddr(), request.getDavSession(), archivaLocator, this,
+ mimeTypes, auditListeners, consumers );
+ availableResources.add( 0, metadataChecksumResource );
+ }
+ }
+ else
+ { // merge the metadata of all repos under group
+ ArchivaRepositoryMetadata mergedMetadata = new ArchivaRepositoryMetadata();
+ for ( String resourceAbsPath : resourcesInAbsolutePath )
+ {
+ try
+ {
+ File metadataFile = new File( resourceAbsPath );
+ ArchivaRepositoryMetadata repoMetadata = RepositoryMetadataReader.read( metadataFile );
+ mergedMetadata = RepositoryMetadataMerge.merge( mergedMetadata, repoMetadata );
+ }
+ catch ( RepositoryMetadataException r )
+ {
+ throw new DavException( HttpServletResponse.SC_INTERNAL_SERVER_ERROR,
+ "Error occurred while reading metadata file." );
+ }
+ }
+
+ try
+ {
+ File resourceFile = writeMergedMetadataToFile( mergedMetadata, filePath );
+
+ LogicalResource logicalResource =
+ new LogicalResource( RepositoryPathUtil.getLogicalResource( locator.getResourcePath() ) );
+
+ ArchivaDavResource metadataResource =
+ new ArchivaDavResource( resourceFile.getAbsolutePath(), logicalResource.getPath(), null,
+ request.getRemoteAddr(), request.getDavSession(), archivaLocator, this,
+ mimeTypes, auditListeners, consumers );
+ availableResources.add( 0, metadataResource );
+ }
+ catch ( RepositoryMetadataException r )
+ {
+ throw new DavException( HttpServletResponse.SC_INTERNAL_SERVER_ERROR,
+ "Error occurred while writing metadata file." );
+ }
+ catch ( IOException ie )
+ {
+ throw new DavException( HttpServletResponse.SC_INTERNAL_SERVER_ERROR,
+ "Error occurred while generating checksum files." );
+ }
+ catch ( DigesterException de )
+ {
+ throw new DavException( HttpServletResponse.SC_INTERNAL_SERVER_ERROR,
+ "Error occurred while generating checksum files." );
+ }
+ }
+ }
}
+
+ DavResource resource = availableResources.get( 0 );
+ setHeaders(response, locator, resource );
- throw e;
+ // compatibility with MRM-440 to ensure browsing the repository works ok
+ if ( resource.isCollection() && !request.getRequestURI().endsWith("/" ) )
+ {
+ throw new BrowserRedirectException( resource.getHref() );
+ }
+ resource.addLockManager(lockManager);
+ return resource;
}
-
+
public DavResource createResource( final DavResourceLocator locator, final DavSession davSession )
throws DavException
- {
+ {
checkLocatorIsInstanceOfRepositoryLocator( locator );
ArchivaDavResourceLocator archivaLocator = (ArchivaDavResourceLocator) locator;
@@ -568,7 +688,7 @@ public class ArchivaDavResourceFactory
//We need to specify this so connecting wagons can work correctly
response.addDateHeader("last-modified", resource.getModificationTime());
-
+
// TODO: [MRM-524] determine http caching options for other types of files (artifacts, sha1, md5, snapshots)
}
@@ -622,87 +742,87 @@ public class ArchivaDavResourceFactory
this.path = path;
}
}
-
+
protected boolean isAuthorized( DavServletRequest request, String repositoryId )
throws DavException
{
try
{
- AuthenticationResult result = httpAuth.getAuthenticationResult( request, null );
+ AuthenticationResult result = httpAuth.getAuthenticationResult( request, null );
SecuritySession securitySession = httpAuth.getSecuritySession();
-
+
return servletAuth.isAuthenticated( request, result ) &&
servletAuth.isAuthorized( request, securitySession, repositoryId,
WebdavMethodUtil.isWriteMethod( request.getMethod() ) );
}
catch ( AuthenticationException e )
- {
+ {
throw new UnauthorizedDavException( repositoryId, "You are not authenticated" );
}
catch ( MustChangePasswordException e )
- {
+ {
throw new UnauthorizedDavException( repositoryId, "You must change your password." );
}
catch ( AccountLockedException e )
- {
+ {
throw new UnauthorizedDavException( repositoryId, "User account is locked." );
}
catch ( AuthorizationException e )
- {
+ {
throw new DavException( HttpServletResponse.SC_INTERNAL_SERVER_ERROR,
"Fatal Authorization Subsystem Error." );
}
catch ( UnauthorizedException e )
- {
+ {
throw new UnauthorizedDavException( repositoryId, e.getMessage() );
}
}
-
+
private DavResource getResource( DavServletRequest request, List<String> repositories, ArchivaDavResourceLocator locator )
throws DavException
{
- List<File> mergedRepositoryContents = new ArrayList<File>();
+ List<File> mergedRepositoryContents = new ArrayList<File>();
LogicalResource logicalResource =
new LogicalResource( RepositoryPathUtil.getLogicalResource( locator.getResourcePath() ) );
-
- // flow:
+
+ // flow:
// if the current user logged in has permission to any of the repositories, allow user to
// browse the repo group but displaying only the repositories which the user has permission to access.
// otherwise, prompt for authentication.
-
+
// put the current session in the session map which will be passed to ArchivaXworkUser
Map<String, Object> sessionMap = new HashMap<String, Object>();
if( request.getSession().getAttribute( SecuritySystemConstants.SECURITY_SESSION_KEY ) != null )
{
- sessionMap.put( SecuritySystemConstants.SECURITY_SESSION_KEY,
+ sessionMap.put( SecuritySystemConstants.SECURITY_SESSION_KEY,
request.getSession().getAttribute( SecuritySystemConstants.SECURITY_SESSION_KEY ) );
}
-
- String activePrincipal = ArchivaXworkUser.getActivePrincipal( sessionMap );
+
+ String activePrincipal = ArchivaXworkUser.getActivePrincipal( sessionMap );
boolean allow = isAllowedToContinue( request, repositories, activePrincipal );
-
+
if( allow )
- {
+ {
for( String repository : repositories )
- {
+ {
// for prompted authentication
if( httpAuth.getSecuritySession() != null )
{
try
- {
- if( isAuthorized( request, repository ) )
+ {
+ if( isAuthorized( request, repository ) )
{
getResource( locator, mergedRepositoryContents, logicalResource, repository );
}
- }
+ }
catch ( DavException e )
- {
+ {
continue;
}
}
else
{
- // for the current user logged in
+ // for the current user logged in
try
{
if( servletAuth.isAuthorizedToAccessVirtualRepository( activePrincipal, repository ) )
@@ -710,27 +830,27 @@ public class ArchivaDavResourceFactory
getResource( locator, mergedRepositoryContents, logicalResource, repository );
}
}
- catch ( UnauthorizedException e )
- {
+ catch ( UnauthorizedException e )
+ {
continue;
}
- }
+ }
}
}
else
{
throw new UnauthorizedDavException( locator.getRepositoryId(), "User not authorized." );
}
-
+
ArchivaVirtualDavResource resource =
new ArchivaVirtualDavResource( mergedRepositoryContents, logicalResource.getPath(), mimeTypes, locator, this );
-
+
// compatibility with MRM-440 to ensure browsing the repository group works ok
if ( resource.isCollection() && !request.getRequestURI().endsWith("/" ) )
{
throw new BrowserRedirectException( resource.getHref() );
}
-
+
return resource;
}
@@ -748,34 +868,34 @@ public class ArchivaDavResourceFactory
{
throw new DavException( HttpServletResponse.SC_NOT_FOUND, "Invalid managed repository <" +
repository + ">" );
- }
-
+ }
+
if ( !locator.getResourcePath().startsWith( ArchivaVirtualDavResource.HIDDEN_PATH_PREFIX ) )
{
if( managedRepository != null )
- {
+ {
File resourceFile = new File( managedRepository.getRepoRoot(), logicalResource.getPath() );
if( resourceFile.exists() )
- {
+ {
mergedRepositoryContents.add( resourceFile );
- }
+ }
}
}
}
-
+
/**
* Check if the current user is authorized to access any of the repos
- *
+ *
* @param request
* @param repositories
* @param activePrincipal
* @return
*/
- private boolean isAllowedToContinue( DavServletRequest request, List<String> repositories, String activePrincipal )
+ private boolean isAllowedToContinue( DavServletRequest request, List<String> repositories, String activePrincipal )
{
boolean allow = false;
-
-
+
+
// if securitySession != null, it means that the user was prompted for authentication
if( httpAuth.getSecuritySession() != null )
{
@@ -790,13 +910,13 @@ public class ArchivaDavResourceFactory
}
}
catch( DavException e )
- {
+ {
continue;
}
- }
+ }
}
else
- {
+ {
for( String repository : repositories )
{
try
@@ -808,13 +928,58 @@ public class ArchivaDavResourceFactory
}
}
catch ( UnauthorizedException e )
- {
+ {
continue;
}
- }
+ }
}
-
+
return allow;
}
+
+ private File writeMergedMetadataToFile( ArchivaRepositoryMetadata mergedMetadata, String outputFilename )
+ throws RepositoryMetadataException, DigesterException, IOException
+ {
+ File outputFile = new File( outputFilename );
+ if( outputFile.exists() )
+ {
+ FileUtils.deleteQuietly( outputFile );
+ }
+
+ outputFile.getParentFile().mkdirs();
+ RepositoryMetadataWriter.write( mergedMetadata, outputFile );
+ createChecksumFile( outputFilename, digestSha1 );
+ createChecksumFile( outputFilename, digestMd5 );
+
+ return outputFile;
+ }
+
+ private void createChecksumFile( String path, Digester digester )
+ throws DigesterException, IOException
+ {
+ File checksumFile = new File( path + digester.getFilenameExtension() );
+ if ( !checksumFile.exists() )
+ {
+ FileUtils.deleteQuietly( checksumFile );
+ checksum.createChecksum( new File( path ), digester );
+ }
+ else if ( !checksumFile.isFile() )
+ {
+ log.error( "Checksum file is not a file." );
+ }
+ }
+
+ private boolean isProjectReference( String requestedResource )
+ {
+ try
+ {
+ VersionedReference versionRef = metadataTools.toVersionedReference( requestedResource );
+ return false;
+ }
+ catch ( RepositoryMetadataException re )
+ {
+ return true;
+ }
+ }
}
diff --git a/archiva-modules/archiva-web/archiva-webdav/src/main/java/org/apache/maven/archiva/webdav/RepositoryServlet.java b/archiva-modules/archiva-web/archiva-webdav/src/main/java/org/apache/maven/archiva/webdav/RepositoryServlet.java
index 4cdffad27..5fa2d3bd7 100644
--- a/archiva-modules/archiva-web/archiva-webdav/src/main/java/org/apache/maven/archiva/webdav/RepositoryServlet.java
+++ b/archiva-modules/archiva-web/archiva-webdav/src/main/java/org/apache/maven/archiva/webdav/RepositoryServlet.java
@@ -28,6 +28,8 @@ import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
+import org.apache.commons.io.FileUtils;
+import org.apache.commons.lang.StringUtils;
import org.apache.jackrabbit.webdav.DavException;
import org.apache.jackrabbit.webdav.DavLocatorFactory;
import org.apache.jackrabbit.webdav.DavMethods;
@@ -44,7 +46,6 @@ import org.apache.maven.archiva.configuration.ArchivaConfiguration;
import org.apache.maven.archiva.configuration.ConfigurationEvent;
import org.apache.maven.archiva.configuration.ConfigurationListener;
import org.apache.maven.archiva.configuration.ManagedRepositoryConfiguration;
-import org.apache.maven.archiva.repository.audit.AuditEvent;
import org.apache.maven.archiva.security.ServletAuthenticator;
import org.codehaus.plexus.redback.xwork.filter.authentication.HttpAuthenticator;
import org.codehaus.plexus.spring.PlexusToSpringUtils;
@@ -104,6 +105,7 @@ public class RepositoryServlet
DavMethods.isDeltaVMethod( webdavRequest ) &&
!( DavMethods.DAV_VERSION_CONTROL == methodCode || DavMethods.DAV_REPORT == methodCode );
WebdavResponse webdavResponse = new WebdavResponseImpl( response, noCache );
+ DavResource resource = null;
try
{
@@ -114,7 +116,7 @@ public class RepositoryServlet
}
// check matching if=header for lock-token relevant operations
- DavResource resource =
+ resource =
getResourceFactory().createResource( webdavRequest.getRequestLocator(), webdavRequest, webdavResponse );
if ( !isPreconditionValid( webdavRequest, resource ) )
@@ -155,7 +157,7 @@ public class RepositoryServlet
}
}
finally
- {
+ {
getDavSessionProvider().releaseSession( webdavRequest );
}
}
diff --git a/archiva-modules/archiva-web/archiva-webdav/src/test/java/org/apache/maven/archiva/webdav/RepositoryServletRepositoryGroupTest.java b/archiva-modules/archiva-web/archiva-webdav/src/test/java/org/apache/maven/archiva/webdav/RepositoryServletRepositoryGroupTest.java
index 57453ea81..26ff32ee1 100644
--- a/archiva-modules/archiva-web/archiva-webdav/src/test/java/org/apache/maven/archiva/webdav/RepositoryServletRepositoryGroupTest.java
+++ b/archiva-modules/archiva-web/archiva-webdav/src/test/java/org/apache/maven/archiva/webdav/RepositoryServletRepositoryGroupTest.java
@@ -30,6 +30,8 @@ import org.apache.commons.io.FileUtils;
import org.apache.maven.archiva.configuration.Configuration;
import org.apache.maven.archiva.configuration.ManagedRepositoryConfiguration;
import org.apache.maven.archiva.configuration.RepositoryGroupConfiguration;
+import org.apache.maven.archiva.model.ArchivaRepositoryMetadata;
+import org.apache.maven.archiva.repository.metadata.RepositoryMetadataReader;
import com.meterware.httpunit.GetMethodWebRequest;
import com.meterware.httpunit.PutMethodWebRequest;
@@ -176,7 +178,7 @@ public class RepositoryServletRepositoryGroupTest
WebResponse response = sc.getResponse( request );
assertResponseNotFound( response );
- }
+ }
/*
* Test Case 3.a
@@ -212,11 +214,79 @@ public class RepositoryServletRepositoryGroupTest
throws Exception
{
WebRequest request = new GetMethodWebRequest( "http://machine.com/repository/" + REPO_GROUP_WITH_VALID_REPOS );
- WebResponse response = sc.getResponse( request );
+ WebResponse response = sc.getResponse( request );
assertNotNull( "Should have received a response", response );
assertEquals( "Should have been an 401 response code.", HttpServletResponse.SC_UNAUTHORIZED, response.getResponseCode() );
}
+
+ // MRM-872
+ public void testGetMergedMetadata()
+ throws Exception
+ {
+ // first metadata file
+ String resourceName = "dummy/dummy-merged-metadata-resource/maven-metadata.xml";
+
+ File dummyInternalResourceFile = new File( repoRootFirst, resourceName );
+ dummyInternalResourceFile.getParentFile().mkdirs();
+ FileUtils.writeStringToFile( dummyInternalResourceFile, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
+ "<metadata>\n<groupId>dummy</groupId>\n<artifactId>dummy-merged-metadata-resource</artifactId>\n" +
+ "<versioning>\n<latest>1.0</latest>\n<release>1.0</release>\n<versions>\n<version>1.0</version>\n" +
+ "<version>2.5</version>\n</versions>\n<lastUpdated>20080708095554</lastUpdated>\n</versioning>\n</metadata>", null );
+
+ //second metadata file
+ resourceName = "dummy/dummy-merged-metadata-resource/maven-metadata.xml";
+ dummyInternalResourceFile = new File( repoRootLast, resourceName );
+ dummyInternalResourceFile.getParentFile().mkdirs();
+ FileUtils.writeStringToFile( dummyInternalResourceFile, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" +
+ "<metadata><groupId>dummy</groupId><artifactId>dummy-merged-metadata-resource</artifactId>" +
+ "<versioning><latest>2.0</latest><release>2.0</release><versions><version>1.0</version>" +
+ "<version>1.5</version><version>2.0</version></versions><lastUpdated>20080709095554</lastUpdated>" +
+ "</versioning></metadata>", null );
+
+ WebRequest request =
+ new GetMethodWebRequest( "http://machine.com/repository/" + REPO_GROUP_WITH_VALID_REPOS + "/dummy/" +
+ "dummy-merged-metadata-resource/maven-metadata.xml" );
+ WebResponse response = sc.getResource( request );
+
+ File returnedMetadata = new File( getBasedir(), "/target/test-classes/retrievedMetadataFile.xml");
+ FileUtils.writeStringToFile( returnedMetadata, response.getText() );
+ ArchivaRepositoryMetadata metadata = RepositoryMetadataReader.read( returnedMetadata );
+
+ assertResponseOK( response );
+ assertEquals( "Versions list size", 4, metadata.getAvailableVersions().size() );
+ assertTrue( "Versions list contains version 1.0", metadata.getAvailableVersions().contains( "1.0" ) );
+ assertTrue( "Versions list contains version 1.5", metadata.getAvailableVersions().contains( "1.5" ) );
+ assertTrue( "Versions list contains version 2.0", metadata.getAvailableVersions().contains( "2.0" ) );
+ assertTrue( "Versions list contains version 2.5", metadata.getAvailableVersions().contains( "2.5" ) );
+
+ //check if the checksum files were generated
+ File checksumFileSha1 = new File( repoRootFirst, resourceName + ".sha1" );
+ checksumFileSha1.getParentFile().mkdirs();
+ FileUtils.writeStringToFile( checksumFileSha1, "3290853214d3687134", null );
+
+ File checksumFileMd5 = new File( repoRootFirst, resourceName + ".md5" );
+ checksumFileMd5.getParentFile().mkdirs();
+ FileUtils.writeStringToFile( checksumFileMd5, "98745897234eda12836423", null );
+
+ // request the sha1 checksum of the metadata
+ request =
+ new GetMethodWebRequest( "http://machine.com/repository/" + REPO_GROUP_WITH_VALID_REPOS + "/dummy/" +
+ "dummy-merged-metadata-resource/maven-metadata.xml.sha1" );
+ response = sc.getResource( request );
+
+ assertResponseOK( response );
+ assertEquals( "d2321a573e0488bca571b624f891104009408dd8 maven-metadata-group-with-valid-repos.xml", response.getText() );
+
+ // request the md5 checksum of the metadata
+ request =
+ new GetMethodWebRequest( "http://machine.com/repository/" + REPO_GROUP_WITH_VALID_REPOS + "/dummy/" +
+ "dummy-merged-metadata-resource/maven-metadata.xml.md5" );
+ response = sc.getResource( request );
+
+ assertResponseOK( response );
+ assertEquals( "79d271fbe8bd1d17b23273937750d407 maven-metadata-group-with-valid-repos.xml", response.getText().trim() );
+ }
protected void assertResponseMethodNotAllowed( WebResponse response )
{
diff --git a/archiva-modules/archiva-web/archiva-webdav/src/test/resources/org/apache/maven/archiva/webdav/RepositoryServletTest.xml b/archiva-modules/archiva-web/archiva-webdav/src/test/resources/org/apache/maven/archiva/webdav/RepositoryServletTest.xml
index f40d694f2..83fd2a4e6 100644
--- a/archiva-modules/archiva-web/archiva-webdav/src/test/resources/org/apache/maven/archiva/webdav/RepositoryServletTest.xml
+++ b/archiva-modules/archiva-web/archiva-webdav/src/test/resources/org/apache/maven/archiva/webdav/RepositoryServletTest.xml
@@ -152,6 +152,20 @@
<role>org.apache.maven.archiva.repository.scanner.RepositoryContentConsumers</role>
<role-hint>default</role-hint>
</requirement>
+ <requirement>
+ <role>org.codehaus.plexus.digest.ChecksumFile</role>
+ <field-name>checksum</field-name>
+ </requirement>
+ <requirement>
+ <role>org.codehaus.plexus.digest.Digester</role>
+ <role-hint>sha1</role-hint>
+ <field-name>digestSha1</field-name>
+ </requirement>
+ <requirement>
+ <role>org.codehaus.plexus.digest.Digester</role>
+ <role-hint>md5</role-hint>
+ <field-name>digestMd5</field-name>
+ </requirement>
</requirements>
</component>
</components>
diff --git a/pom.xml b/pom.xml
index 96107858e..88134bd8b 100644
--- a/pom.xml
+++ b/pom.xml
@@ -229,6 +229,11 @@
</exclusions>
</dependency>
<dependency>
+ <groupId>xerces</groupId>
+ <artifactId>xercesImpl</artifactId>
+ <version>2.8.1</version>
+ </dependency>
+ <dependency>
<groupId>javax.activation</groupId>
<artifactId>activation</artifactId>
<version>1.1</version>
@@ -826,6 +831,12 @@
<groupId>org.apache.maven.wagon</groupId>
<artifactId>wagon-http-lightweight</artifactId>
<version>${wagon.version}</version>
+ <exclusions>
+ <exclusion>
+ <groupId>nekohtml</groupId>
+ <artifactId>xercesMinimal</artifactId>
+ </exclusion>
+ </exclusions>
</dependency>
<dependency>
<groupId>org.apache.maven.wagon</groupId>