001: /*
002: * Copyright 1999-2004 The Apache Software Foundation.
003: *
004: * Licensed under the Apache License, Version 2.0 (the "License");
005: * you may not use this file except in compliance with the License.
006: * You may obtain a copy of the License at
007: *
008: * http://www.apache.org/licenses/LICENSE-2.0
009: *
010: * Unless required by applicable law or agreed to in writing, software
011: * distributed under the License is distributed on an "AS IS" BASIS,
012: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013: * See the License for the specific language governing permissions and
014: * limitations under the License.
015: */
016: /*
017: * $Id: SerializerFactory.java,v 1.10 2005/04/07 04:29:03 minchau Exp $
018: */
019: package org.apache.xml.serializer;
020:
021: import java.util.Hashtable;
022: import java.util.Properties;
023:
024: import javax.xml.transform.OutputKeys;
025:
026: import org.apache.xml.serializer.utils.MsgKey;
027: import org.apache.xml.serializer.utils.Utils;
028: import org.xml.sax.ContentHandler;
029:
030: /**
031: * This class is a public API, it is a factory for creating serializers.
032: *
033: * The properties object passed to the getSerializer() method should be created by
034: * the OutputPropertiesFactory. Although the properties object
035: * used to create a serializer does not need to be obtained
036: * from OutputPropertiesFactory,
037: * using this factory ensures that the default key/value properties
038: * are set for the given output "method".
039: *
040: * <p>
041: * The standard property keys supported are: "method", "version", "encoding",
042: * "omit-xml-declaration", "standalone", doctype-public",
043: * "doctype-system", "cdata-section-elements", "indent", "media-type".
044: * These property keys and their values are described in the XSLT recommendation,
045: * see {@link <a href="http://www.w3.org/TR/1999/REC-xslt-19991116"> XSLT 1.0 recommendation</a>}
046: *
047: * <p>
048: * The value of the "cdata-section-elements" property key is a whitespace
049: * separated list of elements. If the element is in a namespace then
050: * value is passed in this format: {uri}localName
051: *
052: * <p>
053: * The non-standard property keys supported are defined in {@link OutputPropertiesFactory}.
054: *
055: * @see OutputPropertiesFactory
056: * @see Method
057: * @see Serializer
058: */
059: public final class SerializerFactory {
060: /**
061: * This constructor is private just to prevent the creation of such an object.
062: */
063:
064: private SerializerFactory() {
065:
066: }
067:
068: /**
069: * Associates output methods to default output formats.
070: */
071: private static Hashtable m_formats = new Hashtable();
072:
073: /**
074: * Returns a serializer for the specified output method. The output method
075: * is specified by the value of the property associated with the "method" key.
076: * If no implementation exists that supports the specified output method
077: * an exception of some type will be thrown.
078: * For a list of the output "method" key values see {@link Method}.
079: *
080: * @param format The output format, minimally the "method" property must be set.
081: * @return A suitable serializer.
082: * @throws IllegalArgumentException if method is
083: * null or an appropriate serializer can't be found
084: * @throws Exception if the class for the serializer is found but does not
085: * implement ContentHandler.
086: * @throws WrappedRuntimeException if an exception is thrown while trying to find serializer
087: */
088: public static Serializer getSerializer(Properties format) {
089: Serializer ser;
090:
091: try {
092: String method = format.getProperty(OutputKeys.METHOD);
093:
094: if (method == null) {
095: String msg = Utils.messages.createMessage(
096: MsgKey.ER_FACTORY_PROPERTY_MISSING,
097: new Object[] { OutputKeys.METHOD });
098: throw new IllegalArgumentException(msg);
099: }
100:
101: String className = format
102: .getProperty(OutputPropertiesFactory.S_KEY_CONTENT_HANDLER);
103:
104: if (null == className) {
105: // Missing Content Handler property, load default using OutputPropertiesFactory
106: Properties methodDefaults = OutputPropertiesFactory
107: .getDefaultMethodProperties(method);
108: className = methodDefaults
109: .getProperty(OutputPropertiesFactory.S_KEY_CONTENT_HANDLER);
110: if (null == className) {
111: String msg = Utils.messages
112: .createMessage(
113: MsgKey.ER_FACTORY_PROPERTY_MISSING,
114: new Object[] { OutputPropertiesFactory.S_KEY_CONTENT_HANDLER });
115: throw new IllegalArgumentException(msg);
116: }
117:
118: }
119:
120: ClassLoader loader = ObjectFactory.findClassLoader();
121:
122: Class cls = ObjectFactory.findProviderClass(className,
123: loader, true);
124:
125: // _serializers.put(method, cls);
126:
127: Object obj = cls.newInstance();
128:
129: if (obj instanceof SerializationHandler) {
130: // this is one of the supplied serializers
131: ser = (Serializer) cls.newInstance();
132: ser.setOutputFormat(format);
133: } else {
134: /*
135: * This must be a user defined Serializer.
136: * It had better implement ContentHandler.
137: */
138: if (obj instanceof ContentHandler) {
139:
140: /*
141: * The user defined serializer defines ContentHandler,
142: * but we need to wrap it with ToXMLSAXHandler which
143: * will collect SAX-like events and emit true
144: * SAX ContentHandler events to the users handler.
145: */
146: className = SerializerConstants.DEFAULT_SAX_SERIALIZER;
147: cls = ObjectFactory.findProviderClass(className,
148: loader, true);
149: SerializationHandler sh = (SerializationHandler) cls
150: .newInstance();
151: sh.setContentHandler((ContentHandler) obj);
152: sh.setOutputFormat(format);
153:
154: ser = sh;
155: } else {
156: // user defined serializer does not implement
157: // ContentHandler, ... very bad
158: throw new Exception(Utils.messages.createMessage(
159: MsgKey.ER_SERIALIZER_NOT_CONTENTHANDLER,
160: new Object[] { className }));
161: }
162:
163: }
164: } catch (Exception e) {
165: throw new org.apache.xml.serializer.utils.WrappedRuntimeException(
166: e);
167: }
168:
169: // If we make it to here ser is not null.
170: return ser;
171: }
172: }
|