org.mycore.user2.MCRRealmFactory.java Source code

Java tutorial

Introduction

Here is the source code for org.mycore.user2.MCRRealmFactory.java

Source

/*
 * $Id$
 * $Revision: 5697 $ $Date: 20.02.2012 $
 *
 * This file is part of ***  M y C o R e  ***
 * See http://www.mycore.de/ for details.
 *
 * This program is free software; you can use it, redistribute it
 * and / or modify it under the terms of the GNU General Public License
 * (GPL) as published by the Free Software Foundation; either version 2
 * of the License or (at your option) any later version.
 *
 * This program 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 General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program, in a file called gpl.txt or license.txt.
 * If not, write to the Free Software Foundation Inc.,
 * 59 Temple Place - Suite 330, Boston, MA  02111-1307 USA
 */

package org.mycore.user2;

import java.io.File;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

import javax.xml.transform.Source;
import javax.xml.transform.TransformerException;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.jdom2.Document;
import org.jdom2.Element;
import org.jdom2.JDOMException;
import org.jdom2.Namespace;
import org.jdom2.transform.JDOMSource;
import org.mycore.common.MCRException;
import org.mycore.common.config.MCRConfiguration;
import org.mycore.common.content.MCRFileContent;
import org.mycore.common.content.MCRSourceContent;
import org.mycore.common.xml.MCRXMLParserFactory;
import org.xml.sax.SAXException;

/**
 * Handles {@link MCRRealm} instantiation.
 * Will create a file <code>${MCR.datadir}/realms.xml</code> if that file does not exist.
 * You can redefine the location if you define a URI in <code>MCR.users2.Realms.URI</code>.
 * This class monitors the source file for changes and adapts at runtime.
 * @author Thomas Scheffler (yagee)
 *
 */
public class MCRRealmFactory {

    static final String RESOURCE_REALMS_URI = "resource:realms.xml";

    static final String REALMS_URI_CFG_KEY = MCRUser2Constants.CONFIG_PREFIX + "Realms.URI";

    private static final Logger LOGGER = LogManager.getLogger(MCRRealm.class);

    private static final int REFRESH_DELAY = 5000;

    private static long lastModified = 0;

    /** Map of defined realms, key is the ID of the realm */
    private static HashMap<String, MCRRealm> realmsMap = new HashMap<String, MCRRealm>();

    private static HashMap<String, MCRUserAttributeMapper> attributeMapper = new HashMap<String, MCRUserAttributeMapper>();

    /** List of defined realms */
    private static List<MCRRealm> realmsList = new ArrayList<MCRRealm>();

    /** The local realm, which is the default realm */
    private static MCRRealm localRealm;

    private static URI realmsURI;

    private static File realmsFile;

    private static long lastChecked;

    private static Document realmsDocument;

    static {
        MCRConfiguration config = MCRConfiguration.instance();
        String dataDirProperty = "MCR.datadir";
        String dataDir = config.getString(dataDirProperty, null);
        if (dataDir == null) {
            LOGGER.warn(dataDirProperty + " is undefined.");
            try {
                realmsURI = new URI(config.getString(REALMS_URI_CFG_KEY, RESOURCE_REALMS_URI));
            } catch (URISyntaxException e) {
                throw new MCRException(e);
            }
        } else {
            File dataDirFile = new File(dataDir);
            String realmsCfg = config.getString(REALMS_URI_CFG_KEY, dataDirFile.toURI().toString() + "realms.xml");
            try {
                realmsURI = new URI(realmsCfg);
                LOGGER.info("Using realms defined in " + realmsURI);
                if ("file".equals(realmsURI.getScheme())) {
                    realmsFile = new File(realmsURI);
                    LOGGER.info("Loading realms from file: " + realmsFile);
                } else {
                    LOGGER.info("Try loading realms with URIResolver for scheme " + realmsURI.toString());
                }
            } catch (URISyntaxException e) {
                throw new MCRException(e);
            }
        }
        loadRealms();
    }

    /**
     * 
     */
    private static void loadRealms() {
        Element root;
        try {
            root = getRealms().getRootElement();
        } catch (SAXException | JDOMException | TransformerException | IOException e) {
            throw new MCRException("Could not load realms from URI: " + realmsURI);
        }
        String localRealmID = root.getAttributeValue("local");
        /** Map of defined realms, key is the ID of the realm */
        HashMap<String, MCRRealm> realmsMap = new HashMap<String, MCRRealm>();

        HashMap<String, MCRUserAttributeMapper> attributeMapper = new HashMap<String, MCRUserAttributeMapper>();

        /** List of defined realms */
        List<MCRRealm> realmsList = new ArrayList<MCRRealm>();

        List<Element> realms = (List<Element>) (root.getChildren("realm"));
        for (Element child : realms) {
            String id = child.getAttributeValue("id");
            MCRRealm realm = new MCRRealm(id);

            List<Element> labels = (List<Element>) (child.getChildren("label"));
            for (Element label : labels) {
                String text = label.getTextTrim();
                String lang = label.getAttributeValue("lang", Namespace.XML_NAMESPACE);
                realm.setLabel(lang, text);
            }

            realm.setPasswordChangeURL(child.getChildTextTrim("passwordChangeURL"));
            Element login = child.getChild("login");
            if (login != null) {
                realm.setLoginURL(login.getAttributeValue("url"));
                realm.setRedirectParameter(login.getAttributeValue("redirectParameter"));
                realm.setRealmParameter(login.getAttributeValue("realmParameter"));
            }
            Element createElement = child.getChild("create");
            if (createElement != null) {
                realm.setCreateURL(createElement.getAttributeValue("url"));
            }

            attributeMapper.put(id, MCRUserAttributeMapper.instance(child));

            realmsMap.put(id, realm);
            realmsList.add(realm);
            if (localRealmID.equals(id)) {
                localRealm = realm;
            }
        }
        MCRRealmFactory.realmsDocument = root.getDocument();
        MCRRealmFactory.realmsMap = realmsMap;
        MCRRealmFactory.realmsList = realmsList;
        MCRRealmFactory.attributeMapper = attributeMapper;
    }

    private static Document getRealms() throws JDOMException, TransformerException, SAXException, IOException {
        if (realmsFile == null) {
            return MCRSourceContent.getInstance(realmsURI.toASCIIString()).asXML();
        }
        if (!realmsFile.exists() || realmsFile.length() == 0) {
            LOGGER.info("Creating " + realmsFile.getAbsolutePath() + "...");
            MCRSourceContent realmsContent = MCRSourceContent.getInstance(RESOURCE_REALMS_URI);
            realmsContent.sendTo(realmsFile);
        }
        updateLastModified();
        return MCRXMLParserFactory.getNonValidatingParser().parseXML(new MCRFileContent(realmsFile));
    }

    /**
     * Returns the realm with the given ID.
     * 
     * @param id the ID of the realm
     * @return the realm with that ID, or null
     */
    public static MCRRealm getRealm(String id) {
        reInitIfNeeded();
        return realmsMap.get(id);
    }

    public static MCRUserAttributeMapper getAttributeMapper(String id) {
        reInitIfNeeded();
        return attributeMapper.get(id);
    }

    /**
     * Returns a list of all defined realms.
     *  
     * @return a list of all realms.
     */
    public static List<MCRRealm> listRealms() {
        reInitIfNeeded();
        return realmsList;
    }

    /**
     * Returns the Realms JDOM document clone. 
     */
    public static Document getRealmsDocument() {
        reInitIfNeeded();
        return (Document) realmsDocument.clone();
    }

    /**
     * Returns the Realms JDOM document as a {@link Source} useful for transformation processes.
     */
    static Source getRealmsSource() {
        reInitIfNeeded();
        return new JDOMSource(realmsDocument);
    }

    /**
     * Returns the local default realm, as specified by the attribute 'local' in realms.xml
     * 
     * @return the local default realm.
     */
    public static MCRRealm getLocalRealm() {
        reInitIfNeeded();
        return localRealm;
    }

    private static boolean reloadingRequired() {
        boolean reloading = false;

        long now = System.currentTimeMillis();

        if (now > lastChecked + REFRESH_DELAY) {
            lastChecked = now;
            if (hasChanged()) {
                reloading = true;
            }
        }

        return reloading;
    }

    private static boolean hasChanged() {
        if (realmsFile == null || !realmsFile.exists()) {
            return false;
        }
        return realmsFile.lastModified() > lastModified;
    }

    private static void updateLastModified() {
        if (realmsFile == null || !realmsFile.exists()) {
            return;
        }
        lastModified = realmsFile.lastModified();
    }

    private static void reInitIfNeeded() {
        if (reloadingRequired()) {
            loadRealms();
        }
    }

}