KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > sun > org > apache > xml > internal > security > utils > CachedXPathFuncHereAPI


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 package com.sun.org.apache.xml.internal.security.utils;
18
19
20
21 import com.sun.org.apache.xml.internal.dtm.DTMManager;
22 import com.sun.org.apache.xml.internal.security.transforms.implementations.FuncHere;
23 import com.sun.org.apache.xml.internal.security.transforms.implementations.FuncHereContext;
24 import com.sun.org.apache.xml.internal.utils.PrefixResolver;
25 import com.sun.org.apache.xml.internal.utils.PrefixResolverDefault;
26 import com.sun.org.apache.xpath.internal.CachedXPathAPI;
27 import com.sun.org.apache.xpath.internal.Expression;
28 import com.sun.org.apache.xpath.internal.XPath;
29 import com.sun.org.apache.xpath.internal.XPathContext;
30 import com.sun.org.apache.xpath.internal.compiler.FunctionTable;
31 import com.sun.org.apache.xpath.internal.objects.XObject;
32 import org.w3c.dom.*;
33 import org.w3c.dom.traversal.NodeIterator;
34
35 import javax.xml.transform.ErrorListener JavaDoc;
36 import javax.xml.transform.SourceLocator JavaDoc;
37 import javax.xml.transform.TransformerException JavaDoc;
38 import java.lang.reflect.Constructor JavaDoc;
39 import java.lang.reflect.Method JavaDoc;
40 import java.lang.reflect.Modifier JavaDoc;
41
42 /**
43  *
44  * @author $Author: dims $
45  */

46 public class CachedXPathFuncHereAPI {
47
48     static java.util.logging.Logger JavaDoc log =
49            java.util.logging.Logger.getLogger(CachedXPathFuncHereAPI.class.getName());
50    /**
51     * XPathContext, and thus DTMManager and DTMs, persists through multiple
52     * calls to this object.
53     */

54    FuncHereContext _funcHereContext = null;
55
56    /** Field _dtmManager */
57    DTMManager _dtmManager = null;
58
59    XPathContext _context = null;
60
61    String JavaDoc xpathStr=null;
62
63    XPath xpath=null;
64
65    static FunctionTable _funcTable = null;
66
67     static {
68         fixupFunctionTable();
69     }
70
71    /**
72     * Method getFuncHereContext
73     * @return the context for this object
74     *
75     */

76    public FuncHereContext getFuncHereContext() {
77       return this._funcHereContext;
78    }
79
80    /**
81     * Constructor CachedXPathFuncHereAPI
82     *
83     */

84    private CachedXPathFuncHereAPI() {}
85
86    /**
87     * Constructor CachedXPathFuncHereAPI
88     *
89     * @param existingXPathContext
90     */

91    public CachedXPathFuncHereAPI(XPathContext existingXPathContext) {
92       this._dtmManager = existingXPathContext.getDTMManager();
93       this._context=existingXPathContext;
94    }
95
96    /**
97     * Constructor CachedXPathFuncHereAPI
98     *
99     * @param previouslyUsed
100     */

101    public CachedXPathFuncHereAPI(CachedXPathAPI previouslyUsed) {
102       this._dtmManager = previouslyUsed.getXPathContext().getDTMManager();
103       this._context=previouslyUsed.getXPathContext();
104    }
105
106    /**
107     * Use an XPath string to select a single node. XPath namespace
108     * prefixes are resolved from the context node, which may not
109     * be what you want (see the next method).
110     *
111     * @param contextNode The node to start searching from.
112     * @param xpathnode A Node containing a valid XPath string.
113     * @return The first node found that matches the XPath, or null.
114     *
115     * @throws TransformerException
116     */

117    public Node selectSingleNode(Node contextNode, Node xpathnode)
118            throws TransformerException JavaDoc {
119       return selectSingleNode(contextNode, xpathnode, contextNode);
120    }
121
122    /**
123     * Use an XPath string to select a single node.
124     * XPath namespace prefixes are resolved from the namespaceNode.
125     *
126     * @param contextNode The node to start searching from.
127     * @param xpathnode
128     * @param namespaceNode The node from which prefixes in the XPath will be resolved to namespaces.
129     * @return The first node found that matches the XPath, or null.
130     *
131     * @throws TransformerException
132     */

133    public Node selectSingleNode(
134            Node contextNode, Node xpathnode, Node namespaceNode)
135               throws TransformerException JavaDoc {
136
137       // Have the XObject return its result as a NodeSetDTM.
138
NodeIterator nl = selectNodeIterator(contextNode, xpathnode,
139                                            namespaceNode);
140
141       // Return the first node, or null
142
return nl.nextNode();
143    }
144
145    /**
146     * Use an XPath string to select a nodelist.
147     * XPath namespace prefixes are resolved from the contextNode.
148     *
149     * @param contextNode The node to start searching from.
150     * @param xpathnode
151     * @return A NodeIterator, should never be null.
152     *
153     * @throws TransformerException
154     */

155    public NodeIterator selectNodeIterator(Node contextNode, Node xpathnode)
156            throws TransformerException JavaDoc {
157       return selectNodeIterator(contextNode, xpathnode, contextNode);
158    }
159
160    /**
161     * Use an XPath string to select a nodelist.
162     * XPath namespace prefixes are resolved from the namespaceNode.
163     *
164     * @param contextNode The node to start searching from.
165     * @param xpathnode
166     * @param namespaceNode The node from which prefixes in the XPath will be resolved to namespaces.
167     * @return A NodeIterator, should never be null.
168     *
169     * @throws TransformerException
170     * @deprecated
171     */

172    public NodeIterator selectNodeIterator(
173            Node contextNode, Node xpathnode, Node namespaceNode)
174               throws TransformerException JavaDoc {
175
176       // Execute the XPath, and have it return the result
177
XObject list = eval(contextNode, xpathnode, getStrFromNode(xpathnode), namespaceNode);
178
179       // Have the XObject return its result as a NodeSetDTM.
180
return list.nodeset();
181    }
182
183    /**
184     * Use an XPath string to select a nodelist.
185     * XPath namespace prefixes are resolved from the contextNode.
186     *
187     * @param contextNode The node to start searching from.
188     * @param xpathnode
189     * @return A NodeIterator, should never be null.
190     *
191     * @throws TransformerException
192     * @deprecated
193     */

194    public NodeList selectNodeList(Node contextNode, Node xpathnode)
195            throws TransformerException JavaDoc {
196       return selectNodeList(contextNode, xpathnode, getStrFromNode(xpathnode), contextNode);
197    }
198
199    /**
200     * Use an XPath string to select a nodelist.
201     * XPath namespace prefixes are resolved from the namespaceNode.
202     *
203     * @param contextNode The node to start searching from.
204     * @param xpathnode
205     * @param str
206     * @param namespaceNode The node from which prefixes in the XPath will be resolved to namespaces.
207     * @return A NodeIterator, should never be null.
208     *
209     * @throws TransformerException
210     */

211    public NodeList selectNodeList(
212            Node contextNode, Node xpathnode, String JavaDoc str, Node namespaceNode)
213               throws TransformerException JavaDoc {
214
215       // Execute the XPath, and have it return the result
216
XObject list = eval(contextNode, xpathnode, str, namespaceNode);
217
218       // Return a NodeList.
219
return list.nodelist();
220    }
221
222    /**
223     * Evaluate XPath string to an XObject. Using this method,
224     * XPath namespace prefixes will be resolved from the namespaceNode.
225     * @param contextNode The node to start searching from.
226     * @param xpathnode
227     * @return An XObject, which can be used to obtain a string, number, nodelist, etc, should never be null.
228     * @see com.sun.org.apache.xpath.internal.objects.XObject
229     * @see com.sun.org.apache.xpath.internal.objects.XNull
230     * @see com.sun.org.apache.xpath.internal.objects.XBoolean
231     * @see com.sun.org.apache.xpath.internal.objects.XNumber
232     * @see com.sun.org.apache.xpath.internal.objects.XString
233     * @see com.sun.org.apache.xpath.internal.objects.XRTreeFrag
234     *
235     * @throws TransformerException
236     * @deprecated
237     */

238    public XObject eval(Node contextNode, Node xpathnode)
239            throws TransformerException JavaDoc {
240       return eval(contextNode, xpathnode, getStrFromNode(xpathnode),contextNode);
241    }
242
243    /**
244     * Evaluate XPath string to an XObject.
245     * XPath namespace prefixes are resolved from the namespaceNode.
246     * The implementation of this is a little slow, since it creates
247     * a number of objects each time it is called. This could be optimized
248     * to keep the same objects around, but then thread-safety issues would arise.
249     *
250     * @param contextNode The node to start searching from.
251     * @param xpathnode
252     * @param str
253     * @param namespaceNode The node from which prefixes in the XPath will be resolved to namespaces.
254     * @return An XObject, which can be used to obtain a string, number, nodelist, etc, should never be null.
255     * @see com.sun.org.apache.xpath.internal.objects.XObject
256     * @see com.sun.org.apache.xpath.internal.objects.XNull
257     * @see com.sun.org.apache.xpath.internal.objects.XBoolean
258     * @see com.sun.org.apache.xpath.internal.objects.XNumber
259     * @see com.sun.org.apache.xpath.internal.objects.XString
260     * @see com.sun.org.apache.xpath.internal.objects.XRTreeFrag
261     *
262     * @throws TransformerException
263     */

264    public XObject eval(Node contextNode, Node xpathnode, String JavaDoc str, Node namespaceNode)
265            throws TransformerException JavaDoc {
266       // Create the XPath object.
267
//String str = CachedXPathFuncHereAPI.getStrFromNode(xpathnode);
268

269       // Since we don't have a XML Parser involved here, install some default support
270
// for things like namespaces, etc.
271
// (Changed from: XPathContext xpathSupport = new XPathContext();
272
// because XPathContext is weak in a number of areas... perhaps
273
// XPathContext should be done away with.)
274
if (this._funcHereContext == null) {
275          this._funcHereContext = new FuncHereContext(xpathnode,
276                                                      this._dtmManager);
277       }
278
279       // Create an object to resolve namespace prefixes.
280
// XPath namespaces are resolved from the input context node's document element
281
// if it is a root node, or else the current context node (for lack of a better
282
// resolution space, given the simplicity of this sample code).
283
PrefixResolverDefault prefixResolver =
284          new PrefixResolverDefault((namespaceNode.getNodeType()
285                                     == Node.DOCUMENT_NODE)
286                                    ? ((Document) namespaceNode)
287                                       .getDocumentElement()
288                                    : namespaceNode);
289
290       if (str!=xpathStr) {
291         if (str.indexOf("here()")>0) {
292             _context.reset();
293             _dtmManager=_context.getDTMManager();
294         }
295         xpath = createXPath(str, prefixResolver);
296         xpathStr=str;
297       }
298
299       // Execute the XPath, and have it return the result
300
// return xpath.execute(xpathSupport, contextNode, prefixResolver);
301
int ctxtNode = this._funcHereContext.getDTMHandleFromNode(contextNode);
302
303       return xpath.execute(this._funcHereContext, ctxtNode, prefixResolver);
304    }
305
306    /**
307     * Evaluate XPath string to an XObject.
308     * XPath namespace prefixes are resolved from the namespaceNode.
309     * The implementation of this is a little slow, since it creates
310     * a number of objects each time it is called. This could be optimized
311     * to keep the same objects around, but then thread-safety issues would arise.
312     *
313     * @param contextNode The node to start searching from.
314     * @param xpathnode
315     * @param str
316     * @param prefixResolver Will be called if the parser encounters namespace
317     * prefixes, to resolve the prefixes to URLs.
318     * @return An XObject, which can be used to obtain a string, number, nodelist, etc, should never be null.
319     * @see com.sun.org.apache.xpath.internal.objects.XObject
320     * @see com.sun.org.apache.xpath.internal.objects.XNull
321     * @see com.sun.org.apache.xpath.internal.objects.XBoolean
322     * @see com.sun.org.apache.xpath.internal.objects.XNumber
323     * @see com.sun.org.apache.xpath.internal.objects.XString
324     * @see com.sun.org.apache.xpath.internal.objects.XRTreeFrag
325     *
326     * @throws TransformerException
327     */

328    public XObject eval(
329            Node contextNode, Node xpathnode, String JavaDoc str, PrefixResolver prefixResolver)
330               throws TransformerException JavaDoc {
331
332       // Since we don't have a XML Parser involved here, install some default support
333
// for things like namespaces, etc.
334
// (Changed from: XPathContext xpathSupport = new XPathContext();
335
// because XPathContext is weak in a number of areas... perhaps
336
// XPathContext should be done away with.)
337
// Create the XPath object.
338
//String str = CachedXPathFuncHereAPI.getStrFromNode(xpathnode);
339
if (str!=xpathStr) {
340         if (str.indexOf("here()")>0) {
341             _context.reset();
342             _dtmManager=_context.getDTMManager();
343         }
344         try {
345             xpath = createXPath(str, prefixResolver);
346         } catch (TransformerException JavaDoc ex) {
347             //Try to see if it is a problem with the classloader.
348
Throwable JavaDoc th= ex.getCause();
349             if (th instanceof ClassNotFoundException JavaDoc) {
350                  if (th.getMessage().indexOf("FuncHere")>0) {
351                      throw new RuntimeException JavaDoc(I18n.translate("endorsed.jdk1.4.0")/*,*/+ex);
352                  }
353               }
354               throw ex;
355         }
356         xpathStr=str;
357     }
358
359       // Execute the XPath, and have it return the result
360
if (this._funcHereContext == null) {
361          this._funcHereContext = new FuncHereContext(xpathnode,
362                                                      this._dtmManager);
363       }
364
365       int ctxtNode = this._funcHereContext.getDTMHandleFromNode(contextNode);
366
367       return xpath.execute(this._funcHereContext, ctxtNode, prefixResolver);
368    }
369
370     private XPath createXPath(String JavaDoc str, PrefixResolver prefixResolver) throws TransformerException JavaDoc {
371         XPath xpath = null;
372         Class JavaDoc[] classes = new Class JavaDoc[]{String JavaDoc.class, SourceLocator JavaDoc.class, PrefixResolver.class, int.class,
373                 ErrorListener JavaDoc.class, FunctionTable.class};
374         Object JavaDoc[] objects = new Object JavaDoc[]{str, null, prefixResolver, new Integer JavaDoc(XPath.SELECT), null, _funcTable};
375         try {
376             Constructor JavaDoc constructor = XPath.class.getConstructor(classes);
377             xpath = (XPath) constructor.newInstance(objects);
378         } catch (Throwable JavaDoc t) {
379         }
380         if (xpath == null) {
381             xpath = new XPath(str, null, prefixResolver, XPath.SELECT, null);
382         }
383         return xpath;
384     }
385
386     /**
387      * Method getStrFromNode
388      *
389      * @param xpathnode
390      * @return the string for the node.
391      */

392     public static String JavaDoc getStrFromNode(Node xpathnode) {
393
394        if (xpathnode.getNodeType() == Node.TEXT_NODE) {
395
396           // we iterate over all siblings of the context node because eventually,
397
// the text is "polluted" with pi's or comments
398
StringBuffer JavaDoc sb = new StringBuffer JavaDoc();
399
400           for (Node currentSibling = xpathnode.getParentNode().getFirstChild();
401                currentSibling != null;
402                currentSibling = currentSibling.getNextSibling()) {
403              if (currentSibling.getNodeType() == Node.TEXT_NODE) {
404                 sb.append(((Text) currentSibling).getData());
405              }
406           }
407
408           return sb.toString();
409        } else if (xpathnode.getNodeType() == Node.ATTRIBUTE_NODE) {
410           return ((Attr) xpathnode).getNodeValue();
411        } else if (xpathnode.getNodeType() == Node.PROCESSING_INSTRUCTION_NODE) {
412           return ((ProcessingInstruction) xpathnode).getNodeValue();
413        }
414
415        return null;
416     }
417
418     private static void fixupFunctionTable() {
419         boolean installed = false;
420         if (log.isLoggable(java.util.logging.Level.INFO)) log.log(java.util.logging.Level.INFO, "Registering Here function");
421         /**
422          * Try to register our here() implementation as internal function.
423          */

424         try {
425             Class JavaDoc []args = {String JavaDoc.class, Expression.class};
426             Method JavaDoc installFunction = FunctionTable.class.getMethod("installFunction", args);
427             if ((installFunction.getModifiers() & Modifier.STATIC) != 0) {
428                 Object JavaDoc []params = {"here", new FuncHere()};
429                 installFunction.invoke(null, params);
430                 installed = true;
431             }
432         } catch (Throwable JavaDoc t) {
433             if (log.isLoggable(java.util.logging.Level.FINE)) log.log(java.util.logging.Level.FINE, "Error installing function using the static installFunction method", t);
434         }
435         if(!installed) {
436             try {
437                 _funcTable = new FunctionTable();
438                 Class JavaDoc []args = {String JavaDoc.class, Class JavaDoc.class};
439                 Method JavaDoc installFunction = FunctionTable.class.getMethod("installFunction", args);
440                 Object JavaDoc []params = {"here", FuncHere.class};
441                 installFunction.invoke(_funcTable, params);
442                 installed = true;
443             } catch (Throwable JavaDoc t) {
444                 if (log.isLoggable(java.util.logging.Level.FINE)) log.log(java.util.logging.Level.FINE, "Error installing function using the static installFunction method", t);
445             }
446         }
447         if (true) {
448             if (installed) {
449                 if (log.isLoggable(java.util.logging.Level.FINE)) log.log(java.util.logging.Level.FINE, "Registered class " + FuncHere.class.getName()
450                         + " for XPath function 'here()' function in internal table");
451             } else {
452                 if (log.isLoggable(java.util.logging.Level.FINE)) log.log(java.util.logging.Level.FINE, "Unable to register class " + FuncHere.class.getName()
453                         + " for XPath function 'here()' function in internal table");
454             }
455         }
456     }
457 }
458
Popular Tags