1. /*
  2. * Copyright 2001-2004 The Apache Software Foundation.
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. /*
  17. * $Id: TransformerHandlerImpl.java,v 1.18 2004/02/16 22:57:21 minchau Exp $
  18. */
  19. package com.sun.org.apache.xalan.internal.xsltc.trax;
  20. import javax.xml.transform.Result;
  21. import javax.xml.transform.Transformer;
  22. import javax.xml.transform.TransformerException;
  23. import javax.xml.transform.dom.DOMResult;
  24. import javax.xml.transform.sax.TransformerHandler;
  25. import com.sun.org.apache.xalan.internal.xsltc.StripFilter;
  26. import com.sun.org.apache.xalan.internal.xsltc.compiler.util.ErrorMsg;
  27. import com.sun.org.apache.xalan.internal.xsltc.dom.DOMWSFilter;
  28. import com.sun.org.apache.xalan.internal.xsltc.dom.SAXImpl;
  29. import com.sun.org.apache.xalan.internal.xsltc.dom.XSLTCDTMManager;
  30. import com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet;
  31. import com.sun.org.apache.xml.internal.dtm.DTMWSFilter;
  32. import com.sun.org.apache.xml.internal.serializer.SerializationHandler;
  33. import org.xml.sax.Attributes;
  34. import org.xml.sax.ContentHandler;
  35. import org.xml.sax.DTDHandler;
  36. import org.xml.sax.Locator;
  37. import org.xml.sax.SAXException;
  38. import org.xml.sax.ext.DeclHandler;
  39. import org.xml.sax.ext.LexicalHandler;
  40. import org.xml.sax.helpers.DefaultHandler;
  41. /**
  42. * Implementation of a JAXP1.1 TransformerHandler
  43. * @author Morten Jorgensen
  44. */
  45. public class TransformerHandlerImpl implements TransformerHandler, DeclHandler {
  46. private TransformerImpl _transformer;
  47. private AbstractTranslet _translet = null;
  48. private String _systemId;
  49. private SAXImpl _dom = null;
  50. private ContentHandler _handler = null;
  51. private LexicalHandler _lexHandler = null;
  52. private DTDHandler _dtdHandler = null;
  53. private DeclHandler _declHandler = null;
  54. private Result _result = null;
  55. private Locator _locator = null;
  56. private boolean _done = false; // Set in endDocument()
  57. /**
  58. * A flag indicating whether this transformer handler implements the
  59. * identity transform.
  60. */
  61. private boolean _isIdentity = false;
  62. /**
  63. * Cosntructor - pass in reference to a TransformerImpl object
  64. */
  65. public TransformerHandlerImpl(TransformerImpl transformer) {
  66. // Save the reference to the transformer
  67. _transformer = transformer;
  68. if (transformer.isIdentity()) {
  69. // Set initial handler to the empty handler
  70. _handler = new DefaultHandler();
  71. _isIdentity = true;
  72. }
  73. else {
  74. // Get a reference to the translet wrapped inside the transformer
  75. _translet = _transformer.getTranslet();
  76. }
  77. }
  78. /**
  79. * Implements javax.xml.transform.sax.TransformerHandler.getSystemId()
  80. * Get the base ID (URI or system ID) from where relative URLs will be
  81. * resolved.
  82. * @return The systemID that was set with setSystemId(String id)
  83. */
  84. public String getSystemId() {
  85. return _systemId;
  86. }
  87. /**
  88. * Implements javax.xml.transform.sax.TransformerHandler.setSystemId()
  89. * Get the base ID (URI or system ID) from where relative URLs will be
  90. * resolved.
  91. * @param id Base URI for this stylesheet
  92. */
  93. public void setSystemId(String id) {
  94. _systemId = id;
  95. }
  96. /**
  97. * Implements javax.xml.transform.sax.TransformerHandler.getTransformer()
  98. * Get the Transformer associated with this handler, which is needed in
  99. * order to set parameters and output properties.
  100. * @return The Transformer object
  101. */
  102. public Transformer getTransformer() {
  103. return _transformer;
  104. }
  105. /**
  106. * Implements javax.xml.transform.sax.TransformerHandler.setResult()
  107. * Enables the user of the TransformerHandler to set the to set the Result
  108. * for the transformation.
  109. * @param result A Result instance, should not be null
  110. * @throws IllegalArgumentException if result is invalid for some reason
  111. */
  112. public void setResult(Result result) throws IllegalArgumentException {
  113. _result = result;
  114. if (null == result) {
  115. ErrorMsg err = new ErrorMsg(ErrorMsg.ER_RESULT_NULL);
  116. throw new IllegalArgumentException(err.toString()); //"result should not be null");
  117. }
  118. if (_isIdentity) {
  119. try {
  120. // Connect this object with output system directly
  121. SerializationHandler outputHandler =
  122. _transformer.getOutputHandler(result);
  123. _transformer.transferOutputProperties(outputHandler);
  124. _handler = outputHandler;
  125. _lexHandler = outputHandler;
  126. }
  127. catch (TransformerException e) {
  128. _result = null;
  129. }
  130. }
  131. else if (_done) {
  132. // Run the transformation now, if not already done
  133. try {
  134. _transformer.setDOM(_dom);
  135. _transformer.transform(null, _result);
  136. }
  137. catch (TransformerException e) {
  138. // What the hell are we supposed to do with this???
  139. throw new IllegalArgumentException(e.getMessage());
  140. }
  141. }
  142. }
  143. /**
  144. * Implements org.xml.sax.ContentHandler.characters()
  145. * Receive notification of character data.
  146. */
  147. public void characters(char[] ch, int start, int length)
  148. throws SAXException
  149. {
  150. _handler.characters(ch, start, length);
  151. }
  152. /**
  153. * Implements org.xml.sax.ContentHandler.startDocument()
  154. * Receive notification of the beginning of a document.
  155. */
  156. public void startDocument() throws SAXException {
  157. // Make sure setResult() was called before the first SAX event
  158. if (_result == null) {
  159. ErrorMsg err = new ErrorMsg(ErrorMsg.JAXP_SET_RESULT_ERR);
  160. throw new SAXException(err.toString());
  161. }
  162. if (!_isIdentity) {
  163. boolean hasIdCall = (_translet != null) ? _translet.hasIdCall() : false;
  164. XSLTCDTMManager dtmManager = null;
  165. // Create an internal DOM (not W3C) and get SAX2 input handler
  166. try {
  167. dtmManager =
  168. (XSLTCDTMManager)_transformer.getTransformerFactory()
  169. .getDTMManagerClass()
  170. .newInstance();
  171. } catch (Exception e) {
  172. throw new SAXException(e);
  173. }
  174. DTMWSFilter wsFilter;
  175. if (_translet != null && _translet instanceof StripFilter) {
  176. wsFilter = new DOMWSFilter(_translet);
  177. } else {
  178. wsFilter = null;
  179. }
  180. // Construct the DTM using the SAX events that come through
  181. _dom = (SAXImpl)dtmManager.getDTM(null, false, wsFilter, true,
  182. false, hasIdCall);
  183. _handler = _dom.getBuilder();
  184. _lexHandler = (LexicalHandler) _handler;
  185. _dtdHandler = (DTDHandler) _handler;
  186. _declHandler = (DeclHandler) _handler;
  187. // Set document URI
  188. _dom.setDocumentURI(_systemId);
  189. if (_locator != null) {
  190. _handler.setDocumentLocator(_locator);
  191. }
  192. }
  193. // Proxy call
  194. _handler.startDocument();
  195. }
  196. /**
  197. * Implements org.xml.sax.ContentHandler.endDocument()
  198. * Receive notification of the end of a document.
  199. */
  200. public void endDocument() throws SAXException {
  201. // Signal to the DOMBuilder that the document is complete
  202. _handler.endDocument();
  203. if (!_isIdentity) {
  204. // Run the transformation now if we have a reference to a Result object
  205. if (_result != null) {
  206. try {
  207. _transformer.setDOM(_dom);
  208. _transformer.transform(null, _result);
  209. }
  210. catch (TransformerException e) {
  211. throw new SAXException(e);
  212. }
  213. }
  214. // Signal that the internal DOM is built (see 'setResult()').
  215. _done = true;
  216. // Set this DOM as the transformer's DOM
  217. _transformer.setDOM(_dom);
  218. }
  219. if (_isIdentity && _result instanceof DOMResult) {
  220. ((DOMResult)_result).setNode(_transformer.getTransletOutputHandlerFactory().getNode());
  221. }
  222. }
  223. /**
  224. * Implements org.xml.sax.ContentHandler.startElement()
  225. * Receive notification of the beginning of an element.
  226. */
  227. public void startElement(String uri, String localName,
  228. String qname, Attributes attributes)
  229. throws SAXException
  230. {
  231. _handler.startElement(uri, localName, qname, attributes);
  232. }
  233. /**
  234. * Implements org.xml.sax.ContentHandler.endElement()
  235. * Receive notification of the end of an element.
  236. */
  237. public void endElement(String namespaceURI, String localName, String qname)
  238. throws SAXException
  239. {
  240. _handler.endElement(namespaceURI, localName, qname);
  241. }
  242. /**
  243. * Implements org.xml.sax.ContentHandler.processingInstruction()
  244. * Receive notification of a processing instruction.
  245. */
  246. public void processingInstruction(String target, String data)
  247. throws SAXException
  248. {
  249. _handler.processingInstruction(target, data);
  250. }
  251. /**
  252. * Implements org.xml.sax.ext.LexicalHandler.startCDATA()
  253. */
  254. public void startCDATA() throws SAXException {
  255. if (_lexHandler != null) {
  256. _lexHandler.startCDATA();
  257. }
  258. }
  259. /**
  260. * Implements org.xml.sax.ext.LexicalHandler.endCDATA()
  261. */
  262. public void endCDATA() throws SAXException {
  263. if (_lexHandler != null) {
  264. _lexHandler.endCDATA();
  265. }
  266. }
  267. /**
  268. * Implements org.xml.sax.ext.LexicalHandler.comment()
  269. * Receieve notification of a comment
  270. */
  271. public void comment(char[] ch, int start, int length)
  272. throws SAXException
  273. {
  274. if (_lexHandler != null) {
  275. _lexHandler.comment(ch, start, length);
  276. }
  277. }
  278. /**
  279. * Implements org.xml.sax.ContentHandler.ignorableWhitespace()
  280. * Receive notification of ignorable whitespace in element
  281. * content. Similar to characters(char[], int, int).
  282. */
  283. public void ignorableWhitespace(char[] ch, int start, int length)
  284. throws SAXException
  285. {
  286. _handler.ignorableWhitespace(ch, start, length);
  287. }
  288. /**
  289. * Implements org.xml.sax.ContentHandler.setDocumentLocator()
  290. * Receive an object for locating the origin of SAX document events.
  291. */
  292. public void setDocumentLocator(Locator locator) {
  293. _locator = locator;
  294. if (_handler != null) {
  295. _handler.setDocumentLocator(locator);
  296. }
  297. }
  298. /**
  299. * Implements org.xml.sax.ContentHandler.skippedEntity()
  300. * Receive notification of a skipped entity.
  301. */
  302. public void skippedEntity(String name) throws SAXException {
  303. _handler.skippedEntity(name);
  304. }
  305. /**
  306. * Implements org.xml.sax.ContentHandler.startPrefixMapping()
  307. * Begin the scope of a prefix-URI Namespace mapping.
  308. */
  309. public void startPrefixMapping(String prefix, String uri)
  310. throws SAXException {
  311. _handler.startPrefixMapping(prefix, uri);
  312. }
  313. /**
  314. * Implements org.xml.sax.ContentHandler.endPrefixMapping()
  315. * End the scope of a prefix-URI Namespace mapping.
  316. */
  317. public void endPrefixMapping(String prefix) throws SAXException {
  318. _handler.endPrefixMapping(prefix);
  319. }
  320. /**
  321. * Implements org.xml.sax.ext.LexicalHandler.startDTD()
  322. */
  323. public void startDTD(String name, String publicId, String systemId)
  324. throws SAXException
  325. {
  326. if (_lexHandler != null) {
  327. _lexHandler.startDTD(name, publicId, systemId);
  328. }
  329. }
  330. /**
  331. * Implements org.xml.sax.ext.LexicalHandler.endDTD()
  332. */
  333. public void endDTD() throws SAXException {
  334. if (_lexHandler != null) {
  335. _lexHandler.endDTD();
  336. }
  337. }
  338. /**
  339. * Implements org.xml.sax.ext.LexicalHandler.startEntity()
  340. */
  341. public void startEntity(String name) throws SAXException {
  342. if (_lexHandler != null) {
  343. _lexHandler.startEntity(name);
  344. }
  345. }
  346. /**
  347. * Implements org.xml.sax.ext.LexicalHandler.endEntity()
  348. */
  349. public void endEntity(String name) throws SAXException {
  350. if (_lexHandler != null) {
  351. _lexHandler.endEntity(name);
  352. }
  353. }
  354. /**
  355. * Implements org.xml.sax.DTDHandler.unparsedEntityDecl()
  356. */
  357. public void unparsedEntityDecl(String name, String publicId,
  358. String systemId, String notationName) throws SAXException
  359. {
  360. if (_dtdHandler != null) {
  361. _dtdHandler.unparsedEntityDecl(name, publicId, systemId,
  362. notationName);
  363. }
  364. }
  365. /**
  366. * Implements org.xml.sax.DTDHandler.notationDecl()
  367. */
  368. public void notationDecl(String name, String publicId, String systemId)
  369. throws SAXException
  370. {
  371. if (_dtdHandler != null) {
  372. _dtdHandler.notationDecl(name, publicId, systemId);
  373. }
  374. }
  375. /**
  376. * Implements org.xml.sax.ext.DeclHandler.attributeDecl()
  377. */
  378. public void attributeDecl(String eName, String aName, String type,
  379. String valueDefault, String value) throws SAXException
  380. {
  381. if (_declHandler != null) {
  382. _declHandler.attributeDecl(eName, aName, type, valueDefault, value);
  383. }
  384. }
  385. /**
  386. * Implements org.xml.sax.ext.DeclHandler.elementDecl()
  387. */
  388. public void elementDecl(String name, String model)
  389. throws SAXException
  390. {
  391. if (_declHandler != null) {
  392. _declHandler.elementDecl(name, model);
  393. }
  394. }
  395. /**
  396. * Implements org.xml.sax.ext.DeclHandler.externalEntityDecl()
  397. */
  398. public void externalEntityDecl(String name, String publicId, String systemId)
  399. throws SAXException
  400. {
  401. if (_declHandler != null) {
  402. _declHandler.externalEntityDecl(name, publicId, systemId);
  403. }
  404. }
  405. /**
  406. * Implements org.xml.sax.ext.DeclHandler.externalEntityDecl()
  407. */
  408. public void internalEntityDecl(String name, String value)
  409. throws SAXException
  410. {
  411. if (_declHandler != null) {
  412. _declHandler.internalEntityDecl(name, value);
  413. }
  414. }
  415. /** Implementation of the reset() method
  416. *
  417. */
  418. public void reset() {
  419. _systemId = null;
  420. _dom = null;
  421. _handler = null;
  422. _lexHandler = null;
  423. _dtdHandler = null;
  424. _declHandler = null;
  425. _result = null;
  426. _locator = null;
  427. }
  428. }