Java tutorial
/* ========================================================================== * * Copyright 2014 USRZ.com and Pier Paolo Fumagalli * * -------------------------------------------------------------------------- * * 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 org.usrz.libs.httpd; import static org.usrz.libs.httpd.ServerBuilder.RedirectConfigurator.Flags.MATCH_ENTIRE_LINE; import static org.usrz.libs.httpd.ServerBuilder.RedirectConfigurator.Flags.PERMANENT_REDIRECT; import static org.usrz.libs.httpd.ServerBuilder.RedirectConfigurator.Flags.PRESERVE_QUERY_STRING; import static org.usrz.libs.httpd.inject.HttpHandlerProvider.handlerPath; import static org.usrz.libs.utils.Check.notNull; import java.io.File; import java.util.Collections; import java.util.EnumSet; import java.util.Set; import java.util.function.Consumer; import javax.inject.Provider; import javax.ws.rs.core.Application; import org.glassfish.grizzly.http.server.ErrorPageGenerator; import org.glassfish.grizzly.http.server.HttpHandler; import org.glassfish.grizzly.http.server.HttpServer; import org.glassfish.grizzly.http.server.NetworkListener; import org.glassfish.grizzly.http.server.accesslog.AccessLogProbe; import org.glassfish.jersey.server.ResourceConfig; import org.usrz.libs.configurations.Configurations; import org.usrz.libs.httpd.handlers.FileHandlerProvider; import org.usrz.libs.httpd.handlers.RedirectHandler; import org.usrz.libs.httpd.handlers.RestHandlerProvider; import org.usrz.libs.httpd.handlers.RestObjectMapperProvider; import org.usrz.libs.httpd.inject.AccessLogProvider; import org.usrz.libs.httpd.inject.DefaultEPGProvider; import org.usrz.libs.httpd.inject.HttpHandlerPath; import org.usrz.libs.httpd.inject.HttpHandlerProvider; import org.usrz.libs.httpd.inject.HttpServerConfigurations; import org.usrz.libs.httpd.inject.HttpServerProvider; import org.usrz.libs.httpd.inject.NetworkListenerProvider; import org.usrz.libs.utils.inject.ConfiguringBindingBuilder; import com.fasterxml.jackson.databind.ObjectMapper; import com.google.inject.Binder; import com.google.inject.Key; import com.google.inject.Module; import com.google.inject.TypeLiteral; import com.google.inject.name.Names; public class ServerBuilder extends ConfiguringBindingBuilder<ServerBuilder> { protected ServerBuilder(Binder binder) { super(binder, HttpServerConfigurations.class); /* Add the HttpServer in the child isolate as it might needs configs */ binder.bind(HttpServer.class).toProvider(HttpServerProvider.class); } /* ====================================================================== */ public void install(Consumer<Binder> consumer) { consumer.accept(binder()); } public void install(Module... modules) { for (Module module : modules) binder().install(module); } /* ---------------------------------------------------------------------- */ @Override public ServerBuilder configure(Configurations configurations) { /* Add our access log if configured */ final Configurations accessLog = configurations.strip("access_log"); if (!accessLog.isEmpty()) addAccessLog(accessLog); /* Add our singleton listener configured */ final Configurations listener = configurations.strip("listener"); if (!listener.isEmpty()) addListener(listener); /* Add any other listener grouped by "listeners" */ configurations.group("listeners").values().forEach((configuration) -> addListener(configuration)); /* Any document root? */ final File documentRoot = configurations.getFile("document_root"); if (documentRoot != null) this.serveFiles("/", documentRoot); /* And finally remember our JSON configurations */ final Configurations json = configurations.strip("json"); if (!json.isEmpty()) withObjectMapperDefaults(json); /* Bind the configurations for the server */ return super.configure(configurations); } /* ====================================================================== */ public void withObjectMapperDefaults(Configurations configurations) { binder().bind(ObjectMapper.class).toProvider(new RestObjectMapperProvider(configurations)); } /* ====================================================================== */ public void withErrorPageGenerator(ErrorPageGenerator generator) { binder().bind(ErrorPageGenerator.class).toProvider(new DefaultEPGProvider(generator)); } public void withErrorPageGenerator(Class<? extends ErrorPageGenerator> generator) { binder().bind(ErrorPageGenerator.class).toProvider(new DefaultEPGProvider(Key.get(generator))); } public void withErrorPageGenerator(TypeLiteral<? extends ErrorPageGenerator> generator) { binder().bind(ErrorPageGenerator.class).toProvider(new DefaultEPGProvider(Key.get(generator))); } public void withErrorPageGenerator(Key<? extends ErrorPageGenerator> generator) { binder().bind(ErrorPageGenerator.class).toProvider(new DefaultEPGProvider(generator)); } /* ====================================================================== */ public void addAccessLog(Configurations configurations) { final AccessLogProvider provider = new AccessLogProvider(configurations); binder().bind(AccessLogProbe.class).annotatedWith(Names.named(provider.getName())).toProvider(provider) .asEagerSingleton(); } /* ====================================================================== */ public void addListener(Configurations configurations) { final NetworkListenerProvider provider = new NetworkListenerProvider(configurations); binder().bind(NetworkListener.class).annotatedWith(Names.named(provider.getName())).toProvider(provider) .asEagerSingleton(); } /* ====================================================================== */ private void addHandler(HttpHandlerPath path, Provider<HttpHandler> provider) { binder().bind(HttpHandler.class).annotatedWith(path).toProvider(provider).asEagerSingleton(); } /* ---------------------------------------------------------------------- */ public void addHandler(String path, HttpHandler handler) { final HttpHandlerPath at = handlerPath(path); this.addHandler(at, new HttpHandlerProvider(handler, at)); } public void addHandler(String path, Class<? extends HttpHandler> handler) { this.addHandler(path, Key.get(handler)); } public void addHandler(String path, TypeLiteral<? extends HttpHandler> handler) { this.addHandler(path, Key.get(handler)); } public void addHandler(String path, Key<? extends HttpHandler> handler) { final HttpHandlerPath at = handlerPath(path); this.addHandler(at, new HttpHandlerProvider(handler, at)); } /* ---------------------------------------------------------------------- */ public void serveFiles(String path, File documentRoot) { final HttpHandlerPath at = handlerPath(path); this.addHandler(at, new FileHandlerProvider(documentRoot, at)); } public void serveFiles(String path, String documentRoot) { this.serveFiles(path, new File(documentRoot)); } /* ---------------------------------------------------------------------- */ public RestConfigurator serveApp(String path, Application application) { final HttpHandlerPath at = handlerPath(path); this.addHandler(at, new RestHandlerProvider(application, at)); return new RestConfigurator(at); } public RestConfigurator serveApp(String path, Consumer<ResourceConfig> consumer) { final HttpHandlerPath at = handlerPath(path); this.addHandler(at, new RestHandlerProvider(consumer, at)); return new RestConfigurator(at); } /* ---------------------------------------------------------------------- */ public RedirectConfigurator serveRedirects(String path) { final HttpHandlerPath at = handlerPath(path); final RedirectHandler handler = new RedirectHandler(at); this.addHandler(at, new HttpHandlerProvider(handler, at)); return new RedirectConfigurator(handler); } /* ---------------------------------------------------------------------- */ public final class RestConfigurator { private final HttpHandlerPath at; private RestConfigurator(HttpHandlerPath at) { this.at = at; } public RestConfigurator withAppConfigurations(Configurations configurations) { binder().bind(Configurations.class).annotatedWith(at) .toInstance(notNull(configurations, "Null application configurations")); return this; } public RestConfigurator withObjectMapperConfigurations(Configurations configurations) { binder().bind(ObjectMapper.class).annotatedWith(at) .toProvider(new RestObjectMapperProvider(configurations)); return this; } public RestConfigurator withObjectMapper(ObjectMapper mapper) { binder().bind(ObjectMapper.class).annotatedWith(at).toInstance(notNull(mapper, "Null object mapper")); return this; } } /* ---------------------------------------------------------------------- */ public static final class RedirectConfigurator { public enum Flags { PRESERVE_QUERY_STRING, MATCH_ENTIRE_LINE, PERMANENT_REDIRECT } private final RedirectHandler handler; private RedirectConfigurator(RedirectHandler handler) { this.handler = handler; } public RedirectConfigurator redirect(String location, String redirect) { return this.redirect(location, redirect, PRESERVE_QUERY_STRING, MATCH_ENTIRE_LINE); } public RedirectConfigurator redirect(String location, String redirect, Flags flag, Flags... flags) { final Set<Flags> set = flag == null ? Collections.emptySet() : EnumSet.of(flag, flags); boolean preserveQueryString = set.contains(PRESERVE_QUERY_STRING); boolean permanentRedirect = set.contains(PERMANENT_REDIRECT); boolean matchEntireLine = set.contains(MATCH_ENTIRE_LINE); handler.addRedirect(location, redirect, matchEntireLine, permanentRedirect, preserveQueryString); return this; } } }