001/**
002 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
003 *
004 * Copyright (c) 2006 Sun Microsystems Inc. All Rights Reserved
005 *
006 * The contents of this file are subject to the terms
007 * of the Common Development and Distribution License
008 * (the License). You may not use this file except in
009 * compliance with the License.
010 *
011 * You can obtain a copy of the License at
012 * https://opensso.dev.java.net/public/CDDLv1.0.html or
013 * opensso/legal/CDDLv1.0.txt
014 * See the License for the specific language governing
015 * permission and limitations under the License.
016 *
017 * When distributing Covered Code, include this CDDL
018 * Header Notice in each file and include the License file
019 * at opensso/legal/CDDLv1.0.txt.
020 * If applicable, add the following below the CDDL Header,
021 * with the fields enclosed by brackets [] replaced by
022 * your own identifying information:
023 * "Portions Copyrighted [year] [name of copyright owner]"
024 *
025 * $Id: EncryptedResourceID.java,v 1.4 2008/06/25 05:47:10 qcheng Exp $
026 *
027 */
028
029
030package com.sun.identity.liberty.ws.disco;
031
032import org.w3c.dom.*;
033
034import com.sun.identity.shared.xml.XMLUtils;
035import com.sun.identity.liberty.ws.disco.common.DiscoConstants;
036import com.sun.identity.liberty.ws.disco.common.DiscoUtils;
037import com.sun.identity.liberty.ws.util.ProviderManager;
038import com.sun.identity.liberty.ws.util.ProviderUtil;
039import com.sun.identity.xmlenc.*;
040
041/**
042 * The class <code>EncryptedResourceID</code> represents an Encryption
043 * Resource ID element for the Discovery Service.
044 * <p>The following schema fragment specifies the expected content within the
045 * <code>EncryptedResourceID</code> object.
046 * <p>
047 * <pre>
048 * &lt;xs:element name="EncryptedResourceID" type="EncryptedResourceIDType"/>
049 * &lt;complexType name="EncryptedResourceIDType">
050 *   &lt;complexContent>
051 *     &lt;restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
052 *       &lt;sequence>
053 *         &lt;element ref="{http://www.w3.org/2001/04/xmlenc#}EncryptedData"/>
054 *         &lt;element ref="{http://www.w3.org/2001/04/xmlenc#}EncryptedKey"/>
055 *       &lt;/sequence>
056 *     &lt;/restriction>
057 *   &lt;/complexContent>
058 * &lt;/complexType>
059 * </pre>
060 * 
061 * @supported.all.api
062 */
063public class EncryptedResourceID {
064
065    private Element data = null;
066    private Element key = null;
067    private String namespaceURI = null;
068
069    /**
070     * Default constructor.
071     */
072    public EncryptedResourceID() {}
073
074    /**
075     * Constructor.
076     * @param elem <code>EncryptedResourceID</code> DOM element
077     * @exception DiscoveryException if error occurs
078     */
079    public EncryptedResourceID(Element elem) throws DiscoveryException {
080        init(elem, DiscoConstants.DISCO_NS);
081    }
082
083    /**
084     * Constructs a encrypted resource ID.
085     *
086     * @param elem <code>EncryptedResourceID</code> DOM element
087     * @param nspaceURI Name space URI for this element. By default, Discovery
088     *        name space is used.
089     * @exception DiscoveryException if error occurs.
090     */ 
091    public EncryptedResourceID(Element elem, String nspaceURI)
092        throws DiscoveryException {
093        init(elem, nspaceURI);
094    }
095
096    private void init(Element elem, String nspaceURI)
097        throws DiscoveryException {
098        if (elem == null) {
099            DiscoUtils.debug.message("EncryptedResourceID(Element):null input");
100            throw new DiscoveryException(
101                DiscoUtils.bundle.getString("nullInput"));
102        }
103        String tag = null;
104        String nameSpaceURI = null;
105        if (((tag = elem.getLocalName()) == null) ||
106            (!tag.equals("EncryptedResourceID")) ||
107            ((nameSpaceURI = elem.getNamespaceURI()) == null) ||
108            (!nameSpaceURI.equals(nspaceURI)))
109        {
110            DiscoUtils.debug.message("EncryptedResourceID(Ele):wrong input");
111            throw new DiscoveryException(
112                DiscoUtils.bundle.getString("wrongInput"));
113        }
114
115        namespaceURI = nspaceURI;
116        NodeList contentnl = elem.getChildNodes();
117        String nodeName = null;
118        Node child;
119        for (int i = 0, length = contentnl.getLength(); i < length; i++) {
120            child = contentnl.item(i);
121            if ((nodeName = child.getLocalName()) != null) {
122                if (nodeName.equals("EncryptedData")) {
123                    if (data != null) {
124                        if (DiscoUtils.debug.messageEnabled()) {
125                            DiscoUtils.debug.message("EncryptedResourceID(Elem"
126                                + "ent):Included more than one EncryptedData.");
127                        }
128                        throw new DiscoveryException(
129                            DiscoUtils.bundle.getString("moreEncryptedData"));
130                    }
131                    data = (Element) child;
132                } else if (nodeName.equals("EncryptedKey")) {
133                    if (key != null) {
134                        if (DiscoUtils.debug.messageEnabled()) {
135                            DiscoUtils.debug.message("EncryptedResourceID(Elem"
136                                + "ent):Included more than one EncryptedKey.");
137                        }
138                        throw new DiscoveryException(
139                            DiscoUtils.bundle.getString("moreEncryptedKey"));
140                    }
141                    key = (Element) child;
142                } else {
143                    if (DiscoUtils.debug.messageEnabled()) {
144                        DiscoUtils.debug.message("EncryptedResourceID(Element):"
145                            + "invalid node" + nodeName);
146                    }
147                    throw new DiscoveryException(
148                        DiscoUtils.bundle.getString("wrongInput"));
149                }
150            }
151        }
152        if (data == null) {
153            if (DiscoUtils.debug.messageEnabled()) {
154                DiscoUtils.debug.message("EncryptedResourceID(Element): missing"
155                    + " EncryptedData element.");
156            }
157            throw new DiscoveryException(
158                DiscoUtils.bundle.getString("missingEncryptedData"));
159        }
160
161    }
162
163    /**
164     * Constructor.
165     * @param encryptedData Encrypted data in DOM Element.
166     * @param encryptedKey Encrypted key in DOM Element.
167     */
168    public EncryptedResourceID(Element encryptedData,
169                                Element encryptedKey)
170    {
171        data = encryptedData;
172        key = encryptedKey;
173    } 
174
175    /**
176     * Sets encrypted data element.
177     *
178     * @param data encrypted data element.
179     * @see #getEncryptedData()
180     */
181    public void setEncryptedData(Element data) {
182        this.data = data;
183    }
184
185    /** 
186     * Gets encrypted data.
187     *
188     * @return encrypted data.
189     * @see #setEncryptedData(Element)
190     */
191    public Element getEncryptedData() {
192        return data;
193    }
194
195    /**
196     * Gets encrypted key element.
197     *
198     * @return encrypted key element.
199     * @see #setEncryptedKey(Element)
200     */
201    public Element getEncryptedKey() {
202        return key;
203    }
204
205    /**
206     * Sets encrypted key element.
207     *
208     * @param key encrypted key element.
209     * @see #getEncryptedKey()
210     */
211    public void setEncryptedKey(Element key) {
212        this.key = key;
213    }
214
215    /**
216     * Returns an instance of <code>ResourceID</code> object. It takes an
217     * instance of <code>EncryptedResourceID</code> and decrypts the contents
218     * using the decryption key of the provider ID.
219     *
220     * @param eri <code>EncryptedResourceID</code> instance that needs to be
221     *        decrypted.
222     * @param providerID The provider ID whose decryption key that needs to be
223     *        used for decryption.
224     * @throws DiscoveryException if error occurs during the operation.
225     */ 
226    public static ResourceID getDecryptedResourceID(
227        EncryptedResourceID eri, String providerID)
228        throws DiscoveryException {
229
230        if ((eri == null) || (providerID == null)) {
231            throw new DiscoveryException(
232                DiscoUtils.bundle.getString("nullInput"));
233        }
234        ResourceID result = null;
235        try {
236            XMLEncryptionManager manager = XMLEncryptionManager.getInstance();
237            Document encDoc = XMLUtils.toDOMDocument(eri.toString(),
238                                                DiscoUtils.debug);
239
240            Document decryptDoc = manager.decryptAndReplace(encDoc,
241                ProviderUtil.getProviderManager().getDecryptionKey(providerID));
242            Element riEl = (Element) decryptDoc.getElementsByTagNameNS(
243                                DiscoConstants.DISCO_NS,
244                                "ResourceID").item(0);
245            result = new ResourceID(riEl);
246        } catch (Exception e) {
247            DiscoUtils.debug.error("EncryptedResourceID.getDecryptedResource"
248                + "ID: decryption exception:", e);
249            throw new DiscoveryException(e);
250        }
251        return result;
252    }
253
254    /**
255     * Returns an <code>EncryptedResourceID</code> object. It takes a
256     * resource ID and provider ID, encrypts the resource ID based on the
257     * encryption key of the provider ID.
258     *
259     * @param ri The resource ID instance that needs to be encrypted.
260     * @param providerID The provider ID whose encryption key needs to be used
261     *        for encryption.
262     * @throws DiscoveryException if error occurs during this operation.
263     */ 
264    public static EncryptedResourceID getEncryptedResourceID(
265        ResourceID ri,
266        String providerID
267    ) throws DiscoveryException {
268        if ((ri == null) || (providerID == null)) {
269            DiscoUtils.debug.error("EncryptedResourceID.getEncryptedResource"
270                + "ID: null input value");
271            throw new DiscoveryException(
272                        DiscoUtils.bundle.getString("nullInput"));
273        }
274        EncryptedResourceID eri = null;
275        try {
276            ProviderManager pm = ProviderUtil.getProviderManager();
277            Document doc = XMLUtils.toDOMDocument(ri.toString(),
278                                                DiscoUtils.debug);
279
280            XMLEncryptionManager manager = XMLEncryptionManager.getInstance();
281            Document encDoc = manager.encryptAndReplaceResourceID(doc,
282                doc.getDocumentElement(),
283                pm.getEncryptionKeyAlgorithm(providerID),
284                pm.getEncryptionKeyStrength(providerID),
285                pm.getEncryptionKey(providerID),
286                0,
287                providerID);
288            eri = new EncryptedResourceID(encDoc.getDocumentElement());
289        } catch (Exception e) {
290            DiscoUtils.debug.error("EncryptedResourceID.getEncryptedResource"
291                + "ID: encryption exception:", e);
292            throw new DiscoveryException(e);
293        }
294        return eri;
295    }
296
297    /**
298     * Returns string format.
299     *
300     * @return formatted string.
301     */ 
302    public java.lang.String toString() {
303        return toString(namespaceURI);
304    }
305
306    /**
307     * Returns string format.
308     *
309     * @param ns  namespace value
310     * @return formatted string.
311     */
312    public java.lang.String toString(String ns) {
313        StringBuffer sb = new StringBuffer(1000);
314        sb.append("<EncryptedResourceID xmlns=\"").
315            append(ns).append("\">");
316        if (data != null) {
317            sb.append(XMLUtils.print(data));
318        }
319        if (key != null) {
320            sb.append(XMLUtils.print(key));
321        }
322        sb.append("</EncryptedResourceID>");
323        return sb.toString();
324    }
325}