package org.apache.maven.repository.scheduler;

/*
 * Copyright 2005-2006 The Apache Software Foundation.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

import org.apache.maven.repository.configuration.Configuration;
import org.apache.maven.repository.configuration.ConfigurationChangeException;
import org.apache.maven.repository.configuration.ConfigurationChangeListener;
import org.apache.maven.repository.configuration.ConfigurationStore;
import org.apache.maven.repository.configuration.ConfigurationStoreException;
import org.apache.maven.repository.configuration.InvalidConfigurationException;
import org.codehaus.plexus.logging.AbstractLogEnabled;
import org.codehaus.plexus.personality.plexus.lifecycle.phase.Startable;
import org.codehaus.plexus.personality.plexus.lifecycle.phase.StartingException;
import org.codehaus.plexus.personality.plexus.lifecycle.phase.StoppingException;
import org.codehaus.plexus.scheduler.AbstractJob;
import org.codehaus.plexus.scheduler.Scheduler;
import org.quartz.CronTrigger;
import org.quartz.JobDataMap;
import org.quartz.JobDetail;
import org.quartz.SchedulerException;

import java.text.ParseException;

/**
 * Default implementation of a scheduling component for the application.
 *
 * @author <a href="mailto:brett@apache.org">Brett Porter</a>
 * @todo should we use plexus-taskqueue instead of or in addition to this?
 * @plexus.component role="org.apache.maven.repository.scheduler.RepositoryTaskScheduler"
 */
public class DefaultRepositoryTaskScheduler
    extends AbstractLogEnabled
    implements RepositoryTaskScheduler, Startable, ConfigurationChangeListener
{
    /**
     * @plexus.requirement
     */
    private Scheduler scheduler;

    /**
     * @plexus.requirement
     */
    private ConfigurationStore configurationStore;

    private static final String DISCOVERER_GROUP = "DISCOVERER";

    private static final String INDEXER_JOB = "indexerTask";

    /**
     * @plexus.requirement role-hint="indexer"
     */
    private RepositoryTask indexerTask;

    public void start()
        throws StartingException
    {
        Configuration configuration;
        try
        {
            configuration = configurationStore.getConfigurationFromStore();
            configurationStore.addChangeListener( this );
        }
        catch ( ConfigurationStoreException e )
        {
            throw new StartingException( "Unable to read configuration from the store", e );
        }

        try
        {
            scheduleJobs( configuration );
        }
        catch ( ParseException e )
        {
            throw new StartingException( "Invalid configuration: " + configuration.getIndexerCronExpression(), e );
        }
        catch ( SchedulerException e )
        {
            throw new StartingException( "Unable to start scheduler: " + e.getMessage(), e );
        }
    }

    private void scheduleJobs( Configuration configuration )
        throws ParseException, SchedulerException
    {
        JobDetail jobDetail = new JobDetail( INDEXER_JOB, DISCOVERER_GROUP, RepositoryTaskJob.class );
        JobDataMap dataMap = new JobDataMap();
        dataMap.put( AbstractJob.LOGGER, getLogger() );
        dataMap.put( RepositoryTaskJob.TASK_KEY, indexerTask );
        jobDetail.setJobDataMap( dataMap );

        getLogger().info( "Scheduling indexer: " + configuration.getIndexerCronExpression() );
        CronTrigger trigger =
            new CronTrigger( INDEXER_JOB + "Trigger", DISCOVERER_GROUP, configuration.getIndexerCronExpression() );
        scheduler.scheduleJob( jobDetail, trigger );

        try
        {
            indexerTask.executeNowIfNeeded();
        }
        catch ( TaskExecutionException e )
        {
            getLogger().error( "Error executing task first time, continuing anyway: " + e.getMessage(), e );
        }

        // TODO: wire in the converter
    }

    public void stop()
        throws StoppingException
    {
        try
        {
            scheduler.unscheduleJob( INDEXER_JOB, DISCOVERER_GROUP );
        }
        catch ( SchedulerException e )
        {
            throw new StoppingException( "Unable to unschedule tasks", e );
        }
    }

    public void notifyOfConfigurationChange( Configuration configuration )
        throws InvalidConfigurationException, ConfigurationChangeException
    {
        try
        {
            stop();

            scheduleJobs( configuration );
        }
        catch ( StoppingException e )
        {
            throw new ConfigurationChangeException( "Unable to unschedule previous tasks", e );
        }
        catch ( ParseException e )
        {
            throw new InvalidConfigurationException( "discoveryCronExpression", "Invalid cron expression", e );
        }
        catch ( SchedulerException e )
        {
            throw new ConfigurationChangeException( "Unable to schedule new tasks", e );
        }
    }

    public void runIndexer()
        throws TaskExecutionException
    {
        indexerTask.execute();

    }
}

@@ -3476,32 +3476,98 @@
 Exception%0A    %7B%0A
+        if ( configuration.getIndexPath() != null )%0A        %7B%0A    
         JobDetai
@@ -3657,24 +3657,28 @@
  );%0A        
+    
 JobDataMap d
@@ -3700,24 +3700,28 @@
 bDataMap();%0A
+    
         data
@@ -3764,32 +3764,36 @@
 er() );%0A        
+ 
+   
 dataMap.put( Rep
@@ -3840,16 +3840,20 @@
         
+    
 jobDetai
@@ -3881,32 +3881,36 @@
 Map );%0A%0A        
+ 
+   
 getLogger().info
@@ -3988,16 +3988,20 @@
         
+    
 CronTrig
@@ -4026,16 +4026,20 @@
         
+ 
+   
 new Cron
@@ -4134,32 +4134,36 @@
 on() );%0A        
+    
 scheduler.schedu
@@ -4192,32 +4192,36 @@
 ger );%0A%0A        
+ 
+   
 try%0A        %7B%0A  
@@ -4208,34 +4208,42 @@
     try%0A        
+   
+ 
 %7B%0A
+    
             inde
@@ -4272,32 +4272,36 @@
 eded();%0A        
+    
 %7D%0A        catch 
@@ -4286,32 +4286,36 @@
       %7D%0A        
+ 
+   
 catch ( TaskExec
@@ -4333,34 +4333,42 @@
 ion e )%0A        
-%7B%0A
+    %7B%0A    
             getL
@@ -4452,32 +4452,168 @@
 Message(), e );%0A
+            %7D%0A        %7D%0A        else%0A        %7B%0A            getLogger().info( %22Not scheduling indexer - index path is not configured%22 );%0A
         %7D%0A%0A     
@@ -5787,21 +5787,20 @@
 .execute();%0A
-%0A
     %7D%0A%7D%0A

fix bug in initial startup