mirror of git://gcc.gnu.org/git/gcc.git
				
				
				
			
		
			
				
	
	
		
			573 lines
		
	
	
		
			18 KiB
		
	
	
	
		
			Java
		
	
	
		
			Executable File
		
	
	
			
		
		
	
	
			573 lines
		
	
	
		
			18 KiB
		
	
	
	
		
			Java
		
	
	
		
			Executable File
		
	
	
/* GnomeTransformer.java -
 | 
						|
   Copyright (C) 2004 Free Software Foundation, Inc.
 | 
						|
 | 
						|
This file is part of GNU Classpath.
 | 
						|
 | 
						|
GNU Classpath is free software; you can redistribute it and/or modify
 | 
						|
it under the terms of the GNU General Public License as published by
 | 
						|
the Free Software Foundation; either version 2, or (at your option)
 | 
						|
any later version.
 | 
						|
 | 
						|
GNU Classpath 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
 | 
						|
General Public License for more details.
 | 
						|
 | 
						|
You should have received a copy of the GNU General Public License
 | 
						|
along with GNU Classpath; see the file COPYING.  If not, write to the
 | 
						|
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
 | 
						|
02110-1301 USA.
 | 
						|
 | 
						|
Linking this library statically or dynamically with other modules is
 | 
						|
making a combined work based on this library.  Thus, the terms and
 | 
						|
conditions of the GNU General Public License cover the whole
 | 
						|
combination.
 | 
						|
 | 
						|
As a special exception, the copyright holders of this library give you
 | 
						|
permission to link this library with independent modules to produce an
 | 
						|
executable, regardless of the license terms of these independent
 | 
						|
modules, and to copy and distribute the resulting executable under
 | 
						|
terms of your choice, provided that you also meet, for each linked
 | 
						|
independent module, the terms and conditions of the license of that
 | 
						|
module.  An independent module is a module which is not derived from
 | 
						|
or based on this library.  If you modify this library, you may extend
 | 
						|
this exception to your version of the library, but you are not
 | 
						|
obligated to do so.  If you do not wish to do so, delete this
 | 
						|
exception statement from your version. */
 | 
						|
 | 
						|
package gnu.xml.libxmlj.transform;
 | 
						|
 | 
						|
import java.io.InputStream;
 | 
						|
import java.io.IOException;
 | 
						|
import java.io.OutputStream;
 | 
						|
 | 
						|
import java.net.URL;
 | 
						|
 | 
						|
import java.util.HashMap;
 | 
						|
import java.util.Iterator;
 | 
						|
import java.util.Map;
 | 
						|
import java.util.Properties;
 | 
						|
 | 
						|
import javax.xml.transform.ErrorListener;
 | 
						|
import javax.xml.transform.Source;
 | 
						|
import javax.xml.transform.SourceLocator;
 | 
						|
import javax.xml.transform.Result;
 | 
						|
import javax.xml.transform.Templates;
 | 
						|
import javax.xml.transform.Transformer;
 | 
						|
import javax.xml.transform.TransformerConfigurationException;
 | 
						|
import javax.xml.transform.TransformerException;
 | 
						|
import javax.xml.transform.URIResolver;
 | 
						|
 | 
						|
import javax.xml.transform.dom.DOMSource;
 | 
						|
import javax.xml.transform.dom.DOMResult;
 | 
						|
import javax.xml.transform.sax.SAXResult;
 | 
						|
import javax.xml.transform.stream.StreamSource;
 | 
						|
import javax.xml.transform.stream.StreamResult;
 | 
						|
 | 
						|
import org.w3c.dom.Node;
 | 
						|
 | 
						|
import org.xml.sax.EntityResolver;
 | 
						|
import org.xml.sax.ErrorHandler;
 | 
						|
 | 
						|
import gnu.xml.libxmlj.dom.GnomeDocument;
 | 
						|
import gnu.xml.libxmlj.sax.GnomeXMLReader;
 | 
						|
import gnu.xml.libxmlj.util.NamedInputStream;
 | 
						|
import gnu.xml.libxmlj.util.StandaloneLocator;
 | 
						|
import gnu.xml.libxmlj.util.XMLJ;
 | 
						|
 | 
						|
/**
 | 
						|
 * An implementation of {@link javax.xml.transform.Transformer} which
 | 
						|
 * performs XSLT transformation using <code>libxslt</code>.
 | 
						|
 *
 | 
						|
 * @author Julian Scheid
 | 
						|
 * @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
 | 
						|
 */
 | 
						|
public class GnomeTransformer
 | 
						|
  extends Transformer
 | 
						|
  implements Templates
 | 
						|
{
 | 
						|
 | 
						|
  /**
 | 
						|
   * The parameters added by the user via {@link setParameter()}.
 | 
						|
   */
 | 
						|
  private Map parameters;
 | 
						|
 | 
						|
  /**
 | 
						|
   * The output properties set by the user.
 | 
						|
   */
 | 
						|
  private Properties outputProperties;
 | 
						|
 | 
						|
  /**
 | 
						|
   * The URI resolver to use during transformation.
 | 
						|
   */
 | 
						|
  private URIResolver resolver;
 | 
						|
 | 
						|
  /**
 | 
						|
   * The error listener for transformation errors.
 | 
						|
   */
 | 
						|
  private ErrorListener errorListener;
 | 
						|
 | 
						|
  /**
 | 
						|
   * Handle to the source stylesheet.
 | 
						|
   * This is a native pointer of type xsltStylesheetPtr.
 | 
						|
   */
 | 
						|
  private Object stylesheet;
 | 
						|
 | 
						|
  /**
 | 
						|
   * Constructor.
 | 
						|
   * @param source the XSLT stylesheet document source
 | 
						|
   * @param resolver the resolver to use during transformation
 | 
						|
   * @param errorListener the error listener for transformation errors
 | 
						|
   */
 | 
						|
  GnomeTransformer (Source source,
 | 
						|
                    URIResolver resolver,
 | 
						|
                    ErrorListener errorListener)
 | 
						|
    throws TransformerConfigurationException
 | 
						|
  {
 | 
						|
    this.resolver = resolver;
 | 
						|
    this.errorListener = errorListener;
 | 
						|
    parameters = new HashMap ();
 | 
						|
    outputProperties = new Properties ();
 | 
						|
 | 
						|
    if (source == null)
 | 
						|
      {
 | 
						|
        stylesheet = newStylesheet ();
 | 
						|
      }
 | 
						|
    else if (source instanceof StreamSource)
 | 
						|
      {
 | 
						|
        try
 | 
						|
          {
 | 
						|
            StreamSource ss = (StreamSource) source;
 | 
						|
            NamedInputStream in = XMLJ.getInputStream (ss);
 | 
						|
            String systemId = ss.getSystemId ();
 | 
						|
            String publicId = ss.getPublicId ();
 | 
						|
            String base = XMLJ.getBaseURI (systemId);
 | 
						|
            byte[] detectBuffer = in.getDetectBuffer ();
 | 
						|
            if (detectBuffer == null)
 | 
						|
              {
 | 
						|
                String msg = "No document element";
 | 
						|
                throw new TransformerConfigurationException (msg);
 | 
						|
              }
 | 
						|
            stylesheet = newStylesheetFromStream (in, detectBuffer, publicId,
 | 
						|
                                                  systemId, base,
 | 
						|
                                                  (resolver != null),
 | 
						|
                                                  (errorListener != null));
 | 
						|
          }
 | 
						|
        catch (IOException e)
 | 
						|
          {
 | 
						|
            throw new TransformerConfigurationException (e);
 | 
						|
          }
 | 
						|
      }
 | 
						|
    else if (source instanceof DOMSource)
 | 
						|
      {
 | 
						|
        DOMSource ds = (DOMSource) source;
 | 
						|
        Node node = ds.getNode ();
 | 
						|
        if (!(node instanceof GnomeDocument))
 | 
						|
          {
 | 
						|
            String msg = "Node is not a GnomeDocument";
 | 
						|
            throw new TransformerConfigurationException (msg);
 | 
						|
          }
 | 
						|
        GnomeDocument doc = (GnomeDocument) node;
 | 
						|
        stylesheet = newStylesheetFromDoc (doc);
 | 
						|
      }
 | 
						|
    else
 | 
						|
      {
 | 
						|
        String msg = "Source type not supported (" + source + ")";
 | 
						|
        throw new TransformerConfigurationException (msg);
 | 
						|
      }
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * Copy constructor.
 | 
						|
   */
 | 
						|
  private GnomeTransformer (Object stylesheet,
 | 
						|
                            URIResolver resolver,
 | 
						|
                            ErrorListener errorListener,
 | 
						|
                            Map parameters,
 | 
						|
                            Properties outputProperties)
 | 
						|
  {
 | 
						|
    this.stylesheet = stylesheet;
 | 
						|
    this.resolver = resolver;
 | 
						|
    this.errorListener = errorListener;
 | 
						|
    this.parameters = parameters;
 | 
						|
    this.outputProperties = outputProperties;
 | 
						|
  }
 | 
						|
 | 
						|
  private native Object newStylesheet ()
 | 
						|
    throws TransformerConfigurationException;
 | 
						|
 | 
						|
  private native Object newStylesheetFromStream (InputStream in,
 | 
						|
                                                 byte[] detectBuffer,
 | 
						|
                                                 String publicId,
 | 
						|
                                                 String systemId,
 | 
						|
                                                 String base,
 | 
						|
                                                 boolean entityResolver,
 | 
						|
                                                 boolean errorHandler)
 | 
						|
    throws TransformerConfigurationException;
 | 
						|
 | 
						|
  private native Object newStylesheetFromDoc (GnomeDocument doc)
 | 
						|
    throws TransformerConfigurationException;
 | 
						|
 | 
						|
  //--- Implementation of javax.xml.transform.Transformer follows.
 | 
						|
 | 
						|
  // Set, get and clear the parameters to use on transformation
 | 
						|
 | 
						|
  public synchronized void setParameter (String parameter, Object value)
 | 
						|
  {
 | 
						|
    parameters.put (parameter, value);
 | 
						|
  }
 | 
						|
 | 
						|
  public synchronized Object getParameter (String name)
 | 
						|
  {
 | 
						|
    return parameters.get (name);
 | 
						|
  }
 | 
						|
 | 
						|
  public synchronized void clearParameters ()
 | 
						|
  {
 | 
						|
    parameters.clear ();
 | 
						|
  }
 | 
						|
 | 
						|
  // Set and get the ErrorListener to use on transformation
 | 
						|
 | 
						|
  public void setErrorListener (ErrorListener listener)
 | 
						|
  {
 | 
						|
    this.errorListener = listener;
 | 
						|
  }
 | 
						|
 | 
						|
  public ErrorListener getErrorListener ()
 | 
						|
  {
 | 
						|
    return errorListener;
 | 
						|
  }
 | 
						|
 | 
						|
  // Set and get the URIResolver to use on transformation
 | 
						|
 | 
						|
  public void setURIResolver (URIResolver resolver)
 | 
						|
  {
 | 
						|
    this.resolver = resolver;
 | 
						|
  }
 | 
						|
 | 
						|
  public URIResolver getURIResolver ()
 | 
						|
  {
 | 
						|
    return resolver;
 | 
						|
  }
 | 
						|
 | 
						|
  // Set the output properties to use on transformation; get default
 | 
						|
  // output properties and output properties specified in the
 | 
						|
  // stylesheet or by the user.
 | 
						|
 | 
						|
  public void setOutputProperties (Properties outputProperties)
 | 
						|
  {
 | 
						|
    // Note: defensive copying
 | 
						|
    this.outputProperties = new Properties (outputProperties);
 | 
						|
  }
 | 
						|
 | 
						|
  public void setOutputProperty (String name, String value)
 | 
						|
  {
 | 
						|
    outputProperties.setProperty (name, value);
 | 
						|
  }
 | 
						|
 | 
						|
  public Properties getOutputProperties ()
 | 
						|
  {
 | 
						|
    // Note: defensive copying
 | 
						|
    return new Properties (this.outputProperties);
 | 
						|
  }
 | 
						|
 | 
						|
  public String getOutputProperty (String name)
 | 
						|
  {
 | 
						|
    return outputProperties.getProperty (name);
 | 
						|
  }
 | 
						|
 | 
						|
  // -- Templates --
 | 
						|
 | 
						|
  public Transformer newTransformer ()
 | 
						|
  {
 | 
						|
    return new GnomeTransformer (stylesheet, resolver, errorListener,
 | 
						|
                                 new HashMap (parameters),
 | 
						|
                                 new Properties (outputProperties));
 | 
						|
  }
 | 
						|
 | 
						|
  // -- transform --
 | 
						|
 | 
						|
  /**
 | 
						|
   * Transforms the given source and writes the result to the
 | 
						|
   * given target.
 | 
						|
   */
 | 
						|
  public void transform (Source source, Result result)
 | 
						|
    throws TransformerException
 | 
						|
  {
 | 
						|
    if (source instanceof StreamSource)
 | 
						|
      {
 | 
						|
        try
 | 
						|
          {
 | 
						|
            StreamSource ss = (StreamSource) source;
 | 
						|
            NamedInputStream in = XMLJ.getInputStream (ss);
 | 
						|
            String publicId = ss.getPublicId ();
 | 
						|
            String systemId = ss.getSystemId ();
 | 
						|
            String base = XMLJ.getBaseURI (systemId);
 | 
						|
            byte[] detectBuffer = in.getDetectBuffer ();
 | 
						|
            if (detectBuffer == null)
 | 
						|
              {
 | 
						|
                throw new TransformerException ("No document element");
 | 
						|
              }
 | 
						|
            if (result instanceof StreamResult)
 | 
						|
              {
 | 
						|
                OutputStream out = XMLJ.getOutputStream ((StreamResult) result);
 | 
						|
                transformStreamToStream (in, detectBuffer, publicId, systemId,
 | 
						|
                                         base, (resolver != null),
 | 
						|
                                         (errorListener != null), out);
 | 
						|
              }
 | 
						|
            else if (result instanceof DOMResult)
 | 
						|
              {
 | 
						|
                DOMResult dr = (DOMResult) result;
 | 
						|
                GnomeDocument ret =
 | 
						|
                  transformStreamToDoc (in, detectBuffer, publicId, systemId,
 | 
						|
                                        base, (resolver != null),
 | 
						|
                                        (errorListener != null));
 | 
						|
                dr.setNode (ret);
 | 
						|
                dr.setSystemId (null);
 | 
						|
              }
 | 
						|
            else if (result instanceof SAXResult)
 | 
						|
              {
 | 
						|
                SAXResult sr = (SAXResult) result;
 | 
						|
                transformStreamToSAX (in, detectBuffer, publicId, systemId,
 | 
						|
                                      base, (resolver != null),
 | 
						|
                                      (errorListener != null),
 | 
						|
                                      getSAXContext (sr));
 | 
						|
              }
 | 
						|
            else
 | 
						|
              {
 | 
						|
                String msg = "Result type not supported (" + result + ")";
 | 
						|
                throw new TransformerConfigurationException (msg);
 | 
						|
              }
 | 
						|
          }
 | 
						|
        catch (IOException e)
 | 
						|
          {
 | 
						|
            throw new TransformerException (e);
 | 
						|
          }
 | 
						|
      }
 | 
						|
    else if (source instanceof DOMSource)
 | 
						|
      {
 | 
						|
        DOMSource ds = (DOMSource) source;
 | 
						|
        Node node = ds.getNode ();
 | 
						|
        if (!(node instanceof GnomeDocument))
 | 
						|
          {
 | 
						|
            String msg = "Node is not a GnomeDocument (" + node + ")";
 | 
						|
            throw new TransformerException (msg);
 | 
						|
          }
 | 
						|
        GnomeDocument doc = (GnomeDocument) node;
 | 
						|
        if (result instanceof StreamResult)
 | 
						|
          {
 | 
						|
            try
 | 
						|
              {
 | 
						|
                OutputStream out = XMLJ.getOutputStream ((StreamResult) result);
 | 
						|
                transformDocToStream (doc, out);
 | 
						|
              }
 | 
						|
            catch (IOException e)
 | 
						|
              {
 | 
						|
                throw new TransformerException (e);
 | 
						|
              }
 | 
						|
          }
 | 
						|
        else if (result instanceof DOMResult)
 | 
						|
          {
 | 
						|
            DOMResult dr = (DOMResult) result;
 | 
						|
            GnomeDocument ret = transformDocToDoc (doc);
 | 
						|
            dr.setNode (ret);
 | 
						|
            dr.setSystemId (null);
 | 
						|
          }
 | 
						|
        else if (result instanceof SAXResult)
 | 
						|
          {
 | 
						|
            SAXResult sr = (SAXResult) result;
 | 
						|
            transformDocToSAX (doc, getSAXContext (sr));
 | 
						|
          }
 | 
						|
        else
 | 
						|
          {
 | 
						|
            String msg = "Result type not supported";
 | 
						|
            throw new TransformerConfigurationException (msg);
 | 
						|
          }
 | 
						|
      }
 | 
						|
    else
 | 
						|
      {
 | 
						|
        String msg = "Source type not supported";
 | 
						|
        throw new TransformerConfigurationException (msg);
 | 
						|
      }
 | 
						|
  }
 | 
						|
 | 
						|
  private GnomeXMLReader getSAXContext (SAXResult result)
 | 
						|
  {
 | 
						|
    GnomeXMLReader ctx = new GnomeXMLReader ();
 | 
						|
    ctx.setContentHandler (result.getHandler ());
 | 
						|
    ctx.setLexicalHandler (result.getLexicalHandler ());
 | 
						|
    if (errorListener != null)
 | 
						|
      {
 | 
						|
        ErrorHandler errorHandler =
 | 
						|
          new ErrorListenerErrorHandler (errorListener);
 | 
						|
        ctx.setErrorHandler (errorHandler);
 | 
						|
      }
 | 
						|
    if (resolver != null)
 | 
						|
      {
 | 
						|
        EntityResolver entityResolver =
 | 
						|
          new URIResolverEntityResolver (resolver);
 | 
						|
        ctx.setEntityResolver (entityResolver);
 | 
						|
      }
 | 
						|
    return ctx;
 | 
						|
  }
 | 
						|
 | 
						|
  private native void transformStreamToStream (InputStream in,
 | 
						|
                                               byte[] detectBuffer,
 | 
						|
                                               String publicId,
 | 
						|
                                               String systemId,
 | 
						|
                                               String base,
 | 
						|
                                               boolean entityResolver,
 | 
						|
                                               boolean errorHandler,
 | 
						|
                                               OutputStream out)
 | 
						|
    throws TransformerException;
 | 
						|
 | 
						|
  private native GnomeDocument transformStreamToDoc (InputStream in,
 | 
						|
                                                     byte[] detectBuffer,
 | 
						|
                                                     String publicId,
 | 
						|
                                                     String systemId,
 | 
						|
                                                     String base,
 | 
						|
                                                     boolean entityResolver,
 | 
						|
                                                     boolean errorHandler)
 | 
						|
    throws TransformerException;
 | 
						|
 | 
						|
  private native void transformStreamToSAX (InputStream in,
 | 
						|
                                            byte[] detectBuffer,
 | 
						|
                                            String publicId,
 | 
						|
                                            String systemId,
 | 
						|
                                            String base,
 | 
						|
                                            boolean entityResolver,
 | 
						|
                                            boolean errorHandler,
 | 
						|
                                            GnomeXMLReader out)
 | 
						|
    throws TransformerException;
 | 
						|
 | 
						|
  private native void transformDocToStream (GnomeDocument in,
 | 
						|
                                            OutputStream out)
 | 
						|
    throws TransformerException;
 | 
						|
 | 
						|
  private native GnomeDocument transformDocToDoc (GnomeDocument in)
 | 
						|
    throws TransformerException;
 | 
						|
 | 
						|
  private native void transformDocToSAX (GnomeDocument in,
 | 
						|
                                         GnomeXMLReader out)
 | 
						|
    throws TransformerException;
 | 
						|
 | 
						|
  /*
 | 
						|
   * Retrieve parameters as a string array.
 | 
						|
   * This is a convenience method called from native code.
 | 
						|
   */
 | 
						|
  private String[] getParameterArray ()
 | 
						|
  {
 | 
						|
    String[] parameterArray = new String[parameters.size () * 2];
 | 
						|
    int index = 0;
 | 
						|
    for (Iterator it = parameters.keySet ().iterator ();
 | 
						|
         it.hasNext ();
 | 
						|
         ++index)
 | 
						|
      {
 | 
						|
        String parameterKey = (String) it.next ();
 | 
						|
        String parameterValue = (String) parameters.get (parameterKey);
 | 
						|
        parameterArray[index * 2 + 0] = parameterKey;
 | 
						|
        parameterArray[index * 2 + 1] =
 | 
						|
          "'" + ((parameterValue != null) ? parameterValue : "") + "'";
 | 
						|
        // FIXME encode parameter value correctly for XPath
 | 
						|
      }
 | 
						|
    return parameterArray;
 | 
						|
  }
 | 
						|
 | 
						|
  // -- Free xsltStylesheet handle --
 | 
						|
 | 
						|
  public void finalize ()
 | 
						|
  {
 | 
						|
    if (stylesheet != null)
 | 
						|
      {
 | 
						|
        free ();
 | 
						|
        stylesheet = null;
 | 
						|
      }
 | 
						|
  }
 | 
						|
 | 
						|
  private native void free ();
 | 
						|
 | 
						|
  // -- Callbacks --
 | 
						|
 | 
						|
  private InputStream resolveEntity (String publicId, String systemId)
 | 
						|
    throws TransformerException
 | 
						|
  {
 | 
						|
    if (resolver != null)
 | 
						|
      {
 | 
						|
        systemId = resolver.resolve (null, systemId).getSystemId ();
 | 
						|
      }
 | 
						|
    if (systemId == null)
 | 
						|
      {
 | 
						|
        return null;
 | 
						|
      }
 | 
						|
    try
 | 
						|
      {
 | 
						|
        URL url = new URL (systemId);
 | 
						|
        return XMLJ.getInputStream (url);
 | 
						|
      }
 | 
						|
    catch (IOException e)
 | 
						|
      {
 | 
						|
        throw new TransformerException (e);
 | 
						|
      }
 | 
						|
  }
 | 
						|
 | 
						|
  private void setDocumentLocator (Object ctx, Object loc)
 | 
						|
  {
 | 
						|
  }
 | 
						|
 | 
						|
  private void warning (String message,
 | 
						|
                        int lineNumber,
 | 
						|
                        int columnNumber,
 | 
						|
                        String publicId,
 | 
						|
                        String systemId)
 | 
						|
    throws TransformerException
 | 
						|
  {
 | 
						|
    if (errorListener == null)
 | 
						|
      {
 | 
						|
        return;
 | 
						|
      }
 | 
						|
    SourceLocator l = new StandaloneLocator (lineNumber,
 | 
						|
                                             columnNumber,
 | 
						|
                                             publicId,
 | 
						|
                                             systemId);
 | 
						|
    errorListener.warning (new TransformerException (message, l));
 | 
						|
  }
 | 
						|
 | 
						|
  private void error (String message,
 | 
						|
                      int lineNumber,
 | 
						|
                      int columnNumber,
 | 
						|
                      String publicId,
 | 
						|
                      String systemId)
 | 
						|
    throws TransformerException
 | 
						|
  {
 | 
						|
    if (errorListener == null)
 | 
						|
      {
 | 
						|
        return;
 | 
						|
      }
 | 
						|
    SourceLocator l = new StandaloneLocator (lineNumber,
 | 
						|
                                             columnNumber,
 | 
						|
                                             publicId,
 | 
						|
                                             systemId);
 | 
						|
    errorListener.error (new TransformerException (message, l));
 | 
						|
  }
 | 
						|
 | 
						|
  private void fatalError (String message,
 | 
						|
                           int lineNumber,
 | 
						|
                           int columnNumber,
 | 
						|
                           String publicId,
 | 
						|
                           String systemId)
 | 
						|
    throws TransformerException
 | 
						|
  {
 | 
						|
    if (errorListener == null)
 | 
						|
      {
 | 
						|
        return;
 | 
						|
      }
 | 
						|
    SourceLocator l = new StandaloneLocator (lineNumber,
 | 
						|
                                             columnNumber,
 | 
						|
                                             publicId,
 | 
						|
                                             systemId);
 | 
						|
    errorListener.fatalError (new TransformerException (message, l));
 | 
						|
  }
 | 
						|
 | 
						|
}
 |