blob: b2e919c341ac9aef170e365f48bcbe375a83785d [file] [log] [blame]
/*
* Copyright 2005 Sascha Weinreuter
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.intellij.plugins.xslt.run.rt;
import org.xml.sax.SAXParseException;
import javax.xml.transform.*;
import javax.xml.transform.stream.StreamResult;
import javax.xml.transform.stream.StreamSource;
import java.io.*;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketTimeoutException;
import java.util.Enumeration;
import java.util.HashSet;
import java.util.Set;
/** @noinspection CallToPrintStackTrace,UseOfSystemOutOrSystemErr,IOResourceOpenedButNotSafelyClosed,SocketOpenedButNotSafelyClosed,UseOfArchaicSystemPropertyAccessors */
public class XSLTRunner implements XSLTMain {
private XSLTRunner() {
}
public static void main(String[] args) throws Throwable {
final XSLTMain main = loadMain();
TransformerFactory transformerFactory;
try {
transformerFactory = main.createTransformerFactory();
} catch (AbstractMethodError e) {
// old debugger
transformerFactory = createTransformerFactoryStatic();
} catch (ClassNotFoundException e) {
transformerFactory = createTransformerFactoryStatic();
}
final String uriResolverClass = System.getProperty("xslt.uri-resolver");
if (uriResolverClass != null) {
transformerFactory.setURIResolver((URIResolver)Class.forName(uriResolverClass).newInstance());
}
final boolean[] trouble = new boolean[]{ false };
final MyErrorListener listener = new MyErrorListener(trouble);
final boolean isSmartErrorHandling = System.getProperty("xslt.smart-error-handling", "false").equals("true");
if (isSmartErrorHandling) {
transformerFactory.setErrorListener(listener);
}
final File xslt = new File(System.getProperty("xslt.file"));
try {
final Transformer transformer = transformerFactory.newTransformer(new StreamSource(xslt));
if (transformer != null && !trouble[0]) {
final Enumeration props = System.getProperties().keys();
while (props.hasMoreElements()) {
String s = (String)props.nextElement();
if (s.startsWith("xslt.param.")) {
final String name = s.substring("xslt.param.".length());
final String value = System.getProperty(s);
transformer.setParameter(name, value);
}
}
final File input = new File(System.getProperty("xslt.input"));
final String out = System.getProperty("xslt.output");
OutputStream fileStream;
if (out != null) {
final File output = new File(out);
fileStream = new BufferedOutputStream(new FileOutputStream(output));
} else {
fileStream = null;
}
final StreamResult result;
final Integer _port = Integer.getInteger("xslt.listen-port", -1);
final int port = _port.intValue();
if (port != -1) {
// block until IDEA connects
try {
final ServerSocket serverSocket = new ServerSocket(port, 1, InetAddress.getByName("127.0.0.1"));
serverSocket.setSoTimeout(Integer.getInteger("xslt.listen-timeout", 5000).intValue());
final Socket socket = serverSocket.accept();
final BufferedOutputStream socketStream = new BufferedOutputStream(socket.getOutputStream(), 16);
if (out != null) {
result = new StreamResult(new ForkedOutputStream(new OutputStream[]{ socketStream, fileStream }));
} else {
result = new StreamResult(new OutputStreamWriter(socketStream, "UTF-8"));
}
} catch (SocketTimeoutException ignored) {
System.err.println("Plugin did not connect to runner within timeout. Run aborted.");
return;
}
} else {
final String encoding = System.getProperty("file.encoding");
if (encoding != null) {
// ensure proper encoding in xml declaration
transformer.setOutputProperty("encoding", encoding);
if (out != null) {
result = new StreamResult(new OutputStreamWriter(new ForkedOutputStream(new OutputStream[]{System.out, fileStream}), encoding));
} else {
result = new StreamResult(new OutputStreamWriter(System.out, encoding));
}
} else {
if (out != null) {
result = new StreamResult(new ForkedOutputStream(new OutputStream[]{ System.out, fileStream }));
} else {
result = new StreamResult(System.out);
}
}
}
Runtime.getRuntime().addShutdownHook(new Thread() {
public void run() {
try {
final Writer out = result.getWriter();
if (out != null) {
out.flush();
out.close();
} else if (result.getOutputStream() != null) {
result.getOutputStream().flush();
result.getOutputStream().close();
}
} catch (IOException e) {
// no chance to fix...
}
}
});
main.start(transformer, new StreamSource(input), result);
}
} catch (TransformerException e) {
if (isSmartErrorHandling) {
listener.error(e);
} else {
throw e;
}
} catch (Throwable t) {
t.printStackTrace();
System.exit(1);
}
}
public TransformerFactory createTransformerFactory() throws Exception {
return createTransformerFactoryStatic();
}
public static TransformerFactory createTransformerFactoryStatic() throws InstantiationException, IllegalAccessException, ClassNotFoundException {
final String factoryClass = System.getProperty("xslt.transformer-factory");
if (factoryClass != null) {
return (TransformerFactory)Class.forName(factoryClass).newInstance();
} else {
return TransformerFactory.newInstance();
}
}
public void start(Transformer transformer, Source source, Result result) throws TransformerException {
transformer.transform(source, result);
}
private static XSLTMain loadMain() {
final String mainClass = System.getProperty("xslt.main");
if (mainClass == null) {
return new XSLTRunner();
}
try {
return (XSLTMain)Class.forName(mainClass).newInstance();
} catch (ClassNotFoundException e) {
throw new AssertionError(e);
} catch (IllegalAccessException e) {
throw new AssertionError(e);
} catch (InstantiationException e) {
throw new AssertionError(e);
}
}
/** @noinspection UseOfSystemOutOrSystemErr*/
private static class MyErrorListener implements ErrorListener {
private final Set myMessages = new HashSet();
private final boolean[] myTrouble;
public MyErrorListener(boolean[] trouble) {
myTrouble = trouble;
}
public void warning(TransformerException exception) {
handleException(exception, "WARNING");
}
public void error(TransformerException exception) {
handleException(exception, "ERROR");
myTrouble[0] = true;
}
public void fatalError(TransformerException exception) {
handleException(exception, "FATAL");
myTrouble[0] = true;
}
private void handleException(TransformerException exception, String type) {
final String message = getMessage(exception);
if (!myMessages.contains(message)) {
System.err.println("[" + type + "]: " + message);
myMessages.add(message);
}
}
private static String getMessage(TransformerException exception) {
final SourceLocator[] locators = new SourceLocator[]{ exception.getLocator() };
final String[] messages = new String[1];
findLocator(exception, locators, messages);
final SourceLocator locator = locators[0];
if (locator != null) {
final String systemId = locator.getSystemId();
if (systemId != null) {
String s = systemId.replaceAll(" ", "%20") + ": ";
final int lineNumber = locator.getLineNumber();
if (lineNumber != -1) {
s += "line " + lineNumber + ": ";
final int columnNumber = locator.getColumnNumber();
if (columnNumber != -1) {
s += "column " + columnNumber + ": ";
}
}
return s + (messages[0] != null ? messages[0] : exception.getMessage());
}
}
return messages[0] != null ? messages[0] : exception.getMessage();
}
private static void findLocator(Throwable exception, SourceLocator[] locators, String[] messages) {
if (exception instanceof TransformerException) {
final TransformerException t = (TransformerException)exception;
if (t.getLocator() != null) {
messages[0] = t.getMessage();
locators[0] = t.getLocator();
} else if (exception.getCause() != null) {
findLocator(exception.getCause(), locators, messages);
}
} else if (exception instanceof SAXParseException) {
final SAXParseException sae = (SAXParseException)exception;
messages[0] = sae.getMessage();
locators[0] = new SourceLocator() {
public int getColumnNumber() {
return sae.getColumnNumber();
}
public int getLineNumber() {
return sae.getLineNumber();
}
public String getPublicId() {
//noinspection ConstantConditions
return null;
}
public String getSystemId() {
return sae.getSystemId();
}
};
} else if (exception.getCause() != null) {
findLocator(exception.getCause(), locators, messages);
}
try {
final Throwable t = (Throwable)exception.getClass().getMethod("getException", new Class[0]).invoke(exception, new Object[0]);
if (t != exception) {
findLocator(t, locators, messages);
}
} catch (Exception e) {
//
}
}
}
static class ForkedOutputStream extends OutputStream {
OutputStream[] outs;
ForkedOutputStream(OutputStream[] out) {
outs = out;
}
public void write(byte[] b, int off, int len) throws IOException {
for (int i = 0, outsLength = outs.length; i < outsLength; i++) {
outs[i].write(b, off, len);
}
}
public void write(int b) throws IOException {
for (int i = 0, outsLength = outs.length; i < outsLength; i++) {
outs[i].write(b);
}
}
public void flush() throws IOException {
for (int i = 0, outsLength = outs.length; i < outsLength; i++) {
outs[i].flush();
}
}
public void close() throws IOException {
for (int i = 0, outsLength = outs.length; i < outsLength; i++) {
outs[i].close();
}
}
}
}