org.polymap.core.runtime.Polymap.java Source code

Java tutorial

Introduction

Here is the source code for org.polymap.core.runtime.Polymap.java

Source

/*
 * polymap.org Copyright (C) 2009-2013, Polymap GmbH. All rights reserved.
 * 
 * This is free software; you can redistribute it and/or modify it under the terms of
 * the GNU Lesser General Public License as published by the Free Software
 * Foundation; either version 2.1 of the License, or (at your option) any later
 * version.
 * 
 * This software is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
 * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
 */
package org.polymap.core.runtime;

import java.util.HashMap;
import java.util.HashSet;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ExecutorService;

import java.io.File;
import java.io.FileOutputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.security.Principal;

import javax.security.auth.Subject;
import javax.security.auth.login.LoginException;
import javax.servlet.http.HttpServletRequest;

import org.apache.commons.io.IOUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import com.google.common.base.Supplier;

import org.eclipse.swt.widgets.Display;

import org.eclipse.rwt.RWT;
import org.eclipse.rwt.internal.lifecycle.RWTLifeCycle;
import org.eclipse.rwt.internal.service.ContextProvider;

import org.eclipse.core.resources.IWorkspace;
import org.eclipse.core.resources.IWorkspaceRoot;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.equinox.security.auth.ILoginContext;
import org.eclipse.equinox.security.auth.LoginContextFactory;

import org.polymap.core.CorePlugin;
import org.polymap.core.security.AuthorizationModule;
import org.polymap.core.security.ServicesCallbackHandler;
import org.polymap.core.security.UserPrincipal;

/**
 * Static access to the runtime infrastructure.
 *
 * @author <a href="http://www.polymap.de">Falko Brutigam</a>
 * @since 3.0
 */
@SuppressWarnings("restriction")
public final class Polymap {

    private static Log log = LogFactory.getLog(Polymap.class);

    public static final String DEFAULT_LOGIN_CONFIG = "POLYMAP";
    public static final String SERVICES_LOGIN_CONFIG = "Services";

    static {
        // set the default locale to 'en' as all of our message_xx.properties
        // files have 'en' as default
        Locale.setDefault(Locale.ENGLISH);
    }

    // static factory *************************************

    /**
     * Gets or creates the Polymap instance for the application session of the
     * current thread.
     */
    public static Polymap instance() {
        return SessionSingleton.instance(Polymap.class);
    }

    /**
     *
     */
    public static IPath getWorkspacePath() {
        IWorkspace workspace = ResourcesPlugin.getWorkspace();
        IWorkspaceRoot root = workspace.getRoot();
        IPath path = root.getLocation();
        return path;
    }

    /**
    *
    */
    public static File getCacheDir() {
        File cacheDir = new File(getWorkspacePath().toFile(), "cache");
        cacheDir.mkdirs();
        return cacheDir;
    }

    /**
     *
     */
    public static File getConfigDir() {
        File configDir = new File(getWorkspacePath().toFile(), "config");
        configDir.mkdirs();
        return configDir;
    }

    /**
     *
     */
    public static File getDataDir() {
        File dataDir = new File(getWorkspacePath().toFile(), "data");
        dataDir.mkdirs();
        return dataDir;
    }

    /**
     * The {@link Display} of the session of the current thread. Null, if the
     * current thread has no session. The result is equivalent to
     * {@link Display#getCurrent()} except that the calling thread does need to
     * be the UI thread of the session.
     */
    public static Display getSessionDisplay() {
        return RWTLifeCycle.getSessionDisplay();
    }

    public static Locale getSessionLocale() {
        try {
            return instance().getLocale();
        } catch (Exception e) {
            return null;
        }
    }

    // public static ExecutorService      executorService = new PolymapJobExecutor();
    // public static ExecutorService      executorService = PolymapThreadPoolExecutor.newInstance();
    public static ExecutorService executorService = UnboundPoolExecutor.newInstance();

    /**
     * Returns the {@link ExecutorService} for the calling session. This should be
     * used whenever working threads are needed for multi processing. The default
     * Eclipse {@link Job} should be used for normal async business logic operations.
     */
    public static ExecutorService executorService() {
        return executorService;
    }

    // instance *******************************************

    /** The session attributes. */
    private Map attributes = new HashMap();

    private ILoginContext secureContext;

    private Subject subject;

    private Set<Principal> principals = new HashSet();

    private UserPrincipal user;

    private Map initHttpParams;

    /** 
     * The locale of the HTTP Accept-Langueage header or the server default locale. 
     * <p/>
     * Cache the locale for calls from outside the request lifecycle.
     */
    private LazyInit<Locale> locale = new PlainLazyInit(new Supplier<Locale>() {
        public Locale get() {
            try {
                // outside request lifecycle -> exception
                return ContextProvider.getRequest().getLocale();
            } catch (Exception e) {
                return null; // try again next time
            }
        }
    });

    /**
     * No-args default ctor for implicite creation by {@link #getInstance(Class)}.
     */
    private Polymap() {
    }

    public Locale getLocale() {
        return locale.get();
    }

    /**
     * Logging in using default JAAS config.
     */
    public void login() {
        HttpServletRequest request = RWT.getRequest();
        initHttpParams = new HashMap(request.getParameterMap());

        String jaasConfigFile = "jaas_config.txt";
        File configFile = new File(getWorkspacePath().toFile(), jaasConfigFile);

        // create default config
        if (!configFile.exists()) {
            FileOutputStream out = null;
            try {
                log.info("Creating default JAAS config: " + configFile.getAbsolutePath());
                URL defaultConfigUrl = CorePlugin.getDefault().getBundle().getEntry(jaasConfigFile);
                out = new FileOutputStream(configFile);
                IOUtils.copy(defaultConfigUrl.openStream(), out);
            } catch (Exception e) {
                throw new RuntimeException("Unable to create default jaas_config.txt in workspace.", e);
            } finally {
                IOUtils.closeQuietly(out);
            }
        }

        // create secureContext
        try {
            secureContext = LoginContextFactory.createContext(DEFAULT_LOGIN_CONFIG, configFile.toURI().toURL());
        } catch (MalformedURLException e) {
            throw new RuntimeException("Should never happen.", e);
        }

        // login
        for (boolean loggedIn = false; !loggedIn;) {
            try {
                secureContext.login();

                subject = secureContext.getSubject();
                principals = new HashSet(subject.getPrincipals());

                // find user
                for (Principal principal : principals) {
                    if (principal instanceof UserPrincipal) {
                        user = (UserPrincipal) principal;
                        break;
                    }
                }
                if (user == null) {
                    throw new LoginException("Es wurde kein Nutzer in der Konfiguration gefunden");
                }

                // allow to access the instance directly via current session (find user for example)
                SessionContext.current().setAttribute("user", user);

                // add roles of user to principals
                Set<AuthorizationModule> authModules = subject.getPrivateCredentials(AuthorizationModule.class);
                if (authModules.size() != 1) {
                    throw new RuntimeException("No AuthorizationModule specified. Is jaas_config.txt correct?");
                }
                principals.addAll(authModules.iterator().next().rolesOf(subject));

                loggedIn = true;
            } catch (LoginException e) {
                log.warn("Login error: " + e.getLocalizedMessage(), e);
                //                // FIXME causes zombie threads?
                //                // XXX translation
                //                IStatus status = new Status( IStatus.ERROR, CorePlugin.PLUGIN_ID, "Login fehlgeschlagen.", e );
                //                ErrorDialog.openError( null, "Achtung", "Login fehlgeschlagen", status );
            }
        }
    }

    public void login(String username, String passwd) throws LoginException {
        // init params are not available in services
        initHttpParams = new HashMap();

        String jaasConfigFile = "jaas_config.txt";
        File configFile = new File(getWorkspacePath().toFile(), jaasConfigFile);

        ServicesCallbackHandler.challenge(username, passwd);

        // create secureContext
        try {
            secureContext = LoginContextFactory.createContext(SERVICES_LOGIN_CONFIG, configFile.toURI().toURL());
        } catch (MalformedURLException e) {
            throw new RuntimeException("Should never happen.", e);
        }

        // login
        secureContext.login();
        subject = secureContext.getSubject();
        principals = new HashSet(subject.getPrincipals());

        // find user
        for (Principal principal : principals) {
            if (principal instanceof UserPrincipal) {
                user = (UserPrincipal) principal;
                break;
            }
        }
        if (user == null) {
            throw new LoginException("Es wurde kein Nutzer in der Konfiguration gefunden");
        }

        // add roles of user to principals
        log.info("Subject: " + subject);
        Set<AuthorizationModule> authModules = subject.getPrivateCredentials(AuthorizationModule.class);
        if (authModules.size() != 1) {
            throw new RuntimeException("No AuthorizationModule specified.");
        }
        principals.addAll(authModules.iterator().next().rolesOf(subject));

        //        subject.getPrivateCredentials().add( Display.getCurrent() );
        //        subject.getPrivateCredentials().add( SWT.getPlatform() );        

        // allow to access the instance directly via current session (find user for example)
        SessionContext.current().setAttribute("user", user);
    }

    public void logout() {
        if (secureContext != null) {
            try {
                secureContext.logout();
                secureContext = null;
                subject = null;
                principals = null;
                user = null;
            } catch (LoginException e) {
                log.warn("Login error: " + e.getLocalizedMessage(), e);
            }
        }
    }

    public void addPrincipal(Principal principal) {
        principals.add(principal);
        if (principal instanceof UserPrincipal) {
            user = (UserPrincipal) principal;
        }
    }

    public Set<Principal> getPrincipals() {
        assert principals != null : "getPrincipals(): called after logout!";
        return principals;
    }

    public Principal getUser() {
        assert principals != null : "getUser(): called after logout!";
        return user;
    }

    public Subject getSubject() {
        assert principals != null : "getSubject(): called after logout!";
        return subject;
    }

    /**
     * 
     *
     * @param key
     * @param defaultValue
     * @return The value, or the defaultValue if no such init param was given.
     */
    public String getInitRequestParam(String key, String defaultValue) {
        assert initHttpParams != null;
        String[] value = (String[]) initHttpParams.get(key);
        return value != null ? value[0] : defaultValue;
    }

    //    /**
    //     * Returns the preference service for the current session and user.
    //     */
    //    public IPreferencesService getPreferenceService() {
    //        //return Platform.getPreferencesService().
    //        CorePlugin.getDefault().
    //    }

}