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 import java.net.URI;
24 import java.net.URISyntaxException;
25 import java.util.ArrayList;
26 import java.util.Collection;
27 import java.util.List;
28 import java.util.Map;
29
30 import org.apache.commons.configuration.Configuration;
31 import org.neo4j.server.configuration.Configurator;
32 import org.neo4j.server.configuration.PropertyFileConfigurator;
33 import org.neo4j.server.configuration.validation.DatabaseLocationMustBeSpecifiedRule;
34 import org.neo4j.server.configuration.validation.Validator;
35 import org.neo4j.server.database.Database;
36 import org.neo4j.server.database.GraphDatabaseFactory;
37 import org.neo4j.server.logging.Logger;
38 import org.neo4j.server.modules.PluginInitializer;
39 import org.neo4j.server.modules.RESTApiModule;
40 import org.neo4j.server.modules.ServerModule;
41 import org.neo4j.server.plugins.Injectable;
42 import org.neo4j.server.plugins.PluginManager;
43 import org.neo4j.server.startup.healthcheck.StartupHealthCheck;
44 import org.neo4j.server.startup.healthcheck.StartupHealthCheckFailedException;
45 import org.neo4j.server.web.WebServer;
46
47 public class NeoServerWithEmbeddedWebServer implements NeoServer {
48
49 public static final Logger log = Logger.getLogger(NeoServerWithEmbeddedWebServer.class);
50
51 private final File configFile;
52 private Configurator configurator;
53 private Database database;
54 private final WebServer webServer;
55 private final StartupHealthCheck startupHealthCheck;
56
57 private final AddressResolver addressResolver;
58
59 private final List<ServerModule> serverModules = new ArrayList<ServerModule>();
60 private PluginInitializer pluginInitializer;
61
62
63
64 private final Bootstrapper bootstrapper;
65
66 public NeoServerWithEmbeddedWebServer( Bootstrapper bootstrapper, AddressResolver addressResolver,
67 StartupHealthCheck startupHealthCheck, File configFile, WebServer webServer,
68 Iterable<Class<? extends ServerModule>> moduleClasses )
69 {
70 this.bootstrapper = bootstrapper;
71 this.addressResolver = addressResolver;
72 this.startupHealthCheck = startupHealthCheck;
73 this.configFile = configFile;
74 this.webServer = webServer;
75 webServer.setNeoServer( this );
76 for ( Class<? extends ServerModule> moduleClass : moduleClasses )
77 {
78 registerModule( moduleClass );
79 }
80 }
81
82 public NeoServerWithEmbeddedWebServer( Bootstrapper bootstrapper, StartupHealthCheck startupHealthCheck,
83 File configFile, WebServer ws, Iterable<Class<? extends ServerModule>> mc )
84 {
85 this( bootstrapper, new AddressResolver(), startupHealthCheck, configFile, ws, mc );
86 }
87
88 @Override
89 public void start() {
90
91 startupHealthCheck();
92 validateConfiguration();
93
94 startDatabase();
95
96 startExtensionInitialization();
97
98 startModules();
99
100 startWebServer();
101 }
102
103
104
105
106 protected void startExtensionInitialization()
107 {
108 pluginInitializer = new PluginInitializer( this );
109 }
110
111
112
113
114
115 protected final void registerModule(Class<? extends ServerModule> clazz) {
116 try {
117 serverModules.add(clazz.newInstance());
118 } catch (Exception e) {
119 log.warn( "Failed to instantiate server module [%s], reason: %s", clazz.getName(), e.getMessage() );
120 }
121 }
122
123 private void startModules() {
124 for(ServerModule module : serverModules) {
125 module.start(this);
126 }
127 }
128
129 private void stopModules() {
130 for(ServerModule module : serverModules) {
131
132 try{
133 module.stop();
134 }
135 catch(Exception e)
136 {
137 log.error( e );
138 }
139 }
140 }
141
142 private void startupHealthCheck() {
143 if (!startupHealthCheck.run()) {
144 throw new StartupHealthCheckFailedException(startupHealthCheck.failedRule());
145 }
146 }
147
148 private void validateConfiguration() {
149 this.configurator = new PropertyFileConfigurator(new Validator(new DatabaseLocationMustBeSpecifiedRule()), configFile);
150 }
151
152 private void startDatabase() {
153 String dbLocation = new File(configurator.configuration().getString(Configurator.DATABASE_LOCATION_PROPERTY_KEY)).getAbsolutePath();
154 GraphDatabaseFactory dbFactory = bootstrapper.getGraphDatabaseFactory( configurator.configuration() );
155 Map<String, String> databaseTuningProperties = configurator.getDatabaseTuningProperties();
156 if (databaseTuningProperties != null) {
157 this.database = new Database( dbFactory, dbLocation, databaseTuningProperties );
158 } else {
159 this.database = new Database( dbFactory, dbLocation );
160 }
161 }
162
163 @Override
164 public Configuration getConfiguration() {
165 return configurator.configuration();
166 }
167
168 private void startWebServer() {
169
170 int webServerPort = getWebServerPort();
171
172 log.info("Starting Neo Server on port [%s]", webServerPort);
173 webServer.setPort(webServerPort);
174
175
176 try {
177 webServer.start();
178 } catch (Exception e) {
179 e.printStackTrace();
180 log.error("Failed to start Neo Server on port [%d], reason [%s]", getWebServerPort(), e.getMessage());
181 }
182 }
183
184 protected int getWebServerPort() {
185 return configurator.configuration().getInt(Configurator.WEBSERVER_PORT_PROPERTY_KEY, Configurator.DEFAULT_WEBSERVER_PORT);
186 }
187
188 @Override
189 public void stop() {
190 try {
191 stopModules();
192 stopExtensionInitializers();
193 stopDatabase();
194 stopWebServer();
195 log.info("Successfully shutdown Neo Server on port [%d], database [%s]", getWebServerPort(), getDatabase().getLocation());
196 } catch (Exception e) {
197 log.warn("Failed to cleanly shutdown Neo Server on port [%d], database [%s]. Reason: %s", getWebServerPort(), getDatabase().getLocation(),
198 e.getMessage());
199 }
200 }
201
202
203
204
205 private void stopExtensionInitializers()
206 {
207 pluginInitializer.stop( );
208 }
209
210 private void stopWebServer() {
211 if (webServer != null) {
212 webServer.stop();
213 }
214 }
215
216 private void stopDatabase() {
217 if (database != null) {
218 database.shutdown();
219 }
220 }
221
222 @Override
223 public Database getDatabase() {
224 return database;
225 }
226
227
228 public URI baseUri() {
229 StringBuilder sb = new StringBuilder();
230 sb.append("http");
231 int webServerPort = getWebServerPort();
232 if (webServerPort == 443) {
233 sb.append("s");
234
235 }
236 sb.append("://");
237 sb.append(addressResolver.getHostname());
238
239 if (webServerPort != 80) {
240 sb.append(":");
241 sb.append(webServerPort);
242 }
243 sb.append("/");
244
245 try {
246 return new URI(sb.toString());
247 } catch (URISyntaxException e) {
248 throw new RuntimeException(e);
249 }
250 }
251
252 public WebServer getWebServer() {
253 return webServer;
254 }
255
256 @Override
257 public Configurator getConfigurator() {
258 return configurator;
259 }
260
261 @Override
262 public PluginManager getExtensionManager() {
263 if(hasModule(RESTApiModule.class)) {
264 return getModule(RESTApiModule.class).getPlugins();
265 } else {
266 return null;
267 }
268 }
269
270 @Override
271 public Collection<Injectable<?>> getInjectables( List<String> packageNames )
272 {
273 return pluginInitializer.intitializePackages( packageNames );
274 }
275
276 private boolean hasModule(Class<? extends ServerModule> clazz) {
277 for(ServerModule sm : serverModules) {
278 if(sm.getClass() == clazz) {
279 return true;
280 }
281 }
282 return false;
283 }
284
285 @SuppressWarnings("unchecked")
286 private <T extends ServerModule> T getModule(Class<T> clazz) {
287 for(ServerModule sm : serverModules) {
288 if(sm.getClass() == clazz) {
289 return (T) sm;
290 }
291 }
292
293 return null;
294 }
295
296 }