~ubuntu-branches/ubuntu/precise/xom/precise

« back to all changes in this revision

Viewing changes to src/nu/xom/tests/CanonicalizerTest.java

  • Committer: Bazaar Package Importer
  • Author(s): Varun Hiremath
  • Date: 2007-11-25 15:50:40 UTC
  • Revision ID: james.westby@ubuntu.com-20071125155040-r75ikcqf1vu0cei7
Tags: upstream-1.1
ImportĀ upstreamĀ versionĀ 1.1

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* Copyright 2002-2005 Elliotte Rusty Harold
 
2
   
 
3
   This library is free software; you can redistribute it and/or modify
 
4
   it under the terms of version 2.1 of the GNU Lesser General Public 
 
5
   License as published by the Free Software Foundation.
 
6
   
 
7
   This library is distributed in the hope that it will be useful,
 
8
   but WITHOUT ANY WARRANTY; without even the implied warranty of
 
9
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
 
10
   GNU Lesser General Public License for more details.
 
11
   
 
12
   You should have received a copy of the GNU Lesser General Public
 
13
   License along with this library; if not, write to the 
 
14
   Free Software Foundation, Inc., 59 Temple Place, Suite 330, 
 
15
   Boston, MA 02111-1307  USA
 
16
   
 
17
   You can contact Elliotte Rusty Harold by sending e-mail to
 
18
   elharo@metalab.unc.edu. Please include the word "XOM" in the
 
19
   subject line. The XOM home page is located at http://www.xom.nu/
 
20
*/
 
21
 
 
22
package nu.xom.tests;
 
23
 
 
24
import java.io.BufferedInputStream;
 
25
import java.io.ByteArrayInputStream;
 
26
import java.io.ByteArrayOutputStream;
 
27
import java.io.DataInputStream;
 
28
import java.io.File;
 
29
import java.io.FileInputStream;
 
30
import java.io.FilenameFilter;
 
31
import java.io.IOException;
 
32
import java.io.InputStream;
 
33
import java.io.OutputStream;
 
34
 
 
35
import nu.xom.Attribute;
 
36
import nu.xom.Builder;
 
37
import nu.xom.Comment;
 
38
import nu.xom.DocType;
 
39
import nu.xom.Document;
 
40
import nu.xom.Element;
 
41
import nu.xom.Elements;
 
42
import nu.xom.Namespace;
 
43
import nu.xom.Nodes;
 
44
import nu.xom.ParsingException;
 
45
import nu.xom.ProcessingInstruction;
 
46
import nu.xom.Serializer;
 
47
import nu.xom.Text;
 
48
import nu.xom.XPathContext;
 
49
import nu.xom.canonical.CanonicalizationException;
 
50
import nu.xom.canonical.Canonicalizer;
 
51
 
 
52
/**
 
53
 * <p>
 
54
 *  Tests canonicalization.
 
55
 * </p>
 
56
 * 
 
57
 * @author Elliotte Rusty Harold
 
58
 * @version 1.1b6
 
59
 *
 
60
 */
 
61
public class CanonicalizerTest extends XOMTestCase {
 
62
 
 
63
    private final static double version = Double.parseDouble(
 
64
      System.getProperty("java.version").substring(0,3)
 
65
    );
 
66
    
 
67
    private File canonical;
 
68
    private File input;
 
69
    private File output;
 
70
    
 
71
    public CanonicalizerTest(String name) {
 
72
        super(name);
 
73
    }
 
74
 
 
75
    
 
76
    private Builder builder = new Builder(); 
 
77
    
 
78
    
 
79
    protected void setUp() { 
 
80
        File data = new File("data");
 
81
        canonical = new File(data, "canonical");
 
82
        input = new File(canonical, "input");
 
83
        output = new File(canonical, "output");
 
84
    }
 
85
    
 
86
    
 
87
    public void testCanonicalizeOnlyAttributes() throws IOException {
 
88
        
 
89
        Element pdu = new Element("doc");
 
90
        pdu.addAttribute(new Attribute("a1", "v1"));
 
91
        pdu.addAttribute(new Attribute("a2", "v2"));
 
92
        
 
93
        String expected = " a1=\"v1\" a2=\"v2\"";
 
94
        ByteArrayOutputStream out = new ByteArrayOutputStream();
 
95
        Canonicalizer canonicalizer = new Canonicalizer(out);
 
96
        
 
97
        Document doc = new Document(pdu);
 
98
        canonicalizer.write(doc.query("//@*"));  
 
99
        
 
100
        byte[] result = out.toByteArray();
 
101
        out.close();
 
102
        String s = new String(out.toByteArray(), "UTF8");
 
103
        assertEquals(expected, s);
 
104
        
 
105
    }
 
106
 
 
107
    
 
108
    public void testRemoveDuplicateAttributes() throws IOException {
 
109
        
 
110
        Element pdu = new Element("doc");
 
111
        Attribute a1 = new Attribute("a1", "v1");
 
112
        pdu.addAttribute(a1);
 
113
        Attribute a2 = new Attribute("a2", "v2");
 
114
        pdu.addAttribute(a2);
 
115
        
 
116
        String expected = " a1=\"v1\" a2=\"v2\"";
 
117
        ByteArrayOutputStream out = new ByteArrayOutputStream();
 
118
        Canonicalizer canonicalizer = new Canonicalizer(out);
 
119
        
 
120
        Document doc = new Document(pdu);
 
121
        Nodes subset = doc.query("//@*");
 
122
        subset.append(a1);
 
123
        subset.append(a2);
 
124
        canonicalizer.write(subset);  
 
125
        
 
126
        byte[] result = out.toByteArray();
 
127
        out.close();
 
128
        String s = new String(out.toByteArray(), "UTF8");
 
129
        assertEquals(expected, s);
 
130
        
 
131
    }
 
132
 
 
133
    
 
134
    public void testCanonicalizeOnlyNamespaces() throws IOException {
 
135
        
 
136
        Element pdu = new Element("doc", "http://www.example.com");
 
137
        
 
138
        String expected = " xmlns=\"http://www.example.com\"";
 
139
        ByteArrayOutputStream out = new ByteArrayOutputStream();
 
140
        Canonicalizer canonicalizer = new Canonicalizer(out);
 
141
        
 
142
        Document doc = new Document(pdu);
 
143
        canonicalizer.write(doc.query("//namespace::node()"));  
 
144
        
 
145
        byte[] result = out.toByteArray();
 
146
        out.close();
 
147
        String s = new String(out.toByteArray(), "UTF8");
 
148
        assertEquals(expected, s);
 
149
        
 
150
    }
 
151
 
 
152
    
 
153
    public void testCanonicalizeOnlyPrefixedNamespaces() 
 
154
      throws IOException {
 
155
        
 
156
        Element pdu = new Element("pre:doc", "http://www.example.com");
 
157
        
 
158
        String expected = " xmlns:pre=\"http://www.example.com\"";
 
159
        ByteArrayOutputStream out = new ByteArrayOutputStream();
 
160
        Canonicalizer canonicalizer = new Canonicalizer(out);
 
161
        
 
162
        Document doc = new Document(pdu);
 
163
        canonicalizer.write(doc.query("//namespace::node()"));  
 
164
        
 
165
        byte[] result = out.toByteArray();
 
166
        out.close();
 
167
        String s = new String(out.toByteArray(), "UTF8");
 
168
        assertEquals(expected, s);
 
169
        
 
170
    }
 
171
 
 
172
    
 
173
    public void testCanonicalizeWithNullAlgorithm() 
 
174
      throws IOException {
 
175
        
 
176
        ByteArrayOutputStream out = new ByteArrayOutputStream();
 
177
        try {
 
178
            new Canonicalizer(out, null);
 
179
            fail("Allowed null algorithm");
 
180
        }
 
181
        catch (NullPointerException success) {
 
182
            assertNotNull(success.getMessage());
 
183
        }
 
184
        
 
185
    }
 
186
 
 
187
    
 
188
    public void testCanonicalizeCommentsInPrologAndEpilog() throws IOException {
 
189
        
 
190
        Element pdu = new Element("doc");
 
191
        
 
192
        Document doc = new Document(pdu);
 
193
        doc.insertChild(new Comment("comment 1"), 0);
 
194
        doc.insertChild(new Comment("comment 2"), 1);
 
195
        doc.appendChild(new Comment("comment 3"));
 
196
        doc.appendChild(new Comment("comment 4"));
 
197
        
 
198
        String expected = "<!--comment 1-->\n<!--comment 2-->\n\n<!--comment 3-->\n<!--comment 4-->";
 
199
        ByteArrayOutputStream out = new ByteArrayOutputStream();
 
200
        Canonicalizer canonicalizer = new Canonicalizer(out);
 
201
        
 
202
        canonicalizer.write(doc.query("//comment()"));  
 
203
        
 
204
        byte[] result = out.toByteArray();
 
205
        out.close();
 
206
        String s = new String(out.toByteArray(), "UTF8");
 
207
        assertEquals(expected, s);
 
208
        
 
209
    }
 
210
 
 
211
    
 
212
    public void testTamin() throws ParsingException, IOException {
 
213
        
 
214
        String input = "<ns1:root xmlns:ns1='http://www.example.org/'><elt1></elt1></ns1:root>";
 
215
        Document doc = builder.build(input, null);
 
216
        
 
217
        ByteArrayOutputStream out = new ByteArrayOutputStream();
 
218
        Canonicalizer canonicalizer = new Canonicalizer(out);
 
219
        
 
220
        canonicalizer.write(doc);  
 
221
        
 
222
        byte[] result = out.toByteArray();
 
223
        out.close();
 
224
        String s = new String(out.toByteArray(), "UTF8");
 
225
        assertEquals("<ns1:root xmlns:ns1=\"http://www.example.org/\"><elt1></elt1></ns1:root>", s);
 
226
        
 
227
    }
 
228
 
 
229
    
 
230
    public void testCanonicalizePrologAndEpilog() throws IOException {
 
231
        
 
232
        Element pdu = new Element("doc");
 
233
        
 
234
        Document doc = new Document(pdu);
 
235
        doc.insertChild(new ProcessingInstruction("target", "value"), 0);
 
236
        doc.insertChild(new Comment("comment 2"), 1);
 
237
        doc.appendChild(new Comment("comment 3"));
 
238
        doc.appendChild(new ProcessingInstruction("target", "value"));
 
239
        
 
240
        String expected = "<?target value?>\n<!--comment 2-->\n<doc></doc>\n<!--comment 3-->\n<?target value?>";
 
241
        ByteArrayOutputStream out = new ByteArrayOutputStream();
 
242
        Canonicalizer canonicalizer = new Canonicalizer(out);
 
243
        
 
244
        canonicalizer.write(doc);  
 
245
        
 
246
        byte[] result = out.toByteArray();
 
247
        out.close();
 
248
        String s = new String(out.toByteArray(), "UTF8");
 
249
        assertEquals(expected, s);
 
250
        
 
251
    }
 
252
 
 
253
    
 
254
    public void testCanonicalizeOnlyAttributesOnDifferentElements() 
 
255
      throws IOException {
 
256
        
 
257
        Element pdu = new Element("doc");
 
258
        pdu.addAttribute(new Attribute("a2", "v1"));
 
259
        Element child = new Element("child");
 
260
        child.addAttribute(new Attribute("a1", "v2"));
 
261
        pdu.appendChild(child);
 
262
        
 
263
        String expected = " a2=\"v1\" a1=\"v2\"";
 
264
        ByteArrayOutputStream out = new ByteArrayOutputStream();
 
265
        Canonicalizer canonicalizer = new Canonicalizer(out);
 
266
        
 
267
        Document doc = new Document(pdu);
 
268
        canonicalizer.write(doc.query("//@*"));  
 
269
        
 
270
        byte[] result = out.toByteArray();
 
271
        out.close();
 
272
        String s = new String(out.toByteArray(), "UTF8");
 
273
        assertEquals(expected, s);
 
274
        
 
275
    }
 
276
 
 
277
    
 
278
    public void testCanonicalizeAttributesWithFunkyCharacters() 
 
279
      throws IOException {
 
280
        
 
281
        Element pdu = new Element("doc");
 
282
        pdu.addAttribute(new Attribute("a2", "v1&<>\"\t\r\n"));
 
283
        
 
284
        String expected = " a2=\"v1&amp;&lt;>&quot;&#x9;&#xD;&#xA;\"";
 
285
        ByteArrayOutputStream out = new ByteArrayOutputStream();
 
286
        Canonicalizer canonicalizer = new Canonicalizer(out);
 
287
        
 
288
        Document doc = new Document(pdu);
 
289
        canonicalizer.write(doc.query("//@*"));  
 
290
        
 
291
        byte[] result = out.toByteArray();
 
292
        out.close();
 
293
        String s = new String(out.toByteArray(), "UTF8");
 
294
        assertEquals(expected, s);
 
295
        
 
296
    }
 
297
 
 
298
    
 
299
    public void testExclusiveEmptyRootElementInNoNamespace() 
 
300
      throws IOException {
 
301
     
 
302
        Element pdu = new Element("doc");
 
303
   
 
304
        String expected = "<doc></doc>";
 
305
        ByteArrayOutputStream out = new ByteArrayOutputStream();
 
306
        Canonicalizer canonicalizer = new Canonicalizer(out, 
 
307
          Canonicalizer.EXCLUSIVE_XML_CANONICALIZATION_WITH_COMMENTS);
 
308
        
 
309
        Document doc = new Document(pdu);
 
310
        canonicalizer.write(doc);  
 
311
        
 
312
        byte[] result = out.toByteArray();
 
313
        out.close();
 
314
        String s = new String(out.toByteArray(), "UTF8");
 
315
        assertEquals(expected, s);
 
316
        
 
317
    }
 
318
        
 
319
 
 
320
    public void testExclusiveEmptyRootElementInNoNamespaceWithTwoAttributes() 
 
321
      throws IOException {
 
322
     
 
323
        Element pdu = new Element("doc");
 
324
        pdu.addAttribute(new Attribute("a1", "v1"));
 
325
        pdu.addAttribute(new Attribute("a2", "v2"));
 
326
        
 
327
        String expected = "<doc a1=\"v1\" a2=\"v2\"></doc>";
 
328
        ByteArrayOutputStream out = new ByteArrayOutputStream();
 
329
        Canonicalizer canonicalizer = new Canonicalizer(out,
 
330
          Canonicalizer.EXCLUSIVE_XML_CANONICALIZATION_WITH_COMMENTS);
 
331
        
 
332
        Document doc = new Document(pdu);
 
333
        canonicalizer.write(doc);  
 
334
        
 
335
        byte[] result = out.toByteArray();
 
336
        out.close();
 
337
        String s = new String(out.toByteArray(), "UTF8");
 
338
        assertEquals(expected, s);
 
339
        
 
340
    }
 
341
        
 
342
 
 
343
    public void testExclusiveDoesntRenderUnusedPrefix() 
 
344
      throws IOException {
 
345
     
 
346
        Element pdu = new Element("n0:tuck", "http://a.example");
 
347
        pdu.addNamespaceDeclaration("pre", "http://www.example.org/");
 
348
   
 
349
        String expected = "<n0:tuck xmlns:n0=\"http://a.example\"></n0:tuck>";
 
350
        ByteArrayOutputStream out = new ByteArrayOutputStream();
 
351
        Canonicalizer canonicalizer = new Canonicalizer(out,
 
352
          Canonicalizer.EXCLUSIVE_XML_CANONICALIZATION_WITH_COMMENTS);
 
353
        
 
354
        Document doc = new Document(pdu);
 
355
        canonicalizer.write(doc);  
 
356
        
 
357
        byte[] result = out.toByteArray();
 
358
        out.close();
 
359
        String s = new String(out.toByteArray(), "UTF8");
 
360
        assertEquals(expected, s);
 
361
        
 
362
    }
 
363
    
 
364
    
 
365
    public void testWriteDefaultNamespace() throws IOException {
 
366
 
 
367
        Element pdu = new Element("tuck", "http://www.example.org/");
 
368
        
 
369
        String expected = " xmlns=\"http://www.example.org/\"";
 
370
        ByteArrayOutputStream out = new ByteArrayOutputStream();
 
371
        Canonicalizer canonicalizer = new Canonicalizer(out,
 
372
          Canonicalizer.EXCLUSIVE_XML_CANONICALIZATION_WITH_COMMENTS);
 
373
        
 
374
        Document doc = new Document(pdu);
 
375
        Nodes subset = doc.query("//namespace::node()");
 
376
        canonicalizer.write(subset);  
 
377
        
 
378
        byte[] result = out.toByteArray();
 
379
        out.close();
 
380
        String s = new String(out.toByteArray(), "UTF8");
 
381
        assertEquals(expected, s);
 
382
        
 
383
    }
 
384
        
 
385
 
 
386
    public void testOutputAncestorAttributeAndChildHaveDifferentLanguages() 
 
387
      throws IOException {
 
388
     
 
389
        Element pdu = new Element("tuck");
 
390
        pdu.addAttribute(new Attribute("xml:lang", Namespace.XML_NAMESPACE, "fr"));
 
391
        
 
392
        Element middle = new Element("middle");
 
393
        pdu.appendChild(middle);
 
394
        Element child = new Element("child");
 
395
        child.addAttribute(new Attribute("xml:lang", Namespace.XML_NAMESPACE, "en"));
 
396
        middle.appendChild(child);
 
397
        
 
398
        String expected = "<tuck xml:lang=\"fr\"><child xml:lang=\"en\"></child></tuck>";
 
399
        ByteArrayOutputStream out = new ByteArrayOutputStream();
 
400
        Canonicalizer canonicalizer = new Canonicalizer(out,
 
401
          Canonicalizer.EXCLUSIVE_XML_CANONICALIZATION_WITH_COMMENTS);
 
402
        
 
403
        Document doc = new Document(pdu);
 
404
        Nodes subset = doc.query("/* | //child | //@*");
 
405
        canonicalizer.write(subset);  
 
406
        
 
407
        byte[] result = out.toByteArray();
 
408
        out.close();
 
409
        String s = new String(out.toByteArray(), "UTF8");
 
410
        assertEquals(expected, s);
 
411
        
 
412
    }
 
413
        
 
414
 
 
415
    public void testOutputAncestorAttributeUsesPrefix() 
 
416
      throws IOException {
 
417
     
 
418
        Element pdu = new Element("tuck");
 
419
        pdu.addAttribute(new Attribute("pre:foo", "http://www.example.org/", "value"));
 
420
        Element child = new Element("pre:test", "http://www.example.org/");
 
421
        pdu.appendChild(child);
 
422
        
 
423
        String expected = "<tuck xmlns:pre=\"http://www.example.org/\" pre:foo=\"value\"><pre:test></pre:test></tuck>";
 
424
        ByteArrayOutputStream out = new ByteArrayOutputStream();
 
425
        Canonicalizer canonicalizer = new Canonicalizer(out,
 
426
          Canonicalizer.EXCLUSIVE_XML_CANONICALIZATION_WITH_COMMENTS);
 
427
        
 
428
        Document doc = new Document(pdu);
 
429
        canonicalizer.write(doc);  
 
430
        
 
431
        byte[] result = out.toByteArray();
 
432
        out.close();
 
433
        String s = new String(out.toByteArray(), "UTF8");
 
434
        assertEquals(expected, s);
 
435
        
 
436
    }
 
437
        
 
438
 
 
439
    public void testOutputAncestorAttributeRedefinesPrefix() 
 
440
      throws IOException {
 
441
     
 
442
        Element pdu = new Element("tuck");
 
443
        pdu.addAttribute(new Attribute("pre:foo", "http://www.example.com/", "value"));
 
444
        Element child = new Element("pre:test", "http://www.example.org/");
 
445
        pdu.appendChild(child);
 
446
        
 
447
        String expected = "<tuck xmlns:pre=\"http://www.example.com/\" "
 
448
          + "pre:foo=\"value\"><pre:test xmlns:pre=\"http://www.example.org/\"></pre:test></tuck>";
 
449
        ByteArrayOutputStream out = new ByteArrayOutputStream();
 
450
        Canonicalizer canonicalizer = new Canonicalizer(out,
 
451
          Canonicalizer.EXCLUSIVE_XML_CANONICALIZATION_WITH_COMMENTS);
 
452
        
 
453
        Document doc = new Document(pdu);
 
454
        canonicalizer.write(doc);  
 
455
        
 
456
        byte[] result = out.toByteArray();
 
457
        out.close();
 
458
        String s = new String(out.toByteArray(), "UTF8");
 
459
        assertEquals(expected, s);
 
460
        
 
461
    }
 
462
        
 
463
 
 
464
    public void testExclusiveDoesntRenderUnusedPrefixFromUnincludedAttribute() 
 
465
      throws IOException {
 
466
     
 
467
        Element pdu = new Element("n0:tuck", "http://a.example");
 
468
        pdu.addAttribute(new Attribute("pre:foo", "http://www.example.org/", "test"));
 
469
   
 
470
        String expected = "<n0:tuck xmlns:n0=\"http://a.example\"></n0:tuck>";
 
471
        ByteArrayOutputStream out = new ByteArrayOutputStream();
 
472
        Canonicalizer canonicalizer = new Canonicalizer(out, 
 
473
          Canonicalizer.EXCLUSIVE_XML_CANONICALIZATION_WITH_COMMENTS);
 
474
        
 
475
        Document doc = new Document(pdu);
 
476
        canonicalizer.write(doc.query("//* | //namespace::node()"));  
 
477
        
 
478
        byte[] result = out.toByteArray();
 
479
        out.close();
 
480
        String s = new String(out.toByteArray(), "UTF8");
 
481
        assertEquals(expected, s);
 
482
        
 
483
    }
 
484
        
 
485
 
 
486
    public void testWithComments() 
 
487
      throws ParsingException, IOException {
 
488
      
 
489
        File tests = input;
 
490
        String[] inputs = tests.list(new XMLFilter());
 
491
        for (int i = 0; i < inputs.length; i++) {
 
492
            File input = new File(tests, inputs[i]);   
 
493
            Document doc = builder.build(input);
 
494
            ByteArrayOutputStream out = new ByteArrayOutputStream();
 
495
            try {
 
496
                Canonicalizer serializer = new Canonicalizer(out);
 
497
                serializer.write(doc);
 
498
            }
 
499
            finally {
 
500
                out.close();
 
501
            }            
 
502
            byte[] actual = out.toByteArray();
 
503
            
 
504
            // for debugging
 
505
            /* File debug = new File(canonical, "debug/" 
 
506
              + input.getName() + ".dbg");
 
507
            OutputStream fout = new FileOutputStream(debug);
 
508
            fout.write(actual);
 
509
            fout.close(); */
 
510
            
 
511
            File expected = new File(output, input.getName() + ".out");
 
512
            assertEquals(
 
513
              input.getName(), expected.length(), actual.length);
 
514
            byte[] expectedBytes = new byte[actual.length];
 
515
            InputStream fin = new FileInputStream(expected);
 
516
            DataInputStream in = new DataInputStream(fin);
 
517
            try {
 
518
                in.readFully(expectedBytes);
 
519
            }
 
520
            finally {
 
521
                in.close();
 
522
            }
 
523
            for (int j = 0; j < expectedBytes.length; j++) {
 
524
                assertEquals(expectedBytes[i], actual[i]);   
 
525
            }
 
526
            
 
527
        }
 
528
        
 
529
    }
 
530
    
 
531
    
 
532
    public void testNamedAlgorithmWithComments() 
 
533
      throws ParsingException, IOException {
 
534
      
 
535
        File tests = input;
 
536
        String[] inputs = tests.list(new XMLFilter());
 
537
        for (int i = 0; i < inputs.length; i++) {
 
538
            File input = new File(tests, inputs[i]);   
 
539
            Document doc = builder.build(input);
 
540
            ByteArrayOutputStream out = new ByteArrayOutputStream();
 
541
            try {
 
542
                Canonicalizer serializer = new Canonicalizer(
 
543
                  out, Canonicalizer.CANONICAL_XML_WITH_COMMENTS);
 
544
                serializer.write(doc);
 
545
            }
 
546
            finally {
 
547
                out.close();
 
548
            }            
 
549
            byte[] actual = out.toByteArray();
 
550
            
 
551
            // for debugging
 
552
            /* File debug = new File(canonical, "debug/" 
 
553
              + input.getName() + ".dbg");
 
554
            OutputStream fout = new FileOutputStream(debug);
 
555
            fout.write(actual);
 
556
            fout.close(); */
 
557
            
 
558
            File expected = new File(output, input.getName() + ".out");
 
559
            assertEquals(
 
560
              input.getName(), expected.length(), actual.length);
 
561
            byte[] expectedBytes = new byte[actual.length];
 
562
            InputStream fin = new FileInputStream(expected);
 
563
            DataInputStream in = new DataInputStream(fin);
 
564
            try {
 
565
                in.readFully(expectedBytes);
 
566
            }
 
567
            finally {
 
568
                in.close();
 
569
            }
 
570
            for (int j = 0; j < expectedBytes.length; j++) {
 
571
                assertEquals(expectedBytes[i], actual[i]);   
 
572
            }
 
573
            
 
574
        }
 
575
        
 
576
    }
 
577
    
 
578
    
 
579
    public void testWithoutComments() 
 
580
      throws ParsingException, IOException {
 
581
      
 
582
        File tests = input;
 
583
        String[] inputs = tests.list(new XMLFilter());
 
584
        for (int i = 0; i < inputs.length; i++) {
 
585
            File input = new File(tests, inputs[i]); 
 
586
            Document doc = builder.build(input);
 
587
           
 
588
            ByteArrayOutputStream out = new ByteArrayOutputStream();
 
589
            try {
 
590
                Canonicalizer serializer 
 
591
                  = new Canonicalizer(out, false);
 
592
                serializer.write(doc);
 
593
            }
 
594
            finally {
 
595
                out.close();
 
596
            }
 
597
            
 
598
            byte[] actual = out.toByteArray();
 
599
            
 
600
            File expected = new File(canonical, "wocommentsoutput/");
 
601
            expected = new File(expected, input.getName() + ".out");
 
602
            byte[] expectedBytes = new byte[actual.length];
 
603
            InputStream fin = new FileInputStream(expected);
 
604
            DataInputStream in =  new DataInputStream(fin);
 
605
            try {
 
606
                in.readFully(expectedBytes);
 
607
            }
 
608
            finally {
 
609
                in.close();
 
610
            }
 
611
            for (int j = 0; j < expectedBytes.length; j++) {
 
612
                assertEquals(expectedBytes[i], actual[i]);   
 
613
            }
 
614
            out.close();
 
615
 
 
616
        }
 
617
        
 
618
    }   
 
619
    
 
620
    
 
621
    public void testNamedAlgorithmWithoutComments() 
 
622
      throws ParsingException, IOException {
 
623
      
 
624
        File tests = input;
 
625
        String[] inputs = tests.list(new XMLFilter());
 
626
        for (int i = 0; i < inputs.length; i++) {
 
627
            File input = new File(tests, inputs[i]); 
 
628
            Document doc = builder.build(input);
 
629
           
 
630
            ByteArrayOutputStream out = new ByteArrayOutputStream();
 
631
            try {
 
632
                Canonicalizer serializer = new Canonicalizer(
 
633
                  out, Canonicalizer.CANONICAL_XML);
 
634
                serializer.write(doc);
 
635
            }
 
636
            finally {
 
637
                out.close();
 
638
            }
 
639
            
 
640
            byte[] actual = out.toByteArray();
 
641
            
 
642
            File expected = new File(canonical, "wocommentsoutput/");
 
643
            expected = new File(expected, input.getName() + ".out");
 
644
            byte[] expectedBytes = new byte[actual.length];
 
645
            InputStream fin = new FileInputStream(expected);
 
646
            DataInputStream in =  new DataInputStream(fin);
 
647
            try {
 
648
                in.readFully(expectedBytes);
 
649
            }
 
650
            finally {
 
651
                in.close();
 
652
            }
 
653
            for (int j = 0; j < expectedBytes.length; j++) {
 
654
                assertEquals(expectedBytes[i], actual[i]);   
 
655
            }
 
656
            out.close();
 
657
 
 
658
        }
 
659
        
 
660
    }   
 
661
    
 
662
    
 
663
    public void testXMLNamespaceAttributeInheritance() 
 
664
      throws IOException {
 
665
     
 
666
        Element root = new Element("root");
 
667
        Document doc = new Document(root);
 
668
        root.addAttribute(new Attribute("xml:id", Namespace.XML_NAMESPACE, "p1"));
 
669
        root.appendChild(new Element("child312"));
 
670
        
 
671
        String expected = "<child312 xml:id=\"p1\"></child312>";
 
672
 
 
673
        ByteArrayOutputStream out = new ByteArrayOutputStream();
 
674
        try {
 
675
            Canonicalizer serializer = new Canonicalizer(out, false);
 
676
            serializer.write(doc.query("/*/child312"));
 
677
        }
 
678
        finally {
 
679
            out.close();
 
680
        }
 
681
            
 
682
        String actual = new String(out.toByteArray(), "UTF-8");
 
683
        assertEquals(expected, actual);
 
684
        
 
685
    }
 
686
    
 
687
    
 
688
    public void testXMLNamespaceAttributeInheritanceThroughMultipleLevels() 
 
689
      throws IOException {
 
690
     
 
691
        Element superroot = new Element("superroot");
 
692
        Element root = new Element("root");
 
693
        superroot.appendChild(root);
 
694
        superroot.addAttribute(new Attribute("xml:id", Namespace.XML_NAMESPACE, "p0"));
 
695
        Document doc = new Document(superroot);
 
696
        root.addAttribute(new Attribute("xml:id", Namespace.XML_NAMESPACE, "p1"));
 
697
        root.appendChild(new Element("child312"));
 
698
        
 
699
        String expected = "<child312 xml:id=\"p1\"></child312>";
 
700
 
 
701
        ByteArrayOutputStream out = new ByteArrayOutputStream();
 
702
        try {
 
703
            Canonicalizer serializer = new Canonicalizer(out, false);
 
704
            Nodes result = doc.query("/*/*/child312");
 
705
            serializer.write(result);
 
706
        }
 
707
        finally {
 
708
            out.close();
 
709
        }
 
710
            
 
711
        String actual = new String(out.toByteArray(), "UTF-8");
 
712
        assertEquals(expected, actual);
 
713
        
 
714
    }
 
715
    
 
716
    
 
717
    public void testXMLNamespaceAttributeInheritanceThroughMultipleLevelsWithSkippedMiddle() 
 
718
      throws IOException {
 
719
     
 
720
        Element superroot = new Element("superroot");
 
721
        Element root = new Element("root");
 
722
        superroot.appendChild(root);
 
723
        superroot.addAttribute(new Attribute("xml:id", Namespace.XML_NAMESPACE, "p0"));
 
724
        Document doc = new Document(superroot);
 
725
        root.addAttribute(new Attribute("xml:id", Namespace.XML_NAMESPACE, "p1"));
 
726
        root.appendChild(new Element("child312"));
 
727
        
 
728
        String expected = "<superroot xml:id=\"p0\"><child312 xml:id=\"p1\"></child312></superroot>";
 
729
 
 
730
        ByteArrayOutputStream out = new ByteArrayOutputStream();
 
731
        try {
 
732
            Canonicalizer serializer = new Canonicalizer(out, false);
 
733
            serializer.write(doc.query("/* | //child312 | /*/@* | //child312/@*"));
 
734
        }
 
735
        finally {
 
736
            out.close();
 
737
        }
 
738
            
 
739
        String actual = new String(out.toByteArray(), "UTF-8");
 
740
        assertEquals(expected, actual);
 
741
        
 
742
    }
 
743
    
 
744
    
 
745
    public void testXMLNamespaceAttributeInheritanceNearestIsInSubset() 
 
746
      throws IOException {
 
747
     
 
748
        Element superroot = new Element("superroot");
 
749
        Element root = new Element("root");
 
750
        superroot.appendChild(root);
 
751
        superroot.addAttribute(new Attribute("xml:id", Namespace.XML_NAMESPACE, "p0"));
 
752
        Document doc = new Document(superroot);
 
753
        root.appendChild(new Element("child312"));
 
754
        
 
755
        String expected = "<superroot xml:id=\"p0\"><child312></child312></superroot>";
 
756
 
 
757
        ByteArrayOutputStream out = new ByteArrayOutputStream();
 
758
        try {
 
759
            Canonicalizer serializer = new Canonicalizer(out, false);
 
760
            serializer.write(doc.query("/* | //child312 | /*/@* | //child312/@*"));
 
761
        }
 
762
        finally {
 
763
            out.close();
 
764
        }
 
765
            
 
766
        String actual = new String(out.toByteArray(), "UTF-8");
 
767
        assertEquals(expected, actual);
 
768
        
 
769
    }
 
770
    
 
771
    
 
772
    public void testXMLNamespaceAttributeNotOverridden() 
 
773
      throws IOException {
 
774
     
 
775
        Element root = new Element("root");
 
776
        Document doc = new Document(root);
 
777
        Element child = new Element("child312");
 
778
        
 
779
        root.addAttribute(new Attribute("xml:id", Namespace.XML_NAMESPACE, "p1"));
 
780
        child.addAttribute(new Attribute("xml:id", Namespace.XML_NAMESPACE, "p2"));
 
781
        
 
782
        root.appendChild(child);
 
783
        
 
784
        String expected = "<child312 xml:id=\"p2\"></child312>";
 
785
 
 
786
        ByteArrayOutputStream out = new ByteArrayOutputStream();
 
787
        try {
 
788
            Canonicalizer serializer = new Canonicalizer(out, false);
 
789
            serializer.write(doc.query("/*/child312 | /*/*/@*"));
 
790
        }
 
791
        finally {
 
792
            out.close();
 
793
        }
 
794
            
 
795
        String actual = new String(out.toByteArray(), "UTF-8");
 
796
        assertEquals(expected, actual);
 
797
        
 
798
    }
 
799
    
 
800
    
 
801
    public void testXMLNamespaceAttributeNotOverridden2() 
 
802
      throws IOException {
 
803
     
 
804
        Element root = new Element("root");
 
805
        Document doc = new Document(root);
 
806
        Element child = new Element("child312");
 
807
        
 
808
        root.addAttribute(new Attribute("xml:id", Namespace.XML_NAMESPACE, "p1"));
 
809
        child.addAttribute(new Attribute("xml:id", Namespace.XML_NAMESPACE, "p2"));
 
810
        
 
811
        root.appendChild(child);
 
812
        
 
813
        String expected = "<child312></child312>";
 
814
 
 
815
        ByteArrayOutputStream out = new ByteArrayOutputStream();
 
816
        try {
 
817
            Canonicalizer serializer = new Canonicalizer(out, false);
 
818
            serializer.write(doc.query("/*/child312 "));
 
819
        }
 
820
        finally {
 
821
            out.close();
 
822
        }
 
823
            
 
824
        String actual = new String(out.toByteArray(), "UTF-8");
 
825
        assertEquals(expected, actual);
 
826
        
 
827
    }
 
828
    
 
829
    
 
830
    public void testXMLNamespaceAttributeNotInheritedWithExclusiveCanonicalization() 
 
831
      throws IOException {
 
832
     
 
833
        Element root = new Element("root");
 
834
        Document doc = new Document(root);
 
835
        root.addAttribute(new Attribute("xml:id", Namespace.XML_NAMESPACE, "p1"));
 
836
        root.appendChild(new Element("child312"));
 
837
        
 
838
        String expected = "<child312></child312>";
 
839
 
 
840
        ByteArrayOutputStream out = new ByteArrayOutputStream();
 
841
        try {
 
842
            Canonicalizer serializer = new Canonicalizer(out, 
 
843
              Canonicalizer.EXCLUSIVE_XML_CANONICALIZATION);
 
844
            serializer.write(doc.query("/*/child312"));
 
845
        }
 
846
        finally {
 
847
            out.close();
 
848
        }
 
849
            
 
850
        String actual = new String(out.toByteArray(), "UTF-8");
 
851
        assertEquals(expected, actual);
 
852
        
 
853
    }
 
854
    
 
855
    
 
856
    public void testXMLNSAttributeNotInheritedWithExclusiveCanonicalization() 
 
857
      throws IOException {
 
858
     
 
859
        Element root = new Element("root", "http://www.example.org/");
 
860
        Document doc = new Document(root);
 
861
        root.appendChild(new Element("child312", "http://www.example.org/"));
 
862
        
 
863
        String expected = "<child312 xmlns=\"http://www.example.org/\"></child312>";
 
864
 
 
865
        ByteArrayOutputStream out = new ByteArrayOutputStream();
 
866
        try {
 
867
            Canonicalizer serializer = new Canonicalizer(out,
 
868
              Canonicalizer.EXCLUSIVE_XML_CANONICALIZATION);
 
869
            XPathContext context = new XPathContext("pre", "http://www.example.org/");
 
870
            serializer.write(doc.query("/*/pre:child312 | /*/pre:child312/namespace::node()", 
 
871
             context));
 
872
        }
 
873
        finally {
 
874
            out.close();
 
875
        }
 
876
            
 
877
        String actual = new String(out.toByteArray(), "UTF-8");
 
878
        assertEquals(expected, actual);
 
879
        
 
880
    }
 
881
    
 
882
    
 
883
    public void testXMLNSPrefixAttributeInheritedWithExclusiveCanonicalization() 
 
884
      throws IOException {
 
885
     
 
886
        Element root = new Element("pre:root", "http://www.example.org/");
 
887
        Document doc = new Document(root);
 
888
        root.appendChild(new Element("pre:child312", "http://www.example.org/"));
 
889
        
 
890
        String expected = "<pre:child312 xmlns:pre=\"http://www.example.org/\"></pre:child312>";
 
891
 
 
892
        ByteArrayOutputStream out = new ByteArrayOutputStream();
 
893
        try {
 
894
            XPathContext context = new XPathContext("pre", "http://www.example.org/");
 
895
            Canonicalizer serializer = new Canonicalizer(out,
 
896
          Canonicalizer.EXCLUSIVE_XML_CANONICALIZATION);
 
897
            serializer.write(doc.query("/*/pre:child312 | /*/pre:child312/namespace::node()", context));
 
898
        }
 
899
        finally {
 
900
            out.close();
 
901
        }
 
902
            
 
903
        String actual = new String(out.toByteArray(), "UTF-8");
 
904
        assertEquals(expected, actual);
 
905
        
 
906
    }
 
907
    
 
908
    
 
909
    public void testXMLNSEqualsEmptyString() 
 
910
      throws IOException {
 
911
     
 
912
        Element root = new Element("root", "http://www.ietf.org");
 
913
        Document doc = new Document(root);
 
914
        root.appendChild(new Element("child"));
 
915
        
 
916
        String expected = "<root xmlns=\"http://www.ietf.org\"><child xmlns=\"\"></child></root>";
 
917
 
 
918
        ByteArrayOutputStream out = new ByteArrayOutputStream();
 
919
        try {
 
920
            Canonicalizer serializer = new Canonicalizer(out, false);
 
921
            serializer.write(doc);
 
922
        }
 
923
        finally {
 
924
            out.close();
 
925
        }
 
926
            
 
927
        String actual = new String(out.toByteArray(), "UTF-8");
 
928
        assertEquals(expected, actual);
 
929
        
 
930
    }
 
931
    
 
932
    
 
933
    // from section 3.7 of spec
 
934
    public void testDocumentSubsetCanonicalization() 
 
935
      throws ParsingException, IOException {
 
936
        
 
937
        String input = "<!DOCTYPE doc [\n"
 
938
            + "<!ATTLIST e2 xml:space (default|preserve) 'preserve'>\n"
 
939
            + "<!ATTLIST e3 id ID #IMPLIED>\n"
 
940
            + "]>\n"
 
941
            + "<doc xmlns=\"http://www.ietf.org\" xmlns:w3c=\"http://www.w3.org\">\n"
 
942
            + "   <e1>\n"
 
943
            + "      <e2 xmlns=\"\">\n"
 
944
            + "         <e3 id=\"E3\"/>\n"
 
945
            + "      </e2>\n"
 
946
            + "   </e1>\n"
 
947
            + "</doc>";
 
948
        
 
949
        Document doc = builder.build(input, null);
 
950
        XPathContext context = new XPathContext("ietf", "http://www.ietf.org");
 
951
        String xpath = "(//. | //@* | //namespace::*)\n"
 
952
            + "[\n"
 
953
            + "self::ietf:e1 or (parent::ietf:e1 and not(self::text() or self::e2))"
 
954
            + " or\n"
 
955
            + " count(id(\"E3\")|ancestor-or-self::node()) = count(ancestor-or-self::node())\n"
 
956
            + "]";
 
957
        
 
958
        String expected = "<e1 xmlns=\"http://www.ietf.org\" "
 
959
          + "xmlns:w3c=\"http://www.w3.org\"><e3 xmlns=\"\" id=\"E3\" xml:space=\"preserve\"></e3></e1>";
 
960
 
 
961
        ByteArrayOutputStream out = new ByteArrayOutputStream();
 
962
        try {
 
963
            Canonicalizer serializer = new Canonicalizer(out, false);
 
964
            serializer.write(doc.query(xpath, context));
 
965
        }
 
966
        finally {
 
967
            out.close();
 
968
        }
 
969
            
 
970
        String actual = new String(out.toByteArray(), "UTF-8");
 
971
        assertEquals(expected, actual);
 
972
        
 
973
    }
 
974
    
 
975
    
 
976
    public void testCanonicalizeEmptyDocumentSubset() 
 
977
      throws ParsingException, IOException {
 
978
        
 
979
        String input = "<!DOCTYPE doc [\n"
 
980
            + "<!ATTLIST e2 xml:space (default|preserve) 'preserve'>\n"
 
981
            + "<!ATTLIST e3 id ID #IMPLIED>\n"
 
982
            + "]>\n"
 
983
            + "<doc xmlns=\"http://www.ietf.org\" xmlns:w3c=\"http://www.w3.org\">\n"
 
984
            + "   <e1>\n"
 
985
            + "      <e2 xmlns=\"\">\n"
 
986
            + "         <e3 id=\"E3\"/>\n"
 
987
            + "      </e2>\n"
 
988
            + "   </e1>\n"
 
989
            + "</doc>";
 
990
        
 
991
        Document doc = builder.build(input, null);
 
992
        XPathContext context = new XPathContext("ietf", "http://www.ietf.org");
 
993
        String xpath = "//aaa";
 
994
        ByteArrayOutputStream out = new ByteArrayOutputStream();
 
995
        try {
 
996
            Canonicalizer serializer = new Canonicalizer(out, false);
 
997
            serializer.write(doc.query(xpath, context));
 
998
        }
 
999
        finally {
 
1000
            out.close();
 
1001
        }
 
1002
            
 
1003
        String actual = new String(out.toByteArray(), "UTF-8");
 
1004
        assertEquals("", actual);
 
1005
        
 
1006
    }
 
1007
    
 
1008
    
 
1009
    public void testDocumentSubsetCanonicalizationSkippingProcessingInstructions() 
 
1010
      throws ParsingException, IOException {
 
1011
        
 
1012
        String input = "<!DOCTYPE doc [\n"
 
1013
            + "<!ATTLIST e3 id ID #IMPLIED>\n"
 
1014
            + "]>\n<?test?>"
 
1015
            + "<doc xmlns=\"http://www.ietf.org\" xmlns:w3c=\"http://www.w3.org\">\n"
 
1016
            + "   <e1><?test?>\n"
 
1017
            + "      <e2 xmlns=\"\">\n"
 
1018
            + "         <e3 id=\"E3\"/>\n"
 
1019
            + "      </e2>\n"
 
1020
            + "   </e1>\n"
 
1021
            + "</doc><?test?>";
 
1022
        
 
1023
        String expected = "<doc xmlns=\"http://www.ietf.org\" xmlns:w3c=\"http://www.w3.org\">\n"
 
1024
            + "   <e1>\n"
 
1025
            + "      <e2 xmlns=\"\">\n"
 
1026
            + "         <e3 id=\"E3\"></e3>\n"
 
1027
            + "      </e2>\n"
 
1028
            + "   </e1>\n"
 
1029
            + "</doc>";
 
1030
        
 
1031
        Document doc = builder.build(input, null);
 
1032
        XPathContext context = new XPathContext("ietf", "http://www.ietf.org");
 
1033
        String xpath = "//* | //text() | //@* | //namespace::*";
 
1034
        
 
1035
        ByteArrayOutputStream out = new ByteArrayOutputStream();
 
1036
        try {
 
1037
            Canonicalizer serializer = new Canonicalizer(out, false);
 
1038
            serializer.write(doc.query(xpath, context));
 
1039
        }
 
1040
        finally {
 
1041
            out.close();
 
1042
        }
 
1043
            
 
1044
        String actual = new String(out.toByteArray(), "UTF-8");
 
1045
        assertEquals(expected, actual);
 
1046
        
 
1047
    }
 
1048
    
 
1049
    
 
1050
    public void testDocumentSubsetCanonicalizationWithoutSelectingPrologAndEpilog() 
 
1051
      throws ParsingException, IOException {
 
1052
        
 
1053
        String input = "<!-- prolog -->\n"
 
1054
            + "<!DOCTYPE doc [\n"
 
1055
            + "<!ATTLIST e2 xml:space (default|preserve) 'preserve'>\n"
 
1056
            + "<!ATTLIST e3 id ID #IMPLIED>\n"
 
1057
            + "]>\n"
 
1058
            + "<doc xmlns=\"http://www.ietf.org\" xmlns:w3c=\"http://www.w3.org\">\n"
 
1059
            + "   <e1>\n"
 
1060
            + "      <e2 xmlns=\"\">\n"
 
1061
            + "         <e3 id=\"E3\"/>\n"
 
1062
            + "      </e2>\n"
 
1063
            + "   </e1>\n"
 
1064
            + "</doc><!-- epilog -->";
 
1065
        
 
1066
        Document doc = builder.build(input, null);
 
1067
        XPathContext context = new XPathContext("ietf", "http://www.ietf.org");
 
1068
        String xpath = "(/*//. | //@* | //namespace::*)\n"
 
1069
            + "[\n"
 
1070
            + "self::ietf:e1 or (parent::ietf:e1 and not(self::text() or self::e2))"
 
1071
            + " or\n"
 
1072
            + " count(id(\"E3\")|ancestor-or-self::node()) = count(ancestor-or-self::node())\n"
 
1073
            + "]";
 
1074
        
 
1075
        String expected = "<e1 xmlns=\"http://www.ietf.org\" "
 
1076
          + "xmlns:w3c=\"http://www.w3.org\"><e3 xmlns=\"\" id=\"E3\" xml:space=\"preserve\"></e3></e1>";
 
1077
 
 
1078
        ByteArrayOutputStream out = new ByteArrayOutputStream();
 
1079
        try {
 
1080
            Canonicalizer serializer = new Canonicalizer(out, Canonicalizer.CANONICAL_XML_WITH_COMMENTS);
 
1081
            serializer.write(doc.query(xpath, context));
 
1082
        }
 
1083
        finally {
 
1084
            out.close();
 
1085
        }
 
1086
            
 
1087
        String actual = new String(out.toByteArray(), "UTF-8");
 
1088
        assertEquals(expected, actual);
 
1089
        
 
1090
    }
 
1091
    
 
1092
    
 
1093
    public void testEmptyDefaultNamespace() 
 
1094
      throws ParsingException, IOException {
 
1095
        
 
1096
        String input = "<doc xmlns=\"http://www.ietf.org\">"
 
1097
            + "<e2 xmlns=\"\"></e2>"
 
1098
            + "</doc>";
 
1099
        
 
1100
        Document doc = builder.build(input, null);
 
1101
        String xpath = "(//* | //namespace::*)";
 
1102
        
 
1103
        String expected = input;
 
1104
 
 
1105
        ByteArrayOutputStream out = new ByteArrayOutputStream();
 
1106
        try {
 
1107
            Canonicalizer serializer = new Canonicalizer(out, false);
 
1108
            serializer.write(doc.query(xpath));
 
1109
        }
 
1110
        finally {
 
1111
            out.close();
 
1112
        }
 
1113
            
 
1114
        String actual = new String(out.toByteArray(), "UTF-8");
 
1115
        assertEquals(expected, actual);
 
1116
        
 
1117
    }
 
1118
 
 
1119
    
 
1120
    
 
1121
    public void testDocumentSubsetCanonicalizationSimple() 
 
1122
      throws ParsingException, IOException {
 
1123
        
 
1124
        String input = "<!DOCTYPE doc [\n"
 
1125
            + "<!ATTLIST e2 xml:space (default|preserve) 'preserve'>\n"
 
1126
            + "<!ATTLIST e3 id ID #IMPLIED>\n"
 
1127
            + "]>\n"
 
1128
            + "<doc xmlns=\"http://www.ietf.org\" xmlns:w3c=\"http://www.w3.org\">\n"
 
1129
            + "   <e1>\n"
 
1130
            + "      <e2 xmlns=\"\">\n"
 
1131
            + "         <e3 id=\"E3\"/>\n"
 
1132
            + "      </e2>\n"
 
1133
            + "   </e1>\n"
 
1134
            + "</doc>";
 
1135
        
 
1136
        Document doc = builder.build(input, null);
 
1137
        XPathContext context = new XPathContext("ietf", "http://www.ietf.org");
 
1138
        String xpath = "(/* | /*/namespace::*)\n";
 
1139
        
 
1140
        String expected = "<doc xmlns=\"http://www.ietf.org\" xmlns:w3c=\"http://www.w3.org\"></doc>";
 
1141
 
 
1142
        ByteArrayOutputStream out = new ByteArrayOutputStream();
 
1143
        try {
 
1144
            Canonicalizer serializer = new Canonicalizer(out, false);
 
1145
            serializer.write(doc.query(xpath, context));
 
1146
        }
 
1147
        finally {
 
1148
            out.close();
 
1149
        }
 
1150
            
 
1151
        String actual = new String(out.toByteArray(), "UTF-8");
 
1152
        assertEquals(expected, actual);
 
1153
        
 
1154
    }
 
1155
    
 
1156
 
 
1157
    public void testCanonicalizeDocumentSubsetIncludingRoot() 
 
1158
      throws ParsingException, IOException {
 
1159
        
 
1160
        String input = "<doc />";
 
1161
        
 
1162
        Document doc = builder.build(input, null);
 
1163
        
 
1164
        String expected = "<doc></doc>";
 
1165
 
 
1166
        ByteArrayOutputStream out = new ByteArrayOutputStream();
 
1167
        try {
 
1168
            Canonicalizer serializer = new Canonicalizer(out, false);
 
1169
            Nodes subset = doc.query("//.");
 
1170
            serializer.write(subset);
 
1171
        }
 
1172
        finally {
 
1173
            out.close();
 
1174
        }
 
1175
            
 
1176
        String actual = new String(out.toByteArray(), "UTF-8");
 
1177
        assertEquals(expected, actual);
 
1178
        
 
1179
    }
 
1180
    
 
1181
 
 
1182
    public void testCanonicalizeDocumentSubsetThatOnlyContainsRoot() 
 
1183
      throws IOException {
 
1184
        
 
1185
        Document doc = new Document(new Element("root"));
 
1186
 
 
1187
        ByteArrayOutputStream out = new ByteArrayOutputStream();
 
1188
        try {
 
1189
            Canonicalizer serializer = new Canonicalizer(out, false);
 
1190
            Nodes subset = doc.query("/");
 
1191
            serializer.write(subset);
 
1192
        }
 
1193
        finally {
 
1194
            out.close();
 
1195
        }
 
1196
            
 
1197
        String actual = new String(out.toByteArray(), "UTF-8");
 
1198
        assertEquals("", actual);
 
1199
        
 
1200
    }
 
1201
    
 
1202
 
 
1203
    public void testDocumentSubsetCanonicalizationNamespaceInheritance() 
 
1204
      throws ParsingException, IOException {
 
1205
        
 
1206
        String input = "<!DOCTYPE doc [\n"
 
1207
            + "<!ATTLIST e2 xml:space (default|preserve) 'preserve'>\n"
 
1208
            + "<!ATTLIST e3 id ID #IMPLIED>\n"
 
1209
            + "]>\n"
 
1210
            + "<doc xmlns=\"http://www.ietf.org\" xmlns:w3c=\"http://www.w3.org\">\n"
 
1211
            + "   <e1>\n"
 
1212
            + "      <e2 xmlns=\"\">\n"
 
1213
            + "         <e3 id=\"E3\"/>\n"
 
1214
            + "      </e2>\n"
 
1215
            + "   </e1>\n"
 
1216
            + "</doc>";
 
1217
        
 
1218
        Document doc = builder.build(input, null);
 
1219
        XPathContext context = new XPathContext("ietf", "http://www.ietf.org");
 
1220
        String xpath = "(/*/* | /*/*/namespace::*)\n";
 
1221
        
 
1222
        String expected = "<e1 xmlns=\"http://www.ietf.org\" xmlns:w3c=\"http://www.w3.org\"></e1>";
 
1223
 
 
1224
        ByteArrayOutputStream out = new ByteArrayOutputStream();
 
1225
        try {
 
1226
            Canonicalizer serializer = new Canonicalizer(out, false);
 
1227
            serializer.write(doc.query(xpath, context));
 
1228
        }
 
1229
        finally {
 
1230
            out.close();
 
1231
        }
 
1232
            
 
1233
        String actual = new String(out.toByteArray(), "UTF-8");
 
1234
        assertEquals(expected, actual);
 
1235
        
 
1236
    }
 
1237
    
 
1238
    
 
1239
    public void testRelativeNamespaceURIsForbidden() 
 
1240
      throws ParsingException, IOException {
 
1241
        
 
1242
        try {
 
1243
            String data = "<test xmlns=\"relative\">data</test>";
 
1244
            Document doc = builder.build(data, "http://www.ex.org/");
 
1245
            ByteArrayOutputStream out = new ByteArrayOutputStream();
 
1246
            Canonicalizer serializer
 
1247
              = new Canonicalizer(out, false);
 
1248
            serializer.write(doc);
 
1249
            fail("Canonicalized document with relative namespace URI");
 
1250
        }
 
1251
        catch (ParsingException success) {
 
1252
            assertNotNull(success.getMessage());
 
1253
        }    
 
1254
        
 
1255
    }
 
1256
    
 
1257
    
 
1258
    private static class XMLFilter implements FilenameFilter {
 
1259
                
 
1260
        public boolean accept(File directory, String name) {
 
1261
            if (name.endsWith(".xml")) return true;
 
1262
            return false;           
 
1263
        }
 
1264
        
 
1265
    }
 
1266
    
 
1267
    
 
1268
    public void testNFCFromISO88591() 
 
1269
      throws ParsingException, IOException {
 
1270
        isoNormalizationTest("ISO-8859-1");
 
1271
    }
 
1272
    
 
1273
    
 
1274
    public void testNFCFromISO88592() 
 
1275
      throws ParsingException, IOException {
 
1276
        isoNormalizationTest("ISO-8859-2");
 
1277
    }
 
1278
    
 
1279
    
 
1280
    public void testNFCFromISO88593() 
 
1281
      throws ParsingException, IOException {
 
1282
        isoNormalizationTest("ISO-8859-3");
 
1283
    }
 
1284
    
 
1285
    
 
1286
    public void testNFCFromISO88594() 
 
1287
      throws ParsingException, IOException {
 
1288
        isoNormalizationTest("ISO-8859-4");
 
1289
    }
 
1290
    
 
1291
    
 
1292
    public void testNFCFromISO88595() 
 
1293
      throws ParsingException, IOException {
 
1294
        isoNormalizationTest("ISO-8859-5");
 
1295
    }
 
1296
    
 
1297
    
 
1298
    public void testNFCFromISO88596() 
 
1299
      throws ParsingException, IOException {
 
1300
        
 
1301
        // This test fails in 1.2.2 due to an apparent bug in the 
 
1302
        // conversion of the characters '1' and '0' to bytes in 
 
1303
        // ISO-8859-6
 
1304
        isoNormalizationTest("ISO-8859-6");
 
1305
        
 
1306
    }
 
1307
    
 
1308
    
 
1309
    public void testNFCFromISO88597() 
 
1310
      throws ParsingException, IOException {
 
1311
        isoNormalizationTest("ISO-8859-7");
 
1312
    }
 
1313
    
 
1314
    
 
1315
    public void testNFCFromISO88598() 
 
1316
      throws ParsingException, IOException {
 
1317
        isoNormalizationTest("ISO-8859-8");
 
1318
    }
 
1319
    
 
1320
    
 
1321
    public void testNFCFromISO88599() 
 
1322
      throws ParsingException, IOException {
 
1323
        isoNormalizationTest("ISO-8859-9");
 
1324
    }
 
1325
    
 
1326
    
 
1327
    public void testNFCFromISO885913() 
 
1328
      throws ParsingException, IOException {
 
1329
        
 
1330
        if (version >= 1.3) {
 
1331
            // iSO-8859-6 not supported in Java 1.2
 
1332
            isoNormalizationTest("ISO-8859-13");
 
1333
        }
 
1334
        
 
1335
    }
 
1336
 
 
1337
    
 
1338
    public void testNFCFromISO885915() 
 
1339
      throws ParsingException, IOException {
 
1340
        isoNormalizationTest("ISO-8859-15");
 
1341
    }
 
1342
    
 
1343
    
 
1344
    // 14 and 16 aren't tested because Java doesn't support them yet
 
1345
    private void isoNormalizationTest(String encoding)
 
1346
      throws ParsingException, IOException {
 
1347
        
 
1348
        String prolog = "<?xml version='1.0' encoding='" 
 
1349
          + encoding + "'?>\r\n<root>";
 
1350
        
 
1351
        byte[] prologData = prolog.getBytes(encoding);
 
1352
        
 
1353
        String epilog = "</root>";
 
1354
        byte[] epilogData = epilog.getBytes(encoding);      
 
1355
        byte[] data = new byte[prologData.length + epilogData.length + 255 - 160 + 1];
 
1356
        System.arraycopy(prologData, 0, data, 0, prologData.length);
 
1357
        System.arraycopy(epilogData, 0, data, 
 
1358
          data.length - epilogData.length, epilogData.length);
 
1359
        for (int i = 160; i <= 255; i++) {
 
1360
            data[prologData.length + (i-160)] = (byte) i;   
 
1361
        }
 
1362
        InputStream in = new ByteArrayInputStream(data);
 
1363
        Document doc = builder.build(in);
 
1364
        
 
1365
        // make a Unicode normalized version of the same document
 
1366
        ByteArrayOutputStream out = new ByteArrayOutputStream();
 
1367
        Serializer serializer = new Serializer(out);
 
1368
        serializer.setUnicodeNormalizationFormC(true);
 
1369
        serializer.write(doc);
 
1370
        byte[] temp = out.toByteArray();
 
1371
        in = new ByteArrayInputStream(temp);
 
1372
        Document nfcDoc = builder.build(in);
 
1373
        
 
1374
        assertEquals("Parser doesn't use NFC when converting from " + encoding, 
 
1375
          doc, nfcDoc);
 
1376
        
 
1377
    }
 
1378
 
 
1379
    
 
1380
    public void testEBCDIC()
 
1381
      throws ParsingException, IOException {
 
1382
          
 
1383
        String encoding = "IBM037";
 
1384
        String prolog = "<?xml version='1.0' encoding='" 
 
1385
          + encoding + "'?>\r\n<root>";
 
1386
        byte[] prologData = prolog.getBytes(encoding);
 
1387
        String epilog = "</root>";
 
1388
        byte[] epilogData = epilog.getBytes(encoding);      
 
1389
        byte[] data = new byte[prologData.length + epilogData.length + 255 - 160 + 1];
 
1390
        System.arraycopy(prologData, 0, data, 0, prologData.length);
 
1391
        System.arraycopy(epilogData, 0, data, 
 
1392
          data.length - epilogData.length, epilogData.length);
 
1393
        StringBuffer buffer = new StringBuffer(255 - 160 + 1);
 
1394
        for (int i = 160; i <= 255; i++) {
 
1395
            buffer.append((char) i);   
 
1396
        }
 
1397
        byte[] temp = buffer.toString().getBytes(encoding);
 
1398
        System.arraycopy(temp, 0, data, prologData.length, temp.length);        
 
1399
        InputStream in = new ByteArrayInputStream(data);
 
1400
        Document doc = builder.build(in);
 
1401
        
 
1402
        // make a Unicode normalized version of the same document
 
1403
        ByteArrayOutputStream out = new ByteArrayOutputStream();
 
1404
        Serializer serializer = new Serializer(out);
 
1405
        serializer.setUnicodeNormalizationFormC(true);
 
1406
        serializer.write(doc);
 
1407
        temp = out.toByteArray();
 
1408
        in = new ByteArrayInputStream(temp);
 
1409
        Document nfcDoc = builder.build(in);
 
1410
        
 
1411
        // String normalizedResult = Normalizer.normalize(rawResult, Normalizer.NFC);
 
1412
        assertEquals("Parser doesn't use NFC when converting from " + encoding, 
 
1413
          doc, nfcDoc);
 
1414
        
 
1415
    }
 
1416
 
 
1417
    
 
1418
    // make sure null pointer exception doesn't cause any output
 
1419
    public void testNullDocument() 
 
1420
      throws IOException {
 
1421
        
 
1422
        ByteArrayOutputStream out = new ByteArrayOutputStream();
 
1423
        Canonicalizer canonicalizer = new Canonicalizer(out);
 
1424
        try {
 
1425
            canonicalizer.write((Document) null);  
 
1426
            fail("Wrote null document"); 
 
1427
        }   
 
1428
        catch (NullPointerException success) {
 
1429
            // success   
 
1430
        }
 
1431
        byte[] result = out.toByteArray();
 
1432
        assertEquals(0, result.length);
 
1433
        
 
1434
    }
 
1435
    
 
1436
    
 
1437
    public void testWhiteSpaceTrimmingInNonCDATAAttribute() 
 
1438
      throws IOException {
 
1439
        
 
1440
        Attribute attribute = new Attribute("name", "  value1  value2  ");
 
1441
        attribute.setType(Attribute.Type.NMTOKENS);
 
1442
        Element root = new Element("root");
 
1443
        root.addAttribute(attribute);
 
1444
        Document doc = new Document(root);
 
1445
        ByteArrayOutputStream out = new ByteArrayOutputStream();
 
1446
        Canonicalizer canonicalizer = new Canonicalizer(out);
 
1447
        canonicalizer.write(doc);
 
1448
        out.close();
 
1449
        String result = new String(out.toByteArray(), "UTF8");
 
1450
        assertEquals("<root name=\"value1 value2\"></root>", result);
 
1451
        
 
1452
    }
 
1453
    
 
1454
    
 
1455
    // compare to output generated by Apache XML Security code
 
1456
    public void testXMLConformanceTestSuiteDocuments() 
 
1457
      throws ParsingException, IOException {
 
1458
      
 
1459
        File masterList = new File(canonical, "xmlconf");
 
1460
        masterList = new File(masterList, "xmlconf.xml");
 
1461
        if (masterList.exists()) {
 
1462
            Document xmlconf = builder.build(masterList);
 
1463
            Elements testcases = xmlconf.getRootElement().getChildElements("TESTCASES");
 
1464
            processTestCases(testcases);
 
1465
        }
 
1466
 
 
1467
    }
 
1468
 
 
1469
    
 
1470
    // xmlconf/xmltest/valid/sa/097.xml appears to be screwed up by a lot
 
1471
    // of parsers 
 
1472
    private void processTestCases(Elements testcases) 
 
1473
      throws ParsingException, IOException {
 
1474
        
 
1475
        for (int i = 0; i < testcases.size(); i++) {
 
1476
              Element testcase = testcases.get(i); 
 
1477
              Elements tests = testcase.getChildElements("TEST");
 
1478
              processTests(tests);
 
1479
              Elements level2 = testcase.getChildElements("TESTCASES");
 
1480
              // need to be recursive to handle recursive IBM test cases
 
1481
              processTestCases(level2);
 
1482
        }
 
1483
        
 
1484
    }
 
1485
 
 
1486
 
 
1487
    private void processTests(Elements tests) 
 
1488
      throws ParsingException, IOException  {
 
1489
        
 
1490
        Element parent = new Element("e");
 
1491
        Element child = new Element("a");
 
1492
        parent.appendChild(child);
 
1493
        
 
1494
        int size = tests.size();
 
1495
        for (int i = 0; i < size; i++) {
 
1496
            Element test = tests.get(i);
 
1497
            String namespace = test.getAttributeValue("NAMESPACE");
 
1498
            if ("no".equals(namespace)) continue;
 
1499
            String type = test.getAttributeValue("TYPE");
 
1500
            if ("not-wf".equals(type)) continue;
 
1501
            String uri = test.getAttributeValue("URI");
 
1502
            String base = test.getBaseURI();
 
1503
            // Hack because URIUtil isn't public; and I don't want to
 
1504
            // depend on 1.4 only java.net.URI
 
1505
            parent.setBaseURI(base);
 
1506
 
 
1507
            child.addAttribute(new Attribute("xml:base", 
 
1508
              "http://www.w3.org/XML/1998/namespace", uri));
 
1509
            String resolvedURI = child.getBaseURI();
 
1510
            
 
1511
            Document doc = builder.build(resolvedURI);
 
1512
            ByteArrayOutputStream out = new ByteArrayOutputStream();
 
1513
            try {
 
1514
                Canonicalizer serializer = new Canonicalizer(out);
 
1515
                serializer.write(doc);
 
1516
            }
 
1517
            finally {
 
1518
                out.close();
 
1519
            }           
 
1520
            byte[] actual = out.toByteArray();
 
1521
            
 
1522
            File input = new File(resolvedURI.substring(5) + ".can");
 
1523
            assertEquals(resolvedURI, input.length(), actual.length);
 
1524
            byte[] expected = new byte[actual.length];
 
1525
            DataInputStream in = new DataInputStream(
 
1526
              new BufferedInputStream(new FileInputStream(input)));
 
1527
            try {
 
1528
                in.readFully(expected);
 
1529
            }
 
1530
            finally {
 
1531
                in.close();
 
1532
            }
 
1533
            assertEquals(expected, actual);
 
1534
            
 
1535
        }
 
1536
        
 
1537
    }
 
1538
 
 
1539
    
 
1540
    public void testExclusive() throws IOException {
 
1541
     
 
1542
        Element pdu = new Element("n0:pdu", "http://a.example");
 
1543
        Element elem1 = new Element("n1:elem1", "http://b.example");
 
1544
        elem1.appendChild("content");
 
1545
        pdu.appendChild(elem1);
 
1546
        
 
1547
        String expected = "<n1:elem1 xmlns:n1=\"http://b.example\">content</n1:elem1>";
 
1548
        ByteArrayOutputStream out = new ByteArrayOutputStream();
 
1549
        Canonicalizer canonicalizer = new Canonicalizer(out,
 
1550
          Canonicalizer.EXCLUSIVE_XML_CANONICALIZATION_WITH_COMMENTS);
 
1551
        
 
1552
        XPathContext context = new XPathContext("n1", "http://b.example");
 
1553
        Document doc = new Document(pdu);
 
1554
        canonicalizer.write(doc.query("(//. | //@* | //namespace::*)[ancestor-or-self::n1:elem1]", context));  
 
1555
        
 
1556
        byte[] result = out.toByteArray();
 
1557
        out.close();
 
1558
        String s = new String(out.toByteArray(), "UTF8");
 
1559
        assertEquals(expected, s);
 
1560
        
 
1561
    }
 
1562
    
 
1563
    public static void testAustB() throws IOException {
 
1564
        
 
1565
        Element e1 = new Element("a:a", "urn:a");
 
1566
        Element e2 = new Element("b");
 
1567
        e1.appendChild(e2);
 
1568
 
 
1569
        ByteArrayOutputStream out = new ByteArrayOutputStream();
 
1570
        Canonicalizer c = new Canonicalizer(out,
 
1571
        Canonicalizer.EXCLUSIVE_XML_CANONICALIZATION);
 
1572
        c.write(e1);
 
1573
        String s = out.toString("UTF8");
 
1574
        assertEquals("<a:a xmlns:a=\"urn:a\"><b></b></a:a>", s);
 
1575
        
 
1576
    }
 
1577
    
 
1578
    
 
1579
    public static void testAustB2() throws IOException {
 
1580
        
 
1581
        Element e1 = new Element("a:a", "urn:a");
 
1582
        Element e2 = new Element("b");
 
1583
        e1.appendChild(e2);
 
1584
 
 
1585
        ByteArrayOutputStream out = new ByteArrayOutputStream();
 
1586
        Canonicalizer c = new Canonicalizer(out);
 
1587
        c.write(e1);
 
1588
        String s = out.toString("UTF8");
 
1589
        assertEquals("<a:a xmlns:a=\"urn:a\"><b></b></a:a>", s);
 
1590
        
 
1591
    }
 
1592
    
 
1593
    
 
1594
    public static void testAust() throws Exception {
 
1595
        
 
1596
        Element e1 = new Element("a:a", "urn:a");
 
1597
        Element e2 = new Element("a:b", "urn:a");
 
1598
        e1.appendChild(e2);
 
1599
        ByteArrayOutputStream out = new ByteArrayOutputStream();
 
1600
        Canonicalizer c = new Canonicalizer(out,
 
1601
        Canonicalizer.EXCLUSIVE_XML_CANONICALIZATION);
 
1602
        c.write(e2);
 
1603
        String s = out.toString("UTF8");
 
1604
        assertEquals("<a:b xmlns:a=\"urn:a\"></a:b>", s);
 
1605
        
 
1606
    }
 
1607
    
 
1608
    
 
1609
    public static void testAust4() throws Exception {
 
1610
        
 
1611
        Element e1 = new Element("a:a", "urn:a");
 
1612
        Element e2 = new Element("a:b", "urn:a");
 
1613
        e1.appendChild(e2);
 
1614
        ByteArrayOutputStream out = new ByteArrayOutputStream();
 
1615
        Canonicalizer canonicalizer = new Canonicalizer(out,
 
1616
          Canonicalizer.EXCLUSIVE_XML_CANONICALIZATION_WITH_COMMENTS);
 
1617
        XPathContext context = new XPathContext("a", "urn:a");
 
1618
        Document doc = new Document(e1);
 
1619
        canonicalizer.write(doc.query("(//. | //@* | //namespace::*)[ancestor-or-self::a:b]", context));  
 
1620
 
 
1621
        String s = out.toString("UTF8");
 
1622
        assertEquals("<a:b xmlns:a=\"urn:a\"></a:b>", s);
 
1623
        
 
1624
    }
 
1625
    
 
1626
    
 
1627
    public static void testAust5() throws Exception {
 
1628
        
 
1629
        Element e1 = new Element("a:a", "urn:a");
 
1630
        Element e2 = new Element("a:b", "urn:a");
 
1631
        e1.appendChild(e2);
 
1632
        ByteArrayOutputStream out = new ByteArrayOutputStream();
 
1633
        Canonicalizer canonicalizer = new Canonicalizer(out,
 
1634
          Canonicalizer.EXCLUSIVE_XML_CANONICALIZATION_WITH_COMMENTS);
 
1635
        Document doc = new Document(e1);
 
1636
        Nodes set = new Nodes(e2);
 
1637
        canonicalizer.write(set);  
 
1638
 
 
1639
        String s = out.toString("UTF8");
 
1640
        // The namespace was not explicitly included in 
 
1641
        // the set so it should not be output.
 
1642
        assertEquals("<a:b></a:b>", s);
 
1643
        
 
1644
    }
 
1645
    
 
1646
    
 
1647
    public static void testAust3() throws Exception {
 
1648
        
 
1649
        Element e2 = new Element("a:b", "urn:a");
 
1650
        ByteArrayOutputStream os = new ByteArrayOutputStream();
 
1651
            new Canonicalizer(os,
 
1652
        Canonicalizer.EXCLUSIVE_XML_CANONICALIZATION).write(e2);
 
1653
        String s = os.toString("UTF8");
 
1654
        assertEquals("<a:b xmlns:a=\"urn:a\"></a:b>", s);
 
1655
        
 
1656
    }
 
1657
    
 
1658
    
 
1659
    public static void testAust2() throws Exception {
 
1660
        
 
1661
        Element e1 = new Element("a:a", "urn:a");
 
1662
        Element e2 = new Element("a:b", "urn:a");
 
1663
        e1.appendChild(e2);
 
1664
        ByteArrayOutputStream os = new ByteArrayOutputStream();
 
1665
            new Canonicalizer(os,
 
1666
        Canonicalizer.CANONICAL_XML).write(e2);
 
1667
        String s = os.toString("UTF8");
 
1668
        assertEquals("<a:b xmlns:a=\"urn:a\"></a:b>", s);
 
1669
        
 
1670
    }
 
1671
    
 
1672
    
 
1673
    public void testExclusiveWithNamespacedAttributes() throws IOException {
 
1674
     
 
1675
        Element pdu = new Element("n0:pdu", "http://a.example");
 
1676
        Element elem1 = new Element("n1:elem1", "http://b.example");
 
1677
        elem1.appendChild("content");
 
1678
        pdu.appendChild(elem1);
 
1679
        elem1.addAttribute(new Attribute("pre:foo", "http://www.example.org/", "value"));
 
1680
        
 
1681
        String expected = "<n1:elem1 xmlns:n1=\"http://b.example\" "
 
1682
          + "xmlns:pre=\"http://www.example.org/\" pre:foo=\"value\">content</n1:elem1>";
 
1683
        ByteArrayOutputStream out = new ByteArrayOutputStream();
 
1684
        Canonicalizer canonicalizer = new Canonicalizer(out,
 
1685
          Canonicalizer.EXCLUSIVE_XML_CANONICALIZATION_WITH_COMMENTS);
 
1686
        
 
1687
        XPathContext context = new XPathContext("n1", "http://b.example");
 
1688
        Document doc = new Document(pdu);
 
1689
        canonicalizer.write(doc.query("(//. | //@* | //namespace::*)[ancestor-or-self::n1:elem1]", context));  
 
1690
        
 
1691
        byte[] result = out.toByteArray();
 
1692
        out.close();
 
1693
        String s = new String(out.toByteArray(), "UTF8");
 
1694
        assertEquals(expected, s);
 
1695
        
 
1696
    }
 
1697
    
 
1698
 
 
1699
    /* <root xml:lang="en"><a><b>test</b></a></root>
 
1700
 
 
1701
Choose the document subset selected by /root//node()
 
1702
 
 
1703
and expect to see
 
1704
 
 
1705
<a xml:lang="en"><b>test</b></a> */
 
1706
    public void testInheritanceOfXMLLang() throws IOException {
 
1707
     
 
1708
        Element root = new Element("root");
 
1709
        root.addAttribute(new Attribute("xml:lang", Namespace.XML_NAMESPACE, "en"));
 
1710
        Element a = new Element("a");
 
1711
        Element b = new Element("b");
 
1712
        b.appendChild("test");
 
1713
        a.appendChild(b);
 
1714
        root.appendChild(a);
 
1715
        
 
1716
        String expected = "<a xml:lang=\"en\"><b>test</b></a>";
 
1717
        ByteArrayOutputStream out = new ByteArrayOutputStream();
 
1718
        Canonicalizer canonicalizer = new Canonicalizer(out, Canonicalizer.CANONICAL_XML);
 
1719
        
 
1720
        Document doc = new Document(root);
 
1721
        canonicalizer.write(doc.query("/root//node()"));  
 
1722
        
 
1723
        byte[] result = out.toByteArray();
 
1724
        out.close();
 
1725
        String s = new String(out.toByteArray(), "UTF8");
 
1726
        assertEquals(expected, s);
 
1727
        
 
1728
    }    
 
1729
        
 
1730
 
 
1731
    public void testExclusiveWithInclusiveNamespaces() 
 
1732
      throws IOException {
 
1733
     
 
1734
        Element pdu = new Element("n0:pdu", "http://a.example");
 
1735
        Element elem1 = new Element("n1:elem1", "http://b.example");
 
1736
        elem1.appendChild("content");
 
1737
        pdu.appendChild(elem1);
 
1738
        
 
1739
        String expected = "<n1:elem1 xmlns:n0=\"http://a.example\""
 
1740
          + " xmlns:n1=\"http://b.example\">content</n1:elem1>";
 
1741
        ByteArrayOutputStream out = new ByteArrayOutputStream();
 
1742
        Canonicalizer canonicalizer = new Canonicalizer(out,
 
1743
          Canonicalizer.EXCLUSIVE_XML_CANONICALIZATION_WITH_COMMENTS);
 
1744
        
 
1745
        XPathContext context = new XPathContext("n1", "http://b.example");
 
1746
        Document doc = new Document(pdu);
 
1747
        canonicalizer.setInclusiveNamespacePrefixList("n0");
 
1748
        Nodes subset = doc.query(
 
1749
          "(//. | //@* | //namespace::*)[ancestor-or-self::n1:elem1]",
 
1750
          context);
 
1751
        canonicalizer.write(subset);  
 
1752
        
 
1753
        byte[] result = out.toByteArray();
 
1754
        out.close();
 
1755
        String s = new String(out.toByteArray(), "UTF8");
 
1756
        assertEquals(expected, s);
 
1757
        
 
1758
    }
 
1759
 
 
1760
 
 
1761
    public void testClearInclusiveNamespacePrefixes() 
 
1762
      throws IOException {
 
1763
     
 
1764
        Element pdu = new Element("n0:pdu", "http://a.example");
 
1765
        Element elem1 = new Element("n1:elem1", "http://b.example");
 
1766
        elem1.appendChild("content");
 
1767
        pdu.appendChild(elem1);
 
1768
        
 
1769
        String expected = "<n1:elem1"
 
1770
          + " xmlns:n1=\"http://b.example\">content</n1:elem1>";
 
1771
        ByteArrayOutputStream out = new ByteArrayOutputStream();
 
1772
        Canonicalizer canonicalizer = new Canonicalizer(out,
 
1773
          Canonicalizer.EXCLUSIVE_XML_CANONICALIZATION_WITH_COMMENTS);
 
1774
        
 
1775
        XPathContext context = new XPathContext("n1", "http://b.example");
 
1776
        Document doc = new Document(pdu);
 
1777
        canonicalizer.setInclusiveNamespacePrefixList("n0");
 
1778
        canonicalizer.setInclusiveNamespacePrefixList(null);
 
1779
        Nodes subset = doc.query(
 
1780
          "(//. | //@* | //namespace::*)[ancestor-or-self::n1:elem1]",
 
1781
          context);
 
1782
        canonicalizer.write(subset);  
 
1783
        
 
1784
        byte[] result = out.toByteArray();
 
1785
        out.close();
 
1786
        String s = new String(out.toByteArray(), "UTF8");
 
1787
        assertEquals(expected, s);
 
1788
        
 
1789
    }
 
1790
 
 
1791
 
 
1792
    public void testExclusive22a() throws ParsingException, IOException {
 
1793
     
 
1794
        Builder builder = new Builder();
 
1795
        String input = "<n0:local xmlns:n0='foo:bar' xmlns:n3='ftp://example.org'>" +
 
1796
                "<n1:elem2 xmlns:n1=\"http://example.net\" xml:lang=\"en\">"
 
1797
            + "<n3:stuff xmlns:n3=\"ftp://example.org\"/></n1:elem2></n0:local>";
 
1798
        Document doc = builder.build(input, null);
 
1799
        
 
1800
        String expected = "<n1:elem2 xmlns:n1=\"http://example.net\" xml:lang=\"en\">" +
 
1801
                "<n3:stuff xmlns:n3=\"ftp://example.org\"></n3:stuff></n1:elem2>";
 
1802
        ByteArrayOutputStream out = new ByteArrayOutputStream();
 
1803
        Canonicalizer canonicalizer = new Canonicalizer(out,
 
1804
          Canonicalizer.EXCLUSIVE_XML_CANONICALIZATION_WITH_COMMENTS);
 
1805
        
 
1806
        XPathContext context = new XPathContext("n1", "http://example.net");
 
1807
        canonicalizer.write(doc.query(
 
1808
          " (//. | //@* | //namespace::*)[ancestor-or-self::n1:elem2]", 
 
1809
          context));  
 
1810
        
 
1811
        byte[] result = out.toByteArray();
 
1812
        out.close();
 
1813
        String s = new String(out.toByteArray(), "UTF8");
 
1814
        assertEquals(expected, s);
 
1815
        
 
1816
    }
 
1817
        
 
1818
 
 
1819
    public void testExclusive22b() throws ParsingException, IOException {
 
1820
     
 
1821
        Builder builder = new Builder();
 
1822
        String input = "<n2:pdu xmlns:n1='http://example.com' "
 
1823
            + "xmlns:n2='http://foo.example' xml:lang='fr' xml:space='retain'>"
 
1824
            + "<n1:elem2 xmlns:n1='http://example.net' xml:lang='en'>"
 
1825
            + "<n3:stuff xmlns:n3='ftp://example.org'/></n1:elem2></n2:pdu>";
 
1826
        Document doc = builder.build(input, null);
 
1827
        
 
1828
        String expected = "<n1:elem2 xmlns:n1=\"http://example.net\" xml:lang=\"en\">"
 
1829
            + "<n3:stuff xmlns:n3=\"ftp://example.org\"></n3:stuff></n1:elem2>";
 
1830
        ByteArrayOutputStream out = new ByteArrayOutputStream();
 
1831
        Canonicalizer canonicalizer = new Canonicalizer(out,
 
1832
          Canonicalizer.EXCLUSIVE_XML_CANONICALIZATION_WITH_COMMENTS);
 
1833
        
 
1834
        XPathContext context = new XPathContext("n1", "http://example.net");
 
1835
        canonicalizer.write(doc.query(" (//. | //@* | //namespace::*)[ancestor-or-self::n1:elem2]", context));  
 
1836
        
 
1837
        byte[] result = out.toByteArray();
 
1838
        out.close();
 
1839
        String s = new String(out.toByteArray(), "UTF8");
 
1840
        assertEquals(expected, s);
 
1841
        
 
1842
    }
 
1843
        
 
1844
    
 
1845
    // compare to output generated by Apache XML Security code
 
1846
    public void testExclusiveXMLConformanceTestSuiteDocuments() 
 
1847
      throws ParsingException, IOException {
 
1848
      
 
1849
        File masterList = new File(canonical, "xmlconf");
 
1850
        masterList = new File(masterList, "xmlconf.xml");
 
1851
        if (masterList.exists()) {
 
1852
            Document xmlconf = builder.build(masterList);
 
1853
            Elements testcases = xmlconf.getRootElement().getChildElements("TESTCASES");
 
1854
            processExclusiveTestCases(testcases);
 
1855
        }
 
1856
 
 
1857
    }
 
1858
 
 
1859
    
 
1860
    // xmlconf/xmltest/valid/sa/097.xml appears to be screwed up by a lot
 
1861
    // of parsers 
 
1862
    private void processExclusiveTestCases(Elements testcases) 
 
1863
      throws ParsingException, IOException {
 
1864
        
 
1865
        for (int i = 0; i < testcases.size(); i++) {
 
1866
              Element testcase = testcases.get(i); 
 
1867
              Elements tests = testcase.getChildElements("TEST");
 
1868
              processExclusiveTests(tests);
 
1869
              Elements level2 = testcase.getChildElements("TESTCASES");
 
1870
              // need to be recursive to handle recursive IBM test cases
 
1871
              processExclusiveTestCases(level2);
 
1872
        }
 
1873
        
 
1874
    }
 
1875
 
 
1876
 
 
1877
    private void processExclusiveTests(Elements tests) 
 
1878
      throws ParsingException, IOException  {
 
1879
        
 
1880
        for (int i = 0; i < tests.size(); i++) {
 
1881
            Element test = tests.get(i);
 
1882
            String namespace = test.getAttributeValue("NAMESPACE");
 
1883
            if ("no".equals(namespace)) continue;
 
1884
            String type = test.getAttributeValue("TYPE");
 
1885
            if ("not-wf".equals(type)) continue;
 
1886
            String uri = test.getAttributeValue("URI");
 
1887
            String base = test.getBaseURI();
 
1888
            // Hack because URIUtil isn't public; and I don't want to
 
1889
            // depend on 1.4 only java.net.URI
 
1890
            Element parent = new Element("e");
 
1891
            parent.setBaseURI(base);
 
1892
            Element child = new Element("a");
 
1893
            child.addAttribute(new Attribute("xml:base", 
 
1894
              "http://www.w3.org/XML/1998/namespace", uri));
 
1895
            parent.appendChild(child);
 
1896
            String resolvedURI = child.getBaseURI();
 
1897
            
 
1898
            Document doc = builder.build(resolvedURI);
 
1899
            ByteArrayOutputStream out = new ByteArrayOutputStream();
 
1900
            try {
 
1901
                Canonicalizer serializer = new Canonicalizer(
 
1902
                  out, 
 
1903
                  Canonicalizer.EXCLUSIVE_XML_CANONICALIZATION_WITH_COMMENTS
 
1904
                );
 
1905
                serializer.write(doc);
 
1906
            }
 
1907
            finally {
 
1908
                out.close();
 
1909
            }           
 
1910
            byte[] actual = out.toByteArray();
 
1911
            
 
1912
            File input = new File(resolvedURI.substring(5) + ".exc");
 
1913
            byte[] expected = new byte[(int) input.length()];
 
1914
            DataInputStream in = new DataInputStream(
 
1915
              new BufferedInputStream(new FileInputStream(input)));
 
1916
            try {
 
1917
                in.readFully(expected);
 
1918
            }
 
1919
            finally {
 
1920
                in.close();
 
1921
            }
 
1922
            
 
1923
            assertEquals(resolvedURI, new String(expected, "UTF-8"), new String(actual, "UTF-8"));
 
1924
            
 
1925
        }
 
1926
        
 
1927
    }
 
1928
    
 
1929
    
 
1930
    public void testCanonicalizeAttribute() throws IOException {
 
1931
     
 
1932
        Attribute att = new Attribute("pre:foo", "http://www.example.org", "value");
 
1933
        ByteArrayOutputStream out = new ByteArrayOutputStream();
 
1934
        try {
 
1935
            Canonicalizer serializer = new Canonicalizer(out);
 
1936
            serializer.write(att);
 
1937
        }
 
1938
        finally {
 
1939
            out.close();
 
1940
        }           
 
1941
        byte[] actual = out.toByteArray();
 
1942
        byte[] expected = " pre:foo=\"value\"".getBytes("UTF-8");
 
1943
        assertEquals(expected, actual);
 
1944
        
 
1945
    }
 
1946
 
 
1947
    
 
1948
    public void testCanonicalizeNamespace() throws IOException {
 
1949
     
 
1950
        Element element = new Element("pre:foo", "http://www.example.org");
 
1951
        Nodes namespaces = element.query("namespace::pre");
 
1952
        Namespace ns = (Namespace) namespaces.get(0);
 
1953
        ByteArrayOutputStream out = new ByteArrayOutputStream();
 
1954
        try {
 
1955
            Canonicalizer serializer = new Canonicalizer(out);
 
1956
            serializer.write(ns);
 
1957
        }
 
1958
        finally {
 
1959
            out.close();
 
1960
        }           
 
1961
        byte[] actual = out.toByteArray();
 
1962
        byte[] expected = " xmlns:pre=\"http://www.example.org\"".getBytes("UTF-8");
 
1963
        assertEquals(expected, actual);
 
1964
        
 
1965
        
 
1966
    }
 
1967
 
 
1968
    
 
1969
    public void testCanonicalizeDefaultNamespace() throws IOException {
 
1970
     
 
1971
        Element element = new Element("foo", "http://www.example.org");
 
1972
        Nodes namespaces = element.query("namespace::*");
 
1973
        Namespace ns = (Namespace) namespaces.get(0);
 
1974
        if (ns.getPrefix().equals("xml")) ns = (Namespace) namespaces.get(1);
 
1975
        ByteArrayOutputStream out = new ByteArrayOutputStream();
 
1976
        try {
 
1977
            Canonicalizer serializer = new Canonicalizer(out);
 
1978
            serializer.write(ns);
 
1979
        }
 
1980
        finally {
 
1981
            out.close();
 
1982
        }           
 
1983
        byte[] actual = out.toByteArray();
 
1984
        byte[] expected = " xmlns=\"http://www.example.org\"".getBytes("UTF-8");
 
1985
        assertEquals(expected, actual);  
 
1986
        
 
1987
    }
 
1988
 
 
1989
    
 
1990
    public void testCanonicalizeXMLNamespace() throws IOException {
 
1991
     
 
1992
        Element element = new Element("foo");
 
1993
        Nodes namespaces = element.query("namespace::*");
 
1994
        Namespace ns = (Namespace) namespaces.get(0);
 
1995
        ByteArrayOutputStream out = new ByteArrayOutputStream();
 
1996
        try {
 
1997
            Canonicalizer serializer = new Canonicalizer(out);
 
1998
            serializer.write(ns);
 
1999
        }
 
2000
        finally {
 
2001
            out.close();
 
2002
        }           
 
2003
        byte[] actual = out.toByteArray();
 
2004
        byte[] expected 
 
2005
          = " xmlns:xml=\"http://www.w3.org/XML/1998/namespace\"".getBytes("UTF-8");
 
2006
        assertEquals(expected, actual);  
 
2007
        
 
2008
    }
 
2009
 
 
2010
    
 
2011
    public void testCanonicalizeElement() throws IOException {
 
2012
     
 
2013
        Element element = new Element("pre:foo", "http://www.example.org");
 
2014
        element.appendChild("  value \n value");
 
2015
        ByteArrayOutputStream out = new ByteArrayOutputStream();
 
2016
        try {
 
2017
            Canonicalizer serializer = new Canonicalizer(out);
 
2018
            serializer.write(element);
 
2019
        }
 
2020
        finally {
 
2021
            out.close();
 
2022
        }           
 
2023
        byte[] actual = out.toByteArray();
 
2024
        byte[] expected = 
 
2025
          "<pre:foo xmlns:pre=\"http://www.example.org\">  value \n value</pre:foo>"
 
2026
          .getBytes("UTF-8");
 
2027
        assertEquals(expected, actual);
 
2028
        
 
2029
    }
 
2030
 
 
2031
    
 
2032
    public void testDontPutElementInDocument() throws IOException {
 
2033
     
 
2034
 
 
2035
        Element element = new Element("pre:foo", "http://www.example.org");
 
2036
        assertNull(element.getDocument());
 
2037
        ByteArrayOutputStream out = new ByteArrayOutputStream();
 
2038
        try {
 
2039
            Canonicalizer serializer = new Canonicalizer(out);
 
2040
            serializer.write(element);
 
2041
            assertNull(element.getDocument());
 
2042
        }
 
2043
        finally {
 
2044
            out.close();
 
2045
        }
 
2046
        
 
2047
    }
 
2048
 
 
2049
    
 
2050
    public void testCanonicalizeElementInDocument() throws IOException {
 
2051
     
 
2052
        Element root = new Element("root");
 
2053
        Document doc = new Document(root);
 
2054
        Element element = new Element("pre:foo", "http://www.example.org");
 
2055
        root.appendChild(element);
 
2056
        element.appendChild("  value \n value");
 
2057
        ByteArrayOutputStream out = new ByteArrayOutputStream();
 
2058
        try {
 
2059
            Canonicalizer serializer = new Canonicalizer(out);
 
2060
            serializer.write(element);
 
2061
        }
 
2062
        finally {
 
2063
            out.close();
 
2064
        }           
 
2065
        byte[] actual = out.toByteArray();
 
2066
        byte[] expected = 
 
2067
          "<pre:foo xmlns:pre=\"http://www.example.org\">  value \n value</pre:foo>"
 
2068
          .getBytes("UTF-8");
 
2069
        assertEquals(expected, actual);
 
2070
        
 
2071
    }
 
2072
 
 
2073
    
 
2074
    public void testNoInfiniteLoopWhenWritingADocumentlessElement() throws IOException {
 
2075
     
 
2076
        Element root = new Element("root");
 
2077
        Element a = new Element("a");
 
2078
        root.appendChild(a);
 
2079
        Element b = new Element("b");
 
2080
        a.appendChild(b);
 
2081
        
 
2082
        ByteArrayOutputStream out = new ByteArrayOutputStream();
 
2083
        try {
 
2084
            Canonicalizer serializer = new Canonicalizer(out);
 
2085
            serializer.write(b);
 
2086
        }
 
2087
        finally {
 
2088
            out.close();
 
2089
        }           
 
2090
        byte[] actual = out.toByteArray();
 
2091
        byte[] expected = 
 
2092
          "<b></b>"
 
2093
          .getBytes("UTF-8");
 
2094
        assertEquals(expected, actual);
 
2095
        
 
2096
    }
 
2097
 
 
2098
    
 
2099
    public void testExclusiveCanonicalizeElementInDocument() throws IOException {
 
2100
     
 
2101
        Element root = new Element("root");
 
2102
        Document doc = new Document(root);
 
2103
        Element element = new Element("pre:foo", "http://www.example.org");
 
2104
        root.appendChild(element);
 
2105
        element.appendChild("  value \n value");
 
2106
        ByteArrayOutputStream out = new ByteArrayOutputStream();
 
2107
        try {
 
2108
            Canonicalizer serializer = new Canonicalizer(out, Canonicalizer.EXCLUSIVE_XML_CANONICALIZATION);
 
2109
            serializer.write(element);
 
2110
        }
 
2111
        finally {
 
2112
            out.close();
 
2113
        }           
 
2114
        byte[] actual = out.toByteArray();
 
2115
        byte[] expected = 
 
2116
          "<pre:foo xmlns:pre=\"http://www.example.org\">  value \n value</pre:foo>"
 
2117
          .getBytes("UTF-8");
 
2118
        assertEquals(expected, actual);
 
2119
        
 
2120
    }
 
2121
 
 
2122
    
 
2123
    public void testCanonicalizeDocumentTypeDeclaration() throws IOException {
 
2124
     
 
2125
        DocType doctype = new DocType("root", "http://www.example.org");
 
2126
        ByteArrayOutputStream out = new ByteArrayOutputStream();
 
2127
        try {
 
2128
            Canonicalizer serializer = new Canonicalizer(out);
 
2129
            serializer.write(doctype);
 
2130
        }
 
2131
        finally {
 
2132
            out.close();
 
2133
        }           
 
2134
        byte[] actual = out.toByteArray();
 
2135
        assertEquals(0, actual.length);
 
2136
        
 
2137
    }
 
2138
 
 
2139
    
 
2140
    public void testCanonicalizeProcessingInstruction() throws IOException {
 
2141
     
 
2142
        ProcessingInstruction pi = new ProcessingInstruction("target", "value \n value");
 
2143
        ByteArrayOutputStream out = new ByteArrayOutputStream();
 
2144
        try {
 
2145
            Canonicalizer serializer = new Canonicalizer(out);
 
2146
            serializer.write(pi);
 
2147
        }
 
2148
        finally {
 
2149
            out.close();
 
2150
        }           
 
2151
        byte[] actual = out.toByteArray();
 
2152
        byte[] expected = "<?target value \n value?>".getBytes("UTF-8");
 
2153
        assertEquals(expected, actual);
 
2154
        
 
2155
    }
 
2156
 
 
2157
    
 
2158
    public void testCanonicalizeText() throws IOException {
 
2159
     
 
2160
        Text c = new Text("  pre:foo \n  ");
 
2161
        ByteArrayOutputStream out = new ByteArrayOutputStream();
 
2162
        try {
 
2163
            Canonicalizer serializer = new Canonicalizer(out);
 
2164
            serializer.write(c);
 
2165
        }
 
2166
        finally {
 
2167
            out.close();
 
2168
        }           
 
2169
        byte[] actual = out.toByteArray();  
 
2170
        byte[] expected = "  pre:foo \n  ".getBytes("UTF-8");
 
2171
        assertEquals(expected, actual);        
 
2172
        
 
2173
        
 
2174
    }
 
2175
 
 
2176
    
 
2177
    public void testCanonicalizeComment() throws IOException {
 
2178
     
 
2179
        Comment c = new Comment("pre:foo");
 
2180
        ByteArrayOutputStream out = new ByteArrayOutputStream();
 
2181
        try {
 
2182
            Canonicalizer serializer = new Canonicalizer(out);
 
2183
            serializer.write(c);
 
2184
        }
 
2185
        finally {
 
2186
            out.close();
 
2187
        }           
 
2188
        byte[] actual = out.toByteArray();
 
2189
        byte[] expected = "<!--pre:foo-->".getBytes("UTF-8");
 
2190
        assertEquals(expected, actual);
 
2191
        
 
2192
    }
 
2193
    
 
2194
    
 
2195
    public void testUnsupportedAlgorithm() throws IOException {
 
2196
     
 
2197
        ByteArrayOutputStream out = new ByteArrayOutputStream();
 
2198
        try {
 
2199
            new Canonicalizer(out, "http://www.example.org/canonical");
 
2200
            fail("Allowed unrecognized algorithm");
 
2201
        }
 
2202
        catch (CanonicalizationException success) {
 
2203
            assertNotNull(success.getMessage());
 
2204
        } 
 
2205
        finally {
 
2206
            out.close();
 
2207
        }
 
2208
        
 
2209
    }
 
2210
    
 
2211
    
 
2212
    public void testCanonicalizeDetachedNodes() throws IOException {
 
2213
     
 
2214
        ByteArrayOutputStream out = new ByteArrayOutputStream();
 
2215
        Element e = new Element("test");
 
2216
        Nodes nodes = new Nodes(e);
 
2217
        Canonicalizer serializer = new Canonicalizer(out);
 
2218
        try {
 
2219
            serializer.write(nodes);
 
2220
            fail("Canonicalized detached node");
 
2221
        }
 
2222
        catch (CanonicalizationException success) {
 
2223
            assertNotNull(success.getMessage());
 
2224
        } 
 
2225
        finally {
 
2226
            out.close();
 
2227
        }
 
2228
        
 
2229
    }
 
2230
    
 
2231
    
 
2232
    public void testCanonicalizeNodesFromTwoDocuments() throws IOException {
 
2233
     
 
2234
        ByteArrayOutputStream out = new ByteArrayOutputStream();
 
2235
        Element e1 = new Element("test");
 
2236
        new Document(e1);
 
2237
        Element e2 = new Element("test");
 
2238
        new Document(e2);
 
2239
        Nodes nodes = new Nodes(e1);
 
2240
        nodes.append(e2);
 
2241
        Canonicalizer serializer = new Canonicalizer(out);
 
2242
        try {
 
2243
            serializer.write(nodes);
 
2244
            fail("Canonicalized multiple document nodes");
 
2245
        }
 
2246
        catch (CanonicalizationException success) {
 
2247
            assertNotNull(success.getMessage());
 
2248
        } 
 
2249
        finally {
 
2250
            out.close();
 
2251
        }
 
2252
        
 
2253
    }
 
2254
       
 
2255
    
 
2256
    /**
 
2257
     * <p>
 
2258
     * Asserts that two byte arrays are equal. If the two arrays are  
 
2259
     * not equal a <code>ComparisonFailure</code> is thrown. Two 
 
2260
     * arrays are equal if and only if they have the same length, 
 
2261
     * and each item in the expected array is equal to the 
 
2262
     * corresponding item in the actual array. 
 
2263
     * </p>
 
2264
     *
 
2265
     * @param expected the byte array the test should produce
 
2266
     * @param actual the byte array the test does produce
 
2267
     */
 
2268
    private void assertEquals(byte[] expected, byte[] actual) {
 
2269
        
 
2270
        if (expected == null && actual == null) {
 
2271
            return;
 
2272
        }
 
2273
        // what if one is null and the other isn't????
 
2274
        assertEquals(expected.length, actual.length);
 
2275
        for (int i = 0; i < actual.length; i++) {
 
2276
            assertEquals(expected[i], actual[i]);
 
2277
        }
 
2278
        
 
2279
    }
 
2280
    
 
2281
    
 
2282
    // This class forces IOExceptions when writing
 
2283
    private static class UnwriteableOutputStream extends OutputStream {
 
2284
 
 
2285
        public void write(int b) throws IOException {
 
2286
            throw new IOException();
 
2287
        }
 
2288
        
 
2289
    }
 
2290
    
 
2291
    
 
2292
    public void testDetachElementWhenExceptionIsThrown() {
 
2293
        
 
2294
        Element e = new Element("a");
 
2295
        Canonicalizer canonicalizer = new Canonicalizer(new UnwriteableOutputStream());
 
2296
        try {
 
2297
            canonicalizer.write(e);
 
2298
        }
 
2299
        catch (IOException ex) {
 
2300
        }
 
2301
        assertNull(e.getParent());
 
2302
        
 
2303
    }
 
2304
    
 
2305
    
 
2306
}