001    package org.apache.archiva.admin.repository.remote;
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.AuditInformation;
022    import org.apache.archiva.admin.model.RepositoryAdminException;
023    import org.apache.archiva.admin.model.beans.RemoteRepository;
024    import org.apache.archiva.admin.model.remote.RemoteRepositoryAdmin;
025    import org.apache.archiva.admin.repository.AbstractRepositoryAdmin;
026    import org.apache.archiva.audit.AuditEvent;
027    import org.apache.archiva.common.plexusbridge.MavenIndexerUtils;
028    import org.apache.archiva.common.plexusbridge.PlexusSisuBridge;
029    import org.apache.archiva.common.plexusbridge.PlexusSisuBridgeException;
030    import org.apache.archiva.configuration.Configuration;
031    import org.apache.archiva.configuration.ProxyConnectorConfiguration;
032    import org.apache.archiva.configuration.RemoteRepositoryConfiguration;
033    import org.apache.commons.lang.StringUtils;
034    import org.apache.maven.index.NexusIndexer;
035    import org.apache.maven.index.context.IndexCreator;
036    import org.apache.maven.index.context.IndexingContext;
037    import org.apache.maven.index.context.UnsupportedExistingLuceneIndexException;
038    import org.springframework.stereotype.Service;
039    
040    import javax.annotation.PostConstruct;
041    import javax.annotation.PreDestroy;
042    import javax.inject.Inject;
043    import java.io.File;
044    import java.io.IOException;
045    import java.net.MalformedURLException;
046    import java.util.ArrayList;
047    import java.util.HashMap;
048    import java.util.List;
049    import java.util.Map;
050    
051    /**
052     * @author Olivier Lamy
053     * @since 1.4-M1
054     */
055    @Service ( "remoteRepositoryAdmin#default" )
056    public class DefaultRemoteRepositoryAdmin
057        extends AbstractRepositoryAdmin
058        implements RemoteRepositoryAdmin
059    {
060    
061        @Inject
062        private PlexusSisuBridge plexusSisuBridge;
063    
064        @Inject
065        private MavenIndexerUtils mavenIndexerUtils;
066    
067        // fields
068        List<? extends IndexCreator> indexCreators;
069    
070        NexusIndexer indexer;
071    
072        @PostConstruct
073        private void initialize()
074            throws RepositoryAdminException
075        {
076            try
077            {
078                indexCreators = mavenIndexerUtils.getAllIndexCreators();
079                indexer = plexusSisuBridge.lookup( NexusIndexer.class );
080            }
081            catch ( PlexusSisuBridgeException e )
082            {
083                throw new RepositoryAdminException( e.getMessage(), e );
084            }
085            for ( RemoteRepository remoteRepository : getRemoteRepositories() )
086            {
087                createIndexContext( remoteRepository );
088            }
089        }
090    
091        @PreDestroy
092        private void shutdown()
093            throws RepositoryAdminException
094        {
095            try
096            {
097                List<RemoteRepository> remoteRepositories = getRemoteRepositories();
098                // close index on shutdown
099                for ( RemoteRepository remoteRepository : remoteRepositories )
100                {
101                    IndexingContext context = indexer.getIndexingContexts().get( remoteRepository.getId() );
102                    if ( context != null )
103                    {
104                        indexer.removeIndexingContext( context, false );
105                    }
106                }
107            }
108            catch ( IOException e )
109            {
110                throw new RepositoryAdminException( e.getMessage(), e );
111            }
112        }
113    
114    
115        public List<RemoteRepository> getRemoteRepositories()
116            throws RepositoryAdminException
117        {
118            List<RemoteRepository> remoteRepositories = new ArrayList<RemoteRepository>(
119                getArchivaConfiguration().getConfiguration().getRemoteRepositories().size() );
120            for ( RemoteRepositoryConfiguration repositoryConfiguration : getArchivaConfiguration().getConfiguration().getRemoteRepositories() )
121            {
122                RemoteRepository remoteRepository =
123                    new RemoteRepository( repositoryConfiguration.getId(), repositoryConfiguration.getName(),
124                                          repositoryConfiguration.getUrl(), repositoryConfiguration.getLayout(),
125                                          repositoryConfiguration.getUsername(), repositoryConfiguration.getPassword(),
126                                          repositoryConfiguration.getTimeout() );
127                remoteRepository.setDownloadRemoteIndex( repositoryConfiguration.isDownloadRemoteIndex() );
128                remoteRepository.setRemoteIndexUrl( repositoryConfiguration.getRemoteIndexUrl() );
129                remoteRepository.setCronExpression( repositoryConfiguration.getRefreshCronExpression() );
130                remoteRepository.setIndexDirectory( repositoryConfiguration.getIndexDir() );
131                remoteRepository.setRemoteDownloadNetworkProxyId(
132                    repositoryConfiguration.getRemoteDownloadNetworkProxyId() );
133                remoteRepository.setRemoteDownloadTimeout( repositoryConfiguration.getRemoteDownloadTimeout() );
134                remoteRepository.setDownloadRemoteIndexOnStartup(
135                    repositoryConfiguration.isDownloadRemoteIndexOnStartup() );
136                remoteRepository.setDescription( repositoryConfiguration.getDescription() );
137                remoteRepository.setExtraHeaders( repositoryConfiguration.getExtraHeaders() );
138                remoteRepository.setExtraParameters( repositoryConfiguration.getExtraParameters() );
139                remoteRepositories.add( remoteRepository );
140            }
141            return remoteRepositories;
142        }
143    
144        public RemoteRepository getRemoteRepository( String repositoryId )
145            throws RepositoryAdminException
146        {
147            for ( RemoteRepository remoteRepository : getRemoteRepositories() )
148            {
149                if ( StringUtils.equals( repositoryId, remoteRepository.getId() ) )
150                {
151                    return remoteRepository;
152                }
153            }
154            return null;
155        }
156    
157        public Boolean addRemoteRepository( RemoteRepository remoteRepository, AuditInformation auditInformation )
158            throws RepositoryAdminException
159        {
160            triggerAuditEvent( remoteRepository.getId(), null, AuditEvent.ADD_REMOTE_REPO, auditInformation );
161            getRepositoryCommonValidator().basicValidation( remoteRepository, false );
162    
163            //TODO we can validate it's a good uri/url
164            if ( StringUtils.isEmpty( remoteRepository.getUrl() ) )
165            {
166                throw new RepositoryAdminException( "url cannot be null" );
167            }
168    
169            //MRM-752 - url needs trimming
170            remoteRepository.setUrl( StringUtils.trim( remoteRepository.getUrl() ) );
171    
172            RemoteRepositoryConfiguration remoteRepositoryConfiguration =
173                getRemoteRepositoryConfiguration( remoteRepository );
174    
175            Configuration configuration = getArchivaConfiguration().getConfiguration();
176            configuration.addRemoteRepository( remoteRepositoryConfiguration );
177            saveConfiguration( configuration );
178    
179            return Boolean.TRUE;
180        }
181    
182        public Boolean deleteRemoteRepository( String repositoryId, AuditInformation auditInformation )
183            throws RepositoryAdminException
184        {
185    
186            triggerAuditEvent( repositoryId, null, AuditEvent.DELETE_REMOTE_REPO, auditInformation );
187    
188            Configuration configuration = getArchivaConfiguration().getConfiguration();
189    
190            RemoteRepositoryConfiguration remoteRepositoryConfiguration =
191                configuration.getRemoteRepositoriesAsMap().get( repositoryId );
192            if ( remoteRepositoryConfiguration == null )
193            {
194                throw new RepositoryAdminException(
195                    "remoteRepository with id " + repositoryId + " not exist cannot remove it" );
196            }
197    
198            configuration.removeRemoteRepository( remoteRepositoryConfiguration );
199    
200            // TODO use ProxyConnectorAdmin interface ?
201            // [MRM-520] Proxy Connectors are not deleted with the deletion of a Repository.
202            List<ProxyConnectorConfiguration> proxyConnectors =
203                new ArrayList<ProxyConnectorConfiguration>( configuration.getProxyConnectors() );
204            for ( ProxyConnectorConfiguration proxyConnector : proxyConnectors )
205            {
206                if ( StringUtils.equals( proxyConnector.getTargetRepoId(), repositoryId ) )
207                {
208                    configuration.removeProxyConnector( proxyConnector );
209                }
210            }
211    
212            saveConfiguration( configuration );
213    
214            return Boolean.TRUE;
215        }
216    
217        public Boolean updateRemoteRepository( RemoteRepository remoteRepository, AuditInformation auditInformation )
218            throws RepositoryAdminException
219        {
220    
221            String repositoryId = remoteRepository.getId();
222    
223            triggerAuditEvent( repositoryId, null, AuditEvent.MODIFY_REMOTE_REPO, auditInformation );
224    
225            // update means : remove and add
226    
227            Configuration configuration = getArchivaConfiguration().getConfiguration();
228    
229            RemoteRepositoryConfiguration remoteRepositoryConfiguration =
230                configuration.getRemoteRepositoriesAsMap().get( repositoryId );
231            if ( remoteRepositoryConfiguration == null )
232            {
233                throw new RepositoryAdminException(
234                    "remoteRepository with id " + repositoryId + " not exist cannot remove it" );
235            }
236    
237            configuration.removeRemoteRepository( remoteRepositoryConfiguration );
238    
239            remoteRepositoryConfiguration = getRemoteRepositoryConfiguration( remoteRepository );
240            configuration.addRemoteRepository( remoteRepositoryConfiguration );
241            saveConfiguration( configuration );
242    
243            return Boolean.TRUE;
244        }
245    
246        public Map<String, RemoteRepository> getRemoteRepositoriesAsMap()
247            throws RepositoryAdminException
248        {
249            java.util.Map<String, RemoteRepository> map = new HashMap<String, RemoteRepository>();
250    
251            for ( RemoteRepository repo : getRemoteRepositories() )
252            {
253                map.put( repo.getId(), repo );
254            }
255    
256            return map;
257        }
258    
259        public IndexingContext createIndexContext( RemoteRepository remoteRepository )
260            throws RepositoryAdminException
261        {
262            try
263            {
264                String appServerBase = getRegistry().getString( "appserver.base" );
265    
266                String contextKey = "remote-" + remoteRepository.getId();
267                IndexingContext indexingContext = indexer.getIndexingContexts().get( contextKey );
268                if ( indexingContext != null )
269                {
270                    return indexingContext;
271                }
272                // create remote repository path
273                File repoDir = new File( appServerBase, "data/remotes/" + remoteRepository.getId() );
274                if ( !repoDir.exists() )
275                {
276                    repoDir.mkdirs();
277                }
278    
279                File indexDirectory = null;
280    
281                // is there configured indexDirectory ?
282                String indexDirectoryPath = remoteRepository.getIndexDirectory();
283    
284                if ( StringUtils.isNotBlank( indexDirectoryPath ) )
285                {
286                    if ( new File( indexDirectoryPath ).isAbsolute() )
287                    {
288                        indexDirectory = new File( indexDirectoryPath );
289                    }
290                    else
291                    {
292                        indexDirectory = new File( repoDir, indexDirectoryPath );
293                    }
294                }
295                // if not configured use a default value
296                if ( indexDirectory == null )
297                {
298                    indexDirectory = new File( repoDir, ".index" );
299                }
300                if ( !indexDirectory.exists() )
301                {
302                    indexDirectory.mkdirs();
303                }
304                return indexer.addIndexingContext( contextKey, remoteRepository.getId(), repoDir, indexDirectory,
305                                                   remoteRepository.getUrl(), calculateIndexRemoteUrl( remoteRepository ),
306                                                   mavenIndexerUtils.getAllIndexCreators() );
307            }
308            catch ( MalformedURLException e )
309            {
310                throw new RepositoryAdminException( e.getMessage(), e );
311            }
312            catch ( IOException e )
313            {
314                throw new RepositoryAdminException( e.getMessage(), e );
315            }
316            catch ( UnsupportedExistingLuceneIndexException e )
317            {
318                throw new RepositoryAdminException( e.getMessage(), e );
319            }
320    
321        }
322    
323        protected String calculateIndexRemoteUrl( RemoteRepository remoteRepository )
324        {
325            if ( StringUtils.startsWith( remoteRepository.getRemoteIndexUrl(), "http" ) )
326            {
327                String baseUrl = remoteRepository.getRemoteIndexUrl();
328                return baseUrl.endsWith( "/" ) ? StringUtils.substringBeforeLast( baseUrl, "/" ) : baseUrl;
329            }
330            String baseUrl = StringUtils.endsWith( remoteRepository.getUrl(), "/" ) ? StringUtils.substringBeforeLast(
331                remoteRepository.getUrl(), "/" ) : remoteRepository.getUrl();
332    
333            baseUrl = StringUtils.isEmpty( remoteRepository.getRemoteIndexUrl() )
334                ? baseUrl + "/.index"
335                : baseUrl + "/" + remoteRepository.getRemoteIndexUrl();
336            return baseUrl;
337    
338        }
339    
340        private RemoteRepositoryConfiguration getRemoteRepositoryConfiguration( RemoteRepository remoteRepository )
341        {
342            RemoteRepositoryConfiguration remoteRepositoryConfiguration = new RemoteRepositoryConfiguration();
343            remoteRepositoryConfiguration.setId( remoteRepository.getId() );
344            remoteRepositoryConfiguration.setPassword( remoteRepository.getPassword() );
345            remoteRepositoryConfiguration.setTimeout( remoteRepository.getTimeout() );
346            remoteRepositoryConfiguration.setUrl( remoteRepository.getUrl() );
347            remoteRepositoryConfiguration.setUsername( remoteRepository.getUserName() );
348            remoteRepositoryConfiguration.setLayout( remoteRepository.getLayout() );
349            remoteRepositoryConfiguration.setName( remoteRepository.getName() );
350            remoteRepositoryConfiguration.setDownloadRemoteIndex( remoteRepository.isDownloadRemoteIndex() );
351            remoteRepositoryConfiguration.setRemoteIndexUrl( remoteRepository.getRemoteIndexUrl() );
352            remoteRepositoryConfiguration.setRefreshCronExpression( remoteRepository.getCronExpression() );
353            remoteRepositoryConfiguration.setIndexDir( remoteRepository.getIndexDirectory() );
354            remoteRepositoryConfiguration.setRemoteDownloadNetworkProxyId(
355                remoteRepository.getRemoteDownloadNetworkProxyId() );
356            remoteRepositoryConfiguration.setRemoteDownloadTimeout( remoteRepository.getRemoteDownloadTimeout() );
357            remoteRepositoryConfiguration.setDownloadRemoteIndexOnStartup(
358                remoteRepository.isDownloadRemoteIndexOnStartup() );
359            remoteRepositoryConfiguration.setDescription( remoteRepository.getDescription() );
360            remoteRepositoryConfiguration.setExtraHeaders( remoteRepository.getExtraHeaders() );
361            remoteRepositoryConfiguration.setExtraParameters( remoteRepository.getExtraParameters() );
362            return remoteRepositoryConfiguration;
363        }
364    
365    }