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));
 | |
|   }
 | |
| 
 | |
| }
 |