001 /*
002 * Licensed to the Apache Software Foundation (ASF) under one
003 * or more contributor license agreements. See the NOTICE file
004 * distributed with this work for additional information
005 * regarding copyright ownership. The ASF licenses this file
006 * to you under the Apache License, Version 2.0 (the
007 * "License"); you may not use this file except in compliance
008 * with the License. You may obtain a copy of the License at
009 *
010 * http://www.apache.org/licenses/LICENSE-2.0
011 *
012 * Unless required by applicable law or agreed to in writing,
013 * software distributed under the License is distributed on an
014 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
015 * KIND, either express or implied. See the License for the
016 * specific language governing permissions and limitations
017 * under the License.
018 */
019
020
021 package org.apache.geronimo.system.plugin;
022
023 import java.io.File;
024 import java.io.FileInputStream;
025 import java.io.FileOutputStream;
026 import java.io.IOException;
027 import java.io.InputStream;
028 import java.io.OutputStream;
029 import java.util.Collection;
030 import java.util.HashMap;
031 import java.util.Map;
032 import java.util.SortedSet;
033 import java.util.LinkedHashSet;
034 import java.util.jar.JarFile;
035 import java.util.zip.ZipEntry;
036
037 import javax.security.auth.login.FailedLoginException;
038
039 import org.apache.geronimo.kernel.config.ConfigurationStore;
040 import org.apache.geronimo.kernel.config.NoSuchConfigException;
041 import org.apache.geronimo.kernel.repository.Artifact;
042 import org.apache.geronimo.kernel.repository.FileWriteMonitor;
043 import org.apache.geronimo.kernel.repository.ListableRepository;
044 import org.apache.geronimo.kernel.repository.Repository;
045 import org.apache.geronimo.kernel.repository.WritableListableRepository;
046 import org.apache.geronimo.kernel.repository.WriteableRepository;
047 import org.apache.geronimo.kernel.repository.ArtifactResolver;
048 import org.apache.geronimo.kernel.repository.MissingDependencyException;
049 import org.apache.geronimo.system.configuration.RepositoryConfigurationStore;
050 import org.apache.geronimo.system.plugin.model.PluginListType;
051 import org.apache.geronimo.system.plugin.model.PluginType;
052
053 /**
054 * @version $Rev: 706640 $ $Date: 2008-10-21 14:44:05 +0000 (Tue, 21 Oct 2008) $
055 */
056 public class GeronimoSourceRepository implements SourceRepository {
057
058 private final Collection<? extends Repository> repos;
059 private final ArtifactResolver artifactResolver;
060
061 public GeronimoSourceRepository(Collection<? extends Repository> repos, ArtifactResolver artifactResolver) {
062 this.repos = repos;
063 this.artifactResolver = artifactResolver;
064 }
065
066 public PluginListType getPluginList() {
067 Map<PluginType, PluginType> pluginMap = new HashMap<PluginType, PluginType>();
068 for (Repository listableRepository : repos) {
069 if (listableRepository instanceof ListableRepository) {
070 SortedSet<Artifact> artifacts = ((ListableRepository) listableRepository).list();
071 for (Artifact artifact : artifacts) {
072 File location = listableRepository.getLocation(artifact);
073 PluginType data = extractPluginMetadata(location);
074 if (data != null) {
075 PluginType key = PluginInstallerGBean.toKey(data);
076 PluginType existing = pluginMap.get(key);
077 if (existing == null) {
078 pluginMap.put(key, data);
079 } else {
080 existing.getPluginArtifact().addAll(data.getPluginArtifact());
081 }
082 }
083 }
084 }
085 }
086 PluginListType pluginList = new PluginListType();
087 pluginList.getPlugin().addAll(pluginMap.values());
088 return pluginList;
089 }
090
091 public OpenResult open(Artifact artifact, FileWriteMonitor monitor) throws IOException, FailedLoginException {
092 try {
093 artifact = artifactResolver.resolveInClassLoader(artifact);
094 } catch (MissingDependencyException e) {
095 return null;
096 }
097 for (Repository repo: repos) {
098 if (repo.contains(artifact)) {
099 File location = repo.getLocation(artifact);
100 if (location.isFile()) {
101 return new LocalOpenResult(artifact, location);
102 }
103 if (location.isDirectory()) {
104 return new ZipOpenResult(artifact, repo);
105 }
106 }
107 }
108 return null;
109 }
110
111 PluginType extractPluginMetadata(Artifact artifact) {
112 for (Repository repo: repos) {
113 if (repo.contains(artifact)) {
114 File location = repo.getLocation(artifact);
115 return extractPluginMetadata(location);
116 }
117 }
118 return null;
119 }
120
121 static PluginType extractPluginMetadata(File dir) {
122 try {
123 if (dir.isDirectory()) {
124 File meta = new File(dir, "META-INF");
125 if (!meta.isDirectory() || !meta.canRead()) {
126 return null;
127 }
128 File xml = new File(meta, "geronimo-plugin.xml");
129 if (!xml.isFile() || !xml.canRead() || xml.length() == 0) {
130 return null;
131 }
132 InputStream in = new FileInputStream(xml);
133 try {
134 return PluginXmlUtil.loadPluginMetadata(in);
135 } finally {
136 in.close();
137 }
138 } else {
139 if (!dir.isFile() || !dir.canRead()) {
140 throw new IllegalStateException("Cannot read configuration " + dir.getAbsolutePath());
141 }
142 JarFile jar = new JarFile(dir);
143 try {
144 ZipEntry entry = jar.getEntry("META-INF/geronimo-plugin.xml");
145 if (entry == null) {
146 return null;
147 }
148 InputStream in = jar.getInputStream(entry);
149 try {
150 return PluginXmlUtil.loadPluginMetadata(in);
151 } finally {
152 in.close();
153 }
154 } finally {
155 jar.close();
156 }
157 }
158 } catch (Exception e) {
159 //ignore
160 }
161 return null;
162 }
163
164 private static class RepoWrapper implements WritableListableRepository {
165
166 private final Repository repo;
167
168 private RepoWrapper(Repository repo) {
169 this.repo = repo;
170 }
171
172 public void copyToRepository(File source, Artifact destination, FileWriteMonitor monitor) throws IOException {
173 }
174
175 public void copyToRepository(InputStream source, int size, Artifact destination, FileWriteMonitor monitor) throws IOException {
176 }
177
178 public boolean contains(Artifact artifact) {
179 return repo.contains(artifact);
180 }
181
182 public File getLocation(Artifact artifact) {
183 return repo.getLocation(artifact);
184 }
185
186 public LinkedHashSet<Artifact> getDependencies(Artifact artifact) {
187 return null;
188 }
189
190 public SortedSet<Artifact> list() {
191 return null;
192 }
193
194 public SortedSet<Artifact> list(Artifact query) {
195 return null;
196 }
197 }
198
199 private class ZipOpenResult implements OpenResult {
200 private final Artifact artifact;
201 private final Repository repo;
202 File location;
203
204 private ZipOpenResult(Artifact artifact, Repository repo) {
205 this.artifact = artifact;
206 this.repo = repo;
207 }
208
209 public Artifact getArtifact() {
210 return artifact;
211 }
212
213 public File getFile() throws IOException {
214 location = File.createTempFile("geronimo-plugin-download-", ".tmp");
215 OutputStream output = new FileOutputStream(location);
216 WritableListableRepository writableRepo = new RepoWrapper(repo);
217 ConfigurationStore store = new RepositoryConfigurationStore(writableRepo);
218 try {
219 store.exportConfiguration(artifact, output);
220 } catch (NoSuchConfigException e) {
221 throw (IOException)new IOException("Could not locate artefact " + artifact).initCause(e);
222 }
223
224 return location;
225 }
226
227 public void install(WriteableRepository repo, FileWriteMonitor monitor) throws IOException {
228 File file = getFile();
229 repo.copyToRepository(file, artifact, monitor);
230 if (!file.delete()) {
231 // log.warn("Unable to delete temporary download file " + tempFile.getAbsolutePath());
232 file.deleteOnExit();
233 }
234 }
235
236 public void close() {
237 }
238 }
239 }