1. /*
  2. * Copyright 1999-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: DTMManager.java,v 1.18 2004/02/23 10:29:36 aruny Exp $
  18. */
  19. package com.sun.org.apache.xml.internal.dtm;
  20. import com.sun.org.apache.xml.internal.res.XMLErrorResources;
  21. import com.sun.org.apache.xml.internal.res.XMLMessages;
  22. import com.sun.org.apache.xml.internal.utils.PrefixResolver;
  23. import com.sun.org.apache.xml.internal.utils.XMLStringFactory;
  24. /**
  25. * A DTMManager instance can be used to create DTM and
  26. * DTMIterator objects, and manage the DTM objects in the system.
  27. *
  28. * <p>The system property that determines which Factory implementation
  29. * to create is named "com.sun.org.apache.xml.internal.utils.DTMFactory". This
  30. * property names a concrete subclass of the DTMFactory abstract
  31. * class. If the property is not defined, a platform default is be used.</p>
  32. *
  33. * <p>An instance of this class <emph>must</emph> be safe to use across
  34. * thread instances. It is expected that a client will create a single instance
  35. * of a DTMManager to use across multiple threads. This will allow sharing
  36. * of DTMs across multiple processes.</p>
  37. *
  38. * <p>Note: this class is incomplete right now. It will be pretty much
  39. * modeled after javax.xml.transform.TransformerFactory in terms of its
  40. * factory support.</p>
  41. *
  42. * <p>State: In progress!!</p>
  43. */
  44. public abstract class DTMManager
  45. {
  46. /** The default property name to load the manager. */
  47. private static final String defaultPropName =
  48. "com.sun.org.apache.xml.internal.dtm.DTMManager";
  49. /** The default class name to use as the manager. */
  50. private static String defaultClassName =
  51. "com.sun.org.apache.xml.internal.dtm.ref.DTMManagerDefault";
  52. /**
  53. * Factory for creating XMLString objects.
  54. * %TBD% Make this set by the caller.
  55. */
  56. protected XMLStringFactory m_xsf = null;
  57. /**
  58. * Default constructor is protected on purpose.
  59. */
  60. protected DTMManager(){}
  61. /**
  62. * Get the XMLStringFactory used for the DTMs.
  63. *
  64. *
  65. * @return a valid XMLStringFactory object, or null if it hasn't been set yet.
  66. */
  67. public XMLStringFactory getXMLStringFactory()
  68. {
  69. return m_xsf;
  70. }
  71. /**
  72. * Set the XMLStringFactory used for the DTMs.
  73. *
  74. *
  75. * @param xsf a valid XMLStringFactory object, should not be null.
  76. */
  77. public void setXMLStringFactory(XMLStringFactory xsf)
  78. {
  79. m_xsf = xsf;
  80. }
  81. /**
  82. * Obtain a new instance of a <code>DTMManager</code>.
  83. * This static method creates a new factory instance
  84. * This method uses the following ordered lookup procedure to determine
  85. * the <code>DTMManager</code> implementation class to
  86. * load:
  87. * <ul>
  88. * <li>
  89. * Use the <code>com.sun.org.apache.xml.internal.dtm.DTMManager</code> system
  90. * property.
  91. * </li>
  92. * <li>
  93. * Use the JAVA_HOME(the parent directory where jdk is
  94. * installed)/lib/xalan.properties for a property file that contains the
  95. * name of the implementation class keyed on the same value as the
  96. * system property defined above.
  97. * </li>
  98. * <li>
  99. * Use the Services API (as detailed in the JAR specification), if
  100. * available, to determine the classname. The Services API will look
  101. * for a classname in the file
  102. * <code>META-INF/services/com.sun.org.apache.xml.internal.dtm.DTMManager</code>
  103. * in jars available to the runtime.
  104. * </li>
  105. * <li>
  106. * Use the default <code>DTMManager</code> classname, which is
  107. * <code>com.sun.org.apache.xml.internal.dtm.ref.DTMManagerDefault</code>.
  108. * </li>
  109. * </ul>
  110. *
  111. * Once an application has obtained a reference to a <code>
  112. * DTMManager</code> it can use the factory to configure
  113. * and obtain parser instances.
  114. *
  115. * @return new DTMManager instance, never null.
  116. *
  117. * @throws DTMConfigurationException
  118. * if the implementation is not available or cannot be instantiated.
  119. */
  120. public static DTMManager newInstance(XMLStringFactory xsf)
  121. throws DTMConfigurationException
  122. {
  123. DTMManager factoryImpl = null;
  124. try
  125. {
  126. factoryImpl = (DTMManager) ObjectFactory
  127. .createObject(defaultPropName, defaultClassName);
  128. }
  129. catch (ObjectFactory.ConfigurationError e)
  130. {
  131. throw new DTMConfigurationException(XMLMessages.createXMLMessage(
  132. XMLErrorResources.ER_NO_DEFAULT_IMPL, null), e.getException());
  133. //"No default implementation found");
  134. }
  135. if (factoryImpl == null)
  136. {
  137. throw new DTMConfigurationException(XMLMessages.createXMLMessage(
  138. XMLErrorResources.ER_NO_DEFAULT_IMPL, null));
  139. //"No default implementation found");
  140. }
  141. factoryImpl.setXMLStringFactory(xsf);
  142. return factoryImpl;
  143. }
  144. /**
  145. * Get an instance of a DTM, loaded with the content from the
  146. * specified source. If the unique flag is true, a new instance will
  147. * always be returned. Otherwise it is up to the DTMManager to return a
  148. * new instance or an instance that it already created and may be being used
  149. * by someone else.
  150. *
  151. * (More parameters may eventually need to be added for error handling
  152. * and entity resolution, and to better control selection of implementations.)
  153. *
  154. * @param source the specification of the source object, which may be null,
  155. * in which case it is assumed that node construction will take
  156. * by some other means.
  157. * @param unique true if the returned DTM must be unique, probably because it
  158. * is going to be mutated.
  159. * @param whiteSpaceFilter Enables filtering of whitespace nodes, and may
  160. * be null.
  161. * @param incremental true if the DTM should be built incrementally, if
  162. * possible.
  163. * @param doIndexing true if the caller considers it worth it to use
  164. * indexing schemes.
  165. *
  166. * @return a non-null DTM reference.
  167. */
  168. public abstract DTM getDTM(javax.xml.transform.Source source,
  169. boolean unique, DTMWSFilter whiteSpaceFilter,
  170. boolean incremental, boolean doIndexing);
  171. /**
  172. * Get the instance of DTM that "owns" a node handle.
  173. *
  174. * @param nodeHandle the nodeHandle.
  175. *
  176. * @return a non-null DTM reference.
  177. */
  178. public abstract DTM getDTM(int nodeHandle);
  179. /**
  180. * Given a W3C DOM node, try and return a DTM handle.
  181. * Note: calling this may be non-optimal.
  182. *
  183. * @param node Non-null reference to a DOM node.
  184. *
  185. * @return a valid DTM handle.
  186. */
  187. public abstract int getDTMHandleFromNode(org.w3c.dom.Node node);
  188. /**
  189. * Creates a DTM representing an empty <code>DocumentFragment</code> object.
  190. * @return a non-null DTM reference.
  191. */
  192. public abstract DTM createDocumentFragment();
  193. /**
  194. * Release a DTM either to a lru pool, or completely remove reference.
  195. * DTMs without system IDs are always hard deleted.
  196. * State: experimental.
  197. *
  198. * @param dtm The DTM to be released.
  199. * @param shouldHardDelete True if the DTM should be removed no matter what.
  200. * @return true if the DTM was removed, false if it was put back in a lru pool.
  201. */
  202. public abstract boolean release(DTM dtm, boolean shouldHardDelete);
  203. /**
  204. * Create a new <code>DTMIterator</code> based on an XPath
  205. * <a href="http://www.w3.org/TR/xpath#NT-LocationPath>LocationPath</a> or
  206. * a <a href="http://www.w3.org/TR/xpath#NT-UnionExpr">UnionExpr</a>.
  207. *
  208. * @param xpathCompiler ??? Somehow we need to pass in a subpart of the
  209. * expression. I hate to do this with strings, since the larger expression
  210. * has already been parsed.
  211. *
  212. * @param pos The position in the expression.
  213. * @return The newly created <code>DTMIterator</code>.
  214. */
  215. public abstract DTMIterator createDTMIterator(Object xpathCompiler,
  216. int pos);
  217. /**
  218. * Create a new <code>DTMIterator</code> based on an XPath
  219. * <a href="http://www.w3.org/TR/xpath#NT-LocationPath>LocationPath</a> or
  220. * a <a href="http://www.w3.org/TR/xpath#NT-UnionExpr">UnionExpr</a>.
  221. *
  222. * @param xpathString Must be a valid string expressing a
  223. * <a href="http://www.w3.org/TR/xpath#NT-LocationPath>LocationPath</a> or
  224. * a <a href="http://www.w3.org/TR/xpath#NT-UnionExpr">UnionExpr</a>.
  225. *
  226. * @param presolver An object that can resolve prefixes to namespace URLs.
  227. *
  228. * @return The newly created <code>DTMIterator</code>.
  229. */
  230. public abstract DTMIterator createDTMIterator(String xpathString,
  231. PrefixResolver presolver);
  232. /**
  233. * Create a new <code>DTMIterator</code> based only on a whatToShow
  234. * and a DTMFilter. The traversal semantics are defined as the
  235. * descendant access.
  236. * <p>
  237. * Note that DTMIterators may not be an exact match to DOM
  238. * NodeIterators. They are initialized and used in much the same way
  239. * as a NodeIterator, but their response to document mutation is not
  240. * currently defined.
  241. *
  242. * @param whatToShow This flag specifies which node types may appear in
  243. * the logical view of the tree presented by the iterator. See the
  244. * description of <code>NodeFilter</code> for the set of possible
  245. * <code>SHOW_</code> values.These flags can be combined using
  246. * <code>OR</code>.
  247. * @param filter The <code>NodeFilter</code> to be used with this
  248. * <code>DTMFilter</code>, or <code>null</code> to indicate no filter.
  249. * @param entityReferenceExpansion The value of this flag determines
  250. * whether entity reference nodes are expanded.
  251. *
  252. * @return The newly created <code>DTMIterator</code>.
  253. */
  254. public abstract DTMIterator createDTMIterator(int whatToShow,
  255. DTMFilter filter, boolean entityReferenceExpansion);
  256. /**
  257. * Create a new <code>DTMIterator</code> that holds exactly one node.
  258. *
  259. * @param node The node handle that the DTMIterator will iterate to.
  260. *
  261. * @return The newly created <code>DTMIterator</code>.
  262. */
  263. public abstract DTMIterator createDTMIterator(int node);
  264. /* Flag indicating whether an incremental transform is desired */
  265. public static boolean m_incremental = false;
  266. /**
  267. * Set a flag indicating whether an incremental transform is desired
  268. * @param incremental boolean to use to set m_incremental.
  269. *
  270. */
  271. public synchronized static boolean getIncremental()
  272. {
  273. return m_incremental;
  274. }
  275. /**
  276. * Set a flag indicating whether an incremental transform is desired
  277. * @param incremental boolean to use to set m_incremental.
  278. *
  279. */
  280. public synchronized static void setIncremental(boolean incremental)
  281. {
  282. m_incremental = incremental;
  283. }
  284. // -------------------- private methods --------------------
  285. /**
  286. * Temp debug code - this will be removed after we test everything
  287. */
  288. private static boolean debug;
  289. static
  290. {
  291. try
  292. {
  293. debug = System.getProperty("dtm.debug") != null;
  294. }
  295. catch (SecurityException ex){}
  296. }
  297. /** This value, set at compile time, controls how many bits of the
  298. * DTM node identifier numbers are used to identify a node within a
  299. * document, and thus sets the maximum number of nodes per
  300. * document. The remaining bits are used to identify the DTM
  301. * document which contains this node.
  302. *
  303. * If you change IDENT_DTM_NODE_BITS, be sure to rebuild _ALL_ the
  304. * files which use it... including the IDKey testcases.
  305. *
  306. * (FuncGenerateKey currently uses the node identifier directly and
  307. * thus is affected when this changes. The IDKEY results will still be
  308. * _correct_ (presuming no other breakage), but simple equality
  309. * comparison against the previous "golden" files will probably
  310. * complain.)
  311. * */
  312. public static final int IDENT_DTM_NODE_BITS = 16;
  313. /** When this bitmask is ANDed with a DTM node handle number, the result
  314. * is the low bits of the node's index number within that DTM. To obtain
  315. * the high bits, add the DTM ID portion's offset as assigned in the DTM
  316. * Manager.
  317. */
  318. public static final int IDENT_NODE_DEFAULT = (1<<IDENT_DTM_NODE_BITS)-1;
  319. /** When this bitmask is ANDed with a DTM node handle number, the result
  320. * is the DTM's document identity number.
  321. */
  322. public static final int IDENT_DTM_DEFAULT = ~IDENT_NODE_DEFAULT;
  323. /** This is the maximum number of DTMs available. The highest DTM is
  324. * one less than this.
  325. */
  326. public static final int IDENT_MAX_DTMS = (IDENT_DTM_DEFAULT >>> IDENT_DTM_NODE_BITS) + 1;
  327. /**
  328. * %TBD% Doc
  329. *
  330. * NEEDSDOC @param dtm
  331. *
  332. * NEEDSDOC ($objectName$) @return
  333. */
  334. public abstract int getDTMIdentity(DTM dtm);
  335. /**
  336. * %TBD% Doc
  337. *
  338. * NEEDSDOC ($objectName$) @return
  339. */
  340. public int getDTMIdentityMask()
  341. {
  342. return IDENT_DTM_DEFAULT;
  343. }
  344. /**
  345. * %TBD% Doc
  346. *
  347. * NEEDSDOC ($objectName$) @return
  348. */
  349. public int getNodeIdentityMask()
  350. {
  351. return IDENT_NODE_DEFAULT;
  352. }
  353. }