001package 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 022import org.apache.archiva.common.ArchivaException; 023import org.apache.archiva.components.scheduler.DefaultScheduler; 024import org.apache.archiva.components.taskqueue.Task; 025import org.apache.archiva.components.taskqueue.execution.ThreadedTaskQueueExecutor; 026import org.apache.archiva.scheduler.repository.DefaultRepositoryArchivaTaskScheduler; 027import org.quartz.SchedulerException; 028import org.springframework.web.context.WebApplicationContext; 029import org.springframework.web.context.support.WebApplicationContextUtils; 030 031import javax.servlet.ServletContext; 032import javax.servlet.ServletContextEvent; 033import javax.servlet.ServletContextListener; 034import java.lang.reflect.Field; 035import java.util.Properties; 036import java.util.concurrent.ExecutorService; 037 038/** 039 * ArchivaStartup - the startup of all archiva features in a deterministic order. 040 */ 041public class ArchivaStartup 042 implements ServletContextListener 043{ 044 private ThreadedTaskQueueExecutor tqeDbScanning; 045 046 private ThreadedTaskQueueExecutor tqeRepoScanning; 047 048 private ThreadedTaskQueueExecutor tqeIndexing; 049 050 private DefaultRepositoryArchivaTaskScheduler repositoryTaskScheduler; 051 052 @Override 053 public void contextInitialized( ServletContextEvent contextEvent ) 054 { 055 WebApplicationContext wac = 056 WebApplicationContextUtils.getRequiredWebApplicationContext( contextEvent.getServletContext() ); 057 058 SecuritySynchronization securitySync = wac.getBean( SecuritySynchronization.class ); 059 060 repositoryTaskScheduler = 061 wac.getBean( "archivaTaskScheduler#repository", DefaultRepositoryArchivaTaskScheduler.class ); 062 063 Properties archivaRuntimeProperties = wac.getBean( "archivaRuntimeProperties", Properties.class ); 064 065 tqeRepoScanning = wac.getBean( "taskQueueExecutor#repository-scanning", ThreadedTaskQueueExecutor.class ); 066 067 tqeIndexing = wac.getBean( "taskQueueExecutor#indexing", ThreadedTaskQueueExecutor.class ); 068 069 070 try 071 { 072 securitySync.startup(); 073 repositoryTaskScheduler.startup(); 074 Banner.display( (String) archivaRuntimeProperties.get( "archiva.version" ) ); 075 } 076 catch ( ArchivaException e ) 077 { 078 throw new RuntimeException( "Unable to properly startup archiva: " + e.getMessage(), e ); 079 } 080 } 081 082 @Override 083 public void contextDestroyed( ServletContextEvent contextEvent ) 084 { 085 WebApplicationContext applicationContext = 086 WebApplicationContextUtils.getRequiredWebApplicationContext( contextEvent.getServletContext() ); 087 088 // we log using servlet mechanism as due to some possible problem with slf4j when container shutdown 089 // so servletContext.log 090 ServletContext servletContext = contextEvent.getServletContext(); 091 092 // TODO check this stop 093 094 /* 095 if ( applicationContext != null && applicationContext instanceof ClassPathXmlApplicationContext ) 096 { 097 ( (ClassPathXmlApplicationContext) applicationContext ).close(); 098 } */ 099 100 if ( applicationContext != null ) //&& applicationContext instanceof PlexusWebApplicationContext ) 101 { 102 // stop task queue executors 103 stopTaskQueueExecutor( tqeDbScanning, servletContext ); 104 stopTaskQueueExecutor( tqeRepoScanning, servletContext ); 105 stopTaskQueueExecutor( tqeIndexing, servletContext ); 106 107 // stop the DefaultArchivaTaskScheduler and its scheduler 108 if ( repositoryTaskScheduler != null ) 109 { 110 try 111 { 112 repositoryTaskScheduler.stop(); 113 } 114 catch ( SchedulerException e ) 115 { 116 servletContext.log( e.getMessage(), e ); 117 } 118 119 try 120 { 121 // shutdown the scheduler, otherwise Quartz scheduler and Threads still exists 122 Field schedulerField = repositoryTaskScheduler.getClass().getDeclaredField( "scheduler" ); 123 schedulerField.setAccessible( true ); 124 125 DefaultScheduler scheduler = (DefaultScheduler) schedulerField.get( repositoryTaskScheduler ); 126 scheduler.stop(); 127 } 128 catch ( Exception e ) 129 { 130 servletContext.log( e.getMessage(), e ); 131 } 132 } 133 134 // close the application context 135 //applicationContext.close(); 136 // TODO fix close call 137 //applicationContext. 138 } 139 140 141 } 142 143 private void stopTaskQueueExecutor( ThreadedTaskQueueExecutor taskQueueExecutor, ServletContext servletContext ) 144 { 145 if ( taskQueueExecutor != null ) 146 { 147 Task currentTask = taskQueueExecutor.getCurrentTask(); 148 if ( currentTask != null ) 149 { 150 taskQueueExecutor.cancelTask( currentTask ); 151 } 152 153 try 154 { 155 taskQueueExecutor.stop(); 156 ExecutorService service = getExecutorServiceForTTQE( taskQueueExecutor, servletContext ); 157 if ( service != null ) 158 { 159 service.shutdown(); 160 } 161 } 162 catch ( Exception e ) 163 { 164 servletContext.log( e.getMessage(), e ); 165 } 166 } 167 } 168 169 private ExecutorService getExecutorServiceForTTQE( ThreadedTaskQueueExecutor ttqe, ServletContext servletContext ) 170 { 171 ExecutorService service = null; 172 try 173 { 174 Field executorServiceField = ttqe.getClass().getDeclaredField( "executorService" ); 175 executorServiceField.setAccessible( true ); 176 service = (ExecutorService) executorServiceField.get( ttqe ); 177 } 178 catch ( Exception e ) 179 { 180 servletContext.log( e.getMessage(), e ); 181 } 182 return service; 183 } 184}