Package org.fakereplace.integration.jbossas

Source Code of org.fakereplace.integration.jbossas.JBossAsEnvironment

/*
*
*  * Copyright 2012, Stuart Douglas, and individual contributors as indicated
*  * by the @authors tag.
*  *
*  * This 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; either version 2.1 of
*  * the License, or (at your option) any later version.
*  *
*  * This software 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 software; if not, write to the Free
*  * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
*  * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
*
*/
package org.fakereplace.integration.jbossas;

import java.io.FileOutputStream;
import java.io.IOException;
import java.net.URL;
import java.net.URLConnection;
import java.util.Collections;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;

import org.fakereplace.boot.Environment;
import org.fakereplace.logging.Logger;
import org.jboss.as.server.CurrentServiceContainer;
import org.jboss.as.server.deployment.Attachments;
import org.jboss.as.server.deployment.DeploymentUnit;
import org.jboss.as.server.deployment.Services;
import org.jboss.as.server.deployment.module.ResourceRoot;
import org.jboss.modules.ModuleClassLoader;
import org.jboss.modules.ModuleIdentifier;
import org.jboss.msc.service.ServiceController;
import org.jboss.msc.service.ServiceName;
import org.jboss.vfs.VirtualFile;

/**
* @author Stuart Douglas
*/
public class JBossAsEnvironment implements Environment {

    private final Map<ModuleIdentifier, ModuleClassLoader> loadersByModuleIdentifier = new ConcurrentHashMap<ModuleIdentifier, ModuleClassLoader>();
    private final Map<ModuleClassLoader, Map<String, Long>> timestamps = new ConcurrentHashMap<ModuleClassLoader, Map<String, Long>>();

    private final Logger log = Logger.getLogger(JBossAsEnvironment.class);

    @Override
    public boolean isClassReplaceable(final String className, final ClassLoader loader) {
        if (loader instanceof ModuleClassLoader) {
            if (((ModuleClassLoader) loader).getModule().getIdentifier().toString().startsWith("deployment.")) {
                return true;
            }
        }
        return false;
    }

    public void recordTimestamp(String className, ClassLoader loader) {
        log.trace("Recording timestamp for " + className);

        if (!(loader instanceof ModuleClassLoader)) {
            return;
        }
        Map<String, Long> stamps = null;
        final ModuleClassLoader moduleClassLoader = (ModuleClassLoader) loader;
        final ModuleIdentifier moduleIdentifier = moduleClassLoader.getModule().getIdentifier();
        if (loadersByModuleIdentifier.containsKey(moduleIdentifier)) {
            final ModuleClassLoader oldLoader = loadersByModuleIdentifier.get(moduleIdentifier);
            if (oldLoader != moduleClassLoader) {
                loadersByModuleIdentifier.put(moduleIdentifier, moduleClassLoader);
                timestamps.put(moduleClassLoader, stamps = new ConcurrentHashMap<String, Long>());
            } else {
                stamps = timestamps.get(moduleClassLoader);
            }
        } else {
            loadersByModuleIdentifier.put(moduleIdentifier, moduleClassLoader);
            timestamps.put(moduleClassLoader, stamps = new ConcurrentHashMap<String, Long>());
        }

        final URL file = loader.getResource(className.replace(".", "/") + ".class");
        className = className.replace("/", ".");
        if (file != null) {
            try {
                final URLConnection connection = file.openConnection();
                final long lastModified = connection.getLastModified();
                stamps.put(className, lastModified);
                log.trace("Timestamp for " + className + " is " + lastModified);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }


    public Set<Class> getUpdatedClasses(final String deploymentName, Map<String, Long> updatedClasses) {
        log.info("Finding classes for " + deploymentName);
        log.trace("Server time stamps: " + timestamps);
        ServiceController<DeploymentUnit> deploymentService = deploymentService(deploymentName);
        if (deploymentService == null) {
            log.error("Could not find deployment " + deploymentName);
            return Collections.emptySet();
        }

        final ModuleIdentifier moduleId = getModuleIdentifier(deploymentService);
        final ModuleClassLoader loader = loadersByModuleIdentifier.get(moduleId);
        if (loader == null) {
            log.error("Could not find module " + moduleId);
            return Collections.emptySet();
        }
        final Map<String, Long> timestamps = this.timestamps.get(loader);

        final Set<Class> ret = new HashSet<Class>();
        for (Map.Entry<String, Long> entry : updatedClasses.entrySet()) {
            StringBuilder traceString = new StringBuilder();
            traceString.append("Comparing class ");
            traceString.append(entry.getKey());
            traceString.append(" TS: ");
            traceString.append(entry.getValue());

            if (timestamps.containsKey(entry.getKey())) {
                traceString.append(" Server TS: ");
                final Long timestamp = timestamps.get(entry.getKey());
                traceString.append(timestamp);
                if (timestamp < entry.getValue()) {
                    traceString.append(" replacing");
                    try {
                        ret.add(loader.loadClass(entry.getKey()));
                        timestamps.put(entry.getKey(), entry.getValue());
                    } catch (ClassNotFoundException e) {
                        System.err.println("Could not load class " + entry);
                    }
                } else {
                    traceString.append(" not replacing");
                }
            } else {
                traceString.append(" Server TS not found");
            }

            log.trace(traceString.toString());
        }
        return ret;
    }

    @Override
    public Set<String> getUpdatedResources(final String deploymentName, final Map<String, Long> updatedResources) {
        ServiceController<DeploymentUnit> deploymentService = deploymentService(deploymentName);
        if (deploymentService == null) {
            return Collections.emptySet();
        }

        final ModuleIdentifier moduleId = getModuleIdentifier(deploymentService);
        final ModuleClassLoader loader = loadersByModuleIdentifier.get(moduleId);
        if (loader == null) {
            return Collections.emptySet();
        }

        final DeploymentUnit deploymentUnit = deploymentService.getValue();
        final ResourceRoot root = deploymentUnit.getAttachment(Attachments.DEPLOYMENT_ROOT);

        final Set<String> resources = new HashSet<String>();
        for (final Map.Entry<String, Long> entry : updatedResources.entrySet()) {
            final VirtualFile file = root.getRoot().getChild(entry.getKey());
            if (file.exists()) {
                long last = file.getLastModified();
                if (entry.getValue() > last) {
                    resources.add(entry.getKey());
                }
            }
        }
        return resources;
    }

    private ServiceController<DeploymentUnit> deploymentService(final String deploymentName) {
        ServiceController<DeploymentUnit> deploymentService = (ServiceController<DeploymentUnit>) CurrentServiceContainer.getServiceContainer().getService(Services.deploymentUnitName(deploymentName));
        if (deploymentService == null) {
            //now try for a sub deployment
            for (final ServiceName serviceName : CurrentServiceContainer.getServiceContainer().getServiceNames()) {
                if (Services.JBOSS_DEPLOYMENT_SUB_UNIT.isParentOf(serviceName)) {
                    final String[] parts = serviceName.toArray();
                    if (parts[parts.length - 1].equals(deploymentName)) {
                        deploymentService = (ServiceController<DeploymentUnit>) CurrentServiceContainer.getServiceContainer().getService(serviceName);
                        break;
                    }
                }
            }
        }
        return deploymentService;
    }

    @Override
    public void updateResource(final String archiveName, final Map<String, byte[]> replacedResources) {
        ServiceController<DeploymentUnit> deploymentService = deploymentService(archiveName);
        if(deploymentService == null) {
            return;
        }
        final ModuleIdentifier moduleId = getModuleIdentifier(deploymentService);
        final ModuleClassLoader loader = loadersByModuleIdentifier.get(moduleId);
        if (loader == null) {
            return;
        }

        final DeploymentUnit deploymentUnit = deploymentService.getValue();
        final ResourceRoot root = deploymentUnit.getAttachment(Attachments.DEPLOYMENT_ROOT);

        for (final Map.Entry<String, byte[]> entry : replacedResources.entrySet()) {
            final VirtualFile file = root.getRoot().getChild(entry.getKey());
            try {
                final FileOutputStream stream = new FileOutputStream(file.getPhysicalFile(), false);
                try {
                    stream.write(entry.getValue());
                    stream.flush();
                } finally {
                    stream.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    private ModuleIdentifier getModuleIdentifier(final ServiceController<DeploymentUnit> deploymentArchive) {
        return deploymentArchive.getValue().getAttachment(Attachments.MODULE_IDENTIFIER);
    }

}
TOP

Related Classes of org.fakereplace.integration.jbossas.JBossAsEnvironment

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.