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.InputStream;
29import java.io.Reader;
30
31import javax.xml.stream.*;
32import javax.xml.stream.util.XMLEventAllocator ;
33import javax.xml.transform.Source;
34import javax.xml.transform.stream.StreamSource;
35import com.sun.org.apache.xerces.internal.xni.parser.XMLInputSource;
36import com.sun.org.apache.xerces.internal.impl.XMLStreamReaderImpl;
37import com.sun.org.apache.xerces.internal.impl.PropertyManager;
38import com.sun.org.apache.xerces.internal.impl.XMLStreamFilterImpl;
39import com.sun.org.apache.xerces.internal.impl.Constants;
40
41/** Factory Implementation for XMLInputFactory.
42 * @author Neeraj Bajaj Sun Microsystems
43 * @author K.Venugopal Sun Microsystems
44 */
45
46//xxx: Should we be reusing the XMLInputSource object
47public class XMLInputFactoryImpl extends javax.xml.stream.XMLInputFactory {
48
49
50    //List of supported properties and default values.
51    private PropertyManager fPropertyManager = new PropertyManager(PropertyManager.CONTEXT_READER) ;
52    private static final boolean DEBUG = false;
53
54    //Maintain a reference to last reader instantiated.
55    private XMLStreamReaderImpl fTempReader = null ;
56
57    boolean fPropertyChanged = false;
58    //no reader reuse by default
59    boolean fReuseInstance = false;
60
61    /** Creates a new instance of ZephryParserFactory */
62    public XMLInputFactoryImpl() {
63
64    }
65
66    void initEventReader(){
67        fPropertyChanged = true;
68    }
69
70    /**
71     * @param inputstream
72     * @throws XMLStreamException
73     * @return
74     */
75    public XMLEventReader createXMLEventReader(InputStream inputstream) throws XMLStreamException {
76        initEventReader();
77        //delegate everything to XMLStreamReader
78        return new XMLEventReaderImpl(createXMLStreamReader(inputstream));
79    }
80
81    public XMLEventReader createXMLEventReader(Reader reader) throws XMLStreamException {
82        initEventReader();
83        //delegate everything to XMLStreamReader
84        return new XMLEventReaderImpl(createXMLStreamReader(reader));
85    }
86
87    public XMLEventReader createXMLEventReader(Source source) throws XMLStreamException {
88        initEventReader();
89        //delegate everything to XMLStreamReader
90        return new XMLEventReaderImpl(createXMLStreamReader(source));
91    }
92
93    public XMLEventReader createXMLEventReader(String systemId, InputStream inputstream) throws XMLStreamException {
94        initEventReader();
95        //delegate everything to XMLStreamReader
96        return new XMLEventReaderImpl(createXMLStreamReader(systemId, inputstream));
97    }
98
99    public XMLEventReader createXMLEventReader(java.io.InputStream stream, String encoding) throws XMLStreamException {
100        initEventReader();
101        //delegate everything to XMLStreamReader
102        return new XMLEventReaderImpl(createXMLStreamReader(stream, encoding));
103    }
104
105    public XMLEventReader createXMLEventReader(String systemId, Reader reader) throws XMLStreamException {
106        initEventReader();
107        //delegate everything to XMLStreamReader
108        return new XMLEventReaderImpl(createXMLStreamReader(systemId, reader));
109    }
110
111    /** Create a new XMLEventReader from an XMLStreamReader.  After being used
112     * to construct the XMLEventReader instance returned from this method
113     * the XMLStreamReader must not be used.
114     * @param reader the XMLStreamReader to read from (may not be modified)
115     * @return a new XMLEventReader
116     * @throws XMLStreamException
117     */
118    public XMLEventReader createXMLEventReader(XMLStreamReader reader) throws XMLStreamException {
119
120        //xxx: what do we do now -- instance is passed from the application
121        //probably we should check if the state is at the start document,
122        //eventreader call to next() should return START_DOCUMENT and
123        //then delegate every call to underlying streamReader
124        return new XMLEventReaderImpl(reader) ;
125    }
126
127    public XMLStreamReader createXMLStreamReader(InputStream inputstream) throws XMLStreamException {
128        XMLInputSource inputSource = new XMLInputSource(null, null, null, inputstream, null);
129        return getXMLStreamReaderImpl(inputSource);
130    }
131
132    public XMLStreamReader createXMLStreamReader(Reader reader) throws XMLStreamException {
133        XMLInputSource inputSource = new XMLInputSource(null, null, null, reader, null);
134        return getXMLStreamReaderImpl(inputSource);
135    }
136
137    public XMLStreamReader createXMLStreamReader(String systemId, Reader reader) throws XMLStreamException {
138        XMLInputSource inputSource = new XMLInputSource(null,systemId,null,reader,null);
139        return getXMLStreamReaderImpl(inputSource);
140    }
141
142    public XMLStreamReader createXMLStreamReader(Source source) throws XMLStreamException {
143        return new XMLStreamReaderImpl(jaxpSourcetoXMLInputSource(source),
144                new PropertyManager(fPropertyManager));
145    }
146
147    public XMLStreamReader createXMLStreamReader(String systemId, InputStream inputstream) throws XMLStreamException {
148        XMLInputSource inputSource = new XMLInputSource(null,systemId,null,inputstream,null);
149        return getXMLStreamReaderImpl(inputSource);
150    }
151
152
153    public XMLStreamReader createXMLStreamReader(InputStream inputstream, String encoding) throws XMLStreamException {
154        XMLInputSource inputSource = new XMLInputSource(null,null,null,inputstream,encoding);
155        return getXMLStreamReaderImpl(inputSource);
156    }
157
158    public XMLEventAllocator getEventAllocator() {
159        return (XMLEventAllocator)getProperty(XMLInputFactory.ALLOCATOR);
160    }
161
162    public XMLReporter getXMLReporter() {
163        return (XMLReporter)fPropertyManager.getProperty(XMLInputFactory.REPORTER);
164    }
165
166    public XMLResolver getXMLResolver() {
167        Object object = fPropertyManager.getProperty(XMLInputFactory.RESOLVER);
168        return (XMLResolver)object;
169        //return (XMLResolver)fPropertyManager.getProperty(XMLInputFactory.RESOLVER);
170    }
171
172    public void setXMLReporter(XMLReporter xmlreporter) {
173        fPropertyManager.setProperty(XMLInputFactory.REPORTER, xmlreporter);
174    }
175
176    public void setXMLResolver(XMLResolver xmlresolver) {
177        fPropertyManager.setProperty(XMLInputFactory.RESOLVER, xmlresolver);
178    }
179
180    /** Create a filtered event reader that wraps the filter around the event reader
181     * @param reader the event reader to wrap
182     * @param filter the filter to apply to the event reader
183     * @throws XMLStreamException
184     */
185    public XMLEventReader createFilteredReader(XMLEventReader reader, EventFilter filter) throws XMLStreamException {
186        return new EventFilterSupport(reader, filter);
187    }
188
189    /** Create a filtered reader that wraps the filter around the reader
190     * @param reader the reader to filter
191     * @param filter the filter to apply to the reader
192     * @throws XMLStreamException
193     */
194    public XMLStreamReader createFilteredReader(XMLStreamReader reader, StreamFilter filter) throws XMLStreamException {
195        if( reader != null && filter != null )
196            return new XMLStreamFilterImpl(reader,filter);
197
198        return null;
199    }
200
201
202
203    /** Get the value of a feature/property from the underlying implementation
204     * @param name The name of the property (may not be null)
205     * @return The value of the property
206     * @throws IllegalArgumentException if the property is not supported
207     */
208    public Object getProperty(java.lang.String name) throws java.lang.IllegalArgumentException {
209        if(name == null){
210            throw new IllegalArgumentException("Property not supported");
211        }
212        if(fPropertyManager.containsProperty(name))
213            return fPropertyManager.getProperty(name);
214        throw new IllegalArgumentException("Property not supported");
215    }
216
217    /** Query the set of fProperties that this factory supports.
218     *
219     * @param name The name of the property (may not be null)
220     * @return true if the property is supported and false otherwise
221     */
222    public boolean isPropertySupported(String name) {
223        if(name == null)
224            return false ;
225        else
226            return fPropertyManager.containsProperty(name);
227    }
228
229    /** Set a user defined event allocator for events
230     * @param allocator the user defined allocator
231     */
232    public void setEventAllocator(XMLEventAllocator allocator) {
233        fPropertyManager.setProperty(XMLInputFactory.ALLOCATOR, allocator);
234    }
235
236    /** Allows the user to set specific feature/property on the underlying implementation. The underlying implementation
237     * is not required to support every setting of every property in the specification and may use IllegalArgumentException
238     * to signal that an unsupported property may not be set with the specified value.
239     * @param name The name of the property (may not be null)
240     * @param value The value of the property
241     * @throws java.lang.IllegalArgumentException if the property is not supported
242     */
243    public void setProperty(java.lang.String name, Object value) throws java.lang.IllegalArgumentException {
244
245        if(name == null || value == null || !fPropertyManager.containsProperty(name) ){
246            throw new IllegalArgumentException("Property "+name+" is not supported");
247        }
248        if(name == Constants.REUSE_INSTANCE || name.equals(Constants.REUSE_INSTANCE)){
249            fReuseInstance = ((Boolean)value).booleanValue();
250            if(DEBUG)System.out.println("fReuseInstance is set to " + fReuseInstance);
251        }else{//for any other property set the flag
252            //REVISIT: Even in this case instance can be reused, by passing PropertyManager
253            fPropertyChanged = true;
254        }
255        fPropertyManager.setProperty(name,value);
256    }
257
258    XMLStreamReader getXMLStreamReaderImpl(XMLInputSource inputSource) throws javax.xml.stream.XMLStreamException{
259        //1. if the temp reader is null -- create the instance and return
260        if(fTempReader == null){
261            fPropertyChanged = false;
262            return fTempReader = new XMLStreamReaderImpl(inputSource,
263                    new PropertyManager(fPropertyManager));
264        }
265        //if factory is configured to reuse the instance & this instance can be reused
266        //& the setProperty() hasn't been called
267        if(fReuseInstance && fTempReader.canReuse() && !fPropertyChanged){
268            if(DEBUG)System.out.println("Reusing the instance");
269            //we can make setInputSource() call reset() and this way there wont be two function calls
270            fTempReader.reset();
271            fTempReader.setInputSource(inputSource);
272            fPropertyChanged = false;
273            return fTempReader;
274        }else{
275            fPropertyChanged = false;
276            //just return the new instance.. note that we are not setting  fTempReader to the newly created instance
277            return fTempReader = new XMLStreamReaderImpl(inputSource,
278                    new PropertyManager(fPropertyManager));
279        }
280    }
281
282    XMLInputSource jaxpSourcetoXMLInputSource(Source source){
283         if(source instanceof StreamSource){
284             StreamSource stSource = (StreamSource)source;
285             String systemId = stSource.getSystemId();
286             String publicId = stSource.getPublicId();
287             InputStream istream = stSource.getInputStream();
288             Reader reader = stSource.getReader();
289
290             if(istream != null){
291                 return new XMLInputSource(publicId, systemId, null, istream, null);
292             }
293             else if(reader != null){
294                 return new XMLInputSource(publicId, systemId,null, reader, null);
295             }else{
296                 return new XMLInputSource(publicId, systemId, null, false);
297             }
298         }
299
300         throw new UnsupportedOperationException("Cannot create " +
301                "XMLStreamReader or XMLEventReader from a " +
302                source.getClass().getName());
303    }
304
305}//XMLInputFactoryImpl
306