001: /*
002: * This file is part of PFIXCORE.
003: *
004: * PFIXCORE is free software; you can redistribute it and/or modify
005: * it under the terms of the GNU Lesser General Public License as published by
006: * the Free Software Foundation; either version 2 of the License, or
007: * (at your option) any later version.
008: *
009: * PFIXCORE is distributed in the hope that it will be useful,
010: * but WITHOUT ANY WARRANTY; without even the implied warranty of
011: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
012: * GNU Lesser General Public License for more details.
013: *
014: * You should have received a copy of the GNU Lesser General Public License
015: * along with PFIXCORE; if not, write to the Free Software
016: * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
017: */
018:
019: package de.schlund.pfixcore.util;
020:
021: import java.io.File;
022: import java.io.FileOutputStream;
023: import java.io.IOException;
024: import java.io.InputStream;
025: import java.util.ArrayList;
026: import java.util.Enumeration;
027: import java.util.List;
028: import java.util.jar.JarEntry;
029: import java.util.jar.JarFile;
030: import java.util.zip.ZipEntry;
031:
032: import javax.xml.transform.TransformerException;
033: import javax.xml.transform.stream.StreamSource;
034:
035: import org.apache.tools.ant.BuildException;
036: import org.apache.tools.ant.taskdefs.MatchingTask;
037: import org.w3c.dom.Document;
038: import org.w3c.dom.Element;
039: import org.w3c.dom.Node;
040: import org.w3c.dom.NodeList;
041:
042: import de.schlund.pfixxml.util.Xml;
043: import de.schlund.pfixxml.util.XsltVersion;
044:
045: public class UnpackModuleTask extends MatchingTask {
046:
047: private File srcdir;
048: private File extractdir;
049:
050: public void setSrcdir(File srcdir) {
051: this .srcdir = srcdir;
052: }
053:
054: public void setExtracttodir(File extractdir) {
055: this .extractdir = extractdir;
056: }
057:
058: @Override
059: public void execute() throws BuildException {
060: if (srcdir == null) {
061: throw new BuildException(
062: "Mandatory attribute srcdir is not set!");
063: }
064: if (extractdir == null) {
065: throw new BuildException(
066: "Mandatory attribute extractdir is not set!");
067: }
068:
069: String[] filenames = getDirectoryScanner(srcdir)
070: .getIncludedFiles();
071: for (String filename : filenames) {
072: File file = new File(srcdir, filename);
073: processJar(file);
074: }
075: }
076:
077: private void processJar(File jarFile) throws BuildException {
078: JarFile jar;
079: try {
080: jar = new JarFile(jarFile);
081: } catch (IOException e) {
082: throw new BuildException("Error while reading JAR file "
083: + jarFile, e);
084: }
085: ZipEntry dde = jar.getEntry("META-INF/pustefix-module.xml");
086: if (dde == null) {
087: return;
088: }
089: InputStream dds;
090: try {
091: dds = jar.getInputStream(dde);
092: } catch (IOException e) {
093: throw new BuildException(
094: "Error while reading deployment descriptor from module "
095: + jarFile, e);
096: }
097: DeploymentDescriptor dd;
098: try {
099: dd = new DeploymentDescriptor(dds);
100: } catch (TransformerException e) {
101: throw new BuildException(
102: "Error while parsing deployment descriptor from module "
103: + jarFile, e);
104: }
105: String moduleName = dd.getModuleName();
106: for (DeploymentDescriptor.ResourceMapping rm : dd
107: .getResourceMappings()) {
108: String srcpath = rm.sourcePath;
109: String targetpath = rm.targetPath;
110: String searchpath = srcpath + "/";
111: Enumeration<JarEntry> entries = jar.entries();
112: while (entries.hasMoreElements()) {
113: JarEntry entry = entries.nextElement();
114: if (entry.getName().startsWith(searchpath)) {
115: String shortpath = entry.getName().substring(
116: searchpath.length());
117: File targetfile;
118: if (targetpath.length() == 0) {
119: targetfile = new File(this .extractdir,
120: moduleName + "/" + shortpath);
121: } else {
122: targetfile = new File(this .extractdir,
123: moduleName + "/" + targetpath + "/"
124: + shortpath);
125: }
126: if (entry.isDirectory()) {
127: targetfile.mkdirs();
128: } else {
129: try {
130: createFileFromStream(jar
131: .getInputStream(entry), targetfile);
132: } catch (IOException e) {
133: throw new BuildException(
134: "Could not unpack file from JAR module to "
135: + targetfile, e);
136: }
137: }
138: }
139: }
140: }
141: }
142:
143: private void createFileFromStream(InputStream inputStream,
144: File targetfile) throws IOException {
145: FileOutputStream fos = new FileOutputStream(targetfile);
146: int bytesread = 0;
147: byte[] buf = new byte[1024];
148: do {
149: bytesread = inputStream.read(buf);
150: if (bytesread > 0) {
151: fos.write(buf, 0, bytesread);
152: }
153: } while (bytesread != -1);
154: fos.close();
155: inputStream.close();
156: }
157:
158: private class DeploymentDescriptor {
159: public class ResourceMapping {
160: public String sourcePath;
161: public String targetPath;
162: }
163:
164: public final static String NS_MODULE = "http://pustefix.sourceforge.net/moduledescriptor200702";
165:
166: private String moduleName = "";
167:
168: private List<ResourceMapping> mappings;
169:
170: public DeploymentDescriptor(InputStream xmlStream)
171: throws TransformerException {
172: Document doc;
173: doc = Xml.parse(XsltVersion.XSLT1, new StreamSource(
174: xmlStream));
175: Element root = doc.getDocumentElement();
176: if (!root.getNamespaceURI().equals(NS_MODULE)
177: || !root.getNodeName().equals("module-descriptor")) {
178: throw new TransformerException(
179: "Descriptor has invalid format");
180: }
181:
182: NodeList temp = root.getElementsByTagNameNS(NS_MODULE,
183: "module-name");
184: if (temp.getLength() != 1) {
185: throw new TransformerException("Module name not set!");
186: }
187: Element nameElement = (Element) temp.item(0);
188: temp = nameElement.getChildNodes();
189: for (int i = 0; i < temp.getLength(); i++) {
190: if (temp.item(i).getNodeType() != Node.TEXT_NODE) {
191: throw new TransformerException(
192: "Found malformed module-name element!");
193: }
194: moduleName += temp.item(i).getNodeValue();
195: }
196: moduleName = moduleName.trim();
197:
198: temp = root.getElementsByTagNameNS(NS_MODULE, "resources");
199: if (temp.getLength() > 1) {
200: throw new TransformerException(
201: "Found more than one resources element!");
202: }
203: if (temp.getLength() == 0) {
204: this .mappings = new ArrayList<ResourceMapping>();
205: return;
206: }
207: temp = ((Element) temp.item(0)).getElementsByTagNameNS(
208: NS_MODULE, "resource-mapping");
209: ArrayList<ResourceMapping> mappings = new ArrayList<ResourceMapping>();
210: for (int i = 0; i < temp.getLength(); i++) {
211: Element el = (Element) temp.item(i);
212: String srcpath = el.getAttribute("srcpath");
213: if (srcpath == null) {
214: throw new TransformerException(
215: "Mandatory attribute srcpath not set on resource-mapping attribute");
216: }
217: if (srcpath.startsWith("/")) {
218: srcpath = srcpath.substring(1);
219: }
220: if (srcpath.endsWith("/")) {
221: srcpath = srcpath
222: .substring(0, srcpath.length() - 1);
223: }
224: String targetpath = el.getAttribute("targetpath");
225: if (targetpath == null) {
226: targetpath = "";
227: }
228: if (targetpath.startsWith("/")) {
229: targetpath = targetpath.substring(1);
230: }
231: if (targetpath.endsWith("/")) {
232: targetpath = targetpath.substring(0, targetpath
233: .length() - 1);
234: }
235: ResourceMapping rm = new ResourceMapping();
236: rm.sourcePath = srcpath;
237: rm.targetPath = targetpath;
238: mappings.add(rm);
239: }
240: this .mappings = mappings;
241: }
242:
243: public List<ResourceMapping> getResourceMappings() {
244: return this .mappings;
245: }
246:
247: public String getModuleName() {
248: return this.moduleName;
249: }
250: }
251: }
|