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