package org.deephacks.confit.internal.jaxrs; import org.codehaus.jackson.map.DeserializationConfig; import org.deephacks.confit.ConfigContext; import org.deephacks.confit.admin.AdminContext; import org.deephacks.confit.test.ConfigTestData.Child; import org.deephacks.confit.test.ConfigTestData.Grandfather; import org.deephacks.confit.test.ConfigTestData.Parent; import org.deephacks.confit.test.ConfigTestData.Singleton; import org.deephacks.confit.test.ConfigTestData.SingletonParent; import org.eclipse.jetty.server.Server; import org.eclipse.jetty.server.handler.HandlerList; import org.eclipse.jetty.server.handler.ResourceHandler; import org.eclipse.jetty.servlet.ServletContextHandler; import org.eclipse.jetty.servlet.ServletHolder; import org.jboss.resteasy.plugins.providers.jackson.ResteasyJacksonProvider; import org.jboss.resteasy.plugins.server.servlet.HttpServletDispatcher; import org.jboss.resteasy.spi.ResteasyDeployment; import org.jboss.resteasy.spi.ResteasyProviderFactory; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import javax.ws.rs.core.Application; import java.io.File; import java.net.URL; import java.util.HashSet; import java.util.Set; import java.util.concurrent.atomic.AtomicBoolean; public class JettyServer { private static Server server; private static AtomicBoolean RUNNING = new AtomicBoolean(false); static { ConfigContext config = ConfigContext.lookup(); config.register(Child.class, Parent.class, Grandfather.class, Singleton.class, SingletonParent.class); } public static void start() { if (RUNNING.get()) { return; } server = new Server(8080); ResteasyJacksonProvider provider = new ResteasyJacksonProvider(); provider.configure(DeserializationConfig.Feature.FAIL_ON_UNKNOWN_PROPERTIES, false); ResteasyDeployment deployment = new ResteasyDeployment(); deployment.setApplication(new JaxrsApplication()); ResteasyProviderFactory resteasyFactory = ResteasyProviderFactory.getInstance(); resteasyFactory.registerProviderInstance(provider); deployment.setProviderFactory(resteasyFactory); ServletContextHandler servletContextHandler = new ServletContextHandler(ServletContextHandler.SESSIONS); servletContextHandler.setAttribute(ResteasyDeployment.class.getName(), deployment); servletContextHandler.setContextPath("/"); ServletHolder h = new ServletHolder(new HttpServletDispatcher()); h.setInitParameter("javax.ws.rs.Application", JaxrsApplication.class.getName()); servletContextHandler.addServlet(h, JaxrsConfigEndpoint.PATH + "/*"); HandlerList handlers = new HandlerList(); ResourceHandler resourceHandler = new ResourceHandler(); resourceHandler.setDirectoriesListed(false); File root = new File(computeMavenProjectRoot(JaxrsConfigEndpoint.class), "src/main/resources/html"); resourceHandler.setResourceBase(root.getAbsolutePath()); handlers.addHandler(resourceHandler); handlers.addHandler(servletContextHandler); server.setHandler(handlers); try { server.start(); } catch (Exception e) { throw new RuntimeException(e); } RUNNING.set(true); ShutdownHook.install(new Thread() { @Override public void run() { try { server.stop(); RUNNING.set(false); } catch (Exception e) { throw new RuntimeException(); } } }); } private static class JaxrsApplication extends Application { private static final Set<Object> singletons = new HashSet<>(); static { singletons.add(new JaxrsConfigEndpoint(AdminContext.lookup())); } @Override public Set<Class<?>> getClasses() { HashSet<Class<?>> providers = new HashSet<>(); providers.add(JaxrsConfigExceptionHandler.class); return providers; } @Override public Set<Object> getSingletons() { return singletons; } } static class ShutdownHook { private static final Logger log = LoggerFactory.getLogger(ShutdownHook.class); static void install(final Thread threadToJoin) { Thread thread = new ShutdownHookThread(threadToJoin); Runtime.getRuntime().addShutdownHook(thread); log.debug("Create shutdownhook: " + thread.getName()); } private static class ShutdownHookThread extends Thread { private final Thread threadToJoin; private ShutdownHookThread(final Thread threadToJoin) { super("ShutdownHook: " + threadToJoin.getName()); this.threadToJoin = threadToJoin; } @Override public void run() { log.debug("Starting " + getName()); shutdown(threadToJoin, 30000); log.debug("Finished " + getName()); } } public static void shutdown(final Thread t, final long joinwait) { if (t == null) return; t.start(); while (t.isAlive()) { try { t.join(joinwait); } catch (InterruptedException e) { log.warn(t.getName() + "; joinwait=" + joinwait, e); } } } } public static File computeMavenProjectRoot(Class<?> anyTestClass) { final String clsUri = anyTestClass.getName().replace('.', '/') + ".class"; final URL url = anyTestClass.getClassLoader().getResource(clsUri); final String clsPath = url.getPath(); // located in ./target/test-classes or ./eclipse-out/target final File target_test_classes = new File(clsPath.substring(0, clsPath.length() - clsUri.length())); // lookup parent's parent return target_test_classes.getParentFile().getParentFile(); } }