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.kernel.repository; 018 019 import java.io.File; 020 import java.io.FileInputStream; 021 import java.io.IOException; 022 import java.io.InputStream; 023 import java.net.MalformedURLException; 024 import java.net.URL; 025 import java.net.URLClassLoader; 026 import java.util.Enumeration; 027 import java.util.HashMap; 028 import java.util.LinkedHashSet; 029 import java.util.Map; 030 import java.util.zip.ZipEntry; 031 import java.util.zip.ZipException; 032 import java.util.zip.ZipFile; 033 034 import javax.xml.parsers.DocumentBuilderFactory; 035 import javax.xml.parsers.ParserConfigurationException; 036 037 import org.apache.commons.logging.Log; 038 import org.apache.commons.logging.LogFactory; 039 import org.apache.geronimo.kernel.util.XmlUtil; 040 import org.w3c.dom.Document; 041 import org.w3c.dom.Element; 042 import org.w3c.dom.Node; 043 import org.w3c.dom.NodeList; 044 import org.xml.sax.InputSource; 045 import org.xml.sax.SAXException; 046 047 /** 048 * @version $Rev: 506425 $ $Date: 2007-02-12 22:49:46 +1100 (Mon, 12 Feb 2007) $ 049 */ 050 public abstract class AbstractRepository implements WriteableRepository { 051 protected static final Log log = LogFactory.getLog(AbstractRepository.class); 052 private final static ArtifactTypeHandler DEFAULT_TYPE_HANDLER = new CopyArtifactTypeHandler(); 053 protected final File rootFile; 054 private final Map typeHandlers = new HashMap(); 055 056 public AbstractRepository(File rootFile) { 057 if (rootFile == null) throw new NullPointerException("root is null"); 058 059 if (!rootFile.exists() || !rootFile.isDirectory() || !rootFile.canRead()) { 060 throw new IllegalStateException("Maven2Repository must have a root that's a valid readable directory (not " + rootFile.getAbsolutePath() + ")"); 061 } 062 063 this.rootFile = rootFile; 064 log.debug("Repository root is " + rootFile.getAbsolutePath()); 065 066 typeHandlers.put("car", new UnpackArtifactTypeHandler()); 067 } 068 069 public boolean contains(Artifact artifact) { 070 // Note: getLocation(artifact) does an artifact.isResolved() check - no need to do it here. 071 File location = getLocation(artifact); 072 return location.canRead() && (location.isFile() || new File(location, "META-INF").isDirectory()); 073 } 074 075 private static final String NAMESPACE = "http://geronimo.apache.org/xml/ns/deployment-1.2"; 076 public LinkedHashSet getDependencies(Artifact artifact) { 077 if(!artifact.isResolved()) { 078 throw new IllegalArgumentException("Artifact "+artifact+" is not fully resolved"); 079 } 080 LinkedHashSet dependencies = new LinkedHashSet(); 081 URL url; 082 try { 083 File location = getLocation(artifact); 084 url = location.toURL(); 085 } catch (MalformedURLException e) { 086 throw (IllegalStateException)new IllegalStateException("Unable to get URL for dependency " + artifact).initCause(e); 087 } 088 ClassLoader depCL = new URLClassLoader(new URL[]{url}, new ClassLoader() { 089 @Override 090 public URL getResource(String name) { 091 return null; 092 } 093 }); 094 InputStream is = depCL.getResourceAsStream("META-INF/geronimo-dependency.xml"); 095 try { 096 if (is != null) { 097 InputSource in = new InputSource(is); 098 DocumentBuilderFactory dfactory = XmlUtil.newDocumentBuilderFactory(); 099 dfactory.setNamespaceAware(true); 100 try { 101 Document doc = dfactory.newDocumentBuilder().parse(in); 102 Element root = doc.getDocumentElement(); 103 NodeList configs = root.getElementsByTagNameNS(NAMESPACE, "dependency"); 104 for (int i = 0; i < configs.getLength(); i++) { 105 Element dependencyElement = (Element) configs.item(i); 106 String groupId = getString(dependencyElement, "groupId"); 107 String artifactId = getString(dependencyElement, "artifactId"); 108 String version = getString(dependencyElement, "version"); 109 String type = getString(dependencyElement, "type"); 110 if (type == null) { 111 type = "jar"; 112 } 113 dependencies.add(new Artifact(groupId, artifactId, version, type)); 114 } 115 } catch (IOException e) { 116 throw (IllegalStateException)new IllegalStateException("Unable to parse geronimo-dependency.xml file in " + url).initCause(e); 117 } catch (ParserConfigurationException e) { 118 throw (IllegalStateException)new IllegalStateException("Unable to parse geronimo-dependency.xml file in " + url).initCause(e); 119 } catch (SAXException e) { 120 throw (IllegalStateException)new IllegalStateException("Unable to parse geronimo-dependency.xml file in " + url).initCause(e); 121 } 122 } 123 } finally { 124 if (is != null) { 125 try { 126 is.close(); 127 } catch (IOException ignore) { 128 // ignore 129 } 130 } 131 } 132 return dependencies; 133 } 134 135 private String getString(Element dependencyElement, String childName) { 136 NodeList children = dependencyElement.getElementsByTagNameNS(NAMESPACE, childName); 137 if (children == null || children.getLength() == 0) { 138 return null; 139 } 140 String value = ""; 141 NodeList text = children.item(0).getChildNodes(); 142 for (int t = 0; t < text.getLength(); t++) { 143 Node n = text.item(t); 144 if (n.getNodeType() == Node.TEXT_NODE) { 145 value += n.getNodeValue(); 146 } 147 } 148 return value.trim(); 149 } 150 151 public void setTypeHandler(String type, ArtifactTypeHandler handler) { 152 typeHandlers.put(type, handler); 153 } 154 155 public void copyToRepository(File source, Artifact destination, FileWriteMonitor monitor) throws IOException { 156 if(!destination.isResolved()) { 157 throw new IllegalArgumentException("Artifact "+destination+" is not fully resolved"); 158 } 159 if (!source.exists() || !source.canRead() || source.isDirectory()) { 160 throw new IllegalArgumentException("Cannot read source file at " + source.getAbsolutePath()); 161 } 162 int size = 0; 163 try { 164 ZipFile zip = new ZipFile(source); 165 for (Enumeration entries=zip.entries(); entries.hasMoreElements();) { 166 ZipEntry entry = (ZipEntry)entries.nextElement(); 167 size += entry.getSize(); 168 } 169 } catch (ZipException ze) { 170 size = (int)source.length(); 171 } 172 FileInputStream is = new FileInputStream(source); 173 try { 174 copyToRepository(is, size, destination, monitor); 175 } finally { 176 try { 177 is.close(); 178 } catch (IOException ignored) { 179 // ignored 180 } 181 } 182 } 183 184 public void copyToRepository(InputStream source, int size, Artifact destination, FileWriteMonitor monitor) throws IOException { 185 if(!destination.isResolved()) { 186 throw new IllegalArgumentException("Artifact "+destination+" is not fully resolved"); 187 } 188 // is this a writable repository 189 if (!rootFile.canWrite()) { 190 throw new IllegalStateException("This repository is not writable: " + rootFile.getAbsolutePath() + ")"); 191 } 192 193 // where are we going to install the file 194 File location = getLocation(destination); 195 196 // assure that there isn't already a file installed at the specified location 197 if (location.exists()) { 198 throw new IllegalArgumentException("Destination " + location.getAbsolutePath() + " already exists!"); 199 } 200 201 ArtifactTypeHandler typeHandler = (ArtifactTypeHandler) typeHandlers.get(destination.getType()); 202 if (typeHandler == null) typeHandler = DEFAULT_TYPE_HANDLER; 203 typeHandler.install(source, size, destination, monitor, location); 204 205 if (destination.getType().equalsIgnoreCase("car")) { 206 log.debug("Installed module configuration; id=" + destination + "; location=" + location); 207 } 208 } 209 }