SerializerFactory.java revision 1188:86157a0bf14f
1/*
2 * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
3 */
4/*
5 * Licensed to the Apache Software Foundation (ASF) under one or more
6 * contributor license agreements.  See the NOTICE file distributed with
7 * this work for additional information regarding copyright ownership.
8 * The ASF licenses this file to You under the Apache License, Version 2.0
9 * (the "License"); you may not use this file except in compliance with
10 * the License.  You may obtain a copy of the License at
11 *
12 *      http://www.apache.org/licenses/LICENSE-2.0
13 *
14 * Unless required by applicable law or agreed to in writing, software
15 * distributed under the License is distributed on an "AS IS" BASIS,
16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 * See the License for the specific language governing permissions and
18 * limitations under the License.
19 */
20
21package com.sun.org.apache.xml.internal.serializer;
22
23import java.util.Properties;
24
25import javax.xml.transform.OutputKeys;
26
27import com.sun.org.apache.xml.internal.serializer.utils.MsgKey;
28import com.sun.org.apache.xml.internal.serializer.utils.Utils;
29import com.sun.org.apache.xalan.internal.utils.ObjectFactory;
30import 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   */
61public final class SerializerFactory
62{
63  /**
64   * This constructor is private just to prevent the creation of such an object.
65   */
66
67  private SerializerFactory() {
68
69  }
70
71  /**
72   * Returns a serializer for the specified output method. The output method
73   * is specified by the value of the property associated with the "method" key.
74   * If no implementation exists that supports the specified output method
75   * an exception of some type will be thrown.
76   * For a list of the output "method" key values see {@link Method}.
77   *
78   * @param format The output format, minimally the "method" property must be set.
79   * @return A suitable serializer.
80   * @throws IllegalArgumentException if method is
81   * null or an appropriate serializer can't be found
82   * @throws Exception if the class for the serializer is found but does not
83   * implement ContentHandler.
84   * @throws WrappedRuntimeException if an exception is thrown while trying to find serializer
85   */
86  public static Serializer getSerializer(Properties format)
87  {
88      Serializer ser;
89
90      try
91      {
92        String method = format.getProperty(OutputKeys.METHOD);
93
94        if (method == null) {
95            String msg = Utils.messages.createMessage(
96                MsgKey.ER_FACTORY_PROPERTY_MISSING,
97                new Object[] { OutputKeys.METHOD});
98            throw new IllegalArgumentException(msg);
99        }
100
101        String className =
102            format.getProperty(OutputPropertiesFactory.S_KEY_CONTENT_HANDLER);
103
104
105        if (null == className)
106        {
107            // Missing Content Handler property, load default using OutputPropertiesFactory
108            Properties methodDefaults =
109                OutputPropertiesFactory.getDefaultMethodProperties(method);
110            className =
111            methodDefaults.getProperty(OutputPropertiesFactory.S_KEY_CONTENT_HANDLER);
112            if (null == className) {
113                String msg = Utils.messages.createMessage(
114                    MsgKey.ER_FACTORY_PROPERTY_MISSING,
115                    new Object[] { OutputPropertiesFactory.S_KEY_CONTENT_HANDLER});
116                throw new IllegalArgumentException(msg);
117            }
118
119        }
120
121
122
123        Class cls = ObjectFactory.findProviderClass(className, true);
124
125        // _serializers.put(method, cls);
126
127        Object obj = cls.getConstructor().newInstance();
128
129        if (obj instanceof SerializationHandler)
130        {
131              // this is one of the supplied serializers
132            ser = (Serializer) obj;
133            ser.setOutputFormat(format);
134        }
135        else
136        {
137              /*
138               *  This  must be a user defined Serializer.
139               *  It had better implement ContentHandler.
140               */
141               if (obj instanceof ContentHandler)
142               {
143
144                  /*
145                   * The user defined serializer defines ContentHandler,
146                   * but we need to wrap it with ToXMLSAXHandler which
147                   * will collect SAX-like events and emit true
148                   * SAX ContentHandler events to the users handler.
149                   */
150                  className = SerializerConstants.DEFAULT_SAX_SERIALIZER;
151                  cls = ObjectFactory.findProviderClass(className, true);
152                  SerializationHandler sh =
153                      (SerializationHandler) cls.getConstructor().newInstance();
154                  sh.setContentHandler( (ContentHandler) obj);
155                  sh.setOutputFormat(format);
156
157                  ser = sh;
158               }
159               else
160               {
161                  // user defined serializer does not implement
162                  // ContentHandler, ... very bad
163                   throw new Exception(
164                       Utils.messages.createMessage(
165                           MsgKey.ER_SERIALIZER_NOT_CONTENTHANDLER,
166                               new Object[] { className}));
167               }
168
169        }
170      }
171      catch (Exception e)
172      {
173        throw new com.sun.org.apache.xml.internal.serializer.utils.WrappedRuntimeException(e);
174      }
175
176      // If we make it to here ser is not null.
177      return ser;
178  }
179}
180