1 /* 2 * reserved comment block 3 * DO NOT REMOVE OR ALTER! 4 */ 5 /* 6 * Copyright 2005 The Apache Software Foundation. 7 * 8 * Licensed under the Apache License, Version 2.0 (the "License"); 9 * you may not use this file except in compliance with the License. 10 * You may obtain a copy of the License at 11 * 12 * http://www.apache.org/licenses/LICENSE-2.0 13 * 14 * Unless required by applicable law or agreed to in writing, software 15 * distributed under the License is distributed on an "AS IS" BASIS, 16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17 * See the License for the specific language governing permissions and 18 * limitations under the License. 19 * 20 */ 21 /* 22 * Copyright (c) 2005, 2008, Oracle and/or its affiliates. All rights reserved. 23 */ 24 /* 25 * $Id: DOMSignatureProperty.java,v 1.2 2008/07/24 15:20:32 mullan Exp $ 26 */ 27 package org.jcp.xml.dsig.internal.dom; 28 29 import javax.xml.crypto.*; 30 import javax.xml.crypto.dom.DOMCryptoContext; 31 import javax.xml.crypto.dsig.*; 32 33 import java.util.*; 34 import org.w3c.dom.Attr; 35 import org.w3c.dom.Document; 36 import org.w3c.dom.Element; 37 import org.w3c.dom.Node; 38 import org.w3c.dom.NodeList; 39 40 /** 41 * DOM-based implementation of SignatureProperty. 42 * 43 * @author Sean Mullan 44 */ 45 public final class DOMSignatureProperty extends DOMStructure 46 implements SignatureProperty { 47 48 private final String id; 49 private final String target; 50 private final List content; 51 52 /** 53 * Creates a <code>SignatureProperty</code> from the specified parameters. 54 * 55 * @param content a list of one or more {@link XMLStructure}s. The list 56 * is defensively copied to protect against subsequent modification. 57 * @param target the target URI 58 * @param id the Id (may be <code>null</code>) 59 * @return a <code>SignatureProperty</code> 60 * @throws ClassCastException if <code>content</code> contains any 61 * entries that are not of type {@link XMLStructure} 62 * @throws IllegalArgumentException if <code>content</code> is empty 63 * @throws NullPointerException if <code>content</code> or 64 * <code>target</code> is <code>null</code> 65 */ 66 public DOMSignatureProperty(List content, String target, String id) { 67 if (target == null) { 68 throw new NullPointerException("target cannot be null"); 69 } else if (content == null) { 70 throw new NullPointerException("content cannot be null"); 71 } else if (content.isEmpty()) { 72 throw new IllegalArgumentException("content cannot be empty"); 73 } else { 74 List contentCopy = new ArrayList(content); 75 for (int i = 0, size = contentCopy.size(); i < size; i++) { 76 if (!(contentCopy.get(i) instanceof XMLStructure)) { 77 throw new ClassCastException 78 ("content["+i+"] is not a valid type"); 79 } 80 } 81 this.content = Collections.unmodifiableList(contentCopy); 82 } 83 this.target = target; 84 this.id = id; 85 } 86 87 /** 88 * Creates a <code>DOMSignatureProperty</code> from an element. 89 * 90 * @param propElem a SignatureProperty element 91 */ 92 public DOMSignatureProperty(Element propElem) throws MarshalException { 93 // unmarshal attributes 94 target = DOMUtils.getAttributeValue(propElem, "Target"); 95 if (target == null) { 96 throw new MarshalException("target cannot be null"); 97 } 98 Attr attr = propElem.getAttributeNodeNS(null, "Id"); 99 if (attr != null) { 100 id = attr.getValue(); 101 propElem.setIdAttributeNode(attr, true); 102 } else { 103 id = null; 104 } 105 106 NodeList nodes = propElem.getChildNodes(); 107 int length = nodes.getLength(); 108 List content = new ArrayList(length); 109 for (int i = 0; i < length; i++) { 110 content.add(new javax.xml.crypto.dom.DOMStructure(nodes.item(i))); 111 } 112 if (content.isEmpty()) { 113 throw new MarshalException("content cannot be empty"); 114 } else { 115 this.content = Collections.unmodifiableList(content); 116 } 117 } 118 119 public List getContent() { 120 return content; 121 } 122 123 public String getId() { 124 return id; 125 } 126 127 public String getTarget() { 128 return target; 129 } 130 131 public void marshal(Node parent, String dsPrefix, DOMCryptoContext context) 132 throws MarshalException { 133 Document ownerDoc = DOMUtils.getOwnerDocument(parent); 134 135 Element propElem = DOMUtils.createElement 136 (ownerDoc, "SignatureProperty", XMLSignature.XMLNS, dsPrefix); 137 138 // set attributes 139 DOMUtils.setAttributeID(propElem, "Id", id); 140 DOMUtils.setAttribute(propElem, "Target", target); 141 142 // create and append any elements and mixed content 143 for (int i = 0, size = content.size(); i < size; i++) { 144 javax.xml.crypto.dom.DOMStructure property = 145 (javax.xml.crypto.dom.DOMStructure) content.get(i); 146 DOMUtils.appendChild(propElem, property.getNode()); 147 } 148 149 parent.appendChild(propElem); 150 } 151 152 public boolean equals(Object o) { 153 if (this == o) { 154 return true; 155 } 156 157 if (!(o instanceof SignatureProperty)) { 158 return false; 159 } 160 SignatureProperty osp = (SignatureProperty) o; 161 162 boolean idsEqual = (id == null ? osp.getId() == null : 163 id.equals(osp.getId())); 164 165 return (equalsContent(osp.getContent()) && 166 target.equals(osp.getTarget()) && idsEqual); 167 } 168 169 private boolean equalsContent(List otherContent) { 170 int osize = otherContent.size(); 171 if (content.size() != osize) { 172 return false; 173 } 174 for (int i = 0; i < osize; i++) { 175 XMLStructure oxs = (XMLStructure) otherContent.get(i); 176 XMLStructure xs = (XMLStructure) content.get(i); 177 if (oxs instanceof javax.xml.crypto.dom.DOMStructure) { 178 if (!(xs instanceof javax.xml.crypto.dom.DOMStructure)) { 179 return false; 180 } 181 Node onode = 182 ((javax.xml.crypto.dom.DOMStructure) oxs).getNode(); 183 Node node = 184 ((javax.xml.crypto.dom.DOMStructure) xs).getNode(); 185 if (!DOMUtils.nodesEqual(node, onode)) { 186 return false; 187 } 188 } else { 189 if (!(xs.equals(oxs))) { 190 return false; 191 } 192 } 193 } 194 195 return true; 196 } 197 }