1/*
2 * Copyright (c) 2005, 2006, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.  Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26package com.sun.xml.internal.stream;
27
28import java.io.File;
29import java.io.FileWriter;
30import java.io.IOException;
31import java.io.OutputStream;
32import java.io.Writer;
33
34import javax.xml.stream.XMLOutputFactory ;
35import javax.xml.stream.XMLStreamException;
36import javax.xml.transform.Result;
37import javax.xml.transform.dom.DOMResult;
38import javax.xml.transform.stream.StreamResult;
39import javax.xml.transform.stax.StAXResult;
40import com.sun.org.apache.xerces.internal.impl.Constants;
41import com.sun.org.apache.xerces.internal.impl.PropertyManager;
42
43import com.sun.xml.internal.stream.writers.XMLDOMWriterImpl;
44import com.sun.xml.internal.stream.writers.XMLEventWriterImpl;
45import com.sun.xml.internal.stream.writers.XMLStreamWriterImpl;
46
47/**
48 * This class provides the implementation of XMLOutputFactory.
49 *
50 * @author  Neeraj Bajaj,
51 * @author k.venugopal@sun.com
52 */
53public class XMLOutputFactoryImpl extends XMLOutputFactory {
54
55    //List of supported properties and default values.
56    private PropertyManager fPropertyManager = new PropertyManager(PropertyManager.CONTEXT_WRITER);
57
58    //cache the instance of XMLStreamWriterImpl
59    private XMLStreamWriterImpl fStreamWriter = null;
60
61    /**
62     * TODO: at the current time, XMLStreamWriters are not Thread safe.
63     */
64    boolean fReuseInstance = false;
65
66    /** Creates a new instance of XMLOutputFactory */
67    public XMLOutputFactoryImpl() {
68    }
69
70    public javax.xml.stream.XMLEventWriter createXMLEventWriter(java.io.OutputStream outputStream) throws javax.xml.stream.XMLStreamException {
71        return createXMLEventWriter(outputStream,  null);
72    }
73
74    public javax.xml.stream.XMLEventWriter createXMLEventWriter(java.io.OutputStream outputStream, String encoding) throws javax.xml.stream.XMLStreamException {
75        return new XMLEventWriterImpl(createXMLStreamWriter(outputStream, encoding));
76    }
77
78    public javax.xml.stream.XMLEventWriter createXMLEventWriter(javax.xml.transform.Result result) throws javax.xml.stream.XMLStreamException {
79
80        if (result instanceof StAXResult && ((StAXResult)result).getXMLEventWriter() != null)
81            return ((StAXResult)result).getXMLEventWriter();
82
83        return new XMLEventWriterImpl(createXMLStreamWriter(result));
84    }
85
86    public javax.xml.stream.XMLEventWriter createXMLEventWriter(java.io.Writer writer) throws javax.xml.stream.XMLStreamException {
87        return new XMLEventWriterImpl(createXMLStreamWriter(writer));
88    }
89
90    public javax.xml.stream.XMLStreamWriter createXMLStreamWriter(javax.xml.transform.Result result) throws javax.xml.stream.XMLStreamException {
91
92        if (result instanceof StreamResult) {
93            return createXMLStreamWriter((StreamResult) result, null);
94        } else if (result instanceof DOMResult) {
95            return new XMLDOMWriterImpl((DOMResult) result);
96        } else if (result instanceof StAXResult) {
97            if (((StAXResult) result).getXMLStreamWriter() != null) {
98                return ((StAXResult) result).getXMLStreamWriter();
99            } else {
100                throw new java.lang.UnsupportedOperationException("Result of type " + result + " is not supported");
101            }
102        } else {
103            if (result.getSystemId() !=null) {
104                //this is not correct impl of SAXResult. Keep it for now for compatibility
105                return createXMLStreamWriter(new StreamResult(result.getSystemId()));
106            } else {
107                throw new java.lang.UnsupportedOperationException("Result of type " + result + " is not supported. " +
108                        "Supported result types are: DOMResult, StAXResult and StreamResult.");
109            }
110        }
111
112    }
113
114    public javax.xml.stream.XMLStreamWriter createXMLStreamWriter(java.io.Writer writer) throws javax.xml.stream.XMLStreamException {
115        return createXMLStreamWriter(toStreamResult(null, writer, null) , null);
116    }
117
118    public javax.xml.stream.XMLStreamWriter createXMLStreamWriter(java.io.OutputStream outputStream) throws javax.xml.stream.XMLStreamException {
119        return createXMLStreamWriter(outputStream, null);
120    }
121
122    public javax.xml.stream.XMLStreamWriter createXMLStreamWriter(java.io.OutputStream outputStream, String encoding) throws javax.xml.stream.XMLStreamException {
123        return createXMLStreamWriter(toStreamResult(outputStream, null, null) , encoding);
124    }
125
126    public Object getProperty(String name) throws java.lang.IllegalArgumentException {
127        if(name == null){
128            throw new IllegalArgumentException("Property not supported");
129        }
130        if(fPropertyManager.containsProperty(name))
131            return fPropertyManager.getProperty(name);
132        throw new IllegalArgumentException("Property not supported");
133    }
134
135    public boolean isPropertySupported(String name) {
136        if(name == null){
137            return false ;
138        }
139        else{
140            return fPropertyManager.containsProperty(name);
141        }
142    }
143
144    public void setProperty(String name, Object value) throws java.lang.IllegalArgumentException {
145        if(name == null || value == null || !fPropertyManager.containsProperty(name) ){
146            throw new IllegalArgumentException("Property "+name+"is not supported");
147        }
148        if(name == Constants.REUSE_INSTANCE || name.equals(Constants.REUSE_INSTANCE)){
149            fReuseInstance = ((Boolean)value).booleanValue();
150            if(DEBUG)System.out.println("fReuseInstance is set to " + fReuseInstance);
151
152            // TODO: XMLStreamWriters are not Thread safe,
153            // don't let application think it is optimizing
154            if (fReuseInstance) {
155                throw new IllegalArgumentException(
156                        "Property "
157                        + name
158                        + " is not supported: XMLStreamWriters are not Thread safe");
159            }
160        }else{//for any other property set the flag
161            //REVISIT: Even in this case instance can be reused, by passing PropertyManager
162            fPropertyChanged = true;
163        }
164        fPropertyManager.setProperty(name,value);
165    }
166
167    /** StreamResult object is re-used and the values are set appropriately.
168     */
169    StreamResult toStreamResult(OutputStream os, Writer writer, String systemId){
170        StreamResult sr = new StreamResult();
171        sr.setOutputStream(os);
172        sr.setWriter(writer);
173        sr.setSystemId(systemId);
174        return sr;
175    }
176
177    javax.xml.stream.XMLStreamWriter createXMLStreamWriter(javax.xml.transform.stream.StreamResult sr, String encoding) throws javax.xml.stream.XMLStreamException {
178        //if factory is configured to reuse the instance & this instance can be reused
179        //& the setProperty() hasn't been called
180        try{
181            if(fReuseInstance && fStreamWriter != null && fStreamWriter.canReuse() && !fPropertyChanged){
182                fStreamWriter.reset();
183                fStreamWriter.setOutput(sr, encoding);
184                if(DEBUG)System.out.println("reusing instance, object id : " + fStreamWriter);
185                return fStreamWriter;
186            }
187            return fStreamWriter = new XMLStreamWriterImpl(sr, encoding, new PropertyManager(fPropertyManager));
188        }catch(java.io.IOException io){
189            throw new XMLStreamException(io);
190        }
191    }//createXMLStreamWriter(StreamResult,String)
192
193    private static final boolean DEBUG = false;
194
195    /** This flag indicates the change of property. If true,
196     * <code>PropertyManager</code> should be passed when creating
197     * <code>XMLStreamWriterImpl</code> */
198    private boolean fPropertyChanged ;
199}//XMLOutputFactory
200