com.flexive.shared.FxDropApplication.java Source code

Java tutorial

Introduction

Here is the source code for com.flexive.shared.FxDropApplication.java

Source

/***************************************************************
 *  This file is part of the [fleXive](R) framework.
 *
 *  Copyright (c) 1999-2014
 *  UCS - unique computing solutions gmbh (http://www.ucs.at)
 *  All rights reserved
 *
 *  The [fleXive](R) project is free software; you can redistribute
 *  it and/or modify it under the terms of the GNU Lesser General Public
 *  License version 2.1 or higher as published by the Free Software Foundation.
 *
 *  The GNU Lesser General Public License can be found at
 *  http://www.gnu.org/licenses/lgpl.html.
 *  A copy is found in the textfile LGPL.txt and important notices to the
 *  license from the author are found in LICENSE.txt distributed with
 *  these libraries.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  For further information about UCS - unique computing solutions gmbh,
 *  please see the company website: http://www.ucs.at
 *
 *  For further information about [fleXive](R), please see the
 *  project website: http://www.flexive.org
 *
 *
 *  This copyright notice MUST APPEAR in all copies of the file!
 ***************************************************************/
package com.flexive.shared;

import com.google.common.collect.Maps;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.Serializable;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.List;
import java.util.Map;
import java.util.jar.JarEntry;
import java.util.jar.JarInputStream;

import static com.flexive.shared.FxSharedUtils.checkParameterEmpty;

/**
 * Information about a "drop application" deployed as part of the flexive EAR.
 * <p/>
 * <p>
 * Some properties can be configured in a file called <code>flexive-application.properties</code> in the root
 * folder of the application shared JAR file:
 * </p>
 * <code><pre>
 * # Application name
 * name=hello-flexive
 * displayName=Hello-World Application
 *
 * # Context root (must match the path specified in application.xml, used for the backend start page)
 * contextRoot=war
 * </pre></code>
 *
 * @author Daniel Lichtenberger (daniel.lichtenberger@flexive.com), UCS - unique computing solutions gmbh (http://www.ucs.at)
 * @version $Rev$
 * @since 3.0.2
 */
public class FxDropApplication implements Serializable {
    private static final long serialVersionUID = 4947330707321634617L;
    private static final Log LOG = LogFactory.getLog(FxDropApplication.class);

    private final String name;
    private final String displayName;
    private final String contextRoot;
    private final String resourceURL;
    private final boolean isJarProtocol;

    /**
     * Create a new application descriptor.
     *
     * @param name              the unique name of the application
     * @param contextRoot       the context root of the web application
     * @param displayName       a human-readable name of the application
     * @param resourceURL       the URL that was used for loading flexive-application.properties
     * @since 3.1
     */
    public FxDropApplication(String name, String contextRoot, String displayName, URL resourceURL) {
        checkParameterEmpty(name, "name");
        checkParameterEmpty(displayName, "displayName");
        this.name = name;
        this.contextRoot = contextRoot;
        this.displayName = displayName;

        if (resourceURL == null) {
            this.resourceURL = null;
            this.isJarProtocol = false;
        } else {
            // set base url
            String path = resourceURL.getPath().replace("/" + FxSharedUtils.FLEXIVE_DROP_PROPERTIES, "");
            if (path.endsWith("!")) {
                // strip JAR content separator
                path = StringUtils.chop(path);
            }
            this.resourceURL = path;
            this.isJarProtocol = "vfszip".equals(resourceURL.getProtocol())
                    || "vfs".equals(resourceURL.getProtocol()) || "jar".equals(resourceURL.getProtocol())
                    || resourceURL.getPath().indexOf('!') != -1;
        }
    }

    /**
     * Create a new application descriptor. The application name will also be used for the
     * display name and the context root path.
     *
     * @param name      the unique name of the application
     */
    public FxDropApplication(String name) {
        this(name, name, name, (URL) null);
    }

    /**
     * Return the unique name of the application. It should not contain spaces or
     * non-alphanumeric characters (excluding "-" and "_").
     *
     * @return the unique name of the application
     */
    public String getName() {
        return name;
    }

    /**
     * Return the context root of the web application. This defaults to the <code>name</code>,
     * but can be customized in <code>flexive-application.properties</code>.
     * <p>
     * When an application uses <p>flexive-application.properties</p> but does not specify a
     * contextRoot, it is assumed that the application does not provide a web context.
     * </p>
     *
     * @return the context root of the web application
     */
    public String getContextRoot() {
        return contextRoot;
    }

    /**
     * Returns true when the drop application has a web context available (i.e. a context root has been set).
     *
     * @return  true when the drop application has a web context available (i.e. a context root has been set).
     * @since 3.0.3
     */
    public boolean isWebContextAvailable() {
        return contextRoot != null;
    }

    /**
     * Returns a human-readable name of the application. This defaults to the <code>name</code>,
     * but can be customized in <code>flexive-application.properties</code>.
     *
     * @return a human-readable name of the application
     */
    public String getDisplayName() {
        return displayName;
    }

    /**
     * Returns the URL of the JAR file containing the resources of the drop application, usually
     * the "shared" module (but it could be any JAR file).
     *
     * @return the URL of the JAR file containing the resources of the drop application
     */
    public String getResourceJarURL() {
        return resourceURL;
    }

    private JarInputStream getJarStream() throws IOException {
        try {
            return resourceURL != null ? new JarInputStream(new URL(resourceURL).openStream()) : null;
        } catch (MalformedURLException e) {
            //try again using JBoss v5 vfszip ...
            try {
                return new JarInputStream(new URL("vfszip:" + resourceURL).openStream());
            } catch (MalformedURLException e2) {
                //try again using JBoss v6 M3+ vfs ...
                try {
                    final InputStream in = new URL("vfs:" + resourceURL).openStream();
                    return in instanceof JarInputStream ? (JarInputStream) in // JBoss 7 already returns a virtual JAR stream
                            : new JarInputStream(in); // otherwise wrap returned connection
                } catch (MalformedURLException e3) {
                    throw new IllegalArgumentException("Cannot create JAR stream for URL " + resourceURL);
                }
            }
        }
    }

    /**
     * Load text resources packaged with the drop.
     *
     * @param pathPrefix    a path prefix (e.g. "scripts/")
     * @return              a map of filename (relative to the drop application package) -> file contents
     * @throws java.io.IOException  on I/O errors
     * @since 3.1
     */
    public Map<String, String> loadTextResources(String pathPrefix) throws IOException {
        if (pathPrefix == null) {
            pathPrefix = "";
        } else if (pathPrefix.startsWith("/")) {
            pathPrefix = pathPrefix.substring(1);
        }
        if (isJarProtocol) {
            // read directly from jar file

            final Map<String, String> result = Maps.newHashMap();
            final JarInputStream stream = getJarStream();
            try {
                JarEntry entry;
                while ((entry = stream.getNextJarEntry()) != null) {

                    if (!entry.isDirectory() && entry.getName().startsWith(pathPrefix)) {
                        try {
                            result.put(entry.getName(), FxSharedUtils.readFromJarEntry(stream, entry));
                        } catch (Exception e) {
                            if (LOG.isTraceEnabled()) {
                                LOG.trace(
                                        "Failed to read text JAR entry " + entry.getName() + ": " + e.getMessage(),
                                        e);
                            }
                            // ignore, continue reading
                        }

                    }
                }
                return result;
            } finally {
                FxSharedUtils.close(stream);
            }
        } else {
            // read from filesystem

            final List<File> files = FxFileUtils.listRecursive(new File(resourceURL + File.separator + pathPrefix));
            final Map<String, String> result = Maps.newHashMapWithExpectedSize(files.size());
            for (File file : files) {
                try {
                    result.put(StringUtils.replace(file.getPath(), resourceURL + File.separator, ""),
                            FxSharedUtils.loadFile(file));
                } catch (Exception e) {
                    if (LOG.isTraceEnabled()) {
                        LOG.trace("Failed to read text file " + file.getPath() + ": " + e.getMessage(), e);
                    }
                }
            }
            return result;
        }
    }
}