//
// (C) Copyright 2007 VeriSign, Inc. All Rights Reserved.
//
// VeriSign, Inc. shall have no responsibility, financial or
// otherwise, for any consequences arising out of the use of
// this material. The program material is provided on an "AS IS"
// BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
// express or implied.
//
// Distributed under an Apache License
// http://www.apache.org/licenses/LICENSE-2.0
//
package org.verisign.joid.extension;
import org.verisign.joid.OpenIdException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TimeZone;
/**
* Base class for OpenID extension information classes, with utility
* functions for getting and setting different parameter types.
*/
public class Extension {
/**
* RFC3339 date format
*/
private static String DATE_FORMAT = "yyyy-MM-dd'T'HH:mm:ss'Z'";
/**
* Namespace for this extension (OpenID 2.0)
*/
protected String ns;
/**
* Preferred alias prefix for the extension parameters.
*/
protected String prefix;
/**
* The list of parameters, in a <code>Map<String, String></code> object.
*/
protected Map params;
/**
* Create an extension object with the namespace and prefix. This
* constructor is intended to be used to construct extension
* objects "from scratch" without parsing an existing message
* object.
*
* @param ns the extension namespace as a <code>String</code> value
* @param prefix the extension's prefix alias as a <code>String</code> value
*/
public Extension (String ns, String prefix) {
this.ns = ns;
this.prefix = prefix;
params = null;
}
/**
* Create an extension object with the namespace and prefix. This
* constructor is intended to be used to construct extension
* objects from parsing an existing message object.
*
* @param ns the extension namespace as a <code>String</code> value
* @param extensionMap extension parameters in <code>Map<String, String></code> form
*/
public Extension (String ns, Map extensionMap) {
this.ns = ns;
getParams(extensionMap);
}
/**
* Extract parameters for the extension from the given OpenID
* parameter map based on the extension's namespace.
*
* @param extensionMap extension parameters in <code>Map<String, String></code> form
*/
public void getParams (Map extensionMap) {
params = null;
String prefix = getPrefix(extensionMap);
if (prefix == null) {
return;
}
this.prefix = prefix;
params = new HashMap();
Iterator it = extensionMap.entrySet().iterator();
while (it.hasNext()) {
Map.Entry mapEntry = (Map.Entry)it.next();
String key = (String)mapEntry.getKey();
String value = (String) mapEntry.getValue();
if (key.startsWith(prefix)) {
params.put(key.substring(prefix.length() + 1), value);
}
}
if (params.isEmpty()) {
params = null;
}
}
/**
* Return whether the extension object has any parameters assigned
* to it.
*
* @return <code>true</code> if a parameter map exists
*/
public boolean isValid () {
return params != null;
}
/**
* Returns whether there are any valid extension parameters in the
* given parameter map.
*
* @param extensionMap extension parameters in <code>Map<String, String></code> form
* @return <code>true</code> if there are parameters for this extension in the map
*/
public boolean isValid (Map extensionMap) {
return getPrefix(extensionMap) != null;
}
/**
* Extract the extension's alias from the map.
*
* @param extensionMap a <code>Map</code> value
* @return alias <code>String</code>
*/
public String getPrefix (Map extensionMap) {
Iterator it = extensionMap.entrySet().iterator();
while (it.hasNext()) {
Map.Entry mapEntry = (Map.Entry)it.next();
String key = (String)mapEntry.getKey();
String value = (String) mapEntry.getValue();
if (key.startsWith("ns.") &&
value.equals(ns)) {
return key.substring(3);
}
}
return null;
}
/**
* Remove extension parameter.
*
* @param name Parameter name
*/
public void clearParam (String name) {
if (params != null) {
params.remove(name);
}
}
/**
* Get <code>String</code> extension parameter value.
*
* @param name Parameter name
* @return value <code>String</code>
*/
public String getParam (String name) {
return (String)params.get(name);
}
/**
* Set extension parameter's <code>String</code> value.
*
* @param name Parameter name
* @param value value <code>String</code>
*/
public void setParam (String name, String value) {
if (params == null) {
params = new HashMap();
}
params.put(name, value);
}
/**
* Get <code>Integer</code> extension parameter value.
*
* @param name Parameter name
* @return value <code>Integer</code>
* @exception OpenIdException if the parameter was not a valid Integer
*/
public Integer getIntParam (String name) throws OpenIdException {
try {
String paramStr = getParam(name);
if (paramStr != null) {
return new Integer(paramStr);
}
return null;
}
catch (NumberFormatException e) {
// invalid parameter value, throw a protocol error
throw new OpenIdException("Invalid " + name + " parameter", e);
}
}
/**
* Set extension parameter's <code>Integer</code> value.
*
* @param name Parameter name
* @param value value <code>Integer</code>
*/
public void setIntParam (String name, Integer value) {
setParam(name, value == null ? null : value.toString());
}
/**
* Get <code>Date</code> extension parameter value.
*
* @param name Parameter name
* @return value <code>Date</code>
* @exception OpenIdException if the parameter was not a valid Date
*/
public Date getDateParam (String name) throws OpenIdException {
SimpleDateFormat dateFormat = new SimpleDateFormat(DATE_FORMAT);
dateFormat.setTimeZone(TimeZone.getTimeZone("GMT"));
try {
String paramStr = getParam(name);
if (paramStr != null) {
return dateFormat.parse(paramStr.toUpperCase());
}
return null;
}
catch (ParseException e) {
// invalid parameter value, throw a protocol error
throw new OpenIdException("Invalid " + name + " parameter", e);
}
}
/**
* Set extension parameter's <code>Date</code> value.
*
* @param name Parameter name
* @param value value <code>Date</code>
*/
public void setDateParam (String name, Date value) {
SimpleDateFormat dateFormat = new SimpleDateFormat(DATE_FORMAT);
dateFormat.setTimeZone(TimeZone.getTimeZone("GMT"));
setParam(name, dateFormat.format(value));
}
/**
* Get extension parameter's <code>List</code> value.
*
* @param name Parameter name
* @param separator Separation <code>String</code> between list values
* @return value <code>List</code> of <code>String</code>s
*/
public List getListParam (String name, String separator) {
List paramList = new ArrayList();
String paramStr = getParam(name);
if (paramStr != null) {
String[] paramArray = paramStr.split(separator);
for (int i = 0; i < paramArray.length; i++) {
paramList.add(paramArray[i]);
}
}
return paramList;
}
/**
* Get extension parameter's <code>Set</code> value.
*
* @param name Parameter name
* @param separator Separation <code>String</code> between set values
* @return value <code>Set</code> of <code>String</code>s
*/
public Set getSetParam (String name, String separator) {
return new LinkedHashSet(getListParam(name, separator));
}
/**
* Set an extension parameter with multiple values.
*
* @param name Parameter name
* @param paramList a <code>Collection</code> of <code>String</code> values
* @param separator Separation <code>String</code> between list values
*/
public void setListParam (String name, Collection paramList, String separator) {
StringBuffer paramStr = new StringBuffer("");
Iterator it = paramList.iterator();
while (it.hasNext()) {
String param = (String)it.next();
paramStr.append(param);
if (it.hasNext()) {
paramStr.append(separator);
}
}
setParam(name, paramStr.toString());
}
/**
* Returns a map containing all the extension parameter name value
* pairs. All parameter names are prefixed by the specified
* namespace alias. In addition, the namespace alias is defined in a
* name value pair of the form:
* <code>ns.<namespace alias>=<namespace URI></code>
*
* @param nsSuffix the namespace alias for this extension
* @return a <code>Map<String, String></code> containing all extension parameters
*/
public Map getParamMap (String nsSuffix) {
if ((nsSuffix == null) || (nsSuffix.length() == 0)) {
throw new IllegalArgumentException("Missing namespace alias for " + ns);
}
Map map = new HashMap();
// add all non empty params with the openid.ns prefix
Iterator it = params.entrySet().iterator();
while (it.hasNext()) {
Map.Entry mapEntry = (Map.Entry)it.next();
String key = (String)mapEntry.getKey();
String value = (String)mapEntry.getValue();
if (value != null) {
map.put(nsSuffix + "." + key, value);
}
}
map.put("ns." + nsSuffix, ns);
return map;
}
/**
* Returns a map containing all the extension parameters with the
* namespace alias set to the current value.
*
* @return a <code>Map<String, String></code> containing all extension parameters
* @see #getParamMap(String)
*/
public Map getParamMap () {
return getParamMap(prefix);
}
/**
* Returns a simple string representation of the object.
*
* @return a <code>String</code> containing the extension properties
*/
public String toString () {
StringBuffer sb = new StringBuffer("");
sb.append("[Extension ").append(ns).append(", ");
sb.append("prefix=").append(prefix).append(", ");
if (params == null) {
sb.append("No extension params");
}
else {
Iterator it = params.keySet().iterator();
while (it.hasNext()) {
String key = (String)it.next();
sb.append(key).append("='").append((String)params.get(key)).append("'");
if (it.hasNext()) {
sb.append(", ");
}
}
}
sb.append("]");
return sb.toString();
}
}