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: StatusCode.java,v 1.2 2008/06/25 05:47:37 qcheng Exp $ 026 * 027 */ 028 029 030package com.sun.identity.saml.protocol; 031 032import com.sun.identity.shared.xml.XMLUtils; 033 034import com.sun.identity.saml.common.SAMLConstants; 035import com.sun.identity.saml.common.SAMLException; 036import com.sun.identity.saml.common.SAMLRequesterException; 037import com.sun.identity.saml.common.SAMLUtils; 038 039import java.util.Collections; 040import java.util.List; 041import java.util.StringTokenizer; 042 043import org.w3c.dom.Element; 044 045/** 046 * This class represents the <code>StatusCode</code> and 047 * <code>SubStatusCode</code> element. It corresponds to 048 * <code>samlp:StatusCodeType</code> in SAML protocol schema. 049 * 050 * @supported.all.api 051 */ 052public class StatusCode { 053 054 private StatusCode subStatusCode = null; 055 private String value = null; 056 057 /** 058 * This is the default constructor of <code>StatusCode</code>. 059 */ 060 StatusCode() { 061 } 062 063 /** 064 * Constructs an instance of <code>StatusCode</code> from a DOM element. 065 * 066 * @param statusCode An DOM Element that's rooted by 067 * <code><StatusCode></code>. 068 * @exception SAMLException when an error occurs. 069 */ 070 public StatusCode(Element statusCode) throws SAMLException { 071 if (statusCode == null) { 072 SAMLUtils.debug.message("StatusCode: null input."); 073 throw new SAMLRequesterException( 074 SAMLUtils.bundle.getString("nullInput")); 075 } 076 String tagName = statusCode.getLocalName(); 077 if (!tagName.equals("StatusCode")) { 078 SAMLUtils.debug.message("StatusCode: Wrong input: " + tagName); 079 throw new SAMLRequesterException( 080 SAMLUtils.bundle.getString("wrongInput")); 081 } 082 value = statusCode.getAttribute("Value"); 083 if ((value == null) || (value.length() == 0)) { 084 SAMLUtils.debug.message("StatusCode: empty attribute Value."); 085 throw new SAMLRequesterException( 086 SAMLUtils.bundle.getString("missingAttribute")); 087 } 088 089 List subCodenl = XMLUtils.getElementsByTagNameNS1( 090 (Element) statusCode, 091 SAMLConstants.PROTOCOL_NAMESPACE_URI, 092 "StatusCode"); 093 int length = subCodenl.size(); 094 if (length == 1) { 095 subStatusCode = new StatusCode((Element) subCodenl.get(0)); 096 } else if (length != 0) { 097 if (SAMLUtils.debug.messageEnabled()) { 098 SAMLUtils.debug.message("StatusCode: Included more than one" 099 + " <StatusCode> in element " + tagName); 100 } 101 throw new SAMLRequesterException( 102 SAMLUtils.bundle.getString("moreElement")); 103 } 104 } 105 106 /** 107 * Construct a <code>StatusCode</code> object from a value String and a sub 108 * <code>StatusCode</code>. 109 * 110 * @param value The value of the <code>StatusCode</code>. This could be 111 * prefixed by <code>samlp:</code>. If it is not prefixed, or 112 * prefixed by prefix other than <code>samlp:</code>, 113 * <code>samlp:</code> will be used instead. 114 * @param subCode The optional sub <code>StatusCode</code>. 115 * @exception SAMLException if value string is null, empty, or contains 116 * wrong value. 117 */ 118 public StatusCode(String value, StatusCode subCode) throws SAMLException { 119 this.value = checkAndGetValue(value); 120 subStatusCode = subCode; 121 } 122 123 /** 124 * Construct a <code>StatusCode</code> object from a value String. 125 * 126 * @param value The value of the <code>StatusCode</code>. This could be 127 * prefixed by <code>samlp:</code>. It it is not prefixed, or 128 * prefixed by prefix other than <code>samlp:</code>, 129 * <code>samlp:</code> will be used instead. 130 * @exception SAMLException if value string is null, empty, or contains 131 * wrong value. 132 */ 133 public StatusCode(String value) throws SAMLException { 134 this.value = checkAndGetValue(value); 135 } 136 137 private String checkAndGetValue(String value) throws SAMLException { 138 if ((value == null) || (value.length() == 0)) { 139 SAMLUtils.debug.message("StatusCode: empty attribute Value."); 140 throw new SAMLRequesterException( 141 SAMLUtils.bundle.getString("missingAttribute")); 142 } 143 144 if (value.indexOf(":") == -1) { 145 return (SAMLConstants.PROTOCOL_PREFIX + value); 146 } else { 147 StringTokenizer st = new StringTokenizer(value, ":"); 148 if (st.countTokens() != 2) { 149 SAMLUtils.debug.message("StatusCode: wrong attribute value."); 150 throw new SAMLRequesterException( 151 SAMLUtils.bundle.getString("wrongAttrValue")); 152 } 153 return value; 154 } 155 } 156 157 /** 158 * Sets the sub <code>StatusCode</code>. 159 * @param subcode <code>StatusCode</code> to be included. 160 */ 161 public void setStatusCode(StatusCode subcode) { 162 subStatusCode = subcode; 163 } 164 165 /** 166 * Gets the sub <code>StatusCode</code> of the <code>StatusCode</code>. 167 * @return <code>StatusCode</code>. 168 */ 169 public StatusCode getStatusCode() { 170 return subStatusCode; 171 } 172 173 /** 174 * Gets the value of the <code>StatusCode</code>. 175 * @return A String representing the value of the <code>StatusCode</code>. 176 */ 177 public String getValue() { 178 return value; 179 } 180 181 /** 182 * Translates the <code>StatusCode</code> to an XML document String 183 * based on the SAML schema. 184 * @return An XML String representing the <code>StatusCode</code>. 185 */ 186 public String toString() { 187 return toString(true, false); 188 } 189 190 /** 191 * Creates a String representation of the 192 * <code><samlp:StatusCode></code> element. 193 * 194 * @param includeNS Determines whether or not the namespace qualifier 195 * is prepended to the Element when converted 196 * @param declareNS Determines whether or not the namespace is declared 197 * within the Element. 198 * @return A string containing the valid XML for this element. 199 */ 200 public String toString(boolean includeNS, boolean declareNS) { 201 StringBuffer xml = new StringBuffer(100); 202 String prefix = ""; 203 String uri = ""; 204 if (includeNS) { 205 prefix = SAMLConstants.PROTOCOL_PREFIX; 206 } 207 if (declareNS) { 208 uri = SAMLConstants.PROTOCOL_NAMESPACE_STRING; 209 } 210 String tag = "StatusCode"; 211 xml.append("<").append(prefix).append(tag).append(uri). 212 append(" Value=\""); 213 if (value.startsWith(SAMLConstants.PROTOCOL_PREFIX)) { 214 xml.append(value); 215 } else { 216 try { 217 xml.append(checkAndGetValue(value)); 218 } catch (SAMLException e) { 219 SAMLUtils.debug.error("StatusCode.toString: ", e); 220 xml.append(value); 221 } 222 } 223 xml.append("\">\n"); 224 if ((subStatusCode != null) && 225 (subStatusCode != Collections.EMPTY_LIST)) { 226 xml.append(subStatusCode.toString(includeNS, false)); 227 } 228 xml.append("</").append(prefix).append(tag).append(">\n"); 229 return xml.toString(); 230 } 231}