//
// (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;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import java.util.StringTokenizer;
import org.apache.commons.logging.LogFactory;
import org.apache.commons.logging.Log;
/**
* Simple registration extensions, as defined by
* http://openid.net/specs/openid-simple-registration-extension-1_0.html
*
* <strong>This class should only be used by internal request/response
* processing</strong>.
*
* TODO to make this clearer.
*/
public class SimpleRegistration
{
private final static Log log
= LogFactory.getLog(SimpleRegistration.class);
private Set required;
private Set optional;
private Map supplied;
private String policyUrl;
/** The <code>openid.sreg</code> value */
public final static String OPENID_SREG = "openid.sreg";
/** The <code>openid.ns.sreg</code> value */
public final static String OPENID_SREG_NSDEF = "openid.ns.sreg";
/** The <code>openid.sreg.required</code> value */
public final static String OPENID_SREG_REQUIRED
= OPENID_SREG + ".required";
/** The <code>openid.sreg.optional</code> value */
public final static String OPENID_SREG_OPTIONAL
= OPENID_SREG + ".optional";
/** The <code>openid.sreg.policy_url</code> value */
public final static String OPENID_SREG_POLICY_URL
= OPENID_SREG + ".policy_url";
/** Invalid namespace for sreg (from XRDS) seen in the wild */
public final static String OPENID_SREG_NAMESPACE_10 = "http://openid.net/sreg/1.0";
/** Standard namespace value for sreg */
public final static String OPENID_SREG_NAMESPACE_11 = "http://openid.net/extensions/sreg/1.1";
private final static String SREG_NICKNAME = "nickname";
private final static String SREG_EMAIL = "email";
private final static String SREG_FULLNAME = "fullname";
private final static String SREG_DOB = "dob";
private final static String SREG_GENDER = "gender";
private final static String SREG_POSTCODE = "postcode";
private final static String SREG_COUNTRY = "country";
private final static String SREG_LANGUAGE = "language";
private final static String SREG_TIMEZONE = "timezone";
private String namespace;
private String nickName;
private String email;
private String fullName;
private String dob;
private String gender;
private String postCode;
private String country;
private String language;
private String timeZone;
/**
* The set of the nine allowed SREG values.
*/
public final static Set allowed = new HashSet();
static {
allowed.add(SREG_NICKNAME);
allowed.add(SREG_EMAIL);
allowed.add(SREG_FULLNAME);
allowed.add(SREG_DOB);
allowed.add(SREG_GENDER);
allowed.add(SREG_POSTCODE);
allowed.add(SREG_COUNTRY);
allowed.add(SREG_LANGUAGE);
allowed.add(SREG_TIMEZONE);
}
/**
* Creates a simple registration. TODO: public for unit tests only.
*/
public SimpleRegistration(Set required, Set optional, Map supplied,
String policyUrl)
{
this.required = required;
this.optional = optional;
this.supplied = supplied;
this.policyUrl = policyUrl;
this.namespace = OPENID_SREG_NAMESPACE_11;
}
/**
* Creates a simple registration. TODO: public for unit tests only.
*/
public SimpleRegistration(Set required, Set optional, Map supplied,
String policyUrl, String namespace)
{
this.required = required;
this.optional = optional;
this.supplied = supplied;
this.policyUrl = policyUrl;
this.namespace = namespace;
}
SimpleRegistration(Map map) throws OpenIdException
{
required = new HashSet();
optional = new HashSet();
supplied = new HashMap();
namespace = OPENID_SREG_NAMESPACE_11;
Set set = map.entrySet();
for (Iterator iter = set.iterator(); iter.hasNext();){
Map.Entry mapEntry = (Map.Entry) iter.next();
String key = (String) mapEntry.getKey();
String value = (String) mapEntry.getValue();
if (OPENID_SREG_REQUIRED.equals(key)){
addToSetFromList(required, value);
} else if (OPENID_SREG_OPTIONAL.equals(key)){
addToSetFromList(optional, value);
} else if (OPENID_SREG_POLICY_URL.equals(key)){
policyUrl = value;
} else if (OPENID_SREG_NSDEF.equals(key)){
if (OPENID_SREG_NAMESPACE_10.equals(value)
|| OPENID_SREG_NAMESPACE_11.equals(value)) {
namespace = value;
}
}
}
}
public boolean isRequested()
{
return (!(required.isEmpty() && optional.isEmpty()));
}
/**
* Expects a map with values like "openid.sreg.nickname=blahblah" in it
*/
public static SimpleRegistration parseFromResponse(Map map)
{
Set req = new HashSet();
Set opt = new HashSet();
Map sup = new HashMap();
String ns = OPENID_SREG_NAMESPACE_11;
String trigger = OPENID_SREG + ".";
int triggerLength = trigger.length();
Set set = map.entrySet();
for (Iterator iter = set.iterator(); iter.hasNext();){
Map.Entry mapEntry = (Map.Entry) iter.next();
String key = (String) mapEntry.getKey();
String value = (String) mapEntry.getValue();
if (key.startsWith(trigger)){
sup.put(key.substring(triggerLength), value);
} else if (OPENID_SREG_NSDEF.equals(key)){
if (OPENID_SREG_NAMESPACE_10.equals(value)
|| OPENID_SREG_NAMESPACE_11.equals(value)) {
ns = value;
}
}
}
return new SimpleRegistration(req, opt, sup, "", ns);
}
private void addToSetFromList(Set set, String value)
{
StringTokenizer st = new StringTokenizer(value, ",");
while (st.hasMoreTokens()) {
String token = st.nextToken().trim();
if (allowed.contains(token)){
set.add(token);
} else {
log.info("Illegal sreg value: "+token);
}
}
}
public String getPolicyUrl(){return policyUrl;}
public Set getRequired(){return required;} // clone?
public Set getOptional(){return optional;} // clone?
public void setRequired(Set set){required = set;}
public void setOptional(Set set){optional = set;}
public String getNamespace () { return namespace; }
//public Map getSuppliedValues(){return supplied;}
public Map getSuppliedValues()
{
Map map = new HashMap();
addAllNonEmpty(supplied, map);
return map;
}
private void addAllNonEmpty(Map from, Map to)
{
Set set = from.entrySet();
for (Iterator iter = set.iterator(); iter.hasNext();){
Map.Entry mapEntry = (Map.Entry) iter.next();
String key = (String) mapEntry.getKey();
String value = (String) mapEntry.getValue();
if (value != null){
to.put(key, value);
}
}
}
public String toString()
{
return "[SimpleRegistration required="+required
+", optional="+optional+", supplied="+supplied
+", policy url="+policyUrl
+", namespace="+namespace+"]";
}
}