1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
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
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
163 return other.getClass().isAssignableFrom( getClass() );
164 }
165
166 private static void configureLogging()
167 {
168 SysOutOverSLF4J.sendSystemOutAndErrToSLF4J();
169 }
170 }