All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.glassfish.deployment.common.DeploymentUtils Maven / Gradle / Ivy

The newest version!
/*
 * Copyright (c) 2022, 2024 Contributors to the Eclipse Foundation.
 * Copyright (c) 1997, 2018 Oracle and/or its affiliates. All rights reserved.
 *
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Public License v. 2.0, which is available at
 * http://www.eclipse.org/legal/epl-2.0.
 *
 * This Source Code may also be made available under the following Secondary
 * Licenses when the conditions for such availability set forth in the
 * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
 * version 2 with the GNU Classpath Exception, which is available at
 * https://www.gnu.org/software/classpath/license.html.
 *
 * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
 */

package org.glassfish.deployment.common;

import static com.sun.enterprise.util.Utility.isAnyNull;
import static com.sun.enterprise.util.io.FileUtils.makeFriendlyFilenameExtension;
import static com.sun.enterprise.util.io.FileUtils.makeLegalNoBlankFileName;
import static com.sun.enterprise.util.io.FileUtils.safeIsDirectory;
import static java.util.jar.JarFile.MANIFEST_NAME;
import static java.util.logging.Level.WARNING;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Enumeration;
import java.util.List;
import java.util.Properties;
import java.util.jar.Manifest;
import java.util.logging.LogRecord;
import java.util.logging.Logger;
import java.util.zip.Adler32;

import org.glassfish.api.admin.ServerEnvironment;
import org.glassfish.api.deployment.DeploymentContext;
import org.glassfish.api.deployment.archive.ArchiveDetector;
import org.glassfish.api.deployment.archive.ArchiveType;
import org.glassfish.api.deployment.archive.ReadableArchive;
import org.glassfish.api.deployment.archive.WritableArchive;
import org.glassfish.api.deployment.archive.WritableArchiveEntry;
import org.glassfish.hk2.api.ServiceLocator;
import org.glassfish.loader.util.ASClassLoaderUtil;
import org.glassfish.logging.annotation.LogMessageInfo;

import com.sun.enterprise.config.serverbeans.Application;
import com.sun.enterprise.config.serverbeans.Cluster;
import com.sun.enterprise.config.serverbeans.Config;
import com.sun.enterprise.config.serverbeans.Domain;
import com.sun.enterprise.config.serverbeans.HttpService;
import com.sun.enterprise.config.serverbeans.Server;
import com.sun.enterprise.config.serverbeans.VirtualServer;
import com.sun.enterprise.deploy.shared.ArchiveFactory;
import com.sun.enterprise.deploy.shared.FileArchive;
import com.sun.enterprise.util.LocalStringManagerImpl;
import com.sun.enterprise.util.io.FileUtils;

/**
 * Utility methods for deployment.
 */
public class DeploymentUtils {

    private static final Logger deplLogger = DeploymentContextImpl.deplLogger;

    @LogMessageInfo(message = "Exception caught {0}", level = "WARNING")
    private static final String EXCEPTION_CAUGHT = "NCLS-DEPLOYMENT-00010";

    private static final LocalStringManagerImpl localStrings = new LocalStringManagerImpl(DeploymentUtils.class);

    private static final String V2_COMPATIBILITY = "v2";

    private static final String INSTANCE_ROOT_URI_PROPERTY_NAME = "com.sun.aas.instanceRootURI";

    public final static String DAS_TARGET_NAME = "server";
    public final static String DOMAIN_TARGET_NAME = "domain";

    private final static String DOWNLOADABLE_ARTIFACTS_KEY_PREFIX = "downloadable";
    private final static String GENERATED_ARTIFACTS_KEY_PREFIX = "generated";

    public static boolean isDASTarget(final String targetName) {
        return DAS_TARGET_NAME.equals(targetName);
    }

    public static boolean isDomainTarget(final String targetName) {
        return DOMAIN_TARGET_NAME.equals(targetName);
    }

    /**
     * Computes the checksum of the URIs of files contained in a directory.
     *
     * @param directory the directory for which to compute a checksum
     * @return checksum calculated from URIs of files in the directory
     */
    public static long checksum(final File directory) {
        if (!directory.isDirectory()) {
            final String msg = localStrings.getLocalString("enterprise.deployment.remoteDirPathUnusable",
                    "The directory deployment path {0} is not a directory or is inaccessible", directory.getAbsolutePath());
            throw new IllegalArgumentException(msg);
        }

        final List uris = new ArrayList<>();
        scanDirectory(directory.toURI(), directory, uris);

        /*
         * Sort the URIs. File.listFiles does not guarantee any particular ordering of the visited files, and for two checksums
         * to match we need to process the URIs in the same order.
         */
        Collections.sort(uris);

        final Adler32 checksum = new Adler32();
        for (URI uri : uris) {
            checksum.update(uri.toASCIIString().getBytes());
        }

        return checksum.getValue();
    }

    /**
     * Returns the downloadable artifacts object from the specified deployment context, creating it there if it does not
     * already exist.
     *
     * @param deploymentContext the deployment context from which to fetch the downloadable Artifacts object
     * @return
     */
    public static Artifacts downloadableArtifacts(final DeploymentContext deploymentContext) {
        return Artifacts.get(deploymentContext, DOWNLOADABLE_ARTIFACTS_KEY_PREFIX);
    }

    /**
     * Returns the downloadable artifacts object derived from the properties saved with the specified Application
     *
     * @param app the Application config object with (possibly) properties describing downloadable artifacts
     * @return
     */
    public static Artifacts downloadableArtifacts(final Application app) {
        return Artifacts.get(app.getDeployProperties(), DOWNLOADABLE_ARTIFACTS_KEY_PREFIX);
    }

    /**
     * Returns the generated artifacts object from the specified deployment context, creating it there if it does not
     * already exist.
     *
     * @param app
     * @return
     */
    public static Artifacts generatedArtifacts(final DeploymentContext deploymentContext) {
        return Artifacts.get(deploymentContext, GENERATED_ARTIFACTS_KEY_PREFIX);
    }

    /**
     * Returns the generated artifacts object derived from the properties saved with the specified Application
     *
     * @param app the Application config object with (possibly) properties describing generated artifacts
     * @return
     */
    public static Artifacts generatedArtifacts(final Application app) {
        return Artifacts.get(app.getDeployProperties(), GENERATED_ARTIFACTS_KEY_PREFIX);
    }

    private static void scanDirectory(final URI anchorDirURI, final File directory, final List uris) {
        for (File file : directory.listFiles()) {
            uris.add(anchorDirURI.relativize(file.toURI()));
            if (file.isDirectory()) {
                scanDirectory(anchorDirURI, file, uris);
            }
        }
    }

    // Check if the archive matches the specified archive type
    public static boolean isArchiveOfType(ReadableArchive archive, ArchiveType archiveType, DeploymentContext context, ServiceLocator locator) {
        if (isAnyNull(archive, archiveType)) {
            return false;
        }

        String type = archiveType.toString();
        if (context != null && context.getArchiveHandler() != null) {
            // First check the current context for the current archive type
            return type.equals(context.getArchiveHandler().getArchiveType());
        }

        try {
            ArchiveDetector detector = locator.getService(ArchiveDetector.class, type);
            if (detector == null) {
                return false;
            }

            return detector.handles(archive);
        } catch (IOException ioe) {
            LogRecord lr = new LogRecord(WARNING, EXCEPTION_CAUGHT);
            Object args[] = { ioe.getMessage() };
            lr.setParameters(args);
            lr.setThrown(ioe);
            deplLogger.log(lr);

            return false;
        }
    }

    public static boolean isArchiveOfType(ReadableArchive archive, ArchiveType archiveType, ServiceLocator locator) {
        return isArchiveOfType(archive, archiveType, null, locator);
    }

    /**
     * @param pathName
     * @return the default value of the EE name. The default name is the pathname with any filename extension (.jar, .war,
     * .rar) removed, but with any directory names included.
     */
    public static String getDefaultEEName(String pathName) {
        if (pathName == null) {
            return null;
        }

        pathName = pathName.replace('\\', '/');

        if (pathName.endsWith("/")) {
            pathName = pathName.substring(0, pathName.length() - 1);
        }
        if (pathName.lastIndexOf("/") != -1) {
            pathName = pathName.substring(pathName.lastIndexOf("/") + 1);
        }

        if (pathName.endsWith(".jar") || pathName.endsWith(".war") || pathName.endsWith(".rar") || pathName.endsWith(".ear")) {
            return pathName.substring(0, pathName.length() - 4);
        }

        return pathName;
    }

    /**
     * This method returns the relative file path of an embedded module to the application root. For example, if the module
     * is expanded/located at $domain_dir/applications/ee-apps/foo/fooEJB_jar, this method will return fooEJB_jar
     *
     * @param appRootPath The path of the application root which contains the module e.g.
     * $domain_dir/applications/ee-apps/foo
     * @param moduleUri The module uri e.g. fooEJB.jar
     * @return The relative file path of the module to the application root
     */
    public static String getRelativeEmbeddedModulePath(String appRootPath, String moduleUri) {
        moduleUri = makeLegalNoBlankFileName(moduleUri);
        if (safeIsDirectory(new File(appRootPath, moduleUri))) {
            return moduleUri;
        }

        return makeFriendlyFilenameExtension(moduleUri);
    }

    /**
     * This method returns the file path of an embedded module. For example, if the module is expanded/located at
     * $domain_dir/applications/ee-apps/foo/fooEJB_jar, this method will return
     * $domain_dir/applications/ee-apps/foo/fooEJB_jar
     *
     * @param appRootPath The path of the application root which contains the module e.g.
     * $domain_dir/applications/ee-apps/foo
     * @param moduleUri The module uri e.g. fooEJB.jar
     * @return The file path of the module
     */
    public static String getEmbeddedModulePath(String appRootPath, String moduleUri) {
        return appRootPath + File.separator + getRelativeEmbeddedModulePath(appRootPath, moduleUri);
    }

    public static boolean useV2Compatibility(DeploymentContext context) {
        return V2_COMPATIBILITY.equals(context.getAppProps().getProperty(DeploymentProperties.COMPATIBILITY));
    }

    public static String relativizeWithinDomainIfPossible(final URI absURI) throws URISyntaxException {
        URI appURI = new URI(System.getProperty(INSTANCE_ROOT_URI_PROPERTY_NAME)).relativize(absURI);

        return (appURI.isAbsolute()) ? appURI.toString() : "${" + INSTANCE_ROOT_URI_PROPERTY_NAME + "}/" + appURI.toString();
    }

    public static void validateApplicationName(String name) {
        if (name.indexOf('/') != -1) {
            throw new IllegalArgumentException(
                    localStrings.getLocalString("illegal_char_in_name", "Illegal character [{0}] in the name [{1}].", "/", name));
        }

        if (name.indexOf('#') != -1) {
            throw new IllegalArgumentException(
                    localStrings.getLocalString("illegal_char_in_name", "Illegal character [{0}] in the name [{1}].", "#", name));
        }

        if (name.indexOf(';') != -1) {
            throw new IllegalArgumentException(
                    localStrings.getLocalString("illegal_char_in_name", "Illegal character [{0}] in the name [{1}].", ";", name));
        }

        return;
    }

    /**
     * Expand an archive to a directory
     *
     * @param source of the expanding
     * @param target of the expanding
     * @throws IOException when the archive is corrupted
     */
    public static void expand(ReadableArchive source, WritableArchive target) throws IOException {
        Enumeration e = source.entries();
        while (e.hasMoreElements()) {
            String entryName = e.nextElement();
            try (InputStream is = source.getEntry(entryName);
                WritableArchiveEntry os = target.putNextEntry(entryName)) {
                FileUtils.copy(is, os);
            }
        }

        // Last is manifest if exists
        Manifest manifest = source.getManifest();
        if (manifest != null) {
            try (WritableArchiveEntry entry = target.putNextEntry(MANIFEST_NAME)) {
                manifest.write(entry);
            }
        }
    }

    public static String getInternalNameForTenant(String appname, String tenantname) {
        return appname + "___" + tenantname;
    }

    public static String propertiesValue(final Properties props, final char sep) {
        final StringBuilder sb = new StringBuilder();

        String currentSep = "";
        for (Enumeration propertyNames = props.propertyNames(); propertyNames.hasMoreElements();) {
            final Object key = propertyNames.nextElement();
            final Object value = props.get(key);
            sb.append(currentSep)
              .append(key.toString())
              .append("=")
              .append(value.toString());

            currentSep = String.valueOf(sep);
        }

        return sb.toString();
    }

    public static List getManifestLibraries(DeploymentContext context) throws IOException {
        return getManifestLibraries(context.getSource());
    }

    public static List getManifestLibraries(DeploymentContext context, Manifest manifest) throws IOException {
        return getManifestLibraries(context.getSource(), manifest);
    }

    public static List getManifestLibraries(ReadableArchive archive) throws IOException {
        return getManifestLibraries(archive, archive.getManifest());
    }

    private static List getManifestLibraries(ReadableArchive archive, Manifest manifest) {
        String appRootPath = null;
        ReadableArchive parentArchive = archive.getParentArchive();

        if (parentArchive != null) {
            appRootPath = (new File(parentArchive.getURI())).getPath();
        } else {
            try {
                appRootPath = (new File(archive.getURI().getPath())).getParent();
            } catch (Exception e) {
                // ignore, this is the jar inside jar case
            }
        }

        // Add libraries referenced through manifest
        return ASClassLoaderUtil.getManifestClassPathAsURLs(manifest, appRootPath);
    }

    public static List getExternalLibraries(ReadableArchive archive) {
        List externalLibURIs = new ArrayList<>();
        try {
            List manifestURLs = getManifestLibraries(archive);
            URI archiveURI = archive.getURI();
            if (archive.getParentArchive() != null) {
                archiveURI = archive.getParentArchive().getURI();
            }

            for (URL manifestURL : manifestURLs) {
                URI manifestLibURI = archiveURI.relativize(manifestURL.toURI());
                if (manifestLibURI.isAbsolute()) {
                    File externalLib = new File(manifestLibURI);
                    if (externalLib.exists()) {
                        externalLibURIs.add(manifestLibURI);
                    }
                }
            }
        } catch (Exception e) {
            Logger.getAnonymousLogger().log(WARNING, e.getMessage(), e);
        }

        return externalLibURIs;
    }

    /**
     * Opens the specified file as an archive, using the provided archive factory.
     *
     * @param dir directory to be opened as an archive
     * @param archiveFactory ArchiveFactory to use to create the archive object
     * @return FileArchive opened for the directory
     * @throws IOException
     */
    public static FileArchive openAsFileArchive(final File dir, final ArchiveFactory archiveFactory) throws IOException {
        return (FileArchive) archiveFactory.openArchive(dir);
    }

    /*
     * @return comma-separated list of all defined virtual servers (exclusive of __asadmin) on the specified target
     */
    public static String getVirtualServers(String target, ServerEnvironment env, Domain domain) {
        if (target == null) {
            // return null;
            // work around till the OE sets the virtualservers param when it's
            // handling the default target
            target = "server";
        }

        if (env.isDas() && DeploymentUtils.isDomainTarget(target)) {
            target = "server";
        }


        boolean first = true;
        Server server = domain.getServerNamed(target);
        Config config = null;
        if (server != null) {
            config = domain.getConfigs().getConfigByName(server.getConfigRef());
        } else {
            Cluster cluster = domain.getClusterNamed(target);
            if (cluster != null) {
                config = domain.getConfigs().getConfigByName(cluster.getConfigRef());
            }
        }

        StringBuilder virtualServers = new StringBuilder();
        if (config != null) {
            HttpService httpService = config.getHttpService();
            if (httpService != null) {
                List hosts = httpService.getVirtualServer();
                if (hosts != null) {
                    for (VirtualServer host : hosts) {
                        if (("__asadmin").equals(host.getId())) {
                            continue;
                        }
                        if (first) {
                            virtualServers.append(host.getId());
                            first = false;
                        } else {
                            virtualServers.append(",");
                            virtualServers.append(host.getId());
                        }
                    }
                }
            }
        }

        return virtualServers.toString();
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy