/*- ******************************************************************************* * Copyright (c) 2011, 2015 Diamond Light Source Ltd. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Matthew Gerring - initial API and implementation and/or initial documentation *******************************************************************************/ package org.eclipse.dawnsci.remotedataset.server; import java.util.HashMap; import java.util.Map; import org.eclipse.dawnsci.remotedataset.server.event.EventServlet; import org.eclipse.dawnsci.remotedataset.server.event.FileMonitorSocket; import org.eclipse.dawnsci.remotedataset.server.info.InfoServlet; import org.eclipse.dawnsci.remotedataset.server.info.TreeServlet; import org.eclipse.dawnsci.remotedataset.server.slice.SliceServlet; import org.eclipse.equinox.app.IApplicationContext; import org.eclipse.jetty.server.Server; import org.eclipse.jetty.server.ServerConnector; import org.eclipse.jetty.servlet.ServletContextHandler; import org.eclipse.jetty.servlet.ServletHolder; import org.eclipse.jetty.websocket.server.WebSocketHandler; import org.eclipse.jetty.websocket.servlet.WebSocketServletFactory; /** * This object is designed to start the server and * can be used as a spring object for instance. * * {@literal <bean id="dataServer" class="org.eclipse.dawnsci.remotedataset.server.DataServer" init-method="start">} {@literal <property name="port" value="8690" />} {@literal </bean>} <pre> o DataServer should default to non-blocking on start() and this be used from spring. o DataServer started from an IApplication should be blocking. o DataServer can be optionally started blocking by setting org.eclipse.dawnsci.remotedataset.server.blocking=true </pre> * @author Matthew Gerring * */ public class DataServer extends PortServer { public DataServer() { } /** * Method replaces main(...) when running things with OSGi * * Not called on GDA server will will probably start the Data Server by calling 'start' from spring, no arguments. */ @Override public Object start(IApplicationContext context) throws Exception { @SuppressWarnings("rawtypes") final Map args = context.getArguments(); final String[] configuration = (String[])args.get("application.args"); Map<String, String> conf = new HashMap<String, String>(7); for (int i = 0; i < configuration.length; i++) { final String pkey = configuration[i]; if (pkey.startsWith("-")) { conf.put(pkey.substring(1), configuration[i+1]); } } if (conf.containsKey("port")) { setPort(Integer.parseInt(conf.get("port").toString())); } start(true); // blocking return server;// We are done with this application now. } public void start(boolean block) throws Exception { this.server = new Server(); ServerConnector connector = new ServerConnector(server); connector.setPort(getPort()); connector.setReuseAddress(true); server.addConnector(connector); // We enable sessions on the server so that // we can cache LoaderFactories to a given session. // The loader factory therefore needs a non-global // data soft reference cache. ServletContextHandler context = new ServletContextHandler(ServletContextHandler.SESSIONS); context.setContextPath("/"); server.setHandler(context); // Make individual servlets // Slicing (large data in binary http) ServletHolder holderSlice = new ServletHolder("slice", SliceServlet.class); context.addServlet(holderSlice, "/slice/*"); // Doing events, like data changing shape. // FIXME Should not be needed WebSocketHandler wsHandler = new WebSocketHandler() { @Override public void configure(WebSocketServletFactory factory) { factory.register(FileMonitorSocket.class); } }; context.setHandler(wsHandler); // FIXME End should not be needed. ServletHolder holderInfo = new ServletHolder("info", InfoServlet.class); context.addServlet(holderInfo, "/info/*"); ServletHolder holderTree = new ServletHolder("tree", TreeServlet.class); context.addServlet(holderTree, "/tree/*"); // Events json objects to notify of problems. ServletHolder holderEvent = new ServletHolder("event", EventServlet.class); context.addServlet(holderEvent, "/event/*"); server.start(); if (block) server.join(); } public void setMode(DataServerMode mode) { // TODO Other diagnostic things... if (mode.equals(DataServerMode.DIAGNOSTIC)) { FileMonitorSocket.setRecordThreads(true); } else { FileMonitorSocket.setRecordThreads(false); } } public DiagnosticInfo getDiagnosticInfo() { DiagnosticInfo ret = new DiagnosticInfo(); ret.merge(FileMonitorSocket.getDiagnosticInfo()); // TODO Other info? return ret; } }