package permafrost.tundra.server.invoke;
import com.wm.app.b2b.server.BaseService;
import com.wm.app.b2b.server.PackageReplicator;
import com.wm.app.b2b.server.Server;
import com.wm.app.b2b.server.Service;
import com.wm.app.b2b.server.invoke.ServiceStatus;
import com.wm.app.b2b.server.Package;
import com.wm.app.b2b.server.PackageManager;
import com.wm.data.IData;
import com.wm.data.IDataFactory;
import com.wm.lang.ns.NSName;
import com.wm.util.ServerException;
import permafrost.tundra.data.IDataHelper;
import permafrost.tundra.lang.IterableEnumeration;
import java.io.File;
import java.io.IOException;
import java.util.Iterator;
import java.util.regex.Pattern;
/**
* Runs any install services found in a package after it is installed, and any uninstall services found in a package
* prior to it being uninstalled.
*/
public class PackageInstallProcessor extends AbstractInvokeChainProcessor {
/**
* The service used to install packages, which after invocation is when any detected package install services are invoked by this processor.
*/
public static final String INTEGRATION_SERVER_PACKAGE_NAMESPACE = "wm.server.packages";
/**
* The service used to install packages, which after invocation is when any detected package install services are invoked by this processor.
*/
public static final String INTEGRATION_SERVER_PACKAGE_INSTALL_SERVICE = INTEGRATION_SERVER_PACKAGE_NAMESPACE + ":packageInstall";
/**
* The service used to recover packages, which after invocation is when any detected package install services are invoked by this processor.
*/
public static final String INTEGRATION_SERVER_PACKAGE_RECOVER_SERVICE = INTEGRATION_SERVER_PACKAGE_NAMESPACE + ":packageRecover";
/**
* The service used to uninstall packages, which before invocation is when any detected package uninstall services are invoked by this processor.
*/
public static final String INTEGRATION_SERVER_PACKAGE_UNINSTALL_SERVICE = INTEGRATION_SERVER_PACKAGE_NAMESPACE + ":packageDelete";
/**
* The default package install service regular expression pattern.
*/
public static final Pattern DEFAULT_PACKAGE_INSTALL_SERVICE_PATTERN = Pattern.compile("^([^\\.]+\\.)*support(\\.[^\\.]+)*:install$");
/**
* The default package uninstall service regular expression pattern.
*/
public static final Pattern DEFAULT_PACKAGE_UNINSTALL_SERVICE_PATTERN = Pattern.compile("^([^\\.]+\\.)*support(\\.[^\\.]+)*:uninstall$");
/**
* A regular expression pattern used to detect package install services.
*/
protected volatile Pattern installServicePattern, uninstallServicePattern;
/**
* Initialization on demand holder idiom.
*/
private static class Holder {
/**
* The singleton instance of the class.
*/
private static final PackageInstallProcessor INSTANCE = new PackageInstallProcessor();
}
/**
* Constructs a new PackageInstallProcessor using the default package install and uninstall service patterns.
*/
public PackageInstallProcessor() {
this(DEFAULT_PACKAGE_INSTALL_SERVICE_PATTERN, DEFAULT_PACKAGE_UNINSTALL_SERVICE_PATTERN);
}
/**
* Constructs a new PackageInstallProcessor using the given package install service pattern.
*
* @param installServicePattern A regular expression pattern used to find package install services.
* @param uninstallServicePattern A regular expression pattern used to find package uninstall services..
*/
public PackageInstallProcessor(String installServicePattern, String uninstallServicePattern) {
setInstallServicePattern(installServicePattern);
setUninstallServicePattern(uninstallServicePattern);
}
/**
* Constructs a new PackageInstallProcessor using the given package install service pattern.
*
* @param installServicePattern A regular expression pattern used to find package install services.
* @param uninstallServicePattern A regular expression pattern used to find package uninstall services..
*
*/
public PackageInstallProcessor(Pattern installServicePattern, Pattern uninstallServicePattern) {
setInstallServicePattern(installServicePattern);
setUninstallServicePattern(uninstallServicePattern);
}
/**
* Returns the singleton instance of this class.
*
* @return The singleton instance of this class.
*/
public static PackageInstallProcessor getInstance() {
return Holder.INSTANCE;
}
/**
* Sets the pattern used to find install services in a package.
*
* @param installServicePattern The pattern used to find install services in a package.
*/
public void setInstallServicePattern(String installServicePattern) {
setInstallServicePattern(installServicePattern == null ? null : Pattern.compile(installServicePattern));
}
/**
* Sets the pattern used to find install services in a package.
*
* @param installServicePattern The pattern used to find install services in a package.
*/
public void setInstallServicePattern(Pattern installServicePattern) {
this.installServicePattern = installServicePattern;
}
/**
* Sets the pattern used to find uninstall services in a package.
*
* @param uninstallServicePattern The pattern used to find uninstall services in a package.
*/
public void setUninstallServicePattern(String uninstallServicePattern) {
setUninstallServicePattern(uninstallServicePattern == null ? null : Pattern.compile(uninstallServicePattern));
}
/**
* Sets the pattern used to find uninstall services in a package.
*
* @param uninstallServicePattern The pattern used to find uninstall services in a package.
*/
public void setUninstallServicePattern(Pattern uninstallServicePattern) {
this.uninstallServicePattern = uninstallServicePattern;
}
/**
* Process the invocation chain: if invocation is a package install, run package install services afterwards; if
* the invocation is a package uninstall, run package uninstall services before.
*
* @param iterator Invocation chain.
* @param baseService The invoked service.
* @param pipeline The input pipeline for the service.
* @param serviceStatus The status of the service invocation.
* @throws ServerException If the service invocation fails.
*/
@Override
public void process(Iterator iterator, BaseService baseService, IData pipeline, ServiceStatus serviceStatus) throws ServerException {
Pattern installServicePattern = this.installServicePattern, uninstallServicePattern = this.uninstallServicePattern;
String serviceName = baseService.getNSName().getFullName();
if (serviceName.startsWith(INTEGRATION_SERVER_PACKAGE_NAMESPACE)) {
String packageName = null;
boolean isPackageInstall = serviceName.equals(INTEGRATION_SERVER_PACKAGE_INSTALL_SERVICE) && installServicePattern != null;
boolean isPackageRecover = serviceName.equals(INTEGRATION_SERVER_PACKAGE_RECOVER_SERVICE) && installServicePattern != null;
boolean isPackageUninstall = serviceName.equals(INTEGRATION_SERVER_PACKAGE_UNINSTALL_SERVICE) && uninstallServicePattern != null;
if (isPackageInstall) {
String packageInstallFileName = IDataHelper.get(pipeline, "file", String.class);
if (packageInstallFileName != null) {
File packageInstallFile = new File(Server.getPkgInDir(), packageInstallFileName);
try {
packageName = PackageReplicator.getTargetPackageName(packageInstallFileName, packageInstallFile);
} catch (IOException ex) {
// do nothing
}
}
} else if (isPackageRecover || isPackageUninstall) {
packageName = IDataHelper.get(pipeline, "package", String.class);
}
// run any uninstall services found in the package being uninstalled
if (isPackageUninstall && packageName != null) {
Package pkg = PackageManager.getPackage(packageName);
if (pkg != null) {
for (Object item : IterableEnumeration.of(pkg.getState().getLoaded())) {
if (item != null) {
String service = item.toString();
if (uninstallServicePattern.matcher(service).matches()) {
try {
Service.doThreadInvoke(NSName.create(service), IDataFactory.create()).getIData();
} catch (Exception ex) {
// do nothing
}
}
}
}
}
}
super.process(iterator, baseService, pipeline, serviceStatus);
// run any install services found in the package being installed
if ((isPackageInstall || isPackageRecover) && packageName != null) {
Package pkg = PackageManager.getPackage(packageName);
if (pkg != null) {
for (Object item : IterableEnumeration.of(pkg.getState().getLoaded())) {
if (item != null) {
String service = item.toString();
if (installServicePattern.matcher(service).matches()) {
try {
Service.doThreadInvoke(NSName.create(service), IDataFactory.create()).getIData();
} catch (Exception ex) {
// do nothing
}
}
}
}
}
}
} else {
super.process(iterator, baseService, pipeline, serviceStatus);
}
}
}