InstallPackage.java :  » Content-Management-System » contelligent » de » finix » contelligent » core » Java Open Source

Java Open Source » Content Management System » contelligent 
contelligent » de » finix » contelligent » core » InstallPackage.java
/*
 * Copyright 2001-2006 C:1 Financial Services GmbH
 *
 * This software is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License Version 2.1, as published by the Free Software Foundation.
 *
 * 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 library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA
 */

package de.finix.contelligent.core;

import java.io.IOException;
import java.io.InputStream;
import java.net.JarURLConnection;
import java.net.URL;
import java.net.URLClassLoader;
import java.net.URLConnection;
import java.security.PrivilegedExceptionAction;
import java.util.Comparator;
import java.util.Iterator;
import java.util.List;
import java.util.SortedSet;
import java.util.TreeSet;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;

import javax.transaction.HeuristicMixedException;
import javax.transaction.HeuristicRollbackException;
import javax.transaction.RollbackException;
import javax.transaction.SystemException;

import de.finix.contelligent.CallData;
import de.finix.contelligent.ComponentManager;
import de.finix.contelligent.ComponentPath;
import de.finix.contelligent.Contelligent;
import de.finix.contelligent.Session;
import de.finix.contelligent.core.cpkg.ClientModuleManager;
import de.finix.contelligent.core.security.ContelligentSecurityManager;
import de.finix.contelligent.core.security.User;
import de.finix.contelligent.exception.ContelligentException;
import de.finix.contelligent.exception.ContelligentExceptionID;
import de.finix.contelligent.exception.ContelligentRuntimeException;
import de.finix.contelligent.exception.DeadRelationsWarning;
import de.finix.contelligent.exception.WouldCreateDeadRelationsException;
import de.finix.contelligent.logging.LoggingService;
import de.finix.contelligent.persistence.PackageManagerPersistenceAdapter;
import de.finix.contelligent.util.ThreadedMem;
import de.finix.contelligent.xml.elements.PackageElement;
import de.finix.contelligent.xml.elements.PackageImportElement;
import de.finix.contelligent.xml.elements.TypeElement;

class InstallPackage extends SystemStateCommand {

    final static org.apache.log4j.Logger log = LoggingService.getLogger(InstallPackage.class);

    public InstallPackage(ContelligentPackage pkg, URL url) {
        super(pkg, url);
    }

    void prepare() {
    }

    void validate(PackageValidator validator) throws ContelligentException {
        validator.validate(getPkg(), getUrl());
    }

    void execute(Contelligent contelligent, PackageManagerPersistenceAdapter pkgPersistence) throws IOException,
            SystemException, HeuristicMixedException, RollbackException, HeuristicRollbackException,
            ContelligentException {
        int txTimeout = (10 * contelligent.getDefaultTransactionTimeout());

        ClientModuleManager.getInstance().processPackage(getPkg().getElement(), getUrl());

        if (contelligent.isReadOnly()) {
            return; // we are done, do not import
        }
        log.info("... installing package " + getPkg().getName());
        contelligent.beginTx(txTimeout);

        CallDataImpl callData = null;
        ComponentManager importManager = null;
        Session session = null;
        PackageElement element = getPkg().getElement();

        boolean preImportFailed = false;
        // import to import manager
        try {
            BasicComponentManager targetManager = (BasicComponentManager) contelligent.getRootComponentManager();
            importManager = contelligent.getComponentManagerHierarchy().createImportManager(targetManager,
                    getBinaryPath());
            // create session with SystemUser for import:
            User user = ContelligentSecurityManager.getSystemUser();
            session = contelligent.beginSession(user, importManager);
            callData = new CallDataImpl(session);
            ThreadedMem.setCallData(callData);

            installPackage(element, getUrl(), callData);
        } catch (PackageException e) {
            preImportFailed = true;
            throw e;
        } catch (ContelligentException e) {
            preImportFailed = true;
            throw e;
        } catch (Throwable e) {
            preImportFailed = true;
            throw new PackageException(e);
        } finally {
            // always commit imported stuff
            // XXX: [asac: looks rather stupid. Can't imagine any case when a
            // commit is wanted
            // if import failed. If some problems occur the problem is somewhere
            // else and
            // should be fixed at that place ... once you are convinced that
            // this is right,
            // you should outcomment the rollbackTx lines in the exception cases
            // above!!]
            if (preImportFailed) {
                contelligent.rollbackTx();
            } else {
                contelligent.commitTx();
            }
        }

        // now validate and commit import context
        // destroy import manager
        contelligent.beginTx(txTimeout);
        try {
            importManager.validateBlueprintTypes();

            final ComponentManager importManagerTMP = importManager;
            final CallData callDataTMP = callData;

            callData.doWithoutRelationsCheck(new PrivilegedExceptionAction() {
                public Object run() throws Exception {
                    importManagerTMP.commitServer(callDataTMP);
                    return null;
                }
            });

            boolean writePkgInfo = true;

            try {
                ((BasicComponentManager) importManager.getParent()).checkRelations();
            } catch (WouldCreateDeadRelationsException e) {
                if ((((ContelligentImpl) contelligent).getImportMode() == ContelligentImpl.IMPORT_STRICT) && (!BasicComponentManager.deadRelationsCheckDisabled)) {
                    writePkgInfo = false;
                    throw e;
                } else {
                    throw new DeadRelationsWarning();
                }
            } finally {
                if (writePkgInfo) {
                    pkgPersistence.storePackageInfo(element.getName(), element.getVersion(), element.getDisplayName(),
                            element.getProvider(), element.isReadOnly());
                    pkgPersistence.storePackageRequirements(element.getName(), element.getRequirementsMap());
                }
            }
        } catch (DeadRelationsWarning e) {
            contelligent.commitTx();
            throw e;
        } catch (ContelligentException e) {
            contelligent.rollbackTx();
            log.error("Import failed", e);
            throw e;
        } catch (ContelligentRuntimeException e) {
            contelligent.rollbackTx();
            log.error("Import failed", e);
            throw e;
        } catch (Throwable e) {
            contelligent.rollbackTx();
            log.error("Import failed", e);
            throw new PackageException(e);
        } finally {
            if (session != null) {
                contelligent.invalidateSession(session);
            }
            boolean newTX = contelligent.beginTx();
            contelligent.getComponentManagerHierarchy().destroyComponentManager(importManager.getName(), true);

            if (newTX) {
                contelligent.commitTx();
            }
        }
        contelligent.commitTx();
    }

    public String toString() {
        return "Install " + getPkg().getName();
    }

    void installPackage(PackageElement pkg, URL url, CallData callData) throws ContelligentException {
        ComponentManager importManager = callData.getActualManager();
        try {
            log.debug("Starting importing of package " + pkg.getName() + " using URL " + url + " ...");
            ComponentPath pkgRootPath = new ComponentPath("/" + pkg.getName().replace('.', '/'));
            importManager.lockComponent(pkgRootPath, callData);

            Comparator comparator = new PackageManager.PackageImportComparator();
            SortedSet types = new TreeSet(comparator);
            SortedSet components = new TreeSet(comparator);

            types.addAll(pkg.getTypes());
            components.addAll(pkg.getComponents());

            TypeImport typeImporter = new TypeImport();
            Iterator iterator = types.iterator();

            while (iterator.hasNext()) {
                PackageImportElement pkgElement = (PackageImportElement) iterator.next();
                InputStream in = getPackageResourceStream(url, PackageManager.PKG_RESOURCE_PREFIX
                        + pkgElement.getFileName());
                try {
                    if (in == null) {
                        throw new PackageException("Resource '" + pkgElement.getFileName() + "' of package '"
                                + pkg.getName() + "' defined but not found at URL " + url);
                    }
                    log.debug("Importing type-resource '" + pkgElement.getFileName() + "' of package '" + pkg.getName()
                            + "' ...");
                    List typeList = typeImporter.xmlToTypeElements(callData, in, false);
                    Iterator it = typeList.iterator();
                    while (it.hasNext()) {
                        importManager.createType((TypeElement) it.next());
                    }

                } finally {
                    if (in != null) {
                        try {
                            in.close();
                        } catch (IOException e) {
                        }
                    }
                }
            }

            ComponentImport componentsImporter = new ComponentImport();
            iterator = components.iterator();
            while (iterator.hasNext()) {
                PackageImportElement pkgElement = (PackageImportElement) iterator.next();
                InputStream in = getPackageResourceStream(url, PackageManager.PKG_RESOURCE_PREFIX
                        + pkgElement.getFileName());
                try {
                    if (in == null) {
                        throw new ContelligentException("Resource '" + pkgElement.getFileName() + "' of package '"
                                + pkg.getName() + "' defined but not found at URL " + url);
                    }
                    log.debug("Importing component-resource '" + pkgElement.getFileName() + "' of package '"
                            + pkg.getName() + "' ...");
                    componentsImporter.importComponents(callData, in, null);
                } finally {
                    if (in != null) {
                        try {
                            in.close();
                        } catch (IOException e) {
                        }
                    }
                }
            }
        } catch (ContelligentException e) {
            log.error("installPackages()", e);
            throw e;
        } catch (ContelligentRuntimeException e) {
            log.error("installPackages()", e);
            throw e;
        } catch (Exception e) {
            log.error(e);
            throw new PackageException(ContelligentExceptionID.package_import_failed, new Object[] { pkg.getName() }, e);
        }
    }

    // overwrite for exploded pkg manager

    protected String getBinaryPath() {
        return null;
    }

    protected static InputStream getPackageResourceStream(URL packageURL, String resourceName) throws PackageException {
        InputStream result = null;
        try {
            log.debug("getPackageResource() - opening connection to URL '" + packageURL + "' ...");
            URLConnection con = packageURL.openConnection();
            if (!(con instanceof JarURLConnection)) {
                log.debug("getPackageResource() - ... could not use JarURLConnection for URL '" + packageURL
                        + "' -> trying to use URLClassLoader ...");
                URLClassLoader tmpCL = new URLClassLoader(new URL[] { packageURL });
                URL resourceURL = tmpCL.findResource(resourceName);
                if (resourceURL == null) {
                    log.error("getPackageResource() - cannot find resource '" + resourceName + "' in directory '"
                            + packageURL + "'!");
                } else {
                    result = resourceURL.openStream();
                }
            } else {
                log.debug("getPackageResource() - ... using JarURLConnection ...");
                JarURLConnection jarCon = (JarURLConnection) con;
                JarFile jarFile = jarCon.getJarFile();
                JarEntry resourceEntry = jarFile.getJarEntry(resourceName);
                if (resourceEntry == null) {
                    log.error("getPackageResource() - cannot find resource '" + resourceName + "' in jar '"
                            + jarFile.getName() + "'!");
                } else {
                    result = jarFile.getInputStream(resourceEntry);
                }
            }
        } catch (IOException e) {
            log.error("getPackageResource() - IOException: ", e);
            throw new PackageException("getPackageResource() - IOException !", e);
        } catch (Exception e) {
            log.error("getPackageResource() - Exception: ", e);
            throw new PackageException("getPackageResource() - Exception !", e);
        }
        return result;
    }

}
java2s.com  | Contact Us | Privacy Policy
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.