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

org.jboss.arquillian.daemon.main.Main Maven / Gradle / Ivy

The newest version!
/*
 * JBoss, Home of Professional Open Source
 * Copyright 2012, Red Hat Middleware LLC, and individual contributors
 * by the @authors tag. See the copyright.txt in the distribution for a
 * full listing of individual contributors.
 *
 * 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.jboss.arquillian.daemon.main;

import java.io.File;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.URISyntaxException;
import java.net.URL;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.security.ProtectionDomain;
import java.util.Arrays;
import java.util.jar.JarFile;
import java.util.logging.Logger;

import org.jboss.arquillian.daemon.server.Server;
import org.jboss.arquillian.daemon.server.Servers;
import org.jboss.modules.Module;
import org.jboss.modules.ModuleIdentifier;
import org.jboss.modules.ModuleLoadException;
import org.jboss.modules.ModuleLoader;

/**
 * Standalone process entry point for the Arquillian Server Daemon. Accepts two (optional) arguments:
 *
 * 
    *
  1. hostname - The name which the server should bind to. If left unspecified, the server will bind to the wildcard * address.
  2. *
  3. port - An integer between 0 and {@link Servers#MAX_PORT}; if unspecified or 0 the system will choose a port.
  4. *
* * These arguments may be specified as system properties {@link Main#SYSPROP_NAME_BIND_NAME} and * {@link Main#SYSPROP_NAME_BIND_PORT}, which will take precedence over command-line arguments. * * @author Andrew Lee Rubinger */ public class Main { private static final Logger log = Logger.getLogger(Main.class.getName()); private static final String LOCATION_MODULES = "META-INF/modules"; private static final String NAME_MODULE_ARQUILLIAN_DAEMON_SERVER = "org.jboss.arquillian.daemon.server"; private static final String SYSPROP_NAME_BIND_NAME = "arquillian.daemon.bind.name"; private static final String SYSPROP_NAME_BIND_PORT = "arquillian.daemon.bind.port"; /** * Entry point; arguments as documented at the class level * * @param args */ public static void main(final String[] args) { /* * Note: This entry point depends on the Executable JAR structure as assembled by the build; executing directly * from a .class file or via the IDE will fail. */ // Get a reference to this JAR, and create a ModuleLoader pointing to its modules dir final ProtectionDomain domain = getProtectionDomain(); final URL thisJar = domain.getCodeSource().getLocation(); ModuleLoader loader = null; JarFile jar = null; try { try { jar = new JarFile(new File(thisJar.toURI())); } catch (final IOException ioe) { throw new RuntimeException("Could not obtain current JAR file: " + thisJar.toExternalForm()); } catch (final URISyntaxException e) { throw new RuntimeException("Incorrectly-formatted URI to JAR: " + thisJar.toExternalForm()); } // Create a module loader to load from this JAR loader = new HackJarModuleLoader(jar, LOCATION_MODULES); } finally { if (jar != null) { try { jar.close(); } catch (final IOException ioe) { // Swallow } } } // Load the Arquillian Daemon Module final ModuleIdentifier arquillianDaemonServerId = ModuleIdentifier.create(NAME_MODULE_ARQUILLIAN_DAEMON_SERVER); final Module arquillianDaemonModule; try { arquillianDaemonModule = loader.loadModule(arquillianDaemonServerId); } catch (final ModuleLoadException mle) { throw new RuntimeException("Could not load Arquillian Daemon module", mle); } // Use reflection to get the server factory class to avoid CCE final Class serverFactoryClass; try { serverFactoryClass = arquillianDaemonModule.getClassLoader().loadClass(Servers.class.getName()); } catch (final ClassNotFoundException e) { throw new RuntimeException(e); } final Method createServerMethod = getMethod(serverFactoryClass, Servers.METHOD_NAME_CREATE, Servers.METHOD_PARAMS_CREATE); // Get the bind name String hostname = null; if (args.length >= 1) { hostname = args[0]; } hostname = getDefaultValue(SYSPROP_NAME_BIND_NAME, hostname); // Get the bind port String port = null; if (args.length >= 2) { port = args[1]; } port = getDefaultValue(SYSPROP_NAME_BIND_PORT, port); if (port == null || port.length() == 0) { port = "0"; // Let the system select } // Make a server from the factory final Object server; try { server = createServerMethod.invoke(null, hostname, Integer.parseInt(port)); } catch (final Exception e) { throw new RuntimeException("Could not create a new server instance", e); } // Start final Class serverClass; try { serverClass = arquillianDaemonModule.getClassLoader().loadClass(Server.class.getName()); } catch (final ClassNotFoundException cnfe) { throw new RuntimeException("Could not get server interface class", cnfe); } final Method startMethod = getMethod(serverClass, Server.METHOD_NAME_START, Server.METHOD_PARAMS_START); try { startMethod.invoke(server); } catch (final Exception e) { throw new RuntimeException("Could not start server", e); } // Gracefully shut down the server when we quit Runtime.getRuntime().addShutdownHook(new Thread(new Runnable() { @Override public void run() { log.info("Caught signal, shutting down..."); final Method stopMethod = getMethod(serverClass, Server.METHOD_NAME_STOP, Server.METHOD_PARAMS_STOP); try { stopMethod.invoke(server); } catch (final InvocationTargetException ite) { final Throwable cause = ite.getCause(); if (cause instanceof IllegalStateException) { // Server isn't running, ignore return; } throw new RuntimeException("Encountered error invoking stop on server", cause); } catch (final Exception e) { throw new RuntimeException("Could not stop server", e); } } })); } private static final String getDefaultValue(final String sysProp, final String suppliedValue) { final String fromSysProp = SecurityActions.getSystemProperty(sysProp); return fromSysProp != null ? fromSysProp : suppliedValue; } private static Method getMethod(final Class clazz, final String methodName, final Class[] paramTypes) throws SecurityException { assert clazz != null; assert methodName != null && methodName.length() > 0; assert paramTypes != null; try { if (System.getSecurityManager() == null) { return clazz.getMethod(methodName, paramTypes); } else { return AccessController.doPrivileged(new PrivilegedAction() { @Override public Method run() { try { return clazz.getMethod(methodName, paramTypes); } catch (final NoSuchMethodException nsme) { throw new RuntimeException("Could not get method " + methodName + " with types " + Arrays.asList(paramTypes) + " from " + clazz, nsme); } } }); } } catch (final NoSuchMethodException nsme) { throw new RuntimeException("Could not get method " + methodName + " with types " + Arrays.asList(paramTypes) + " from " + clazz, nsme); } } private static ProtectionDomain getProtectionDomain() throws SecurityException { final Class
mainClass = Main.class; if (System.getSecurityManager() == null) { return mainClass.getProtectionDomain(); } else { return AccessController.doPrivileged(new PrivilegedAction() { @Override public ProtectionDomain run() { return mainClass.getProtectionDomain(); } }); } } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy