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: PAOSHeader.java,v 1.4 2008/06/25 05:47:20 qcheng Exp $
026 *
027 */
028
029
030package com.sun.identity.liberty.ws.paos; 
031
032import java.util.ArrayList;
033import java.util.HashMap;
034import java.util.HashSet;
035import java.util.Iterator;
036import java.util.StringTokenizer;
037
038import javax.servlet.http.HttpServletRequest;
039
040/**
041 * The <code>PAOSHeader</code> class is used by a web application
042 * on HTTP server side to parse a <code>PAOS</code> header in an HTTP request
043 * from the user agent side. This header is used by the User Agent
044 * as a <code>PAOS</code> server to publish which services are available, which
045 * <code>PAOS</code> versions are supported, etc..
046 *
047 * An example <code>PAOS</code> header looks like the following:
048 * <pre>
049 * PAOS: ver="ver1","ver2",ext="ext1","ext2";"service1","opt11",
050 *           "opt12";"service2","opt21","opt22"
051 * </pre>
052 *
053 * This class has methods for obtaining all the parts inside such
054 * a header.
055 *
056 * @supported.all.api
057 */
058public class PAOSHeader {
059
060    private String paosHeaderStr = null;
061
062    private ArrayList versionList = new ArrayList();
063    private ArrayList extensionList = new ArrayList();
064    
065    private static final String PAOS_HEADER = "PAOS";
066
067    // keys are strings and value are sets (set elements are
068    // Strings)
069    private HashMap servicesAndOptions = new HashMap();
070
071    /**
072     * This constructor accepts an <code>HttpServletRequest</code>
073     * and tries to parse the <code>PAOS</code> header string if there is one
074     * inside.
075     *
076     * @param req the incoming HTTP request which is supposed
077     *            to contain the <code>PAOS</code> header.
078     * @throws PAOSException if there are any parsing errors because
079     *            the <code>PAOS</code> header is not there at all or
080     *            because its content is not compliant to the
081     *            <code>PAOS</code> specifications.
082     */
083    public PAOSHeader(HttpServletRequest req) throws PAOSException {
084        paosHeaderStr = req.getHeader(PAOS_HEADER);
085        if (PAOSUtils.debug.messageEnabled()) {
086            PAOSUtils.debug.message("PAOSHeader.PAOSHeader: PAOS Header = " +
087                paosHeaderStr);
088        }
089        if (paosHeaderStr != null) {
090            paosHeaderStr = paosHeaderStr.trim();
091        } else {
092            PAOSUtils.debug.error(
093                    "PAOSHeader:PAOSHeader: No POAS header.");
094            throw new PAOSException(
095                    "There is no PAOS header.");
096        }
097        parse();
098    }
099    
100    /**
101     * This constructor accepts a <code>PAOS</code> header string and tries to
102     * parse it. 
103     *
104     * @param paosHeaderString the <code>PAOS</code> header string which
105     *        supposedly contains information on available services, etc..
106     * @throws PAOSException if there are any parsing error because the
107     *            <code>PAOS</code> header is invalid.
108     */
109    public PAOSHeader(String paosHeaderString) throws PAOSException {
110        if (paosHeaderStr != null) {
111            paosHeaderStr = paosHeaderStr.trim();
112        } else {
113            PAOSUtils.debug.error(
114                    "PAOSHeader:PAOSHeader: No POAS header.");
115            throw new PAOSException(
116                    "There is no PAOS header.");
117        }
118        parse();
119    }
120    
121    /**
122     * Parses the <code>PAOS</code> Header.
123     */
124    private void parse() throws PAOSException {
125        
126        if (paosHeaderStr.length() == 0) {
127            PAOSUtils.debug.error(
128                "PAOSHeader:PAOSHeader: Null POAS header.");
129            throw new PAOSException(
130                "PAOS header value is empty"); 
131        }
132        
133        StringTokenizer st1 = new 
134            StringTokenizer(paosHeaderStr, ";");
135        
136        int n = st1.countTokens();
137        
138        String versExts = st1.nextToken().trim();
139        
140        int indexOfExt = versExts.indexOf("ext=");
141        
142        String vers = null;
143        
144        if (indexOfExt < 0) {
145            vers = versExts;
146        } else {
147            vers = versExts.substring(0, indexOfExt).trim();
148        }
149        String versions = null;
150        
151        if (vers.startsWith("ver=")) {
152            versions = vers.substring(4).trim();
153        } else {
154            versions = vers;
155        }
156
157        StringTokenizer st3 = new StringTokenizer(versions, ",");
158        
159        while (st3.hasMoreTokens()) {
160            versionList.add(trimQuotes(st3.nextToken().trim()));
161        }
162        
163        if (indexOfExt >= 0) {
164            
165            String extensions = versExts.substring(indexOfExt+4).trim();
166            
167            StringTokenizer st4 = new StringTokenizer(extensions, ",");
168            while (st4.hasMoreTokens()) {
169                extensionList.add(trimQuotes(st4.nextToken().trim()));
170            }
171        }
172        String servAndOpt = null;
173        StringTokenizer st5 = null;
174        String serv = null;
175        HashSet optSet = null;
176        while (st1.hasMoreTokens()) {
177            
178            servAndOpt = st1.nextToken();
179            
180            st5 = new StringTokenizer(servAndOpt, ",");
181            
182            if (st5.hasMoreTokens()) {
183                serv = trimQuotes(st5.nextToken().trim());
184            }
185            if (st5.hasMoreTokens()) {
186                optSet = new HashSet();
187                while (st5.hasMoreTokens()) {
188                    optSet.add(trimQuotes(st5.nextToken().trim()));
189                }
190            }
191            servicesAndOptions.put(serv, optSet);
192            optSet = null;
193        }
194    }
195    
196    private String trimQuotes(String inStr) {
197        
198        if ((inStr.startsWith("\"") && inStr.endsWith("\"")) ||
199            (inStr.startsWith("'") && inStr.endsWith("'"))) {
200            return inStr.substring(1, inStr.length()-1);
201        }
202        return inStr;
203    }
204    
205    /**
206     * Returns the list of versions as <code>String</code>s.
207     *
208     * @return the list of versions as <code>String</code>s.
209     */
210    public Iterator getVersions() {
211        return versionList.iterator();
212    }
213    
214    /**
215     * Returns the list of extensions as <code>String</code>s.
216     *
217     * @return the list of extensions as <code>String</code>s.
218     */
219    public Iterator getExtensions() {
220        return extensionList.iterator();
221    }
222
223    /**
224     * Returns a <code>HashMap</code> containing the services and
225     * corresponding options.
226     *
227     * @return a <code>HashMap</code> with each key being a service represented
228     *         as a <code>String</code>, and with each value being a
229     *         <code>Set</code> of the corresponding options represented
230     *         as <code>String</code>s
231     */
232     public HashMap getServicesAndOptions() { 
233        return servicesAndOptions;
234    }
235}




























































Copyright © 2010-2017, ForgeRock All Rights Reserved.