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.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.WeakHashMap;

import org.fakereplace.api.environment.ChangedClasses;
import org.fakereplace.api.environment.Environment;
import org.fakereplace.hibernate4.HibernateEnvironment;
import org.fakereplace.integration.jbossas.hibernate4.JBossASHibernateEnvironment;
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 Logger log = Logger.getLogger(JBossAsEnvironment.class);

    private static final Map<Class<?>, Object> SERVICES;

    /**
     * When classes are replaced we need to update their timestamps, otherwise they will be replaced on every subsequent
     * invocation.
     */
    private final Map<Class<?>, Long> replacedClassTimestamps = Collections.synchronizedMap(new WeakHashMap<Class<?>, Long>());

    static {
        final Map<Class<?>, Object> services = new HashMap<Class<?>, Object>();
        services.put(HibernateEnvironment.class, new JBossASHibernateEnvironment());
        SERVICES = Collections.unmodifiableMap(services);
    }

    @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) {

    }

    public ChangedClasses getUpdatedClasses(final String deploymentName, Map<String, Long> updatedClasses) {
        log.info("Finding classes for " + deploymentName);
        ServiceController<DeploymentUnit> deploymentService = deploymentService(deploymentName);
        if (deploymentService == null) {
            log.error("Could not find deployment " + deploymentName);
            return ChangedClasses.EMPTY;
        }

        final ModuleIdentifier moduleId = getModuleIdentifier(deploymentService);
        final ModuleClassLoader loader = deploymentService.getValue().getAttachment(Attachments.MODULE).getClassLoader();
        if (loader == null) {
            log.error("Could not find module " + moduleId);
            return ChangedClasses.EMPTY;
        }

        final Set<Class<?>> ret = new HashSet<Class<?>>();
        final Set<String> newClasses = new HashSet<String>();
        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());

            final String resourceName = entry.getKey().replace(".", "/") + ".class";
            final URL resource = loader.getResource(resourceName);
            if (resource == null) {
                //new class
                newClasses.add(entry.getKey());
                traceString.append(" not found on server, adding as new class");
            } else {
                try {
                    final URLConnection urlConnection = resource.openConnection();
                    Long timeStamp = urlConnection.getLastModified();
                    final Class<?> clazz = loader.loadClass(entry.getKey());
                    Long replacedTs = replacedClassTimestamps.get(clazz);
                    if (replacedTs != null) {
                        timeStamp = replacedTs;
                    }
                    if (timeStamp < entry.getValue()) {
                        traceString.append(" replacing");
                        ret.add(clazz);
                        replacedClassTimestamps.put(clazz, entry.getValue());
                    } else {
                        traceString.append(" not replacing");
                    }
                } catch (IOException e) {
                    log.error("Could not open connection for " + resourceName, e);
                } catch (ClassNotFoundException e) {
                    log.debug("Could not load class " + entry.getKey(), e);
                }

                log.trace(traceString.toString());

            }
        }
        return new ChangedClasses(ret, newClasses, loader);
    }

    @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 ModuleClassLoader loader = deploymentService.getValue().getAttachment(Attachments.MODULE).getClassLoader();
        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 ModuleClassLoader loader = deploymentService.getValue().getAttachment(Attachments.MODULE).getClassLoader();
        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();
            }
        }
    }

    @Override
    public <T> T getService(final Class<T> clazz) {
        return (T) SERVICES.get(clazz);
    }

    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.