001 /*
002 * Licensed to the Apache Software Foundation (ASF) under one
003 * or more contributor license agreements. See the NOTICE file
004 * distributed with this work for additional information
005 * regarding copyright ownership. The ASF licenses this file
006 * to you under the Apache License, Version 2.0 (the "License");
007 * you may not use this file except in compliance with the License.
008 * You may obtain a copy of the License at
009 *
010 * http://www.apache.org/licenses/LICENSE-2.0
011 *
012 * Unless required by applicable law or agreed to in writing, software
013 * distributed under the License is distributed on an "AS IS" BASIS,
014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
015 * See the License for the specific language governing permissions and
016 * limitations under the License.
017 */
018 /*
019 * $Id: SerializerFactory.java 468654 2006-10-28 07:09:23Z minchau $
020 */
021 package org.apache.xml.serializer;
022
023 import java.util.Hashtable;
024 import java.util.Properties;
025
026 import javax.xml.transform.OutputKeys;
027
028 import org.apache.xml.serializer.utils.MsgKey;
029 import org.apache.xml.serializer.utils.Utils;
030 import org.xml.sax.ContentHandler;
031
032 /**
033 * This class is a public API, it is a factory for creating serializers.
034 *
035 * The properties object passed to the getSerializer() method should be created by
036 * the OutputPropertiesFactory. Although the properties object
037 * used to create a serializer does not need to be obtained
038 * from OutputPropertiesFactory,
039 * using this factory ensures that the default key/value properties
040 * are set for the given output "method".
041 *
042 * <p>
043 * The standard property keys supported are: "method", "version", "encoding",
044 * "omit-xml-declaration", "standalone", doctype-public",
045 * "doctype-system", "cdata-section-elements", "indent", "media-type".
046 * These property keys and their values are described in the XSLT recommendation,
047 * see {@link <a href="http://www.w3.org/TR/1999/REC-xslt-19991116"> XSLT 1.0 recommendation</a>}
048 *
049 * <p>
050 * The value of the "cdata-section-elements" property key is a whitespace
051 * separated list of elements. If the element is in a namespace then
052 * value is passed in this format: {uri}localName
053 *
054 * <p>
055 * The non-standard property keys supported are defined in {@link OutputPropertiesFactory}.
056 *
057 * @see OutputPropertiesFactory
058 * @see Method
059 * @see Serializer
060 */
061 public final class SerializerFactory
062 {
063 /**
064 * This constructor is private just to prevent the creation of such an object.
065 */
066
067 private SerializerFactory() {
068
069 }
070 /**
071 * Associates output methods to default output formats.
072 */
073 private static Hashtable m_formats = new Hashtable();
074
075 /**
076 * Returns a serializer for the specified output method. The output method
077 * is specified by the value of the property associated with the "method" key.
078 * If no implementation exists that supports the specified output method
079 * an exception of some type will be thrown.
080 * For a list of the output "method" key values see {@link Method}.
081 *
082 * @param format The output format, minimally the "method" property must be set.
083 * @return A suitable serializer.
084 * @throws IllegalArgumentException if method is
085 * null or an appropriate serializer can't be found
086 * @throws Exception if the class for the serializer is found but does not
087 * implement ContentHandler.
088 * @throws WrappedRuntimeException if an exception is thrown while trying to find serializer
089 */
090 public static Serializer getSerializer(Properties format)
091 {
092 Serializer ser;
093
094 try
095 {
096 String method = format.getProperty(OutputKeys.METHOD);
097
098 if (method == null) {
099 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 }