/*******************************************************************************
* Copyright (c) 2009, 2010 Innovation Gate GmbH.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Innovation Gate GmbH - initial API and implementation
******************************************************************************/
package de.innovationgate.eclipse.wgadesigner.editors.helpers;
import java.io.File;
import java.io.FilenameFilter;
import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
import java.util.Properties;
import java.util.zip.ZipException;
import org.apache.commons.vfs.FileObject;
import org.apache.commons.vfs.FileSystemException;
import org.apache.commons.vfs.FileSystemManager;
import org.apache.commons.vfs.VFS;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IFolder;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResourceDelta;
import org.eclipse.core.resources.IResourceDeltaVisitor;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.core.runtime.Path;
import de.innovationgate.eclipse.utils.Activator;
import de.innovationgate.eclipse.utils.FileUtils;
import de.innovationgate.eclipse.wgadesigner.WGADesignerPlugin;
import de.innovationgate.utils.WGUtils;
import de.innovationgate.wga.common.beans.csconfig.v1.Version;
/**
* bean representing a wga deployment
* provides file system paths to webapps dir and workdirs
*
*
*/
public class WGADeployment {
private File _baseDir;
private File _webappDir;
private File _workDir;
private File _defaultPluginsDir;
public WGADeployment( File baseDir) {
_baseDir = baseDir;
_webappDir = new File(_baseDir, "webapp");
_workDir = new File(_baseDir, "work");
_defaultPluginsDir = new File(_baseDir, "defaultPlugins");
if (!_webappDir.exists()) {
_webappDir.mkdir();
}
if (!_workDir.exists()) {
_workDir.mkdir();
}
if (!_defaultPluginsDir.exists()) {
_defaultPluginsDir.mkdir();
}
}
public File getWebappDir() {
return _webappDir;
}
public File getWorkDir() {
return _workDir;
}
public void updateWGA(File wgaWarOrFolder, IProgressMonitor monitor) throws ZipException, IOException {
if (monitor == null) {
monitor = new NullProgressMonitor();
}
try {
monitor.beginTask("Updating wga deployment.", 3);
monitor.setTaskName("Deleting workdir " + _workDir.getAbsolutePath() + "'.");
// cleanup workdir
WGUtils.delTree(_workDir, false);
monitor.worked(1);
monitor.setTaskName("Removing wga deployment " + _webappDir.getAbsolutePath() + "'.");
// remove wga deployment
WGUtils.delTree(_webappDir, false);
monitor.worked(1);
monitor.setTaskName("Deploying wga from location '" + wgaWarOrFolder.getAbsolutePath() + "'.");
// deploy wga
File target = getDeployDir();
if (!target.exists()) {
target.mkdir();
if (wgaWarOrFolder.isFile() && wgaWarOrFolder.getName().endsWith(".war")) {
FileUtils.unzip(wgaWarOrFolder, target);
} else if (wgaWarOrFolder.isDirectory()){
WGUtils.copyDirContent(wgaWarOrFolder, target);
}
}
monitor.worked(1);
} finally {
monitor.done();
}
}
public File getDeployDir() {
return new File(_webappDir, "ROOT");
}
public String getContextPath() {
// wga is deployed as root app - if this will be changed in future
// context path has to adapted accordingly
return "";
}
/**
* updates the wga deployment with the given resource delta
* the resource delta should start at project level
* @param delta
* @param monitor
* @throws ZipException
* @throws IOException
* @throws CoreException
*/
public void updateWGA(IResourceDelta projectDelta, IProgressMonitor monitor) throws CoreException {
if (monitor == null) {
monitor = new NullProgressMonitor();
}
try {
monitor.beginTask("Incremental updating wga deployment.", 1);
IResourceDelta delta = projectDelta.findMember(new Path("WebContent"));
if (delta != null) {
IResourceDeltaVisitor visitor = new IResourceDeltaVisitor() {
public boolean visit(IResourceDelta delta) throws CoreException {
if (delta.getResource() != null) {
if (delta.getResource() instanceof IFile) {
IFile file = (IFile)delta.getResource();
String absolutePath = file.getLocation().toString();
// make path relative to WebContent folder
int pos = absolutePath.lastIndexOf("WebContent/");
if (pos != -1) {
String relativePathToFile = absolutePath.substring(pos + "WebContent/".length());
File targetFile = new File(getDeployDir(), relativePathToFile);
File sourceFile = file.getLocation().toFile();
if (delta.getKind() == IResourceDelta.ADDED || delta.getKind() == IResourceDelta.CHANGED) {
try {
if (WGADesignerPlugin.getDefault().isDebugging()) {
System.out.println("Updating resource '" + targetFile.getAbsolutePath() + "' of deployment '" + getName() + "'.");
}
// ensure that target folder exists
if (!targetFile.getParentFile().exists()) {
targetFile.getParentFile().mkdirs();
}
FileUtils.copy(sourceFile, targetFile);
} catch (IOException e) {
WGADesignerPlugin.getDefault().logError("Unable to update resource '" + targetFile.getAbsolutePath() + "' in wga deployment '" + getName() + "'. Deployment is out of sync.");
}
} else if (delta.getKind() == IResourceDelta.REMOVED) {
if (targetFile.exists()) {
if (WGADesignerPlugin.getDefault().isDebugging()) {
System.out.println("Deleting resource '" + targetFile.getAbsolutePath() + "' of deployment '" + getName() + "'.");
}
if (!targetFile.delete()) {
WGADesignerPlugin.getDefault().logError("Unable to delete resource '" + targetFile.getAbsolutePath() + "' in wga deployment '" + getName() + "'. Deployment is out of sync.");
}
}
}
} else {
// invalid resource - should not happen - ignore
}
} else if (delta.getResource() instanceof IFolder) {
IFolder folder = (IFolder)delta.getResource();
String absolutePath = folder.getLocation().toString();
// make path relative to WebContent folder
int pos = absolutePath.lastIndexOf("WebContent/");
if (pos != -1) {
String relativePathToFolder = absolutePath.substring(pos + "WebContent/".length());
File targetFolder = new File(getDeployDir(), relativePathToFolder);
if (delta.getKind() == IResourceDelta.ADDED) {
if (WGADesignerPlugin.getDefault().isDebugging()) {
System.out.println("Creating folder '" + targetFolder.getAbsolutePath() + "' in deployment '" + getName() + "'.");
}
targetFolder.mkdirs();
} else if (delta.getKind() == IResourceDelta.REMOVED) {
if (WGADesignerPlugin.getDefault().isDebugging()) {
System.out.println("Deleting folder '" + targetFolder.getAbsolutePath() + "' of deployment '" + getName() + "'.");
}
if (targetFolder.exists()) {
WGUtils.delTree(targetFolder);
}
}
} else {
// invalid resource - should not happen - ignore
}
}
}
// continue with children
return true;
}
};
delta.accept(visitor);
}
monitor.worked(1);
} finally {
monitor.done();
}
}
/**
* checks if the installation has a valid wga deployment
* @return
*/
public boolean isDeployed() {
return getDeployDir().exists();
}
public static boolean isWGAVersionSupported(File wgaWar) {
InputStream propIn = null;
try {
FileSystemManager fsManager = VFS.getManager();
FileObject propFile = fsManager.resolveFile( "zip:" + wgaWar.toURI() + "!/WEB-INF/wgabuild.properties");
propIn = propFile.getURL().openStream();
Version version = WGADeployment.determineWGAVersion(propIn);
if (version != null) {
if (version.isAtLeast(Activator.SUPPORTED_WGA_VERSION_MIN.getMajor(), Activator.SUPPORTED_WGA_VERSION_MIN.getMinor())) {
if (version.getMajorVersion() < Activator.SUPPORTED_WGA_VERSION_MAX.getMajor()) {
return true;
} else if (version.getMajorVersion() == Activator.SUPPORTED_WGA_VERSION_MAX.getMajor()) {
return version.getMinorVersion() <= Activator.SUPPORTED_WGA_VERSION_MAX.getMinor();
} else {
return false;
}
} else {
return false;
}
}
} catch (FileSystemException e) {
} catch (IOException e) {
} finally {
if (propIn != null) {
try {
propIn.close();
} catch (IOException e) {
}
}
}
return true;
}
public String getName() {
return _baseDir.getName();
}
public String getWGAVersionString() {
String wgaVersion = "n.a.";
Version version = getWGAVersion();
if (version != null) {
wgaVersion = version.getMainVersionString();
}
return wgaVersion;
}
public Version getWGAVersion() {
if (isDeployed()) {
try {
return determineWGAVersion();
} catch (Exception e) {
return null;
}
}
return null;
}
public static String determineWGAVersion(InputStream wgabuildProperties, String delimiter, boolean includeMinorVersion, boolean includeMaintenanceVersion) throws IOException {
Version versionObj = determineWGAVersion(wgabuildProperties);
StringBuffer version = new StringBuffer();
version.append(versionObj.getMajorVersion());
if (includeMinorVersion) {
version.append(delimiter);
version.append(versionObj.getMinorVersion());
}
if (includeMaintenanceVersion) {
version.append(delimiter);
version.append(versionObj.getMaintenanceVersion());
}
return version.toString();
}
public static Version determineWGAVersion(InputStream wgabuildProperties) throws IOException {
Properties props = new Properties();
props.load(wgabuildProperties);
Version version = new Version();
if (props.getProperty("majorVersion") != null) {
version.setMajorVersion(Integer.parseInt(props.getProperty("majorVersion")));
}
if (props.getProperty("minorVersion") != null) {
version.setMinorVersion(Integer.parseInt(props.getProperty("minorVersion")));
}
if (props.getProperty("maintenanceVersion") != null) {
version.setMaintenanceVersion(Integer.parseInt(props.getProperty("maintenanceVersion")));
}
if (props.getProperty("patchVersion") != null) {
version.setPatchVersion(Integer.parseInt(props.getProperty("patchVersion")));
}
if (props.getProperty("buildVersion") != null) {
version.setBuildVersion(Integer.parseInt(props.getProperty("buildVersion")));
}
return version;
}
public Version determineWGAVersion() throws IOException, ClassNotFoundException, IllegalArgumentException, SecurityException, IllegalAccessException, NoSuchFieldException {
File classesDir = new File(getDeployDir(), "WEB-INF/classes");
URLClassLoader loader = new URLClassLoader(new URL[] {classesDir.toURL()}, this.getClass().getClassLoader());
Class wgaVersionClass = loader.loadClass("de.innovationgate.wgpublisher.WGAVersion");
Version version = new Version();
version.setMajorVersion(wgaVersionClass.getDeclaredField("WGAPUBLISHER_MAJOR_VERSION").getInt(null));
version.setMinorVersion(wgaVersionClass.getDeclaredField("WGAPUBLISHER_MINOR_VERSION").getInt(null));
version.setMaintenanceVersion(wgaVersionClass.getDeclaredField("WGAPUBLISHER_MAINTENANCE_VERSION").getInt(null));
version.setPatchVersion(wgaVersionClass.getDeclaredField("WGAPUBLISHER_PATCH_VERSION").getInt(null));
version.setBuildVersion(wgaVersionClass.getDeclaredField("WGAPUBLISHER_BUILD_VERSION").getInt(null));
return version;
}
public String toString() {
return getName() + " (" + getWGAVersionString() + ")";
}
public File getBaseDir() {
return _baseDir;
}
public void addDefaultPlugin(File pluginFile) throws IOException {
FileUtils.copy(pluginFile, new File(_defaultPluginsDir, pluginFile.getName()));
}
public boolean removeDefaultPlugin(String pluginFileName) {
File pluginFile = new File(_defaultPluginsDir, pluginFileName);
if (pluginFile.exists()) {
return pluginFile.delete();
} else {
return false;
}
}
public File getDefaultPluginsDir() {
return _defaultPluginsDir;
}
public List<File> getDefaultPluginFiles() {
File[] pluginFiles = getDefaultPluginsDir().listFiles(new FilenameFilter() {
public boolean accept(File dir, String name) {
return name.endsWith(".wgaplugin");
}
});
return Arrays.asList(pluginFiles);
}
public List<String> getDefaultPluginNames() {
List<String> pluginNames = new ArrayList<String>();
Iterator<File> files = getDefaultPluginFiles().iterator();
while (files.hasNext()) {
File file = files.next();
pluginNames.add(file.getName());
}
return pluginNames;
}
public void updateWGA(IProject project, IProgressMonitor monitor) throws ZipException, IOException {
updateWGA(project.getFolder("WebContent").getLocation().toFile(), monitor);
}
/**
* checks if this deployment is configurable
* @return
*/
public boolean isConfigurable() {
if (!isDeployed()) {
return false;
}
try {
File wgutils = new File(getWebappDir(), "libs/wgutils.jar");
URL[] jars = new URL[1];
jars[0] = wgutils.toURL();
URLClassLoader classLoader = new URLClassLoader(jars);
Class factoryClass = classLoader.loadClass("de.innovationgate.wga.config.WGAConfigurationFactory");
} catch (MalformedURLException e) {
return false;
} catch (ClassNotFoundException e) {
return false;
}
return true;
}
public boolean isWorkspaceDeployment() {
return WGADesignerPlugin.getDefault().getWGADeploymentManager().isProjectDeployment(this);
}
public void setUpdateURL(String url) {
WGADesignerPlugin.getDefault().getPreferenceStore().setValue(getPrefKeyPrefix() + "updateURL", url);
}
public String getUpdateURL() {
return WGADesignerPlugin.getDefault().getPreferenceStore().getString(getPrefKeyPrefix() + "updateURL");
}
private String getPrefKeyPrefix() {
return "WGADeployment.preferences." + getName() + ".";
}
}