gt:             throw new OXFException(e);
context: /**
   * Copyright (C) 2010 Orbeon, Inc.
   *
   * This program is free software; you can redistribute it and/or modify it under the terms of the
   * GNU Lesser General Public License as published by the Free Software Foundation; either version
   * 2.1 of the License, or (at your option) any later version.
   *
   * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
   * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
   * See the GNU Lesser General Public License for more details.
   *
   * The full text of the license is available at http://www.gnu.org/copyleft/lesser.html
   */
  package org.orbeon.oxf.xml;
  
  import org.orbeon.dom.Document;
  import org.orbeon.dom.io.DocumentSource;
  import org.orbeon.oxf.common.OXFException;
  import org.orbeon.oxf.pipeline.api.TransformerXMLReceiver;
  import org.orbeon.oxf.processor.transformer.TransformerURIResolver;
  import org.orbeon.oxf.resources.URLFactory;
  import org.orbeon.oxf.util.StringBuilderWriter;
  import org.orbeon.oxf.util.XPath;
  import org.orbeon.oxf.xml.dom4j.*;
  import org.orbeon.saxon.Configuration;
  import org.orbeon.saxon.TransformerFactoryImpl;
  import org.orbeon.dom.saxon.DocumentWrapper;
  import org.orbeon.saxon.om.DocumentInfo;
  import org.orbeon.saxon.om.NodeInfo;
  import org.orbeon.saxon.tinytree.TinyBuilder;
  import org.w3c.dom.Node;
  import org.xml.sax.ContentHandler;
  import org.xml.sax.SAXException;
  import scala.Tuple2;
  
  import javax.xml.transform.*;
  import javax.xml.transform.dom.DOMResult;
  import javax.xml.transform.dom.DOMSource;
  import javax.xml.transform.sax.SAXResult;
  import javax.xml.transform.sax.SAXTransformerFactory;
  import javax.xml.transform.sax.TransformerHandler;
  import javax.xml.transform.stream.StreamResult;
  import java.io.ByteArrayInputStream;
  import java.io.IOException;
  import java.io.InputStream;
  import java.io.UnsupportedEncodingException;
  import java.util.HashMap;
  import java.util.Iterator;
  import java.util.Map;
  import java.util.Properties;
  
  /**
   * Utility class for XSLT and other transformations.
   */
  public class TransformerUtils {
  
      public static final String DEFAULT_OUTPUT_ENCODING = "utf-8";
  
      /**
       * Property name to use for choosing the amount of indentation.
       */
      public static final String INDENT_AMOUNT_PROPERTY = "{http://orbeon.org/oxf/}indent-spaces";
  
      private static final String SAXON_INDENT_AMOUNT_PROPERTY = "{http://saxon.sf.net/}indent-spaces";
  
      // Class.forName is expensive, so we cache mappings
      private static Map<String, Class> classNameToHandlerClass = new HashMap<String, Class>();
  
      private static Class getTransformerClass(String clazz) throws ClassNotFoundException {
          Class transformerClass = classNameToHandlerClass.get(clazz);
          if (transformerClass == null) {
              transformerClass = Class.forName(clazz);
              classNameToHandlerClass.put(clazz, transformerClass);
          }
          return transformerClass;
      }
  
      /*
       * NOTE: Factories are not thread-safe. So we should not store them into transformerFactories
       * for now, or we should make sure there is one factory per thread, or that we synchronize.
       */
      public static SAXTransformerFactory getFactory(String className, Map attributes, Configuration configuration) {
          try {
              final SAXTransformerFactory factory; {
                  if (className.equals(TransformerFactoryImpl.class.getName())) {
                      factory = new TransformerFactoryImpl(configuration);
                  } else {
                      factory = (SAXTransformerFactory) getTransformerClass(className).newInstance();
                  }
              }
  
              for (Iterator i = attributes.keySet().iterator(); i.hasNext();) {
                  final String key = (String) i.next();
                  factory.setAttribute(key, attributes.get(key));
              }
  
              return factory;
          } catch (Exception e) {
              throw new OXFException(e);
          }
      }
  
      /*
       * NOTE: Factories are not thread-safe. So we should not store them into transformerFactories
       * for now, or we should make sure there is one factory per thread, or that we synchronize.
       */
      public static SAXTransformerFactory getFactory(String clazz) {
          try {
              return (SAXTransformerFactory) getTransformerClass(clazz).newInstance();
          } catch (Exception e) {
              throw new OXFException(e);
          }
      }
  
      public static Transformer getXMLIdentityTransformer() {
          try {
              Transformer transformer = getIdentityTransformer();
              transformer.setOutputProperty(OutputKeys.ENCODING, DEFAULT_OUTPUT_ENCODING);
              transformer.setOutputProperty(OutputKeys.METHOD, "xml");
              transformer.setOutputProperty(OutputKeys.VERSION, "1.0");
              transformer.setOutputProperty(OutputKeys.INDENT, "no");
              transformer.setOutputProperty(INDENT_AMOUNT_PROPERTY, "0");
              return transformer;
          } catch (TransformerException e) {
              throw new OXFException(e);
          }
      }
  
      /**
       * Apply output properties on a Transformer.
       *
       * @param transformer           transformer to apply properties on
       * @param method                output method
       * @param version               HTML or XML version
       * @param publicDoctype         public doctype
       * @param systemDoctype         system doctype
       * @param encoding              character encoding
       * @param omitXMLDeclaration    whether XML declaration must be omitted
       * @param standalone            whether a standalone declaration must be set and to what value
       * @param indent                whether the HTML or XML must be indented
       * @param indentAmount          amount of indenting for the markup
       */
      public static void applyOutputProperties(Transformer transformer,
                                               String method,
                                               String version,
                                               String publicDoctype,
                                               String systemDoctype,
                                               String encoding,
                                               boolean omitXMLDeclaration,
                                               Boolean standalone,
                                               boolean indent,
                                               int indentAmount) {
          if (method != null && !"".equals(method))
              transformer.setOutputProperty(OutputKeys.METHOD, method);
          if (version != null && !"".equals(version))
              transformer.setOutputProperty(OutputKeys.VERSION, version);
          if (publicDoctype != null && !"".equals(publicDoctype))
              transformer.setOutputProperty(OutputKeys.DOCTYPE_PUBLIC, publicDoctype);
          if (systemDoctype != null && !"".equals(systemDoctype))
              transformer.setOutputProperty(OutputKeys.DOCTYPE_SYSTEM, systemDoctype);
          if (encoding != null && !"".equals(encoding))
              transformer.setOutputProperty(OutputKeys.ENCODING, encoding);
          transformer.setOutputProperty(OutputKeys.INDENT, indent ? "yes" : "no");
          if (indent)
              transformer.setOutputProperty(INDENT_AMOUNT_PROPERTY, String.valueOf(indentAmount));
          transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, omitXMLDeclaration ? "yes" : "no");
          if (standalone != null)
              transformer.setOutputProperty(OutputKeys.STANDALONE, standalone ? "yes" : "no");
      }
  
      /**
       * Return a new identity transformer object.
       *
       * @return  a new identity Transformer object
       * @throws TransformerConfigurationException
       */
      public static Transformer getIdentityTransformer() throws TransformerConfigurationException {
          return getIdentityTransformer(XPath.GlobalConfiguration());
      }
  
      public static Transformer getIdentityTransformer(Configuration configuration) throws TransformerConfigurationException {
          // See https://github.com/orbeon/orbeon-forms/issues/2577
          final Transformer transformer = new IdentityTransformerWithFixup(configuration);
          return new TransformerWrapper(transformer, INDENT_AMOUNT_PROPERTY, SAXON_INDENT_AMOUNT_PROPERTY);
      }
  
      /**
       * Return a new identity TransformerHandler object.
       *
       * @return  a new identity TransformerHandler object
       */
      public static TransformerXMLReceiver getIdentityTransformerHandler() {
          return getIdentityTransformerHandler(XPath.GlobalConfiguration());
      }
  
      public static TransformerXMLReceiver getIdentityTransformerHandler(Configuration configuration) {
          try {
              TransformerHandler transformerHandler = new TransformerFactoryImpl(configuration).newTransformerHandler();
              // Wrap TransformerHandler for properties
              return new TransformerHandlerWrapper(transformerHandler, INDENT_AMOUNT_PROPERTY, SAXON_INDENT_AMOUNT_PROPERTY);
          } catch (TransformerException e) {
              throw new OXFException(e);
          }
      }
  
      public static TransformerHandler getTransformerHandler(Templates templates, String clazz, Map attributes, Configuration configuration) throws TransformerConfigurationException {
          return ((attributes != null) ? getFactory(clazz, attributes, configuration) : getFactory(clazz)).newTransformerHandler(templates);
      }
  
      public static Templates getTemplates(Source source, String clazz, Map attributes, Configuration configuration, ErrorListener errorListener, URIResolver uriResolver)
              throws TransformerConfigurationException {
          final SAXTransformerFactory factory = (attributes != null) ? getFactory(clazz, attributes, configuration) : getFactory(clazz);
          factory.setErrorListener(errorListener);
          factory.setURIResolver(uriResolver);
  
          final Templates templates = factory.newTemplates(source);
          // These should only be used during stylesheet compilation. It is dangerous to keep them around when the
          // Templates object is cached especially the URI Resolver which may reference PipelineContext objects.
  //        factory.setErrorListener(null);// This causes issues with Xalan
          factory.setURIResolver(null);
  
          return templates;
      }
  
      /**
       * Transform a W3C DOM node into a dom4j document
       *
       * @param   node    W3C DOM node
       * @return  dom4j document
       * @throws TransformerException
       */
      public static Document domToDom4jDocument(org.w3c.dom.Node node) throws TransformerException {
          final Transformer identity = getIdentityTransformer();
          final LocationDocumentResult documentResult = new LocationDocumentResult();
          identity.transform(new DOMSource(node), documentResult);
          return documentResult.getDocument();
      }
  
      /**
       * Transform a SAXStore into a dom4j document
       *
       * @param   saxStore input SAXStore
       * @return  dom4j document
       */
      public static Document saxStoreToDom4jDocument(SAXStore saxStore) {
          final TransformerXMLReceiver identity = getIdentityTransformerHandler();
          final LocationDocumentResult documentResult = new LocationDocumentResult();
          identity.setResult(documentResult);
          try {
              saxStore.replay(identity);
          } catch (SAXException e) {
  