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: FSScoping.java,v 1.2 2008/06/25 05:46:45 qcheng Exp $
026 *
027 */
028
029package com.sun.identity.federation.message;
030
031import com.sun.identity.federation.common.FSUtils;
032import com.sun.identity.federation.common.IFSConstants;
033import com.sun.identity.federation.message.common.FSMsgException;
034import com.sun.identity.federation.message.common.IDPEntries;
035import com.sun.identity.federation.message.common.IDPEntry;
036import com.sun.identity.shared.encode.URLEncDec;
037import com.sun.identity.shared.xml.XMLUtils;
038import java.util.ArrayList;
039import java.util.Iterator;
040import java.util.List;
041import javax.servlet.http.HttpServletRequest;
042import org.w3c.dom.Element;
043import org.w3c.dom.Node;
044import org.w3c.dom.NodeList;
045
046
047/**
048 * This class <code>FSScoping</code> creates scoping element for the
049 * authentication request.
050 *
051 * @supported.all.api
052 */
053
054public class FSScoping {
055    
056    private int proxyCount = -1;
057    private FSIDPList idpList = null;
058    
059    /**
060     * Default constructor
061     */
062    public FSScoping() {}
063    
064    /**
065     * Constructor creates <code>FSScoping</code> object.
066     *
067     * @param idpList the <code>FSIDPList</code> object.
068     * @param proxyCount the number of proxies
069     */
070    public FSScoping(FSIDPList idpList, int proxyCount) {
071        this.idpList = idpList;
072        this.proxyCount = proxyCount;
073    }
074    
075    /**
076     * Constructor creates <code>FSScoping</code> object from
077     * the Document Element.
078     *
079     * @param root the Document Element .
080     * @throws FSMsgException if there is a failure creating this object.
081     */
082    public FSScoping(Element root) throws FSMsgException {
083        if(root == null) {
084            FSUtils.debug.error("FSScoping(Element): null input");
085            throw new FSMsgException("nullInput", null);
086        }
087        String tagName = root.getLocalName();
088        if(tagName == null || !tagName.equals("Scoping")) {
089            FSUtils.debug.error("FSScoping(Element): wrong input");
090            throw new FSMsgException("wrongInput", null);
091        }
092        NodeList childNodes = root.getChildNodes();
093        int length = childNodes.getLength();
094        for (int i=0; i < length; i++) {
095            Node child = childNodes.item(i);
096            String nodeName = child.getLocalName();
097            if(nodeName == null) {
098                continue;
099            }
100            if(nodeName.equals("ProxyCount")) {
101                String count = XMLUtils.getElementValue((Element)child);
102                try {
103                    proxyCount = Integer.parseInt(count);
104                } catch (NumberFormatException ne) {
105                    FSUtils.debug.error("FSScoping(Element): invalid proxy" +
106                            "Count", ne);
107                    throw new FSMsgException("wrongInput", null);
108                }
109            } else if(nodeName.equals("IDPList")) {
110                idpList = new FSIDPList((Element)child);
111            }
112        }
113    }
114    
115    /**
116     * Sets the proxy count.
117     *
118     * @param count number of proxies
119     */
120    public void setProxyCount(int count) {
121        proxyCount = count;
122    }
123    
124    /**
125     * Returns the proxy count.
126     *
127     * @return number of proxies.
128     */
129    public int getProxyCount() {
130        return proxyCount;
131    }
132    
133    /**
134     * Sets preferred ordered List of IDPs that is known to SP for proxying.
135     *
136     * @param idpList the <code>FSIDPList</code> object.
137     */
138    public void setIDPList(FSIDPList idpList) {
139        this.idpList = idpList;
140    }
141    
142    /**
143     * Returns the preferred IDPs list in an authentication request.
144     *
145     * @return the <code>FSIDPList</code> object.
146     */
147    public FSIDPList getIDPList() {
148        return idpList;
149    }
150    
151    /**
152     * Returns a <code>XML</code> string representation of this object.
153     *
154     * @return XML String representing this object.
155     * @throws FSMsgException if there is an error creating
156     *         the XML string or if the required elements to create
157     *         the string do not conform to the schema.
158     */
159    
160    public String toXMLString() throws FSMsgException {
161        return toXMLString(true, true);
162    }
163    
164    /**
165     * Creates a String representation of this object.
166     *
167     * @param includeNS : Determines whether or not the namespace qualifier
168     *        is prepended to the Element when converted
169     * @param declareNS : Determines whether or not the namespace is declared
170     *        within the Element.
171     * @return string containing the valid XML for this element.
172     * @throws FSMsgException if there is an error.
173     */
174    public String toXMLString(boolean includeNS, boolean declareNS)
175    throws FSMsgException {
176        StringBuffer xml = new StringBuffer(300);
177        String prefix = "";
178        String uri = "";
179        if(includeNS) {
180            prefix = IFSConstants.LIB_PREFIX;
181        }
182        if(declareNS) {
183            uri = IFSConstants.LIB_12_NAMESPACE_STRING;
184        }
185        xml.append("<").append(prefix).append("Scoping")
186        .append(uri).append(">\n");
187        if(proxyCount >= 0) {
188            xml.append("<").append(prefix).append("ProxyCount").append(">")
189            .append(proxyCount).append("</").append(prefix)
190            .append("ProxyCount").append(">\n");
191        }
192        if(idpList != null) {
193            xml.append(idpList.toXMLString(true, false));
194        }
195        xml.append("</").append(prefix).append("Scoping").append(">\n");
196        return xml.toString();
197    }
198    
199    /**
200     * Returns an URL Encoded String.
201     *
202     * @return a url encoded query string.
203     * @throws FSMsgException if there is an error.
204     */
205    public String toURLEncodedQueryString() throws FSMsgException {
206        
207        if(proxyCount == -1) {
208            FSUtils.debug.error("FSScoping.toURLEncodedQueryString: " +
209                    "proxyCount is not defined.");
210            throw new FSMsgException("proxyCountNotDefined",null);
211        }
212        
213        StringBuffer sb = new StringBuffer(100);
214        sb.append("ProxyCount=").append(proxyCount).append("&");
215        if (idpList != null) {
216            IDPEntries entries = idpList.getIDPEntries();
217            if(entries != null) {
218                List idps = entries.getIDPEntryList();
219                if(idps != null && idps.size() != 0) {
220                    Iterator iter = idps.iterator();
221                    StringBuffer strProviders = new StringBuffer(100);
222                    String space = "";
223                    while(iter.hasNext()) {
224                        IDPEntry entry = (IDPEntry)iter.next();
225                        String providerID = entry.getProviderID();
226                        strProviders.append(space).append(providerID);
227                        space = " ";
228                    }
229                    sb.append("IDPEntries=").append(
230                            URLEncDec.encode(strProviders.toString()));
231                }
232            }
233        }
234        sb.append(IFSConstants.AMPERSAND);
235        return sb.toString();
236        
237    }
238    
239    /**
240     * Returns <code>FSScoping</code> object. The
241     * object is creating by parsing the <code>HttpServletRequest</code>
242     * object.
243     *
244     * @param request the <code>HttpServletRequest</code> object.
245     * @throws FSMsgException if there is an error creating this object.
246     */
247    public static FSScoping parseURLEncodedRequest(HttpServletRequest request) {
248        
249        if (request == null) {
250            return null;
251        }
252        String count = request.getParameter("ProxyCount");
253        if(count == null) {
254            return null;
255        }
256        int proxyCount = -1;
257        try {
258            proxyCount = Integer.parseInt(count);
259        } catch (NumberFormatException ne) {
260            FSUtils.debug.error("FSScoping.parseURLEncodedRequest:" +
261                    "proxyCount can not be parsed.");
262            return null;
263        }
264        
265        FSScoping scoping = new FSScoping();
266        scoping.setProxyCount(proxyCount);
267        
268        String[] idps = request.getParameterValues("IDPEntries");
269        if (idps == null || idps.length == 0) {
270            return scoping;
271        }
272        
273        List list = new ArrayList();
274        for (int i=0; i < idps.length; i++) {
275            String providerID = idps[i];
276            IDPEntry entry = new IDPEntry(providerID, null, null);
277            list.add(entry);
278        }
279        IDPEntries entries = new IDPEntries(list);
280        FSIDPList idpsList = new FSIDPList(entries, null);
281        scoping.setIDPList(idpsList);
282        
283        return scoping;
284    }
285}