PageRenderTime 36ms CodeModel.GetById 12ms RepoModel.GetById 0ms app.codeStats 0ms

/bundles/plugins-trunk/XML/xml/parser/EntityMgrFixerConfiguration.java

#
Java | 362 lines | 256 code | 50 blank | 56 comment | 43 complexity | f13df38f733fd7157c93c29e41336b52 MD5 | raw file
Possible License(s): BSD-3-Clause, AGPL-1.0, Apache-2.0, LGPL-2.0, LGPL-3.0, GPL-2.0, CC-BY-SA-3.0, LGPL-2.1, GPL-3.0, MPL-2.0-no-copyleft-exception, IPL-1.0
  1. /*
  2. * EntityMgrFixerConfiguration.java - work-around for XERCESJ-1205
  3. * :tabSize=8:indentSize=8:noTabs=false:
  4. * :folding=explicit:collapseFolds=1:
  5. *
  6. * copyright (C) 2011 Eric Le Lay
  7. *
  8. * The XML plugin is licensed under the GNU General Public License, with
  9. * the following exception:
  10. *
  11. * "Permission is granted to link this code with software released under
  12. * the Apache license version 1.1, for example used by the Xerces XML
  13. * parser package."
  14. */
  15. package xml.parser;
  16. import java.io.IOException;
  17. import org.apache.xerces.impl.XMLEntityManager;
  18. import org.apache.xerces.impl.dtd.DTDGrammar;
  19. import org.apache.xerces.impl.dtd.XMLDTDDescription;
  20. import org.apache.xerces.impl.dtd.XMLEntityDecl;
  21. import org.apache.xerces.parsers.XIncludeAwareParserConfiguration;
  22. import org.apache.xerces.util.SymbolTable;
  23. import org.apache.xerces.xni.Augmentations;
  24. import org.apache.xerces.xni.NamespaceContext;
  25. import org.apache.xerces.xni.QName;
  26. import org.apache.xerces.xni.XMLAttributes;
  27. import org.apache.xerces.xni.XMLDocumentHandler;
  28. import org.apache.xerces.xni.XMLLocator;
  29. import org.apache.xerces.xni.XMLResourceIdentifier;
  30. import org.apache.xerces.xni.XMLString;
  31. import org.apache.xerces.xni.XNIException;
  32. import org.apache.xerces.xni.grammars.XMLGrammarPool;
  33. import org.apache.xerces.xni.parser.XMLComponent;
  34. import org.apache.xerces.xni.parser.XMLComponentManager;
  35. import org.apache.xerces.xni.parser.XMLConfigurationException;
  36. import org.apache.xerces.xni.parser.XMLDocumentFilter;
  37. import org.apache.xerces.xni.parser.XMLDocumentSource;
  38. import org.gjt.sp.util.Log;
  39. /**
  40. * fix for bug #3393297 - "XMLPlugin doesn't find DTD upon second parse".
  41. * work-around for Xerces bug [XERCESJ-1205]
  42. * "Entity resolution does not work with DTD grammar caching resolved". code is
  43. * brittle (depends on the implementation in XIncludeAwareParserConfiguration
  44. * and the like).
  45. *
  46. * @see http://sourceforge.net/tracker/?func=detail&aid=3393297&group_id=588&atid=565475
  47. * @see https://issues.apache.org/jira/browse/XERCESJ-1205
  48. * @author kerik-sf
  49. * @version $Id: EntityMgrFixerConfiguration.java 20051 2011-10-05 16:36:13Z kerik-sf $
  50. * */
  51. class EntityMgrFixerConfiguration extends XIncludeAwareParserConfiguration {
  52. protected EntityMgrFixer fEntityMgrFixer;
  53. private class EntityMgrFixer implements XMLComponent, XMLDocumentFilter {
  54. // instance variables
  55. // for XMLDocumentFilter
  56. protected XMLDocumentHandler fDocumentHandler;
  57. protected XMLDocumentSource fDocumentSource;
  58. protected XMLLocator fDocLocation;
  59. /**
  60. * save locator for future use and forward.
  61. * */
  62. @Override
  63. public void startDocument(XMLLocator locator, String encoding,
  64. NamespaceContext namespaceContext, Augmentations augs)
  65. throws XNIException {
  66. // save XMLLocator for future use
  67. fDocLocation = locator;
  68. if (fDocumentHandler != null) {
  69. fDocumentHandler.startDocument(locator, encoding,
  70. namespaceContext, augs);
  71. }
  72. }
  73. /**
  74. * copy external entities from a cached grammar to the entity manager.
  75. * relies on being called when the grammar has been loaded (see
  76. * XMLDTDValidator, line 769)
  77. **/
  78. @Override
  79. public void doctypeDecl(String rootElement, String publicId,
  80. String systemId, Augmentations augs) throws XNIException {
  81. if (fDocumentHandler != null) {
  82. fDocumentHandler.doctypeDecl(rootElement, publicId, systemId,
  83. augs);
  84. }
  85. if (fValidationManager.isCachedDTD()) {
  86. // duplicates code from XMLDTDValidator to retrieve the grammar
  87. String eid = null;
  88. try {
  89. eid = XMLEntityManager.expandSystemId(systemId,
  90. fDocLocation.getExpandedSystemId(), false);
  91. } catch (java.io.IOException e) {
  92. }
  93. XMLDTDDescription grammarDesc = new XMLDTDDescription(publicId,
  94. systemId, fDocLocation.getExpandedSystemId(), eid,
  95. rootElement);
  96. DTDGrammar grammar = (DTDGrammar) fGrammarPool
  97. .retrieveGrammar(grammarDesc);
  98. // grammar is cached so it should be retrieved
  99. assert (grammar != null);
  100. // now copy to the entityManager
  101. ((EntityMgrFixerConfiguration.MyEntityManager) fEntityManager)
  102. .copyEntitiesFromDTD(grammar);
  103. }
  104. }
  105. /* {{{ forward-only */
  106. @Override
  107. public void xmlDecl(String version, String encoding, String standalone,
  108. Augmentations augs) throws XNIException {
  109. if (fDocumentHandler != null) {
  110. fDocumentHandler.xmlDecl(version, encoding, standalone, augs);
  111. }
  112. }
  113. @Override
  114. public void comment(XMLString text, Augmentations augs)
  115. throws XNIException {
  116. if (fDocumentHandler != null) {
  117. fDocumentHandler.comment(text, augs);
  118. }
  119. }
  120. @Override
  121. public void processingInstruction(String target, XMLString data,
  122. Augmentations augs) throws XNIException {
  123. if (fDocumentHandler != null) {
  124. fDocumentHandler.processingInstruction(target, data, augs);
  125. }
  126. }
  127. @Override
  128. public void startElement(QName element, XMLAttributes attributes,
  129. Augmentations augs) throws XNIException {
  130. if (fDocumentHandler != null) {
  131. fDocumentHandler.startElement(element, attributes, augs);
  132. }
  133. }
  134. @Override
  135. public void emptyElement(QName element, XMLAttributes attributes,
  136. Augmentations augs) throws XNIException {
  137. if (fDocumentHandler != null) {
  138. fDocumentHandler.emptyElement(element, attributes, augs);
  139. }
  140. }
  141. @Override
  142. public void startGeneralEntity(String name,
  143. XMLResourceIdentifier identifier, String encoding,
  144. Augmentations augs) throws XNIException {
  145. if (fDocumentHandler != null) {
  146. fDocumentHandler.startGeneralEntity(name, identifier, encoding,
  147. augs);
  148. }
  149. }
  150. @Override
  151. public void textDecl(String version, String encoding, Augmentations augs)
  152. throws XNIException {
  153. if (fDocumentHandler != null) {
  154. fDocumentHandler.textDecl(version, encoding, augs);
  155. }
  156. }
  157. @Override
  158. public void endGeneralEntity(String name, Augmentations augs)
  159. throws XNIException {
  160. if (fDocumentHandler != null) {
  161. fDocumentHandler.endGeneralEntity(name, augs);
  162. }
  163. }
  164. @Override
  165. public void characters(XMLString text, Augmentations augs)
  166. throws XNIException {
  167. if (fDocumentHandler != null) {
  168. fDocumentHandler.characters(text, augs);
  169. }
  170. }
  171. @Override
  172. public void ignorableWhitespace(XMLString text, Augmentations augs)
  173. throws XNIException {
  174. if (fDocumentHandler != null) {
  175. fDocumentHandler.ignorableWhitespace(text, augs);
  176. }
  177. }
  178. @Override
  179. public void endElement(QName element, Augmentations augs)
  180. throws XNIException {
  181. if (fDocumentHandler != null) {
  182. fDocumentHandler.endElement(element, augs);
  183. }
  184. }
  185. @Override
  186. public void startCDATA(Augmentations augs) throws XNIException {
  187. if (fDocumentHandler != null) {
  188. fDocumentHandler.startCDATA(augs);
  189. }
  190. }
  191. @Override
  192. public void endCDATA(Augmentations augs) throws XNIException {
  193. if (fDocumentHandler != null) {
  194. fDocumentHandler.endCDATA(augs);
  195. }
  196. }
  197. @Override
  198. public void endDocument(Augmentations augs) throws XNIException {
  199. if (fDocumentHandler != null) {
  200. fDocumentHandler.endDocument(augs);
  201. }
  202. }
  203. /* }}} */
  204. /* {{{ piping */
  205. @Override
  206. public void setDocumentSource(XMLDocumentSource source) {
  207. fDocumentSource = source;
  208. }
  209. @Override
  210. public XMLDocumentSource getDocumentSource() {
  211. return fDocumentSource;
  212. }
  213. @Override
  214. public void setDocumentHandler(XMLDocumentHandler handler) {
  215. fDocumentHandler = handler;
  216. }
  217. @Override
  218. public XMLDocumentHandler getDocumentHandler() {
  219. return fDocumentHandler;
  220. }
  221. /* }}} */
  222. /* {{{ unimplemented stubs */
  223. @Override
  224. public void reset(XMLComponentManager componentManager)
  225. throws XMLConfigurationException {
  226. }
  227. @Override
  228. public String[] getRecognizedFeatures() {
  229. return null;
  230. }
  231. @Override
  232. public void setFeature(String featureId, boolean state)
  233. throws XMLConfigurationException {
  234. }
  235. @Override
  236. public String[] getRecognizedProperties() {
  237. return null;
  238. }
  239. @Override
  240. public void setProperty(String propertyId, Object value)
  241. throws XMLConfigurationException {
  242. }
  243. @Override
  244. public Boolean getFeatureDefault(String featureId) {
  245. return null;
  246. }
  247. @Override
  248. public Object getPropertyDefault(String propertyId) {
  249. return null;
  250. }
  251. /* }}} */
  252. }
  253. /**
  254. * add a method to copy external entities from a cached grammar to
  255. * XMLEntityManager. fInExternalSubset is what requires subclassing.
  256. **/
  257. private static class MyEntityManager extends XMLEntityManager {
  258. private void copyEntitiesFromDTD(DTDGrammar grammar) {
  259. XMLEntityDecl entityDecl = new XMLEntityDecl();
  260. for (int i = 0; grammar.getEntityDecl(i, entityDecl); i++) {
  261. fInExternalSubset = entityDecl.inExternal;
  262. // see test_data/dtd/sample2.xml for an example why internal
  263. // entities should not be added
  264. if (entityDecl.inExternal) {
  265. if (entityDecl.publicId != null
  266. || entityDecl.systemId != null) {
  267. try {
  268. addExternalEntity(entityDecl.name,
  269. entityDecl.publicId, entityDecl.systemId,
  270. entityDecl.baseSystemId);
  271. } catch (IOException e) {
  272. Log.log(Log.WARNING,
  273. EntityMgrFixerConfiguration.class,
  274. "error adding external entity from cached grammar ("
  275. + entityDecl + ")", e);
  276. }
  277. } else {
  278. addInternalEntity(entityDecl.name, entityDecl.value);
  279. }
  280. }
  281. }
  282. fInExternalSubset = false;
  283. }
  284. }
  285. public EntityMgrFixerConfiguration(SymbolTable symbolTable,
  286. XMLGrammarPool cachedGrammarPool) {
  287. super(symbolTable, cachedGrammarPool);
  288. // override fEntityManager with my own
  289. // XXX: code is brittle, check with XML11Configuration() for any other
  290. // use of fEntityManager on new release
  291. fCommonComponents.remove(fEntityManager);
  292. fEntityManager = new MyEntityManager();
  293. fProperties.put(ENTITY_MANAGER, fEntityManager);
  294. addCommonComponent(fEntityManager);
  295. fErrorReporter.setDocumentLocator(fEntityManager.getEntityScanner());
  296. }
  297. @Override
  298. protected void configurePipeline() {
  299. super.configurePipeline();
  300. fEntityMgrFixer = new EntityMgrFixer();
  301. // insert the EntityMgrFixer in the end of the pipeline
  302. XMLDocumentSource prev = fLastComponent;
  303. fLastComponent = fEntityMgrFixer;
  304. XMLDocumentHandler next = prev.getDocumentHandler();
  305. prev.setDocumentHandler(fEntityMgrFixer);
  306. fEntityMgrFixer.setDocumentSource(prev);
  307. if (next != null) {
  308. fEntityMgrFixer.setDocumentHandler(next);
  309. next.setDocumentSource(fEntityMgrFixer);
  310. }
  311. }
  312. }