1 package org.apache.maven.archiva.web.action;
4 * Licensed to the Apache Software Foundation (ASF) under one
5 * or more contributor license agreements. See the NOTICE file
6 * distributed with this work for additional information
7 * regarding copyright ownership. The ASF licenses this file
8 * to you under the Apache License, Version 2.0 (the
9 * "License"); you may not use this file except in compliance
10 * with the License. You may obtain a copy of the License at
12 * http://www.apache.org/licenses/LICENSE-2.0
14 * Unless required by applicable law or agreed to in writing,
15 * software distributed under the License is distributed on an
16 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17 * KIND, either express or implied. See the License for the
18 * specific language governing permissions and limitations
22 import org.apache.commons.lang.StringUtils;
23 import org.apache.maven.archiva.configuration.ArchivaConfiguration;
24 import org.apache.maven.archiva.configuration.Configuration;
25 import org.apache.maven.archiva.configuration.ConfiguredRepositoryFactory;
26 import org.apache.maven.archiva.indexer.RepositoryArtifactIndex;
27 import org.apache.maven.archiva.indexer.RepositoryArtifactIndexFactory;
28 import org.apache.maven.archiva.indexer.RepositoryIndexException;
29 import org.apache.maven.archiva.indexer.RepositoryIndexSearchException;
30 import org.codehaus.plexus.xwork.action.PlexusActionSupport;
33 import java.io.IOException;
34 import java.util.ArrayList;
35 import java.util.Collections;
36 import java.util.Iterator;
37 import java.util.List;
39 import java.util.StringTokenizer;
40 import java.util.TreeMap;
43 * Browse the repository.
45 * @todo cache should be a proper cache class that is a singleton requirement rather than static variables
46 * @plexus.component role="com.opensymphony.xwork.Action" role-hint="browseAction"
48 public class BrowseAction
49 extends PlexusActionSupport
54 private RepositoryArtifactIndexFactory factory;
59 private ConfiguredRepositoryFactory repositoryFactory;
64 private ArchivaConfiguration archivaConfiguration;
68 private String groupId;
70 private static final String GROUP_SEPARATOR = ".";
72 private List artifactIds;
74 private String artifactId;
76 private List versions;
78 private static GroupTreeNode rootNode;
80 private static long groupCacheTime;
82 public String browse()
83 throws RepositoryIndexException, IOException
85 RepositoryArtifactIndex index = getIndex();
87 if ( !index.exists() )
89 addActionError( "The repository is not yet indexed. Please wait, and then try again." );
93 GroupTreeNode rootNode = buildGroupTree( index );
95 this.groups = collateGroups( rootNode );
100 public String browseGroup()
101 throws RepositoryIndexException, IOException, RepositoryIndexSearchException
103 RepositoryArtifactIndex index = getIndex();
105 if ( !index.exists() )
107 addActionError( "The repository is not yet indexed. Please wait, and then try again." );
111 GroupTreeNode rootNode = buildGroupTree( index );
113 if ( StringUtils.isEmpty( groupId ) )
116 addActionError( "You must specify a group ID to browse" );
120 StringTokenizer tok = new StringTokenizer( groupId, GROUP_SEPARATOR );
121 while ( tok.hasMoreTokens() )
123 String part = tok.nextToken();
125 if ( !rootNode.getChildren().containsKey( part ) )
129 "Can't find part: " + part + " for groupId " + groupId + " in children " + rootNode.getChildren() );
130 addActionError( "The group specified was not found" );
135 rootNode = (GroupTreeNode) rootNode.getChildren().get( part );
139 this.groups = collateGroups( rootNode );
141 this.artifactIds = index.getArtifactIds( groupId );
142 Collections.sort( this.artifactIds );
147 public String browseArtifact()
148 throws RepositoryIndexException, IOException, RepositoryIndexSearchException
150 RepositoryArtifactIndex index = getIndex();
152 if ( StringUtils.isEmpty( groupId ) )
155 addActionError( "You must specify a group ID to browse" );
159 if ( StringUtils.isEmpty( artifactId ) )
162 addActionError( "You must specify a artifact ID to browse" );
166 this.versions = index.getVersions( groupId, artifactId );
167 Collections.sort( this.versions );
169 if ( versions.isEmpty() )
172 addActionError( "Could not find any artifacts with the given group and artifact ID" );
179 private GroupTreeNode buildGroupTree( RepositoryArtifactIndex index )
180 throws IOException, RepositoryIndexException
182 // TODO: give action message if indexing is in progress
184 long lastUpdate = index.getLastUpdatedTime();
186 if ( rootNode == null || lastUpdate > groupCacheTime )
188 List groups = index.getAllGroupIds();
190 getLogger().info( "Loaded " + groups.size() + " groups from index" );
192 rootNode = new GroupTreeNode();
194 // build a tree structure
195 for ( Iterator i = groups.iterator(); i.hasNext(); )
197 String groupId = (String) i.next();
199 StringTokenizer tok = new StringTokenizer( groupId, GROUP_SEPARATOR );
201 GroupTreeNode node = rootNode;
203 while ( tok.hasMoreTokens() )
205 String part = tok.nextToken();
207 if ( !node.getChildren().containsKey( part ) )
209 GroupTreeNode newNode = new GroupTreeNode( part, node );
210 node.addChild( newNode );
215 node = (GroupTreeNode) node.getChildren().get( part );
219 groupCacheTime = lastUpdate;
223 getLogger().debug( "Loaded groups from cache" );
229 private List collateGroups( GroupTreeNode rootNode )
231 List groups = new ArrayList();
232 for ( Iterator i = rootNode.getChildren().values().iterator(); i.hasNext(); )
234 GroupTreeNode node = (GroupTreeNode) i.next();
236 while ( node.getChildren().size() == 1 )
238 node = (GroupTreeNode) node.getChildren().values().iterator().next();
241 groups.add( node.getFullName() );
246 private RepositoryArtifactIndex getIndex()
247 throws RepositoryIndexException
249 Configuration configuration = archivaConfiguration.getConfiguration();
250 File indexPath = new File( configuration.getIndexPath() );
252 return factory.createStandardIndex( indexPath );
255 public List getGroups()
260 public List getArtifactIds()
265 public String getGroupId()
270 public void setGroupId( String groupId )
272 this.groupId = groupId;
275 public String getArtifactId()
280 public void setArtifactId( String artifactId )
282 this.artifactId = artifactId;
285 public List getVersions()
290 private static class GroupTreeNode
292 private final String name;
294 private final String fullName;
296 private final Map children = new TreeMap();
304 GroupTreeNode( String name, GroupTreeNode parent )
307 this.fullName = parent.fullName != null ? parent.fullName + GROUP_SEPARATOR + name : name;
310 public String getName()
315 public String getFullName()
320 public Map getChildren()
325 public void addChild( GroupTreeNode newNode )
327 children.put( newNode.name, newNode );