package com.hivemq.spi.services.rest; import com.hivemq.spi.annotations.NotNull; import com.hivemq.spi.annotations.ReadOnly; import com.hivemq.spi.annotations.ThreadSafe; import com.hivemq.spi.services.rest.listener.HttpListener; import com.hivemq.spi.services.rest.listener.Listener; import com.hivemq.spi.services.rest.servlet.ServletFilter; import javax.servlet.Filter; import javax.servlet.http.HttpServlet; import javax.ws.rs.core.Application; import javax.ws.rs.ext.ContextResolver; import javax.ws.rs.ext.ExceptionMapper; import javax.ws.rs.ext.MessageBodyReader; import javax.ws.rs.ext.MessageBodyWriter; import java.util.Collection; /** * This HiveMQ REST service allows to expose Java Servlets (3.0), Filters and JAX-RS (2.0) resources. * <p/> * The REST service has a listener concept so different resources can be bound to different * transports (TCP / TLS) and different ports on different interfaces. * <p/> * The REST Service supports first-class dependency injection and even allows to use constructor injection. * <p/> * It's possible to annotate JAX-RS resources with {@link javax.inject.Singleton} to bind a resource to a singleton * context instead of a per-request context. * <p> * The REST Service implementation is guaranteed to be thread safe. * * @author Dominik Obermaier * @since 3.0 */ @ThreadSafe public interface RESTService { /** * Adds a new listener to the REST Service programmatically. * <p/> * Note: Typically the listeners are added via the configuration file. If adding * the configuration via the config file does not suit your needs, the programmatic API * offers a convenient way to add an arbitrary number of listeners at runtime. * <p/> * Note: If you add listeners at runtime, existing servlets or JAX-RS resource on other listeners won't be added * to this new listener automatically. * * @param listener the {@link Listener} implementation * @throws NullPointerException if the passed listener is <code>null</code> * @throws IllegalArgumentException if the passed listener is not a valid listener type (like {@link HttpListener} */ void addListener(@NotNull Listener listener); /** * Returns an immutable view of all listeners. * <p/> * In order to get more information you need to downcast to a specific listener type. You can do this e.g. by * code such as * <pre> * if (listener instanceof HttpListener) { * HttpListener httpListener = (HttpListener) listener; * } * </pre> * * @return an immutable view of all listeners */ @ReadOnly Collection<Listener> getListeners(); /** * Adds a servlet instance to a specific path and adds the servlet to all available listeners. * * @param servlet the servlet to add * @param path the path to bind the servlet to * @throws NullPointerException if the servlet or the path is null */ void addServlet(@NotNull HttpServlet servlet, @NotNull String path); /** * Adds a servlet instance to a specific path and adds the servlet to all specified listeners. If the * collection of listeners is empty, the servlet will be added to all available listeners * * @param servlet the servlet to add * @param path the path to bind the servlet to * @param listenerIdentifiers a collection with identifiers of listeners * @throws NullPointerException if the servlet, the path or the listener identifiers collection is null */ void addServlet(@NotNull HttpServlet servlet, @NotNull String path, @NotNull Collection<String> listenerIdentifiers); /** * Adds a servlet to a specific path and adds the servlet to all available listeners. * <p/> * The given servlet class will be instantiated by HiveMQ and the servlet can use dependency injection. * <p/> * The servlet will be instantiated once and not per request, so it's essentially a singleton. * * @param servlet the servlet to add * @param path the path to bind the servlet to * @return The instantiated servlet * @throws NullPointerException if the servlet or the path is null */ <T extends HttpServlet> T addServlet(@NotNull Class<T> servlet, @NotNull String path); /** * Adds a servlet to a specific path and adds the servlet to all specified listeners. If the * collection of listeners is empty, the servlet will be added to all available listeners * <p/> * The given servlet class will be instantiated by HiveMQ and the servlet can use dependency injection. * <p/> * The servlet will be instantiated once and not per request, so it's essentially a singleton. * * @param servlet the servlet to add * @param path the path to bind the servlet to * @param listenerIdentifiers a collection with identifiers of listeners * @return The instantiated servlet * @throws NullPointerException if the servlet or the path is null */ <T extends HttpServlet> T addServlet(@NotNull Class<T> servlet, @NotNull String path, @NotNull Collection<String> listenerIdentifiers); /** * Adds a specific {@link ServletFilter} with a given path to the RESTService on all available listeners. * * @param filter the {@link ServletFilter} * @param path the Path * @param <T> the {@link Filter} which is contained in the {@link ServletFilter} * @return the concrete {@link Filter} instance * @throws NullPointerException if the {@link ServletFilter} or path is null */ <T extends Filter> T addFilter(@NotNull ServletFilter<T> filter, @NotNull String path); /** * Adds a specific {@link ServletFilter} with a given path to the RESTService on specific listeners. * * @param filter the {@link ServletFilter} * @param path the Path * @param listeners a collection of listeners * @param <T> the {@link Filter} which is contained in the {@link ServletFilter} * @return the concrete {@link Filter} instance * @throws NullPointerException if the {@link ServletFilter}, path or listener collection is null */ <T extends Filter> T addFilter(@NotNull ServletFilter<T> filter, @NotNull String path, @NotNull Collection<String> listeners); /** * Adds a servlet instance to a specific path and adds the servlet to all available listeners. * <p/> * Additionally a servlet filter is added directly to the servlet path mapping. This is a convenient * method if you need a specific filter only for one servlet * * @param servlet the servlet to add * @param path the path to bind the servlet to * @param filters an arbitrary amount of filters for this specific servlet * @throws NullPointerException if the servlet, the path or the filter array is null */ @SuppressWarnings("unchecked") void addServletWithFilters(@NotNull HttpServlet servlet, @NotNull String path, @NotNull ServletFilter<? extends Filter>... filters); /** * Adds a servlet instance to a specific path and adds the servlet to all specific listeners. * <p/> * Additionally a servlet filter is added directly to the servlet path mapping. This is a convenient * method if you need a specific filter only for one servlet and only on specific listeners * * @param servlet the servlet to add * @param path the path to bind the servlet to * @param listenerIdentifiers a collection of listener identifierd * @param filters an arbitrary amount of filters for this specific servlet * @throws NullPointerException if the servlet, the path, the listener collection or the filter array is null */ @SuppressWarnings("unchecked") void addServletWithFilters(@NotNull HttpServlet servlet, @NotNull String path, @NotNull Collection<String> listenerIdentifiers, @NotNull ServletFilter<? extends Filter>... filters); /** * Adds a servlet to a specific path and adds the servlet to all available listeners. If the * collection of listeners is empty, the servlet will be added to all available listeners * <p/> * The given servlet class will be instantiated by HiveMQ and the servlet can use dependency injection. * <p/> * Additionally a servlet filter is added directly to the servlet path mapping. This is a convenient * method if you need a specific filter only for one servlet * * @param servlet the servlet to add * @param path the path to bind the servlet to * @param filters an arbitrary amount of filters for this specific servlet * @return the instantiated servlet * @throws NullPointerException if the servlet, the path or the filter array is null */ @SuppressWarnings("unchecked") <T extends HttpServlet> T addServletWithFilters(@NotNull Class<T> servlet, @NotNull String path, @NotNull ServletFilter<? extends Filter>... filters); /** * Adds a servlet to a specific path and adds the servlet to all specified listeners. If the * collection of listeners is empty, the servlet will be added to all available listeners * <p/> * The given servlet class will be instantiated by HiveMQ and the servlet can use dependency injection. * <p/> * Additionally a servlet filter is added directly to the servlet path mapping. This is a convenient * method if you need a specific filter only for one servlet * * @param servlet the servlet to add * @param path the path to bind the servlet to * @param listenerIdentifiers the collection of listeners * @param filters an arbitrary amount of filters for this specific servlet * @return the instantiated servlet * @throws NullPointerException if the servlet, the path or the filter array is null */ @SuppressWarnings("unchecked") <T extends HttpServlet> T addServletWithFilters(@NotNull Class<T> servlet, @NotNull String path, @NotNull Collection<String> listenerIdentifiers, @NotNull ServletFilter<? extends Filter>... filters); /** * Adds a {@link Application} to the RESTService. * <p/> * Please be aware that when using this method, only all properties, classes and singletons are * added to the RESTService, the {@link Application} and all annotations on the {@link Application} * are ignored. So essentially this is a convenient method which allows you to add a lot of resources at once * <p/> * Important: {@link javax.ws.rs.ApplicationPath} annotations are ignored. * <p/> * All resources defined in the Application will be added to all available listeners. * * @param application the {@link Application} * @throws NullPointerException if the passed {@link Application} is null */ void addJaxRsApplication(@NotNull Application application); /** * Adds a {@link Application} to the RESTService. * <p/> * Please be aware that when using this method, only all properties, classes and singletons are * added to the RESTService, the {@link Application} and all annotations on the {@link Application} * are ignored. So essentially this is a convenient method which allows you to add a lot of resources at once * <p/> * Important: {@link javax.ws.rs.ApplicationPath} annotations are ignored. * <p/> * All resources defined in the Application will be added to all specified listeners. * * @param application the {@link Application} * @param listenerIdentifiers a collection of listeners * @throws NullPointerException if the passed {@link Application} or the collection of listeners is null */ void addJaxRsApplication(@NotNull Application application, @NotNull Collection<String> listenerIdentifiers); /** * Adds all given JAX-RS resources as singleton to all available listeners. * Since you have to instantiate the singleton objects on your own, * these singletons can't use dependency injection by HiveMQ and you have to pass your dependencies on your own * to the objects. * <p/> * If you want to have singletons which use dependency injection, consider using another method of the RESTService * which accepts classes instead of objects. You can annotate these methods with {@link javax.inject.Singleton} * * @param singletons an arbitrary number of singleton resources * @throws NullPointerException if the singleton array is null */ void addJaxRsSingletons(@NotNull Object... singletons); /** * Adds all given JAX-RS resources as singleton to all specified listeners. * Since you have to instantiate the singleton objects on your own, * these singletons can't use dependency injection by HiveMQ and you have to pass your dependencies on your own * to the objects. * <p/> * If you want to have singletons which use dependency injection, consider using another method of the RESTService * which accepts classes instead of objects. You can annotate these methods with {@link javax.inject.Singleton} * * @param singletons an collection of singleton resources * @param listenerIdentifiers a collection of listeners * @throws NullPointerException if the singleton array is null */ void addJaxRsSingletons(@NotNull Collection<Object> singletons, @NotNull Collection<String> listenerIdentifiers); /** * Adds an arbitrary number of JAX-RS resources to all available listeners. * These resources can use dependency injection and HiveMQ will instantiate the resources for you at runtime * * @param resources a arbitrary number of JAX-RS resource classes * @throws NullPointerException if the resources array is null */ void addJaxRsResources(@NotNull Class<?>... resources); /** * Adds an arbitrary number of JAX-RS resources to all specified listeners. * These resources can use dependency injection and HiveMQ will instantiate the resources for you at runtime * * @param resources a collection of JAX-RS resource classes * @param listenerIdentifiers a collection of listeners * @throws NullPointerException if the resources array or the listener collection is null */ void addJaxRsResources(@NotNull Collection<Class<?>> resources, @NotNull Collection<String> listenerIdentifiers); /** * Adds an {@link ExceptionMapper} to all available listeners. * <p> * Since you have to instantiate the {@link ExceptionMapper} objects on your own, * it can't use dependency injection by HiveMQ and you have to pass your dependencies on your own * to the objects. * <p/> * If you want to have {@link ExceptionMapper}s which use dependency injection, * consider using another method of the RESTService which accepts classes instead of objects. * * @param exceptionMapper the JAX-RS {@link ExceptionMapper} instance that should be added to all listeners * @throws NullPointerException if the ExceptionMapper is null * @since 3.2 */ void addExceptionMapper(@NotNull final ExceptionMapper<? extends Throwable> exceptionMapper); /** * Adds an {@link ExceptionMapper} to all specified listeners. * <p> * Since you have to instantiate the {@link ExceptionMapper} objects on your own, * it can't use dependency injection by HiveMQ and you have to pass your dependencies on your own * to the objects. * <p/> * If you want to have {@link ExceptionMapper}s which use dependency injection, * consider using another method of the RESTService which accepts classes instead of objects. * * @param exceptionMapper the JAX-RS {@link ExceptionMapper} instance that should be added to all specified listeners * @param listenerIdentifier a collection of listeners * @throws NullPointerException if the ExceptionMapper or the listener collection is null * @since 3.2 */ void addExceptionMapper(@NotNull final ExceptionMapper<? extends Throwable> exceptionMapper, @NotNull final Collection<String> listenerIdentifier); /** * Adds an {@link ExceptionMapper} to all available listeners. * <p> * The ExceptionMapper can use dependency injection and HiveMQ will instantiate it for you at runtime * * @param exceptionMapper the JAX-RS {@link ExceptionMapper} class that should be added to all listeners * @throws NullPointerException if the ExceptionMapper is null * @since 3.2 */ void addExceptionMapper(@NotNull final Class<? extends ExceptionMapper<? extends Throwable>> exceptionMapper); /** * Adds an {@link ExceptionMapper} to all specified listeners. * <p> * The ExceptionMapper can use dependency injection and HiveMQ will instantiate it for you at runtime * * @param exceptionMapper the JAX-RS {@link ExceptionMapper} class that should be added to all specified listeners * @param listenerIdentifier a collection of listeners * @throws NullPointerException if the ExceptionMapper or the listener collection is null * @since 3.2 */ void addExceptionMapper(@NotNull final Class<? extends ExceptionMapper<? extends Throwable>> exceptionMapper, @NotNull final Collection<String> listenerIdentifier); /** * Adds an {@link ContextResolver} to all available listeners. * <p> * The ContextResolver can use dependency injection and HiveMQ will instantiate it for you at runtime * * @param contextResolver the JAX-RS {@link ContextResolver} class that should be added to all listeners * @throws NullPointerException if the ContextResolver is null * @since 3.2 */ void addContextResolver(@NotNull final Class<? extends ContextResolver> contextResolver); /** * Adds an {@link ContextResolver} to all specified listeners. * <p> * The ContextResolver can use dependency injection and HiveMQ will instantiate it for you at runtime * * @param contextResolver the JAX-RS {@link ContextResolver} class that should be added to all specified listeners * @param listenerIdentifier the collection of listeners * @throws NullPointerException if the ContextResolver or the listener collection is null * @since 3.2 */ void addContextResolver(@NotNull final Class<? extends ContextResolver> contextResolver, @NotNull final Collection<String> listenerIdentifier); /** * Adds a {@link MessageBodyWriter} to all listeners. * <p> * The MessageBodyWriter can use dependency injection and HiveMQ will instantiate it for you at runtime * * @param messageBodyWriter the JAX-RS {@link MessageBodyWriter} class that should be added to all listeners * @throws NullPointerException if the MessageBodyWriter is null * @since 3.2 */ void addMessageBodyWriter(@NotNull final Class<? extends MessageBodyWriter> messageBodyWriter); /** * Adds a {@link MessageBodyWriter} to all specified listeners. * <p> * The MessageBodyWriter can use dependency injection and HiveMQ will instantiate it for you at runtime * * @param messageBodyWriter the JAX-RS {@link MessageBodyWriter} class that should be added to all specified listeners * @param listenerIdentifier the collection of listeners * @throws NullPointerException if the MessageBodyWriter or the listener collection is null * @since 3.2 */ void addMessageBodyWriter(@NotNull final Class<? extends MessageBodyWriter> messageBodyWriter, @NotNull final Collection<String> listenerIdentifier); /** * Adds a {@link MessageBodyReader} to all listeners. * <p> * The MessageBodyReader can use dependency injection and HiveMQ will instantiate it for you at runtime * * @param messageBodyReader the JAX-RS {@link MessageBodyReader} class that should be added to all listeners * @throws NullPointerException if the MessageBodyReader is null * @since 3.2 */ void addMessageBodyReader(@NotNull final Class<? extends MessageBodyReader> messageBodyReader); /** * Adds a {@link MessageBodyReader} to all specified listeners. * <p> * The MessageBodyReader can use dependency injection and HiveMQ will instantiate it for you at runtime * * @param messageBodyReader the JAX-RS {@link MessageBodyReader} class that should be added to all specified listeners * @param listenerIdentifier the collection of listeners * @throws NullPointerException if the MessageBodyReader or the listener collection is null * @since 3.2 */ void addMessageBodyReader(@NotNull final Class<? extends MessageBodyReader> messageBodyReader, @NotNull final Collection<String> listenerIdentifier); }