/*******************************************************************************
* 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.util.ArrayList;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
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.IFolder;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResourceChangeEvent;
import org.eclipse.core.resources.IResourceChangeListener;
import org.eclipse.core.resources.IResourceDelta;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.core.runtime.Path;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.jobs.Job;
import de.innovationgate.eclipse.utils.WorkbenchUtils;
import de.innovationgate.eclipse.wgadesigner.WGADesignerPlugin;
import de.innovationgate.eclipse.wgadesigner.classpath.WGADeploymentLibrarySet;
import de.innovationgate.utils.WGUtils;
import de.innovationgate.wga.common.beans.csconfig.v1.Version;
/**
* manager for wga deployment
* A WGARuntime can choose the wga deployment to use for the current environment.
*
*
*/
public class WGADeploymentManager implements IResourceChangeListener {
// base directory for all manager work
private File _baseDir;
//private String _defaultDeploymentName;
public static final String DEFAULT_DEPLOYMENT_NAME = "default";
public static final String DEFAULT_DEPLOYMENT_PREFIX = "wga";
private Set<WGADeploymentsListener> _listeners = new HashSet<WGADeploymentsListener>();
//private static final String WGA_PROJECT_DEPLOYMENT_PREFIX = "PRJ_";
public WGADeploymentManager() {
}
public void init(File baseDir) throws ZipException, IOException {
_baseDir = baseDir;
if (!_baseDir.exists()) {
_baseDir.mkdirs();
}
// check deployments for local CVS wga versions
IProject[] projects = ResourcesPlugin.getWorkspace().getRoot().getProjects();
for (IProject project : projects) {
if (project.isAccessible() && isWGAPublisherProject(project)) {
WGADeployment deployment = getDeployment(project.getName());
if (deployment != null) {
deployment.updateWGA(project, new NullProgressMonitor());
} else {
createDeployment(project, new NullProgressMonitor());
}
}
}
// register an libraryset for each deployment which is not a workspace
Iterator<WGADeployment> deployments = getDeployments().iterator();
while (deployments.hasNext()) {
WGADeployment deployment = deployments.next();
WGADeploymentLibrarySet librarySet = new WGADeploymentLibrarySet(deployment);
WGADesignerPlugin.getDefault().getLibrarySets().put(librarySet.getId(), librarySet);
}
ResourcesPlugin.getWorkspace().addResourceChangeListener(this, IResourceChangeEvent.PRE_BUILD|IResourceChangeEvent.PRE_DELETE);
}
public void createOrUpdateDefaultDeployment(File defaultWGAWar, IProgressMonitor monitor) throws FileSystemException, IOException, ZipException {
if (monitor == null) {
monitor = new NullProgressMonitor();
}
FileSystemManager fsManager = VFS.getManager();
FileObject propFile = fsManager.resolveFile( "zip:" + defaultWGAWar.toURI() + "!/WEB-INF/wgabuild.properties");
//_defaultDeploymentName = DEFAULT_DEPLOYMENT_PREFIX + WGADeployment.determineWGAVersion(propFile.getURL().openStream(), "_", true, false);
// init default wga installation
// check if we already have a deployment with same major, minor version
WGADeployment existingDefaultDeployment = getDeployment(DEFAULT_DEPLOYMENT_NAME);
if (existingDefaultDeployment != null) {
InputStream propIn = null;
try {
propIn = propFile.getURL().openStream();
Version newDefaultDeploymentVersion = WGADeployment.determineWGAVersion(propIn);
Version existingDefaultDeploymentVersion = existingDefaultDeployment.getWGAVersion();
if (!newDefaultDeploymentVersion.equals(existingDefaultDeploymentVersion)) {
// we have to update the default deployment
createDeployment(DEFAULT_DEPLOYMENT_NAME, defaultWGAWar, monitor, true);
}
} finally {
if (propIn != null) {
try {
propIn.close();
} catch (IOException e) {
}
}
}
} else {
// no deployment with this version yet
createDeployment(DEFAULT_DEPLOYMENT_NAME, defaultWGAWar, monitor, true);
}
// add default plugins to default deployment
File[] plugins = WGADesignerPlugin.getDefault().getWgaDefaultPluginsDir().listFiles(new FilenameFilter() {
public boolean accept(File dir, String name) {
return name.endsWith(".wgaplugin");
}
});
for (File pluginFile : plugins) {
getDefaultDeployment().addDefaultPlugin(pluginFile);
}
}
public void resourceChanged(IResourceChangeEvent event) {
if (event.getType() == IResourceChangeEvent.PRE_BUILD) {
IResourceDelta[] projectDeltas = event.getDelta().getAffectedChildren();
for (IResourceDelta projectDelta : projectDeltas) {
IProject project = (IProject) projectDelta.getResource();
if (isWGAPublisherProject(project)) {
try {
WorkbenchUtils.addBuilder(project, WGADesignerPlugin.BUILDER_WGA_DEPLOYMENTS);
} catch (Exception e) {
WGADesignerPlugin.getDefault().getLog().log(new Status(Status.ERROR, WGADesignerPlugin.PLUGIN_ID, "Unable to add wga deployment builder to project '" + project.getName() + "'.", e));
}
}
}
} else if (event.getType() == IResourceChangeEvent.PRE_DELETE) {
IProject project = (IProject) event.getResource();
if (isWGAPublisherProject(project)) {
final WGADeployment deployment = getDeployment(project.getName());
if (deployment != null) {
Job job = new Job("Removing WGA Deployment '" + deployment.getName() + "'.") {
@Override
protected IStatus run(IProgressMonitor monitor) {
removeDeployment(deployment, monitor);
return Status.OK_STATUS;
}
};
job.setPriority(Job.SHORT);
job.schedule();
}
}
}
}
/**
* checks if this deployment represents a lokal (cvs checkedout( WGAPublisher project
* @param deployment
* @return
*/
public boolean isProjectDeployment(WGADeployment deployment) {
IProject project = ResourcesPlugin.getWorkspace().getRoot().getProject(deployment.getName());
if (project != null && isWGAPublisherProject(project)) {
return true;
} else {
return false;
}
}
private boolean isWGAPublisherProject(IProject project) {
IFolder webContent = project.getFolder("WebContent");
if (webContent.exists()) {
IFolder webinf = webContent.getFolder("WEB-INF");
if (webinf.exists() && webinf.exists(new Path("web.xml"))) {
// TODO check web.xml for WGACore
return true;
}
}
return false;
}
/**
* returns the wga deployment of the given name
* @param name
* @return
*/
public WGADeployment getDeployment(String name) {
Iterator<WGADeployment> deployments = getDeployments().iterator();
while (deployments.hasNext()) {
WGADeployment deployment = deployments.next();
if (deployment.getName().equals(name)) {
return deployment;
}
}
return null;
}
public WGADeployment getDefaultDeployment() {
return getDeployment(getDefaultDeploymentName());
}
public boolean hasDeployment(String name) {
return getDeployment(name) != null;
}
/**
* creates a new wga deployment with the given name and wga.war if it does not exists
* note: no update is performed if deployment already exist
* @param name
* @param wgaWar
* @param monitor
* @return
* @throws ZipException
* @throws IOException
*/
public WGADeployment createDeployment(String name, File wgaWar, IProgressMonitor monitor) throws ZipException, IOException {
return createDeployment(name, wgaWar, monitor, false);
}
/**
* creates a new wga deployment with the given name and wga.war if it does not exists
* note: no update is performed if deployment already exist
* @param name
* @param wgaWar
* @param monitor
* @param forceUpdate
* @return
* @throws ZipException
* @throws IOException
*/
public WGADeployment createDeployment(String name, File wgaWar, IProgressMonitor monitor, boolean forceUpdate) throws ZipException, IOException {
File deploymentDir = new File(_baseDir, name);
if (!deploymentDir.exists()) {
deploymentDir.mkdir();
}
WGADeployment deployment = new WGADeployment(deploymentDir);
if (forceUpdate || !deployment.isDeployed()) {
deployment.updateWGA(wgaWar, monitor);
}
// register library set
WGADeploymentLibrarySet librarySet = new WGADeploymentLibrarySet(deployment);
WGADesignerPlugin.getDefault().getLibrarySets().put(librarySet.getId(), librarySet);
fireDeploymentsChanged();
return deployment;
}
/**
* creates a new wga deployment from an local project (WGAPublisher CVS-Version)
* note: no update is performed if deployment already exist
* @param project
* @param monitor
* @return
* @throws IOException
* @throws ZipException
*/
public WGADeployment createDeployment(IProject project, IProgressMonitor monitor) throws ZipException, IOException {
File deploymentDir = new File(_baseDir, project.getName());
if (!deploymentDir.exists()) {
deploymentDir.mkdir();
}
WGADeployment deployment = new WGADeployment(deploymentDir);
if (!deployment.isDeployed()) {
deployment.updateWGA(project.getFolder("WebContent").getLocation().toFile(), monitor);
}
// register library set
WGADeploymentLibrarySet librarySet = new WGADeploymentLibrarySet(deployment);
WGADesignerPlugin.getDefault().getLibrarySets().put(librarySet.getId(), librarySet);
fireDeploymentsChanged();
return deployment;
}
public List<WGADeployment> getDeployments() {
List<WGADeployment> deployments = new ArrayList<WGADeployment>();
File[] deploymentDirs = _baseDir.listFiles();
for (int i=0; i < deploymentDirs.length; i++) {
File deploymentDir = deploymentDirs[i];
if (deploymentDir.isDirectory() && !deploymentDir.isHidden()) {
deployments.add(new WGADeployment(deploymentDir));
}
}
return deployments;
}
public void removeDeployment(WGADeployment deployment, IProgressMonitor monitor) {
// if (deployment.getName().equals(getDefaultDeploymentName())) {
// throw new IllegalArgumentException("Default deployment cannot be removed.");
// }
if (monitor == null) {
monitor = new NullProgressMonitor();
}
try {
monitor.beginTask("Removing wga deployment '" + deployment.getBaseDir().getAbsolutePath() + "'.", 1);
WGUtils.delTree(deployment.getBaseDir());
// unregister library set
WGADeploymentLibrarySet librarySet = new WGADeploymentLibrarySet(deployment);
WGADesignerPlugin.getDefault().getLibrarySets().remove(librarySet.getId());
fireDeploymentsChanged();
monitor.worked(1);
} finally {
monitor.done();
}
}
public String getDefaultDeploymentName() {
return DEFAULT_DEPLOYMENT_NAME;
}
public void addListener(WGADeploymentsListener listener) {
_listeners.add(listener);
}
public void removeListener(WGADeploymentsListener listener) {
_listeners.remove(listener);
}
private void fireDeploymentsChanged() {
Iterator<WGADeploymentsListener> listeners = _listeners.iterator();
while (listeners.hasNext()) {
WGADeploymentsListener listener = listeners.next();
try {
listener.deploymentsChanged();
} catch (Exception e) {
WGADesignerPlugin.getDefault().logError("Unable to notify WGADeploymentListener '" + listener.getClass().getName() + "'.", e);
}
}
}
}