diff --git a/archiva-base/archiva-consumers/archiva-lucene-consumers/src/main/java/org/apache/maven/archiva/consumers/lucene/IndexArtifactConsumer.java b/archiva-base/archiva-consumers/archiva-lucene-consumers/src/main/java/org/apache/maven/archiva/consumers/lucene/IndexArtifactConsumer.java index 1038cb372..6f9ecff45 100644 --- a/archiva-base/archiva-consumers/archiva-lucene-consumers/src/main/java/org/apache/maven/archiva/consumers/lucene/IndexArtifactConsumer.java +++ b/archiva-base/archiva-consumers/archiva-lucene-consumers/src/main/java/org/apache/maven/archiva/consumers/lucene/IndexArtifactConsumer.java @@ -19,12 +19,30 @@ package org.apache.maven.archiva.consumers.lucene; * under the License. */ +import org.apache.commons.lang.StringUtils; +import org.apache.maven.archiva.configuration.ArchivaConfiguration; +import org.apache.maven.archiva.configuration.ConfigurationNames; +import org.apache.maven.archiva.configuration.RepositoryConfiguration; 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.hashcodes.HashcodesRecord; import org.apache.maven.archiva.model.ArchivaArtifact; +import org.apache.maven.archiva.model.ArchivaRepository; +import org.apache.maven.archiva.repository.ArchivaConfigurationAdaptor; +import org.apache.maven.archiva.repository.layout.BidirectionalRepositoryLayout; +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 java.util.HashMap; +import java.util.Iterator; import java.util.List; +import java.util.Map; /** * IndexArtifactConsumer @@ -38,41 +56,88 @@ import java.util.List; */ public class IndexArtifactConsumer extends AbstractMonitoredConsumer - implements DatabaseUnprocessedArtifactConsumer + implements DatabaseUnprocessedArtifactConsumer, RegistryListener, Initializable { + private static final String INDEX_ERROR = "indexing_error"; + /** * @plexus.configuration default-value="index-artifact" */ private String id; /** - * @plexus.configuration default-value="Index the artifact details for Full Text Search." + * @plexus.configuration default-value="Index the artifact checksums for Find functionality." */ private String description; + + /** + * @plexus.requirement + */ + private ArchivaConfiguration configuration; + + /** + * @plexus.requirement role="org.apache.maven.archiva.repository.layout.BidirectionalRepositoryLayout" + */ + private Map bidirectionalLayoutMap; + + /** + * @plexus.requirement role-hint="lucene" + */ + private RepositoryContentIndexFactory indexFactory; + + private Map repositoryMap = new HashMap(); public void beginScan() { - // TODO Auto-generated method stub - + /* nothing to do here */ } public void completeScan() { - // TODO Auto-generated method stub - + /* nothing to do here */ } public List getIncludedTypes() { - // TODO Auto-generated method stub - return null; + return null; // TODO: define these as a list of artifacts. } public void processArchivaArtifact( ArchivaArtifact artifact ) throws ConsumerException { - // TODO Auto-generated method stub + HashcodesRecord record = new HashcodesRecord(); + record.setRepositoryId( artifact.getModel().getRepositoryId() ); + record.setArtifact( artifact ); + + IndexedRepositoryDetails pnl = getIndexedRepositoryDetails( artifact ); + String artifactPath = pnl.layout.toPath( artifact ); + record.setFilename( artifactPath ); + + try + { + pnl.index.modifyRecord( record ); + } + catch ( RepositoryIndexException e ) + { + triggerConsumerError( INDEX_ERROR, "Unable to index hashcodes: " + e.getMessage() ); + } + } + private IndexedRepositoryDetails getIndexedRepositoryDetails( ArchivaArtifact artifact ) + { + String repoId = artifact.getModel().getRepositoryId(); + if ( StringUtils.isBlank( repoId ) ) + { + throw new IllegalStateException( "Unable to process artifact [" + artifact + + "] as it has no repository id associated with it." ); + } + + return getIndexedRepositoryDetails( repoId ); + } + + private IndexedRepositoryDetails getIndexedRepositoryDetails( String id ) + { + return (IndexedRepositoryDetails) this.repositoryMap.get( id ); } public String getDescription() @@ -90,4 +155,60 @@ public class IndexArtifactConsumer return false; } + public void afterConfigurationChange( Registry registry, String propertyName, Object propertyValue ) + { + if ( ConfigurationNames.isRepositories( propertyName ) ) + { + initRepositoryMap(); + } + } + + public void beforeConfigurationChange( Registry registry, String propertyName, Object propertyValue ) + { + /* do nothing */ + } + + public void initialize() + throws InitializationException + { + initRepositoryMap(); + configuration.addChangeListener( this ); + } + + private void initRepositoryMap() + { + synchronized ( this.repositoryMap ) + { + this.repositoryMap.clear(); + + Iterator it = configuration.getConfiguration().getRepositories().iterator(); + while ( it.hasNext() ) + { + RepositoryConfiguration repoconfig = (RepositoryConfiguration) it.next(); + if ( !repoconfig.isManaged() ) + { + continue; + } + + ArchivaRepository repository = ArchivaConfigurationAdaptor.toArchivaRepository( repoconfig ); + IndexedRepositoryDetails pnl = new IndexedRepositoryDetails(); + + pnl.path = repository.getUrl().getPath(); + pnl.layout = (BidirectionalRepositoryLayout) this.bidirectionalLayoutMap.get( repoconfig.getLayout() ); + + pnl.index = indexFactory.createHashcodeIndex( repository ); + + this.repositoryMap.put( repoconfig.getId(), pnl ); + } + } + } + + class IndexedRepositoryDetails + { + public String path; + + public BidirectionalRepositoryLayout layout; + + public RepositoryContentIndex index; + } } diff --git a/archiva-scheduled/src/main/java/org/apache/maven/archiva/scheduled/DefaultArchivaTaskScheduler.java b/archiva-scheduled/src/main/java/org/apache/maven/archiva/scheduled/DefaultArchivaTaskScheduler.java index 083e9b07d..8d0e5690d 100644 --- a/archiva-scheduled/src/main/java/org/apache/maven/archiva/scheduled/DefaultArchivaTaskScheduler.java +++ b/archiva-scheduled/src/main/java/org/apache/maven/archiva/scheduled/DefaultArchivaTaskScheduler.java @@ -176,6 +176,15 @@ public class DefaultArchivaTaskScheduler dataMap.put( DatabaseTaskJob.TASK_QUEUE, databaseUpdateQueue ); databaseJob.setJobDataMap( dataMap ); + CronExpressionValidator cronValidator = new CronExpressionValidator(); + if ( !cronValidator.validate( cronString ) ) + { + getLogger().warn( + "Cron expression [" + cronString + + "] for database update is invalid. Defaulting to hourly." ); + cronString = CRON_HOURLY; + } + try { CronTrigger trigger = new CronTrigger( DATABASE_JOB_TRIGGER, DATABASE_SCAN_GROUP, cronString ); diff --git a/archiva-web/archiva-webapp/src/main/java/org/apache/maven/archiva/web/action/admin/IndexRepositoryAction.java b/archiva-web/archiva-webapp/src/main/java/org/apache/maven/archiva/web/action/admin/SchedulerAction.java similarity index 75% rename from archiva-web/archiva-webapp/src/main/java/org/apache/maven/archiva/web/action/admin/IndexRepositoryAction.java rename to archiva-web/archiva-webapp/src/main/java/org/apache/maven/archiva/web/action/admin/SchedulerAction.java index fcb345892..fb0db8436 100644 --- a/archiva-web/archiva-webapp/src/main/java/org/apache/maven/archiva/web/action/admin/IndexRepositoryAction.java +++ b/archiva-web/archiva-webapp/src/main/java/org/apache/maven/archiva/web/action/admin/SchedulerAction.java @@ -24,6 +24,7 @@ import org.apache.maven.archiva.common.ArchivaException; import org.apache.maven.archiva.scheduled.ArchivaTaskScheduler; import org.apache.maven.archiva.scheduled.DefaultArchivaTaskScheduler; import org.apache.maven.archiva.scheduled.tasks.ArchivaTask; +import org.apache.maven.archiva.scheduled.tasks.DatabaseTask; import org.apache.maven.archiva.scheduled.tasks.RepositoryTask; import org.apache.maven.archiva.security.ArchivaRoleConstants; import org.codehaus.plexus.redback.rbac.Resource; @@ -36,12 +37,16 @@ import org.codehaus.plexus.xwork.action.PlexusActionSupport; /** * Configures the application. * - * @plexus.component role="com.opensymphony.xwork.Action" role-hint="indexRepositoryAction" + * @plexus.component role="com.opensymphony.xwork.Action" role-hint="schedulerAction" */ -public class IndexRepositoryAction +public class SchedulerAction extends PlexusActionSupport implements SecureAction { + private static final String REPO_SUCCESS = "repoSucces"; + + private static final String DB_SUCCESS = "dbSuccess"; + /** * @plexus.requirement */ @@ -49,7 +54,7 @@ public class IndexRepositoryAction private String repoid; - public String run() + public String scanRepository() { if ( StringUtils.isBlank( repoid ) ) { @@ -106,6 +111,48 @@ public class IndexRepositoryAction return SUCCESS; } + public String updateDatabase() + { + DatabaseTask task = new DatabaseTask(); + task.setName( DefaultArchivaTaskScheduler.DATABASE_JOB + ":user-requested" ); + task.setQueuePolicy( ArchivaTask.QUEUE_POLICY_WAIT ); + + boolean scheduleTask = false; + + try + { + if ( taskScheduler.isProcessingDatabaseTask() ) + { + addActionError( "Database task was already queued." ); + } + else + { + scheduleTask = true; + } + } + catch ( ArchivaException e ) + { + scheduleTask = false; + addActionError( e.getMessage() ); + } + + if ( scheduleTask ) + { + try + { + taskScheduler.queueDatabaseTask( task ); + addActionMessage( "Your request to update the database has been queued." ); + } + catch ( TaskQueueException e ) + { + addActionError( "Unable to queue your request to update the database: " + e.getMessage() ); + } + } + + // Return to the database screen. + return SUCCESS; + } + public void addActionMessage( String aMessage ) { super.addActionMessage( aMessage ); diff --git a/archiva-web/archiva-webapp/src/main/java/org/apache/maven/archiva/web/startup/ConfigurationSynchronization.java b/archiva-web/archiva-webapp/src/main/java/org/apache/maven/archiva/web/startup/ConfigurationSynchronization.java index d6e4fecce..a6b62c117 100644 --- a/archiva-web/archiva-webapp/src/main/java/org/apache/maven/archiva/web/startup/ConfigurationSynchronization.java +++ b/archiva-web/archiva-webapp/src/main/java/org/apache/maven/archiva/web/startup/ConfigurationSynchronization.java @@ -144,5 +144,6 @@ public class ConfigurationSynchronization { Banner.display( getLogger(), ArchivaVersion.determineVersion( this.getClass().getClassLoader() ) ); synchConfiguration(); + archivaConfiguration.addChangeListener( this ); } } diff --git a/archiva-web/archiva-webapp/src/main/resources/webwork.properties b/archiva-web/archiva-webapp/src/main/resources/webwork.properties index b53334909..d9155d8ca 100644 --- a/archiva-web/archiva-webapp/src/main/resources/webwork.properties +++ b/archiva-web/archiva-webapp/src/main/resources/webwork.properties @@ -22,6 +22,6 @@ webwork.mapper.class = org.apache.maven.archiva.web.mapper.RepositoryActionMappe webwork.objectFactory = org.codehaus.plexus.xwork.PlexusObjectFactory webwork.url.includeParams = none -webwork.devMode = true +# webwork.devMode = true # TODO: package up a theme and share with Continuum. Should contain everything from xhtml, and set templateDir to WEB-INF/themes diff --git a/archiva-web/archiva-webapp/src/main/resources/xwork.xml b/archiva-web/archiva-webapp/src/main/resources/xwork.xml index 73cc1bfb5..79aeb4a7e 100644 --- a/archiva-web/archiva-webapp/src/main/resources/xwork.xml +++ b/archiva-web/archiva-webapp/src/main/resources/xwork.xml @@ -238,7 +238,7 @@ deleteRepository - + repositories @@ -344,6 +344,10 @@ /WEB-INF/jsp/admin/database.jsp + + database + + diff --git a/archiva-web/archiva-webapp/src/main/webapp/WEB-INF/jsp/admin/database.jsp b/archiva-web/archiva-webapp/src/main/webapp/WEB-INF/jsp/admin/database.jsp index 04a7e2ba0..7c34f97f8 100644 --- a/archiva-web/archiva-webapp/src/main/webapp/WEB-INF/jsp/admin/database.jsp +++ b/archiva-web/archiva-webapp/src/main/webapp/WEB-INF/jsp/admin/database.jsp @@ -56,6 +56,10 @@ + + + +

Database - Unprocessed Artifacts Scanning

diff --git a/archiva-web/archiva-webapp/src/main/webapp/WEB-INF/jsp/admin/repositories.jsp b/archiva-web/archiva-webapp/src/main/webapp/WEB-INF/jsp/admin/repositories.jsp index 7d3af58c6..7b3a9ca39 100644 --- a/archiva-web/archiva-webapp/src/main/webapp/WEB-INF/jsp/admin/repositories.jsp +++ b/archiva-web/archiva-webapp/src/main/webapp/WEB-INF/jsp/admin/repositories.jsp @@ -157,7 +157,7 @@ - +