| /* |
| * 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(); |
| } |
| } |
| } |
| } |