1 /* |
1 /* |
2 * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. |
2 * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. |
|
3 * @LastModified: Oct 2017 |
3 */ |
4 */ |
4 /* |
5 /* |
5 * Licensed to the Apache Software Foundation (ASF) under one or more |
6 * Licensed to the Apache Software Foundation (ASF) under one or more |
6 * contributor license agreements. See the NOTICE file distributed with |
7 * contributor license agreements. See the NOTICE file distributed with |
7 * this work for additional information regarding copyright ownership. |
8 * this work for additional information regarding copyright ownership. |
38 import com.sun.org.apache.xpath.internal.objects.DTMXRTreeFrag; |
39 import com.sun.org.apache.xpath.internal.objects.DTMXRTreeFrag; |
39 import com.sun.org.apache.xpath.internal.objects.XObject; |
40 import com.sun.org.apache.xpath.internal.objects.XObject; |
40 import com.sun.org.apache.xpath.internal.objects.XString; |
41 import com.sun.org.apache.xpath.internal.objects.XString; |
41 import com.sun.org.apache.xpath.internal.res.XPATHErrorResources; |
42 import com.sun.org.apache.xpath.internal.res.XPATHErrorResources; |
42 import java.lang.reflect.Method; |
43 import java.lang.reflect.Method; |
|
44 import java.util.ArrayList; |
43 import java.util.HashMap; |
45 import java.util.HashMap; |
44 import java.util.Iterator; |
46 import java.util.Iterator; |
|
47 import java.util.List; |
|
48 import java.util.Map; |
45 import java.util.Stack; |
49 import java.util.Stack; |
46 import java.util.Vector; |
|
47 import javax.xml.transform.ErrorListener; |
50 import javax.xml.transform.ErrorListener; |
48 import javax.xml.transform.SourceLocator; |
51 import javax.xml.transform.SourceLocator; |
49 import javax.xml.transform.TransformerException; |
|
50 import javax.xml.transform.URIResolver; |
52 import javax.xml.transform.URIResolver; |
51 import org.xml.sax.XMLReader; |
53 import org.xml.sax.XMLReader; |
52 |
54 |
53 /** |
55 /** |
54 * Default class for the runtime execution context for XPath. |
56 * Default class for the runtime execution context for XPath. |
67 * %REVIEW% I'm using a Vector rather than Stack so we can reuse |
69 * %REVIEW% I'm using a Vector rather than Stack so we can reuse |
68 * the DTMs if the problem occurs multiple times. I'm not sure that's |
70 * the DTMs if the problem occurs multiple times. I'm not sure that's |
69 * really a net win versus discarding the DTM and starting a new one... |
71 * really a net win versus discarding the DTM and starting a new one... |
70 * but the retained RTF DTM will have been tail-pruned so should be small. |
72 * but the retained RTF DTM will have been tail-pruned so should be small. |
71 */ |
73 */ |
72 private Vector m_rtfdtm_stack=null; |
74 private List<DTM> m_rtfdtm_stack=null; |
73 /** Index of currently active RTF DTM in m_rtfdtm_stack */ |
75 /** Index of currently active RTF DTM in m_rtfdtm_stack */ |
74 private int m_which_rtfdtm=-1; |
76 private int m_which_rtfdtm=-1; |
75 |
77 |
76 /** |
78 /** |
77 * Most recent "reusable" DTM for Global Result Tree Fragments. No stack is |
79 * Most recent "reusable" DTM for Global Result Tree Fragments. No stack is |
81 |
83 |
82 /** |
84 /** |
83 * HashMap of cached the DTMXRTreeFrag objects, which are identified by DTM IDs. |
85 * HashMap of cached the DTMXRTreeFrag objects, which are identified by DTM IDs. |
84 * The object are just wrappers for DTMs which are used in XRTreeFrag. |
86 * The object are just wrappers for DTMs which are used in XRTreeFrag. |
85 */ |
87 */ |
86 private HashMap m_DTMXRTreeFrags = null; |
88 private Map<Integer, DTMXRTreeFrag> m_DTMXRTreeFrags = null; |
87 |
89 |
88 /** |
90 /** |
89 * state of the secure processing feature. |
91 * state of the secure processing feature. |
90 */ |
92 */ |
91 private boolean m_isSecureProcessing = false; |
93 private boolean m_isSecureProcessing = false; |
340 * Reset for new run. |
342 * Reset for new run. |
341 */ |
343 */ |
342 public void reset() |
344 public void reset() |
343 { |
345 { |
344 releaseDTMXRTreeFrags(); |
346 releaseDTMXRTreeFrags(); |
345 // These couldn't be disposed of earlier (see comments in release()); zap them now. |
347 // These couldn't be disposed of earlier (see comments in release()); zap them now. |
346 if(m_rtfdtm_stack!=null) |
348 if(m_rtfdtm_stack!=null) { |
347 for (java.util.Enumeration e = m_rtfdtm_stack.elements() ; e.hasMoreElements() ;) |
349 for (DTM dtm : m_rtfdtm_stack) { |
348 m_dtmManager.release((DTM)e.nextElement(), true); |
350 m_dtmManager.release(dtm, true); |
|
351 } |
|
352 } |
349 |
353 |
350 m_rtfdtm_stack=null; // drop our references too |
354 m_rtfdtm_stack=null; // drop our references too |
351 m_which_rtfdtm=-1; |
355 m_which_rtfdtm=-1; |
352 |
356 |
353 if(m_global_rtfdtm!=null) |
357 if(m_global_rtfdtm!=null) |
358 m_dtmManager = DTMManager.newInstance( |
362 m_dtmManager = DTMManager.newInstance( |
359 com.sun.org.apache.xpath.internal.objects.XMLStringFactoryImpl.getFactory() |
363 com.sun.org.apache.xpath.internal.objects.XMLStringFactoryImpl.getFactory() |
360 ); |
364 ); |
361 |
365 |
362 m_saxLocations.removeAllElements(); |
366 m_saxLocations.removeAllElements(); |
363 m_axesIteratorStack.removeAllElements(); |
367 m_axesIteratorStack.removeAllElements(); |
364 m_contextNodeLists.removeAllElements(); |
368 m_contextNodeLists.removeAllElements(); |
365 m_currentExpressionNodes.removeAllElements(); |
369 m_currentExpressionNodes.removeAllElements(); |
366 m_currentNodes.removeAllElements(); |
370 m_currentNodes.removeAllElements(); |
367 m_iteratorRoots.RemoveAllNoClear(); |
371 m_iteratorRoots.RemoveAllNoClear(); |
368 m_predicatePos.removeAllElements(); |
372 m_predicatePos.removeAllElements(); |
369 m_predicateRoots.RemoveAllNoClear(); |
373 m_predicateRoots.RemoveAllNoClear(); |
370 m_prefixResolvers.removeAllElements(); |
374 m_prefixResolvers.removeAllElements(); |
371 |
375 |
372 m_prefixResolvers.push(null); |
376 m_prefixResolvers.push(null); |
373 m_currentNodes.push(DTM.NULL); |
377 m_currentNodes.push(DTM.NULL); |
374 m_currentExpressionNodes.push(DTM.NULL); |
378 m_currentExpressionNodes.push(DTM.NULL); |
375 m_saxLocations.push(null); |
379 m_saxLocations.push(null); |
376 } |
380 } |
377 |
381 |
620 //========================================================== |
624 //========================================================== |
621 |
625 |
622 /** |
626 /** |
623 * The current context node list. |
627 * The current context node list. |
624 */ |
628 */ |
625 private Stack m_contextNodeLists = new Stack(); |
629 private Stack<DTMIterator> m_contextNodeLists = new Stack<>(); |
626 |
630 |
627 public Stack getContextNodeListsStack() { return m_contextNodeLists; } |
631 public Stack<DTMIterator> getContextNodeListsStack() { return m_contextNodeLists; } |
628 public void setContextNodeListsStack(Stack s) { m_contextNodeLists = s; } |
632 public void setContextNodeListsStack(Stack<DTMIterator> s) { m_contextNodeLists = s; } |
629 |
633 |
630 /** |
634 /** |
631 * Get the current context node list. |
635 * Get the current context node list. |
632 * |
636 * |
633 * @return the <a href="http://www.w3.org/TR/xslt#dt-current-node-list">current node list</a>, |
637 * @return the <a href="http://www.w3.org/TR/xslt#dt-current-node-list">current node list</a>, |
923 //========================================================== |
927 //========================================================== |
924 |
928 |
925 /** |
929 /** |
926 * Stack of AxesIterators. |
930 * Stack of AxesIterators. |
927 */ |
931 */ |
928 private Stack m_axesIteratorStack = new Stack(); |
932 private Stack<SubContextList> m_axesIteratorStack = new Stack<>(); |
929 |
933 |
930 public Stack getAxesIteratorStackStacks() { return m_axesIteratorStack; } |
934 public Stack<SubContextList> getAxesIteratorStackStacks() { return m_axesIteratorStack; } |
931 public void setAxesIteratorStackStacks(Stack s) { m_axesIteratorStack = s; } |
935 public void setAxesIteratorStackStacks(Stack<SubContextList> s) { m_axesIteratorStack = s; } |
932 |
936 |
933 /** |
937 /** |
934 * Push a TreeWalker on the stack. |
938 * Push a TreeWalker on the stack. |
935 * |
939 * |
936 * @param iter A sub-context AxesWalker. |
940 * @param iter A sub-context AxesWalker. |
956 * @return the sub-context node list. |
960 * @return the sub-context node list. |
957 * @xsl.usage internal |
961 * @xsl.usage internal |
958 */ |
962 */ |
959 public SubContextList getSubContextList() |
963 public SubContextList getSubContextList() |
960 { |
964 { |
961 return m_axesIteratorStack.isEmpty() |
965 return m_axesIteratorStack.isEmpty() ? null : m_axesIteratorStack.peek(); |
962 ? null : (SubContextList) m_axesIteratorStack.peek(); |
|
963 } |
966 } |
964 |
967 |
965 /** |
968 /** |
966 * Get the <a href="http://www.w3.org/TR/xslt#dt-current-node-list">current node list</a> |
969 * Get the <a href="http://www.w3.org/TR/xslt#dt-current-node-list">current node list</a> |
967 * as defined by the XSLT spec. |
970 * as defined by the XSLT spec. |
970 * @xsl.usage internal |
973 * @xsl.usage internal |
971 */ |
974 */ |
972 |
975 |
973 public com.sun.org.apache.xpath.internal.axes.SubContextList getCurrentNodeList() |
976 public com.sun.org.apache.xpath.internal.axes.SubContextList getCurrentNodeList() |
974 { |
977 { |
975 return m_axesIteratorStack.isEmpty() |
978 return m_axesIteratorStack.isEmpty() ? null : m_axesIteratorStack.get(0); |
976 ? null : (SubContextList) m_axesIteratorStack.elementAt(0); |
|
977 } |
979 } |
978 //========================================================== |
980 //========================================================== |
979 // SECTION: Implementation of ExpressionContext interface |
981 // SECTION: Implementation of ExpressionContext interface |
980 //========================================================== |
982 //========================================================== |
981 |
983 |
1198 // isTreeIncomplete all the way up to DTM, so we wouldn't need to explicitly |
1200 // isTreeIncomplete all the way up to DTM, so we wouldn't need to explicitly |
1199 // specify the subclass here.) |
1201 // specify the subclass here.) |
1200 |
1202 |
1201 if(m_rtfdtm_stack==null) |
1203 if(m_rtfdtm_stack==null) |
1202 { |
1204 { |
1203 m_rtfdtm_stack=new Vector(); |
1205 m_rtfdtm_stack=new ArrayList<>(); |
1204 rtfdtm=(SAX2RTFDTM)m_dtmManager.getDTM(null,true,null,false,false); |
1206 rtfdtm=(SAX2RTFDTM)m_dtmManager.getDTM(null,true,null,false,false); |
1205 m_rtfdtm_stack.addElement(rtfdtm); |
1207 m_rtfdtm_stack.add(rtfdtm); |
1206 ++m_which_rtfdtm; |
1208 ++m_which_rtfdtm; |
1207 } |
1209 } |
1208 else if(m_which_rtfdtm<0) |
1210 else if(m_which_rtfdtm<0) |
1209 { |
1211 { |
1210 rtfdtm=(SAX2RTFDTM)m_rtfdtm_stack.elementAt(++m_which_rtfdtm); |
1212 rtfdtm=(SAX2RTFDTM)m_rtfdtm_stack.get(++m_which_rtfdtm); |
1211 } |
1213 } |
1212 else |
1214 else |
1213 { |
1215 { |
1214 rtfdtm=(SAX2RTFDTM)m_rtfdtm_stack.elementAt(m_which_rtfdtm); |
1216 rtfdtm=(SAX2RTFDTM)m_rtfdtm_stack.get(m_which_rtfdtm); |
1215 |
1217 |
1216 // It might already be under construction -- the classic example would be |
1218 // It might already be under construction -- the classic example would be |
1217 // an xsl:variable which uses xsl:call-template as part of its value. To |
1219 // an xsl:variable which uses xsl:call-template as part of its value. To |
1218 // handle this recursion, we have to start a new RTF DTM, pushing the old |
1220 // handle this recursion, we have to start a new RTF DTM, pushing the old |
1219 // one onto a stack so we can return to it. This is not as uncommon a case |
1221 // one onto a stack so we can return to it. This is not as uncommon a case |
1220 // as we might wish, unfortunately, as some folks insist on coding XSLT |
1222 // as we might wish, unfortunately, as some folks insist on coding XSLT |
1221 // as if it were a procedural language... |
1223 // as if it were a procedural language... |
1222 if(rtfdtm.isTreeIncomplete()) |
1224 if(rtfdtm.isTreeIncomplete()) |
|
1225 { |
|
1226 if(++m_which_rtfdtm < m_rtfdtm_stack.size()) |
|
1227 rtfdtm=(SAX2RTFDTM)m_rtfdtm_stack.get(m_which_rtfdtm); |
|
1228 else |
1223 { |
1229 { |
1224 if(++m_which_rtfdtm < m_rtfdtm_stack.size()) |
1230 rtfdtm=(SAX2RTFDTM)m_dtmManager.getDTM(null,true,null,false,false); |
1225 rtfdtm=(SAX2RTFDTM)m_rtfdtm_stack.elementAt(m_which_rtfdtm); |
1231 m_rtfdtm_stack.add(rtfdtm); |
1226 else |
|
1227 { |
|
1228 rtfdtm=(SAX2RTFDTM)m_dtmManager.getDTM(null,true,null,false,false); |
|
1229 m_rtfdtm_stack.addElement(rtfdtm); |
|
1230 } |
|
1231 } |
1232 } |
|
1233 } |
1232 } |
1234 } |
1233 |
1235 |
1234 return rtfdtm; |
1236 return rtfdtm; |
1235 } |
1237 } |
1236 |
1238 |
1267 |
1269 |
1268 if(m_which_rtfdtm==previous) |
1270 if(m_which_rtfdtm==previous) |
1269 { |
1271 { |
1270 if(previous>=0) // guard against none-active |
1272 if(previous>=0) // guard against none-active |
1271 { |
1273 { |
1272 boolean isEmpty=((SAX2RTFDTM)(m_rtfdtm_stack.elementAt(previous))).popRewindMark(); |
1274 boolean isEmpty=((SAX2RTFDTM)(m_rtfdtm_stack.get(previous))).popRewindMark(); |
1273 } |
1275 } |
1274 } |
1276 } |
1275 else while(m_which_rtfdtm!=previous) |
1277 else while(m_which_rtfdtm!=previous) |
1276 { |
1278 { |
1277 // Empty each DTM before popping, so it's ready for reuse |
1279 // Empty each DTM before popping, so it's ready for reuse |
1278 // _DON'T_ pop the previous, since it's still open (which is why we |
1280 // _DON'T_ pop the previous, since it's still open (which is why we |
1279 // stacked up more of these) and did not receive a mark. |
1281 // stacked up more of these) and did not receive a mark. |
1280 boolean isEmpty=((SAX2RTFDTM)(m_rtfdtm_stack.elementAt(m_which_rtfdtm))).popRewindMark(); |
1282 boolean isEmpty=((SAX2RTFDTM)(m_rtfdtm_stack.get(m_which_rtfdtm))).popRewindMark(); |
1281 --m_which_rtfdtm; |
1283 --m_which_rtfdtm; |
1282 } |
1284 } |
1283 } |
1285 } |
1284 |
1286 |
1285 /** |
1287 /** |
1289 * @param dtmIdentity |
1291 * @param dtmIdentity |
1290 * @return DTMXRTreeFrag |
1292 * @return DTMXRTreeFrag |
1291 */ |
1293 */ |
1292 public DTMXRTreeFrag getDTMXRTreeFrag(int dtmIdentity){ |
1294 public DTMXRTreeFrag getDTMXRTreeFrag(int dtmIdentity){ |
1293 if(m_DTMXRTreeFrags == null){ |
1295 if(m_DTMXRTreeFrags == null){ |
1294 m_DTMXRTreeFrags = new HashMap(); |
1296 m_DTMXRTreeFrags = new HashMap<>(); |
1295 } |
1297 } |
1296 |
1298 |
1297 if(m_DTMXRTreeFrags.containsKey(dtmIdentity)){ |
1299 if(m_DTMXRTreeFrags.containsKey(dtmIdentity)){ |
1298 return (DTMXRTreeFrag)m_DTMXRTreeFrags.get(dtmIdentity); |
1300 return m_DTMXRTreeFrags.get(dtmIdentity); |
1299 }else{ |
1301 }else{ |
1300 final DTMXRTreeFrag frag = new DTMXRTreeFrag(dtmIdentity,this); |
1302 final DTMXRTreeFrag frag = new DTMXRTreeFrag(dtmIdentity,this); |
1301 m_DTMXRTreeFrags.put(dtmIdentity,frag); |
1303 m_DTMXRTreeFrags.put(dtmIdentity,frag); |
1302 return frag ; |
1304 return frag ; |
1303 } |
1305 } |
1309 */ |
1311 */ |
1310 private final void releaseDTMXRTreeFrags(){ |
1312 private final void releaseDTMXRTreeFrags(){ |
1311 if(m_DTMXRTreeFrags == null){ |
1313 if(m_DTMXRTreeFrags == null){ |
1312 return; |
1314 return; |
1313 } |
1315 } |
1314 final Iterator iter = (m_DTMXRTreeFrags.values()).iterator(); |
1316 final Iterator<DTMXRTreeFrag> iter = (m_DTMXRTreeFrags.values()).iterator(); |
1315 while(iter.hasNext()){ |
1317 while(iter.hasNext()){ |
1316 DTMXRTreeFrag frag = (DTMXRTreeFrag)iter.next(); |
1318 DTMXRTreeFrag frag = iter.next(); |
1317 frag.destruct(); |
1319 frag.destruct(); |
1318 iter.remove(); |
1320 iter.remove(); |
1319 } |
1321 } |
1320 m_DTMXRTreeFrags = null; |
1322 m_DTMXRTreeFrags = null; |
1321 } |
1323 } |