com.flipkart.polyguice.dropwiz.PolyguiceApp.java Source code

Java tutorial

Introduction

Here is the source code for com.flipkart.polyguice.dropwiz.PolyguiceApp.java

Source

/*
 * Copyright (c) The original author or authors
 *
 * 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.flipkart.polyguice.dropwiz;

import io.dropwizard.Application;
import io.dropwizard.Configuration;
import io.dropwizard.lifecycle.Managed;
import io.dropwizard.setup.Environment;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;

import javax.servlet.Servlet;
import javax.servlet.ServletRegistration;
import javax.servlet.annotation.WebInitParam;
import javax.servlet.annotation.WebServlet;

import org.apache.commons.lang3.StringUtils;
import org.reflections.Reflections;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.flipkart.polyguice.core.support.Polyguice;

/**
 * @author indroneel.das
 *
 */

public class PolyguiceApp<T extends Configuration> extends Application<T> {

    private static final Logger LOGGER = LoggerFactory.getLogger(PolyguiceApp.class);

    private List<String> scanPkgNames;
    private Polyguice polyguice;

    public PolyguiceApp() {
        scanPkgNames = new ArrayList<>();
    }

    public final PolyguiceApp<T> setPolyguice(Polyguice pg) {
        polyguice = pg;
        return this;
    }

    public final PolyguiceApp<T> scanPackage(String name) {
        scanPkgNames.add(name);
        return this;
    }

    ////////////////////////////////////////////////////////////////////////////
    // Methods of base class Application

    @Override
    public final void run(T config, Environment env) throws Exception {

        if (polyguice == null) {
            throw new RuntimeException("polyguice not set");
        }

        if (polyguice.isPrepared()) {
            throw new RuntimeException("polyguice should not be prepared yet");
        }

        preRun(config, env);

        DropConfigProvider dcp = new DropConfigProvider(config);
        polyguice.registerConfigurationProvider(dcp);
        polyguice.prepare();

        Set<Class<?>> resTypes = findResourceTypes();
        LOGGER.debug("found potential resources: {}", resTypes);
        for (Class<?> cls : resTypes) {
            try {
                Object resource = createResource(cls, config, env);
                if (resource != null) {
                    LOGGER.debug("resource created: {}", cls.getName());
                    polyguice.getComponentContext().inject(resource);
                    env.jersey().register(resource);
                } else {
                    LOGGER.warn("error creating resource: {}", cls.getName());
                }
            } catch (Exception exep) {
                LOGGER.error(exep.getMessage(), exep);
            }
        }

        List<Class<?>> servletTypes = findServletTypes();
        LOGGER.debug("found potential servlets: {}", servletTypes);
        for (Class<?> type : servletTypes) {
            registerServlet(type, env);
        }

        env.lifecycle().manage(new PolyguiceManaged());
        postRun(config, env);
    }

    ////////////////////////////////////////////////////////////////////////////
    // Methods to be implemented or used from derived classes

    protected final Polyguice getPolyguice() {
        return polyguice;
    }

    protected void preRun(T config, Environment env) throws Exception {
        //NOOP
    }

    protected void postRun(T config, Environment env) throws Exception {
        //NOOP
    }

    ////////////////////////////////////////////////////////////////////////////
    // Helper methods

    private Set<Class<?>> findResourceTypes() {
        Reflections reflections = new Reflections(scanPkgNames.toArray());
        return reflections.getTypesAnnotatedWith(Resource.class);
    }

    private List<Class<?>> findServletTypes() {
        Reflections reflections = new Reflections(scanPkgNames.toArray());
        Set<Class<?>> types = reflections.getTypesAnnotatedWith(WebServlet.class);
        List<Class<?>> result = new ArrayList<>();
        for (Class<?> type : types) {
            if (Servlet.class.isAssignableFrom(type)) {
                result.add(type);
            }
        }
        return result;
    }

    private Object createResource(Class<?> cls, T config, Environment env) throws InstantiationException,
            IllegalAccessException, IllegalArgumentException, InvocationTargetException {

        LOGGER.debug("creating object of type {}", cls);
        try {
            Constructor<?> ctor = cls.getConstructor(Configuration.class, Environment.class);
            int mod = ctor.getModifiers();
            if (Modifier.isPublic(mod) && !Modifier.isAbstract(mod)) {
                LOGGER.debug("using ctor {}", ctor.toGenericString());
                return ctor.newInstance(config, env);
            }
        } catch (NoSuchMethodException exep) {
            //NOOP, not even log
        }

        try {
            Constructor<?> ctor = cls.getConstructor(Environment.class, Configuration.class);
            int mod = ctor.getModifiers();
            if (Modifier.isPublic(mod) && !Modifier.isAbstract(mod)) {
                LOGGER.debug("using ctor {}", ctor.toGenericString());
                return ctor.newInstance(env, config);
            }
        } catch (NoSuchMethodException exep) {
            //NOOP, not even log
        }

        try {
            Constructor<?> ctor = cls.getConstructor(Configuration.class);
            int mod = ctor.getModifiers();
            if (Modifier.isPublic(mod) && !Modifier.isAbstract(mod)) {
                LOGGER.debug("using ctor {}", ctor.toGenericString());
                return ctor.newInstance(config);
            }
        } catch (NoSuchMethodException exep) {
            //NOOP, not even log
        }

        try {
            Constructor<?> ctor = cls.getConstructor(Environment.class);
            int mod = ctor.getModifiers();
            if (Modifier.isPublic(mod) && !Modifier.isAbstract(mod)) {
                LOGGER.debug("using ctor {}", ctor.toGenericString());
                return ctor.newInstance(env);
            }
        } catch (NoSuchMethodException exep) {
            //NOOP, not even log
        }

        try {
            Constructor<?> ctor = cls.getConstructor();
            int mod = ctor.getModifiers();
            if (Modifier.isPublic(mod) && !Modifier.isAbstract(mod)) {
                LOGGER.debug("using ctor {}", ctor.toGenericString());
                return ctor.newInstance();
            }
        } catch (NoSuchMethodException exep) {
            //NOOP, not even log
        }
        return null;
    }

    private void registerServlet(Class<?> type, Environment env) {
        LOGGER.debug("registering servlet: {}", type.getName());
        WebServlet ann = type.getAnnotation(WebServlet.class);
        String srvName = ann.name();
        if (StringUtils.isBlank(srvName)) {
            LOGGER.error("servlet {}: name could not be blank", type.getName());
            return;
        }
        String[] paths = ann.urlPatterns();
        if (paths == null || paths.length == 0) {
            paths = ann.value();
            if (paths == null || paths.length == 0) {
                LOGGER.error("url patterns missing for servlet {}", type.getName());
                return;
            }
        }
        int losu = ann.loadOnStartup();
        Servlet servlet = null;
        try {
            servlet = (Servlet) type.newInstance();
            polyguice.getComponentContext().inject(servlet);
        } catch (Exception exep) {
            LOGGER.error("error creating servlet {}", type.getName());
            return;
        }
        ServletRegistration.Dynamic dynamic = env.servlets().addServlet(srvName, servlet);
        dynamic.addMapping(paths);
        dynamic.setLoadOnStartup(losu);
        if (ann.initParams() == null) {
            return;
        }
        for (WebInitParam param : ann.initParams()) {
            String name = param.name();
            String value = param.value();
            if (StringUtils.isNoneBlank(name)) {
                dynamic.setInitParameter(name, value);
            }
        }
    }

    ////////////////////////////////////////////////////////////////////////////
    // Inner class for managing Polyguice

    private class PolyguiceManaged implements Managed {

        public void start() throws Exception {
            /*
             * NOOP. Polyguice must already be prepared and started before this
             * method is called.
             */
        }

        @Override
        public void stop() throws Exception {
            if (polyguice != null) {
                polyguice.stop();
            }
        }
    }
}