Java tutorial
package de.fhg.iais.cortex; /****************************************************************************** * Copyright 2011 (c) Fraunhofer IAIS Netmedia http://www.iais.fraunhofer.de * * ************************************************************************** * * 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. * ******************************************************************************/ import java.io.File; import java.io.IOException; import java.net.InetAddress; import java.net.UnknownHostException; import java.util.Arrays; import java.util.HashSet; import java.util.List; import java.util.ListIterator; import java.util.Set; import java.util.logging.Handler; import java.util.logging.LogManager; import org.apache.commons.io.FileUtils; import org.apache.commons.io.LineIterator; import org.apache.commons.lang.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.slf4j.MDC; import org.slf4j.bridge.SLF4JBridgeHandler; import ch.qos.logback.classic.LoggerContext; import ch.qos.logback.classic.joran.JoranConfigurator; import ch.qos.logback.core.joran.spi.JoranException; import ch.qos.logback.core.util.StatusPrinter; import com.google.common.base.Charsets; import de.fhg.iais.commons.dbc.DbcException; import de.fhg.iais.cortex.guice.modules.CortexModuleCollector; import de.fhg.iais.cortex.guice.modules.CortexPropertiesModule; /** * Starts Cortex. The selective started is called implicitly from the Starter. */ public class Starter { private static final Logger LOG = LoggerFactory.getLogger(Starter.class); private String config = null; private final boolean restore = false; private final Set<String> autoStartNames = new HashSet<String>(); private PriorityBasedServerStarter serverStarter; /** * Starts Cortex. * * @param args * the command line arguments * @see #configure(ListIterator) The list of applicable command line * arguments */ public static void main(String[] args) { try { configureLogging(); Starter starter = new Starter("."); starter.start(args); LOG.info("Cortex services started."); // register a shutdown hook which makes it possible to stop the // services with a soft kill Runtime.getRuntime().addShutdownHook(new ShutdownHookThread(starter)); } catch (RuntimeException e) { LOG.warn("Start of Cortex failed: " + e.getMessage()); } } private static class ShutdownHookThread extends Thread { private final Starter starter; public ShutdownHookThread(Starter starter) { super(); this.starter = starter; } @Override public void run() { try { LOG.info("catched shutdown message, stopping services..."); this.starter.stop(); } catch (final Exception e) { LOG.error("shutdown failed", e); } } } private static void configureLogging() { String hostAddress = "n/a"; try { hostAddress = InetAddress.getLocalHost().getCanonicalHostName(); } catch (UnknownHostException e) { LOG.warn("Hostname/IP not available"); } MDC.put("host_name", hostAddress); // SLF4J is bound to logback LoggerContext lc = (LoggerContext) LoggerFactory.getILoggerFactory(); try { JoranConfigurator configurator = new JoranConfigurator(); configurator.setContext(lc); lc.reset(); configurator.doConfigure("conf/logback.xml"); } catch (JoranException je) { je.printStackTrace(); // NOSONAR } StatusPrinter.printInCaseOfErrorsOrWarnings(lc); LOG.info("-- CORTEX starting"); java.util.logging.Logger rootLogger = LogManager.getLogManager().getLogger(""); Handler[] handlers = rootLogger.getHandlers(); for (Handler handler : handlers) { rootLogger.removeHandler(handler); } SLF4JBridgeHandler.install(); } public Starter(String baseDir) { LineIterator it = createLineIterator(baseDir + "/conf/startServers.txt"); try { while (it.hasNext()) { String nextLine = it.nextLine(); if (!StringUtils.isEmpty(nextLine) && !isComment(nextLine)) { this.autoStartNames.add(nextLine); } } } finally { LineIterator.closeQuietly(it); } } private LineIterator createLineIterator(String filePath) { File f = new File(filePath); try { return FileUtils.lineIterator(f, Charsets.UTF_8.name()); } catch (IOException e) { throw new DbcException( "Error while starting Cortex Server. Reading \"" + f.getAbsolutePath() + "\" failed", e); } } private boolean isComment(String nextLine) { return nextLine.startsWith(";") || nextLine.startsWith("#"); } /** * Configures this object and starts all configured servers * * @param args * the command line arguments used to configure this object * @return {@code true} if all configured servers could be started, {@code false} otherwise * @see #configure(ListIterator) The list of applicable command line * arguments */ public boolean start(String[] args) { this.serverStarter = new PriorityBasedServerStarter(this.autoStartNames); configure(args); return start(); } /** * Configures this object according to a list of command line arguments. * * @param args * @see #configure(ListIterator) The list of applicable command line * arguments */ private void configure(String[] args) { List<String> argList = Arrays.asList(args); configure(argList.listIterator()); } /** * Configures this object according to a list of command line arguments.<br> * <br> * The following arguments are recognized and processed from the left to the * right. Initially all servers are enabled.<br> * <br> * -conf <ConfigName> sets the name of the spring main configuration. * If there is more than one "-conf" argument, the rightmost one will be * used. If there is no "-conf" argument, the "default" spring main * configuration is used.<br> * <br> * +ALL enables all servers.<br> * -ALL disables all servers.<br> * +<servername> enables a single server.<br> * -<servername> disables a single server.<br> * <br> * Examples: to start all servers without the triplestore:<br> * +ALL -TRIPLESTORE<br> * Examples: to start only the triplestore server:<br> * -ALL +TRIPLESTORE<br> * Examples: to start the triplestore and the search server:<br> * -ALL +TRIPLESTORE +SEARCH<br> * Nonsense-examples: to start the search server:<br> * +ALL +TRIPLESTORE -ALL +SEARCH<br> */ private void configure(ListIterator<String> argIterator) { while (argIterator.hasNext()) { handleNextArgument(argIterator); } } /** * Starts the configured servers * * @return {@code true} if all servers could be started, {@code false} otherwise */ private boolean start() { try { CortexPropertiesModule properties; try { properties = new CortexPropertiesModule(this.config); properties.addProperty("restore", String.valueOf(this.restore)); } catch (IOException e) { String path = CortexPropertiesModule.createPath(this.config); throw new DbcException("Can't load \"" + path + "\"", e); } CortexModuleCollector collector = new CortexModuleCollector(properties); this.serverStarter.start(collector); return true; } catch (InterruptedException e) { LOG.warn("An exception aborted the starter."); throw new DbcException("Server start has been interrupted by an exception.", e); } } private void handleNextArgument(ListIterator<String> argIterator) { String arg = argIterator.next(); if (StringUtils.isEmpty(arg)) { return; } if (arg.equals("-conf")) { if (!argIterator.hasNext()) { LOG.warn("Found option \"-conf\" without [name of configuration] as next argument - ignored"); } else { this.config = argIterator.next(); } } else if (!handleServerArgument(arg)) { LOG.warn("Found unknown argument \"{}\" - ignored", arg); } } private boolean handleServerArgument(String arg) { switch (arg.charAt(0)) { case '+': return setServerEnabled(arg.substring(1), true); case '-': return setServerEnabled(arg.substring(1), false); default: return false; } } private boolean setServerEnabled(String argument, boolean serverEnabled) { if (argument.equalsIgnoreCase("all")) { for (String serverName : this.autoStartNames) { this.serverStarter.setServerEnabled(serverName, serverEnabled); } } else { this.serverStarter.setServerEnabled(argument, serverEnabled); } return true; } /** * Stops the cortex. */ public boolean stop() { try { this.serverStarter.stop(); return true; } catch (InterruptedException e) { LOG.warn("Stopping Cortex Server has been interrupted by an exception."); throw new DbcException(e); } } }