This project has retired. For details please refer to its Attic page.
Source code
001package org.apache.archiva.admin.repository.group;
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
021import org.apache.archiva.admin.model.AuditInformation;
022import org.apache.archiva.admin.model.RepositoryAdminException;
023import org.apache.archiva.admin.model.beans.ManagedRepository;
024import org.apache.archiva.admin.model.beans.RepositoryGroup;
025import org.apache.archiva.admin.model.group.RepositoryGroupAdmin;
026import org.apache.archiva.admin.model.managed.ManagedRepositoryAdmin;
027import org.apache.archiva.admin.repository.AbstractRepositoryAdmin;
028import org.apache.archiva.configuration.Configuration;
029import org.apache.archiva.configuration.RepositoryGroupConfiguration;
030import org.apache.archiva.metadata.model.facets.AuditEvent;
031import org.apache.archiva.scheduler.MergedRemoteIndexesScheduler;
032import org.apache.commons.lang.StringUtils;
033import org.slf4j.Logger;
034import org.slf4j.LoggerFactory;
035import org.springframework.stereotype.Service;
036
037import javax.annotation.PostConstruct;
038import javax.inject.Inject;
039import java.io.File;
040import java.util.ArrayList;
041import java.util.Arrays;
042import java.util.Collections;
043import java.util.HashMap;
044import java.util.List;
045import java.util.Map;
046import java.util.regex.Matcher;
047import java.util.regex.Pattern;
048
049/**
050 * @author Olivier Lamy
051 */
052@Service("repositoryGroupAdmin#default")
053public class DefaultRepositoryGroupAdmin
054    extends AbstractRepositoryAdmin
055    implements RepositoryGroupAdmin
056{
057
058    private Logger log = LoggerFactory.getLogger( getClass() );
059
060    private static final Pattern REPO_GROUP_ID_PATTERN = Pattern.compile( "[A-Za-z0-9\\._\\-]+" );
061
062    @Inject
063    private ManagedRepositoryAdmin managedRepositoryAdmin;
064
065    @Inject
066    private MergedRemoteIndexesScheduler mergedRemoteIndexesScheduler;
067
068    private File groupsDirectory;
069
070    @PostConstruct
071    public void initialize()
072    {
073        String appServerBase = getRegistry().getString( "appserver.base" );
074        groupsDirectory = new File( appServerBase + File.separatorChar + "groups" );
075        if ( !groupsDirectory.exists() )
076        {
077            groupsDirectory.mkdirs();
078        }
079
080        try
081        {
082            for ( RepositoryGroup repositoryGroup : getRepositoriesGroups() )
083            {
084                mergedRemoteIndexesScheduler.schedule( repositoryGroup,
085                                                       getMergedIndexDirectory( repositoryGroup.getId() ) );
086                // create the directory for each group if not exists
087                File groupPath = new File( groupsDirectory, repositoryGroup.getId() );
088                if ( !groupPath.exists() )
089                {
090                    groupPath.mkdirs();
091                }
092            }
093        }
094        catch ( RepositoryAdminException e )
095        {
096            log.warn( "fail to getRepositoriesGroups {}", e.getMessage(), e );
097        }
098
099    }
100
101
102    @Override
103    public File getMergedIndexDirectory( String repositoryGroupId )
104    {
105        return new File( groupsDirectory, repositoryGroupId );
106    }
107
108    @Override
109    public List<RepositoryGroup> getRepositoriesGroups()
110        throws RepositoryAdminException
111    {
112        List<RepositoryGroup> repositoriesGroups =
113            new ArrayList<>( getArchivaConfiguration().getConfiguration().getRepositoryGroups().size() );
114
115        for ( RepositoryGroupConfiguration repositoryGroupConfiguration : getArchivaConfiguration().getConfiguration().getRepositoryGroups() )
116        {
117            repositoriesGroups.add( new RepositoryGroup( repositoryGroupConfiguration.getId(), new ArrayList<String>(
118                repositoryGroupConfiguration.getRepositories() ) ).mergedIndexPath(
119                repositoryGroupConfiguration.getMergedIndexPath() ).mergedIndexTtl(
120                repositoryGroupConfiguration.getMergedIndexTtl() ).cronExpression(
121                repositoryGroupConfiguration.getCronExpression() ) );
122        }
123
124        return repositoriesGroups;
125    }
126
127    @Override
128    public RepositoryGroup getRepositoryGroup( String repositoryGroupId )
129        throws RepositoryAdminException
130    {
131        List<RepositoryGroup> repositoriesGroups = getRepositoriesGroups();
132        for ( RepositoryGroup repositoryGroup : repositoriesGroups )
133        {
134            if ( StringUtils.equals( repositoryGroupId, repositoryGroup.getId() ) )
135            {
136                return repositoryGroup;
137            }
138        }
139        return null;
140    }
141
142    @Override
143    public Boolean addRepositoryGroup( RepositoryGroup repositoryGroup, AuditInformation auditInformation )
144        throws RepositoryAdminException
145    {
146        validateRepositoryGroup( repositoryGroup, false );
147        validateManagedRepositoriesExists( repositoryGroup.getRepositories() );
148
149        RepositoryGroupConfiguration repositoryGroupConfiguration = new RepositoryGroupConfiguration();
150        repositoryGroupConfiguration.setId( repositoryGroup.getId() );
151        repositoryGroupConfiguration.setRepositories( repositoryGroup.getRepositories() );
152        repositoryGroupConfiguration.setMergedIndexPath( repositoryGroup.getMergedIndexPath() );
153        repositoryGroupConfiguration.setMergedIndexTtl( repositoryGroup.getMergedIndexTtl() );
154        repositoryGroupConfiguration.setCronExpression( repositoryGroup.getCronExpression() );
155        Configuration configuration = getArchivaConfiguration().getConfiguration();
156        configuration.addRepositoryGroup( repositoryGroupConfiguration );
157        saveConfiguration( configuration );
158        triggerAuditEvent( repositoryGroup.getId(), null, AuditEvent.ADD_REPO_GROUP, auditInformation );
159        mergedRemoteIndexesScheduler.schedule( repositoryGroup, getMergedIndexDirectory( repositoryGroup.getId() ) );
160        return Boolean.TRUE;
161    }
162
163    @Override
164    public Boolean deleteRepositoryGroup( String repositoryGroupId, AuditInformation auditInformation )
165        throws RepositoryAdminException
166    {
167        Configuration configuration = getArchivaConfiguration().getConfiguration();
168        RepositoryGroupConfiguration repositoryGroupConfiguration =
169            configuration.getRepositoryGroupsAsMap().get( repositoryGroupId );
170        mergedRemoteIndexesScheduler.unschedule(
171            new RepositoryGroup( repositoryGroupId, Collections.<String>emptyList() ) );
172        if ( repositoryGroupConfiguration == null )
173        {
174            throw new RepositoryAdminException(
175                "repositoryGroup with id " + repositoryGroupId + " doesn't not exists so cannot remove" );
176        }
177        configuration.removeRepositoryGroup( repositoryGroupConfiguration );
178        triggerAuditEvent( repositoryGroupId, null, AuditEvent.DELETE_REPO_GROUP, auditInformation );
179
180        return Boolean.TRUE;
181    }
182
183    @Override
184    public Boolean updateRepositoryGroup( RepositoryGroup repositoryGroup, AuditInformation auditInformation )
185        throws RepositoryAdminException
186    {
187        return updateRepositoryGroup( repositoryGroup, auditInformation, true );
188    }
189
190    private Boolean updateRepositoryGroup( RepositoryGroup repositoryGroup, AuditInformation auditInformation,
191                                           boolean triggerAuditEvent )
192        throws RepositoryAdminException
193    {
194        validateRepositoryGroup( repositoryGroup, true );
195        validateManagedRepositoriesExists( repositoryGroup.getRepositories() );
196        Configuration configuration = getArchivaConfiguration().getConfiguration();
197
198        RepositoryGroupConfiguration repositoryGroupConfiguration =
199            configuration.getRepositoryGroupsAsMap().get( repositoryGroup.getId() );
200
201        configuration.removeRepositoryGroup( repositoryGroupConfiguration );
202
203        repositoryGroupConfiguration.setRepositories( repositoryGroup.getRepositories() );
204        repositoryGroupConfiguration.setMergedIndexPath( repositoryGroup.getMergedIndexPath() );
205        repositoryGroupConfiguration.setMergedIndexTtl( repositoryGroup.getMergedIndexTtl() );
206        repositoryGroupConfiguration.setCronExpression( repositoryGroup.getCronExpression() );
207        configuration.addRepositoryGroup( repositoryGroupConfiguration );
208
209        saveConfiguration( configuration );
210        if ( triggerAuditEvent )
211        {
212            triggerAuditEvent( repositoryGroup.getId(), null, AuditEvent.MODIFY_REPO_GROUP, auditInformation );
213        }
214        mergedRemoteIndexesScheduler.unschedule( repositoryGroup );
215        mergedRemoteIndexesScheduler.schedule( repositoryGroup, getMergedIndexDirectory( repositoryGroup.getId() ) );
216        return Boolean.TRUE;
217    }
218
219
220    @Override
221    public Boolean addRepositoryToGroup( String repositoryGroupId, String repositoryId,
222                                         AuditInformation auditInformation )
223        throws RepositoryAdminException
224    {
225        RepositoryGroup repositoryGroup = getRepositoryGroup( repositoryGroupId );
226        if ( repositoryGroup == null )
227        {
228            throw new RepositoryAdminException(
229                "repositoryGroup with id " + repositoryGroupId + " doesn't not exists so cannot add repository to it" );
230        }
231
232        if ( repositoryGroup.getRepositories().contains( repositoryId ) )
233        {
234            throw new RepositoryAdminException(
235                "repositoryGroup with id " + repositoryGroupId + " already contain repository with id" + repositoryId );
236        }
237        validateManagedRepositoriesExists( Arrays.asList( repositoryId ) );
238
239        repositoryGroup.addRepository( repositoryId );
240        updateRepositoryGroup( repositoryGroup, auditInformation, false );
241        triggerAuditEvent( repositoryGroup.getId(), null, AuditEvent.ADD_REPO_TO_GROUP, auditInformation );
242        return Boolean.TRUE;
243    }
244
245    @Override
246    public Boolean deleteRepositoryFromGroup( String repositoryGroupId, String repositoryId,
247                                              AuditInformation auditInformation )
248        throws RepositoryAdminException
249    {
250        RepositoryGroup repositoryGroup = getRepositoryGroup( repositoryGroupId );
251        if ( repositoryGroup == null )
252        {
253            throw new RepositoryAdminException( "repositoryGroup with id " + repositoryGroupId
254                                                    + " doesn't not exists so cannot remove repository from it" );
255        }
256
257        if ( !repositoryGroup.getRepositories().contains( repositoryId ) )
258        {
259            throw new RepositoryAdminException(
260                "repositoryGroup with id " + repositoryGroupId + " doesn't not contains repository with id"
261                    + repositoryId
262            );
263        }
264
265        repositoryGroup.removeRepository( repositoryId );
266        updateRepositoryGroup( repositoryGroup, auditInformation, false );
267        triggerAuditEvent( repositoryGroup.getId(), null, AuditEvent.DELETE_REPO_FROM_GROUP, auditInformation );
268        return Boolean.TRUE;
269    }
270
271    @Override
272    public Map<String, RepositoryGroup> getRepositoryGroupsAsMap()
273        throws RepositoryAdminException
274    {
275        List<RepositoryGroup> repositoriesGroups = getRepositoriesGroups();
276        Map<String, RepositoryGroup> map = new HashMap<>( repositoriesGroups.size() );
277        for ( RepositoryGroup repositoryGroup : repositoriesGroups )
278        {
279            map.put( repositoryGroup.getId(), repositoryGroup );
280        }
281        return map;
282    }
283
284    @Override
285    public Map<String, List<String>> getGroupToRepositoryMap()
286        throws RepositoryAdminException
287    {
288
289        Map<String, List<String>> map = new HashMap<>();
290
291        for ( ManagedRepository repo : getManagedRepositoryAdmin().getManagedRepositories() )
292        {
293            for ( RepositoryGroup group : getRepositoriesGroups() )
294            {
295                if ( !group.getRepositories().contains( repo.getId() ) )
296                {
297                    String groupId = group.getId();
298                    List<String> repos = map.get( groupId );
299                    if ( repos == null )
300                    {
301                        repos = new ArrayList<>();
302                        map.put( groupId, repos );
303                    }
304                    repos.add( repo.getId() );
305                }
306            }
307        }
308        return map;
309    }
310
311    @Override
312    public Map<String, List<String>> getRepositoryToGroupMap()
313        throws RepositoryAdminException
314    {
315        Map<String, List<String>> map = new HashMap<>();
316
317        for ( RepositoryGroup group : getRepositoriesGroups() )
318        {
319            for ( String repositoryId : group.getRepositories() )
320            {
321                List<String> groups = map.get( repositoryId );
322                if ( groups == null )
323                {
324                    groups = new ArrayList<>();
325                    map.put( repositoryId, groups );
326                }
327                groups.add( group.getId() );
328            }
329        }
330        return map;
331    }
332
333    public Boolean validateRepositoryGroup( RepositoryGroup repositoryGroup, boolean updateMode )
334        throws RepositoryAdminException
335    {
336        String repoGroupId = repositoryGroup.getId();
337        if ( StringUtils.isBlank( repoGroupId ) )
338        {
339            throw new RepositoryAdminException( "repositoryGroup id cannot be empty" );
340        }
341
342        if ( repoGroupId.length() > 100 )
343        {
344            throw new RepositoryAdminException(
345                "Identifier [" + repoGroupId + "] is over the maximum limit of 100 characters" );
346
347        }
348
349        Matcher matcher = REPO_GROUP_ID_PATTERN.matcher( repoGroupId );
350        if ( !matcher.matches() )
351        {
352            throw new RepositoryAdminException(
353                "Invalid character(s) found in identifier. Only the following characters are allowed: alphanumeric, '.', '-' and '_'" );
354        }
355
356        if ( repositoryGroup.getMergedIndexTtl() <= 0 )
357        {
358            throw new RepositoryAdminException( "Merged Index TTL must be greater than 0." );
359        }
360
361        Configuration configuration = getArchivaConfiguration().getConfiguration();
362
363        if ( configuration.getRepositoryGroupsAsMap().containsKey( repoGroupId ) )
364        {
365            if ( !updateMode )
366            {
367                throw new RepositoryAdminException( "Unable to add new repository group with id [" + repoGroupId
368                                                        + "], that id already exists as a repository group." );
369            }
370        }
371        else if ( configuration.getManagedRepositoriesAsMap().containsKey( repoGroupId ) )
372        {
373            throw new RepositoryAdminException( "Unable to add new repository group with id [" + repoGroupId
374                                                    + "], that id already exists as a managed repository." );
375        }
376        else if ( configuration.getRemoteRepositoriesAsMap().containsKey( repoGroupId ) )
377        {
378            throw new RepositoryAdminException( "Unable to add new repository group with id [" + repoGroupId
379                                                    + "], that id already exists as a remote repository." );
380        }
381
382        return Boolean.TRUE;
383    }
384
385    private void validateManagedRepositoriesExists( List<String> managedRepositoriesIds )
386        throws RepositoryAdminException
387    {
388        for ( String id : managedRepositoriesIds )
389        {
390            if ( getManagedRepositoryAdmin().getManagedRepository( id ) == null )
391            {
392                throw new RepositoryAdminException(
393                    "managedRepository with id " + id + " not exists so cannot be used in a repositoryGroup" );
394            }
395        }
396    }
397
398    public ManagedRepositoryAdmin getManagedRepositoryAdmin()
399    {
400        return managedRepositoryAdmin;
401    }
402
403    public void setManagedRepositoryAdmin( ManagedRepositoryAdmin managedRepositoryAdmin )
404    {
405        this.managedRepositoryAdmin = managedRepositoryAdmin;
406    }
407}