org.eclipse.edt.ide.deployment.rui.operation.CopyJavaRuntimeResourcesOperation.java Source code

Java tutorial

Introduction

Here is the source code for org.eclipse.edt.ide.deployment.rui.operation.CopyJavaRuntimeResourcesOperation.java

Source

/*******************************************************************************
 * Copyright  2012, 2013 IBM Corporation and others.
 * 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:
 * IBM Corporation - initial API and implementation
 *
 *******************************************************************************/
package org.eclipse.edt.ide.deployment.rui.operation;

import java.io.BufferedInputStream;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.HashSet;
import java.util.Set;
import java.util.jar.Attributes;
import java.util.jar.JarEntry;
import java.util.jar.JarOutputStream;
import java.util.jar.Manifest;
import java.util.zip.CRC32;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IFolder;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IResourceProxy;
import org.eclipse.core.resources.IResourceProxyVisitor;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.FileLocator;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Path;
import org.eclipse.core.runtime.Platform;
import org.eclipse.edt.ide.core.EDTCoreIDEPlugin;
import org.eclipse.edt.ide.core.EDTRuntimeContainer;
import org.eclipse.edt.ide.core.EDTRuntimeContainerEntry;
import org.eclipse.edt.ide.core.IGenerator;
import org.eclipse.edt.ide.deployment.core.model.RUIApplication;
import org.eclipse.edt.ide.deployment.operation.AbstractDeploymentOperation;
import org.eclipse.edt.ide.deployment.results.IDeploymentResultsCollector;
import org.eclipse.edt.ide.deployment.rui.Activator;
import org.eclipse.edt.ide.deployment.rui.internal.util.Utils;
import org.eclipse.edt.ide.deployment.solution.DeploymentContext;
import org.eclipse.edt.ide.deployment.utilities.DeploymentUtilities;
import org.eclipse.edt.ide.ui.internal.util.CoreUtility;
import org.eclipse.jdt.core.IClasspathEntry;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.JavaCore;
import org.osgi.framework.Bundle;
import org.osgi.framework.Version;

public class CopyJavaRuntimeResourcesOperation extends AbstractDeploymentOperation {

    private static final String WEBLIB_FOLDER = "WEB-INF/lib/"; //$NON-NLS-1$
    private static final String JAVA_RUNTIME_PROJECT = "org.eclipse.edt.runtime.java"; //$NON-NLS-1$
    private static final String ICU_PROJECT = "com.ibm.icu"; //$NON-NLS-1$

    private IFolder projectRootFolder;

    public void execute(DeploymentContext context, IDeploymentResultsCollector resultsCollector,
            IProgressMonitor monitor) throws CoreException {

        boolean deployedJavaRuntime = false;
        boolean deployedICU = false;
        projectRootFolder = Utils.getContextDirectory(context.getTargetProject());

        if (context.getSourceProject().hasNature(JavaCore.NATURE_ID)) {
            IJavaProject javaProject = JavaCore.create(context.getSourceProject());
            Set<IClasspathEntry> entries = new HashSet<IClasspathEntry>();
            getClasspathContainers(javaProject, new HashSet<IJavaProject>(10), entries);

            Set<EDTRuntimeContainer> toCopy = new HashSet<EDTRuntimeContainer>(entries.size());
            IGenerator[] generators = EDTCoreIDEPlugin.getPlugin().getGenerators();
            for (IGenerator gen : generators) {
                EDTRuntimeContainer[] containers = gen.getRuntimeContainers();
                for (EDTRuntimeContainer container : containers) {
                    IPath path = container.getPath();
                    for (IClasspathEntry entry : entries) {
                        if (entry.getPath().equals(path)) {
                            toCopy.add(container);
                            break;
                        }
                    }
                }
            }

            if (toCopy.size() > 0) {
                for (EDTRuntimeContainer container : toCopy) {
                    for (EDTRuntimeContainerEntry entry : container.getEntries()) {
                        IClasspathEntry cpEntry = entry.getClasspathEntry();
                        if (cpEntry == null) {
                            continue;
                        }

                        IPath path = cpEntry.getPath();
                        if (path != null) {
                            File file = path.toFile();
                            if (!file.exists()) {
                                continue;
                            }

                            // For the version, only keep major.minor.service, no qualifier.
                            Version version = new Version(entry.getBundleVersion());
                            StringBuilder bundleVersion = new StringBuilder(20);
                            bundleVersion.append(version.getMajor());
                            bundleVersion.append('.');
                            bundleVersion.append(version.getMinor());
                            bundleVersion.append('.');
                            bundleVersion.append(version.getMicro());

                            String targetPrefix = entry.getBundleId() + "_"; //$NON-NLS-1$
                            String targetName = targetPrefix + bundleVersion.toString() + ".jar"; //$NON-NLS-1$

                            if (!deployedJavaRuntime && targetPrefix.equals(JAVA_RUNTIME_PROJECT + "_")) { //$NON-NLS-1$
                                deployedJavaRuntime = true;
                            } else if (!deployedICU && targetPrefix.equals(ICU_PROJECT + "_")) { //$NON-NLS-1$
                                deployedICU = true;
                            }

                            deployRuntime(file, targetPrefix, targetName, resultsCollector, monitor);
                        }
                    }
                }
            }
        }

        // RUI apps always need the Java runtime.
        RUIApplication ruiApp = context.getDeploymentDesc().getRUIApplication();
        if (ruiApp != null && (ruiApp.deployAllHandlers()
                || (ruiApp.getRUIHandlers() != null && ruiApp.getRUIHandlers().size() > 0))) {
            if (!deployedJavaRuntime) {
                deployProject(JAVA_RUNTIME_PROJECT, resultsCollector, monitor);
            }
            if (!deployedICU) {
                deployProject(ICU_PROJECT, resultsCollector, monitor);
            }
        }
    }

    private void deployProject(String projectName, IDeploymentResultsCollector resultsCollector,
            IProgressMonitor monitor) {
        try {
            Bundle bundle = Platform.getBundle(projectName);
            File javaRuntimeFile = FileLocator.getBundleFile(bundle);

            // For the version, only keep major.minor.service, no qualifier.
            Version version = bundle.getVersion();
            StringBuilder bundleVersion = new StringBuilder(20);
            bundleVersion.append(version.getMajor());
            bundleVersion.append('.');
            bundleVersion.append(version.getMinor());
            bundleVersion.append('.');
            bundleVersion.append(version.getMicro());

            String targetPrefix = projectName + "_"; //$NON-NLS-1$
            String targetName = targetPrefix + bundleVersion.toString() + ".jar"; //$NON-NLS-1$
            if (javaRuntimeFile.isDirectory()) {
                // We really want its bin directory
                File bin = new File(javaRuntimeFile, "bin"); //$NON-NLS-1$
                if (bin.exists()) {
                    javaRuntimeFile = bin;
                }
            }
            deployRuntime(javaRuntimeFile, targetPrefix, targetName, resultsCollector, monitor);
        } catch (IOException ioe) {
            resultsCollector.addMessage(DeploymentUtilities.createDeployMessage(IStatus.ERROR,
                    DeploymentUtilities.createExceptionMessage(ioe)));
        }
    }

    private void deployRuntime(File file, String targetPrefix, String targetName,
            IDeploymentResultsCollector resultsCollector, IProgressMonitor monitor) {
        ZipOutputStream zos = null;
        InputStream fis = null;
        try {
            if (file.isDirectory()) {
                // Package the directory into a jar and stick it in the target location.
                ByteArrayOutputStream bos = new ByteArrayOutputStream();
                Manifest manifest = new Manifest();
                manifest.getMainAttributes().put(Attributes.Name.MANIFEST_VERSION, "1.0"); //$NON-NLS-1$

                zos = new JarOutputStream(bos, manifest);
                CRC32 crc = new CRC32();

                // Add initial '/' entry
                ZipEntry root = new ZipEntry("/");
                zos.putNextEntry(root);

                createRuntimeJar(zos, crc, file, file.getPath().length());
                zos.close();
                zos = null;
                fis = new ByteArrayInputStream(bos.toByteArray());
            } else {
                // Already a jar - copy it.
                fis = new FileInputStream(file);
            }

            copyFile(fis, targetName, targetPrefix, monitor);
        } catch (Exception e) {
            resultsCollector.addMessage(DeploymentUtilities.createDeployMessage(IStatus.ERROR,
                    DeploymentUtilities.createExceptionMessage(e)));
        } finally {
            if (zos != null) {
                try {
                    zos.close();
                } catch (IOException ioe) {
                }
            }
            if (fis != null) {
                try {
                    fis.close();
                } catch (IOException ioe) {
                }
            }
        }
    }

    private void copyFile(InputStream fis, final String targetName, final String targetPrefix,
            final IProgressMonitor monitor) throws CoreException {
        IPath path = new Path(WEBLIB_FOLDER + targetName);
        IPath targetFilePath = projectRootFolder.getFullPath().append(path);
        CoreUtility.createFolder(
                ResourcesPlugin.getWorkspace().getRoot().getFolder(targetFilePath.removeLastSegments(1)), true,
                true, monitor);
        IFile targetFile = ResourcesPlugin.getWorkspace().getRoot().getFile(targetFilePath);
        if (targetFile.exists()) {
            targetFile.setContents(fis, true, true, monitor);
        } else {
            targetFile.create(fis, true, monitor);
        }

        // Delete any other versions of the jar if they exist.
        final IFolder targetFolder = ResourcesPlugin.getWorkspace().getRoot()
                .getFolder(projectRootFolder.getFullPath().append(WEBLIB_FOLDER));
        if (targetFolder.exists()) {
            targetFolder.accept(new IResourceProxyVisitor() {
                @Override
                public boolean visit(IResourceProxy proxy) throws CoreException {
                    switch (proxy.getType()) {
                    case IResource.FILE:
                        String name = proxy.getName();
                        if (name.startsWith(targetPrefix) && name.endsWith(".jar") && !name.equals(targetName)) {
                            proxy.requestResource().delete(true, monitor);
                        }
                        return false;
                    case IResource.FOLDER:
                        if (proxy.getName().equals(targetFolder.getName())
                                && proxy.requestResource().equals(targetFolder)) {
                            return true;
                        }
                        return false;
                    }
                    return false;
                }
            }, IResource.NONE);
        }
    }

    private void createRuntimeJar(ZipOutputStream zos, CRC32 crc, File runtimeLoc, int len) {
        int bytesRead;
        for (File file : runtimeLoc.listFiles()) {
            try {
                if (file.isFile()) {
                    byte[] buffer = new byte[1024];
                    BufferedInputStream bis = new BufferedInputStream(new FileInputStream(file));
                    String fileName = file.getPath().substring(len + 1);
                    if (File.separatorChar == '\\') {
                        fileName = fileName.replace("\\", "/"); //$NON-NLS-1$ //$NON-NLS-2$
                    }

                    JarEntry entry = new JarEntry(fileName);
                    entry.setSize(file.length());
                    entry.setTime(file.lastModified());
                    zos.putNextEntry(entry);
                    while ((bytesRead = bis.read(buffer)) != -1) {
                        zos.write(buffer, 0, bytesRead);
                    }
                    bis.close();
                    zos.closeEntry();
                } else {
                    String fileName = file.getPath().substring(len);
                    if (File.separatorChar == '\\') {
                        fileName = fileName.replace("\\", "/"); //$NON-NLS-1$ //$NON-NLS-2$
                    }
                    if (!fileName.endsWith("/")) { //$NON-NLS-1$
                        fileName += "/"; //$NON-NLS-1$
                    }

                    JarEntry entry = new JarEntry(fileName);
                    entry.setTime(file.lastModified());
                    zos.putNextEntry(entry);
                    createRuntimeJar(zos, crc, file, len);
                }
            } catch (Exception e) {
                Activator.getDefault().log(e.getMessage(), e);
            }
        }
    }

    /**
     * Finds all the classpath entries on the Java build path, including referenced projects, that are of type {@link IClasspathEntry#CPE_CONTAINER}.
     * @throws CoreException
     */
    private void getClasspathContainers(IJavaProject project, Set<IJavaProject> seen, Set<IClasspathEntry> entries)
            throws CoreException {
        if (seen.contains(project)) {
            return;
        }

        seen.add(project);

        for (IClasspathEntry entry : project.getRawClasspath()) {
            switch (entry.getEntryKind()) {
            case IClasspathEntry.CPE_CONTAINER:
                entries.add(entry);
                break;

            case IClasspathEntry.CPE_PROJECT:
                IProject p = ResourcesPlugin.getWorkspace().getRoot().getProject(entry.getPath().lastSegment());
                if (p.isAccessible() && p.hasNature(JavaCore.NATURE_ID)) {
                    getClasspathContainers(JavaCore.create(p), seen, entries);
                }
                break;
            }
        }
    }
}