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

org.bonitasoft.engine.classloader.ClassLoaderServiceImpl Maven / Gradle / Ivy

/**
 * Copyright (C) 2011-2013 BonitaSoft S.A.
 * BonitaSoft, 32 rue Gustave Eiffel - 38000 Grenoble
 * This library is free software; you can redistribute it and/or modify it under the terms
 * of the GNU Lesser General Public License as published by the Free Software Foundation
 * version 2.1 of the License.
 * 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 Lesser General Public License for more details.
 * You should have received a copy of the GNU Lesser General Public License along with this
 * program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
 * Floor, Boston, MA 02110-1301, USA.
 **/
package org.bonitasoft.engine.classloader;

import java.io.File;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.bonitasoft.engine.commons.LogUtil;
import org.bonitasoft.engine.commons.NullCheckingUtil;
import org.bonitasoft.engine.log.technical.TechnicalLogSeverity;
import org.bonitasoft.engine.log.technical.TechnicalLoggerService;

/**
 * @author Elias Ricken de Medeiros
 * @author Baptiste Mesta
 * @author Matthieu Chaffotte
 */
public class ClassLoaderServiceImpl implements ClassLoaderService {

    private final TechnicalLoggerService logger;

    private final String temporaryFolder;

    private VirtualClassLoader virtualGlobalClassLoader;
    private final Map localClassLoaders = new HashMap();

    private static final String separator = ":";

    private static final String GLOBAL_FOLDER = "global";
    public static final String GLOBAL_TYPE = "___global___";
    public static final long GLOBAL_ID = -1;
    private static final String LOCAL_FOLDER = "local";

    public ClassLoaderServiceImpl(final String temporaryFolder, final TechnicalLoggerService logger) {
        this.logger = logger;
        if (temporaryFolder.startsWith("${") && temporaryFolder.contains("}")) {
            final Pattern pattern = Pattern.compile("^(.*)\\$\\{(.*)\\}(.*)$");
            final Matcher matcher = pattern.matcher(temporaryFolder);
            matcher.find();
            final StringBuilder sb = new StringBuilder();
            sb.append(matcher.group(1));
            sb.append(System.getProperty(matcher.group(2)));
            sb.append(matcher.group(3));
            this.temporaryFolder = sb.toString();
        } else {
            this.temporaryFolder = temporaryFolder;
        }
    }

    private String getKey(final String type, final long id) {
        final StringBuffer stb = new StringBuffer();
        stb.append(type);
        stb.append(separator);
        stb.append(id);
        return stb.toString();
    }

    @Override
    public long getGlobalClassLoaderId() {
        return GLOBAL_ID;
    }

    @Override
    public String getGlobalClassLoaderType() {
        return GLOBAL_TYPE;
    }

    private synchronized VirtualClassLoader getVirtualGlobalClassLoader() throws ClassLoaderException {
        if (this.virtualGlobalClassLoader == null) {
            this.virtualGlobalClassLoader = new VirtualClassLoader(GLOBAL_TYPE, GLOBAL_ID, VirtualClassLoader.class.getClassLoader());
        }
        return this.virtualGlobalClassLoader;
    }

    @Override
    public synchronized ClassLoader getGlobalClassLoader() throws ClassLoaderException {
        return getVirtualGlobalClassLoader();
    }

    @Override
    public synchronized ClassLoader getLocalClassLoader(final String type, final long id) throws ClassLoaderException {
        if (this.logger.isLoggable(this.getClass(), TechnicalLogSeverity.TRACE)) {
            this.logger.log(this.getClass(), TechnicalLogSeverity.TRACE, LogUtil.getLogBeforeMethod(this.getClass(), "getLocalClassLoader"));
        }
        NullCheckingUtil.checkArgsNotNull(id, type);
        final String key = getKey(type, id);
        final VirtualClassLoader classLoader = this.localClassLoaders.get(key);
        if (classLoader == null) {
            final VirtualClassLoader virtualClassLoader = new VirtualClassLoader(type, id, getGlobalClassLoader()); 
            this.localClassLoaders.put(key, virtualClassLoader);
        }
        if (this.logger.isLoggable(this.getClass(), TechnicalLogSeverity.TRACE)) {
            this.logger.log(this.getClass(), TechnicalLogSeverity.TRACE, LogUtil.getLogAfterMethod(this.getClass(), "getLocalClassLoader"));
        }
        return this.localClassLoaders.get(key);
    }

    @Override
    public void removeLocalClassLoader(final String type, final long id) {
        if (this.logger.isLoggable(this.getClass(), TechnicalLogSeverity.TRACE)) {
            this.logger.log(this.getClass(), TechnicalLogSeverity.TRACE, LogUtil.getLogBeforeMethod(this.getClass(), "removeLocalClassLoader"));
        }
        NullCheckingUtil.checkArgsNotNull(id, type);
        final String key = getKey(type, id);
        final VirtualClassLoader localClassLoader = this.localClassLoaders.get(key);
        if (localClassLoader != null) {
            localClassLoader.release();
            this.localClassLoaders.remove(key);
        }
        if (this.logger.isLoggable(this.getClass(), TechnicalLogSeverity.TRACE)) {
            this.logger.log(this.getClass(), TechnicalLogSeverity.TRACE, LogUtil.getLogAfterMethod(this.getClass(), "removeLocalClassLoader"));
        }
        // TODO FIXME else log
    }

    private String getGlobalTemporaryFolder() {
        final StringBuffer stb = new StringBuffer(this.temporaryFolder);
        stb.append(File.separator);
        stb.append(GLOBAL_FOLDER);
        return stb.toString();
    }

    private String getLocalTemporaryFolder(final String artifactType, final long artifactId) {
        final StringBuffer stb = new StringBuffer(this.temporaryFolder);
        stb.append(File.separator);
        stb.append(LOCAL_FOLDER);
        stb.append(File.separator);
        stb.append(artifactType);
        stb.append(File.separator);
        stb.append(artifactId);
        return stb.toString();
    }


    @Override
    public synchronized void removeAllLocalClassLoaders(final String application) {
        if (this.logger.isLoggable(this.getClass(), TechnicalLogSeverity.TRACE)) {
            this.logger.log(this.getClass(), TechnicalLogSeverity.TRACE, LogUtil.getLogBeforeMethod(this.getClass(), "removeAllLocalClassLoaders"));
        }
        NullCheckingUtil.checkArgsNotNull(application);
        final Set keySet = new HashSet(this.localClassLoaders.keySet());
        for (final String key : keySet) {
            if (key.startsWith(application + separator)) {
                final VirtualClassLoader localClassLoader = this.localClassLoaders.get(key);
                if (localClassLoader != null) {
                    localClassLoader.release();
                }
                this.localClassLoaders.remove(key);
            }
        }
        if (this.logger.isLoggable(this.getClass(), TechnicalLogSeverity.TRACE)) {
            this.logger.log(this.getClass(), TechnicalLogSeverity.TRACE, LogUtil.getLogAfterMethod(this.getClass(), "removeAllLocalClassLoaders"));
        }
    }

    public String getTemporaryFolder() {
        return this.temporaryFolder;
    }

    @Override
    public synchronized void refreshGlobalClassLoader(final Map resources) throws ClassLoaderException {
        final VirtualClassLoader virtualClassloader = (VirtualClassLoader) getGlobalClassLoader();
        virtualClassloader.release();
        virtualClassloader.setClassLoader(new BonitaClassLoader(resources, getGlobalClassLoaderType(), getGlobalClassLoaderId(), getGlobalTemporaryFolder(), ClassLoaderServiceImpl.class.getClassLoader()));
    }

    @Override
    public synchronized void refreshLocalClassLoader(final String type, final long id, final Map resources) throws ClassLoaderException {
        final VirtualClassLoader virtualClassloader = (VirtualClassLoader) getLocalClassLoader(type, id);
        virtualClassloader.release();
        virtualClassloader.setClassLoader(new BonitaClassLoader(resources, type, id, getLocalTemporaryFolder(type, id), getGlobalClassLoader()));
    }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy