org.eclipse.cft.server.core.internal.CloudUtil.java Source code

Java tutorial

Introduction

Here is the source code for org.eclipse.cft.server.core.internal.CloudUtil.java

Source

/*******************************************************************************
 * Copyright (c) 2012, 2017 Pivotal Software, Inc. and others
 * 
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * and Apache License v2.0 which accompanies this distribution. 
 * 
 * The Eclipse Public License is available at 
 * 
 * http://www.eclipse.org/legal/epl-v10.html
 * 
 * and the Apache License v2.0 is available at 
 * 
 * http://www.apache.org/licenses/LICENSE-2.0
 * 
 * You may elect to redistribute this code under either of these licenses.
 *  
 *  Contributors:
 *     Pivotal Software, Inc. - initial API and implementation
 ********************************************************************************/
package org.eclipse.cft.server.core.internal;

import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

import org.cloudfoundry.client.lib.CloudCredentials;
import org.cloudfoundry.client.lib.domain.CloudApplication;
import org.eclipse.cft.server.core.ApplicationDeploymentInfo;
import org.eclipse.cft.server.core.CFServiceInstance;
import org.eclipse.cft.server.core.EnvironmentVariable;
import org.eclipse.core.resources.IContainer;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.MultiStatus;
import org.eclipse.core.runtime.Path;
import org.eclipse.core.runtime.Status;
import org.eclipse.jst.server.core.IJ2EEModule;
import org.eclipse.jst.server.core.IWebModule;
import org.eclipse.osgi.util.NLS;
import org.eclipse.wst.server.core.IModule;
import org.eclipse.wst.server.core.IModuleType;
import org.eclipse.wst.server.core.internal.ProgressUtil;
import org.eclipse.wst.server.core.internal.Server;
import org.eclipse.wst.server.core.internal.ServerPlugin;
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.util.ModuleFile;
import org.eclipse.wst.server.core.util.ModuleFolder;
import org.eclipse.wst.server.core.util.PublishHelper;
import org.springframework.security.oauth2.common.OAuth2AccessToken;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;

/**
 * @author Christian Dupuis
 * @author Terry Denney
 * @author Steffen Pingel
 * @author Leo Dos Santos
 * @author Nieraj Singh
 */
@SuppressWarnings("restriction")
public class CloudUtil {

    public static final int DEFAULT_MEMORY = 512;

    private static final IStatus[] EMPTY_STATUS = new IStatus[0];

    public static IWebModule getWebModule(IModule[] modules) {

        IModuleType moduleType = modules[0].getModuleType();

        if (modules.length == 1 && moduleType != null && "jst.web".equals(moduleType.getId())) { //$NON-NLS-1$
            return (IWebModule) modules[0].loadAdapter(IWebModule.class, null);
        }
        return null;

    }

    /**
     * Creates a partial war file containing only the resources listed in the
     * list to filter in. Note that at least one content must be present in the
     * list to filter in, otherwise null is returned.
     * @param resources
     * @param module
     * @param server
     * @param monitor
     * @return partial war file with resources specified in the filter in list,
     * or null if filter list is empty or null
     * @throws CoreException
     */
    public static File createWarFile(List<IModuleResource> allResources, IModule module,
            Set<IModuleResource> filterInResources, IProgressMonitor monitor) throws CoreException {
        if (allResources == null || allResources.isEmpty() || filterInResources == null
                || filterInResources.isEmpty()) {
            return null;
        }
        List<IStatus> result = new ArrayList<IStatus>();
        try {
            File tempDirectory = getTempFolder(module);
            // tempFile needs to be in the same location as the war file
            // otherwise PublishHelper will fail
            String fileName = module.getName() + ".war"; //$NON-NLS-1$

            File warFile = new File(tempDirectory, fileName);
            warFile.createNewFile();
            warFile.deleteOnExit();
            List<IModuleResource> newResources = new ArrayList<IModuleResource>();
            for (IModuleResource mr : allResources) {
                newResources.add(processModuleResource(mr));
            }

            IStatus[] status = publishZip(allResources, warFile, filterInResources, monitor);
            merge(result, status);
            throwException(result, "Publishing of : " + module.getName() + " failed"); //$NON-NLS-1$ //$NON-NLS-2$

            return warFile;
        } catch (IOException e) {
            throw new CoreException(new Status(IStatus.ERROR, CloudFoundryPlugin.PLUGIN_ID,
                    "Failed to create war file: " + e.getMessage(), e)); //$NON-NLS-1$
        }
    }

    public static File createWarFile(IModule[] modules, Server server, IProgressMonitor monitor)
            throws CoreException {
        List<IStatus> result = new ArrayList<IStatus>();
        try {
            File tempFile = getTempFolder(modules[0]);
            // tempFile needs to be in the same location as the war file
            // otherwise PublishHelper will fail
            File targetFile = new File(tempFile, modules[0].getName() + ".war"); //$NON-NLS-1$
            targetFile.deleteOnExit();
            PublishHelper helper = new PublishHelper(tempFile);

            ArrayList<IModuleResource> resources = new ArrayList<IModuleResource>(
                    Arrays.asList(server.getResources(modules)));

            IWebModule webModule = getWebModule(modules);

            if (webModule != null) {

                IModule[] children = webModule.getModules();

                if (children != null) {
                    for (IModule child : children) {
                        String childUri = null;
                        if (webModule != null) {
                            childUri = webModule.getURI(child);
                        }
                        IJ2EEModule childModule = (IJ2EEModule) child.loadAdapter(IJ2EEModule.class, monitor);
                        boolean isBinary = false;
                        if (childModule != null) {
                            isBinary = childModule.isBinary();
                        }
                        if (isBinary) {
                            // binaries are copied to the destination
                            // directory
                            if (childUri == null) {
                                childUri = "WEB-INF/lib/" + child.getName(); //$NON-NLS-1$
                            }
                            IPath jarPath = new Path(childUri);
                            File jarFile = new File(tempFile, jarPath.lastSegment());
                            jarPath = jarPath.removeLastSegments(1);

                            IModuleResource[] mr = server.getResources(new IModule[] { child });
                            IStatus[] status = helper.publishToPath(mr, new Path(jarFile.getAbsolutePath()),
                                    monitor);
                            merge(result, status);
                            resources.add(new ModuleFile(jarFile, jarFile.getName(), jarPath));
                        } else {
                            // other modules are assembled into a jar
                            if (childUri == null) {
                                childUri = "WEB-INF/lib/" + child.getName() + ".jar"; //$NON-NLS-1$ //$NON-NLS-2$
                            }
                            IPath jarPath = new Path(childUri);
                            File jarFile = new File(tempFile, jarPath.lastSegment());
                            jarPath = jarPath.removeLastSegments(1);

                            IModuleResource[] mr = server.getResources(new IModule[] { child });
                            IStatus[] status = helper.publishZip(mr, new Path(jarFile.getAbsolutePath()), monitor);
                            merge(result, status);
                            resources.add(new ModuleFile(jarFile, jarFile.getName(), jarPath));
                        }
                    }
                }
            }

            List<IModuleResource> newResources = new ArrayList<IModuleResource>();
            for (IModuleResource mr : resources) {
                newResources.add(processModuleResource(mr));
            }

            IStatus[] status = helper.publishZip(newResources.toArray(new IModuleResource[0]),
                    new Path(targetFile.getAbsolutePath()), monitor);
            merge(result, status);
            throwException(result, "Publishing of " + modules[0].getName() + " failed"); //$NON-NLS-1$ //$NON-NLS-2$

            return targetFile;
        } catch (IOException e) {
            throw new CoreException(new Status(IStatus.ERROR, CloudFoundryPlugin.PLUGIN_ID,
                    "Failed to create war file: " + e.getMessage(), e)); //$NON-NLS-1$
        }

    }

    private static IModuleResource processModuleResource(IModuleResource or) {
        if (or instanceof IModuleFolder) {
            IModuleFolder of = (IModuleFolder) or;
            IPath p = of.getModuleRelativePath();
            if (p.isAbsolute()) {
                p = p.makeRelative();
            }
            ModuleFolder nf = new ModuleFolder(null, of.getName(), p);
            List<IModuleResource> c = new ArrayList<IModuleResource>();
            for (IModuleResource mc : of.members()) {
                c.add(processModuleResource(mc));
            }
            nf.setMembers(c.toArray(new IModuleResource[0]));
            return nf;
        }
        return or;
    }

    private static File getTempFolder(IModule module) throws IOException {
        File tempFile = File.createTempFile("tempFileForWar", null); //$NON-NLS-1$
        tempFile.delete();
        tempFile.mkdirs();
        return tempFile;
    }

    protected static void throwException(List<IStatus> status, String message) throws CoreException {
        if (status == null || status.size() == 0) {
            return;
        }
        throw new CoreException(
                new MultiStatus(CloudFoundryPlugin.PLUGIN_ID, 0, status.toArray(new IStatus[0]), message, null));
    }

    public static IStatus[] publishZip(List<IModuleResource> allResources, File tempFile,
            Set<IModuleResource> filterInFiles, IProgressMonitor monitor) {

        monitor = ProgressUtil.getMonitorFor(monitor);

        try {
            BufferedOutputStream bout = new BufferedOutputStream(new FileOutputStream(tempFile));
            ZipOutputStream zout = new ZipOutputStream(bout);
            addZipEntries(zout, allResources, filterInFiles);
            zout.close();

        } catch (CoreException e) {
            return new IStatus[] { e.getStatus() };
        } catch (Exception e) {

            return new Status[] { new Status(IStatus.ERROR, ServerPlugin.PLUGIN_ID, 0,
                    NLS.bind(Messages.ERROR_CREATE_ZIP, tempFile.getName(), e.getLocalizedMessage()), e) };
        } finally {
            if (tempFile != null && tempFile.exists())
                tempFile.deleteOnExit();
        }
        return EMPTY_STATUS;
    }

    private static final int BUFFER = 65536;

    private static byte[] buf = new byte[BUFFER];

    public static String getZipRelativeName(IModuleResource resource) {
        IPath path = resource.getModuleRelativePath().append(resource.getName());
        String entryPath = path.toPortableString();
        if (resource instanceof IModuleFolder && !entryPath.endsWith("/")) { //$NON-NLS-1$
            entryPath += '/';
        }

        return entryPath;

    }

    private static void addZipEntries(ZipOutputStream out, List<IModuleResource> allResources,
            Set<IModuleResource> filterInFiles) throws Exception {
        if (allResources == null)
            return;

        for (IModuleResource resource : allResources) {
            if (resource instanceof IModuleFolder) {

                IModuleResource[] folderResources = ((IModuleFolder) resource).members();

                String entryPath = getZipRelativeName(resource);

                ZipEntry zipEntry = new ZipEntry(entryPath);

                long timeStamp = 0;
                IContainer folder = (IContainer) resource.getAdapter(IContainer.class);
                if (folder != null) {
                    timeStamp = folder.getLocalTimeStamp();
                }

                if (timeStamp != IResource.NULL_STAMP && timeStamp != 0) {
                    zipEntry.setTime(timeStamp);
                }

                out.putNextEntry(zipEntry);
                out.closeEntry();

                addZipEntries(out, Arrays.asList(folderResources), filterInFiles);
                continue;
            }

            IModuleFile moduleFile = (IModuleFile) resource;
            // Only add files that are in the filterInList
            if (!filterInFiles.contains(moduleFile)) {
                continue;
            }

            String entryPath = getZipRelativeName(resource);

            ZipEntry zipEntry = new ZipEntry(entryPath);

            InputStream input = null;
            long timeStamp = 0;
            IFile iFile = (IFile) moduleFile.getAdapter(IFile.class);
            if (iFile != null) {
                timeStamp = iFile.getLocalTimeStamp();
                input = iFile.getContents();
            } else {
                File file = (File) moduleFile.getAdapter(File.class);
                timeStamp = file.lastModified();
                input = new FileInputStream(file);
            }

            if (timeStamp != IResource.NULL_STAMP && timeStamp != 0) {
                zipEntry.setTime(timeStamp);
            }

            out.putNextEntry(zipEntry);

            try {
                int n = 0;
                while (n > -1) {
                    n = input.read(buf);
                    if (n > 0) {
                        out.write(buf, 0, n);
                    }
                }
            } finally {
                input.close();
            }

            out.closeEntry();
        }
    }

    /**
     * Creates a temporary folder and file with the given names. It is the
     * responsibility of the caller to properly dispose the folder and file
     * after it is created
     * @param folderName
     * @param fileName
     * @return
     * @throws IOException
     */
    public static File createTemporaryFile(String folderName, String fileName) throws IOException {
        File tempFolder = File.createTempFile(folderName, null);
        // Delete an existing one
        tempFolder.delete();

        tempFolder.mkdirs();
        tempFolder.setExecutable(true);

        File targetFile = new File(tempFolder, fileName);

        // delete existing file
        targetFile.delete();

        targetFile.createNewFile();
        targetFile.setExecutable(true);
        targetFile.setWritable(true);

        return targetFile;
    }

    public static void merge(List<IStatus> result, IStatus[] status) {
        if (result == null || status == null || status.length == 0) {
            return;
        }

        int size = status.length;
        for (int i = 0; i < size; i++) {
            result.add(status[i]);
        }
    }

    public static IStatus basicValidateDeploymentInfo(ApplicationDeploymentInfo deploymentInfo) {
        IStatus status = Status.OK_STATUS;

        String errorMessage = null;

        if (deploymentInfo == null) {
            errorMessage = Messages.AbstractApplicationDelegate_ERROR_MISSING_DEPLOY_INFO;
        } else if (StringUtils.isEmpty(deploymentInfo.getDeploymentName())) {
            errorMessage = Messages.AbstractApplicationDelegate_ERROR_MISSING_APPNAME;
        } else if (deploymentInfo.getMemory() <= 0) {
            errorMessage = Messages.AbstractApplicationDelegate_ERROR_MISSING_MEM;
        }

        if (errorMessage != null) {
            status = CloudFoundryPlugin.getErrorStatus(errorMessage);
        }

        return status;
    }

    /**
     * Parses deployment information from a deployed Cloud Application. Returns
     * null if the cloud application is null.
     * @param cloudApplication deployed in a CF server
     * @return Parsed deployment information, or null if Cloud Application is
     * null.
     */
    public static ApplicationDeploymentInfo parseApplicationDeploymentInfo(CloudApplication cloudApplication) {

        if (cloudApplication != null) {

            String deploymentName = cloudApplication.getName();
            ApplicationDeploymentInfo deploymentInfo = new ApplicationDeploymentInfo(deploymentName);

            deploymentInfo.setInstances(cloudApplication.getInstances());
            if (cloudApplication.getStaging() != null) {
                deploymentInfo.setBuildpack(cloudApplication.getStaging().getBuildpackUrl());
            }
            deploymentInfo.setMemory(cloudApplication.getMemory());

            List<String> boundServiceNames = cloudApplication.getServices();
            if (boundServiceNames != null) {
                List<CFServiceInstance> services = new ArrayList<CFServiceInstance>();
                for (String name : boundServiceNames) {
                    if (name != null) {
                        services.add(new CFServiceInstance(name));
                    }
                }
                deploymentInfo.setServices(services);
            }

            if (cloudApplication.getUris() != null) {
                deploymentInfo.setUris(new ArrayList<String>(cloudApplication.getUris()));
            }

            deploymentInfo.setDiskQuota(cloudApplication.getDiskQuota());

            Map<String, String> envMap = cloudApplication.getEnvAsMap();

            if (envMap != null) {
                List<EnvironmentVariable> variables = new ArrayList<EnvironmentVariable>();
                for (Entry<String, String> entry : envMap.entrySet()) {
                    String varName = entry.getKey();
                    if (varName != null) {
                        EnvironmentVariable variable = new EnvironmentVariable();
                        variable.setVariable(varName);
                        variable.setValue(entry.getValue());
                        variables.add(variable);
                    }
                }
                deploymentInfo.setEnvVariables(variables);
            }
            return deploymentInfo;

        }
        return null;
    }

    /** Create new cloud credentials with passcode and token value, based on which is available. */
    public static CloudCredentials createSsoCredentials(String passcode, String tokenValue) {
        CloudCredentials credentials = null;
        if (tokenValue != null && !tokenValue.isEmpty()) {
            try {
                OAuth2AccessToken token = getTokenAsOAuth2Access(tokenValue);
                credentials = new CloudCredentials(passcode, token);
            } catch (IOException e) {
                // ignore
            }
        }
        if (credentials == null) {
            credentials = new CloudCredentials(passcode);
        }
        return credentials;
    }

    public static OAuth2AccessToken getTokenAsOAuth2Access(String authToken) throws IOException {
        return new ObjectMapper().readValue(authToken, OAuth2AccessToken.class);
    }

    public static String getTokenAsJson(OAuth2AccessToken token) throws JsonProcessingException {
        return new ObjectMapper().writeValueAsString(token);
    }
}