Source for gnu.xml.libxmlj.transform.GnomeTransformerFactory

   1: /* GnomeTransformerFactory.java -
   2:    Copyright (C) 2004 Free Software Foundation, Inc.
   3: 
   4: This file is part of GNU Classpath.
   5: 
   6: GNU Classpath is free software; you can redistribute it and/or modify
   7: it under the terms of the GNU General Public License as published by
   8: the Free Software Foundation; either version 2, or (at your option)
   9: any later version.
  10: 
  11: GNU Classpath is distributed in the hope that it will be useful, but
  12: WITHOUT ANY WARRANTY; without even the implied warranty of
  13: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  14: General Public License for more details.
  15: 
  16: You should have received a copy of the GNU General Public License
  17: along with GNU Classpath; see the file COPYING.  If not, write to the
  18: Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
  19: 02110-1301 USA.
  20: 
  21: Linking this library statically or dynamically with other modules is
  22: making a combined work based on this library.  Thus, the terms and
  23: conditions of the GNU General Public License cover the whole
  24: combination.
  25: 
  26: As a special exception, the copyright holders of this library give you
  27: permission to link this library with independent modules to produce an
  28: executable, regardless of the license terms of these independent
  29: modules, and to copy and distribute the resulting executable under
  30: terms of your choice, provided that you also meet, for each linked
  31: independent module, the terms and conditions of the license of that
  32: module.  An independent module is a module which is not derived from
  33: or based on this library.  If you modify this library, you may extend
  34: this exception to your version of the library, but you are not
  35: obligated to do so.  If you do not wish to do so, delete this
  36: exception statement from your version. */
  37: 
  38: package gnu.xml.libxmlj.transform;
  39: 
  40: import java.io.InputStream;
  41: import java.io.IOException;
  42: import java.util.HashMap;
  43: import java.util.Map;
  44: 
  45: import javax.xml.parsers.FactoryConfigurationError;
  46: import javax.xml.parsers.ParserConfigurationException;
  47: import javax.xml.parsers.SAXParser;
  48: import javax.xml.parsers.SAXParserFactory;
  49: 
  50: import javax.xml.transform.ErrorListener;
  51: import javax.xml.transform.Source;
  52: import javax.xml.transform.Templates;
  53: import javax.xml.transform.Transformer;
  54: import javax.xml.transform.TransformerFactory;
  55: import javax.xml.transform.TransformerConfigurationException;
  56: import javax.xml.transform.URIResolver;
  57: 
  58: import javax.xml.transform.dom.DOMResult;
  59: import javax.xml.transform.dom.DOMSource;
  60: import javax.xml.transform.sax.SAXSource;
  61: import javax.xml.transform.stream.StreamResult;
  62: import javax.xml.transform.stream.StreamSource;
  63: 
  64: import org.w3c.dom.Document;
  65: import org.w3c.dom.Node;
  66: import org.xml.sax.InputSource;
  67: import org.xml.sax.SAXException;
  68: import org.xml.sax.XMLReader;
  69: import org.xml.sax.helpers.DefaultHandler;
  70: 
  71: import gnu.xml.libxmlj.util.XMLJ;
  72: 
  73: /**
  74:  *  An implementation of <code>TransformerFactory</code> producing
  75:  *  <code>Transformer</code> objects which use <code>libxslt</code>
  76:  *  for transformation.
  77:  *
  78:  *  @author Julian Scheid
  79:  *  @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
  80:  */
  81: public class GnomeTransformerFactory
  82:   extends TransformerFactory
  83: {
  84: 
  85:   static
  86:   {
  87:     XMLJ.init ();
  88:   }
  89: 
  90:   /**
  91:    *  URIResolver set by user, or default implementation.
  92:    */
  93:   private URIResolver uriResolver;
  94: 
  95:   /**
  96:    *  ErrorListener set by user, or default implementation.
  97:    */
  98:   private ErrorListener errorListener;
  99: 
 100:   /**
 101:    *  Attributes set by user.
 102:    */
 103:   private Map attributes = new HashMap ();
 104: 
 105:   //--- Implementation of javax.xml.transform.TransformerFactory
 106:   //--- follows.
 107: 
 108:   // -- begin getAssociatedStylesheet implementation --
 109: 
 110:   /**
 111:    * Returns the stylesheet associated with the specified XML source, or
 112:    * <code>null</code> if no associated stylesheet could be found.
 113:    */
 114:   public Source getAssociatedStylesheet(Source source, String media,
 115:                                         String title, String charset)
 116:     throws TransformerConfigurationException
 117:   {
 118:     String href= null;
 119:     String base = source.getSystemId();
 120:     if (source instanceof DOMSource)
 121:       {
 122:         Node node = ((DOMSource) source).getNode();
 123:         Document doc = (node.getNodeType() == Node.DOCUMENT_NODE) ?
 124:           (Document) node : node.getOwnerDocument();
 125:         if (base == null)
 126:           {
 127:             base = doc.getDocumentURI();
 128:           }
 129:         for (node = doc.getFirstChild(); node != null;
 130:              node = node.getNextSibling())
 131:           {
 132:             if (node.getNodeType() == Node.PROCESSING_INSTRUCTION_NODE &&
 133:                 "xml-stylesheet".equals(node.getNodeName()))
 134:               {
 135:                 String data = node.getNodeValue();
 136:                 if (media != null &&
 137:                     !media.equals(parseParameter(data, "type")))
 138:                   {
 139:                     continue;
 140:                   }
 141:                 if (title != null &&
 142:                     !title.equals(parseParameter(data, "title")))
 143:                   {
 144:                     continue;
 145:                   }
 146:                 href = parseParameter(data, "href");
 147:               }
 148:           }
 149:       }
 150:     else
 151:       {
 152:         InputSource input;
 153:         XMLReader parser = null;
 154:         try
 155:           {
 156:             if (source instanceof SAXSource)
 157:               {
 158:                 SAXSource sax = (SAXSource) source;
 159:                 input = sax.getInputSource();
 160:                 parser = sax.getXMLReader();
 161:               }
 162:             else
 163:               {
 164:                 StreamSource stream = (StreamSource) source;
 165:                 InputStream in = stream.getInputStream();
 166:                 input = new InputSource(in);
 167:               }
 168:             input.setSystemId(base);
 169:             if (parser == null)
 170:               {
 171:                 parser = createXMLReader();
 172:               }
 173:             AssociatedStylesheetHandler ash =
 174:               new AssociatedStylesheetHandler();
 175:             ash.media = media;
 176:             ash.title = title;
 177:             parser.setContentHandler(ash);
 178:             parser.parse(input);
 179:             href = ash.href;
 180:           }
 181:         catch (SAXException e)
 182:           {
 183:             throw new TransformerConfigurationException(e);
 184:           }
 185:         catch (IOException e)
 186:           {
 187:             throw new TransformerConfigurationException(e);
 188:           }
 189:       }
 190:     if (href == null)
 191:       {
 192:         return null;
 193:       }
 194:     if (base != null)
 195:       {
 196:         base = XMLJ.getBaseURI(base);
 197:       }
 198:     href = XMLJ.getAbsoluteURI(base, href);
 199:     return new StreamSource(href);
 200:   }
 201: 
 202:   private XMLReader createXMLReader()
 203:     throws TransformerConfigurationException
 204:   {
 205:     try
 206:       {
 207:         SAXParserFactory factory = SAXParserFactory.newInstance();
 208:         SAXParser parser = factory.newSAXParser();
 209:         return parser.getXMLReader();
 210:       }
 211:     catch (FactoryConfigurationError e)
 212:       {
 213:         throw new TransformerConfigurationException(e);
 214:       }
 215:     catch (ParserConfigurationException e)
 216:       {
 217:         throw new TransformerConfigurationException(e);
 218:       }
 219:     catch (SAXException e)
 220:       {
 221:         throw new TransformerConfigurationException(e);
 222:       }
 223:   }
 224: 
 225:   class AssociatedStylesheetHandler
 226:     extends DefaultHandler
 227:   {
 228: 
 229:     String media;
 230:     String title;
 231:     String href;
 232: 
 233:     public void processingInstruction(String target, String data)
 234:       throws SAXException
 235:     {
 236:       if ("xml-stylesheet".equals(target))
 237:         {
 238:           if (media != null && !media.equals(parseParameter(data, "type")))
 239:             {
 240:               return;
 241:             }
 242:           if (title != null && !title.equals(parseParameter(data, "title")))
 243:             {
 244:               return;
 245:             }
 246:           href = parseParameter(data, "href");
 247:         }
 248:     }
 249: 
 250:   }
 251: 
 252:   String parseParameter(String data, String name)
 253:   {
 254:     int start = data.indexOf(name + "=");
 255:     if (start != -1)
 256:       {
 257:         start += name.length() + 2;
 258:         char delim = data.charAt(start - 1);
 259:         int end = data.indexOf(delim, start);
 260:         if (end != -1)
 261:           {
 262:             return data.substring(start, end);
 263:           }
 264:       }
 265:     return null;
 266:   }
 267: 
 268:   // -- end getAssociatedStylesheet implementation --
 269: 
 270:   public synchronized void setAttribute (String name, Object value)
 271:   {
 272:     this.attributes.put (name, value);
 273:   }
 274: 
 275:   public synchronized Object getAttribute (String name)
 276:   {
 277:     return attributes.get (name);
 278:   }
 279: 
 280:   public void setErrorListener (ErrorListener errorListener)
 281:   {
 282:     this.errorListener = errorListener;
 283:   }
 284: 
 285:   public ErrorListener getErrorListener ()
 286:   {
 287:     return errorListener;
 288:   }
 289: 
 290:   public void setURIResolver (URIResolver uriResolver)
 291:   {
 292:     this.uriResolver = uriResolver;
 293:   }
 294: 
 295:   public URIResolver getURIResolver ()
 296:   {
 297:     return uriResolver;
 298:   }
 299: 
 300:   public boolean getFeature (String name)
 301:   {
 302:     return (StreamSource.FEATURE.equals (name) ||
 303:             StreamResult.FEATURE.equals (name) ||
 304:             DOMSource.FEATURE.equals (name) ||
 305:             DOMResult.FEATURE.equals (name));
 306:   }
 307: 
 308:   public void setFeature(String name, boolean value)
 309:     throws TransformerConfigurationException
 310:   {
 311:     throw new TransformerConfigurationException(name);
 312:   }
 313: 
 314:   /**
 315:    *  Returns a new instance of class {@link Transformer} for a
 316:    *  null souce.
 317:    */
 318:   public Transformer newTransformer ()
 319:     throws TransformerConfigurationException
 320:   {
 321:     return newTransformer (null);
 322:   }
 323: 
 324:   /**
 325:    *  Returns a new instance of class {@link Transformer} for
 326:    *  the given souce.
 327:    */
 328:   public Transformer newTransformer (Source source)
 329:     throws TransformerConfigurationException
 330:   {
 331:     return new GnomeTransformer (source, uriResolver, errorListener);
 332:   }
 333: 
 334:   /**
 335:    *  Returns a new instance of class {@link Templates} for
 336:    *  the given souce.
 337:    */
 338:   public Templates newTemplates (Source source)
 339:     throws TransformerConfigurationException
 340:   {
 341:     return new GnomeTransformer (source, uriResolver, errorListener);
 342:   }
 343: 
 344:   /**
 345:    *  Perform native cleanup.
 346:    */
 347:   public static native void freeLibxsltGlobal ();
 348: 
 349: }