• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
SerializerFactory()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    */
getSerializer(Properties format)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