Package dtool.genie

Source Code of dtool.genie.GenieServer$GenieCommandException

/*******************************************************************************
* Copyright (c) 2014, 2014 Bruno Medeiros and other Contributors.
* 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:
*     Bruno Medeiros - initial API and implementation
*******************************************************************************/
package dtool.genie;

import static melnorme.utilbox.core.Assert.AssertNamespace.assertNotNull;
import static melnorme.utilbox.core.CoreUtil.array;

import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.Socket;

import melnorme.utilbox.misc.FileUtil;
import melnorme.utilbox.misc.StringUtil;

import com.google.gson.stream.JsonToken;
import com.google.gson.stream.MalformedJsonException;

import dtool.engine.DToolServer;
import dtool.genie.cmdline.StartServerOperation;
import dtool.util.JsonReaderExt;
import dtool.util.JsonWriterExt;
import dtool.util.StatusException;

public class GenieServer extends AbstractSocketServer {
 
  protected final DToolServer dtoolServer;
  protected File sentinelFile;
 
  public static final String ENGINE_NAME = "D Tool Genie";
  public static final String ENGINE_VERSION = "0.1.0";
  public static final String ENGINE_PROTOCOL_VERSION = "0.1";
 
  public static File getSentinelFile() {
    return new File(System.getProperty("user.home"), StartServerOperation.SENTINEL_FILE_NAME);
  }
 
  public GenieServer(DToolServer dtoolServer, int portNumber) throws StatusException {
    super(portNumber);
    this.dtoolServer = assertNotNull(dtoolServer);
   
    dtoolServer.logMessage(" ------ Started Genie Server ------ ");
    logMessage("Listening on port: " + this.portNumber);
   
    this.sentinelFile = getSentinelFile();
    try {
      FileUtil.writeStringToFile(sentinelFile, getServerPortNumber()+"", StringUtil.UTF8);
    } catch (IOException e) {
      throw new StatusException("Error writing to sentinel file " + sentinelFile, e);
    }
  }
 
  public DToolServer getDToolServer() {
    return dtoolServer;
  }
 
  @Override
  public void logMessage(String message) {
    dtoolServer.logMessage("# GenieServer: " + message);
  }
  @Override
  public void logError(String message, Throwable throwable) {
    dtoolServer.logError("# GenieServer: " + message, throwable);
  }
  @Override
  public void handleInternalError(Throwable throwable) {
    dtoolServer.handleInternalError(throwable);
  }
 
  @Override
  public void runServer() {
    try {
      super.runServer();
    } finally {
      disposeSentinelFile();
    }
  }
 
  public void shutdown() {
    closeServerSocket();
    disposeSentinelFile(); // Note that some connection handlers can still be active
  }
 
  protected void disposeSentinelFile() {
    if(sentinelFile != null) {
      sentinelFile.delete();
      sentinelFile = null;
    }
  }
 
  @Override
  protected GenieConnectionHandler createConnectionHandlerRunnable(Socket clientSocket) {
    return new GenieConnectionHandler(clientSocket);
  }
 
  @Override
  protected Thread createHandlerThread(ConnectionHandlerRunnable genieConnectionHandler) {
    Thread thread = super.createHandlerThread(genieConnectionHandler);
    thread.setName("GenieConnectionHandler:" + genieConnectionHandler.clientSocket.getPort());
    return thread;
  }
 
  public class GenieConnectionHandler extends ConnectionHandlerRunnable {
   
    public GenieConnectionHandler(Socket clientSocket) {
      super(clientSocket);
    }
   
    @Override
    protected void handleConnectionStream() throws IOException {
      try(
        BufferedReader serverInput = new BufferedReader(
          new InputStreamReader(clientSocket.getInputStream(), StringUtil.UTF8));
        OutputStreamWriter serverResponse =
          new OutputStreamWriter(clientSocket.getOutputStream(), StringUtil.UTF8);
        JsonReaderExt jsonParser = new JsonReaderExt(serverInput);
        JsonWriterExt jsonWriter = new JsonWriterExt(serverResponse);
      ) {
       
        try {
          jsonParser.setLenient(true);
          jsonWriter.setLenient(true);
         
          while(!jsonParser.isEOF()) {
            processJsonMessage(jsonParser, jsonWriter);
          }
        } catch (MalformedJsonException jsonException) {
          logProtocolMessageError(jsonException);
          return;
        }
      }
    }
   
  }
 
  public void logProtocolMessageError(Throwable throwable) {
    logError("Protocol message error: ", throwable);
  }
 
  public JsonCommandHandler[] getCommandHandlers() {
    return array(
      new AboutCommandHandler(this),
      new ShudtownCommandHandler(this),
      new FindDefinitionCommandHandler(this)
    );
  }
 
  protected void processJsonMessage(JsonReaderExt jsonParser, JsonWriterExt jsonWriter) throws IOException {
    jsonParser.consumeExpected(JsonToken.BEGIN_OBJECT);
    try {
     
      String commandName = jsonParser.consumeExpectedPropName();
     
      for (JsonCommandHandler commandHandler : getCommandHandlers()) {
        if(commandHandler.canHandle(commandName)) {
          commandHandler.processCommand(jsonParser, jsonWriter);
          return;
        }
      }
     
      new JsonCommandHandler(commandName, this) {
        @Override
        protected void writeResponseJsonContents() throws IOException {
          String msg = "Unknown command: " + commandName;
          logProtocolMessageError(validationError(msg));
          jsonWriter.writeProperty("error", msg);
        };
      }.processCommand(jsonParser, jsonWriter);
     
    } finally {
      jsonParser.consumeExpected(JsonToken.END_OBJECT);
    }
   
  }
 
  @SuppressWarnings("serial")
  public static class GenieCommandException extends StatusException {
   
    public GenieCommandException(String message) {
      super(message, null);
    }
   
  }
 
  public static class AboutCommandHandler extends JsonCommandHandler {
   
    public AboutCommandHandler(GenieServer genieServer) {
      super("about", genieServer);
    }
   
    @Override
    protected void writeResponseJsonContents() throws IOException {
      jsonWriter.writeProperty("engine", ENGINE_NAME);
      jsonWriter.writeProperty("version", ENGINE_VERSION);
      jsonWriter.writeProperty("protocol_version", ENGINE_PROTOCOL_VERSION);
    }
   
  }
 
  public static class ShudtownCommandHandler extends JsonCommandHandler {
   
    public ShudtownCommandHandler(GenieServer genieServer) {
      super("shutdown", genieServer);
    }
   
    @Override
    protected void processCommandResponse() throws IOException, GenieCommandException {
      super.processCommandResponse();
      genieServer.shutdown();
    }
   
    @Override
    protected void writeResponseJsonContents() throws IOException {
    }
   
  }
 
}
TOP

Related Classes of dtool.genie.GenieServer$GenieCommandException

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.