1/*
2 * Copyright (c) 2005, 2014, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.  Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25/*
26 * $Id: DOMCryptoContext.java,v 1.3 2005/05/09 18:33:26 mullan Exp $
27 */
28package javax.xml.crypto.dom;
29
30import javax.xml.crypto.KeySelector;
31import javax.xml.crypto.URIDereferencer;
32import javax.xml.crypto.XMLCryptoContext;
33import java.util.Collections;
34import java.util.HashMap;
35import java.util.Iterator;
36import java.util.Map;
37import org.w3c.dom.Element;
38
39/**
40 * This class provides a DOM-specific implementation of the
41 * {@link XMLCryptoContext} interface. It also includes additional
42 * methods that are specific to a DOM-based implementation for registering
43 * and retrieving elements that contain attributes of type ID.
44 *
45 * @author Sean Mullan
46 * @author JSR 105 Expert Group
47 * @since 1.6
48 */
49public class DOMCryptoContext implements XMLCryptoContext {
50
51    private HashMap<String,String> nsMap = new HashMap<>();
52    private HashMap<String,Element> idMap = new HashMap<>();
53    private HashMap<Object,Object> objMap = new HashMap<>();
54    private String baseURI;
55    private KeySelector ks;
56    private URIDereferencer dereferencer;
57    private HashMap<String,Object> propMap = new HashMap<>();
58    private String defaultPrefix;
59
60    /**
61     * Default constructor. (For invocation by subclass constructors).
62     */
63    protected DOMCryptoContext() {}
64
65    /**
66     * This implementation uses an internal {@link HashMap} to get the prefix
67     * that the specified URI maps to. It returns the <code>defaultPrefix</code>
68     * if it maps to <code>null</code>.
69     *
70     * @throws NullPointerException {@inheritDoc}
71     */
72    public String getNamespacePrefix(String namespaceURI,
73        String defaultPrefix) {
74        if (namespaceURI == null) {
75            throw new NullPointerException("namespaceURI cannot be null");
76        }
77        String prefix = nsMap.get(namespaceURI);
78        return (prefix != null ? prefix : defaultPrefix);
79    }
80
81    /**
82     * This implementation uses an internal {@link HashMap} to map the URI
83     * to the specified prefix.
84     *
85     * @throws NullPointerException {@inheritDoc}
86     */
87    public String putNamespacePrefix(String namespaceURI, String prefix) {
88        if (namespaceURI == null) {
89            throw new NullPointerException("namespaceURI is null");
90        }
91        return nsMap.put(namespaceURI, prefix);
92    }
93
94    public String getDefaultNamespacePrefix() {
95        return defaultPrefix;
96    }
97
98    public void setDefaultNamespacePrefix(String defaultPrefix) {
99        this.defaultPrefix = defaultPrefix;
100    }
101
102    public String getBaseURI() {
103        return baseURI;
104    }
105
106    /**
107     * @throws IllegalArgumentException {@inheritDoc}
108     */
109    public void setBaseURI(String baseURI) {
110        if (baseURI != null) {
111            java.net.URI.create(baseURI);
112        }
113        this.baseURI = baseURI;
114    }
115
116    public URIDereferencer getURIDereferencer() {
117        return dereferencer;
118    }
119
120    public void setURIDereferencer(URIDereferencer dereferencer) {
121        this.dereferencer = dereferencer;
122    }
123
124    /**
125     * This implementation uses an internal {@link HashMap} to get the object
126     * that the specified name maps to.
127     *
128     * @throws NullPointerException {@inheritDoc}
129     */
130    public Object getProperty(String name) {
131        if (name == null) {
132            throw new NullPointerException("name is null");
133        }
134        return propMap.get(name);
135    }
136
137    /**
138     * This implementation uses an internal {@link HashMap} to map the name
139     * to the specified object.
140     *
141     * @throws NullPointerException {@inheritDoc}
142     */
143    public Object setProperty(String name, Object value) {
144        if (name == null) {
145            throw new NullPointerException("name is null");
146        }
147        return propMap.put(name, value);
148    }
149
150    public KeySelector getKeySelector() {
151        return ks;
152    }
153
154    public void setKeySelector(KeySelector ks) {
155        this.ks = ks;
156    }
157
158    /**
159     * Returns the <code>Element</code> with the specified ID attribute value.
160     *
161     * <p>This implementation uses an internal {@link HashMap} to get the
162     * element that the specified attribute value maps to.
163     *
164     * @param idValue the value of the ID
165     * @return the <code>Element</code> with the specified ID attribute value,
166     *    or <code>null</code> if none.
167     * @throws NullPointerException if <code>idValue</code> is <code>null</code>
168     * @see #setIdAttributeNS
169     */
170    public Element getElementById(String idValue) {
171        if (idValue == null) {
172            throw new NullPointerException("idValue is null");
173        }
174        return idMap.get(idValue);
175    }
176
177    /**
178     * Registers the element's attribute specified by the namespace URI and
179     * local name to be of type ID. The attribute must have a non-empty value.
180     *
181     * <p>This implementation uses an internal {@link HashMap} to map the
182     * attribute's value to the specified element.
183     *
184     * @param element the element
185     * @param namespaceURI the namespace URI of the attribute (specify
186     *    <code>null</code> if not applicable)
187     * @param localName the local name of the attribute
188     * @throws IllegalArgumentException if <code>localName</code> is not an
189     *    attribute of the specified element or it does not contain a specific
190     *    value
191     * @throws NullPointerException if <code>element</code> or
192     *    <code>localName</code> is <code>null</code>
193     * @see #getElementById
194     */
195    public void setIdAttributeNS(Element element, String namespaceURI,
196        String localName) {
197        if (element == null) {
198            throw new NullPointerException("element is null");
199        }
200        if (localName == null) {
201            throw new NullPointerException("localName is null");
202        }
203        String idValue = element.getAttributeNS(namespaceURI, localName);
204        if (idValue == null || idValue.length() == 0) {
205            throw new IllegalArgumentException(localName + " is not an " +
206                "attribute");
207        }
208        idMap.put(idValue, element);
209    }
210
211    /**
212     * Returns a read-only iterator over the set of Id/Element mappings of
213     * this <code>DOMCryptoContext</code>. Attempts to modify the set via the
214     * {@link Iterator#remove} method throw an
215     * <code>UnsupportedOperationException</code>. The mappings are returned
216     * in no particular order. Each element in the iteration is represented as a
217     * {@link java.util.Map.Entry}. If the <code>DOMCryptoContext</code> is
218     * modified while an iteration is in progress, the results of the
219     * iteration are undefined.
220     *
221     * @return a read-only iterator over the set of mappings
222     */
223    public Iterator<Map.Entry<String, Element>> iterator() {
224        return Collections.unmodifiableMap(idMap).entrySet().iterator();
225    }
226
227    /**
228     * This implementation uses an internal {@link HashMap} to get the object
229     * that the specified key maps to.
230     */
231    public Object get(Object key) {
232        return objMap.get(key);
233    }
234
235    /**
236     * This implementation uses an internal {@link HashMap} to map the key
237     * to the specified object.
238     *
239     * @throws IllegalArgumentException {@inheritDoc}
240     */
241    public Object put(Object key, Object value) {
242        return objMap.put(key, value);
243    }
244}
245