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 /* 24 * Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved. 25 */ 26 /* 27 * $Id: DOMManifest.java 1333415 2012-05-03 12:03:51Z coheigea $ 28 */ 29 package org.jcp.xml.dsig.internal.dom; 30 31 import javax.xml.crypto.*; 32 import javax.xml.crypto.dom.DOMCryptoContext; 33 import javax.xml.crypto.dsig.*; 34 35 import java.security.Provider; 36 import java.util.*; 37 38 import org.w3c.dom.Attr; 39 import org.w3c.dom.Document; 40 import org.w3c.dom.Element; 41 import org.w3c.dom.Node; 42 43 /** 44 * DOM-based implementation of Manifest. 45 * 46 * @author Sean Mullan 47 */ 48 public final class DOMManifest extends DOMStructure implements Manifest { 49 50 private final List<Reference> references; 51 private final String id; 52 53 /** 54 * Creates a <code>DOMManifest</code> containing the specified 55 * list of {@link Reference}s and optional id. 56 * 57 * @param references a list of one or more <code>Reference</code>s. The list 58 * is defensively copied to protect against subsequent modification. 59 * @param id the id (may be <code>null</code> 60 * @throws NullPointerException if <code>references</code> is 61 * <code>null</code> 62 * @throws IllegalArgumentException if <code>references</code> is empty 63 * @throws ClassCastException if <code>references</code> contains any 64 * entries that are not of type {@link Reference} 65 */ 66 public DOMManifest(List<? extends Reference> references, String id) { 67 if (references == null) { 68 throw new NullPointerException("references cannot be null"); 69 } 70 this.references = 71 Collections.unmodifiableList(new ArrayList<Reference>(references)); 72 if (this.references.isEmpty()) { 73 throw new IllegalArgumentException("list of references must " + 74 "contain at least one entry"); 75 } 76 for (int i = 0, size = this.references.size(); i < size; i++) { 77 if (!(this.references.get(i) instanceof Reference)) { 78 throw new ClassCastException 79 ("references["+i+"] is not a valid type"); 80 } 81 } 82 this.id = id; 83 } 84 85 /** 86 * Creates a <code>DOMManifest</code> from an element. 87 * 88 * @param manElem a Manifest element 89 */ 90 public DOMManifest(Element manElem, XMLCryptoContext context, 91 Provider provider) 92 throws MarshalException 93 { 94 Attr attr = manElem.getAttributeNodeNS(null, "Id"); 95 if (attr != null) { 96 this.id = attr.getValue(); 97 manElem.setIdAttributeNode(attr, true); 98 } else { 99 this.id = null; 100 } 101 102 boolean secVal = Utils.secureValidation(context); 103 104 Element refElem = DOMUtils.getFirstChildElement(manElem, "Reference"); 105 List<Reference> refs = new ArrayList<Reference>(); 106 refs.add(new DOMReference(refElem, context, provider)); 107 108 refElem = DOMUtils.getNextSiblingElement(refElem); 109 while (refElem != null) { 110 String localName = refElem.getLocalName(); 111 if (!localName.equals("Reference")) { 112 throw new MarshalException("Invalid element name: " + 113 localName + ", expected Reference"); 114 } 115 refs.add(new DOMReference(refElem, context, provider)); 116 if (secVal && (refs.size() > DOMSignedInfo.MAXIMUM_REFERENCE_COUNT)) { 117 String error = "A maxiumum of " + DOMSignedInfo.MAXIMUM_REFERENCE_COUNT + " " 118 + "references per Manifest are allowed with secure validation"; 119 throw new MarshalException(error); 120 } 121 refElem = DOMUtils.getNextSiblingElement(refElem); 122 } 123 this.references = Collections.unmodifiableList(refs); 124 } 125 126 public String getId() { 127 return id; 128 } 129 130 @SuppressWarnings("unchecked") 131 static List<Reference> getManifestReferences(Manifest mf) { 132 return mf.getReferences(); 133 } 134 135 public List<Reference> getReferences() { 136 return references; 137 } 138 139 public void marshal(Node parent, String dsPrefix, DOMCryptoContext context) 140 throws MarshalException 141 { 142 Document ownerDoc = DOMUtils.getOwnerDocument(parent); 143 Element manElem = DOMUtils.createElement(ownerDoc, "Manifest", 144 XMLSignature.XMLNS, dsPrefix); 145 146 DOMUtils.setAttributeID(manElem, "Id", id); 147 148 // add references 149 for (Reference ref : references) { 150 ((DOMReference)ref).marshal(manElem, dsPrefix, context); 151 } 152 parent.appendChild(manElem); 153 } 154 155 @Override 156 public boolean equals(Object o) { 157 if (this == o) { 158 return true; 159 } 160 161 if (!(o instanceof Manifest)) { 162 return false; 163 } 164 Manifest oman = (Manifest)o; 165 166 boolean idsEqual = (id == null ? oman.getId() == null 167 : id.equals(oman.getId())); 168 169 return (idsEqual && references.equals(oman.getReferences())); 170 } 171 172 @Override 173 public int hashCode() { 174 int result = 17; 175 if (id != null) { 176 result = 31 * result + id.hashCode(); 177 } 178 result = 31 * result + references.hashCode(); 179 180 return result; 181 } 182 }