author | joehw |
Tue, 09 Jul 2013 16:34:52 -0700 | |
changeset 18890 | 25bdeca3173b |
parent 18354 | ce3ebc4a1aec |
child 20967 | d3f1925927e5 |
permissions | -rw-r--r-- |
12005 | 1 |
/* |
2 |
* reserved comment block |
|
3 |
* DO NOT REMOVE OR ALTER! |
|
4 |
*/ |
|
5 |
/* |
|
6 |
* Copyright 1999-2004 The Apache Software Foundation. |
|
7 |
* |
|
8 |
* Licensed under the Apache License, Version 2.0 (the "License"); |
|
9 |
* you may not use this file except in compliance with the License. |
|
10 |
* 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 |
/* |
|
21 |
* $Id: XMLReaderManager.java,v 1.2.4.1 2005/09/15 08:16:02 suresh_emailid Exp $ |
|
22 |
*/ |
|
23 |
package com.sun.org.apache.xml.internal.utils; |
|
24 |
||
17534 | 25 |
import com.sun.org.apache.xalan.internal.XalanConstants; |
12458 | 26 |
import com.sun.org.apache.xalan.internal.utils.FactoryImpl; |
17534 | 27 |
import com.sun.org.apache.xalan.internal.utils.SecuritySupport; |
12005 | 28 |
import java.util.HashMap; |
17534 | 29 |
import javax.xml.XMLConstants; |
12005 | 30 |
import javax.xml.parsers.FactoryConfigurationError; |
31 |
import javax.xml.parsers.ParserConfigurationException; |
|
32 |
import javax.xml.parsers.SAXParserFactory; |
|
17534 | 33 |
import org.xml.sax.SAXException; |
12005 | 34 |
import org.xml.sax.XMLReader; |
35 |
import org.xml.sax.helpers.XMLReaderFactory; |
|
36 |
||
37 |
/** |
|
38 |
* Creates XMLReader objects and caches them for re-use. |
|
39 |
* This class follows the singleton pattern. |
|
40 |
*/ |
|
41 |
public class XMLReaderManager { |
|
42 |
||
43 |
private static final String NAMESPACES_FEATURE = |
|
44 |
"http://xml.org/sax/features/namespaces"; |
|
45 |
private static final String NAMESPACE_PREFIXES_FEATURE = |
|
46 |
"http://xml.org/sax/features/namespace-prefixes"; |
|
47 |
private static final XMLReaderManager m_singletonManager = |
|
48 |
new XMLReaderManager(); |
|
49 |
private static final String property = "org.xml.sax.driver"; |
|
50 |
/** |
|
51 |
* Parser factory to be used to construct XMLReader objects |
|
52 |
*/ |
|
53 |
private static SAXParserFactory m_parserFactory; |
|
54 |
||
55 |
/** |
|
56 |
* Cache of XMLReader objects |
|
57 |
*/ |
|
58 |
private ThreadLocal m_readers; |
|
59 |
||
60 |
/** |
|
61 |
* Keeps track of whether an XMLReader object is in use. |
|
62 |
*/ |
|
63 |
private HashMap m_inUse; |
|
64 |
||
12458 | 65 |
private boolean m_useServicesMechanism = true; |
17534 | 66 |
/** |
67 |
* protocols allowed for external DTD references in source file and/or stylesheet. |
|
68 |
*/ |
|
69 |
private String _accessExternalDTD = XalanConstants.EXTERNAL_ACCESS_DEFAULT; |
|
70 |
||
12005 | 71 |
/** |
72 |
* Hidden constructor |
|
73 |
*/ |
|
74 |
private XMLReaderManager() { |
|
75 |
} |
|
76 |
||
77 |
/** |
|
78 |
* Retrieves the singleton reader manager |
|
79 |
*/ |
|
12458 | 80 |
public static XMLReaderManager getInstance(boolean useServicesMechanism) { |
81 |
m_singletonManager.setServicesMechnism(useServicesMechanism); |
|
12005 | 82 |
return m_singletonManager; |
83 |
} |
|
84 |
||
85 |
/** |
|
86 |
* Retrieves a cached XMLReader for this thread, or creates a new |
|
87 |
* XMLReader, if the existing reader is in use. When the caller no |
|
88 |
* longer needs the reader, it must release it with a call to |
|
89 |
* {@link #releaseXMLReader}. |
|
90 |
*/ |
|
91 |
public synchronized XMLReader getXMLReader() throws SAXException { |
|
92 |
XMLReader reader; |
|
93 |
||
94 |
if (m_readers == null) { |
|
95 |
// When the m_readers.get() method is called for the first time |
|
96 |
// on a thread, a new XMLReader will automatically be created. |
|
97 |
m_readers = new ThreadLocal(); |
|
98 |
} |
|
99 |
||
100 |
if (m_inUse == null) { |
|
101 |
m_inUse = new HashMap(); |
|
102 |
} |
|
103 |
||
104 |
// If the cached reader for this thread is in use, construct a new |
|
105 |
// one; otherwise, return the cached reader unless it isn't an |
|
106 |
// instance of the class set in the 'org.xml.sax.driver' property |
|
107 |
reader = (XMLReader) m_readers.get(); |
|
108 |
boolean threadHasReader = (reader != null); |
|
12458 | 109 |
String factory = SecuritySupport.getSystemProperty(property); |
12005 | 110 |
if (threadHasReader && m_inUse.get(reader) != Boolean.TRUE && |
111 |
( factory == null || reader.getClass().getName().equals(factory))) { |
|
112 |
m_inUse.put(reader, Boolean.TRUE); |
|
113 |
} else { |
|
114 |
try { |
|
115 |
try { |
|
116 |
// According to JAXP 1.2 specification, if a SAXSource |
|
117 |
// is created using a SAX InputSource the Transformer or |
|
118 |
// TransformerFactory creates a reader via the |
|
119 |
// XMLReaderFactory if setXMLReader is not used |
|
120 |
reader = XMLReaderFactory.createXMLReader(); |
|
121 |
||
122 |
} catch (Exception e) { |
|
123 |
try { |
|
124 |
// If unable to create an instance, let's try to use |
|
125 |
// the XMLReader from JAXP |
|
126 |
if (m_parserFactory == null) { |
|
12458 | 127 |
m_parserFactory = FactoryImpl.getSAXFactory(m_useServicesMechanism); |
12005 | 128 |
m_parserFactory.setNamespaceAware(true); |
129 |
} |
|
130 |
||
131 |
reader = m_parserFactory.newSAXParser().getXMLReader(); |
|
132 |
} catch (ParserConfigurationException pce) { |
|
133 |
throw pce; // pass along pce |
|
134 |
} |
|
135 |
} |
|
136 |
try { |
|
137 |
reader.setFeature(NAMESPACES_FEATURE, true); |
|
138 |
reader.setFeature(NAMESPACE_PREFIXES_FEATURE, false); |
|
139 |
} catch (SAXException se) { |
|
140 |
// Try to carry on if we've got a parser that |
|
141 |
// doesn't know about namespace prefixes. |
|
142 |
} |
|
143 |
} catch (ParserConfigurationException ex) { |
|
144 |
throw new SAXException(ex); |
|
145 |
} catch (FactoryConfigurationError ex1) { |
|
146 |
throw new SAXException(ex1.toString()); |
|
147 |
} catch (NoSuchMethodError ex2) { |
|
148 |
} catch (AbstractMethodError ame) { |
|
149 |
} |
|
150 |
||
151 |
// Cache the XMLReader if this is the first time we've created |
|
152 |
// a reader for this thread. |
|
153 |
if (!threadHasReader) { |
|
154 |
m_readers.set(reader); |
|
155 |
m_inUse.put(reader, Boolean.TRUE); |
|
156 |
} |
|
157 |
} |
|
158 |
||
18890
25bdeca3173b
8016648: FEATURE_SECURE_PROCESSING set to true or false causes SAXParseException to be thrown
joehw
parents:
18354
diff
changeset
|
159 |
try { |
25bdeca3173b
8016648: FEATURE_SECURE_PROCESSING set to true or false causes SAXParseException to be thrown
joehw
parents:
18354
diff
changeset
|
160 |
//reader is cached, but this property might have been reset |
25bdeca3173b
8016648: FEATURE_SECURE_PROCESSING set to true or false causes SAXParseException to be thrown
joehw
parents:
18354
diff
changeset
|
161 |
reader.setProperty(XMLConstants.ACCESS_EXTERNAL_DTD, _accessExternalDTD); |
25bdeca3173b
8016648: FEATURE_SECURE_PROCESSING set to true or false causes SAXParseException to be thrown
joehw
parents:
18354
diff
changeset
|
162 |
} catch (SAXException se) { |
25bdeca3173b
8016648: FEATURE_SECURE_PROCESSING set to true or false causes SAXParseException to be thrown
joehw
parents:
18354
diff
changeset
|
163 |
System.err.println("Warning: " + reader.getClass().getName() + ": " |
25bdeca3173b
8016648: FEATURE_SECURE_PROCESSING set to true or false causes SAXParseException to be thrown
joehw
parents:
18354
diff
changeset
|
164 |
+ se.getMessage()); |
25bdeca3173b
8016648: FEATURE_SECURE_PROCESSING set to true or false causes SAXParseException to be thrown
joehw
parents:
18354
diff
changeset
|
165 |
} |
25bdeca3173b
8016648: FEATURE_SECURE_PROCESSING set to true or false causes SAXParseException to be thrown
joehw
parents:
18354
diff
changeset
|
166 |
|
12005 | 167 |
return reader; |
168 |
} |
|
169 |
||
170 |
/** |
|
171 |
* Mark the cached XMLReader as available. If the reader was not |
|
172 |
* actually in the cache, do nothing. |
|
173 |
* |
|
174 |
* @param reader The XMLReader that's being released. |
|
175 |
*/ |
|
176 |
public synchronized void releaseXMLReader(XMLReader reader) { |
|
177 |
// If the reader that's being released is the cached reader |
|
178 |
// for this thread, remove it from the m_isUse list. |
|
179 |
if (m_readers.get() == reader && reader != null) { |
|
180 |
m_inUse.remove(reader); |
|
181 |
} |
|
182 |
} |
|
12458 | 183 |
/** |
184 |
* Return the state of the services mechanism feature. |
|
185 |
*/ |
|
186 |
public boolean useServicesMechnism() { |
|
187 |
return m_useServicesMechanism; |
|
188 |
} |
|
189 |
||
190 |
/** |
|
191 |
* Set the state of the services mechanism feature. |
|
192 |
*/ |
|
193 |
public void setServicesMechnism(boolean flag) { |
|
194 |
m_useServicesMechanism = flag; |
|
195 |
} |
|
196 |
||
17534 | 197 |
/** |
198 |
* Get property value |
|
199 |
*/ |
|
200 |
public String getProperty(String name) { |
|
201 |
if (name.equals(XMLConstants.ACCESS_EXTERNAL_DTD)) { |
|
202 |
return _accessExternalDTD; |
|
203 |
} |
|
204 |
return null; |
|
205 |
} |
|
206 |
||
207 |
/** |
|
208 |
* Set property. |
|
209 |
*/ |
|
210 |
public void setProperty(String name, String value) { |
|
211 |
if (name.equals(XMLConstants.ACCESS_EXTERNAL_DTD)) { |
|
212 |
_accessExternalDTD = (String)value; |
|
213 |
} |
|
214 |
} |
|
12005 | 215 |
} |