KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > sun > org > apache > xml > internal > security > signature > XMLSignatureInputDebugger


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.signature;
18
19 import java.io.IOException JavaDoc;
20 import java.io.StringWriter JavaDoc;
21 import java.io.Writer JavaDoc;
22 import java.util.Arrays JavaDoc;
23 import java.util.Set JavaDoc;
24
25 import com.sun.org.apache.xml.internal.security.c14n.helper.AttrCompare;
26 import com.sun.org.apache.xml.internal.security.utils.XMLUtils;
27 import org.w3c.dom.Attr JavaDoc;
28 import org.w3c.dom.Comment JavaDoc;
29 import org.w3c.dom.Document JavaDoc;
30 import org.w3c.dom.Element JavaDoc;
31 import org.w3c.dom.NamedNodeMap JavaDoc;
32 import org.w3c.dom.Node JavaDoc;
33 import org.w3c.dom.ProcessingInstruction JavaDoc;
34
35 /**
36  * Class XMLSignatureInputDebugger
37  *
38  * @author $Author: raul $
39  * @version $Revision: 1.3 $
40  */

41 public class XMLSignatureInputDebugger {
42
43
44
45     /** Field _xmlSignatureInput */
46     private Set JavaDoc _xpathNodeSet;
47
48     private Set JavaDoc _inclusiveNamespaces;
49
50     /** Field _doc */
51     private Document JavaDoc _doc = null;
52
53     /** Field _writer */
54     private Writer JavaDoc _writer = null;
55
56     // J-
57
// public static final String HTMLPrefix = "<!DOCTYPE HTML PUBLIC
58
// \"-//W3C//DTD HTML 4.01 Transitional//EN\"><html><head><style
59
// type=\"text/css\"><!-- .INCLUDED { color: #000000; background-color:
60
// #FFFFFF; font-weight: bold; } .EXCLUDED { color: #666666;
61
// background-color: #999999; } .INCLUDEDINCLUSIVENAMESPACE { color:
62
// #0000FF; background-color: #FFFFFF; font-weight: bold; font-style:
63
// italic; } .EXCLUDEDINCLUSIVENAMESPACE { color: #0000FF; background-color:
64
// #999999; font-style: italic; } --> </style> </head><body
65
// bgcolor=\"#999999\"><pre>";
66
/** The HTML Prefix* */
67     static final String JavaDoc HTMLPrefix = "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">\n"
68             + "<html>\n"
69             + "<head>\n"
70             + "<title>Caninical XML node set</title>\n"
71             + "<style type=\"text/css\">\n"
72             + "<!-- \n"
73             + ".INCLUDED { \n"
74             + " color: #000000; \n"
75             + " background-color: \n"
76             + " #FFFFFF; \n"
77             + " font-weight: bold; } \n"
78             + ".EXCLUDED { \n"
79             + " color: #666666; \n"
80             + " background-color: \n"
81             + " #999999; } \n"
82             + ".INCLUDEDINCLUSIVENAMESPACE { \n"
83             + " color: #0000FF; \n"
84             + " background-color: #FFFFFF; \n"
85             + " font-weight: bold; \n"
86             + " font-style: italic; } \n"
87             + ".EXCLUDEDINCLUSIVENAMESPACE { \n"
88             + " color: #0000FF; \n"
89             + " background-color: #999999; \n"
90             + " font-style: italic; } \n"
91             + "--> \n"
92             + "</style> \n"
93             + "</head>\n"
94             + "<body bgcolor=\"#999999\">\n"
95             + "<h1>Explanation of the output</h1>\n"
96             + "<p>The following text contains the nodeset of the given Reference before it is canonicalized. There exist four different styles to indicate how a given node is treated.</p>\n"
97             + "<ul>\n"
98             + "<li class=\"INCLUDED\">A node which is in the node set is labeled using the INCLUDED style.</li>\n"
99             + "<li class=\"EXCLUDED\">A node which is <em>NOT</em> in the node set is labeled EXCLUDED style.</li>\n"
100             + "<li class=\"INCLUDEDINCLUSIVENAMESPACE\">A namespace which is in the node set AND in the InclusiveNamespaces PrefixList is labeled using the INCLUDEDINCLUSIVENAMESPACE style.</li>\n"
101             + "<li class=\"EXCLUDEDINCLUSIVENAMESPACE\">A namespace which is in NOT the node set AND in the InclusiveNamespaces PrefixList is labeled using the INCLUDEDINCLUSIVENAMESPACE style.</li>\n"
102             + "</ul>\n" + "<h1>Output</h1>\n" + "<pre>\n";
103
104     /** HTML Suffix * */
105     static final String JavaDoc HTMLSuffix = "</pre></body></html>";
106
107     static final String JavaDoc HTMLExcludePrefix = "<span class=\"EXCLUDED\">";
108
109     static final String JavaDoc HTMLExcludeSuffix = "</span>";
110
111     static final String JavaDoc HTMLIncludePrefix = "<span class=\"INCLUDED\">";
112
113     static final String JavaDoc HTMLIncludeSuffix = "</span>";
114
115     static final String JavaDoc HTMLIncludedInclusiveNamespacePrefix = "<span class=\"INCLUDEDINCLUSIVENAMESPACE\">";
116
117     static final String JavaDoc HTMLIncludedInclusiveNamespaceSuffix = "</span>";
118
119     static final String JavaDoc HTMLExcludedInclusiveNamespacePrefix = "<span class=\"EXCLUDEDINCLUSIVENAMESPACE\">";
120
121     static final String JavaDoc HTMLExcludedInclusiveNamespaceSuffix = "</span>";
122
123     private static final int NODE_BEFORE_DOCUMENT_ELEMENT = -1;
124
125     private static final int NODE_NOT_BEFORE_OR_AFTER_DOCUMENT_ELEMENT = 0;
126
127     private static final int NODE_AFTER_DOCUMENT_ELEMENT = 1;
128
129     static final AttrCompare ATTR_COMPARE = new AttrCompare();
130
131     // J+
132
private XMLSignatureInputDebugger() {
133         // do nothing
134
}
135
136     /**
137      * Constructor XMLSignatureInputDebugger
138      *
139      * @param xmlSignatureInput the signatur to pretty print
140      */

141     public XMLSignatureInputDebugger(
142             XMLSignatureInput xmlSignatureInput) {
143
144         if (!xmlSignatureInput.isNodeSet()) {
145             this._xpathNodeSet = null;
146         } else {
147             this._xpathNodeSet = xmlSignatureInput._inputNodeSet;
148         }
149     }
150
151     /**
152      * Constructor XMLSignatureInputDebugger
153      *
154      * @param xmlSignatureInput the signatur to pretty print
155      * @param inclusiveNamespace
156      */

157     public XMLSignatureInputDebugger(
158             XMLSignatureInput xmlSignatureInput, Set JavaDoc inclusiveNamespace) {
159
160         this(xmlSignatureInput);
161
162         this._inclusiveNamespaces = inclusiveNamespace;
163     }
164
165     /**
166      * Method getHTMLRepresentation
167      *
168      * @return The HTML Representation.
169      * @throws XMLSignatureException
170      */

171     public String JavaDoc getHTMLRepresentation() throws XMLSignatureException {
172
173         if ((this._xpathNodeSet == null) || (this._xpathNodeSet.size() == 0)) {
174             return HTMLPrefix + "<blink>no node set, sorry</blink>"
175                     + HTMLSuffix;
176         }
177
178         {
179
180             // get only a single node as anchor to fetch the owner document
181
Node JavaDoc n = (Node JavaDoc) this._xpathNodeSet.iterator().next();
182
183             this._doc = XMLUtils.getOwnerDocument(n);
184         }
185
186         try {
187             this._writer = new StringWriter JavaDoc();
188
189             this.canonicalizeXPathNodeSet(this._doc);
190             this._writer.close();
191
192             return this._writer.toString();
193         } catch (IOException JavaDoc ex) {
194             throw new XMLSignatureException("empty", ex);
195         } finally {
196             this._xpathNodeSet = null;
197             this._doc = null;
198             this._writer = null;
199         }
200     }
201
202     /**
203      * Method canonicalizeXPathNodeSet
204      *
205      * @param currentNode
206      * @throws XMLSignatureException
207      * @throws IOException
208      */

209     private void canonicalizeXPathNodeSet(Node JavaDoc currentNode)
210             throws XMLSignatureException, IOException JavaDoc {
211
212         int currentNodeType = currentNode.getNodeType();
213         switch (currentNodeType) {
214
215         case Node.DOCUMENT_TYPE_NODE:
216         default:
217             break;
218
219         case Node.ENTITY_NODE:
220         case Node.NOTATION_NODE:
221         case Node.DOCUMENT_FRAGMENT_NODE:
222         case Node.ATTRIBUTE_NODE:
223             throw new XMLSignatureException("empty");
224         case Node.DOCUMENT_NODE:
225             this._writer.write(HTMLPrefix);
226
227             for (Node JavaDoc currentChild = currentNode.getFirstChild(); currentChild != null; currentChild = currentChild
228                     .getNextSibling()) {
229                 this.canonicalizeXPathNodeSet(currentChild);
230             }
231
232             this._writer.write(HTMLSuffix);
233             break;
234
235         case Node.COMMENT_NODE:
236             if (this._xpathNodeSet.contains(currentNode)) {
237                 this._writer.write(HTMLIncludePrefix);
238             } else {
239                 this._writer.write(HTMLExcludePrefix);
240             }
241
242             int position = getPositionRelativeToDocumentElement(currentNode);
243
244             if (position == NODE_AFTER_DOCUMENT_ELEMENT) {
245                 this._writer.write("\n");
246             }
247
248             this.outputCommentToWriter((Comment JavaDoc) currentNode);
249
250             if (position == NODE_BEFORE_DOCUMENT_ELEMENT) {
251                 this._writer.write("\n");
252             }
253
254             if (this._xpathNodeSet.contains(currentNode)) {
255                 this._writer.write(HTMLIncludeSuffix);
256             } else {
257                 this._writer.write(HTMLExcludeSuffix);
258             }
259             break;
260
261         case Node.PROCESSING_INSTRUCTION_NODE:
262             if (this._xpathNodeSet.contains(currentNode)) {
263                 this._writer.write(HTMLIncludePrefix);
264             } else {
265                 this._writer.write(HTMLExcludePrefix);
266             }
267
268             position = getPositionRelativeToDocumentElement(currentNode);
269
270             if (position == NODE_AFTER_DOCUMENT_ELEMENT) {
271                 this._writer.write("\n");
272             }
273
274             this.outputPItoWriter((ProcessingInstruction JavaDoc) currentNode);
275
276             if (position == NODE_BEFORE_DOCUMENT_ELEMENT) {
277                 this._writer.write("\n");
278             }
279
280             if (this._xpathNodeSet.contains(currentNode)) {
281                 this._writer.write(HTMLIncludeSuffix);
282             } else {
283                 this._writer.write(HTMLExcludeSuffix);
284             }
285             break;
286
287         case Node.TEXT_NODE:
288         case Node.CDATA_SECTION_NODE:
289             if (this._xpathNodeSet.contains(currentNode)) {
290                 this._writer.write(HTMLIncludePrefix);
291             } else {
292                 this._writer.write(HTMLExcludePrefix);
293             }
294
295             outputTextToWriter(currentNode.getNodeValue());
296
297             for (Node JavaDoc nextSibling = currentNode.getNextSibling(); (nextSibling != null)
298                     && ((nextSibling.getNodeType() == Node.TEXT_NODE) || (nextSibling
299                             .getNodeType() == Node.CDATA_SECTION_NODE)); nextSibling = nextSibling
300                     .getNextSibling()) {
301
302                 /*
303                  * The XPath data model allows to select only the first of a
304                  * sequence of mixed text and CDATA nodes. But we must output
305                  * them all, so we must search:
306                  *
307                  * @see http://nagoya.apache.org/bugzilla/show_bug.cgi?id=6329
308                  */

309                 this.outputTextToWriter(nextSibling.getNodeValue());
310             }
311
312             if (this._xpathNodeSet.contains(currentNode)) {
313                 this._writer.write(HTMLIncludeSuffix);
314             } else {
315                 this._writer.write(HTMLExcludeSuffix);
316             }
317             break;
318
319         case Node.ELEMENT_NODE:
320             Element JavaDoc currentElement = (Element JavaDoc) currentNode;
321
322             if (this._xpathNodeSet.contains(currentNode)) {
323                 this._writer.write(HTMLIncludePrefix);
324             } else {
325                 this._writer.write(HTMLExcludePrefix);
326             }
327
328             this._writer.write("&lt;");
329             this._writer.write(currentElement.getTagName());
330
331             if (this._xpathNodeSet.contains(currentNode)) {
332                 this._writer.write(HTMLIncludeSuffix);
333             } else {
334                 this._writer.write(HTMLExcludeSuffix);
335             }
336
337             // we output all Attrs which are available
338
NamedNodeMap JavaDoc attrs = currentElement.getAttributes();
339             int attrsLength = attrs.getLength();
340             Object JavaDoc attrs2[] = new Object JavaDoc[attrsLength];
341
342             for (int i = 0; i < attrsLength; i++) {
343                 attrs2[i] = attrs.item(i);
344             }
345
346             Arrays.sort(attrs2, ATTR_COMPARE);
347             Object JavaDoc attrs3[] = attrs2;
348
349             for (int i = 0; i < attrsLength; i++) {
350                 Attr JavaDoc a = (Attr JavaDoc) attrs3[i];
351                 boolean included = this._xpathNodeSet.contains(a);
352                 boolean inclusive = this._inclusiveNamespaces.contains(a
353                         .getName());
354
355                 if (included) {
356                     if (inclusive) {
357
358                         // included and inclusive
359
this._writer
360                                 .write(HTMLIncludedInclusiveNamespacePrefix);
361                     } else {
362
363                         // included and not inclusive
364
this._writer.write(HTMLIncludePrefix);
365                     }
366                 } else {
367                     if (inclusive) {
368
369                         // excluded and inclusive
370
this._writer
371                                 .write(HTMLExcludedInclusiveNamespacePrefix);
372                     } else {
373
374                         // excluded and not inclusive
375
this._writer.write(HTMLExcludePrefix);
376                     }
377                 }
378
379                 this.outputAttrToWriter(a.getNodeName(), a.getNodeValue());
380
381                 if (included) {
382                     if (inclusive) {
383
384                         // included and inclusive
385
this._writer
386                                 .write(HTMLIncludedInclusiveNamespaceSuffix);
387                     } else {
388
389                         // included and not inclusive
390
this._writer.write(HTMLIncludeSuffix);
391                     }
392                 } else {
393                     if (inclusive) {
394
395                         // excluded and inclusive
396
this._writer
397                                 .write(HTMLExcludedInclusiveNamespaceSuffix);
398                     } else {
399
400                         // excluded and not inclusive
401
this._writer.write(HTMLExcludeSuffix);
402                     }
403                 }
404             }
405
406             if (this._xpathNodeSet.contains(currentNode)) {
407                 this._writer.write(HTMLIncludePrefix);
408             } else {
409                 this._writer.write(HTMLExcludePrefix);
410             }
411
412             this._writer.write("&gt;");
413
414             if (this._xpathNodeSet.contains(currentNode)) {
415                 this._writer.write(HTMLIncludeSuffix);
416             } else {
417                 this._writer.write(HTMLExcludeSuffix);
418             }
419
420             // traversal
421
for (Node JavaDoc currentChild = currentNode.getFirstChild(); currentChild != null; currentChild = currentChild
422                     .getNextSibling()) {
423                 this.canonicalizeXPathNodeSet(currentChild);
424             }
425
426             if (this._xpathNodeSet.contains(currentNode)) {
427                 this._writer.write(HTMLIncludePrefix);
428             } else {
429                 this._writer.write(HTMLExcludePrefix);
430             }
431
432             this._writer.write("&lt;/");
433             this._writer.write(currentElement.getTagName());
434             this._writer.write("&gt;");
435
436             if (this._xpathNodeSet.contains(currentNode)) {
437                 this._writer.write(HTMLIncludeSuffix);
438             } else {
439                 this._writer.write(HTMLExcludeSuffix);
440             }
441             break;
442         }
443     }
444
445     /**
446      * Checks whether a Comment or ProcessingInstruction is before or after the
447      * document element. This is needed for prepending or appending "\n"s.
448      *
449      * @param currentNode
450      * comment or pi to check
451      * @return NODE_BEFORE_DOCUMENT_ELEMENT,
452      * NODE_NOT_BEFORE_OR_AFTER_DOCUMENT_ELEMENT or
453      * NODE_AFTER_DOCUMENT_ELEMENT
454      * @see #NODE_BEFORE_DOCUMENT_ELEMENT
455      * @see #NODE_NOT_BEFORE_OR_AFTER_DOCUMENT_ELEMENT
456      * @see #NODE_AFTER_DOCUMENT_ELEMENT
457      */

458     private int getPositionRelativeToDocumentElement(Node JavaDoc currentNode) {
459
460         if (currentNode == null) {
461             return NODE_NOT_BEFORE_OR_AFTER_DOCUMENT_ELEMENT;
462         }
463
464         Document JavaDoc doc = currentNode.getOwnerDocument();
465
466         if (currentNode.getParentNode() != doc) {
467             return NODE_NOT_BEFORE_OR_AFTER_DOCUMENT_ELEMENT;
468         }
469
470         Element JavaDoc documentElement = doc.getDocumentElement();
471
472         if (documentElement == null) {
473             return NODE_NOT_BEFORE_OR_AFTER_DOCUMENT_ELEMENT;
474         }
475
476         if (documentElement == currentNode) {
477             return NODE_NOT_BEFORE_OR_AFTER_DOCUMENT_ELEMENT;
478         }
479
480         for (Node JavaDoc x = currentNode; x != null; x = x.getNextSibling()) {
481             if (x == documentElement) {
482                 return NODE_BEFORE_DOCUMENT_ELEMENT;
483             }
484         }
485
486         return NODE_AFTER_DOCUMENT_ELEMENT;
487     }
488
489     /**
490      * Normalizes an {@link Attr}ibute value
491      *
492      * The string value of the node is modified by replacing
493      * <UL>
494      * <LI>all ampersands (&) with <CODE>&amp;amp;</CODE></LI>
495      * <LI>all open angle brackets (<) with <CODE>&amp;lt;</CODE></LI>
496      * <LI>all quotation mark characters with <CODE>&amp;quot;</CODE></LI>
497      * <LI>and the whitespace characters <CODE>#x9</CODE>, #xA, and #xD,
498      * with character references. The character references are written in
499      * uppercase hexadecimal with no leading zeroes (for example, <CODE>#xD</CODE>
500      * is represented by the character reference <CODE>&amp;#xD;</CODE>)</LI>
501      * </UL>
502      *
503      * @param name
504      * @param value
505      * @throws IOException
506      */

507     private void outputAttrToWriter(String JavaDoc name, String JavaDoc value)
508             throws IOException JavaDoc {
509
510         this._writer.write(" ");
511         this._writer.write(name);
512         this._writer.write("=\"");
513
514         int length = value.length();
515
516         for (int i = 0; i < length; i++) {
517             char c = value.charAt(i);
518
519             switch (c) {
520
521             case '&':
522                 this._writer.write("&amp;amp;");
523                 break;
524
525             case '<':
526                 this._writer.write("&amp;lt;");
527                 break;
528
529             case '"':
530                 this._writer.write("&amp;quot;");
531                 break;
532
533             case 0x09: // '\t'
534
this._writer.write("&amp;#x9;");
535                 break;
536
537             case 0x0A: // '\n'
538
this._writer.write("&amp;#xA;");
539                 break;
540
541             case 0x0D: // '\r'
542
this._writer.write("&amp;#xD;");
543                 break;
544
545             default:
546                 this._writer.write(c);
547                 break;
548             }
549         }
550
551         this._writer.write("\"");
552     }
553
554     /**
555      * Normalizes a {@link org.w3c.dom.Comment} value
556      *
557      * @param currentPI
558      * @throws IOException
559      */

560     private void outputPItoWriter(ProcessingInstruction JavaDoc currentPI)
561             throws IOException JavaDoc {
562
563         if (currentPI == null) {
564             return;
565         }
566
567         this._writer.write("&lt;?");
568
569         String JavaDoc target = currentPI.getTarget();
570         int length = target.length();
571
572         for (int i = 0; i < length; i++) {
573             char c = target.charAt(i);
574
575             switch (c) {
576
577             case 0x0D:
578                 this._writer.write("&amp;#xD;");
579                 break;
580
581             case ' ':
582                 this._writer.write("&middot;");
583                 break;
584
585             case '\n':
586                 this._writer.write("&para;\n");
587                 break;
588
589             default:
590                 this._writer.write(c);
591                 break;
592             }
593         }
594
595         String JavaDoc data = currentPI.getData();
596
597         length = data.length();
598
599         if ((data != null) && (length > 0)) {
600             this._writer.write(" ");
601
602             for (int i = 0; i < length; i++) {
603                 char c = data.charAt(i);
604
605                 switch (c) {
606
607                 case 0x0D:
608                     this._writer.write("&amp;#xD;");
609                     break;
610
611                 default:
612                     this._writer.write(c);
613                     break;
614                 }
615             }
616         }
617
618         this._writer.write("?&gt;");
619     }
620
621     /**
622      * Method outputCommentToWriter
623      *
624      * @param currentComment
625      * @throws IOException
626      */

627     private void outputCommentToWriter(Comment JavaDoc currentComment)
628             throws IOException JavaDoc {
629
630         if (currentComment == null) {
631             return;
632         }
633
634         this._writer.write("&lt;!--");
635
636         String JavaDoc data = currentComment.getData();
637         int length = data.length();
638
639         for (int i = 0; i < length; i++) {
640             char c = data.charAt(i);
641
642             switch (c) {
643
644             case 0x0D:
645                 this._writer.write("&amp;#xD;");
646                 break;
647
648             case ' ':
649                 this._writer.write("&middot;");
650                 break;
651
652             case '\n':
653                 this._writer.write("&para;\n");
654                 break;
655
656             default:
657                 this._writer.write(c);
658                 break;
659             }
660         }
661
662         this._writer.write("--&gt;");
663     }
664
665     /**
666      * Method outputTextToWriter
667      *
668      * @param text
669      * @throws IOException
670      */

671     private void outputTextToWriter(String JavaDoc text) throws IOException JavaDoc {
672
673         if (text == null) {
674             return;
675         }
676
677         int length = text.length();
678
679         for (int i = 0; i < length; i++) {
680             char c = text.charAt(i);
681
682             switch (c) {
683
684             case '&':
685                 this._writer.write("&amp;amp;");
686                 break;
687
688             case '<':
689                 this._writer.write("&amp;lt;");
690                 break;
691
692             case '>':
693                 this._writer.write("&amp;gt;");
694                 break;
695
696             case 0xD:
697                 this._writer.write("&amp;#xD;");
698                 break;
699
700             case ' ':
701                 this._writer.write("&middot;");
702                 break;
703
704             case '\n':
705                 this._writer.write("&para;\n");
706                 break;
707
708             default:
709                 this._writer.write(c);
710                 break;
711             }
712         }
713     }
714 }
Popular Tags