com.mgmtp.jfunk.core.config.JFunkBaseModule.java Source code

Java tutorial

Introduction

Here is the source code for com.mgmtp.jfunk.core.config.JFunkBaseModule.java

Source

/*
 * Copyright (c) 2015 mgm technology partners GmbH
 *
 * 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.mgmtp.jfunk.core.config;

import static com.google.common.base.Preconditions.checkState;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.lang.annotation.Annotation;
import java.nio.charset.Charset;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Set;

import javax.inject.Inject;
import javax.inject.Provider;
import javax.inject.Singleton;

import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
import org.apache.commons.io.IOUtils;

import com.google.common.base.Charsets;
import com.google.common.eventbus.EventBus;
import com.google.inject.Provides;
import com.google.inject.Scope;
import com.google.inject.matcher.Matchers;
import com.mgmtp.jfunk.common.JFunkConstants;
import com.mgmtp.jfunk.common.config.ModuleScoped;
import com.mgmtp.jfunk.common.config.ScriptScoped;
import com.mgmtp.jfunk.common.config.StackedScope;
import com.mgmtp.jfunk.common.config.ThreadScope;
import com.mgmtp.jfunk.common.random.MathRandom;
import com.mgmtp.jfunk.common.util.Configuration;
import com.mgmtp.jfunk.core.data.DataSetAdapter;
import com.mgmtp.jfunk.core.event.AfterCommandEvent;
import com.mgmtp.jfunk.core.event.BeforeCommandEvent;
import com.mgmtp.jfunk.core.event.EventHandlers;
import com.mgmtp.jfunk.core.mail.EmailModule;
import com.mgmtp.jfunk.core.reporting.ReportContext;
import com.mgmtp.jfunk.core.scripting.BreakIndex;
import com.mgmtp.jfunk.core.scripting.Cmd;
import com.mgmtp.jfunk.core.scripting.ExecutionMode;
import com.mgmtp.jfunk.core.scripting.ModuleArchiver;
import com.mgmtp.jfunk.core.scripting.ModuleArchiver.ArchivingMode;
import com.mgmtp.jfunk.core.scripting.ModuleMetaData;
import com.mgmtp.jfunk.core.scripting.ScriptContext;
import com.mgmtp.jfunk.core.scripting.ScriptMetaData;
import com.mgmtp.jfunk.core.scripting.ScriptingModule;
import com.mgmtp.jfunk.core.util.CsvDataProcessor;
import com.mgmtp.jfunk.data.DataSourceModule;

/**
 * Guice module for jFunk which is always needed. It is loaded automatically by the
 * {@link ModulesLoader}. Additional modules need to be configured in a properties file (see
 * {@link ModulesLoader}.
 */
public final class JFunkBaseModule extends BaseJFunkGuiceModule {

    @Override
    protected void doConfigure() {
        ThreadScope scope = new ThreadScope();
        scope.enterScope(); // need to enter it right away for the main thread

        bindScope(ThreadScope.class, scope, ScriptScoped.class);
        bindScope(StackedScope.class, new StackedScope(), ModuleScoped.class);

        bindListener(Matchers.any(), new ConfigurationTypeListener(getProvider(Configuration.class)));

        bind(ScriptMetaData.class);
        bind(ModuleMetaData.class);

        bind(DataSetAdapter.class);
        bind(CsvDataProcessor.class);

        bindCommandInterceptor();

        String encoding = System.getProperty("file.encoding");
        Charset charset = null;
        try {
            charset = Charset.forName(encoding);
        } catch (IllegalArgumentException ex) {
            charset = Charsets.UTF_8;
        }
        bind(Charset.class).toInstance(charset);

        install(new DataSourceModule());
        install(new ScriptingModule());
        install(new EmailModule());
    }

    private <T extends Scope> void bindScope(final Class<T> scopeClass, final T scope,
            final Class<? extends Annotation> scopeAnnotation) {
        // We need a custom thread scope for things related to test runs, because each test runs in
        // its own thread. This gives us thread-local Guice singletons.
        bindScope(scopeAnnotation, scope);

        // We also need to get a hold of the ThreadScope instance via Guice in order to be able to
        // call its cleanUp method after a thread is done. We need to do a clean-up in order to
        // avoid memory leaks.
        bind(scopeClass).toInstance(scope);
    }

    private void bindCommandInterceptor() {
        MethodInterceptor interceptor = new MethodInterceptor() {
            @Inject
            Provider<EventBus> eventBusProvider;

            @Override
            public Object invoke(final MethodInvocation invocation) throws Throwable { //NOSONAR
                String command = invocation.getMethod().getName();
                Object[] params = invocation.getArguments();

                boolean success = false;
                EventBus eventBus = eventBusProvider.get();
                try {
                    eventBus.post(new BeforeCommandEvent(command, params));
                    Object result = invocation.proceed();
                    success = true;
                    return result;
                } finally {
                    eventBus.post(new AfterCommandEvent(command, params, success));
                }
            }
        };
        requestInjection(interceptor);
        bindInterceptor(Matchers.subclassesOf(ScriptContext.class), Matchers.annotatedWith(Cmd.class), interceptor);
    }

    /**
     * Provides the version of perfLoad as specified in the Maven pom.
     * 
     * @return the version string
     */
    @Provides
    @Singleton
    @JFunkVersion
    protected String providePerfLoadVersion() {
        ClassLoader loader = Thread.currentThread().getContextClassLoader();
        InputStream is = loader.getResourceAsStream("com/mgmtp/jfunk/common/version.txt");
        try {
            return IOUtils.toString(is, "UTF-8");
        } catch (IOException ex) {
            throw new IllegalStateException("Could not read jFunk version.", ex);
        } finally {
            IOUtils.closeQuietly(is);
        }
    }

    @Provides
    @ScriptScoped
    Deque<ReportContext> provideReportContextStack() {
        return new ArrayDeque<>();
    }

    @Provides
    @ScriptScoped
    Configuration provideConfiguration(final DataSetAdapter dsAdapter, final Charset charset) {
        Configuration configuration = new Configuration(dsAdapter, charset);
        configuration.load(JFunkConstants.SCRIPT_PROPERTIES, false);
        return configuration;
    }

    @Provides
    @Singleton
    EventBus provideEventBus(@EventHandlers final Set<Object> eventHandlers) {
        EventBus eventBus = new EventBus();
        for (Object eventHandler : eventHandlers) {
            eventBus.register(eventHandler);
        }
        return eventBus;
    }

    @Provides
    @ArchiveDir
    File provideArchiveDir(final Configuration config) {
        File archiveDir = new File(config.get(JFunkConstants.ARCHIVE_DIR, JFunkConstants.ARCHIVE_DIR_DEFAULT))
                .getAbsoluteFile();
        archiveDir.mkdirs();
        checkState(archiveDir.exists(), "Could not create archive directory: %s", archiveDir);
        return archiveDir;
    }

    @Provides
    @ModuleArchiveDir
    File provideModuleArchiveDir(final Provider<ModuleArchiver> moduleArchiverProvider) {
        return moduleArchiverProvider.get().getModuleArchiveDir();
    }

    @Provides
    @ScriptScoped
    MathRandom provideMathRandom(final Configuration config) {
        String seedString = config.get(JFunkConstants.RANDOM_SEED, false);
        return seedString == null ? new MathRandom() : new MathRandom(Long.parseLong(seedString));
    }

    @Provides
    ExecutionMode provideExecutionMode(final Configuration config) {
        String execMode = config.get(JFunkConstants.EXECUTION_MODE, JFunkConstants.EXECUTION_MODE_ALL);
        return ExecutionMode.valueOf(execMode);
    }

    @Provides
    @BreakIndex
    int provideBreakIndex(final Configuration config) {
        return config.getInteger(JFunkConstants.STEP, 0);
    }

    @Provides
    ArchivingMode provideArchivingMode(final Configuration config) {
        return ArchivingMode.valueOf(config.get(JFunkConstants.ARCHIVING_MODE, JFunkConstants.ARCHIVING_MODE_ALL));
    }
}