/*
* IdentityFilter.java
*
* Created on September 7, 2007, 3:44 PM
*
* To change this template, choose Tools | Template Manager
* and open the template in the editor.
*/
package org.atomojo.www.util;
import java.util.Map;
import java.util.TreeMap;
import java.util.logging.Level;
import org.infoset.xml.Name;
import org.restlet.Context;
import org.restlet.Request;
import org.restlet.Response;
import org.restlet.Restlet;
import org.restlet.data.Cookie;
import org.restlet.data.Reference;
import org.restlet.routing.Filter;
/**
*
* @author alex
*/
public class IdentityFilter extends Filter
{
static int MAX_CACHE = 1000;
static long MAX_AGE = 5*60*1000;
TreeMap<String,Long> createdTimes;
TreeMap<String,Identity> identities;
public static Name NAME = Name.create("{http://www.atomojo.org/Vocabulary/Auth/2007/1/0}name");
public static Name EMAIL = Name.create("{http://www.atomojo.org/Vocabulary/Auth/2007/1/0}email");
public static Name GROUP = Name.create("{http://www.atomojo.org/Vocabulary/Auth/2007/1/0}group");
public static Name ROLE = Name.create("{http://www.atomojo.org/Vocabulary/Auth/2007/1/0}role");
static Reference getReferenceAttribute(Request request,String name,Reference defaultValue)
{
Object o = request.getAttributes().get(name);
return o==null ? defaultValue : (Reference)o;
}
boolean lookup;
long maxAge;
int maxCache;
String cookieName;
Reference confService;
/** Creates a new instance of IdentityFilter */
public IdentityFilter(Context context)
{
this(context,null,null);
}
public IdentityFilter(Context context,Restlet next,Reference service)
{
super(context,next);
this.confService = service;
lookup = "true".equals(context.getParameters().getFirstValue("identity.lookup"));
createdTimes = new TreeMap<String,Long>();
identities = new TreeMap<String,Identity>();
String maxAgeS = context.getParameters().getFirstValue("identity.max.age");
maxAge = maxAgeS==null ? MAX_AGE : Long.parseLong(maxAgeS)*1000;
String maxCacheS = context.getParameters().getFirstValue("identity.max.cache");
maxCache = maxCacheS==null ? MAX_CACHE : Integer.parseInt(maxCacheS);
cookieName = context.getParameters().getFirstValue("identity.cookie");
if (cookieName==null) {
cookieName = "I";
}
getLogger().info("identity.max.age="+(maxAge/1000)+"s, identity.max.cache="+maxCache+", identity.lookup="+lookup);
IdentityManager manager = (IdentityManager)context.getAttributes().get(IdentityManager.ATTR);
if (manager==null) {
manager = new IdentityManager() {
public void add(String id,Identity identity) {
IdentityFilter.this.addIdentity(id, identity);
}
public boolean remove(String id) {
return IdentityFilter.this.removeIdentity(id);
}
};
context.getAttributes().put(IdentityManager.ATTR, manager);
}
getLogger().info("Identity Manager: "+manager);
}
public boolean removeIdentity(String id) {
createdTimes.remove(id);
return identities.remove(id)!=null;
}
public void addIdentity(String id,Identity identity)
{
identities.put(id,identity);
createdTimes.put(id,new Long(System.currentTimeMillis()));
}
protected int beforeHandle(Request request,Response response)
{
Reference service = getReferenceAttribute(request,"auth-service",confService);
Cookie cookie = request.getCookies().getFirst(cookieName);
if (cookie!=null) {
getLogger().info("cookie: "+cookieName+"="+cookie.getValue());
Identity identity = identities.get(cookie.getValue());
if (identity!=null) {
getLogger().info("Found "+identity.getAlias()+", checking age...");
// check age
Long created = createdTimes.get(cookie.getValue());
if (created==null) {
getLogger().info("Expiring.");
identities.remove(cookie.getValue());
identity = null;
} else if ((System.currentTimeMillis()-created.longValue())>=maxAge) {
removeIdentity(cookie.getValue());
identity = null;
}
}
if (identity==null) {
// TODO: make this configurable
if (!lookup) {
return Filter.CONTINUE;
}
getLogger().info("Looking up identity "+cookie.getValue());
try {
identity = RealmGuard.checkSession(getContext().createChildContext(),service, cookie.getValue());
} catch (RequestFailedException ex) {
if (ex.getStatus()!=null) {
getLogger().severe("Cannot check session against service, status="+ex.getStatus().getCode());
} else {
getLogger().log(Level.SEVERE,"Cannot authenticate against service.",ex);
}
}
if (identity!=null) {
addIdentity(cookie.getValue(),identity);
}
}
if (identity!=null) {
addIdentity(request,identity);
}
} else {
getLogger().fine("No I cookie.");
}
return Filter.CONTINUE;
}
public static void addIdentity(Request request,Identity identity) {
Map<String,Object> atts = request.getAttributes();
atts.put(Identity.IDENTITY_ATTR,identity);
atts.put(Identity.PARAMETER_IDENTITY_ID, identity.getId());
if (identity.getAlias()!=null) {
atts.put(Identity.PARAMETER_IDENTITY_ALIAS, identity.getAlias());
}
if (identity.getName()!=null) {
atts.put(Identity.PARAMETER_IDENTITY_NAME, identity.getName());
}
if (identity.getEmail()!=null) {
atts.put(Identity.PARAMETER_IDENTITY_EMAIL, identity.getEmail());
}
atts.put(Identity.PARAMETER_IDENTITY_SESSION, identity.getSession());
}
}