View Javadoc
1   /*
2    * reserved comment block
3    * DO NOT REMOVE OR ALTER!
4    */
5   /**
6    * Licensed to the Apache Software Foundation (ASF) under one
7    * or more contributor license agreements. See the NOTICE file
8    * distributed with this work for additional information
9    * regarding copyright ownership. The ASF licenses this file
10   * to you under the Apache License, Version 2.0 (the
11   * "License"); you may not use this file except in compliance
12   * with the License. You may obtain a copy of the License at
13   *
14   * http://www.apache.org/licenses/LICENSE-2.0
15   *
16   * Unless required by applicable law or agreed to in writing,
17   * software distributed under the License is distributed on an
18   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
19   * KIND, either express or implied. See the License for the
20   * specific language governing permissions and limitations
21   * under the License.
22   */
23  package com.sun.org.apache.xml.internal.security.c14n.helper;
24  
25  import com.sun.org.apache.xml.internal.security.utils.Constants;
26  import org.w3c.dom.Attr;
27  import java.io.Serializable;
28  import java.util.Comparator;
29  
30  /**
31   * Compares two attributes based on the C14n specification.
32   *
33   * <UL>
34   * <LI>Namespace nodes have a lesser document order position than attribute
35   *   nodes.
36   * <LI> An element's namespace nodes are sorted lexicographically by
37   *   local name (the default namespace node, if one exists, has no
38   *   local name and is therefore lexicographically least).
39   * <LI> An element's attribute nodes are sorted lexicographically with
40   *   namespace URI as the primary key and local name as the secondary
41   *   key (an empty namespace URI is lexicographically least).
42   * </UL>
43   *
44   * @author Christian Geuer-Pollmann
45   */
46  public class AttrCompare implements Comparator<Attr>, Serializable {
47  
48      private static final long serialVersionUID = -7113259629930576230L;
49      private static final int ATTR0_BEFORE_ATTR1 = -1;
50      private static final int ATTR1_BEFORE_ATTR0 = 1;
51      private static final String XMLNS = Constants.NamespaceSpecNS;
52  
53      /**
54       * Compares two attributes based on the C14n specification.
55       *
56       * <UL>
57       * <LI>Namespace nodes have a lesser document order position than
58       *   attribute nodes.
59       * <LI> An element's namespace nodes are sorted lexicographically by
60       *   local name (the default namespace node, if one exists, has no
61       *   local name and is therefore lexicographically least).
62       * <LI> An element's attribute nodes are sorted lexicographically with
63       *   namespace URI as the primary key and local name as the secondary
64       *   key (an empty namespace URI is lexicographically least).
65       * </UL>
66       *
67       * @param attr0
68       * @param attr1
69       * @return returns a negative integer, zero, or a positive integer as
70       *   obj0 is less than, equal to, or greater than obj1
71       *
72       */
73      public int compare(Attr attr0, Attr attr1) {
74          String namespaceURI0 = attr0.getNamespaceURI();
75          String namespaceURI1 = attr1.getNamespaceURI();
76  
77          boolean isNamespaceAttr0 = XMLNS.equals(namespaceURI0);
78          boolean isNamespaceAttr1 = XMLNS.equals(namespaceURI1);
79  
80          if (isNamespaceAttr0) {
81              if (isNamespaceAttr1) {
82                  // both are namespaces
83                  String localname0 = attr0.getLocalName();
84                  String localname1 = attr1.getLocalName();
85  
86                  if ("xmlns".equals(localname0)) {
87                      localname0 = "";
88                  }
89  
90                  if ("xmlns".equals(localname1)) {
91                      localname1 = "";
92                  }
93  
94                  return localname0.compareTo(localname1);
95              }
96              // attr0 is a namespace, attr1 is not
97              return ATTR0_BEFORE_ATTR1;
98          } else if (isNamespaceAttr1) {
99              // attr1 is a namespace, attr0 is not
100             return ATTR1_BEFORE_ATTR0;
101         }
102 
103         // none is a namespace
104         if (namespaceURI0 == null) {
105             if (namespaceURI1 == null) {
106                 String name0 = attr0.getName();
107                 String name1 = attr1.getName();
108                 return name0.compareTo(name1);
109             }
110             return ATTR0_BEFORE_ATTR1;
111         } else if (namespaceURI1 == null) {
112             return ATTR1_BEFORE_ATTR0;
113         }
114 
115         int a = namespaceURI0.compareTo(namespaceURI1);
116         if (a != 0) {
117             return a;
118         }
119 
120         return (attr0.getLocalName()).compareTo(attr1.getLocalName());
121     }
122 }