001    package org.apache.archiva.web.startup;
002    
003    /*
004     * Licensed to the Apache Software Foundation (ASF) under one
005     * or more contributor license agreements.  See the NOTICE file
006     * distributed with this work for additional information
007     * regarding copyright ownership.  The ASF licenses this file
008     * to you under the Apache License, Version 2.0 (the
009     * "License"); you may not use this file except in compliance
010     * with the License.  You may obtain a copy of the License at
011     *
012     *  http://www.apache.org/licenses/LICENSE-2.0
013     *
014     * Unless required by applicable law or agreed to in writing,
015     * software distributed under the License is distributed on an
016     * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
017     * KIND, either express or implied.  See the License for the
018     * specific language governing permissions and limitations
019     * under the License.
020     */
021    
022    import org.apache.archiva.common.ArchivaException;
023    import org.apache.archiva.common.plexusbridge.PlexusSisuBridge;
024    import org.apache.archiva.common.plexusbridge.PlexusSisuBridgeException;
025    import org.apache.archiva.redback.components.scheduler.DefaultScheduler;
026    import org.apache.archiva.scheduler.repository.DefaultRepositoryArchivaTaskScheduler;
027    import org.apache.maven.index.NexusIndexer;
028    import org.apache.maven.index.context.IndexingContext;
029    import org.apache.archiva.redback.components.taskqueue.Task;
030    import org.apache.archiva.redback.components.taskqueue.execution.ThreadedTaskQueueExecutor;
031    import org.quartz.SchedulerException;
032    import org.springframework.web.context.WebApplicationContext;
033    import org.springframework.web.context.support.WebApplicationContextUtils;
034    
035    import javax.servlet.ServletContextEvent;
036    import javax.servlet.ServletContextListener;
037    import java.lang.reflect.Field;
038    import java.util.Properties;
039    import java.util.concurrent.ExecutorService;
040    
041    /**
042     * ArchivaStartup - the startup of all archiva features in a deterministic order.
043     *
044     *
045     */
046    public class ArchivaStartup
047        implements ServletContextListener
048    {
049        private ThreadedTaskQueueExecutor tqeDbScanning;
050    
051        private ThreadedTaskQueueExecutor tqeRepoScanning;
052    
053        private ThreadedTaskQueueExecutor tqeIndexing;
054    
055        private DefaultRepositoryArchivaTaskScheduler repositoryTaskScheduler;
056    
057        private PlexusSisuBridge plexusSisuBridge;
058    
059        private NexusIndexer nexusIndexer;
060    
061        public void contextInitialized( ServletContextEvent contextEvent )
062        {
063            WebApplicationContext wac =
064                WebApplicationContextUtils.getRequiredWebApplicationContext( contextEvent.getServletContext() );
065    
066            SecuritySynchronization securitySync = wac.getBean( SecuritySynchronization.class );
067    
068            repositoryTaskScheduler =
069                wac.getBean( "archivaTaskScheduler#repository", DefaultRepositoryArchivaTaskScheduler.class );
070    
071            Properties archivaRuntimeProperties = wac.getBean( "archivaRuntimeProperties", Properties.class );
072    
073            tqeRepoScanning = wac.getBean( "taskQueueExecutor#repository-scanning", ThreadedTaskQueueExecutor.class );
074    
075            tqeIndexing = wac.getBean( "taskQueueExecutor#indexing", ThreadedTaskQueueExecutor.class );
076    
077            plexusSisuBridge = wac.getBean( PlexusSisuBridge.class );
078    
079            try
080            {
081                nexusIndexer = plexusSisuBridge.lookup( NexusIndexer.class );
082            }
083            catch ( PlexusSisuBridgeException e )
084            {
085                throw new RuntimeException( "Unable to get NexusIndexer: " + e.getMessage(), e );
086            }
087            try
088            {
089                securitySync.startup();
090                repositoryTaskScheduler.startup();
091                Banner.display( (String) archivaRuntimeProperties.get( "archiva.version" ) );
092            }
093            catch ( ArchivaException e )
094            {
095                throw new RuntimeException( "Unable to properly startup archiva: " + e.getMessage(), e );
096            }
097        }
098    
099        public void contextDestroyed( ServletContextEvent contextEvent )
100        {
101            WebApplicationContext applicationContext =
102                WebApplicationContextUtils.getRequiredWebApplicationContext( contextEvent.getServletContext() );
103    
104            // TODO check this stop
105    
106            /*
107            if ( applicationContext != null && applicationContext instanceof ClassPathXmlApplicationContext )
108            {
109                ( (ClassPathXmlApplicationContext) applicationContext ).close();
110            } */
111    
112            if ( applicationContext != null ) //&& applicationContext instanceof PlexusWebApplicationContext )
113            {
114                // stop task queue executors
115                stopTaskQueueExecutor( tqeDbScanning );
116                stopTaskQueueExecutor( tqeRepoScanning );
117                stopTaskQueueExecutor( tqeIndexing );
118    
119                // stop the DefaultArchivaTaskScheduler and its scheduler
120                if ( repositoryTaskScheduler != null )
121                {
122                    try
123                    {
124                        repositoryTaskScheduler.stop();
125                    }
126                    catch ( SchedulerException e )
127                    {
128                        e.printStackTrace();
129                    }
130    
131                    try
132                    {
133                        // shutdown the scheduler, otherwise Quartz scheduler and Threads still exists
134                        Field schedulerField = repositoryTaskScheduler.getClass().getDeclaredField( "scheduler" );
135                        schedulerField.setAccessible( true );
136    
137                        DefaultScheduler scheduler = (DefaultScheduler) schedulerField.get( repositoryTaskScheduler );
138                        scheduler.stop();
139                    }
140                    catch ( Exception e )
141                    {
142                        e.printStackTrace();
143                    }
144                }
145    
146                // close the application context
147                //applicationContext.close();
148                // TODO fix close call
149                //applicationContext.
150            }
151    
152            // closing correctly indexer to close correctly lock and file
153            for ( IndexingContext indexingContext : nexusIndexer.getIndexingContexts().values() )
154            {
155                try
156                {
157                    indexingContext.close( false );
158                }
159                catch ( Exception e )
160                {
161                    contextEvent.getServletContext().log( "skip error closing indexingContext " + e.getMessage() );
162                }
163            }
164    
165        }
166    
167        private void stopTaskQueueExecutor( ThreadedTaskQueueExecutor taskQueueExecutor )
168        {
169            if ( taskQueueExecutor != null )
170            {
171                Task currentTask = taskQueueExecutor.getCurrentTask();
172                if ( currentTask != null )
173                {
174                    taskQueueExecutor.cancelTask( currentTask );
175                }
176    
177                try
178                {
179                    taskQueueExecutor.stop();
180                    ExecutorService service = getExecutorServiceForTTQE( taskQueueExecutor );
181                    if ( service != null )
182                    {
183                        service.shutdown();
184                    }
185                }
186                catch ( Exception e )
187                {
188                    e.printStackTrace();
189                }
190            }
191        }
192    
193        private ExecutorService getExecutorServiceForTTQE( ThreadedTaskQueueExecutor ttqe )
194        {
195            ExecutorService service = null;
196            try
197            {
198                Field executorServiceField = ttqe.getClass().getDeclaredField( "executorService" );
199                executorServiceField.setAccessible( true );
200                service = (ExecutorService) executorServiceField.get( ttqe );
201            }
202            catch ( Exception e )
203            {
204                e.printStackTrace();
205            }
206            return service;
207        }
208    }