dk.itst.oiosaml.sp.service.DispatcherServlet.java Source code

Java tutorial

Introduction

Here is the source code for dk.itst.oiosaml.sp.service.DispatcherServlet.java

Source

/*
 * The contents of this file are subject to the Mozilla Public 
 * License Version 1.1 (the "License"); you may not use this 
 * file except in compliance with the License. You may obtain 
 * a copy of the License at http://www.mozilla.org/MPL/
 * 
 * Software distributed under the License is distributed on an 
 * "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express 
 * or implied. See the License for the specific language governing
 * rights and limitations under the License.
 *
 *
 * The Original Code is OIOSAML Java Service Provider.
 * 
 * The Initial Developer of the Original Code is Trifork A/S. Portions 
 * created by Trifork A/S are Copyright (C) 2008 Danish National IT 
 * and Telecom Agency (http://www.itst.dk). All Rights Reserved.
 * 
 * Contributor(s):
 *   Joakim Recht <jre@trifork.com>
 *   Rolf Njor Jensen <rolf@trifork.com>
 *
 */
package dk.itst.oiosaml.sp.service;

import java.io.IOException;
import java.io.PrintWriter;
import java.util.HashMap;
import java.util.Map;

import javax.servlet.ServletConfig;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.configuration.Configuration;
import org.apache.log4j.Logger;
import org.apache.velocity.VelocityContext;
import org.apache.velocity.app.VelocityEngine;
import org.opensaml.xml.security.credential.Credential;

import dk.itst.oiosaml.configuration.SAMLConfiguration;
import dk.itst.oiosaml.logging.Audit;
import dk.itst.oiosaml.security.CredentialRepository;
import dk.itst.oiosaml.sp.bindings.BindingHandlerFactory;
import dk.itst.oiosaml.sp.bindings.DefaultBindingHandlerFactory;
import dk.itst.oiosaml.sp.configuration.ConfigurationHandler;
import dk.itst.oiosaml.sp.metadata.IdpMetadata;
import dk.itst.oiosaml.sp.metadata.SPMetadata;
import dk.itst.oiosaml.sp.service.session.SessionHandler;
import dk.itst.oiosaml.sp.service.session.SessionHandlerFactory;
import dk.itst.oiosaml.sp.service.util.Constants;
import dk.itst.oiosaml.sp.service.util.Utils;

/**
 * Main servlet for all SAML handling.
 * 
 * This servlet simply dispatches to {@link dk.itst.oiosaml.sp.model.OIOSamlObject}s based on the requested url.
 * 
 * @author Joakim Recht <jre@trifork.com>
 * @author Rolf Njor Jensen <rolf@trifork.com>
 *
 */
public class DispatcherServlet extends HttpServlet {
    private static final Logger log = Logger.getLogger(DispatcherServlet.class);

    private transient IdpMetadata idpMetadata;
    private transient SPMetadata spMetadata;
    private Configuration configuration;
    private Credential credential;

    private Map<String, SAMLHandler> handlers = new HashMap<String, SAMLHandler>();
    private boolean initialized = false;
    private transient VelocityEngine engine;

    private BindingHandlerFactory bindingHandlerFactory;

    private SessionHandlerFactory sessionHandlerFactory;
    private ServletContext servletContext;

    @Override
    public final void init(ServletConfig config) throws ServletException {
        setHandler(new ConfigurationHandler(config.getServletContext()), "configure");

        servletContext = config.getServletContext();
        initServlet();
        engine = new VelocityEngine();
        engine.setProperty(VelocityEngine.RESOURCE_LOADER, "classpath");
        engine.setProperty("classpath.resource.loader.class",
                "org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader");
        try {
            engine.init();
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    private void initServlet() {
        try {
            if (initialized == false) {
                setConfiguration(SAMLConfiguration.getSystemConfiguration());
                Audit.configureLog4j(SAMLConfiguration.getStringPrefixedWithBRSHome(configuration,
                        Constants.PROP_LOG_FILE_NAME));

                handlers.putAll(Utils.getHandlers(configuration, servletContext));
                if (log.isDebugEnabled())
                    log.debug("Found handlers: " + handlers);

                setHandler(new IndexHandler(), "");
                sessionHandlerFactory = SessionHandlerFactory.Factory.newInstance(configuration);
                sessionHandlerFactory.getHandler()
                        .resetReplayProtection(configuration.getInt(Constants.PROP_NUM_TRACKED_ASSERTIONIDS));

                if (configuration.getBoolean(Constants.PROP_DEVEL_MODE, false)) {
                    log.warn("Running in devel mode");
                    return;
                }
                setBindingHandler(new DefaultBindingHandlerFactory());
                setIdPMetadata(IdpMetadata.getInstance());
                setSPMetadata(SPMetadata.getInstance());
                setCredential(new CredentialRepository().getCredential(
                        SAMLConfiguration.getStringPrefixedWithBRSHome(configuration,
                                Constants.PROP_CERTIFICATE_LOCATION),
                        configuration.getString(Constants.PROP_CERTIFICATE_PASSWORD)));

                initialized = true;
            }
        } catch (IllegalStateException e) {
            try {
                handlers.putAll(Utils.getHandlers(SAMLConfiguration.getCommonConfiguration(), servletContext));
            } catch (IOException e1) {
                log.error("Unable to load config", e);
            }
        }
    }

    protected final void doGet(HttpServletRequest req, HttpServletResponse res)
            throws ServletException, IOException {
        initServlet();
        String action = req.getRequestURI().substring(req.getRequestURI().lastIndexOf("/") + 1);
        if (handlers.containsKey(action)) {
            try {
                SAMLHandler handler = handlers.get(action);
                SessionHandler sessionHandler = sessionHandlerFactory != null ? sessionHandlerFactory.getHandler()
                        : null;
                RequestContext context = new RequestContext(req, res, idpMetadata, spMetadata, credential,
                        configuration, sessionHandler, bindingHandlerFactory);
                handler.handleGet(context);
            } catch (Exception e) {
                Audit.logError(action, false, e);
                handleError(req, res, e);
            }
        } else {
            throw new UnsupportedOperationException(action + ", allowed: " + handlers.keySet());
        }
    }

    protected void doPost(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException {
        initServlet();
        String action = req.getRequestURI().substring(req.getRequestURI().lastIndexOf("/") + 1);
        if (handlers.containsKey(action)) {
            try {
                SAMLHandler handler = handlers.get(action);
                SessionHandler sessionHandler = sessionHandlerFactory != null ? sessionHandlerFactory.getHandler()
                        : null;
                RequestContext context = new RequestContext(req, res, idpMetadata, spMetadata, credential,
                        configuration, sessionHandler, bindingHandlerFactory);
                handler.handlePost(context);
            } catch (Exception e) {
                Audit.logError(action, false, e);
                handleError(req, res, e);
            }
        } else {
            throw new UnsupportedOperationException(action);
        }
    }

    public void setInitialized(boolean b) {
        initialized = b;
    }

    public boolean isInitialized() {
        return initialized;
    }

    public final void setCredential(Credential credential) {
        this.credential = credential;
    }

    public final void setConfiguration(Configuration systemConfiguration) {
        this.configuration = systemConfiguration;
    }

    public final void setSPMetadata(SPMetadata metadata) {
        this.spMetadata = metadata;
    }

    public final void setIdPMetadata(IdpMetadata metadata) {
        this.idpMetadata = metadata;
    }

    public void setHandler(SAMLHandler handler, String dispatchPath) {
        handlers.put(dispatchPath, handler);
    }

    public void setBindingHandler(BindingHandlerFactory bindingHandlerFactory) {
        this.bindingHandlerFactory = bindingHandlerFactory;
    }

    public void setSessionHandlerFactory(SessionHandlerFactory sessionHandlerFactory) {
        this.sessionHandlerFactory = sessionHandlerFactory;
    }

    private void handleError(HttpServletRequest request, HttpServletResponse response, Exception e)
            throws ServletException, IOException {
        log.error("Unable to validate Response", e);

        String err = null;
        if (configuration != null) {
            err = configuration.getString(Constants.PROP_ERROR_SERVLET, null);
        }
        if (err != null) {
            request.setAttribute(Constants.ATTRIBUTE_ERROR, e.getMessage());
            request.setAttribute(Constants.ATTRIBUTE_EXCEPTION, e);
            request.getRequestDispatcher(err).forward(request, response);
        } else {
            VelocityContext ctx = new VelocityContext();
            ctx.put(Constants.ATTRIBUTE_ERROR, e.getMessage());
            ctx.put(Constants.ATTRIBUTE_EXCEPTION, e);

            response.setContentType("text/html");
            response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);

            String prefix = "/" + getClass().getPackage().getName().replace('.', '/') + "/";
            try {
                engine.mergeTemplate(prefix + "error.vm", ctx, response.getWriter());
            } catch (Exception e1) {
                log.error("Unable to render error template", e1);
                throw new ServletException(e1);
            }
        }

    }

    @Override
    public void destroy() {
        if (sessionHandlerFactory != null) {
            sessionHandlerFactory.close();
        }
        SessionHandlerFactory.Factory.close();
    }

    private class IndexHandler implements SAMLHandler {
        public void handleGet(RequestContext context) throws ServletException, IOException {
            PrintWriter w = context.getResponse().getWriter();

            w.println("<html><head><title>SAML Endppoints</title></head><body><h1>SAML Endpoints</h1>");
            w.println("<ul>");
            for (Map.Entry<String, SAMLHandler> e : handlers.entrySet()) {
                w.println("<li><a href=\"");
                w.print(e.getKey());
                w.print("\">");
                w.print(e.getKey());
                w.print("</a>: ");
                w.print(e.getValue());
                w.println("</li>");
            }
            w.println("</ul>");
            w.println("</body></html>");
        }

        public void handlePost(RequestContext context) throws ServletException, IOException {
        }

    }
}