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 }