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 }