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: AuthorityBinding.java,v 1.2 2008/06/25 05:47:32 qcheng Exp $
026 *
027 */
028
029
030package com.sun.identity.saml.assertion;
031
032import java.util.*; 
033import org.w3c.dom.*; 
034import com.sun.identity.saml.common.SAMLUtilsCommon;
035import com.sun.identity.saml.common.SAMLConstants;
036import com.sun.identity.saml.common.SAMLException;
037import com.sun.identity.saml.common.SAMLRequesterException;
038
039/**
040 * The <code>AuthorityBinding</code> element may be used to indicate
041 * to a replying party receiving an <code>AuthenticationStatement</code> that
042 * a SAML authority may be available to provide additional information about
043 * the subject of the statement. A single SAML authority may advertise its
044 * presence over multiple protocol binding, at multiple locations, and as
045 * more than one kind of authority by sending multiple elements as needed.
046 * @supported.all.api
047 */
048public class AuthorityBinding  { 
049    private String _binding = null;
050    private String _location = null; 
051    private int _authorityKind = AuthorityKindType.NOT_SUPPORTED;  
052     
053/**
054 *The <code>AuthorityKindType</code> is an inner class defining constants for 
055 *the representing the type of SAML protocol queries to which the authority 
056 *described by this element will respond.
057 *<br>1 implies <code>AUTHENTICATION</code>
058 *<br>2 implies <code>ATTRIBUTE</code>
059 *<br>3 implies <code>AUTHORIZATION</code>
060 *<br>-1  implies <code>NOT_SUPPORTED</code>
061 */
062    public static class AuthorityKindType {
063
064        /**
065         * Authentication Query.
066         */
067        public static final int  AUTHENTICATION = 1;  // "authentication"
068
069        /**
070         * Attribute Query.
071         */
072        public static final int  ATTRIBUTE      = 2;       // "attribute"
073
074        /**
075         * Authorization Decision Query.
076         */
077        public static final int  AUTHORIZATION  = 3;   // "authorization"
078
079        /**
080         * Unsupported Query.
081         */
082        public static final int  NOT_SUPPORTED  = -1;  // not supported 
083    }
084    
085    /**
086     * Constructs an <code>AuthorityBinding</code> element from an existing XML
087     * block.
088     *
089     * @param element representing a DOM tree element.
090     * @exception SAMLException if there is an error in the sender or in the
091     *            element definition.
092     */
093    public AuthorityBinding(Element element) throws SAMLException {
094        // make sure that the input xml block is not null
095        if (element == null) {
096            SAMLUtilsCommon.debug.message("AuthorityBinding: Input is null.");
097            throw new SAMLRequesterException(
098                      SAMLUtilsCommon.bundle.getString("nullInput"));
099        }
100        // Make sure this is an AuthorityBinding.
101        String tag = null;
102        tag = element.getLocalName(); 
103        if ((tag == null) || (!tag.equals("AuthorityBinding"))) {
104            SAMLUtilsCommon.debug.message("AuthorityBinding: wrong input");
105            throw new SAMLRequesterException(
106                      SAMLUtilsCommon.bundle.getString("wrongInput"));
107        }
108        
109        int i = 0; 
110        //handle the attributes of AuthorityBinding
111        NamedNodeMap atts = ((Node)element).getAttributes(); 
112        int attrCount = atts.getLength(); 
113        for (i = 0; i < attrCount; i++) {
114            Node att = atts.item(i);
115            if (att.getNodeType() == Node.ATTRIBUTE_NODE) {
116                String attName = att.getLocalName();
117                if (attName == null || attName.length() == 0) {
118                    if (SAMLUtilsCommon.debug.messageEnabled()) {
119                        SAMLUtilsCommon.debug.message("AuthorityBinding: " +
120                            "Attribute Name is either null or empty.");
121                    }
122                    throw new SAMLRequesterException(
123                        SAMLUtilsCommon.bundle.getString("nullInput"));
124                }
125                if (attName.equals("AuthorityKind")) {
126                    String kind = ((Attr)att).getValue().trim();
127                    if (kind == null || kind.length() == 0) {
128                        if (SAMLUtilsCommon.debug.messageEnabled()) {
129                            SAMLUtilsCommon.debug.message("AuthorityBinding: "+
130                                            "AuthorityKind is null or empty.");
131                        }
132                        throw new SAMLRequesterException(
133                            SAMLUtilsCommon.bundle.getString(
134                            "missingAttributeValue"));
135                    }
136                    if (kind.equals("samlp:AuthenticationQuery")) 
137                        _authorityKind = AuthorityKindType.AUTHENTICATION; 
138                    else if (kind.equals("samlp:AttributeQuery"))
139                        _authorityKind = AuthorityKindType.ATTRIBUTE; 
140                    else if (kind.equals("samlp:AuthorizationDecisionQuery"))
141                        _authorityKind = AuthorityKindType.AUTHORIZATION; 
142                    else {
143                        if (SAMLUtilsCommon.debug.messageEnabled()) {
144                            SAMLUtilsCommon.debug.message("AuthorityBinding: " +
145                                           "The type of authority is illegal!");
146                        }
147                        throw new SAMLRequesterException(
148                            SAMLUtilsCommon.bundle.getString("wrongInput"));  
149                    }
150                } else if (attName.equals("Binding")) { 
151                    _binding = ((Attr)att).getValue().trim();
152                    if (_binding == null || _binding.length() == 0) {
153                        if (SAMLUtilsCommon.debug.messageEnabled()) {
154                            SAMLUtilsCommon.debug.message("AuthorityBinding: "+
155                                "Binding URI is null or empty.");
156                        }
157                        throw new SAMLRequesterException(
158                            SAMLUtilsCommon.bundle.getString(
159                            "missingAttributeValue"));
160                    }
161                }  else if (attName.equals("Location")) {
162                     _location = ((Attr)att).getValue().trim();
163                     if (_location == null || _location.length() == 0) {
164                         if (SAMLUtilsCommon.debug.messageEnabled()) {
165                             SAMLUtilsCommon.debug.message("AuthorityBinding:"
166                                 + " Location URI is null or empty.");
167                         }
168                        throw new SAMLRequesterException(
169                            SAMLUtilsCommon.bundle.getString(
170                            "missingAttributeValue"));
171                     }
172                }
173            }  // end of  if (att.getNodeType() == Node.ATTRIBUTE_NODE)
174        }  // end of for loop 
175         
176        // AuthorityKind is required 
177        if ( _authorityKind == AuthorityKindType.NOT_SUPPORTED) {
178            if (SAMLUtilsCommon.debug.messageEnabled()) {
179                SAMLUtilsCommon.debug.message("AuthorityBinding: " +
180                                        "AuthorityKind is required attribute");
181            }
182            throw new SAMLRequesterException(
183                        SAMLUtilsCommon.bundle.getString("missingAttribute"));
184        }   
185        // Location is required 
186        if ( _location == null) {
187            if (SAMLUtilsCommon.debug.messageEnabled()) {
188                SAMLUtilsCommon.debug.message("AuthorityBinding: Location is " +
189                                        "required attribute");
190            }
191            throw new SAMLRequesterException(
192                        SAMLUtilsCommon.bundle.getString("missingAttribute"));
193        }
194        // Binding is required 
195        if ( _binding == null) {
196            if (SAMLUtilsCommon.debug.messageEnabled()) {
197                SAMLUtilsCommon.debug.message("AuthorityBinding: Binding is" +
198                                        " required attribute");
199            }
200            throw new SAMLRequesterException(
201                        SAMLUtilsCommon.bundle.getString("missingAttribute"));
202        }
203        // handle the children elements of AuthorityBinding
204        // Since it does not contain any child element_node, 
205        // we will throw exception if we found any such child. 
206        NodeList  nodes = element.getChildNodes();
207        int nodeCount = nodes.getLength(); 
208        if (nodeCount > 0) {
209            for (i = 0; i < nodeCount; i++) {
210                Node currentNode = nodes.item(i);               
211                if (currentNode.getNodeType() == Node.ELEMENT_NODE) {
212                    if (SAMLUtilsCommon.debug.messageEnabled()) {
213                        SAMLUtilsCommon.debug.message("AuthorityBinding: " +
214                                                " illegal input!");
215                    }
216                    throw new SAMLRequesterException(
217                        SAMLUtilsCommon.bundle.getString("wrongInput"));
218                }
219            }
220        }
221    }
222    
223    /**
224     *Constructs <code>AuthorityBinding</code>
225     *@param authKind A integer representing the type of SAML protocol queries
226     *       to which the authority described by this element will 
227     *       respond. If you do NO specify this attribute, pass in 
228     *       value "-1". 
229     *@param location A URI describing how to locate and communicate with the 
230     *       authority, the exact syntax of which depends on the 
231     *       protocol binding in use.  
232     *@param binding A String representing a URI reference identifying the  
233     *       SAML protocol binding to use in  communicating with the 
234     *       authority.         
235     *@exception SAMLException if there is an error in the sender or in the
236     *           element definition.
237     */         
238    public AuthorityBinding(int authKind, String location, String binding)
239                                                    throws SAMLException {
240        if (location == null || location.length() == 0){
241            if (SAMLUtilsCommon.debug.messageEnabled()) {
242                  SAMLUtilsCommon.debug.message("AuthorityBinding: The " +
243                      "Location URI can not be null or empty!");
244            }
245            throw new SAMLRequesterException(
246                        SAMLUtilsCommon.bundle.getString("nullInput"));
247        } else {
248            _location = location;
249        }
250        
251         if (binding == null || binding.length() == 0){
252            if (SAMLUtilsCommon.debug.messageEnabled()) {
253                  SAMLUtilsCommon.debug.message("AuthorityBinding: The " +
254                      "binding URI can not be null or empty!");
255            }
256            throw new SAMLRequesterException(
257                        SAMLUtilsCommon.bundle.getString("nullInput"));
258        } else {
259            _binding = binding;
260        }
261        
262        if (authKind >= AuthorityKindType.AUTHENTICATION &&
263            authKind <= AuthorityKindType.AUTHORIZATION ) {
264            _authorityKind = authKind; 
265        } else {
266            if (SAMLUtilsCommon.debug.messageEnabled()) {
267                 SAMLUtilsCommon.debug.message("AuthorityBinding:The type of "+
268                                          "authority is illegal!");
269            }
270            throw new SAMLRequesterException(
271                        SAMLUtilsCommon.bundle.getString("wrongInput"));   
272        }
273    }
274    
275    /**
276     *Gets the Location URI
277     *@return  A String representing the URI describing how to locate and 
278     *          communicate with the authority, the exact syntax of which
279     *          depends on the protocol binding in use.  
280     */
281    public String getLocation() {
282        return _location;
283    }
284    
285    /**
286     *Gets the binding URI 
287     *@return A String representing a URI reference identifying the SAML 
288     *        protocol binding to use in  communicating with the authority.  
289     */
290    public String getBinding() {
291        return _binding;
292    }
293    
294    /**
295     * Returns the <code>AuthorityKind</code>.
296     *
297     * @return A integer representing the type of SAML protocol queries to which
298     *        the authority described by this element will respond.
299     */
300    public int getAuthorityKind() {
301        return _authorityKind; 
302    }
303    
304    /** 
305     * Returns a String representation of the <code>AuthorityBinding</code>
306     *
307     * @return A String representation of the
308     *        <code>AuthorityBinding</code> element.
309     */
310    public String toString() {
311        return (toString(true, false)); 
312    }
313   
314    /** 
315     * Returns a String representation of the <code>AuthorityBinding</code>
316     * @param includeNS Determines whether or not the namespace qualifier is 
317     *        prepended to the Element when converted
318     * @param declareNS Determines whether or not the namespace is declared 
319     *        within the Element.
320     * @return A String representation of the <code>AuthorityBinding</code>
321     *        element.
322     */                             
323    public String toString(boolean includeNS, boolean declareNS) {
324        StringBuffer result  = new StringBuffer(300); 
325        String prefix = "";
326        String uri = "";
327        if (includeNS) {
328            prefix = SAMLConstants.ASSERTION_PREFIX;
329        }
330        if (declareNS) {
331            uri = SAMLConstants.assertionDeclareStr;
332        }
333        result.append("<").append(prefix).append("AuthorityBinding").
334               append(uri).append(" AuthorityKind=\"");
335        switch(_authorityKind) {
336            case AuthorityKindType.AUTHENTICATION: 
337                 result.append("samlp:AuthenticationQuery");
338                 break; 
339            case AuthorityKindType.ATTRIBUTE: 
340                 result.append("samlp:AttributeQuery");
341                 break ; 
342            case AuthorityKindType.AUTHORIZATION:
343                 result.append("samlp:AuthorizationDecisionQuery");
344                 break ;  
345        }
346        result.append("\"").append(" Location=\"").append(_location).
347               append("\"").append(" Binding=\"").append(_binding).
348               append("\"").append(" />\n");
349        return(result.toString());
350    }
351}
352