com.adaptris.core.management.ManagementComponentFactory.java Source code

Java tutorial

Introduction

Here is the source code for com.adaptris.core.management.ManagementComponentFactory.java

Source

/*
 * Copyright 2015 Adaptris Ltd.
 *
 * 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.adaptris.core.management;

import static com.adaptris.core.management.Constants.CFG_KEY_MANAGEMENT_COMPONENT;
import static com.adaptris.core.util.PropertyHelper.getPropertyIgnoringCase;
import static org.apache.commons.lang.StringUtils.isEmpty;

import java.io.InputStream;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.adaptris.core.management.classloader.ClassLoaderFactory;

/**
 * Simple factory that creates management components.
 *
 * @author lchan
 */
public class ManagementComponentFactory {

    private transient Logger log = LoggerFactory.getLogger(this.getClass().getName());

    private static final String COMPONENT_SEPARATOR = ":";
    private static final String PROPERTY_KEY = "class";
    private static final String RESOURCE_PATH = "META-INF/com/adaptris/core/management/components/";
    private static final String CLASSLOADER_KEY = "classloader";
    private static final ManagementComponentFactory INSTANCE = new ManagementComponentFactory();

    private final Map<Properties, List<Object>> managementComponents = new HashMap<>();

    private ManagementComponentFactory() {
    }

    public static List<Object> create(final BootstrapProperties p) throws Exception {
        if (!INSTANCE.getManagementComponents().containsKey(p)) {
            List<Object> obj = INSTANCE.createComponents(p);
            INSTANCE.getManagementComponents().put(p, obj);
        }
        return INSTANCE.getManagementComponents().get(p);
    }

    public static void initCreated(BootstrapProperties p) {
        INSTANCE.invokeInit(p, INSTANCE.getManagementComponents().get(p));
    }

    public static void startCreated(BootstrapProperties p) {
        INSTANCE.invoke(INSTANCE.getManagementComponents().get(p), "start", new Class[0], new Object[0]);
    }

    public static void stopCreated(BootstrapProperties p, boolean reverseOrder) {
        INSTANCE.invoke(reverseOrder(INSTANCE.getManagementComponents().get(p), reverseOrder), "stop", new Class[0],
                new Object[0]);
    }

    public static void closeCreated(BootstrapProperties p, boolean reverseOrder) {
        INSTANCE.invoke(reverseOrder(INSTANCE.getManagementComponents().get(p), reverseOrder), "destroy",
                new Class[0], new Object[0]);
    }

    private static List<Object> reverseOrder(List<Object> list, boolean reverseOrder) {
        List<Object> newList = new ArrayList<>(list);
        if (reverseOrder) {
            Collections.reverse(newList);
        }
        return newList;
    }

    private Map<Properties, List<Object>> getManagementComponents() {
        return managementComponents;
    }

    private List<Object> createComponents(final BootstrapProperties p) throws Exception {
        List<Object> result = new ArrayList<>();
        final String componentList = getPropertyIgnoringCase(p, CFG_KEY_MANAGEMENT_COMPONENT, "");
        if (!isEmpty(componentList)) {
            final String components[] = componentList.split(COMPONENT_SEPARATOR);
            for (final String c : components) {
                result.add(resolve(c, p));
            }
        }
        return result;
    }

    private void invokeInit(Properties initProperties, List<Object> mgmtComponents) {
        invoke(mgmtComponents, "init", new Class[] { Properties.class }, new Properties[] { initProperties });
    }

    private void invoke(List<Object> objects, final String methodName, final Class[] paramTypes,
            final Object[] params) {
        if (objects == null) {
            return;
        }
        for (final Object o : objects) {
            invokeMethod(o, methodName, paramTypes, params);
        }
    }

    private void invokeMethod(final Object o, final String methodName, final Class[] paramTypes,
            final Object[] params) {
        final Class<? extends Object> clas = o.getClass();
        List<String> types = paramTypes(paramTypes);
        try {
            log.trace("{}#{}({})", clas.getName(), methodName, (types.size() > 0 ? types : ""));
            final Method method = clas.getMethod(methodName, paramTypes);
            method.setAccessible(true);
            method.invoke(o, params);
        } catch (NoSuchMethodException | InvocationTargetException | IllegalAccessException e) {
            log.trace("FAILED: {}#{}({})", clas, methodName, (types.size() > 0 ? types : ""), e);
        }
    }

    private static List<String> paramTypes(Class[] params) {
        List<String> result = new ArrayList<>();
        for (Class p : params) {
            if (p != null) {
                result.add(p.getCanonicalName());
            }
        }
        return result;
    }

    private Object resolve(final String name, BootstrapProperties bootstrapProperties) throws Exception {
        final ClassLoader originalContectClassLoader = Thread.currentThread().getContextClassLoader();
        ClassLoader classLoader = getClass().getClassLoader();
        try (final InputStream in = classLoader.getResourceAsStream(RESOURCE_PATH + name)) {
            if (in != null) {
                final Properties p = new Properties();
                p.load(in);

                final String classloaderProperty = p.getProperty(CLASSLOADER_KEY);
                if (classloaderProperty != null) {
                    log.debug("Using custom class loader " + classloaderProperty);
                    final Class<ClassLoaderFactory> classLoaderFactoryClass = (Class<ClassLoaderFactory>) Class
                            .forName(classloaderProperty);
                    final Constructor<ClassLoaderFactory> constructor = classLoaderFactoryClass
                            .getConstructor(BootstrapProperties.class);
                    final ClassLoaderFactory classLoaderFactory = constructor.newInstance(bootstrapProperties);
                    classLoader = classLoaderFactory.create(classLoader);
                    Thread.currentThread().setContextClassLoader(classLoader);
                }
                final Object component = Class.forName(p.getProperty(PROPERTY_KEY), true, classLoader)
                        .newInstance();
                if (classloaderProperty != null) {
                    invokeMethod(component, "setClassLoader", new Class[] { ClassLoader.class },
                            new ClassLoader[] { classLoader });
                }
                return component;
            }
            return Class.forName(name).newInstance();
        } finally {
            Thread.currentThread().setContextClassLoader(originalContectClassLoader);
        }
    }

}