/*
* 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;
}
}
|