]> source.dussan.org Git - archiva.git/blob
b2af23c833cc99d5b9fae70da4cbc612b939af05
[archiva.git] /
1 package org.apache.maven.archiva.web.action;
2
3 /*
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
11  *
12  *   http://www.apache.org/licenses/LICENSE-2.0
13  *
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
19  * under the License.
20  */
21
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;
31
32 import java.io.File;
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;
38 import java.util.Map;
39 import java.util.StringTokenizer;
40 import java.util.TreeMap;
41
42 /**
43  * Browse the repository.
44  *
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"
47  */
48 public class BrowseAction
49     extends PlexusActionSupport
50 {
51     /**
52      * @plexus.requirement
53      */
54     private RepositoryArtifactIndexFactory factory;
55
56     /**
57      * @plexus.requirement
58      */
59     private ConfiguredRepositoryFactory repositoryFactory;
60
61     /**
62      * @plexus.requirement
63      */
64     private ArchivaConfiguration archivaConfiguration;
65
66     private List groups;
67
68     private String groupId;
69
70     private static final String GROUP_SEPARATOR = ".";
71
72     private List artifactIds;
73
74     private String artifactId;
75
76     private List versions;
77
78     private static GroupTreeNode rootNode;
79
80     private static long groupCacheTime;
81
82     public String browse()
83         throws RepositoryIndexException, IOException
84     {
85         RepositoryArtifactIndex index = getIndex();
86
87         if ( !index.exists() )
88         {
89             addActionError( "The repository is not yet indexed. Please wait, and then try again." );
90             return ERROR;
91         }
92
93         GroupTreeNode rootNode = buildGroupTree( index );
94
95         this.groups = collateGroups( rootNode );
96
97         return SUCCESS;
98     }
99
100     public String browseGroup()
101         throws RepositoryIndexException, IOException, RepositoryIndexSearchException
102     {
103         RepositoryArtifactIndex index = getIndex();
104
105         if ( !index.exists() )
106         {
107             addActionError( "The repository is not yet indexed. Please wait, and then try again." );
108             return ERROR;
109         }
110
111         GroupTreeNode rootNode = buildGroupTree( index );
112
113         if ( StringUtils.isEmpty( groupId ) )
114         {
115             // TODO: i18n
116             addActionError( "You must specify a group ID to browse" );
117             return ERROR;
118         }
119
120         StringTokenizer tok = new StringTokenizer( groupId, GROUP_SEPARATOR );
121         while ( tok.hasMoreTokens() )
122         {
123             String part = tok.nextToken();
124
125             if ( !rootNode.getChildren().containsKey( part ) )
126             {
127                 // TODO: i18n
128                 getLogger().debug(
129                     "Can't find part: " + part + " for groupId " + groupId + " in children " + rootNode.getChildren() );
130                 addActionError( "The group specified was not found" );
131                 return ERROR;
132             }
133             else
134             {
135                 rootNode = (GroupTreeNode) rootNode.getChildren().get( part );
136             }
137         }
138
139         this.groups = collateGroups( rootNode );
140
141         this.artifactIds = index.getArtifactIds( groupId );
142         Collections.sort( this.artifactIds );
143
144         return SUCCESS;
145     }
146
147     public String browseArtifact()
148         throws RepositoryIndexException, IOException, RepositoryIndexSearchException
149     {
150         RepositoryArtifactIndex index = getIndex();
151
152         if ( StringUtils.isEmpty( groupId ) )
153         {
154             // TODO: i18n
155             addActionError( "You must specify a group ID to browse" );
156             return ERROR;
157         }
158
159         if ( StringUtils.isEmpty( artifactId ) )
160         {
161             // TODO: i18n
162             addActionError( "You must specify a artifact ID to browse" );
163             return ERROR;
164         }
165
166         this.versions = index.getVersions( groupId, artifactId );
167         Collections.sort( this.versions );
168
169         if ( versions.isEmpty() )
170         {
171             // TODO: i18n
172             addActionError( "Could not find any artifacts with the given group and artifact ID" );
173             return ERROR;
174         }
175
176         return SUCCESS;
177     }
178
179     private GroupTreeNode buildGroupTree( RepositoryArtifactIndex index )
180         throws IOException, RepositoryIndexException
181     {
182         // TODO: give action message if indexing is in progress
183
184         long lastUpdate = index.getLastUpdatedTime();
185
186         if ( rootNode == null || lastUpdate > groupCacheTime )
187         {
188             List groups = index.getAllGroupIds();
189
190             getLogger().info( "Loaded " + groups.size() + " groups from index" );
191
192             rootNode = new GroupTreeNode();
193
194             // build a tree structure
195             for ( Iterator i = groups.iterator(); i.hasNext(); )
196             {
197                 String groupId = (String) i.next();
198
199                 StringTokenizer tok = new StringTokenizer( groupId, GROUP_SEPARATOR );
200
201                 GroupTreeNode node = rootNode;
202
203                 while ( tok.hasMoreTokens() )
204                 {
205                     String part = tok.nextToken();
206
207                     if ( !node.getChildren().containsKey( part ) )
208                     {
209                         GroupTreeNode newNode = new GroupTreeNode( part, node );
210                         node.addChild( newNode );
211                         node = newNode;
212                     }
213                     else
214                     {
215                         node = (GroupTreeNode) node.getChildren().get( part );
216                     }
217                 }
218             }
219             groupCacheTime = lastUpdate;
220         }
221         else
222         {
223             getLogger().debug( "Loaded groups from cache" );
224         }
225
226         return rootNode;
227     }
228
229     private List collateGroups( GroupTreeNode rootNode )
230     {
231         List groups = new ArrayList();
232         for ( Iterator i = rootNode.getChildren().values().iterator(); i.hasNext(); )
233         {
234             GroupTreeNode node = (GroupTreeNode) i.next();
235
236             while ( node.getChildren().size() == 1 )
237             {
238                 node = (GroupTreeNode) node.getChildren().values().iterator().next();
239             }
240
241             groups.add( node.getFullName() );
242         }
243         return groups;
244     }
245
246     private RepositoryArtifactIndex getIndex()
247         throws RepositoryIndexException
248     {
249         Configuration configuration = archivaConfiguration.getConfiguration();
250         File indexPath = new File( configuration.getIndexPath() );
251
252         return factory.createStandardIndex( indexPath );
253     }
254
255     public List getGroups()
256     {
257         return groups;
258     }
259
260     public List getArtifactIds()
261     {
262         return artifactIds;
263     }
264
265     public String getGroupId()
266     {
267         return groupId;
268     }
269
270     public void setGroupId( String groupId )
271     {
272         this.groupId = groupId;
273     }
274
275     public String getArtifactId()
276     {
277         return artifactId;
278     }
279
280     public void setArtifactId( String artifactId )
281     {
282         this.artifactId = artifactId;
283     }
284
285     public List getVersions()
286     {
287         return versions;
288     }
289
290     private static class GroupTreeNode
291     {
292         private final String name;
293
294         private final String fullName;
295
296         private final Map children = new TreeMap();
297
298         GroupTreeNode()
299         {
300             name = null;
301             fullName = null;
302         }
303
304         GroupTreeNode( String name, GroupTreeNode parent )
305         {
306             this.name = name;
307             this.fullName = parent.fullName != null ? parent.fullName + GROUP_SEPARATOR + name : name;
308         }
309
310         public String getName()
311         {
312             return name;
313         }
314
315         public String getFullName()
316         {
317             return fullName;
318         }
319
320         public Map getChildren()
321         {
322             return children;
323         }
324
325         public void addChild( GroupTreeNode newNode )
326         {
327             children.put( newNode.name, newNode );
328         }
329     }
330 }