com.threewks.thundr.jrebel.ThundrJRebelPlugin.java Source code

Java tutorial

Introduction

Here is the source code for com.threewks.thundr.jrebel.ThundrJRebelPlugin.java

Source

/*
 * This file is a component of thundr, a software library from 3wks.
 * Read more: http://www.3wks.com.au/thundr
 * Copyright (C) 2013 3wks, <thundr@3wks.com.au>
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *         http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.threewks.thundr.jrebel;

import com.threewks.thundr.logger.Logger;
import org.apache.commons.lang3.exception.ExceptionUtils;
import org.zeroturnaround.javarebel.*;

import java.io.IOException;
import java.io.InputStream;
import java.util.HashSet;
import java.util.Properties;
import java.util.Set;

public class ThundrJRebelPlugin implements Plugin {

    public static final String ApplicationModuleClassName = "ApplicationModule";
    public static final String BaseModuleClassName = "com.threewks.thundr.injection.BaseModule";
    public static final String ThundrServletClassName = "com.threewks.thundr.ThundrServlet";
    private static final String PropertiesFileName = "jrebel-thundr-watch.properties";
    private static final String ApplicationRoutesClassName = "ApplicationRoutesClassName";

    @Override
    public void preinit() {
        Logger.info("Initializing %s", getName());

        // Register the CBP
        Integration i = IntegrationFactory.getInstance();
        ClassLoader cl = ThundrJRebelPlugin.class.getClassLoader();
        i.addIntegrationProcessor(cl, ThundrServletClassName, new ReloadThundrServletClassBytecodeProcessor());

        registerListener();
    }

    @Override
    public boolean checkDependencies(ClassLoader classLoader, ClassResourceSource classResourceSource) {
        return classResourceSource.getClassResource(BaseModuleClassName) != null;
    }

    @Override
    public String getId() {
        return "thundr-plugin";
    }

    @Override
    public String getName() {
        return "Thundr Plugin for JRebel 2";
    }

    @Override
    public String getDescription() {
        return "Application module reloading for the Thundr framework";
    }

    @Override
    public String getAuthor() {
        return "3wks";
    }

    @Override
    public String getWebsite() {
        return "http://www.3wks.com.au";
    }

    @Override
    public String getSupportedVersions() {
        return null;
    }

    @Override
    public String getTestedVersions() {
        return null;
    }

    @SuppressWarnings("unchecked")
    private void registerListener() {
        // Set up the reload listener
        final Set<String> watchedClasses = loadWatchedClassList();
        ReloaderFactory.getInstance().addClassReloadListener(new ClassEventListener() {
            @Override
            public void onClassEvent(int eventType, Class klass) {
                try {
                    Class applicationModuleClass = Class.forName(BaseModuleClassName);
                    if (applicationModuleClass.isAssignableFrom(klass)
                            || watchedClasses.contains(klass.getCanonicalName())) {
                        Logger.info("%s was modified. InjectionContext will be reloaded on next request...",
                                klass.getCanonicalName());
                        ThundrServletReloader.markDirty();
                    }
                } catch (Exception e) {
                    Logger.error("Error marking ApplicationModule for reloading: %s",
                            ExceptionUtils.getStackTrace(e));
                }
            }

            @Override
            public int priority() {
                return 0;
            }
        });
    }

    private Set<String> loadWatchedClassList() {
        Set<String> watchedClasses = new HashSet<String>();
        watchedClasses.add(ApplicationRoutesClassName);

        InputStream inputStream = getClass().getClassLoader().getResourceAsStream(PropertiesFileName);
        if (inputStream == null) {
            Logger.info("No %s found using defaults.", PropertiesFileName);
        } else {
            Logger.info("Found %s, loading...", PropertiesFileName);
            try {
                Properties properties = new Properties();
                properties.load(inputStream);
                watchedClasses.addAll((Set) properties.keySet());
            } catch (IOException e) {
                Logger.error("There was a problem loading %s: %s; ignoring", PropertiesFileName, e.getMessage());
            }
        }
        return watchedClasses;
    }
}