blob: 925e367fb306eb083b3e1e92318d73e72dbc8440 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.royale.test.ant;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.util.ArrayList;
import java.util.List;
import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.Callable;
import org.apache.tools.ant.BuildException;
import org.java_websocket.WebSocket;
import org.java_websocket.handshake.ClientHandshake;
import org.java_websocket.server.WebSocketServer;
public class RoyaleUnitWebSocketServer extends WebSocketServer implements IRoyaleUnitServer
{
private static final String START_OF_TEST_RUN_ACK = "<startOfTestRunAck/>";
private static final String END_OF_TEST_RUN_ACK = "<endOfTestRunAck/>";
public RoyaleUnitWebSocketServer(int port, int timeout)
{
super(new InetSocketAddress(port));
this.timeout = timeout;
//because we may be running many sets of tests in a short period of
//time, and the socket can end up in a timeout state after it is closed,
//this allows us to reuse the same port again quickly
this.setReuseAddr(true);
}
private int timeout;
private Timer timeoutTimer;
private List<String> queue = new ArrayList<String>();
private Exception resultException;
public Exception getException()
{
return resultException;
}
@Override
public void stop() throws IOException, InterruptedException
{
LoggingUtil.log("\nStopping server ...");
if(timeoutTimer != null)
{
timeoutTimer.cancel();
timeoutTimer = null;
}
for(WebSocket socket : getConnections())
{
sendTestRunEndAcknowledgement(socket);
}
super.stop();
}
@Override
public void onOpen(WebSocket connection, ClientHandshake handshake)
{
if(timeoutTimer != null)
{
timeoutTimer.cancel();
timeoutTimer = null;
}
LoggingUtil.log("Client connected.");
LoggingUtil.log("Receiving data ...");
sendTestRunStartAcknowledgement(connection);
}
@Override
public void onClose(WebSocket connection, int code, String reason, boolean remote)
{
Thread.currentThread().interrupt();
}
@Override
public void onMessage(WebSocket connection, String message)
{
queue.add(message);
}
@Override
public void onError(WebSocket connection, Exception ex)
{
resultException = ex;
}
@Override
public void onStart()
{
LoggingUtil.log("Starting server ...");
LoggingUtil.log("Waiting for client connection ...");
timeoutTimer = new Timer();
timeoutTimer.schedule(new TimerTask()
{
public void run()
{
resultException = new BuildException("Socket timeout waiting for royaleunit report");
}
}, timeout);
}
public boolean isPending()
{
return resultException == null && queue.size() == 0;
}
/**
* Reads tokens from the web socket
*/
public String readNextTokenFromSocket() throws IOException
{
return queue.remove(0);
}
private void sendOutboundMessage(WebSocket connection, String message)
{
connection.send(message);
}
/**
* Generate and send message to inform test runner to begin sending test data
*/
private void sendTestRunStartAcknowledgement(WebSocket connection)
{
LoggingUtil.log("Sending acknowledgement to player to start sending test data ...\n");
sendOutboundMessage(connection, START_OF_TEST_RUN_ACK);
}
/**
* Sends the end of test run to the listener to close the connection
*/
private void sendTestRunEndAcknowledgement(WebSocket connection)
{
LoggingUtil.log("End of test data reached, sending acknowledgement to player ...");
sendOutboundMessage(connection, END_OF_TEST_RUN_ACK);
}
}