KickJava   Java API By Example, From Geeks To Geeks.

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


1
2 /*
3  * Copyright 1999-2004 The Apache Software Foundation.
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  *
17  */

18 package com.sun.org.apache.xml.internal.security.utils;
19
20
21
22 import java.io.IOException JavaDoc;
23 import java.io.OutputStream JavaDoc;
24 import java.util.HashSet JavaDoc;
25 import java.util.Iterator JavaDoc;
26 import java.util.Set JavaDoc;
27
28 import com.sun.org.apache.xml.internal.security.c14n.CanonicalizationException;
29 import com.sun.org.apache.xml.internal.security.c14n.Canonicalizer;
30 import com.sun.org.apache.xml.internal.security.c14n.InvalidCanonicalizerException;
31 import org.w3c.dom.Attr JavaDoc;
32 import org.w3c.dom.Document JavaDoc;
33 import org.w3c.dom.Element JavaDoc;
34 import org.w3c.dom.NamedNodeMap JavaDoc;
35 import org.w3c.dom.Node JavaDoc;
36 import org.w3c.dom.NodeList JavaDoc;
37 import org.w3c.dom.Text JavaDoc;
38
39
40
41 /**
42  * DOM and XML accessibility and comfort functions.
43  *
44  * @author Christian Geuer-Pollmann
45  */

46 public class XMLUtils {
47
48    /**
49     * Constructor XMLUtils
50     *
51     */

52    private XMLUtils() {
53
54       // we don't allow instantiation
55
}
56
57    
58    /**
59     * @param rootNode
60     * @param result
61     * @param exclude
62     * @param com wheather comments or not
63     */

64    public static void getSet(Node JavaDoc rootNode,Set JavaDoc result,Node JavaDoc exclude ,boolean com) {
65       if ((exclude!=null) && isDescendantOrSelf(exclude,rootNode)){
66         return;
67       }
68       getSetRec(rootNode,result,exclude,com);
69    }
70    static final void getSetRec(final Node JavaDoc rootNode,final Set JavaDoc result,
71         final Node JavaDoc exclude ,final boolean com) {
72        //Set result = new HashSet();
73
if (rootNode==exclude) {
74           return;
75        }
76        switch (rootNode.getNodeType()) {
77         case Node.ELEMENT_NODE:
78                 result.add(rootNode);
79                 Element JavaDoc el=(Element JavaDoc)rootNode;
80                 if (el.hasAttributes()) {
81                     NamedNodeMap JavaDoc nl = ((Element JavaDoc)rootNode).getAttributes();
82                     for (int i=0;i<nl.getLength();i++) {
83                         result.add(nl.item(i));
84                     }
85                 }
86                 //no return keep working
87
case Node.DOCUMENT_NODE:
88                 for (Node JavaDoc r=rootNode.getFirstChild();r!=null;r=r.getNextSibling()){
89                     if (r.getNodeType()==Node.TEXT_NODE) {
90                         result.add(r);
91                         while ((r!=null) && (r.getNodeType()==Node.TEXT_NODE)) {
92                             r=r.getNextSibling();
93                         }
94                         if (r==null)
95                             return;
96                     }
97                     getSetRec(r,result,exclude,com);
98                 }
99                 return;
100             case Node.COMMENT_NODE:
101                 if (com) {
102                     result.add(rootNode);
103                 }
104                 return;
105             case Node.DOCUMENT_TYPE_NODE:
106                 return;
107             default:
108                 result.add(rootNode);
109        }
110        return;
111    }
112
113
114    /**
115     * Outputs a DOM tree to an {@link OutputStream}.
116     *
117     * @param contextNode root node of the DOM tree
118     * @param os the {@link OutputStream}
119     */

120    public static void outputDOM(Node JavaDoc contextNode, OutputStream JavaDoc os) {
121       XMLUtils.outputDOM(contextNode, os, false);
122    }
123
124    /**
125     * Outputs a DOM tree to an {@link OutputStream}. <I>If an Exception is
126     * thrown during execution, it's StackTrace is output to System.out, but the
127     * Exception is not re-thrown.</I>
128     *
129     * @param contextNode root node of the DOM tree
130     * @param os the {@link OutputStream}
131     * @param addPreamble
132     */

133    public static void outputDOM(Node JavaDoc contextNode, OutputStream JavaDoc os,
134                                 boolean addPreamble) {
135
136       try {
137          if (addPreamble) {
138             os.write("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n".getBytes());
139          }
140
141          os.write(
142             Canonicalizer.getInstance(
143                Canonicalizer.ALGO_ID_C14N_WITH_COMMENTS).canonicalizeSubtree(
144                contextNode));
145       } catch (IOException JavaDoc ex) {}
146       catch (InvalidCanonicalizerException ex) {
147          ex.printStackTrace();
148       } catch (CanonicalizationException ex) {
149          ex.printStackTrace();
150       }
151    }
152
153    /**
154     * Serializes the <CODE>contextNode</CODE> into the OutputStream, <I>but
155     * supresses all Exceptions</I>.
156     * <BR />
157     * NOTE: <I>This should only be used for debugging purposes,
158     * NOT in a production environment; this method ignores all exceptions,
159     * so you won't notice if something goes wrong. If you're asking what is to
160     * be used in a production environment, simply use the code inside the
161     * <code>try{}</code> statement, but handle the Exceptions appropriately.</I>
162     *
163     * @param contextNode
164     * @param os
165     */

166    public static void outputDOMc14nWithComments(Node JavaDoc contextNode,
167            OutputStream JavaDoc os) {
168
169       try {
170          os.write(
171             Canonicalizer.getInstance(
172                Canonicalizer.ALGO_ID_C14N_WITH_COMMENTS).canonicalizeSubtree(
173                contextNode));
174       } catch (IOException JavaDoc ex) {
175
176          // throw new RuntimeException(ex.getMessage());
177
} catch (InvalidCanonicalizerException ex) {
178
179          // throw new RuntimeException(ex.getMessage());
180
} catch (CanonicalizationException ex) {
181
182          // throw new RuntimeException(ex.getMessage());
183
}
184    }
185
186  
187    /**
188     * Method getFullTextChildrenFromElement
189     *
190     * @param element
191     * @return the string of chi;ds
192     */

193    public static String JavaDoc getFullTextChildrenFromElement(Element JavaDoc element) {
194
195       StringBuffer JavaDoc sb = new StringBuffer JavaDoc();
196       NodeList JavaDoc children = element.getChildNodes();
197       int iMax = children.getLength();
198
199       for (int i = 0; i < iMax; i++) {
200          Node JavaDoc curr = children.item(i);
201
202          if (curr.getNodeType() == Node.TEXT_NODE) {
203             sb.append(((Text JavaDoc) curr).getData());
204          }
205       }
206
207       return sb.toString();
208    }
209
210
211    /**
212     * Creates an Element in the XML Signature specification namespace.
213     *
214     * @param doc the factory Document
215     * @param elementName the local name of the Element
216     * @return the Element
217     */

218    public static Element JavaDoc createElementInSignatureSpace(Document JavaDoc doc,
219            String JavaDoc elementName) {
220
221       if (doc == null) {
222          throw new RuntimeException JavaDoc("Document is null");
223       }
224
225       String JavaDoc ds = Constants.getSignatureSpecNSprefix();
226
227       if ((ds == null) || (ds.length() == 0)) {
228          Element JavaDoc element = doc.createElementNS(Constants.SignatureSpecNS,
229                                                elementName);
230
231          element.setAttributeNS(Constants.NamespaceSpecNS, "xmlns",
232                                 Constants.SignatureSpecNS);
233
234          return element;
235       }
236          Element JavaDoc element = doc.createElementNS(Constants.SignatureSpecNS,
237                                                ds + ":" + elementName);
238
239          element.setAttributeNS(Constants.NamespaceSpecNS, "xmlns:" + ds,
240                                 Constants.SignatureSpecNS);
241
242          return element;
243       
244    }
245
246
247    /**
248     * Returns true if the element is in XML Signature namespace and the local
249     * name equals the supplied one.
250     *
251     * @param element
252     * @param localName
253     * @return true if the element is in XML Signature namespace and the local name equals the supplied one
254     */

255    public static boolean elementIsInSignatureSpace(Element JavaDoc element,
256            String JavaDoc localName) {
257
258       if ((element == null) ||
259           !Constants.SignatureSpecNS.equals(element.getNamespaceURI()) ){
260          return false;
261       }
262
263       if (!element.getLocalName().equals(localName)) {
264          return false;
265       }
266
267       return true;
268    }
269
270    /**
271     * Returns true if the element is in XML Encryption namespace and the local
272     * name equals the supplied one.
273     *
274     * @param element
275     * @param localName
276     * @return true if the element is in XML Encryption namespace and the local name equals the supplied one
277     */

278    public static boolean elementIsInEncryptionSpace(Element JavaDoc element,
279            String JavaDoc localName) {
280
281       if ((element == null) ||
282             !EncryptionConstants.EncryptionSpecNS.equals(element.getNamespaceURI())
283           ){
284          return false;
285       }
286
287       if (!element.getLocalName().equals(localName)) {
288          return false;
289       }
290
291       return true;
292    }
293
294    /**
295     * This method returns the owner document of a particular node.
296     * This method is necessary because it <I>always</I> returns a
297     * {@link Document}. {@link Node#getOwnerDocument} returns <CODE>null</CODE>
298     * if the {@link Node} is a {@link Document}.
299     *
300     * @param node
301     * @return the owner document of the node
302     */

303    public static Document JavaDoc getOwnerDocument(Node JavaDoc node) {
304
305       if (node.getNodeType() == Node.DOCUMENT_NODE) {
306          return (Document JavaDoc) node;
307       }
308          try {
309             return node.getOwnerDocument();
310          } catch (NullPointerException JavaDoc npe) {
311             throw new NullPointerException JavaDoc(I18n.translate("endorsed.jdk1.4.0")
312                                            + " Original message was \""
313                                            + npe.getMessage() + "\"");
314          }
315       
316    }
317
318     /**
319      * This method returns the first non-null owner document of the Node's in this Set.
320      * This method is necessary because it <I>always</I> returns a
321      * {@link Document}. {@link Node#getOwnerDocument} returns <CODE>null</CODE>
322      * if the {@link Node} is a {@link Document}.
323      *
324      * @param xpathNodeSet
325      * @return the owner document
326      */

327     public static Document JavaDoc getOwnerDocument(Set JavaDoc xpathNodeSet) {
328        NullPointerException JavaDoc npe = null;
329        Iterator JavaDoc iterator = xpathNodeSet.iterator();
330        while(iterator.hasNext()) {
331            Node JavaDoc node = (Node JavaDoc) iterator.next();
332            int nodeType =node.getNodeType();
333            if (nodeType == Node.DOCUMENT_NODE) {
334               return (Document JavaDoc) node;
335            }
336               try {
337                  if (nodeType==Node.ATTRIBUTE_NODE) {
338                     return ((Attr JavaDoc)node).getOwnerElement().getOwnerDocument();
339                  }
340                  return node.getOwnerDocument();
341               } catch (NullPointerException JavaDoc e) {
342                   npe = e;
343               }
344            
345        }
346        throw new NullPointerException JavaDoc(I18n.translate("endorsed.jdk1.4.0")
347                                        + " Original message was \""
348                                        + (npe == null ? "" : npe.getMessage()) + "\"");
349     }
350     
351
352  
353    /**
354     * Method createDSctx
355     *
356     * @param doc
357     * @param prefix
358     * @param namespace
359     * @return the element.
360     */

361    public static Element JavaDoc createDSctx(Document JavaDoc doc, String JavaDoc prefix,
362                                      String JavaDoc namespace) {
363
364       if ((prefix == null) || (prefix.trim().length() == 0)) {
365          throw new IllegalArgumentException JavaDoc("You must supply a prefix");
366       }
367
368       Element JavaDoc ctx = doc.createElementNS(null, "namespaceContext");
369
370       ctx.setAttributeNS(Constants.NamespaceSpecNS, "xmlns:" + prefix.trim(),
371                          namespace);
372
373       return ctx;
374    }
375
376
377
378    /**
379     * Method addReturnToElement
380     *
381     * @param e
382     */

383    public static void addReturnToElement(Element JavaDoc e) {
384
385       Document JavaDoc doc = e.getOwnerDocument();
386
387       e.appendChild(doc.createTextNode("\n"));
388    }
389
390    /**
391     * Method convertNodelistToSet
392     *
393     * @param xpathNodeSet
394     * @return the set with the nodelist
395     */

396    public static Set JavaDoc convertNodelistToSet(NodeList JavaDoc xpathNodeSet) {
397
398       if (xpathNodeSet == null) {
399          return new HashSet JavaDoc();
400       }
401
402       int length = xpathNodeSet.getLength();
403       Set JavaDoc set = new HashSet JavaDoc(length);
404
405       for (int i = 0; i < length; i++) {
406          set.add(xpathNodeSet.item(i));
407       }
408
409       return set;
410    }
411
412
413    /**
414     * This method spreads all namespace attributes in a DOM document to their
415     * children. This is needed because the XML Signature XPath transform
416     * must evaluate the XPath against all nodes in the input, even against
417     * XPath namespace nodes. Through a bug in XalanJ2, the namespace nodes are
418     * not fully visible in the Xalan XPath model, so we have to do this by
419     * hand in DOM spaces so that the nodes become visible in XPath space.
420     *
421     * @param doc
422     * @see <A HREF="http://nagoya.apache.org/bugzilla/show_bug.cgi?id=2650">Namespace axis resolution is not XPath compliant </A>
423     */

424    public static void circumventBug2650(Document JavaDoc doc) {
425
426       Element JavaDoc documentElement = doc.getDocumentElement();
427
428       // if the document element has no xmlns definition, we add xmlns=""
429
Attr JavaDoc xmlnsAttr =
430          documentElement.getAttributeNodeNS(Constants.NamespaceSpecNS, "xmlns");
431
432       if (xmlnsAttr == null) {
433          documentElement.setAttributeNS(Constants.NamespaceSpecNS, "xmlns", "");
434       }
435
436       XMLUtils.circumventBug2650internal(doc);
437    }
438
439    /**
440     * This is the work horse for {@link #circumventBug2650}.
441     *
442     * @param node
443     * @see <A HREF="http://nagoya.apache.org/bugzilla/show_bug.cgi?id=2650">Namespace axis resolution is not XPath compliant </A>
444     */

445    private static void circumventBug2650internal(Node JavaDoc node) {
446        Node JavaDoc parent=null;
447        Node JavaDoc sibling=null;
448        final String JavaDoc namespaceNs=Constants.NamespaceSpecNS;
449        do {
450          switch (node.getNodeType()) {
451          case Node.ELEMENT_NODE :
452              Element JavaDoc element = (Element JavaDoc) node;
453              if (!element.hasChildNodes())
454                  break;
455              if (element.hasAttributes()) {
456              NamedNodeMap JavaDoc attributes = element.getAttributes();
457              int attributesLength = attributes.getLength();
458              
459              for (Node JavaDoc child = element.getFirstChild(); child!=null;
460                 child=child.getNextSibling()) {
461
462                 if (child.getNodeType() != Node.ELEMENT_NODE) {
463                     continue;
464                 }
465                 Element JavaDoc childElement = (Element JavaDoc) child;
466
467                 for (int i = 0; i < attributesLength; i++) {
468                     Attr JavaDoc currentAttr = (Attr JavaDoc) attributes.item(i);
469                     if (!namespaceNs.equals(currentAttr.getNamespaceURI()))
470                         continue;
471                     if (childElement.hasAttributeNS(namespaceNs,
472                                 currentAttr.getLocalName())) {
473                             continue;
474                     }
475                     childElement.setAttributeNS(namespaceNs,
476                                                 currentAttr.getName(),
477                                                 currentAttr.getNodeValue());
478                             
479                         
480                 }
481              }
482              }
483          case Node.ENTITY_REFERENCE_NODE :
484          case Node.DOCUMENT_NODE :
485              parent=node;
486              sibling=node.getFirstChild();
487              break;
488          }
489          while ((sibling==null) && (parent!=null)) {
490                  sibling=parent.getNextSibling();
491                  parent=parent.getParentNode();
492              };
493        if (sibling==null) {
494                  return;
495              }
496         
497          node=sibling;
498          sibling=node.getNextSibling();
499        } while (true);
500    }
501
502    /**
503     * @param sibling
504     * @param nodeName
505     * @param number
506     * @return nodes with the constrain
507     */

508    public static Element JavaDoc selectDsNode(Node JavaDoc sibling, String JavaDoc nodeName, int number) {
509     while (sibling!=null) {
510         if (nodeName.equals(sibling.getLocalName())
511                 && Constants.SignatureSpecNS.equals(sibling.getNamespaceURI())) {
512             if (number==0){
513                 return (Element JavaDoc)sibling;
514             }
515             number--;
516         }
517         sibling=sibling.getNextSibling();
518     }
519     return null;
520    }
521    
522    /**
523     * @param sibling
524     * @param nodeName
525     * @param number
526     * @return nodes with the constrain
527     */

528
529    public static Element JavaDoc selectXencNode(Node JavaDoc sibling, String JavaDoc nodeName, int number) {
530     while (sibling!=null) {
531         if (nodeName.equals(sibling.getLocalName())
532                 && EncryptionConstants.EncryptionSpecNS.equals(sibling.getNamespaceURI())) {
533             if (number==0){
534                 return (Element JavaDoc)sibling;
535             }
536             number--;
537         }
538         sibling=sibling.getNextSibling();
539     }
540     return null;
541    }
542    
543
544    /**
545     * @param sibling
546     * @param nodeName
547     * @param number
548     * @return nodes with the constrain
549     */

550    public static Text JavaDoc selectDsNodeText(Node JavaDoc sibling, String JavaDoc nodeName, int number) {
551         Node JavaDoc n=selectDsNode(sibling,nodeName,number);
552         if (n==null) {
553             return null;
554         }
555         n=n.getFirstChild();
556         while (n!=null && n.getNodeType()!=Node.TEXT_NODE) {
557             n=n.getNextSibling();
558         }
559         return (Text JavaDoc)n;
560    }
561    
562    /**
563     * @param sibling
564     * @param uri
565     * @param nodeName
566     * @param number
567     * @return nodes with the constrain
568     */

569    public static Text JavaDoc selectNodeText(Node JavaDoc sibling, String JavaDoc uri, String JavaDoc nodeName, int number) {
570         Node JavaDoc n=selectNode(sibling,uri,nodeName,number);
571     if (n==null) {
572         return null;
573     }
574     n=n.getFirstChild();
575     while (n!=null && n.getNodeType()!=Node.TEXT_NODE) {
576         n=n.getNextSibling();
577     }
578     return (Text JavaDoc)n;
579    }
580    
581    /**
582     * @param sibling
583     * @param uri
584     * @param nodeName
585     * @param number
586     * @return nodes with the constrain
587     */

588    public static Element JavaDoc selectNode(Node JavaDoc sibling, String JavaDoc uri,String JavaDoc nodeName, int number) {
589     while (sibling!=null) {
590         if (nodeName.equals(sibling.getLocalName())
591                 && uri.equals(sibling.getNamespaceURI())) {
592             if (number==0){
593                 return (Element JavaDoc)sibling;
594             }
595             number--;
596         }
597         sibling=sibling.getNextSibling();
598     }
599     return null;
600    }
601    
602    /**
603     * @param sibling
604     * @param nodeName
605     * @return nodes with the constrain
606     */

607    public static Element JavaDoc[] selectDsNodes(Node JavaDoc sibling,String JavaDoc nodeName) {
608      return selectNodes(sibling,Constants.SignatureSpecNS,nodeName);
609    }
610    
611    /**
612     * @param sibling
613     * @param uri
614     * @param nodeName
615     * @return nodes with the constrain
616     */

617     public static Element JavaDoc[] selectNodes(Node JavaDoc sibling,String JavaDoc uri,String JavaDoc nodeName) {
618         int size=20;
619         Element JavaDoc[] a= new Element JavaDoc[size];
620         int curr=0;
621         //List list=new ArrayList();
622
while (sibling!=null) {
623             if (nodeName.equals(sibling.getLocalName())
624                     && uri.equals(sibling.getNamespaceURI())) {
625                 a[curr++]=(Element JavaDoc)sibling;
626                 if (size<=curr) {
627                     int cursize= size<<2;
628                     Element JavaDoc []cp=new Element JavaDoc[cursize];
629                     System.arraycopy(a,0,cp,0,size);
630                     a=cp;
631                     size=cursize;
632                 }
633             }
634             sibling=sibling.getNextSibling();
635         }
636         Element JavaDoc []af=new Element JavaDoc[curr];
637         System.arraycopy(a,0,af,0,curr);
638         return af;
639    }
640
641    /**
642     * @param signatureElement
643     * @param inputSet
644     * @return nodes with the constrain
645     */

646     public static Set JavaDoc excludeNodeFromSet(Node JavaDoc signatureElement, Set JavaDoc inputSet) {
647       Set JavaDoc resultSet = new HashSet JavaDoc();
648       Iterator JavaDoc iterator = inputSet.iterator();
649
650       while (iterator.hasNext()) {
651         Node JavaDoc inputNode = (Node JavaDoc) iterator.next();
652
653         if (!XMLUtils
654                 .isDescendantOrSelf(signatureElement, inputNode)) {
655            resultSet.add(inputNode);
656         }
657      }
658      return resultSet;
659      }
660
661    /**
662     * Returns true if the descendantOrSelf is on the descendant-or-self axis
663     * of the context node.
664     *
665     * @param ctx
666     * @param descendantOrSelf
667     * @return true if the node is descendant
668     */

669    static public boolean isDescendantOrSelf(Node JavaDoc ctx, Node JavaDoc descendantOrSelf) {
670
671       if (ctx == descendantOrSelf) {
672          return true;
673       }
674
675       Node JavaDoc parent = descendantOrSelf;
676
677       while (true) {
678          if (parent == null) {
679             return false;
680          }
681
682          if (parent == ctx) {
683             return true;
684          }
685
686          if (parent.getNodeType() == Node.ATTRIBUTE_NODE) {
687             parent = ((Attr JavaDoc) parent).getOwnerElement();
688          } else {
689             parent = parent.getParentNode();
690          }
691       }
692    }
693 }
694
Popular Tags