/**
* JBoss, Home of Professional Open Source
* Copyright 2013, Red Hat Middleware LLC, and individual contributors
* by the @authors tag. See the copyright.txt in the distribution for a
* full listing of individual contributors.
*
* Licensed 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.jboss.arquillian.warp.impl.server.commandBus;
import static org.jboss.arquillian.warp.impl.server.execution.WarpFilter.ARQUILLIAN_MANAGER_ATTRIBUTE;
import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.concurrent.ConcurrentHashMap;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.jboss.arquillian.container.test.spi.command.CommandService;
import org.jboss.arquillian.core.spi.Manager;
import org.jboss.arquillian.warp.impl.server.delegation.RequestDelegationService;
import org.jboss.arquillian.warp.impl.server.event.ActivateManager;
import org.jboss.arquillian.warp.impl.server.event.PassivateManager;
import org.jboss.arquillian.warp.impl.shared.command.CommandPayload;
import org.jboss.arquillian.warp.impl.shared.command.Command;
import org.jboss.arquillian.warp.impl.shared.command.OperationMode;
/**
* Processes {@link CommandService} requests.
*
* @author Aris Tzoumas
*/
public class CommandBusOnServer implements
RequestDelegationService {
public static final String COMMAND_EVENT_BUS_PATH = "CommandEventBus";
public static final String COMMAND_EVENT_BUS_MAPPING = "/" + COMMAND_EVENT_BUS_PATH;
private static final String METHOD_NAME = "methodName";
private static final String CLASS_NAME = "className";
private static final String OPERATION_MODE = "operationMode";
static ConcurrentHashMap<String, CommandPayload> events = new ConcurrentHashMap<String, CommandPayload>();
static String currentCall = "";
@Override
public boolean canDelegate(HttpServletRequest request) {
String path = request.getRequestURI();
return (path != null && path.endsWith(COMMAND_EVENT_BUS_MAPPING));
}
@Override
public void delegate(HttpServletRequest request,
HttpServletResponse response, FilterChain filterChain) {
try {
executeEvent(request, response);
} catch (ServletException e) {
throw new RuntimeException(e);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
private void executeEvent(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String className = null;
String methodName = null;
String operationMode = null;
try {
className = request.getParameter(CLASS_NAME);
if (className == null) {
throw new IllegalArgumentException(CLASS_NAME + " must be specified");
}
methodName = request.getParameter(METHOD_NAME);
if (methodName == null) {
throw new IllegalArgumentException(METHOD_NAME + " must be specified");
}
operationMode = request.getParameter(OPERATION_MODE);
if (operationMode == null) {
throw new IllegalArgumentException(OPERATION_MODE + " must be specified");
}
String eventKey = className + methodName;
currentCall = eventKey;
if (OperationMode.GET.name().equals(operationMode)) {
executeGetOperation(request, response);
} else if (OperationMode.PUT.name().equals(operationMode)) {
executePutOperation(request, response);
} else {
throw new IllegalArgumentException("Unsupported " + OPERATION_MODE + " parameter.");
}
} catch (Exception e) {
response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, e.getMessage());
}
}
/**
* Container-to-Client command execution
*/
private void executeGetOperation(HttpServletRequest request, HttpServletResponse response) throws IOException, ClassNotFoundException {
if (request.getContentLength() > 0) {
response.setStatus(HttpServletResponse.SC_NO_CONTENT);
ObjectInputStream input = new ObjectInputStream(new BufferedInputStream(request.getInputStream()));
CommandPayload paylod = (CommandPayload) input.readObject();
events.put(currentCall, paylod);
} else {
if (events.containsKey(currentCall) && !events.get(currentCall).isExecuted()) {
response.setStatus(HttpServletResponse.SC_OK);
ObjectOutputStream output = new ObjectOutputStream(response.getOutputStream());
output.writeObject(events.remove(currentCall));
output.flush();
output.close();
} else {
response.setStatus(HttpServletResponse.SC_NO_CONTENT);
}
}
}
/**
* Client-to-Container event propagation
*/
private void executePutOperation(HttpServletRequest request, HttpServletResponse response) throws IOException, ClassNotFoundException {
if (request.getContentLength() > 0) {
ObjectInputStream input = new ObjectInputStream(new BufferedInputStream(request.getInputStream()));
CommandPayload payload = (CommandPayload) input.readObject();
Command operation = payload.getCommand();
Manager manager = (Manager)request.getAttribute(ARQUILLIAN_MANAGER_ATTRIBUTE);
// execute remote Event
try{
manager.fire(new ActivateManager(manager));
manager.inject(operation);
operation.perform();
manager.fire(new PassivateManager(manager));
} catch (Throwable e) {
payload.setThrowable(e);
}
response.setStatus(HttpServletResponse.SC_OK);
ObjectOutputStream output = new ObjectOutputStream(response.getOutputStream());
output.writeObject(payload);
output.flush();
output.close();
} else {
response.setStatus(HttpServletResponse.SC_NO_CONTENT);
}
}
public static ConcurrentHashMap<String, CommandPayload> getEvents() {
return events;
}
public static String getCurrentCall() {
return currentCall;
}
}