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: SmartTransformerFactoryImpl.java 468653 2006-10-28 07:07:05Z minchau $
020     */
021    
022    
023    package org.apache.xalan.xsltc.trax;
024    
025    import javax.xml.XMLConstants;
026    import javax.xml.transform.ErrorListener;
027    import javax.xml.transform.Source;
028    import javax.xml.transform.Templates;
029    import javax.xml.transform.Transformer;
030    import javax.xml.transform.TransformerConfigurationException;
031    import javax.xml.transform.TransformerException;
032    import javax.xml.transform.URIResolver;
033    import javax.xml.transform.dom.DOMResult;
034    import javax.xml.transform.dom.DOMSource;
035    import javax.xml.transform.sax.SAXResult;
036    import javax.xml.transform.sax.SAXSource;
037    import javax.xml.transform.sax.SAXTransformerFactory;
038    import javax.xml.transform.sax.TemplatesHandler;
039    import javax.xml.transform.sax.TransformerHandler;
040    import javax.xml.transform.stream.StreamResult;
041    import javax.xml.transform.stream.StreamSource;
042    
043    import org.apache.xalan.xsltc.compiler.util.ErrorMsg;
044    import org.xml.sax.XMLFilter;
045    
046    /**
047     * Implementation of a transformer factory that uses an XSLTC 
048     * transformer factory for the creation of Templates objects
049     * and uses the Xalan processor transformer factory for the
050     * creation of Transformer objects.  
051     * @author G. Todd Miller 
052     */
053    public class SmartTransformerFactoryImpl extends SAXTransformerFactory 
054    {
055        /**
056         * <p>Name of class as a constant to use for debugging.</p>
057         */
058        private static final String CLASS_NAME = "SmartTransformerFactoryImpl";
059    
060        private SAXTransformerFactory _xsltcFactory = null;
061        private SAXTransformerFactory _xalanFactory = null;
062        private SAXTransformerFactory _currFactory = null;
063        private ErrorListener      _errorlistener = null;
064        private URIResolver        _uriresolver = null;
065        
066        /**
067         * <p>State of secure processing feature.</p>
068         */
069        private boolean featureSecureProcessing = false;
070    
071        /**
072         * implementation of the SmartTransformerFactory. This factory
073         * uses org.apache.xalan.xsltc.trax.TransformerFactory
074         * to return Templates objects; and uses 
075         * org.apache.xalan.processor.TransformerFactory
076         * to return Transformer objects.  
077         */
078        public SmartTransformerFactoryImpl() { }
079    
080        private void createXSLTCTransformerFactory() {
081            _xsltcFactory = new TransformerFactoryImpl();
082            _currFactory = _xsltcFactory;
083        }
084    
085        private void createXalanTransformerFactory() {
086            final String xalanMessage =
087                "org.apache.xalan.xsltc.trax.SmartTransformerFactoryImpl "+
088                "could not create an "+
089                "org.apache.xalan.processor.TransformerFactoryImpl.";
090            // try to create instance of Xalan factory...   
091            try {
092                Class xalanFactClass = ObjectFactory.findProviderClass(
093                    "org.apache.xalan.processor.TransformerFactoryImpl",
094                    ObjectFactory.findClassLoader(), true);
095                _xalanFactory = (SAXTransformerFactory)
096                    xalanFactClass.newInstance();
097            } 
098            catch (ClassNotFoundException e) {
099                System.err.println(xalanMessage);
100            }
101            catch (InstantiationException e) {
102                System.err.println(xalanMessage);
103            }
104            catch (IllegalAccessException e) {
105                System.err.println(xalanMessage);
106            }
107            _currFactory = _xalanFactory;
108        }
109    
110        public void setErrorListener(ErrorListener listener) 
111            throws IllegalArgumentException 
112        {
113            _errorlistener = listener;
114        }
115    
116        public ErrorListener getErrorListener() { 
117            return _errorlistener;
118        }
119    
120        public Object getAttribute(String name) 
121            throws IllegalArgumentException 
122        {
123            // GTM: NB: 'debug' should change to something more unique... 
124            if ((name.equals("translet-name")) || (name.equals("debug"))) { 
125                if (_xsltcFactory == null) {
126                    createXSLTCTransformerFactory();
127                }
128                return _xsltcFactory.getAttribute(name); 
129            }
130            else {
131                if (_xalanFactory == null) {
132                    createXalanTransformerFactory();
133                } 
134                return _xalanFactory.getAttribute(name);
135            }
136        }
137    
138        public void setAttribute(String name, Object value) 
139            throws IllegalArgumentException { 
140            // GTM: NB: 'debug' should change to something more unique... 
141            if ((name.equals("translet-name")) || (name.equals("debug"))) { 
142                if (_xsltcFactory == null) {
143                    createXSLTCTransformerFactory();
144                }
145                _xsltcFactory.setAttribute(name, value); 
146            }
147            else {
148                if (_xalanFactory == null) {
149                    createXalanTransformerFactory();
150                } 
151                _xalanFactory.setAttribute(name, value);
152            }
153        }
154    
155        /**
156         * <p>Set a feature for this <code>SmartTransformerFactory</code> and <code>Transformer</code>s
157         * or <code>Template</code>s created by this factory.</p>
158         * 
159         * <p>
160         * Feature names are fully qualified {@link java.net.URI}s.
161         * Implementations may define their own features.
162         * An {@link TransformerConfigurationException} is thrown if this <code>TransformerFactory</code> or the
163         * <code>Transformer</code>s or <code>Template</code>s it creates cannot support the feature.
164         * It is possible for an <code>TransformerFactory</code> to expose a feature value but be unable to change its state.
165         * </p>
166         * 
167         * <p>See {@link javax.xml.transform.TransformerFactory} for full documentation of specific features.</p>
168         * 
169         * @param name Feature name.
170         * @param value Is feature state <code>true</code> or <code>false</code>.
171         *  
172         * @throws TransformerConfigurationException if this <code>TransformerFactory</code>
173         *   or the <code>Transformer</code>s or <code>Template</code>s it creates cannot support this feature.
174         * @throws NullPointerException If the <code>name</code> parameter is null.
175         */
176        public void setFeature(String name, boolean value)
177            throws TransformerConfigurationException {
178    
179            // feature name cannot be null
180            if (name == null) {
181                ErrorMsg err = new ErrorMsg(ErrorMsg.JAXP_SET_FEATURE_NULL_NAME);
182                throw new NullPointerException(err.toString());
183            }
184            // secure processing?
185            else if (name.equals(XMLConstants.FEATURE_SECURE_PROCESSING)) {
186                featureSecureProcessing = value;            
187                // all done processing feature
188                return;
189            }
190            else {  
191                // unknown feature
192                ErrorMsg err = new ErrorMsg(ErrorMsg.JAXP_UNSUPPORTED_FEATURE, name);
193                throw new TransformerConfigurationException(err.toString());
194            }
195        }
196    
197        /**
198         * javax.xml.transform.sax.TransformerFactory implementation.
199         * Look up the value of a feature (to see if it is supported).
200         * This method must be updated as the various methods and features of this
201         * class are implemented.
202         *
203         * @param name The feature name
204         * @return 'true' if feature is supported, 'false' if not
205         */
206        public boolean getFeature(String name) { 
207            // All supported features should be listed here
208            String[] features = {
209                DOMSource.FEATURE,
210                DOMResult.FEATURE,
211                SAXSource.FEATURE,
212                SAXResult.FEATURE,
213                StreamSource.FEATURE,
214                StreamResult.FEATURE
215            };
216                    
217            // feature name cannot be null
218            if (name == null) {
219                ErrorMsg err = new ErrorMsg(ErrorMsg.JAXP_GET_FEATURE_NULL_NAME);
220                throw new NullPointerException(err.toString());
221            }
222    
223            // Inefficient, but it really does not matter in a function like this
224            for (int i = 0; i < features.length; i++) {
225                if (name.equals(features[i]))
226                    return true;
227            }
228    
229            // secure processing?
230            if (name.equals(XMLConstants.FEATURE_SECURE_PROCESSING)) {
231                return featureSecureProcessing;
232            }
233    
234            // unknown feature
235            return false;
236        }
237    
238        public URIResolver getURIResolver() {
239            return _uriresolver; 
240        } 
241    
242        public void setURIResolver(URIResolver resolver) {
243            _uriresolver = resolver;
244        }
245    
246        public Source getAssociatedStylesheet(Source source, String media,
247                                              String title, String charset)
248            throws TransformerConfigurationException 
249        {
250            if (_currFactory == null) {
251                createXSLTCTransformerFactory();
252            }
253            return _currFactory.getAssociatedStylesheet(source, media,
254                    title, charset);
255        }
256    
257        /**
258         * Create a Transformer object that copies the input document to the
259         * result. Uses the org.apache.xalan.processor.TransformerFactory.
260         * @return A Transformer object.
261         */
262        public Transformer newTransformer()
263            throws TransformerConfigurationException 
264        {
265            if (_xalanFactory == null) {
266                createXalanTransformerFactory();
267            }
268            if (_errorlistener != null) {
269                _xalanFactory.setErrorListener(_errorlistener);         
270            }
271            if (_uriresolver != null) {
272                _xalanFactory.setURIResolver(_uriresolver);
273            }
274            _currFactory = _xalanFactory;    
275            return _currFactory.newTransformer(); 
276        }
277    
278        /**
279         * Create a Transformer object that from the input stylesheet 
280         * Uses the org.apache.xalan.processor.TransformerFactory.
281         * @param source the stylesheet.
282         * @return A Transformer object.
283         */
284        public Transformer newTransformer(Source source) throws
285            TransformerConfigurationException 
286        {
287            if (_xalanFactory == null) {
288                createXalanTransformerFactory();
289            }
290            if (_errorlistener != null) {
291                _xalanFactory.setErrorListener(_errorlistener);         
292            }
293            if (_uriresolver != null) {
294                _xalanFactory.setURIResolver(_uriresolver);
295            }
296            _currFactory = _xalanFactory;    
297            return _currFactory.newTransformer(source); 
298        }
299    
300        /**
301         * Create a Templates object that from the input stylesheet 
302         * Uses the org.apache.xalan.xsltc.trax.TransformerFactory.
303         * @param source the stylesheet.
304         * @return A Templates object.
305         */
306        public Templates newTemplates(Source source)
307            throws TransformerConfigurationException 
308        {
309            if (_xsltcFactory == null) {
310                createXSLTCTransformerFactory();
311            }
312            if (_errorlistener != null) {
313                _xsltcFactory.setErrorListener(_errorlistener);         
314            }
315            if (_uriresolver != null) {
316                _xsltcFactory.setURIResolver(_uriresolver);
317            }
318            _currFactory = _xsltcFactory;    
319            return _currFactory.newTemplates(source); 
320        }
321    
322        /**
323         * Get a TemplatesHandler object that can process SAX ContentHandler
324         * events into a Templates object. Uses the
325         * org.apache.xalan.xsltc.trax.TransformerFactory.
326         */
327        public TemplatesHandler newTemplatesHandler() 
328            throws TransformerConfigurationException 
329        {
330            if (_xsltcFactory == null) {
331                createXSLTCTransformerFactory();
332            }
333            if (_errorlistener != null) {
334                _xsltcFactory.setErrorListener(_errorlistener);         
335            }
336            if (_uriresolver != null) {
337                _xsltcFactory.setURIResolver(_uriresolver);
338            }
339            return _xsltcFactory.newTemplatesHandler();
340        }
341    
342        /**
343         * Get a TransformerHandler object that can process SAX ContentHandler
344         * events based on a copy transformer. 
345         * Uses org.apache.xalan.processor.TransformerFactory. 
346         */
347        public TransformerHandler newTransformerHandler() 
348            throws TransformerConfigurationException 
349        {
350            if (_xalanFactory == null) {
351                createXalanTransformerFactory();
352            }
353            if (_errorlistener != null) {
354                _xalanFactory.setErrorListener(_errorlistener);         
355            }
356            if (_uriresolver != null) {
357                _xalanFactory.setURIResolver(_uriresolver);
358            }
359            return _xalanFactory.newTransformerHandler(); 
360        }
361    
362        /**
363         * Get a TransformerHandler object that can process SAX ContentHandler
364         * events based on a transformer specified by the stylesheet Source. 
365         * Uses org.apache.xalan.processor.TransformerFactory. 
366         */
367        public TransformerHandler newTransformerHandler(Source src) 
368            throws TransformerConfigurationException 
369        {
370            if (_xalanFactory == null) {
371                createXalanTransformerFactory();
372            }
373            if (_errorlistener != null) {
374                _xalanFactory.setErrorListener(_errorlistener);         
375            }
376            if (_uriresolver != null) {
377                _xalanFactory.setURIResolver(_uriresolver);
378            }
379            return _xalanFactory.newTransformerHandler(src); 
380        }
381    
382    
383        /**
384         * Get a TransformerHandler object that can process SAX ContentHandler
385         * events based on a transformer specified by the stylesheet Source. 
386         * Uses org.apache.xalan.xsltc.trax.TransformerFactory. 
387         */
388        public TransformerHandler newTransformerHandler(Templates templates) 
389            throws TransformerConfigurationException  
390        {
391            if (_xsltcFactory == null) {
392                createXSLTCTransformerFactory();
393            }
394            if (_errorlistener != null) {
395                _xsltcFactory.setErrorListener(_errorlistener);         
396            }
397            if (_uriresolver != null) {
398                _xsltcFactory.setURIResolver(_uriresolver);
399            }
400            return _xsltcFactory.newTransformerHandler(templates);
401        }
402    
403    
404        /**
405         * Create an XMLFilter that uses the given source as the
406         * transformation instructions. Uses
407         * org.apache.xalan.xsltc.trax.TransformerFactory.
408         */
409        public XMLFilter newXMLFilter(Source src) 
410            throws TransformerConfigurationException {
411            if (_xsltcFactory == null) {
412                createXSLTCTransformerFactory();
413            }
414            if (_errorlistener != null) {
415                _xsltcFactory.setErrorListener(_errorlistener);         
416            }
417            if (_uriresolver != null) {
418                _xsltcFactory.setURIResolver(_uriresolver);
419            }
420            Templates templates = _xsltcFactory.newTemplates(src);
421            if (templates == null ) return null;
422            return newXMLFilter(templates); 
423        }
424    
425        /*
426         * Create an XMLFilter that uses the given source as the
427         * transformation instructions. Uses
428         * org.apache.xalan.xsltc.trax.TransformerFactory.
429         */
430        public XMLFilter newXMLFilter(Templates templates) 
431            throws TransformerConfigurationException {
432            try {
433                return new org.apache.xalan.xsltc.trax.TrAXFilter(templates);
434            }
435            catch(TransformerConfigurationException e1) {
436                if (_xsltcFactory == null) {
437                    createXSLTCTransformerFactory();
438                }
439                ErrorListener errorListener = _xsltcFactory.getErrorListener();
440                if(errorListener != null) {
441                    try {
442                        errorListener.fatalError(e1);
443                        return null;
444                    }
445                    catch( TransformerException e2) {
446                        new TransformerConfigurationException(e2);
447                    }
448                }
449                throw e1;
450            }
451        }
452    }