view src/de/mpiwg/itgroup/annotationManager/restlet/RestServer.java @ 15:6c7c4140630d

on the way to updating annotations.
author casties
date Wed, 21 Mar 2012 18:12:45 +0100
parents 9393c9c9b916
children 0cd1e7608d25
line wrap: on
line source

package de.mpiwg.itgroup.annotationManager.restlet;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.Hashtable;
import java.util.Properties;

import javax.naming.NamingEnumeration;
import javax.naming.NamingException;
import javax.naming.directory.Attribute;
import javax.naming.directory.DirContext;
import javax.naming.directory.InitialDirContext;
import javax.naming.directory.SearchControls;
import javax.naming.directory.SearchResult;
import javax.security.auth.Subject;
import javax.security.auth.login.Configuration;
import javax.security.auth.login.LoginContext;
import javax.security.auth.login.LoginException;
import javax.servlet.ServletContext;

import org.apache.log4j.BasicConfigurator;
import org.apache.log4j.Level;
import org.apache.log4j.Logger;
import org.restlet.Application;
import org.restlet.Context;
import org.restlet.Request;
import org.restlet.Response;
import org.restlet.Restlet;
import org.restlet.data.ChallengeScheme;
import org.restlet.data.ClientInfo;
import org.restlet.ext.jaas.JaasVerifier;
import org.restlet.routing.Router;
import org.restlet.security.ChallengeAuthenticator;
import org.restlet.security.User;

import com.sun.security.auth.login.ConfigFile;

public class RestServer extends Application {

    private ChallengeAuthenticator authenticator;

    /**
     * Properties holding consumer keys and secrets
     */
    private Properties consumerKeys;
    public final String CONSUMER_KEYS_PATH = "WEB-INF/consumerkeys.property";

    /**
     * constructor
     * 
     * @param parentContext
     */
    public RestServer(Context parentContext) {
        super(parentContext);

        Logger rl = Logger.getRootLogger();
        BasicConfigurator.configure();
        rl.setLevel(Level.DEBUG);
        // read consumerKeys from webapp
        consumerKeys = new Properties();
        ServletContext sc = (ServletContext) getContext().getServerDispatcher()
                .getContext().getAttributes()
                .get("org.restlet.ext.servlet.ServletContext");
        if (sc != null) {
            InputStream ps = sc.getResourceAsStream(CONSUMER_KEYS_PATH);
            if (ps == null) {
                // try as file
                File pf = new File(sc.getRealPath(CONSUMER_KEYS_PATH));
                if (pf != null) {
                    rl.debug("trying file for consumer keys: "+pf);
                    try {
                        ps = new FileInputStream(pf);
                    } catch (FileNotFoundException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                }
            }
            if (ps != null) {
                rl.debug("loading consumer keys from "+CONSUMER_KEYS_PATH);
                try {
                    consumerKeys.load(ps);
                } catch (IOException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
                rl.debug("consumer keys: "+consumerKeys);
            } else {
                rl.error("Unable to get resource "+CONSUMER_KEYS_PATH);
            }
        } else {
            rl.error("Unable to get ServletContext!");
        }
        
    }
    
    /**
     * returns consumer secret for consumer key.
     * returns null if consumer key doesn't exist.
     * @param consumerKey
     * @return
     */
    public String getConsumerSecret(String consumerKey) {
        return consumerKeys.getProperty(consumerKey);
    }

    /**
     * Erzeuge einen Authenticator
     * 
     * @return
     */
    private ChallengeAuthenticator createAuthenticator() {
        Context context = getContext();
        boolean optional = true;
        ChallengeScheme challengeScheme = ChallengeScheme.HTTP_BASIC;
        String realm = "Annotation Service";

        JaasVerifier verifier = new JaasVerifier(
                "BasicJaasAuthenticationApplication");
        // JaasVerifier verifier = new JaasVerifier("DummyAuthentication");

        Configuration jaasConfig;
        jaasConfig = createConfiguration();

        verifier.setConfiguration(jaasConfig);
        verifier.setUserPrincipalClassName("com.sun.security.auth.UserPrincipal");

        ChallengeAuthenticator auth = new ChallengeAuthenticator(context,
                optional, challengeScheme, realm, verifier) {
            @Override
            protected boolean authenticate(Request request, Response response) {
                if (request.getChallengeResponse() == null) {
                    return false;
                } else {
                    return super.authenticate(request, response);
                }
            }
        };

        return auth;
    }

    /**
     * Konfiguration fuer den Authentificator in Jaas. Pfad zum
     * JAAS-Konfigurationsfile liegt im Context-Parameter
     * "de.mpiwg.itgroup.annotationManager.jaas.configFilePath".
     * 
     * @return
     */
    protected Configuration createConfiguration() {
        Configuration jaasConfig;
        URI confUri;

        Context context = getContext();
        String configFilePath = context.getParameters().getFirstValue(
                "de.mpiwg.itgroup.annotationManager.jaas.configFilePath");

        try {
            confUri = new URI(configFilePath);
        } catch (URISyntaxException e) {
            e.printStackTrace();
            confUri = null;
        }

        jaasConfig = new ConfigFile(confUri);
        return jaasConfig;
    }

    /*
     * (non-Javadoc)
     * 
     * @see org.restlet.Application#createInboundRoot()
     */
    public synchronized Restlet createInboundRoot() {
        this.authenticator = createAuthenticator();

        // String target = "{rh}/{rf}/XX";
        // Redirector redirector = new
        // Redirector(getContext().createChildContext(), target,
        // Redirector.MODE_CLIENT_SEE_OTHER);

        Router router = new Router(getContext());

        router.attach("/annotator/annotations", AnnotatorAnnotations.class);
        router.attach("/annotator/annotations/{id}", AnnotatorAnnotations.class);
        router.attach("/annotator/search", AnnotatorSearch.class);
        
        router.attach("/dummy", Dummy.class);

        // router.attach("",redirector);
        router.attach("/annotator", ExtendedAnnotationInput.class);
        router.attach("/", AnnotatorInfo.class);
        authenticator.setNext(router);
        return authenticator;
    }

    /**
     * Authentifiziere den Benutzer aus dem Request (BasicAuthenfication)
     * 
     * @param request
     * @param response
     * @return
     */
    public boolean authenticate(Request request, Response response) {
        if (!request.getClientInfo().isAuthenticated()) {
            authenticator.challenge(response, false);
            return false;
        }

        if (request.getClientInfo().getUser() == null) // FIXME sometimes ist
                                                       // authenticated true,
                                                       // but no user
        {
            authenticator.challenge(response, false);
            return false;
        }
        return true;
    }

    /**
     * Authentifiziere den Benutzer
     * 
     * @param username
     * @param password
     * @param request
     * @return
     */
    public boolean authenticate(String username, String password,
            Request request) {
        LoginContext lc;

        try {
            Configuration conf = createConfiguration();

            lc = new LoginContext("BasicJaasAuthenticationApplication", null,
                    new MyCallBackHandler(username, password), conf);
            // lc = new LoginContext("DummyAuthentication", null, new
            // MyCallBackHandler(username,password),conf);
            lc.login();
        } catch (LoginException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
            return false;
        }

        Subject subject = lc.getSubject();
        ClientInfo clientInfo = new ClientInfo();
        User user = new User(username);
        clientInfo.setAuthenticated(true);
        clientInfo.setUser(user);

        request.setClientInfo(clientInfo);
        return true;
    }

    /**
     * Hole den vollen Benutzernamen aus dem LDAP
     * 
     * @param creator
     * @return
     */
    public String getUserNameFromLdap(String creator) {
        String retString = creator; // falls nichts gefunden wird einfach den
                                    // creator zurueckgeben
        Hashtable<String, String> env = new Hashtable<String, String>();
        String sp = "com.sun.jndi.ldap.LdapCtxFactory";
        env.put(javax.naming.Context.INITIAL_CONTEXT_FACTORY, sp);

        String ldapUrl = "ldap://ldapreplik.mpiwg-berlin.mpg.de/dc=mpiwg-berlin,dc=mpg,dc=de";// TODO
                                                                                              // should
                                                                                              // go
                                                                                              // into
                                                                                              // config
                                                                                              // file
        env.put(javax.naming.Context.PROVIDER_URL, ldapUrl);

        DirContext dctx;
        try {
            dctx = new InitialDirContext(env);
        } catch (NamingException e1) {
            // TODO Auto-generated catch block
            e1.printStackTrace();
            return retString;
        }

        String base = "ou=People";

        SearchControls sc = new SearchControls();
        String[] attributeFilter = { "cn", "mail" };
        sc.setReturningAttributes(attributeFilter);
        sc.setSearchScope(SearchControls.SUBTREE_SCOPE);

        String filter = "(uid=" + creator + ")";

        try {
            NamingEnumeration<SearchResult> results = dctx.search(base, filter,
                    sc);
            while (results.hasMore()) {
                SearchResult sr = (SearchResult) results.next();
                javax.naming.directory.Attributes attrs = sr.getAttributes();

                Attribute attr = attrs.get("cn");
                retString = (String) attr.get();
            }
        } catch (NamingException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

        try {
            dctx.close();
        } catch (NamingException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return retString;
    }

}