org.josso.tooling.gshell.install.installer.TomcatInstaller.java Source code

Java tutorial

Introduction

Here is the source code for org.josso.tooling.gshell.install.installer.TomcatInstaller.java

Source

/*
 * JOSSO: Java Open Single Sign-On
 *
 * Copyright 2004-2009, Atricore, Inc.
 *
 * 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.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this software; if not, write to the Free
 * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
 * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
 *
 */

package org.josso.tooling.gshell.install.installer;

import org.josso.tooling.gshell.install.JOSSOArtifact;
import org.josso.tooling.gshell.install.TargetPlatform;
import org.josso.tooling.gshell.install.util.XUpdateUtil;
import org.apache.commons.vfs.FileObject;
import org.apache.commons.vfs.FileType;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xmldb.common.xml.queries.XUpdateQuery;
import org.xmldb.xupdate.lexus.XUpdateQueryImpl;

import javax.xml.xpath.XPathFactory;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathExpression;
import javax.xml.xpath.XPathConstants;
import java.io.IOException;

/**
 * @org.apache.xbean.XBean element="tomcat-installer"
 *
 * @author <a href="mailto:sgonzalez@josso.org">Sebastian Gonzalez Oyuela</a>
 * @version $Id$
 */
public class TomcatInstaller extends VFSInstaller {

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

    public TomcatInstaller(TargetPlatform targetPlatform) {
        super(targetPlatform);
    }

    public TomcatInstaller() {
        super();
    }

    @Override
    public void validatePlatform() throws InstallException {

        super.validatePlatform();
        try {

            boolean valid = true;

            FileObject catalinaJar = targetLibDir.resolveFile("catalina.jar");

            if (catalinaJar == null || !catalinaJar.exists()
                    || !catalinaJar.getType().getName().equals(FileType.FILE.getName())) {
                valid = false;
                getPrinter().printErrStatus("CatalinaHome", "Cannot find catalina");
            }

            FileObject serverXml = targetConfDir.resolveFile("server.xml");
            if (serverXml == null || !serverXml.exists()
                    || !serverXml.getType().getName().equals(FileType.FILE.getName())) {
                valid = false;
                getPrinter().printErrStatus("CatalinaHome", "Cannot find server.xml");
            }

            // TODO : Validate Version ?

            if (!valid)
                throw new InstallException(
                        "Target does not seem a " + getTargetPlatform().getDescription() + " install.");

        } catch (IOException e) {
            getPrinter().printErrStatus("CatalinaHome", e.getMessage());
            throw new InstallException(e.getMessage(), e);
        }

        getPrinter().printOkStatus("CatalinaHome");
    }

    public void installComponent(JOSSOArtifact artifact, boolean replace) throws InstallException {
        try {

            // TODO : This should be part of the install command, maybe based on 'features' definitions.

            FileObject srcFile = getFileSystemManager().resolveFile(artifact.getLocation());

            // Install only the proper artifact for the target platform ...
            if (artifact.getBaseName().startsWith("josso-agent-shared")) {
                installFile(srcFile, this.targetJOSSOSharedLibDir, replace);

            } else if (artifact.getBaseName().startsWith("josso-agents-bin")) {

                // For Tomcat 6 and 7, jaxws is used
                if (getTargetPlatform().getVersion().startsWith("6.0")
                        && artifact.getClassifier().equals("jaxws")) {
                    installFile(srcFile, this.targetJOSSOLibDir, replace);
                } else if (getTargetPlatform().getVersion().startsWith("7.0")
                        && artifact.getClassifier().equals("jaxws")) {
                    installFile(srcFile, this.targetJOSSOLibDir, replace);
                } else if (artifact.getClassifier() == null || artifact.getClassifier().equals("axis")) {
                    installFile(srcFile, this.targetJOSSOLibDir, replace);
                }

            } else if (artifact.getBaseName().startsWith("josso-tomcat50-agent")
                    && getTargetPlatform().getVersion().startsWith("5.0")) {
                installFile(srcFile, this.targetJOSSOLibDir, replace);

            } else if (artifact.getBaseName().startsWith("josso-tomcat55-agent")
                    && getTargetPlatform().getVersion().startsWith("5.5")) {
                installFile(srcFile, this.targetJOSSOLibDir, replace);

            } else if (artifact.getBaseName().startsWith("josso-tomcat60-agent")
                    && getTargetPlatform().getVersion().startsWith("6.0")) {
                installFile(srcFile, this.targetJOSSOLibDir, replace);

            } else if (artifact.getBaseName().startsWith("josso-tomcat70-agent")
                    && getTargetPlatform().getVersion().startsWith("7.0")) {
                installFile(srcFile, this.targetJOSSOLibDir, replace);

            } else {
                log.debug("Artifact is not valid for selected platform : " + artifact);
            }

        } catch (IOException e) {
            throw new InstallException(e.getMessage(), e);
        }
    }

    public void install3rdPartyComponent(JOSSOArtifact artifact, boolean replace) throws InstallException {

        if (artifact.getBaseName().startsWith("log4j") || artifact.getBaseName().startsWith("spring-2.0"))
            return;

        if (artifact.getBaseName().startsWith("slf4j"))
            return;

        if (artifact.getBaseName().startsWith("jcl-over-slf4j"))
            return;

        if (artifact.getBaseName().startsWith("logback"))
            return;

        try {

            FileObject srcFile = getFileSystemManager().resolveFile(artifact.getLocation());

            // Some jars must be copied in special directories in Tomcat 5.5 / 5.0
            if (getTargetPlatform().getVersion().startsWith("5.")) {

                if (artifact.getBaseName().startsWith("commons-collections")) {
                    removeOldJar(srcFile.getName().getBaseName(), this.targetEndorsedLibDir, true);
                    installFile(srcFile, this.targetEndorsedLibDir, replace);
                } else {
                    removeOldJar(srcFile.getName().getBaseName(), this.targetLibDir, true);
                    installFile(srcFile, this.targetLibDir, replace);
                }

            } else if (getTargetPlatform().getVersion().startsWith("6.0")
                    || getTargetPlatform().getVersion().startsWith("7.0")) {

                // Minmal set of dependencies for TC 6/7
                if (artifact.getBaseName().startsWith("spring-")) {
                    removeOldJar(srcFile.getName().getBaseName(), this.targetLibDir, true);
                    installFile(srcFile, this.targetLibDir, replace);
                } else if (artifact.getBaseName().startsWith("xbean-")) {
                    removeOldJar(srcFile.getName().getBaseName(), this.targetLibDir, true);
                    installFile(srcFile, this.targetLibDir, replace);
                } else if (artifact.getBaseName().startsWith("commons-")) {
                    removeOldJar(srcFile.getName().getBaseName(), this.targetLibDir, true);
                    installFile(srcFile, this.targetLibDir, replace);
                }

            } else {
                removeOldJar(srcFile.getName().getBaseName(), this.targetLibDir, true);
                installFile(srcFile, this.targetLibDir, replace);
            }

        } catch (IOException e) {
            throw new InstallException(e.getMessage(), e);
        }
    }

    public void installApplication(JOSSOArtifact artifact, boolean replace) throws InstallException {

        try {

            if (!artifact.getType().equals("war")) {
                log.debug("Application type : " + artifact.getType() + " not supported.");
                return;
            }

            // If the war is already expanded, copy it with a new name.
            FileObject srcFile = getFileSystemManager().resolveFile(artifact.getLocation());

            // Is this the josso gateaway ?
            String name = artifact.getBaseName();
            boolean isFolder = srcFile.getType().equals(FileType.FOLDER);

            if (name.startsWith("josso-gateway-web")) {
                // INSTALL GWY
                // Do we have to explode the war ?
                if (getTargetPlatform().isJOSSOWarExploded() && !isFolder) {
                    installJar(srcFile, this.targetDeployDir, "josso", true, replace);
                } else {
                    installFile(srcFile, this.targetDeployDir, "josso.war", replace);
                }
                return;
            }

            if (artifact.getBaseName().startsWith("josso-partner-tomcat-web")) {
                installJar(srcFile, this.targetDeployDir, "partnerapp", true, replace);
                return;
            }

        } catch (IOException e) {
            throw new InstallException(e.getMessage(), e);
        }
    }

    @Override
    public void installConfiguration(JOSSOArtifact artifact, boolean replace) throws InstallException {
        try {
            FileObject srcFile = getFileSystemManager().resolveFile(artifact.getLocation());

            String name = srcFile.getName().getBaseName();

            if (name.startsWith("setenv")) {
                installFile(srcFile, this.targetBinDir, replace);
            } else if (name.equals("jaas.conf")) {
                installFile(srcFile, this.targetConfDir, replace);
            } else {
                installFile(srcFile, this.targetJOSSOConfDir, replace);
            }
        } catch (IOException e) {
            throw new InstallException(e.getMessage(), e);
        }

    }

    @Override
    public boolean backupAgentConfigurations(boolean remove) {
        try {
            super.backupAgentConfigurations(remove);
            // backup jaas.conf
            FileObject jaasConfigFile = targetConfDir.resolveFile("jaas.conf");
            if (jaasConfigFile.exists()) {
                // backup file in the same folder it is installed
                backupFile(jaasConfigFile, jaasConfigFile.getParent());
                if (remove) {
                    jaasConfigFile.delete();
                }
            }
            // backup setenv.sh and setenv.bat
            FileObject[] libs = targetBinDir.getChildren();
            for (int i = 0; i < libs.length; i++) {
                FileObject cfgFile = libs[i];

                if (!cfgFile.getType().getName().equals(FileType.FILE.getName())) {
                    // ignore folders
                    continue;
                }
                if (cfgFile.getName().getBaseName().startsWith("setenv")
                        && (cfgFile.getName().getBaseName().endsWith(".sh")
                                || cfgFile.getName().getBaseName().endsWith(".bat"))) {
                    // backup files in the same folder they're installed in
                    backupFile(cfgFile, cfgFile.getParent());
                    if (remove) {
                        cfgFile.delete();
                    }
                }
            }
        } catch (Exception e) {
            getPrinter().printErrStatus("BackupAgentConfigurations", e.getMessage());
            return false;
        }
        return true;
    }

    public void configureAgent() throws InstallException {

        // Setup XUpdate :
        System.setProperty("org.xmldb.common.xml.queries.XPathQueryFactory",
                "org.xmldb.common.xml.queries.xalan2.XPathQueryFactoryImpl");

        // For now, only one file to configure:
        configureServerXml();
    }

    protected void configureServerXml() throws InstallException {
        // --------------------------------------------------------------------
        // Configure server.xml
        // --------------------------------------------------------------------

        // We will use xupdate to alter catalina configuration : server.xml
        FileObject serverXml = null;

        try {

            serverXml = targetConfDir.resolveFile("server.xml");

            // Get a DOM document of the server.xml :
            Node serverXmlDom = readContentAsDom(serverXml);

            boolean modified = false;

            // Perfomr specific configurations
            if (configureRealm(serverXmlDom))
                modified = true;

            if (configureValve(serverXmlDom))
                modified = true;

            if (modified) {

                // Backup Container configuration.  If we cannot perform a backup, do nothing
                if (!backupFile(serverXml, targetConfDir)) {
                    getPrinter().printActionWarnStatus("Configure",
                            targetConfDir.getName().getFriendlyURI() + "/server.xml",
                            "Must be done manually (Follow setup guide)");
                    return;
                }

                // Write modifications to file
                writeContentFromDom(serverXmlDom, serverXml);
                getPrinter().printActionOkStatus("Save", serverXml.getName().getBaseName(),
                        serverXml.getName().getFriendlyURI());

            }

        } catch (Exception e) {
            log.error(e.getMessage(), e);
            getPrinter().printErrStatus("Cannot configure container : ", e.getMessage());
            getPrinter().printActionWarnStatus("Configure",
                    targetConfDir.getName().getFriendlyURI() + "/server.xml",
                    "Must be done manually (Follow setup guide)");
        }

    }

    protected boolean configureRealm(Node serverXmlDom) throws Exception {

        XPath xpath = XPathFactory.newInstance().newXPath();

        // Because we removed all realms, we always add JOSSO realm
        String usersClassNames = "org.josso.gateway.identity.service.BaseUserImpl";
        String roleClassNames = "org.josso.gateway.identity.service.BaseRoleImpl";
        String realmClass = "org.josso." + getPlatformId() + ".agent.jaas.CatalinaJAASRealm"; // TODO : Be carefull with platform ID, this could not match the agent pacakge

        // Check if josso agent valve is already present

        XPathExpression findAgentRealm = xpath
                .compile("/Server/Service/Engine/Realm[@className=\"" + realmClass + "\"]");
        NodeList agentRealms = (NodeList) findAgentRealm.evaluate(serverXmlDom, XPathConstants.NODESET);

        // If we already have a JOSSO Valve, do nothing!
        if (agentRealms != null && agentRealms.getLength() > 0) {
            for (int i = 0; i < agentRealms.getLength(); i++) {
                Node valve = agentRealms.item(i);
                Node valveClassNode = valve.getAttributes().getNamedItem("className");
                getPrinter().printActionWarnStatus("Configure", "JOSSO JASS Realm", "Already configured : "
                        + (valveClassNode != null ? valveClassNode.getNodeValue() : "<unknown>"));
            }
            return false;
        }

        XPathExpression findRealmsExpr = xpath.compile("/Server/Service/Engine/Realm");
        NodeList realms = (NodeList) findRealmsExpr.evaluate(serverXmlDom, XPathConstants.NODESET);

        if (realms != null && realms.getLength() > 0) {
            String qryModifications = "\n\t<xupdate:remove select=\"/Server/Service/Engine/Realm\"/>";
            String qry = XUpdateUtil.XUPDATE_START + qryModifications + XUpdateUtil.XUPDATE_END;
            log.debug("XUPDATE QUERY: \n" + qry);
            XUpdateQuery xq = new XUpdateQueryImpl();
            xq.setQString(qry);
            xq.execute(serverXmlDom);

            for (int i = 0; i < realms.getLength(); i++) {
                Node realmDom = realms.item(i);
                Node className = realmDom.getAttributes().getNamedItem("className");
                getPrinter().printActionOkStatus("Removed", "Tomcat default Realm ",
                        (className != null ? className.getNodeValue() : "<unknown>"));
            }
        }

        String appendJossoRealmQryMod = "\n\t<xupdate:insert-before select=\"//Server/Service/Engine/Host[1]\" >"
                + "\n\t<xupdate:comment>" + " ================================================== "
                + "</xupdate:comment>" + "\n\t<xupdate:comment>"
                + "   JOSSO JAAS Realm, configuration automatially generated by JOSSO Installer "
                + "</xupdate:comment>" + "\n\t<xupdate:element name=\"Realm\">"
                + "<xupdate:attribute name=\"appName\">josso</xupdate:attribute>"
                + "<xupdate:attribute name=\"debug\">1</xupdate:attribute>"
                + "\n\t<xupdate:attribute name=\"className\">" + realmClass + "</xupdate:attribute>"
                + "\n\t<xupdate:attribute name=\"userClassNames\">" + usersClassNames + "</xupdate:attribute>"
                + "\n\t<xupdate:attribute name=\"roleClassNames\">" + roleClassNames + "</xupdate:attribute>"
                + "</xupdate:element>" + "\n\t<xupdate:comment>"
                + " ================================================== " + "</xupdate:comment>\n\t"
                + "</xupdate:insert-before>";

        String appendJossoRealmQryStr = XUpdateUtil.XUPDATE_START + appendJossoRealmQryMod
                + XUpdateUtil.XUPDATE_END;
        log.debug("XUPDATE QUERY: \n" + appendJossoRealmQryStr);

        XUpdateQuery appendJossoRealmQry = new XUpdateQueryImpl();
        appendJossoRealmQry.setQString(appendJossoRealmQryStr);
        appendJossoRealmQry.execute(serverXmlDom);

        getPrinter().printActionOkStatus("Configured", "JOSSO JAAS Realm ", realmClass);

        return true;

    }

    protected boolean configureValve(Node serverXmlDom) throws Exception {

        XPath xpath = XPathFactory.newInstance().newXPath();

        // Check if josso agent valve is already present
        String valveClass = "org.josso." + getPlatformId() + ".agent.SSOAgentValve"; // TODO : Be carefull with platform ID, this could not match the agent pacakge
        XPathExpression findAgentValve = xpath
                .compile("/Server/Service/Engine/Host/Valve[@className=\"" + valveClass + "\"]");
        NodeList agentValves = (NodeList) findAgentValve.evaluate(serverXmlDom, XPathConstants.NODESET);

        // If we already have a JOSSO Valve, do nothing!
        if (agentValves != null && agentValves.getLength() > 0) {
            for (int i = 0; i < agentValves.getLength(); i++) {
                Node valve = agentValves.item(i);
                Node valveClassNode = valve.getAttributes().getNamedItem("className");
                getPrinter().printActionWarnStatus("Configure", "JOSSO Agent Valve", "Already configured : "
                        + (valveClassNode != null ? valveClassNode.getNodeValue() : "<unknown>"));
            }
            return false;
        }

        String appendJossoValveQryMod = "\n\t<xupdate:append select=\"//Server/Service/Engine/Host\" >"
                + "\n\t<xupdate:comment>" + " ================================================== "
                + "</xupdate:comment>" + "\n\t<xupdate:comment>"
                + "   JOSSO Agent Valve, configuration automatially generated by JOSSO Installer "
                + "</xupdate:comment>" + "\n\t<xupdate:element name=\"Valve\">"
                + "<xupdate:attribute name=\"appName\">josso</xupdate:attribute>"
                + "<xupdate:attribute name=\"debug\">1</xupdate:attribute>"
                + "\n\t\t<xupdate:attribute name=\"className\">" + valveClass + "</xupdate:attribute>"
                + "</xupdate:element>" + "\n\t<xupdate:comment>"
                + " ================================================== " + "</xupdate:comment>\n\t"
                + "</xupdate:append>";

        String appendJossoValveQryStr = XUpdateUtil.XUPDATE_START + appendJossoValveQryMod
                + XUpdateUtil.XUPDATE_END;
        log.debug("XUPDATE QUERY: \n" + appendJossoValveQryStr);

        XUpdateQuery appendJossoValveQry = new XUpdateQueryImpl();
        appendJossoValveQry.setQString(appendJossoValveQryStr);
        appendJossoValveQry.execute(serverXmlDom);

        getPrinter().printActionOkStatus("Configured", "JOSSO Agent Valve ", valveClass);

        return true;

    }

}