All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.graylog2.plugin.inject.Graylog2Module Maven / Gradle / Ivy

There is a newer version: 6.0.6
Show newest version
/**
 * This file is part of Graylog.
 *
 * Graylog is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * Graylog 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 General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with Graylog.  If not, see .
 */
package org.graylog2.plugin.inject;

import com.google.common.util.concurrent.Service;
import com.google.inject.AbstractModule;
import com.google.inject.Key;
import com.google.inject.TypeLiteral;
import com.google.inject.assistedinject.FactoryModuleBuilder;
import com.google.inject.multibindings.MapBinder;
import com.google.inject.multibindings.Multibinder;
import com.google.inject.multibindings.OptionalBinder;
import com.google.inject.name.Names;

import org.apache.shiro.realm.AuthenticatingRealm;
import org.graylog2.audit.AuditEventSender;
import org.graylog2.audit.AuditEventType;
import org.graylog2.audit.PluginAuditEventTypes;
import org.graylog2.audit.formatter.AuditEventFormatter;
import org.graylog2.migrations.Migration;
import org.graylog2.plugin.alarms.AlertCondition;
import org.graylog2.plugin.dashboards.widgets.WidgetStrategy;
import org.graylog2.plugin.decorators.SearchResponseDecorator;
import org.graylog2.plugin.indexer.retention.RetentionStrategy;
import org.graylog2.plugin.indexer.rotation.RotationStrategy;
import org.graylog2.plugin.inputs.MessageInput;
import org.graylog2.plugin.inputs.annotations.ConfigClass;
import org.graylog2.plugin.inputs.annotations.FactoryClass;
import org.graylog2.plugin.inputs.codecs.Codec;
import org.graylog2.plugin.inputs.transports.Transport;
import org.graylog2.plugin.lookup.LookupCache;
import org.graylog2.plugin.lookup.LookupCacheConfiguration;
import org.graylog2.plugin.lookup.LookupDataAdapter;
import org.graylog2.plugin.lookup.LookupDataAdapterConfiguration;
import org.graylog2.plugin.outputs.MessageOutput;
import org.graylog2.plugin.security.PasswordAlgorithm;
import org.graylog2.plugin.security.PluginPermissions;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.lang.annotation.Annotation;

import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import javax.ws.rs.container.ContainerResponseFilter;
import javax.ws.rs.container.DynamicFeature;
import javax.ws.rs.ext.ExceptionMapper;

public abstract class Graylog2Module extends AbstractModule {
    private static final Logger LOG = LoggerFactory.getLogger(Graylog2Module.class);

    protected void installTransport(
            MapBinder> mapBinder,
            String name,
            Class transportClass) {

        final Class configClass =
                (Class)
                        findInnerClassAnnotatedWith(ConfigClass.class, transportClass, Transport.Config.class);

        final Class> factoryClass =
                (Class>)
                        findInnerClassAnnotatedWith(FactoryClass.class, transportClass, Transport.Factory.class);

        if (configClass == null) {
            LOG.error("Unable to find an inner class annotated with @ConfigClass in transport {}. This transport will not be available!",
                    transportClass);
            return;
        }
        if (factoryClass == null) {
            LOG.error("Unable to find an inner class annotated with @FactoryClass in transport {}. This transport will not be available!",
                    transportClass);
            return;
        }
        installTransport(mapBinder, name, transportClass, configClass, factoryClass);
    }

    protected void installTransport(
            MapBinder> mapBinder,
            String name,
            Class transportClass,
            Class configClass,
            Class> factoryClass) {
        final Key> factoryKey = Key.get(factoryClass);
        install(new FactoryModuleBuilder()
                .implement(Transport.class, transportClass)
                .implement(Transport.Config.class, configClass)
                .build(factoryClass));

        mapBinder.addBinding(name).to(factoryKey);
    }

    protected void installCodec(MapBinder> mapBinder, Class codecClass) {
        if (codecClass.isAnnotationPresent(org.graylog2.plugin.inputs.annotations.Codec.class)) {
            final org.graylog2.plugin.inputs.annotations.Codec a = codecClass.getAnnotation(org.graylog2.plugin.inputs.annotations.Codec.class);
            installCodec(mapBinder, a.name(), codecClass);
        } else {
            LOG.error("Codec {} not annotated with {}. Cannot determine its id. This is a bug, please use that annotation, this codec will not be available",
                    codecClass, org.graylog2.plugin.inputs.annotations.Codec.class);
        }
    }

    protected void installCodec(
            MapBinder> mapBinder,
            String name,
            Class codecClass) {

        final Class configClass =
                (Class)
                        findInnerClassAnnotatedWith(ConfigClass.class, codecClass, Codec.Config.class);

        final Class> factoryClass =
                (Class>)
                        findInnerClassAnnotatedWith(FactoryClass.class, codecClass, Codec.Factory.class);

        if (configClass == null) {
            LOG.error("Unable to find an inner class annotated with @ConfigClass in codec {}. This codec will not be available!",
                    codecClass);
            return;
        }
        if (factoryClass == null) {
            LOG.error("Unable to find an inner class annotated with @FactoryClass in codec {}. This codec will not be available!",
                    codecClass);
            return;
        }
        installCodec(mapBinder, name, codecClass, configClass, factoryClass);
    }

    protected void installCodec(
            MapBinder> mapBinder,
            String name,
            Class codecClass,
            Class configClass,
            Class> factoryClass) {

        final Key> factoryKey = Key.get(factoryClass);

        install(new FactoryModuleBuilder()
                .implement(Codec.class, codecClass)
                .implement(Codec.Config.class, configClass)
                .build(factoryClass));

        mapBinder.addBinding(name).to(factoryKey);
    }

    @Nullable
    protected Class findInnerClassAnnotatedWith(Class annotationClass,
                                                   Class containingClass,
                                                   Class targetClass) {
        final Class[] declaredClasses = containingClass.getDeclaredClasses();
        Class annotatedClass = null;
        for (final Class declaredClass : declaredClasses) {
            if (!declaredClass.isAnnotationPresent(annotationClass)) {
                continue;
            }
            if (targetClass.isAssignableFrom(declaredClass)) {
                if (annotatedClass != null) {
                    LOG.error("Multiple annotations for {} found in {}. This is invalid.", annotatedClass.getSimpleName(), containingClass);
                    return null;
                }
                annotatedClass = declaredClass;
            } else {
                LOG.error("{} annotated as {} is not extending the expected {}. Did you forget to implement the correct interface?",
                        declaredClass, annotationClass.getSimpleName(), targetClass);
                return null;
            }
        }
        return annotatedClass;
    }

    protected MapBinder> codecMapBinder() {
        return MapBinder.newMapBinder(binder(),
                TypeLiteral.get(String.class),
                new TypeLiteral>() {
                });
    }

    protected MapBinder> transportMapBinder() {
        return MapBinder.newMapBinder(binder(),
                TypeLiteral.get(String.class),
                new TypeLiteral>() {
                });
    }

    protected MapBinder> inputsMapBinder() {
        return MapBinder.newMapBinder(binder(),
                TypeLiteral.get(String.class),
                new TypeLiteral>() {
                });
    }

    protected MapBinder rotationStrategiesMapBinder() {
        return MapBinder.newMapBinder(binder(), String.class, RotationStrategy.class);
    }

    protected MapBinder retentionStrategyMapBinder() {
        return MapBinder.newMapBinder(binder(), String.class, RetentionStrategy.class);
    }

    protected void installRotationStrategy(MapBinder mapBinder, Class target) {
        mapBinder.addBinding(target.getCanonicalName()).to(target);
    }

    protected void installRetentionStrategy(MapBinder mapBinder, Class target) {
        mapBinder.addBinding(target.getCanonicalName()).to(target);
    }

    protected  void installInput(MapBinder> inputMapBinder,
                                                         Class target,
                                                         Class> targetFactory) {
        install(new FactoryModuleBuilder().implement(MessageInput.class, target).build(targetFactory));
        inputMapBinder.addBinding(target.getCanonicalName()).to(Key.get(targetFactory));
    }

    protected  void installInput(MapBinder> inputMapBinder,
                                                         Class target) {
        Class> factoryClass =
                (Class>) findInnerClassAnnotatedWith(FactoryClass.class, target, MessageInput.Factory.class);

        if (factoryClass == null) {
            LOG.error("Unable to find an inner class annotated with @FactoryClass in input {}. This input will not be available!", target);
            return;
        }

        installInput(inputMapBinder, target, factoryClass);
    }

    protected MapBinder> outputsMapBinder() {
        return MapBinder.newMapBinder(binder(),
                TypeLiteral.get(String.class),
                new TypeLiteral>() {
                });
    }

    protected  void installOutput(MapBinder> outputMapBinder,
                                                           Class target,
                                                           Class> targetFactory) {
        install(new FactoryModuleBuilder().implement(MessageOutput.class, target).build(targetFactory));
        outputMapBinder.addBinding(target.getCanonicalName()).to(Key.get(targetFactory));
    }

    protected  void installOutput(MapBinder> outputMapBinder,
                                                           Class target) {
        Class> factoryClass =
                (Class>) findInnerClassAnnotatedWith(FactoryClass.class, target, MessageOutput.Factory.class);

        if (factoryClass == null) {
            LOG.error("Unable to find an inner class annotated with @FactoryClass in output {}. This output will not be available!", target);
            return;
        }

        installOutput(outputMapBinder, target, factoryClass);
    }

    protected MapBinder> widgetStrategyBinder() {
        return MapBinder.newMapBinder(binder(), TypeLiteral.get(String.class), new TypeLiteral>() {
        });
    }

    protected void installWidgetStrategy(MapBinder> widgetStrategyBinder,
                                         Class target,
                                         Class> targetFactory) {
        install(new FactoryModuleBuilder().implement(WidgetStrategy.class, target).build(targetFactory));
        widgetStrategyBinder.addBinding(target.getCanonicalName()).to(Key.get(targetFactory));
    }

    protected void installWidgetStrategyWithAlias(MapBinder> widgetStrategyBinder,
                                                  String key,
                                                  Class target,
                                                  Class> targetFactory) {
        installWidgetStrategy(widgetStrategyBinder, target, targetFactory);
        widgetStrategyBinder.addBinding(key).to(Key.get(targetFactory));
    }

    protected Multibinder permissionsBinder() {
        return Multibinder.newSetBinder(binder(), PluginPermissions.class);
    }

    protected void installPermissions(Multibinder classMultibinder,
                                      Class permissionsClass) {
        classMultibinder.addBinding().to(permissionsClass);
    }

    protected Multibinder auditEventTypesBinder() {
        return Multibinder.newSetBinder(binder(), PluginAuditEventTypes.class);
    }

    protected void installAuditEventTypes(Multibinder classMultibinder,
                                          Class auditEventTypesClass) {
        classMultibinder.addBinding().to(auditEventTypesClass);
    }

    protected MapBinder auditEventFormatterMapBinder() {
        return MapBinder.newMapBinder(binder(), AuditEventType.class, AuditEventFormatter.class);
    }

    protected void installAuditEventFormatter(MapBinder auditEventFormatterMapBinder,
                                              AuditEventType auditEventType,
                                              Class auditEventFormatter) {
        auditEventFormatterMapBinder.addBinding(auditEventType).to(auditEventFormatter);
    }

    protected OptionalBinder auditEventSenderBinder() {
        return OptionalBinder.newOptionalBinder(binder(), AuditEventSender.class);
    }


    @Nonnull
    protected Multibinder> jerseyDynamicFeatureBinder() {
        return Multibinder.newSetBinder(binder(), new DynamicFeatureType());
    }

    @Nonnull
    protected Multibinder> jerseyContainerResponseFilterBinder() {
        return Multibinder.newSetBinder(binder(), new ContainerResponseFilterType());
    }

    @Nonnull
    protected Multibinder> jerseyExceptionMapperBinder() {
        return Multibinder.newSetBinder(binder(), new ExceptionMapperType());
    }

    @Nonnull
    protected Multibinder jerseyAdditionalComponentsBinder() {
        return Multibinder.newSetBinder(binder(), Class.class, Names.named("additionalJerseyComponents"));
    }

    protected Multibinder serviceBinder() {
        return Multibinder.newSetBinder(binder(), Service.class);
    }

    protected MapBinder passwordAlgorithmBinder() {
        return MapBinder.newMapBinder(binder(), String.class, PasswordAlgorithm.class);
    }

    protected MapBinder authenticationRealmBinder() {
        return MapBinder.newMapBinder(binder(), String.class, AuthenticatingRealm.class);
    }

    protected MapBinder searchResponseDecoratorBinder() {
        return MapBinder.newMapBinder(binder(), String.class, SearchResponseDecorator.Factory.class);
    }

    protected void installSearchResponseDecorator(MapBinder searchResponseDecoratorBinder,
                                                  Class searchResponseDecoratorClass,
                                                  Class searchResponseDecoratorFactoryClass) {
        install(new FactoryModuleBuilder().implement(SearchResponseDecorator.class, searchResponseDecoratorClass).build(searchResponseDecoratorFactoryClass));
        searchResponseDecoratorBinder.addBinding(searchResponseDecoratorClass.getCanonicalName()).to(searchResponseDecoratorFactoryClass);
    }

    protected MapBinder alertConditionBinder() {
        return MapBinder.newMapBinder(binder(), String.class, AlertCondition.Factory.class);
    }

    protected void installAlertCondition(MapBinder alertConditionBinder,
                                         Class alertConditionClass,
                                         Class alertConditionFactoryClass) {
        install(new FactoryModuleBuilder().implement(AlertCondition.class, alertConditionClass).build(alertConditionFactoryClass));
        alertConditionBinder.addBinding(alertConditionClass.getCanonicalName()).to(alertConditionFactoryClass);
    }

    protected void installAlertConditionWithCustomName(MapBinder alertConditionBinder,
                                                       String identifier,
                                                       Class alertConditionClass,
                                                       Class alertConditionFactoryClass) {
        install(new FactoryModuleBuilder().implement(AlertCondition.class, alertConditionClass).build(alertConditionFactoryClass));
        alertConditionBinder.addBinding(identifier).to(alertConditionFactoryClass);
    }

    protected MapBinder lookupCacheBinder() {
        return MapBinder.newMapBinder(binder(), String.class, LookupCache.Factory.class);
    }

    protected void installLookupCache(String name,
                                      Class cacheClass,
                                      Class factoryClass,
                                      Class configClass) {
        install(new FactoryModuleBuilder().implement(LookupCache.class, cacheClass).build(factoryClass));
        lookupCacheBinder().addBinding(name).to(factoryClass);
        jacksonSubTypesBinder().addBinding(name).toInstance(configClass);
    }


    protected MapBinder lookupDataAdapterBinder() {
        return MapBinder.newMapBinder(binder(), String.class, LookupDataAdapter.Factory.class);
    }

    protected void installLookupDataAdapter(String name,
                                            Class adapterClass,
                                            Class factoryClass,
                                            Class configClass) {
        install(new FactoryModuleBuilder().implement(LookupDataAdapter.class, adapterClass).build(factoryClass));
        lookupDataAdapterBinder().addBinding(name).to(factoryClass);
        jacksonSubTypesBinder().addBinding(name).toInstance(configClass);
    }

    protected MapBinder jacksonSubTypesBinder() {
        return MapBinder.newMapBinder(binder(), TypeLiteral.get(String.class), TypeLiteral.get(Object.class), JacksonSubTypes.class);
    }

    protected Multibinder migrationsBinder() {
        return Multibinder.newSetBinder(binder(), Migration.class);
    }

    private static class DynamicFeatureType extends TypeLiteral> {}

    private static class ContainerResponseFilterType extends TypeLiteral> {}

    private static class ExceptionMapperType extends TypeLiteral> {}
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy