com.ibm.ecm.extension.aspera.AsperaPlugin.java Source code

Java tutorial

Introduction

Here is the source code for com.ibm.ecm.extension.aspera.AsperaPlugin.java

Source

/*
 * Licensed Materials - Property of IBM
 * (C) Copyright IBM Corp. 2010, 2017
 * US Government Users Restricted Rights - Use, duplication or disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
 */

package com.ibm.ecm.extension.aspera;

import com.ibm.ecm.extension.*;
import com.ibm.ecm.extension.aspera.faspex.FaspexClient;
import org.apache.commons.lang.SystemUtils;

import javax.servlet.http.HttpServletRequest;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardCopyOption;
import java.nio.file.attribute.PosixFilePermission;
import java.util.*;

/**
 * The main class for the Aspera faspex plug-in. Files required to send files to a faspex server are copied when
 * the plug-in starts and deleted when the plug-in terminates.
 */
public class AsperaPlugin extends Plugin {
    private static final String ID = "aspera";
    private static final String MESSAGE_PROPERTIES = "com.ibm.ecm.extension.aspera.nls.ServicesMessages";
    private static final String applicationInit = "applicationInit";
    private static final String applicationTerminate = "applicationTerminate";
    private static final String BIN = "bin";
    private static final String BIN_LINUX = "bin/linux-64";
    private static final String BIN_OSX = "bin/osx-64";
    private static final String BIN_WINDOWS = "bin/windows-64";
    private static final String ETC = "etc";

    private String resourcesRoot;
    private List<Path> resourcePaths = new ArrayList<>();
    private PluginLogger logger;

    /**
     * Returns an array of actions provided by the plug-in.
     *
     * @return An array of actions
     */
    @Override
    public PluginAction[] getActions() {
        return new PluginAction[] { new SendAction() };
    }

    /**
     * Returns the Id of the plug-in.
     *
     * @return The Id
     */
    @Override
    public String getId() {
        return ID;
    }

    /**
     * Returns a localized name of the plug-in.
     *
     * @param locale The locale for which a resource bundle is desired
     * @return The localized name
     */
    @Override
    public String getName(final Locale locale) {
        return Util.getString("plugin.name", locale);
    }

    /**
     * Returns the name of the compressed and gzipped JavaScript file for the plug-in.
     *
     * @return The name of the JavaScript file
     */
    @Override
    public String getScript() {
        return "AsperaPlugin.js.jgz";
    }

    /**
     * Returns the name of the main, uncompressed, JavaScript file of the plug-in used in debug mode (debug=true).
     *
     * @return The name of the JavaScript file
     */
    @Override
    public String getDebugScript() {
        return "AsperaPlugin.js";
    }

    /**
     * Returns an array of services provided by the plug-in.
     *
     * @return An array of services
     */
    @Override
    public PluginService[] getServices() {
        return new PluginService[] { new SendService(), new PackageActionService() };
    }

    /**
     * Returns the version number of the plug-in.
     *
     * @return The version number
     */
    @Override
    public String getVersion() {
        return "3.0.2-sample-1.0";
    }

    /**
     * Returns the name of the Dojo module that is contained in the resources for the plug-in.
     *
     * @return The name of the the Dojo module
     */
    @Override
    public String getDojoModule() {
        return "aspera";
    }

    /**
     * Returns the name of the compressed and gzipped CSS file for the plug-in.
     *
     * @return The name of the CSS file
     */
    @Override
    public String getCSSFileName() {
        return "AsperaPlugin.css.jgz";
    }

    /**
     * Returns the name of the uncompressed CSS file for the plug-in used in debug mode (debug=true).
     *
     * @return The name of the CSS file
     */
    @Override
    public String getDebugCSSFileName() {
        return "AsperaPlugin.css";
    }

    /**
     * Returns the name of the Dojo <code>dijit</code> class that provides a configuration interface widget for the plug-in.
     *
     * @return The name of the Dojo <code>dijit</code> class
     */
    @Override
    public String getConfigurationDijitClass() {
        return "aspera.ConfigurationPane";
    }

    /**
     * Returns the base name of the plug-in message resources file.
     *
     * @return The base name of the resources file
     */
    @Override
    public String getPluginMessageResourcesName() {
        return MESSAGE_PROPERTIES;
    }

    /**
     * Copies files required to send files to a temporary directory and loads a secret key.
     *
     * @param request   The HttpServletRequest object provided by the ICN API
     * @param callbacks The PluginServiceCallbacks object provided by the ICN API
     * @throws AsperaPluginException if an error occurs while initializing the plug-in
     */
    @Override
    public void applicationInit(final HttpServletRequest request, final PluginServiceCallbacks callbacks)
            throws AsperaPluginException {
        logger = callbacks.getLogger();
        logger.logEntry(this, applicationInit, request);
        try {
            super.applicationInit(request, callbacks);
        } catch (final Exception e) { // NOPMD - thrown from the super method
            throw new AsperaPluginException("An error occurred while initializing the plugin.", e);
        }

        createResourcesFolderStructure();
        logger.logDebug(this, applicationInit, request, "created folder structure for resources: " + resourcesRoot);
        copyResources();
        Encryption.loadSecretKey();
        logger.logExit(this, applicationInit, request);
    }

    private void createResourcesFolderStructure() throws AsperaPluginException {
        final File resourcesDir = new File(System.getProperty("java.io.tmpdir"), "aspera-plugin-resources");
        resourcesRoot = createResourceFolder(resourcesDir);
        createResourceFolder(new File(resourcesRoot, BIN));
        createResourceFolder(new File(resourcesRoot, ETC));
    }

    private String createResourceFolder(final File resourceFolder) throws AsperaPluginException {
        if (!resourceFolder.exists() && !resourceFolder.mkdir()) {
            throw new AsperaPluginException("Failed to create a plugin resource folder: " + resourceFolder);
        }

        try {
            return resourceFolder.getCanonicalPath();
        } catch (final IOException e) {
            throw new AsperaPluginException(
                    "Failed to get the canonical path of the resource folder: " + resourceFolder, e);
        }
    }

    private void copyResources() throws AsperaPluginException {
        resourcePaths.add(copyResource("", "asperaweb_id_dsa.openssh", ""));
        resourcePaths.add(copyResource(ETC, "aspera-license", ETC));
        resourcePaths.add(copyResource(ETC, "aspera.conf", ETC));
        if (SystemUtils.IS_OS_WINDOWS) {
            copyWindowsResources();
        } else if (SystemUtils.IS_OS_MAC_OSX) {
            resourcePaths.add(makeFileExecutable(copyResource(BIN_OSX, "ascp4", BIN)));
        } else if (SystemUtils.IS_OS_LINUX) {
            resourcePaths.add(makeFileExecutable(copyResource(BIN_LINUX, "ascp4", BIN)));
        } else {
            throw new AsperaPluginException("The operating system is not supported.");
        }
    }

    private void copyWindowsResources() throws AsperaPluginException {
        resourcePaths.add(copyResource(BIN_WINDOWS, "ascp4.exe", BIN));
        resourcePaths.add(copyResource(BIN_WINDOWS, "fasp3.dll", BIN));
        resourcePaths.add(copyResource(BIN_WINDOWS, "libeay32.dll", BIN));
        resourcePaths.add(copyResource(BIN_WINDOWS, "msvcp100.dll", BIN));
        resourcePaths.add(copyResource(BIN_WINDOWS, "msvcr100.dll", BIN));
        resourcePaths.add(copyResource(BIN_WINDOWS, "ssleay32.dll", BIN));
    }

    private Path makeFileExecutable(final Path file) throws AsperaPluginException {
        final Set<PosixFilePermission> perms = new HashSet<>();
        perms.add(PosixFilePermission.OWNER_READ);
        perms.add(PosixFilePermission.OWNER_WRITE);
        perms.add(PosixFilePermission.OWNER_EXECUTE);
        perms.add(PosixFilePermission.GROUP_READ);
        perms.add(PosixFilePermission.GROUP_EXECUTE);
        try {
            Files.setPosixFilePermissions(file, perms);
        } catch (final IOException e) {
            throw new AsperaPluginException("Failed to make the file executable: " + file, e);
        }

        return file;
    }

    private Path copyResource(final String subFolder, final String resourceName, final String toSubFolder)
            throws AsperaPluginException {
        final Path path = toSubFolder.isEmpty() ? Paths.get(resourcesRoot, resourceName)
                : Paths.get(resourcesRoot, toSubFolder, resourceName);
        final InputStream resource = this.getClass()
                .getResourceAsStream("/aspera/" + subFolder + (subFolder.isEmpty() ? "" : "/") + resourceName);
        try {
            Files.copy(resource, path, StandardCopyOption.REPLACE_EXISTING);
        } catch (final IOException e) {
            throw new AsperaPluginException("Failed to copy the plugin resource file: " + path, e);
        }

        return path;
    }

    /**
     * Stops all in-progress transfers and deletes files that were copied to a temporary directory.
     *
     * @param request   The HttpServletRequest object provided by the ICN API
     * @param callbacks The PluginServiceCallbacks object provided by the ICN API
     * @throws AsperaPluginRuntimeException if an error occurs while terminating the plug-in
     */
    @Override
    public void applicationTerminate(final HttpServletRequest request, final PluginServiceCallbacks callbacks)
            throws AsperaPluginException {
        logger = callbacks.getLogger();
        logger.logEntry(this, applicationTerminate, request);
        FaspexClient.terminate();
        logger.logDebug(this, applicationTerminate, request, "terminated faspex client");
        deleteResources();
        logger.logDebug(this, applicationTerminate, request, "deleted resources");

        try {
            Encryption.loadSecretKey(); // reset the secret key
            super.applicationTerminate(request, callbacks);
        } catch (final Exception e) { // NOPMD - thrown from the super method
            throw new AsperaPluginException("An error occurred while terminating the plugin.", e);
        }
        logger.logExit(this, applicationTerminate, request);
    }

    private void deleteResources() {
        if (resourcePaths == null) {
            return;
        }

        resourcePaths.parallelStream().filter(path -> path.toFile().exists()).map(Path::toFile).forEach(file -> {
            final boolean deleted = file.delete();
            if (!deleted) {
                file.deleteOnExit();
            }
        });
        resourcePaths = new ArrayList<>();
    }

    /**
     * Provides the copyright license for the plug-in. The information is displayed in the About dialog Plugins tab.
     *
     * @return The copyright license
     */
    @Override
    public String getCopyright() {
        return "Licensed Materials - Property of IBM<br>(C) Copyright IBM Corp. 2010, 2017<br>US Government Users Restricted Rights - Use, duplication or disclosure restricted by GSA ADP Schedule Contract with IBM Corp.";
    }
}