001    package org.apache.archiva.scheduler.indexing;
002    /*
003     * Licensed to the Apache Software Foundation (ASF) under one
004     * or more contributor license agreements.  See the NOTICE file
005     * distributed with this work for additional information
006     * regarding copyright ownership.  The ASF licenses this file
007     * to you under the Apache License, Version 2.0 (the
008     * "License"); you may not use this file except in compliance
009     * with the License.  You may obtain a copy of the License at
010     *
011     *   http://www.apache.org/licenses/LICENSE-2.0
012     *
013     * Unless required by applicable law or agreed to in writing,
014     * software distributed under the License is distributed on an
015     * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
016     * KIND, either express or implied.  See the License for the
017     * specific language governing permissions and limitations
018     * under the License.
019     */
020    
021    import org.apache.archiva.admin.model.RepositoryAdminException;
022    import org.apache.archiva.admin.model.beans.NetworkProxy;
023    import org.apache.archiva.admin.model.beans.RemoteRepository;
024    import org.apache.archiva.admin.model.networkproxy.NetworkProxyAdmin;
025    import org.apache.archiva.admin.model.proxyconnector.ProxyConnectorAdmin;
026    import org.apache.archiva.admin.model.remote.RemoteRepositoryAdmin;
027    import org.apache.archiva.common.ArchivaException;
028    import org.apache.archiva.common.plexusbridge.MavenIndexerUtils;
029    import org.apache.archiva.common.plexusbridge.PlexusSisuBridge;
030    import org.apache.archiva.common.plexusbridge.PlexusSisuBridgeException;
031    import org.apache.archiva.configuration.ArchivaConfiguration;
032    import org.apache.archiva.configuration.ConfigurationEvent;
033    import org.apache.archiva.configuration.ConfigurationListener;
034    import org.apache.archiva.proxy.common.WagonFactory;
035    import org.apache.commons.lang.StringUtils;
036    import org.apache.maven.index.NexusIndexer;
037    import org.apache.maven.index.context.IndexingContext;
038    import org.apache.maven.index.context.UnsupportedExistingLuceneIndexException;
039    import org.apache.maven.index.packer.IndexPacker;
040    import org.apache.maven.index.updater.IndexUpdater;
041    import org.slf4j.Logger;
042    import org.slf4j.LoggerFactory;
043    import org.springframework.scheduling.TaskScheduler;
044    import org.springframework.scheduling.support.CronTrigger;
045    import org.springframework.stereotype.Service;
046    
047    import javax.annotation.PostConstruct;
048    import javax.annotation.PreDestroy;
049    import javax.inject.Inject;
050    import javax.inject.Named;
051    import java.io.IOException;
052    import java.util.Date;
053    import java.util.List;
054    import java.util.concurrent.CopyOnWriteArrayList;
055    
056    /**
057     * @author Olivier Lamy
058     * @since 1.4-M1
059     */
060    @Service ("downloadRemoteIndexScheduler#default")
061    public class DefaultDownloadRemoteIndexScheduler
062        implements ConfigurationListener, DownloadRemoteIndexScheduler
063    {
064    
065        private Logger log = LoggerFactory.getLogger( getClass() );
066    
067        @Inject
068        @Named (value = "taskScheduler#indexDownloadRemote")
069        private TaskScheduler taskScheduler;
070    
071        @Inject
072        private ArchivaConfiguration archivaConfiguration;
073    
074        @Inject
075        private WagonFactory wagonFactory;
076    
077        @Inject
078        private RemoteRepositoryAdmin remoteRepositoryAdmin;
079    
080        @Inject
081        private ProxyConnectorAdmin proxyConnectorAdmin;
082    
083        @Inject
084        private NetworkProxyAdmin networkProxyAdmin;
085    
086        @Inject
087        private PlexusSisuBridge plexusSisuBridge;
088    
089        @Inject
090        private MavenIndexerUtils mavenIndexerUtils;
091    
092        private NexusIndexer nexusIndexer;
093    
094        private IndexUpdater indexUpdater;
095    
096        private IndexPacker indexPacker;
097    
098        // store ids about currently running remote download : updated in DownloadRemoteIndexTask
099        private List<String> runningRemoteDownloadIds = new CopyOnWriteArrayList<String>();
100    
101        @PostConstruct
102        public void startup()
103            throws ArchivaException, RepositoryAdminException, PlexusSisuBridgeException, IOException,
104            UnsupportedExistingLuceneIndexException, DownloadRemoteIndexException
105        {
106            archivaConfiguration.addListener( this );
107            // TODO add indexContexts even if null
108    
109            nexusIndexer = plexusSisuBridge.lookup( NexusIndexer.class );
110    
111            indexUpdater = plexusSisuBridge.lookup( IndexUpdater.class );
112    
113            this.indexPacker = plexusSisuBridge.lookup( IndexPacker.class );
114    
115            for ( RemoteRepository remoteRepository : remoteRepositoryAdmin.getRemoteRepositories() )
116            {
117                String contextKey = "remote-" + remoteRepository.getId();
118                IndexingContext context = nexusIndexer.getIndexingContexts().get( contextKey );
119                if ( context == null )
120                {
121                    continue;
122                }
123    
124                // TODO record jobs from configuration
125                if ( remoteRepository.isDownloadRemoteIndex() && StringUtils.isNotEmpty(
126                    remoteRepository.getCronExpression() ) )
127                {
128                    boolean fullDownload = context.getIndexDirectoryFile().list().length == 0;
129                    scheduleDownloadRemote( remoteRepository.getId(), false, fullDownload );
130                }
131            }
132    
133    
134        }
135    
136        @PreDestroy
137        public void shutdown()
138            throws RepositoryAdminException, IOException
139        {
140            for ( RemoteRepository remoteRepository : remoteRepositoryAdmin.getRemoteRepositories() )
141            {
142                String contextKey = "remote-" + remoteRepository.getId();
143                IndexingContext context = nexusIndexer.getIndexingContexts().get( contextKey );
144                if ( context == null )
145                {
146                    continue;
147                }
148                nexusIndexer.removeIndexingContext( context, false );
149            }
150        }
151    
152        public void configurationEvent( ConfigurationEvent event )
153        {
154            // TODO remove jobs and add again
155        }
156    
157    
158        public void scheduleDownloadRemote( String repositoryId, boolean now, boolean fullDownload )
159            throws DownloadRemoteIndexException
160        {
161            try
162            {
163                RemoteRepository remoteRepository = remoteRepositoryAdmin.getRemoteRepository( repositoryId );
164                if ( remoteRepository == null )
165                {
166                    log.warn( "ignore scheduleDownloadRemote for repo with id {} as not exists", repositoryId );
167                    return;
168                }
169                NetworkProxy networkProxy = null;
170                if ( StringUtils.isNotBlank( remoteRepository.getRemoteDownloadNetworkProxyId() ) )
171                {
172                    networkProxy = networkProxyAdmin.getNetworkProxy( remoteRepository.getRemoteDownloadNetworkProxyId() );
173                    if ( networkProxy == null )
174                    {
175                        log.warn(
176                            "your remote repository is configured to download remote index trought a proxy we cannot find id:{}",
177                            remoteRepository.getRemoteDownloadNetworkProxyId() );
178                    }
179                }
180    
181                DownloadRemoteIndexTaskRequest downloadRemoteIndexTaskRequest =
182                    new DownloadRemoteIndexTaskRequest().setRemoteRepository( remoteRepository ).setNetworkProxy(
183                        networkProxy ).setFullDownload( fullDownload ).setWagonFactory(
184                        wagonFactory ).setRemoteRepositoryAdmin( remoteRepositoryAdmin ).setIndexUpdater(
185                        indexUpdater ).setIndexPacker( this.indexPacker );
186    
187                if ( now )
188                {
189                    log.info( "schedule download remote index for repository {}", remoteRepository.getId() );
190                    // do it now
191                    taskScheduler.schedule(
192                        new DownloadRemoteIndexTask( downloadRemoteIndexTaskRequest, this.runningRemoteDownloadIds ),
193                        new Date() );
194                }
195                else
196                {
197                    log.info( "schedule download remote index for repository {} with cron expression {}",
198                              remoteRepository.getId(), remoteRepository.getCronExpression() );
199                    try
200                    {
201                        CronTrigger cronTrigger = new CronTrigger( remoteRepository.getCronExpression() );
202                        taskScheduler.schedule(
203                            new DownloadRemoteIndexTask( downloadRemoteIndexTaskRequest, this.runningRemoteDownloadIds ),
204                            cronTrigger );
205                    }
206                    catch ( IllegalArgumentException e )
207                    {
208                        log.warn( "Unable to schedule remote index download: " + e.getLocalizedMessage() );
209                    }
210    
211                    if ( remoteRepository.isDownloadRemoteIndexOnStartup() )
212                    {
213                        log.info(
214                            "remote repository {} configured with downloadRemoteIndexOnStartup schedule now a download",
215                            remoteRepository.getId() );
216                        taskScheduler.schedule(
217                            new DownloadRemoteIndexTask( downloadRemoteIndexTaskRequest, this.runningRemoteDownloadIds ),
218                            new Date() );
219                    }
220                }
221    
222            }
223            catch ( RepositoryAdminException e )
224            {
225                log.error( e.getMessage(), e );
226                throw new DownloadRemoteIndexException( e.getMessage(), e );
227            }
228        }
229    
230        public TaskScheduler getTaskScheduler()
231        {
232            return taskScheduler;
233        }
234    
235        public void setTaskScheduler( TaskScheduler taskScheduler )
236        {
237            this.taskScheduler = taskScheduler;
238        }
239    }