org.openid4java.message.ax.FetchRequest Maven / Gradle / Ivy
/*
* Copyright 2006-2008 Sxip Identity Corporation
*/
package org.openid4java.message.ax;
import org.openid4java.message.MessageException;
import org.openid4java.message.Parameter;
import org.openid4java.message.ParameterList;
import java.net.URL;
import java.net.MalformedURLException;
import java.util.Map;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedHashMap;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
/**
* Implements the extension for Attribute Exchange fetch requests.
*
* @see AxMessage Message
* @author Marius Scurtescu, Johnny Bufu
*/
public class FetchRequest extends AxMessage
{
private static Log _log = LogFactory.getLog(FetchRequest.class);
private static final boolean DEBUG = _log.isDebugEnabled();
private int _aliasCounter = 0;
/**
* Constructs a Fetch Request with an empty parameter list.
*/
protected FetchRequest()
{
_parameters.set(new Parameter("mode", "fetch_request"));
if (DEBUG) _log.debug("Created empty fetch request.");
}
/**
* Constructs a Fetch Request with an empty parameter list.
*/
public static FetchRequest createFetchRequest()
{
return new FetchRequest();
}
/**
* Constructs a FetchRequest from a parameter list.
*
* The parameter list can be extracted from a received message with the
* getExtensionParams method of the Message class, and MUST NOT contain
* the "openid.." prefix.
*/
protected FetchRequest(ParameterList params)
{
_parameters = params;
}
/**
* Constructs a FetchRequest from a parameter list.
*
* The parameter list can be extracted from a received message with the
* getExtensionParams method of the Message class, and MUST NOT contain
* the "openid.." prefix.
*/
public static FetchRequest createFetchRequest(ParameterList params)
throws MessageException
{
FetchRequest req = new FetchRequest(params);
if (! req.isValid())
throw new MessageException("Invalid parameters for a fetch request");
if (DEBUG)
_log.debug("Created fetch request from parameter list:\n" + params);
return req;
}
/**
* Adds an attribute to the fetch request.
*
* @param alias The attribute alias that will be associated
* with the attribute type URI
* @param typeUri The attribute type URI
* @param required If true, marks the attribute as 'required';
* 'if_available' otherwise.
* @param count The number of attribute values requested.
* 0 for the special value "unlimited".
*/
public void addAttribute(String alias, String typeUri,
boolean required, int count)
throws MessageException
{
if ( alias.indexOf(',') > -1 || alias.indexOf('.') > -1 ||
alias.indexOf(':') > -1 || alias.indexOf('\n') > -1 )
throw new MessageException(
"Characters [.,:\\n] are not allowed in attribute aliases: " + alias);
_parameters.set(new Parameter("type." + alias, typeUri));
String level = required ? "required" : "if_available";
Parameter levelParam = _parameters.getParameter(level);
Parameter newParam;
if (levelParam == null)
{
newParam = new Parameter(level, alias);
}
else
{
newParam = new Parameter(level,
levelParam.getValue() + "," + alias);
_parameters.removeParameters(level);
}
_parameters.set(newParam);
setCount(alias, count);
if (DEBUG) _log.debug("Added new attribute to fetch request; type: "
+ typeUri + " alias: " + alias + " count: "
+ count + " required: " + required);
}
/**
* Adds an attribute to the fetch request, with a default value-count of 1.
*
* @see #addAttribute(String, String, boolean, int)
*/
public void addAttribute(String alias, String typeUri, boolean required)
throws MessageException
{
addAttribute(alias, typeUri, required, 1);
}
/**
* Adds an attribute to the fetch request, with a default value-count of 1.
* An alias is generated for the provided type URI.
*
* @see #addAttribute(String, String, boolean, int)
*/
public String addAttribute(String typeUri, boolean required)
throws MessageException
{
String alias = generateAlias();
addAttribute(alias, typeUri, required, 1);
return alias;
}
/**
* Sets the desired number of attribute vaules requested for the specified
* attribute alias. Special value 0 means "unlimited".
*
* @param alias The attribute alias.
*/
public void setCount(String alias, int count)
{
if (count == 0)
_parameters.set(new Parameter("count." + alias, "unlimited"));
else if (count > 1)
_parameters.set(
new Parameter("count." + alias, Integer.toString(count)));
}
/**
* Returns the number of values requested for the specified attribute alias.
* 1 (the default number) is returned if the count parameter is absent.
* 0 is returned if the special value "unlimited" was requested.
*
* @param alias The attribute alias.
*/
public int getCount(String alias)
{
if ("unlimited".equals(_parameters.getParameterValue("count." + alias)))
return 0;
else if (_parameters.hasParameter("count." + alias))
return Integer.parseInt(_parameters.getParameterValue("count." + alias));
else
return 1;
}
/**
* Sets the optional 'update_url' parameter where the OP can later re-post
* fetch-response updates to the values of the requested attributes.
*
* @param updateUrl The URL where the RP accepts later updates
* to the requested attributes.
*/
public void setUpdateUrl(String updateUrl) throws MessageException
{
try
{
new URL(updateUrl);
} catch (MalformedURLException e)
{
throw new MessageException("Invalid update_url: " + updateUrl);
}
if (DEBUG) _log.debug("Setting fetch request update_url: " + updateUrl);
_parameters.set(new Parameter("update_url", updateUrl));
}
/**
* Gets the optional 'update_url' parameter if available, or null otherwise.
*/
public String getUpdateUrl()
{
return _parameters.hasParameter("update_url") ?
_parameters.getParameterValue("update_url") : null;
}
/**
* Returns a map with the requested attributes.
*
* @param required If set to true the list of 'required' attributes
* is returned, otherwise the list of 'if_available'
* attributes.
* @return Map of attribute aliases -> attribute type URIs.
*/
public Map getAttributes(boolean required)
{
HashMap attributes = new LinkedHashMap();
String level = required ? "required" : "if_available";
Parameter param = _parameters.getParameter(level);
if (param != null)
{
String[] values = param.getValue().split(",");
for (int i = 0; i < values.length; i++)
{
String alias = values[i];
attributes.put(alias,
_parameters.getParameterValue("type." + alias));
}
}
return attributes;
}
/**
* Gets all requested attributes (required and optional).
*
* @return Map of attribute aliases -> attribute type URIs.
*/
public Map getAttributes()
{
Map attributes = getAttributes(true);
attributes.putAll(getAttributes(false));
return attributes;
}
/**
* Checks the validity of the extension.
*
* Used when constructing a extension from a parameter list.
*
* @return True if the extension is valid, false otherwise.
*/
public boolean isValid()
{
if ( ! _parameters.hasParameter("required") &&
! _parameters.hasParameter("if_available") )
{
_log.warn("One of 'required' or 'if_available' parameters must be present.");
return false;
}
if ( ! _parameters.hasParameter("mode") ||
! "fetch_request".equals(_parameters.getParameterValue("mode")))
{
_log.warn("Invalid mode value in fetch_request: "
+ _parameters.getParameterValue("mode"));
return false;
}
if (_parameters.hasParameter("required"))
{
String[] aliases = _parameters.getParameterValue("required").split(",");
for (int i = 0; i < aliases.length; i++)
{
String alias = aliases[i];
if ( ! _parameters.hasParameter("type." + alias) )
{
_log.warn("Type missing for attribute alias: " + alias);
return false;
}
if (! checkCount(alias)) return false;
}
}
if ( _parameters.hasParameter("if_available"))
{
String[] aliases = _parameters.getParameterValue("if_available").split(",");
for (int i = 0; i < aliases.length; i++)
{
String alias = aliases[i];
if ( ! _parameters.hasParameter("type." + alias) )
{
_log.warn("Type missing for attribute alias: " + alias);
return false;
}
if (! checkCount(alias)) return false;
}
}
Iterator it = _parameters.getParameters().iterator();
while (it.hasNext())
{
String paramName = ((Parameter) it.next()).getKey();
if (! paramName.equals("mode") &&
! paramName.startsWith("type.") &&
! paramName.startsWith("count.") &&
! paramName.equals("required") &&
! paramName.equals("if_available") &&
! paramName.equals("update_url"))
{
_log.warn("Invalid parameter name in fetch request: " + paramName);
//return false;
}
}
return true;
}
private boolean checkCount(String alias)
{
int count = getCount(alias);
if ( count < 0 ||
( count == 0 &&
! "unlimited".equals(_parameters.getParameterValue("count." + alias))) )
{
_log.warn("Invalid value for count." + alias + ": " +
_parameters.getParameterValue("count." + alias));
return false;
}
return true;
}
private synchronized String generateAlias()
{
return "attr" + Integer.toString(++ _aliasCounter);
}
}