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: SerializerSwitcher.java 468645 2006-10-28 06:57:24Z minchau $
020     */
021    package org.apache.xalan.transformer;
022    
023    import java.io.OutputStream;
024    import java.io.Writer;
025    import java.util.Properties;
026    
027    import javax.xml.transform.OutputKeys;
028    import javax.xml.transform.TransformerException;
029    
030    import org.apache.xml.serializer.Serializer;
031    import org.apache.xml.serializer.SerializerFactory;
032    import org.apache.xml.serializer.Method;
033    import org.apache.xalan.templates.OutputProperties;
034    
035    import org.xml.sax.ContentHandler;
036    
037    /**
038     * This is a helper class that decides if Xalan needs to switch
039     * serializers, based on the first output element.
040     */
041    public class SerializerSwitcher
042    {
043    
044      /**
045       * Switch to HTML serializer if element is HTML
046       *
047       *
048       * @param transformer Non-null transformer instance
049       * @param ns Namespace URI of the element
050       * @param localName Local part of name of element
051       *
052       * @throws TransformerException
053       */
054      public static void switchSerializerIfHTML(
055              TransformerImpl transformer, String ns, String localName)
056                throws TransformerException
057      {
058    
059        if (null == transformer)
060          return;
061    
062        if (((null == ns) || (ns.length() == 0))
063                && localName.equalsIgnoreCase("html"))
064        {
065          // System.out.println("transformer.getOutputPropertyNoDefault(OutputKeys.METHOD): "+
066          //              transformer.getOutputPropertyNoDefault(OutputKeys.METHOD));     
067          // Access at level of hashtable to see if the method has been set.
068          if (null != transformer.getOutputPropertyNoDefault(OutputKeys.METHOD))
069            return;
070    
071          // Getting the output properties this way won't cause a clone of 
072          // the properties.
073          Properties prevProperties = transformer.getOutputFormat().getProperties();
074          
075          // We have to make sure we get an output properties with the proper 
076          // defaults for the HTML method.  The easiest way to do this is to 
077          // have the OutputProperties class do it.
078          OutputProperties htmlOutputProperties = new OutputProperties(Method.HTML);
079    
080          htmlOutputProperties.copyFrom(prevProperties, true);
081          Properties htmlProperties = htmlOutputProperties.getProperties();
082    
083          try
084          {
085    //        Serializer oldSerializer = transformer.getSerializer();
086            Serializer oldSerializer = null;
087    
088            if (null != oldSerializer)
089            {
090              Serializer serializer =
091                SerializerFactory.getSerializer(htmlProperties);
092    
093              Writer writer = oldSerializer.getWriter();
094    
095              if (null != writer)
096                serializer.setWriter(writer);
097              else
098              {
099                OutputStream os = oldSerializer.getOutputStream();
100    
101                if (null != os)
102                  serializer.setOutputStream(os);
103              }
104    
105    //          transformer.setSerializer(serializer);
106    
107              ContentHandler ch = serializer.asContentHandler();
108    
109              transformer.setContentHandler(ch);
110            }
111          }
112          catch (java.io.IOException e)
113          {
114            throw new TransformerException(e);
115          }
116        }
117      }
118      
119      /**
120       * Get the value of a property, without using the default properties.  This 
121       * can be used to test if a property has been explicitly set by the stylesheet 
122       * or user.
123       *
124       * @param name The property name, which is a fully-qualified URI.
125       *
126       * @return The value of the property, or null if not found.
127       *
128       * @throws IllegalArgumentException If the property is not supported, 
129       * and is not namespaced.
130       */
131      private static String getOutputPropertyNoDefault(String qnameString, Properties props)
132        throws IllegalArgumentException
133      {    
134        String value = (String)props.get(qnameString);
135        
136        return value;
137      }
138      
139      /**
140       * Switch to HTML serializer if element is HTML
141       *
142       *
143       * @param ns Namespace URI of the element
144       * @param localName Local part of name of element
145       *
146       * @throws TransformerException
147       * @return new contentHandler.
148       */
149      public static Serializer switchSerializerIfHTML(
150              String ns, String localName, Properties props, Serializer oldSerializer)
151                throws TransformerException
152      {
153        Serializer newSerializer = oldSerializer;
154    
155        if (((null == ns) || (ns.length() == 0))
156                && localName.equalsIgnoreCase("html"))
157        {
158          // System.out.println("transformer.getOutputPropertyNoDefault(OutputKeys.METHOD): "+
159          //              transformer.getOutputPropertyNoDefault(OutputKeys.METHOD));     
160          // Access at level of hashtable to see if the method has been set.
161          if (null != getOutputPropertyNoDefault(OutputKeys.METHOD, props))
162            return newSerializer;
163    
164          // Getting the output properties this way won't cause a clone of 
165          // the properties.
166          Properties prevProperties = props;
167          
168          // We have to make sure we get an output properties with the proper 
169          // defaults for the HTML method.  The easiest way to do this is to 
170          // have the OutputProperties class do it.
171          OutputProperties htmlOutputProperties = new OutputProperties(Method.HTML);
172    
173          htmlOutputProperties.copyFrom(prevProperties, true);
174          Properties htmlProperties = htmlOutputProperties.getProperties();
175    
176    //      try
177          {
178            if (null != oldSerializer)
179            {
180              Serializer serializer =
181                SerializerFactory.getSerializer(htmlProperties);
182    
183              Writer writer = oldSerializer.getWriter();
184    
185              if (null != writer)
186                serializer.setWriter(writer);
187              else
188              {
189                OutputStream os = serializer.getOutputStream();
190    
191                if (null != os)
192                  serializer.setOutputStream(os);
193              }
194              newSerializer = serializer;
195            }
196          }
197    //      catch (java.io.IOException e)
198    //      {
199    //        throw new TransformerException(e);
200    //      }
201        }
202        return newSerializer;
203      }
204      
205    }