org.eclipse.virgo.ide.runtime.internal.core.ServerPublishOperation.java Source code

Java tutorial

Introduction

Here is the source code for org.eclipse.virgo.ide.runtime.internal.core.ServerPublishOperation.java

Source

/*******************************************************************************
 * Copyright (c) 2009, 2010 SpringSource, a divison of VMware, Inc.
 * 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:
 *     SpringSource, a division of VMware, Inc. - initial API and implementation
 *******************************************************************************/
package org.eclipse.virgo.ide.runtime.internal.core;

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.Writer;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IAdaptable;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.jst.server.core.PublishUtil;
import org.eclipse.virgo.ide.facet.core.FacetCorePlugin;
import org.eclipse.virgo.ide.facet.core.FacetUtils;
import org.eclipse.virgo.ide.manifest.core.BundleManifestCorePlugin;
import org.eclipse.virgo.ide.module.core.ServerModuleDelegate;
import org.eclipse.virgo.ide.runtime.core.ServerUtils;
import org.eclipse.wst.server.core.IModule;
import org.eclipse.wst.server.core.IServer;
import org.eclipse.wst.server.core.ServerUtil;
import org.eclipse.wst.server.core.model.IModuleFile;
import org.eclipse.wst.server.core.model.IModuleFolder;
import org.eclipse.wst.server.core.model.IModuleResource;
import org.eclipse.wst.server.core.model.IModuleResourceDelta;
import org.eclipse.wst.server.core.model.PublishOperation;
import org.eclipse.wst.server.core.model.ServerBehaviourDelegate;
import org.eclipse.wst.sse.core.StructuredModelManager;
import org.eclipse.wst.sse.core.internal.provisional.IStructuredModel;
import org.eclipse.wst.xml.core.internal.document.DOMModelImpl;
import org.eclipse.wst.xml.core.internal.provisional.document.IDOMDocument;
import org.springframework.ide.eclipse.beans.core.internal.model.namespaces.DelegatingNamespaceHandlerResolver;
import org.springframework.ide.eclipse.beans.core.namespaces.NamespaceUtils;
import org.springframework.ide.eclipse.core.java.JdtUtils;
import org.springframework.util.AntPathMatcher;
import org.springframework.util.StringUtils;

import org.eclipse.virgo.util.osgi.manifest.BundleManifest;
import org.eclipse.virgo.util.osgi.manifest.BundleManifestFactory;

/**
 * {@link PublishOperation} extension that deals with deploy, clean and refresh of dm Server modules.
 * @author Christian Dupuis
 * @since 1.0.0
 */
@SuppressWarnings("restriction")
public class ServerPublishOperation extends PublishOperation {

    private int deltaKind;

    private int kind;

    private IModule[] modules;

    private ServerBehaviour server;

    public ServerPublishOperation(ServerBehaviour server, int kind, IModule[] module, int deltaKind) {
        super("Publish to server", "Publish module to SpringSource dm Server");
        this.server = server;
        this.kind = kind;
        this.modules = module;
        this.deltaKind = deltaKind;
    }

    @Override
    public void execute(IProgressMonitor monitor, IAdaptable info) throws CoreException {
        boolean shouldRedeploy = false;
        List<IStatus> status = new ArrayList<IStatus>();
        if (modules.length == 1) {
            shouldRedeploy = publishModule(modules[0], status, monitor);
        }

        boolean shouldReployChild = false;
        IProject project = modules[0].getProject();
        if (!FacetUtils.isBundleProject(project) && !FacetUtils.isParProject(project)
                && ServerUtils.getServer(server).getChildModules(modules) != null
                && !FacetUtils.isPlanProject(project)) {
            for (IModule module : ServerUtils.getServer(server).getChildModules(modules)) {
                if (publishJar(module, status, monitor)) {
                    shouldReployChild = true;
                }
            }
        }

        if (shouldRedeploy || shouldReployChild) {
            server.getServerDeployer().redeploy(modules[0]);
        }

        server.onModulePublishStateChange(modules, IServer.PUBLISH_STATE_NONE);
    }

    @Override
    public int getKind() {
        return REQUIRED;
    }

    @Override
    public int getOrder() {
        return 0;
    }

    /**
     * Checks if the given <code>file</code> is a root node that is a known Spring namespace.
     */
    private boolean checkIfSpringConfigurationFile(IFile file) {
        IStructuredModel model = null;
        try {
            model = StructuredModelManager.getModelManager().getExistingModelForRead(file);
            if (model == null) {
                model = StructuredModelManager.getModelManager().getModelForRead(file);
            }
            if (model != null) {
                IDOMDocument document = ((DOMModelImpl) model).getDocument();
                if (document != null && document.getDocumentElement() != null) {
                    String namespaceUri = document.getDocumentElement().getNamespaceURI();
                    if (NamespaceUtils.DEFAULT_NAMESPACE_URI.equals(namespaceUri)
                            || new DelegatingNamespaceHandlerResolver(
                                    JdtUtils.getClassLoader(file.getProject(), null), null)
                                            .resolve(namespaceUri) != null) {
                        return false;
                    }
                }
            }
        } catch (Exception e) {
        } finally {
            if (model != null) {
                model.releaseFromRead();
            }
            model = null;
        }
        return true;
    }

    /**
     * Check if resource delta only contains static resources
     */
    private boolean onlyStaticResources(IModuleResourceDelta delta, Set<IModuleFile> files) {
        if (delta.getModuleResource() instanceof IModuleFolder) {
            for (IModuleResourceDelta child : delta.getAffectedChildren()) {
                if (!onlyStaticResources(child, files)) {
                    return false;
                }
            }
            return true;
        } else {
            if (delta.getModuleResource() instanceof IModuleFile) {
                files.add((IModuleFile) delta.getModuleResource());
            }
            String name = delta.getModuleResource().getName();

            // make that configurable
            if (name.endsWith(".xml")) {
                IFile file = (IFile) delta.getModuleResource().getAdapter(IFile.class);
                // check for spring context xml files first but exclude
                if (!checkIfSpringConfigurationFile(file)) {
                    return false;
                }
            }
            boolean isStatic = false;
            // Check the configuration options for static resources
            AntPathMatcher matcher = new AntPathMatcher();
            for (String pattern : StringUtils
                    .delimitedListToStringArray(ServerUtils.getServer(server).getStaticFilenamePatterns(), ",")) {
                if (pattern.startsWith("!") && matcher.match(pattern.substring(1), name)) {
                    isStatic = false;
                } else if (matcher.match(pattern, name)) {
                    isStatic = true;
                }
            }
            return isStatic;
        }
    }

    private boolean publishJar(IModule module, List<IStatus> status, IProgressMonitor monitor)
            throws CoreException {
        IPath path = server.getModuleDeployDirectory(modules[0]).append("WEB-INF").append("lib");
        IPath zipPath = path.append(module.getName() + ".jar");

        if (kind == IServer.PUBLISH_CLEAN || deltaKind == ServerBehaviourDelegate.REMOVED) {
            if (zipPath.toFile().exists()) {
                zipPath.toFile().delete();
            }

            if (deltaKind == ServerBehaviourDelegate.REMOVED) {
                return false;
            }
        }
        if (kind != IServer.PUBLISH_CLEAN && kind != IServer.PUBLISH_FULL) {
            IModuleResourceDelta[] delta = server.getPublishedResourceDelta(new IModule[] { modules[0], module });
            if (delta == null || delta.length == 0) {
                return false;
            }
        }

        if (!path.toFile().exists()) {
            path.toFile().mkdirs();
        }

        PublishUtil.publishZip(server.getResources(new IModule[] { modules[0], module }), zipPath, monitor);
        return true;
    }

    /**
     * Creates a dummy manifest for WTP Dynamic Web Projects only
     */
    private void publishManifest(IModule module, IPath path) {

        if (FacetUtils.hasProjectFacet(module.getProject(), FacetCorePlugin.WEB_FACET_ID)) {
            File manifestFile = path.append(BundleManifestCorePlugin.MANIFEST_FOLDER_NAME)
                    .append(BundleManifestCorePlugin.MANIFEST_FILE_NAME).toFile();
            if (manifestFile.exists()) {
                return;
            }
            BundleManifest manifest = BundleManifestFactory.createBundleManifest();
            Writer writer = null;
            try {
                manifestFile.getParentFile().mkdirs();
                writer = new FileWriter(manifestFile);
                manifest.write(writer);
            } catch (IOException e) {
            } finally {
                if (writer != null) {
                    try {
                        writer.flush();
                        writer.close();
                    } catch (IOException e) {
                    }
                }
            }
        }
    }

    private boolean publishModule(IModule module, List<IStatus> status, IProgressMonitor monitor)
            throws CoreException {
        IPath path = server.getModuleDeployDirectory(module);

        if (deltaKind == ServerBehaviourDelegate.REMOVED) {
            File f = path.toFile();
            if (ServerUtils.getServer(server).getServer().getServerState() == IServer.STATE_STARTED) {
                server.getServerDeployer().undeploy(module);
            }
            if (f.exists() && !path.equals(server.getServerDeployDirectory())) {
                PublishUtil.deleteDirectory(f, new NullProgressMonitor());
            }

            if (module.getModuleType().getId().equals(FacetCorePlugin.PLAN_FACET_ID)) {
                // Delete the plan file
                path = path.append(module.getId().substring(module.getId().lastIndexOf('/')));
                File planFile = path.toFile();
                if (planFile.exists()) {
                    planFile.delete();
                }

                // Delete all child modules that are not being used anymore
                ServerModuleDelegate planModule = (ServerModuleDelegate) module
                        .loadAdapter(ServerModuleDelegate.class, null);
                IServer s = server.getServer();
                for (IModule childModule : planModule.getChildModules()) {
                    if (!ServerUtil.containsModule(s, childModule, monitor)) {
                        IPath modulePath = server.getModuleDeployDirectory(childModule);
                        File moduleFile = modulePath.toFile();
                        if (moduleFile.exists()) {
                            PublishUtil.deleteDirectory(moduleFile, new NullProgressMonitor());
                        }
                    }
                }
            }

            return false;
        }

        if (kind == IServer.PUBLISH_CLEAN || kind == IServer.PUBLISH_FULL) {
            IModuleResource[] mr = server.getResources(modules);
            status.addAll(Arrays.asList(PublishUtil.publishFull(mr, path, monitor)));
            // Hack to get a MANIFEST.MF into the deployment area
            publishManifest(module, path);

            if (ServerUtils.getServer(server).getServer().getServerState() == IServer.STATE_STARTED) {
                // redeploy
                return true;
            }
            return false;
        }

        IModuleResourceDelta[] delta = server.getPublishedResourceDelta(modules);
        for (IModuleResourceDelta d : delta) {
            status.addAll(Arrays.asList(PublishUtil.publishDelta(d, path, monitor)));
        }

        publishManifest(module, path);

        if (ServerUtils.getServer(server).getServer().getServerState() == IServer.STATE_STARTED
                && deltaKind != ServerBehaviourDelegate.NO_CHANGE) {

            Set<IModuleFile> files = new HashSet<IModuleFile>();
            // first check if only static resources are changed
            boolean onlyStaticResources = true;
            for (IModuleResourceDelta d : delta) {
                if (!onlyStaticResources(d, files)) {
                    onlyStaticResources = false;
                    // don't break to get a full set of all files
                }
            }

            if (!onlyStaticResources) {
                // redeploy
                return true;
            } else {
                // refresh static resources
                for (IModuleFile file : files) {
                    server.getServerDeployer().refreshStatic(module, file);
                }
            }
        }
        return false;
    }

}