View Javadoc

    1   /**
    2    * Copyright (c) 2002-2011 "Neo Technology,"
    3    * Network Engine for Objects in Lund AB [http://neotechnology.com]
    4    *
    5    * This file is part of Neo4j.
    6    *
    7    * Neo4j is free software: you can redistribute it and/or modify
    8    * it under the terms of the GNU General Public License as published by
    9    * the Free Software Foundation, either version 3 of the License, or
    10   * (at your option) any later version.
    11   *
    12   * This program is distributed in the hope that it will be useful,
    13   * but WITHOUT ANY WARRANTY; without even the implied warranty of
    14   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    15   * GNU General Public License for more details.
    16   *
    17   * You should have received a copy of the GNU General Public License
    18   * along with this program.  If not, see <http://www.gnu.org/licenses/>.
    19   */
    20  package org.neo4j.server;
    21
    22  import java.io.File;
    23
    24  import org.apache.commons.configuration.Configuration;
    25  import org.neo4j.graphdb.TransactionFailureException;
    26  import org.neo4j.helpers.Service;
    27  import org.neo4j.helpers.collection.IteratorUtil;
    28  import org.neo4j.server.configuration.Configurator;
    29  import org.neo4j.server.database.GraphDatabaseFactory;
    30  import org.neo4j.server.logging.Logger;
    31  import org.neo4j.server.modules.ServerModule;
    32  import org.neo4j.server.startup.healthcheck.StartupHealthCheck;
    33  import org.neo4j.server.startup.healthcheck.StartupHealthCheckRule;
    34  import org.neo4j.server.web.Jetty6WebServer;
    35
    36  import uk.org.lidalia.sysoutslf4j.context.SysOutOverSLF4J;
    37
    38  public abstract class Bootstrapper
    39  {
    40      public static final Integer OK = 0;
    41      public static final Integer WEB_SERVER_STARTUP_ERROR_CODE = 1;
    42      public static final Integer GRAPH_DATABASE_STARTUP_ERROR_CODE = 2;
    43      public static final String KEY_LOG4J_CONFIG_XML_PATH = "log4j.config.xml.path";
    44
    45      private static Logger log = Logger.getLogger( NeoServerBootstrapper.class );
    46
    47      private NeoServerWithEmbeddedWebServer server;
    48
    49      public void controlEvent( int arg )
    50      {
    51          // Do nothing, required by the WrapperListener interface
    52      }
    53
    54      public Integer start()
    55      {
    56          return start( new String[0] );
    57      }
    58
    59      public Integer start( String[] args )
    60      {
    61          try
    62          {
    63              StartupHealthCheck startupHealthCheck = new StartupHealthCheck( rules() );
    64              Jetty6WebServer webServer = new Jetty6WebServer();
    65              server = new NeoServerWithEmbeddedWebServer( this, new AddressResolver(),
    66                      startupHealthCheck, getConfigFile(), webServer, getServerModules() );
    67              server.start();
    68              log.info( "Server started on [%s]", server.baseUri() );
    69
    70              Runtime.getRuntime().addShutdownHook( new Thread()
    71              {
    72                  @Override
    73                  public void run()
    74                  {
    75                      log.info( "Neo4j Server shutdown initiated by kill signal" );
    76                      if ( server != null )
    77                      {
    78                          server.stop();
    79                      }
    80                  }
    81              } );
    82
    83              return OK;
    84          }
    85          catch ( TransactionFailureException tfe )
    86          {
    87              tfe.printStackTrace();
    88              log.error( String.format( "Failed to start Neo Server on port [%d], because ", server.getWebServerPort() )
    89                         + tfe + ". Another process may be using database location " + server.getDatabase().getLocation() );
    90              return GRAPH_DATABASE_STARTUP_ERROR_CODE;
    91          }
    92          catch ( Exception e )
    93          {
    94              e.printStackTrace();
    95              log.error( "Failed to start Neo Server on port [%s]", server.getWebServerPort() );
    96              return WEB_SERVER_STARTUP_ERROR_CODE;
    97          }
    98      }
    99
    100     protected abstract GraphDatabaseFactory getGraphDatabaseFactory( Configuration configuration );
    101
    102     private StartupHealthCheckRule[] rules()
    103     {
    104         return IteratorUtil.asCollection( getHealthCheckRules() ).toArray( new StartupHealthCheckRule[0] );
    105     }
    106
    107     protected abstract Iterable<StartupHealthCheckRule> getHealthCheckRules();
    108
    109     protected abstract Iterable<Class<? extends ServerModule>> getServerModules();
    110
    111     public void stop()
    112     {
    113         stop( 0 );
    114     }
    115
    116     public int stop( int stopArg )
    117     {
    118         String location = "unknown location";
    119         try
    120         {
    121             log.info( "Successfully shutdown Neo Server on port [%d], database [%s]", server.getWebServerPort(),
    122                     location );
    123             return 0;
    124         }
    125         catch ( Exception e )
    126         {
    127             log.error( "Failed to cleanly shutdown Neo Server on port [%d], database [%s]. Reason [%s] ",
    128                     server.getWebServerPort(), location, e.getMessage() );
    129             return 1;
    130         }
    131     }
    132
    133     public NeoServerWithEmbeddedWebServer getServer()
    134     {
    135         return server;
    136     }
    137
    138     protected static File getConfigFile()
    139     {
    140         return new File( System.getProperty( Configurator.NEO_SERVER_CONFIG_FILE_KEY, Configurator.DEFAULT_CONFIG_DIR ) );
    141     }
    142
    143     public static void main( String[] args )
    144     {
    145         configureLogging();
    146         Bootstrapper bootstrapper = loadMostDerivedBootstrapper();
    147         bootstrapper.start( args );
    148     }
    149
    150     public static Bootstrapper loadMostDerivedBootstrapper()
    151     {
    152         Bootstrapper winner = new NeoServerBootstrapper();
    153         for ( Bootstrapper candidate : Service.load( Bootstrapper.class ) )
    154         {
    155             if ( candidate.isMoreDerivedThan( winner ) ) winner = candidate;
    156         }
    157         return winner;
    158     }
    159
    160     protected boolean isMoreDerivedThan( Bootstrapper other )
    161     {
    162         // Default implementation just checks if this is a subclass of other
    163         return other.getClass().isAssignableFrom( getClass() );
    164     }
    165
    166     private static void configureLogging()
    167     {
    168         SysOutOverSLF4J.sendSystemOutAndErrToSLF4J();
    169     }
    170 }