001    /**
002     *  Licensed to the Apache Software Foundation (ASF) under one or more
003     *  contributor license agreements.  See the NOTICE file distributed with
004     *  this work for additional information regarding copyright ownership.
005     *  The ASF licenses this file to You under the Apache License, Version 2.0
006     *  (the "License"); you may not use this file except in compliance with
007     *  the License.  You may obtain a copy of the License at
008     *
009     *     http://www.apache.org/licenses/LICENSE-2.0
010     *
011     *  Unless required by applicable law or agreed to in writing, software
012     *  distributed under the License is distributed on an "AS IS" BASIS,
013     *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014     *  See the License for the specific language governing permissions and
015     *  limitations under the License.
016     */
017    package org.apache.geronimo.system.repository;
018    
019    import java.io.File;
020    import java.io.FilenameFilter;
021    import java.net.URI;
022    import java.util.ArrayList;
023    import java.util.List;
024    import java.util.SortedSet;
025    import java.util.TreeSet;
026    
027    import org.apache.geronimo.gbean.GBeanInfo;
028    import org.apache.geronimo.gbean.GBeanInfoBuilder;
029    import org.apache.geronimo.kernel.repository.Artifact;
030    import org.apache.geronimo.kernel.repository.WritableListableRepository;
031    import org.apache.geronimo.system.serverinfo.ServerInfo;
032    
033    /**
034     * @version $Rev: 487175 $ $Date: 2006-12-14 03:10:31 -0800 (Thu, 14 Dec 2006) $
035     */
036    public class Maven2Repository extends AbstractRepository implements WritableListableRepository {
037        public Maven2Repository(URI root, ServerInfo serverInfo) {
038            super(root, serverInfo);
039        }
040    
041        public Maven2Repository(File rootFile) {
042            super(rootFile);
043        }
044    
045        public File getLocation(Artifact artifact) {
046            if(!artifact.isResolved()) {
047                throw new IllegalArgumentException("Artifact "+artifact+" is not fully resolved");
048            }
049            File path = new File(rootFile, artifact.getGroupId().replace('.', File.separatorChar));
050            path = new File(path, artifact.getArtifactId());
051            path = new File(path, artifact.getVersion().toString());
052            path = new File(path, artifact.getArtifactId() + "-" + artifact.getVersion() + "." + artifact.getType());
053    
054            return path;
055        }
056    
057        public SortedSet list() {
058            return listInternal(null, null, null);
059        }
060    
061        public SortedSet list(Artifact query) {
062            if(query.getGroupId() != null) { // todo: see if more logic can be shared with the other case
063                File path = new File(rootFile, query.getGroupId().replace('.', File.separatorChar));
064                path = new File(path, query.getArtifactId());
065                if(!path.canRead() || !path.isDirectory()) {
066                    return new TreeSet();
067                }
068    
069                SortedSet artifacts = new TreeSet();
070    
071                File[] versionDirs = path.listFiles();
072                for (int i = 0; i < versionDirs.length; i++) {
073                    File versionDir = versionDirs[i];
074                    if (versionDir.canRead() && versionDir.isDirectory()) {
075                        String version = versionDir.getName();
076                        if(query.getVersion() != null && !query.getVersion().toString().equals(version)) {
077                            continue;
078                        }
079                        // Assumes that artifactId is set
080                        final String filePrefix = query.getArtifactId() + "-" + version + ".";
081                        File[] list = versionDir.listFiles(new FilenameFilter() {
082                            public boolean accept(File dir, String name) {
083                                return name.startsWith(filePrefix);
084                            }
085                        });
086                        for (int j = 0; j < list.length; j++) {
087                            File file = list[j];
088                            String end = file.getName().substring(filePrefix.length());
089                            if(query.getType() != null && !query.getType().equals(end)) {
090                                continue;
091                            }
092                            if(end.indexOf('.') < 0) {
093                                artifacts.add(new Artifact(query.getGroupId(), query.getArtifactId(), version, end));
094                            }
095                        }
096                    }
097                }
098                return artifacts;
099            } else {
100                return listInternal(query.getArtifactId(), query.getType(), query.getVersion() == null ? null : query.getVersion().toString());
101            }
102        }
103    
104        private SortedSet listInternal(String artifactMatch, String typeMatch, String versionMatch) {
105            SortedSet artifacts = new TreeSet();
106            File[] groupIds = rootFile.listFiles();
107            for (int i = 0; i < groupIds.length; i++) {
108                File groupId = groupIds[i];
109                if (groupId.canRead() && groupId.isDirectory()) {
110                    File[] versionDirs = groupId.listFiles();
111                    for (int j = 0; j < versionDirs.length; j++) {
112                        File versionDir = versionDirs[j];
113                        if (versionDir.canRead() && versionDir.isDirectory()) {
114                            artifacts.addAll(getArtifacts(null, versionDir, artifactMatch, typeMatch, versionMatch));
115                        }
116                    }
117                }
118            }
119            return artifacts;
120        }
121    
122        private List getArtifacts(String groupId, File versionDir, String artifactMatch, String typeMatch, String versionMatch) {
123            // org/apache/xbean/xbean-classpath/2.2-SNAPSHOT/xbean-classpath-2.2-SNAPSHOT.jar
124            List artifacts = new ArrayList();
125            String artifactId = versionDir.getParentFile().getName();
126    
127            File[] files = versionDir.listFiles();
128            for (int i = 0; i < files.length; i++) {
129                File file = files[i];
130                if (file.canRead()) {
131                    if (file.isDirectory()) {
132                        File test = new File(file, "META-INF");
133                        if(test.exists() && test.isDirectory() && test.canRead() && groupId != null) {
134                            String version = versionDir.getName();
135                            String fileHeader = artifactId + "-" + version + ".";
136    
137                            String fileName = file.getName();
138                            if (fileName.startsWith(fileHeader)) {
139                                // type is everything after the file header
140                                String type = fileName.substring(fileHeader.length());
141    
142                                if (!type.endsWith(".sha1") && !type.endsWith(".md5")) {
143                                    if(artifactMatch != null && !artifactMatch.equals(artifactId)) {
144                                        continue;
145                                    }
146                                    if(typeMatch != null && !typeMatch.equals(type)) {
147                                        continue;
148                                    }
149                                    if(versionMatch != null && !versionMatch.equals(version)) {
150                                        continue;
151                                    }
152                                    artifacts.add(new Artifact(groupId,
153                                            artifactId,
154                                            version,
155                                            type));
156                                }
157                            }
158                        } else { // this is just part of the path to the artifact
159                            String nextGroupId;
160                            if (groupId == null) {
161                                nextGroupId = artifactId;
162                            } else {
163                                nextGroupId = groupId + "." + artifactId;
164                            }
165    
166                            artifacts.addAll(getArtifacts(nextGroupId, file, artifactMatch, typeMatch, versionMatch));
167                        }
168                    } else if (groupId != null) {
169                        String version = versionDir.getName();
170                        String fileHeader = artifactId + "-" + version + ".";
171    
172                        String fileName = file.getName();
173                        if (fileName.startsWith(fileHeader)) {
174                            // type is everything after the file header
175                            String type = fileName.substring(fileHeader.length());
176    
177                            if (!type.endsWith(".sha1") && !type.endsWith(".md5")) {
178                                if(artifactMatch != null && !artifactMatch.equals(artifactId)) {
179                                    continue;
180                                }
181                                if(typeMatch != null && !typeMatch.equals(type)) {
182                                    continue;
183                                }
184                                if(versionMatch != null && !versionMatch.equals(version)) {
185                                    continue;
186                                }
187                                artifacts.add(new Artifact(groupId,
188                                        artifactId,
189                                        version,
190                                        type
191                                ));
192                            }
193                        }
194                    }
195                }
196            }
197            return artifacts;
198        }
199    
200    
201        public static final GBeanInfo GBEAN_INFO;
202    
203        static {
204            GBeanInfoBuilder infoFactory = GBeanInfoBuilder.createStatic(Maven2Repository.class, "Repository");
205            infoFactory.addAttribute("root", URI.class, true);
206            infoFactory.addReference("ServerInfo", ServerInfo.class, "GBean");
207            infoFactory.addInterface(Maven2Repository.class);
208            infoFactory.setConstructor(new String[]{"root", "ServerInfo"});
209            GBEAN_INFO = infoFactory.getBeanInfo();
210        }
211    
212        public static GBeanInfo getGBeanInfo() {
213            return GBEAN_INFO;
214        }
215    }