001: package org.andromda.maven.site;
002:
003: import java.io.ByteArrayOutputStream;
004: import java.io.File;
005: import java.io.FileOutputStream;
006: import java.io.IOException;
007: import java.io.InputStream;
008:
009: import java.net.URL;
010:
011: import javax.xml.parsers.DocumentBuilder;
012: import javax.xml.parsers.DocumentBuilderFactory;
013: import javax.xml.parsers.ParserConfigurationException;
014: import javax.xml.transform.Result;
015: import javax.xml.transform.Source;
016: import javax.xml.transform.TransformerFactory;
017: import javax.xml.transform.dom.DOMSource;
018: import javax.xml.transform.stream.StreamResult;
019: import javax.xml.transform.stream.StreamSource;
020:
021: import org.apache.commons.lang.StringUtils;
022: import org.w3c.dom.Document;
023: import org.xml.sax.EntityResolver;
024: import org.xml.sax.InputSource;
025: import org.xml.sax.SAXException;
026:
027: /**
028: * Used to perform the transformation of XSL documents
029: * within the site plugin.
030: *
031: * @author Chad Brandon
032: */
033: public class XslTransformer {
034: /**
035: * Applies the given XSLT files to the model in the order in which they are found.
036: */
037: public void transform(final String xmlDocument,
038: final String transformation, final String outputLocation) {
039: try {
040: if (StringUtils.isNotBlank(xmlDocument)) {
041: final Source xmlSource = new DOMSource(this
042: .urlToDocument(xmlDocument));
043: final TransformerFactory factory = TransformerFactory
044: .newInstance();
045: final URL xslt = new File(transformation).toURL();
046: if (xslt != null) {
047: final Source xsltSource = new StreamSource(xslt
048: .openStream());
049: final javax.xml.transform.Transformer transformer = factory
050: .newTransformer(xsltSource);
051: final ByteArrayOutputStream output = new ByteArrayOutputStream();
052: final Result result = new StreamResult(output);
053: transformer.transform(xmlSource, result);
054: final byte[] outputResult = output.toByteArray();
055: if (StringUtils.isNotBlank(outputLocation)) {
056: final File fileOutput = new File(outputLocation);
057: final File parent = fileOutput.getParentFile();
058: if (parent != null) {
059: parent.mkdirs();
060: }
061: FileOutputStream outputStream = new FileOutputStream(
062: fileOutput);
063: outputStream.write(outputResult);
064: outputStream.flush();
065: outputStream.close();
066: outputStream = null;
067: }
068: }
069: }
070: } catch (final Exception exception) {
071: throw new RuntimeException(exception);
072: }
073: }
074:
075: /**
076: * Parses the XML retrieved from the String URL and returns a Document object.
077: * @param url the url of the XML to parse.
078: * @return Document newly created Document object.
079: * @throws ParserConfigurationException
080: * @throws IOException
081: * @throws SAXException
082: */
083: private Document urlToDocument(String url) throws Exception {
084: DocumentBuilderFactory factory = DocumentBuilderFactory
085: .newInstance();
086: DocumentBuilder builder = factory.newDocumentBuilder();
087: builder
088: .setEntityResolver(new XslTransformerEntityResolver(url));
089: return builder.parse(new InputSource(url));
090: }
091:
092: /**
093: * The prefix that the systemId should start with when attempting
094: * to resolve it within a jar.
095: */
096: private static final String SYSTEM_ID_FILE = "file:";
097:
098: /**
099: * Provides the resolution of external entities.
100: */
101: private static final class XslTransformerEntityResolver implements
102: EntityResolver {
103: private String xmlDocument;
104:
105: XslTransformerEntityResolver(final String xmlDocument) {
106: this .xmlDocument = xmlDocument;
107: }
108:
109: /**
110: * @see org.xml.sax.EntityResolver#resolveEntity(java.lang.String, java.lang.String)
111: */
112: public InputSource resolveEntity(final String publicId,
113: final String systemId) throws SAXException, IOException {
114: InputSource source = null;
115: String path = systemId;
116: if (path != null && path.startsWith(SYSTEM_ID_FILE)) {
117: final String xmlResource = this .xmlDocument;
118: path = path.replaceFirst(SYSTEM_ID_FILE, "");
119:
120: // - remove any extra starting slashes
121: path = path.replaceAll("\\+", "/")
122: .replaceAll("/+", "/");
123:
124: // - if we still have one starting slash, remove it
125: if (path.startsWith("/")) {
126: path = path.substring(1, path.length());
127: }
128: final String xmlResourceName = xmlResource.replaceAll(
129: ".*(\\+|/)", "");
130: URL uri = null;
131: InputStream inputStream = null;
132: uri = new File(StringUtils.replace(xmlResource,
133: xmlResourceName, path)).toURL();
134: if (uri != null) {
135: inputStream = uri.openStream();
136: }
137: if (inputStream != null) {
138: source = new InputSource(inputStream);
139: source.setPublicId(publicId);
140: source.setSystemId(uri.toString());
141: }
142: }
143: return source;
144: }
145: }
146: }
|