Home | History | Annotate | Download | only in serializer
      1 /*
      2  * Licensed to the Apache Software Foundation (ASF) under one
      3  * or more contributor license agreements. See the NOTICE file
      4  * distributed with this work for additional information
      5  * regarding copyright ownership. The ASF licenses this file
      6  * to you under the Apache License, Version 2.0 (the  "License");
      7  * you may not use this file except in compliance with the License.
      8  * You may obtain a copy of the License at
      9  *
     10  *     http://www.apache.org/licenses/LICENSE-2.0
     11  *
     12  * Unless required by applicable law or agreed to in writing, software
     13  * distributed under the License is distributed on an "AS IS" BASIS,
     14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     15  * See the License for the specific language governing permissions and
     16  * limitations under the License.
     17  */
     18 /*
     19  * $Id: SerializerFactory.java 468654 2006-10-28 07:09:23Z minchau $
     20  */
     21 package org.apache.xml.serializer;
     22 
     23 import java.util.Hashtable;
     24 import java.util.Properties;
     25 
     26 import javax.xml.transform.OutputKeys;
     27 
     28 import org.apache.xml.serializer.utils.MsgKey;
     29 import org.apache.xml.serializer.utils.Utils;
     30 import org.xml.sax.ContentHandler;
     31 
     32 /**
     33  * This class is a public API, it is a factory for creating serializers.
     34    *
     35    * The properties object passed to the getSerializer() method should be created by
     36    * the OutputPropertiesFactory. Although the properties object
     37    * used to create a serializer does not need to be obtained
     38    * from OutputPropertiesFactory,
     39    * using this factory ensures that the default key/value properties
     40    * are set for the given output "method".
     41    *
     42    * <p>
     43    * The standard property keys supported are: "method", "version", "encoding",
     44    * "omit-xml-declaration", "standalone", doctype-public",
     45    * "doctype-system", "cdata-section-elements", "indent", "media-type".
     46    * These property keys and their values are described in the XSLT recommendation,
     47    * see {@link <a href="http://www.w3.org/TR/1999/REC-xslt-19991116"> XSLT 1.0 recommendation</a>}
     48    *
     49    * <p>
     50    * The value of the "cdata-section-elements" property key is a whitespace
     51    * separated list of elements. If the element is in a namespace then
     52    * value is passed in this format: {uri}localName
     53    *
     54    * <p>
     55    * The non-standard property keys supported are defined in {@link OutputPropertiesFactory}.
     56    *
     57    * @see OutputPropertiesFactory
     58    * @see Method
     59    * @see Serializer
     60    */
     61 public final class SerializerFactory
     62 {
     63   /**
     64    * This constructor is private just to prevent the creation of such an object.
     65    */
     66 
     67   private SerializerFactory() {
     68 
     69   }
     70   /**
     71    * Associates output methods to default output formats.
     72    */
     73   private static Hashtable m_formats = new Hashtable();
     74 
     75   /**
     76    * Returns a serializer for the specified output method. The output method
     77    * is specified by the value of the property associated with the "method" key.
     78    * If no implementation exists that supports the specified output method
     79    * an exception of some type will be thrown.
     80    * For a list of the output "method" key values see {@link Method}.
     81    *
     82    * @param format The output format, minimally the "method" property must be set.
     83    * @return A suitable serializer.
     84    * @throws IllegalArgumentException if method is
     85    * null or an appropriate serializer can't be found
     86    * @throws Exception if the class for the serializer is found but does not
     87    * implement ContentHandler.
     88    * @throws WrappedRuntimeException if an exception is thrown while trying to find serializer
     89    */
     90   public static Serializer getSerializer(Properties format)
     91   {
     92       Serializer ser;
     93 
     94       try
     95       {
     96         String method = format.getProperty(OutputKeys.METHOD);
     97 
     98         if (method == null) {
     99             String msg = Utils.messages.createMessage(
    100                 MsgKey.ER_FACTORY_PROPERTY_MISSING,
    101                 new Object[] { OutputKeys.METHOD});
    102             throw new IllegalArgumentException(msg);
    103         }
    104 
    105         String className =
    106             format.getProperty(OutputPropertiesFactory.S_KEY_CONTENT_HANDLER);
    107 
    108 
    109         if (null == className)
    110         {
    111             // Missing Content Handler property, load default using OutputPropertiesFactory
    112             Properties methodDefaults =
    113                 OutputPropertiesFactory.getDefaultMethodProperties(method);
    114             className =
    115             methodDefaults.getProperty(OutputPropertiesFactory.S_KEY_CONTENT_HANDLER);
    116             if (null == className) {
    117                 String msg = Utils.messages.createMessage(
    118                     MsgKey.ER_FACTORY_PROPERTY_MISSING,
    119                     new Object[] { OutputPropertiesFactory.S_KEY_CONTENT_HANDLER});
    120                 throw new IllegalArgumentException(msg);
    121             }
    122 
    123         }
    124 
    125 
    126 
    127         ClassLoader loader = ObjectFactory.findClassLoader();
    128 
    129         Class cls = ObjectFactory.findProviderClass(className, loader, true);
    130 
    131         // _serializers.put(method, cls);
    132 
    133         Object obj = cls.newInstance();
    134 
    135         if (obj instanceof SerializationHandler)
    136         {
    137               // this is one of the supplied serializers
    138             ser = (Serializer) cls.newInstance();
    139             ser.setOutputFormat(format);
    140         }
    141         else
    142         {
    143               /*
    144                *  This  must be a user defined Serializer.
    145                *  It had better implement ContentHandler.
    146                */
    147                if (obj instanceof ContentHandler)
    148                {
    149 
    150                   /*
    151                    * The user defined serializer defines ContentHandler,
    152                    * but we need to wrap it with ToXMLSAXHandler which
    153                    * will collect SAX-like events and emit true
    154                    * SAX ContentHandler events to the users handler.
    155                    */
    156                   className = SerializerConstants.DEFAULT_SAX_SERIALIZER;
    157                   cls = ObjectFactory.findProviderClass(className, loader, true);
    158                   SerializationHandler sh =
    159                       (SerializationHandler) cls.newInstance();
    160                   sh.setContentHandler( (ContentHandler) obj);
    161                   sh.setOutputFormat(format);
    162 
    163                   ser = sh;
    164                }
    165                else
    166                {
    167                   // user defined serializer does not implement
    168                   // ContentHandler, ... very bad
    169                    throw new Exception(
    170                        Utils.messages.createMessage(
    171                            MsgKey.ER_SERIALIZER_NOT_CONTENTHANDLER,
    172                                new Object[] { className}));
    173                }
    174 
    175         }
    176       }
    177       catch (Exception e)
    178       {
    179         throw new org.apache.xml.serializer.utils.WrappedRuntimeException(e);
    180       }
    181 
    182       // If we make it to here ser is not null.
    183       return ser;
    184   }
    185 }
    186