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: AttributeQuery.java,v 1.2 2008/06/25 05:47:36 qcheng Exp $
026 *
027 */
028
029
030package com.sun.identity.saml.protocol;
031
032import com.sun.identity.saml.assertion.AttributeDesignator;
033import com.sun.identity.saml.assertion.Subject;
034
035import com.sun.identity.saml.common.SAMLConstants;
036import com.sun.identity.saml.common.SAMLException;
037import com.sun.identity.saml.common.SAMLRequesterException;
038import com.sun.identity.saml.common.SAMLUtils;
039
040import java.util.ArrayList;
041import java.util.Collections;
042import java.util.Iterator;
043import java.util.List;
044
045import org.w3c.dom.Element;
046import org.w3c.dom.Node;
047import org.w3c.dom.NodeList;
048
049/**
050 * This concrete class extends from the abstract base class
051 * <code>SubjectQuery</code>.
052 * It represents the query for an attribute assertion. It corresponds
053 * to the <code>samlp:AttributeQueryType</code> in the SAML protocol schema.
054 *
055 * @supported.all.api
056 */
057public class AttributeQuery extends SubjectQuery {
058
059    /**
060     * O or more AttributeDesignator of this query.
061     */
062    protected List attributeDesignators = Collections.EMPTY_LIST;
063
064    protected String resource = null;
065   
066    /**
067     * Default constructor 
068     */
069    protected AttributeQuery() {
070    }
071   
072    /**
073     * This constructor is used to build an Attribute Query from a DOM
074     * tree that was built from the XML string.
075     *
076     * @param element the DOM tree element which contains an Attribute Query.
077     * @throws SAMLException
078     */
079    public AttributeQuery(Element element) throws SAMLException {
080        // make sure the input is not null
081        if (element == null) {
082            SAMLUtils.debug.message("AttributeQuery(Element): null input.");
083            throw new SAMLRequesterException(
084                SAMLUtils.bundle.getString("nullInput"));
085        }
086
087        // make sure it's an AttributeQuery
088        boolean valid = SAMLUtils.checkQuery(element, "AttributeQuery");
089        if (!valid) {
090            SAMLUtils.debug.message("AttributeQuery: wrong input.");
091            throw new SAMLRequesterException(
092                SAMLUtils.bundle.getString("wrongInput"));
093        }
094
095        if (element.hasAttribute("Resource")) {
096            resource = element.getAttribute("Resource");
097        }
098
099        NodeList nl = element.getChildNodes();
100        Node child;
101        String childName;
102        for (int k = 0, length = nl.getLength(); k < length; k++) {
103            child = nl.item(k);
104            if ((childName = child.getLocalName()) != null) {
105                if (childName.equals("Subject")) {
106                    if (subject != null) {
107                        if (SAMLUtils.debug.messageEnabled()) {
108                            SAMLUtils.debug.message("AttributeQuery(Element): "
109                                + "contained more than one Subject");
110                        }
111                        throw new SAMLRequesterException(
112                            SAMLUtils.bundle.getString("moreElement"));
113                    }
114                    subject = new Subject((Element) child);
115                } else if (childName.equals("AttributeDesignator")) {
116                    if (attributeDesignators == Collections.EMPTY_LIST) {
117                        attributeDesignators = new ArrayList();
118                    }
119                    attributeDesignators.add(
120                                new AttributeDesignator((Element) child));
121                } else {
122                    if (SAMLUtils.debug.messageEnabled()) {
123                        SAMLUtils.debug.message("AttributeQuery(Element): "
124                            + "included wrong element:" + childName);
125                    }
126                    throw new SAMLRequesterException(
127                        SAMLUtils.bundle.getString("wrongInput"));
128                }
129            } // end childName != null
130        } // end for loop
131
132        // make sure there is one Subject
133        if (subject == null) {
134            SAMLUtils.debug.message("AttributeQuery: missing Subject");
135            throw new SAMLRequesterException(
136                SAMLUtils.bundle.getString("missingElement"));
137        }
138    }
139
140    /**
141     * Constructor.
142     * @param theSubject Subject of this query.
143     * @param designators List of <code>AttributeDesignators</code> of this
144     *        query.
145     * @param theResource the Resource attribute of this query in String format.
146     * @throws SAMLException
147     */
148    public AttributeQuery(Subject theSubject,
149                        List designators,
150                        String theResource)
151                                        throws SAMLException
152    {
153        buildAttributeQuery(theSubject, designators, theResource);
154    }
155
156    /**
157     * Constructor to construct an <code>AttributeQuery</code> with a list of 
158     * <code>AttributeDesignators</code>.
159     *
160     * @param theSubject Subject of this query.
161     * @param designators List of <code>AttributeDesignators</code> of this
162     *        query.
163     * @throws SAMLException
164     */       
165    public  AttributeQuery(Subject theSubject,
166                                List designators) throws SAMLException {
167        buildAttributeQuery(theSubject, designators, null);
168    }
169
170    /**
171     * Constructor to construct an <code>AttributeQuery</code> with 0
172     * <code>AttributeDesignator</code>, and no Resource attribute.
173     *
174     * @param theSubject Subject of this query.
175     * @throws SAMLException
176     */
177    public AttributeQuery(Subject theSubject) throws SAMLException {
178        buildAttributeQuery(theSubject, null, null);
179    }
180 
181    private void buildAttributeQuery(Subject theSubject,
182                                        List designators,
183                                        String theResource)
184                                        throws SAMLException {
185        if (theSubject == null) {
186            SAMLUtils.debug.message("AttributeQuery: missing subject.");
187            throw new SAMLRequesterException(
188                        SAMLUtils.bundle.getString("missingElement"));
189        }
190        this.subject = theSubject;
191
192        int length;
193        Object temp = null;
194        if ((designators != null) &&
195            ((length = designators.size()) != 0)) {
196            for (int i = 0; i < length; i++) {
197                temp = designators.get(i);
198                if (!(temp instanceof AttributeDesignator)) {
199                    if (SAMLUtils.debug.messageEnabled()) {
200                        SAMLUtils.debug.message("AttributeQuery: Wrong input "
201                            + "for AttributeDesignator.");
202                    }
203                    throw new SAMLRequesterException(
204                        SAMLUtils.bundle.getString("wrongInput"));
205                }
206            }
207            this.attributeDesignators = designators;
208        }
209
210        this.resource = theResource;
211    }
212
213    /**
214     * Returns the Resource String.
215     *
216     * @return the Resource associated with this query in String format; or
217     *          null if there is none.
218     */
219    public String getResource() {
220        return resource;
221    }
222
223    /**
224     * Returns the <code>AttributeDesignators</code>.
225     *
226     * @return the <code>AttributeDesignators</code>(s) associated with this
227     *         query. It could contain 0 or more
228     *         <code>AttributeDesignators</code>.
229     */
230    public List getAttributeDesignator() {
231        return attributeDesignators; 
232    }
233
234    /**
235     * Returns the type of the query.
236     *
237     * @return an integer which is Query.ATTRIBUTE_QUERY.
238     */
239    public int getQueryType() {
240        return Query.ATTRIBUTE_QUERY;
241    }
242
243    /**
244     * Returns the String Representation of the <code>AttributeQuery</code> 
245     * object.
246     *
247     * @return XML String representing the <code>AttributeQuery</code>.
248     */
249    public String toString() {
250        return toString(true, false);
251    }
252
253    /**
254     * Returns a String representation of the <code>samlp:AttributeQuery</code>
255     * element.
256     *
257     * @param includeNS Determines whether or not the namespace qualifier
258     *        is prepended to the Element when converted.
259     * @param declareNS Determines whether or not the namespace is declared
260     *        within the Element.
261     * @return A string containing the valid XML for this element.
262     */
263    public String toString(boolean includeNS, boolean declareNS) {
264        StringBuffer xml = new StringBuffer(300);
265        String prefix = "";
266        String uri = "";
267        if (includeNS) {
268            prefix = SAMLConstants.PROTOCOL_PREFIX;
269        }
270        if (declareNS) {
271            uri = SAMLConstants.PROTOCOL_NAMESPACE_STRING;
272        }
273        xml.append("<").append(prefix).append("AttributeQuery").append(uri);
274        if (resource != null) {
275            xml.append(" Resource=\"").append(resource).append("\"");
276        }
277        xml.append(">\n").append(subject.toString(true, true));
278        Iterator iterator = attributeDesignators.iterator();
279        while (iterator.hasNext()) {
280            xml.append(((AttributeDesignator) iterator.next()).
281                                                toString(true, true));
282        }
283        xml.append("</").append(prefix).append("AttributeQuery>\n");
284        return xml.toString();
285    }
286}