/** Copyright (C) 2012 Delcyon, Inc. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>. */ package com.delcyon.capo.controller.elements; import java.io.ByteArrayOutputStream; import java.util.HashMap; import java.util.logging.Level; import org.w3c.dom.Document; import org.w3c.dom.Element; import com.delcyon.capo.controller.ControlElement; import com.delcyon.capo.controller.ControlElementProvider; import com.delcyon.capo.controller.Group; import com.delcyon.capo.controller.client.ClientSideControl; import com.delcyon.capo.controller.client.ServerControllerResponse; import com.delcyon.capo.controller.server.ControllerClientRequestProcessor; import com.delcyon.capo.datastream.StreamUtil; import com.delcyon.capo.protocol.client.CapoConnection; import com.delcyon.capo.protocol.server.ClientRequest; import com.delcyon.capo.protocol.server.ClientRequestProcessor; import com.delcyon.capo.protocol.server.ClientRequestProcessorSessionManager; import com.delcyon.capo.protocol.server.ClientRequestXMLProcessor; import com.delcyon.capo.resourcemanager.remote.RemoteResourceRequest; import com.delcyon.capo.resourcemanager.remote.RemoteResourceDescriptorMessage.MessageType; import com.delcyon.capo.server.CapoServer; import com.delcyon.capo.util.XMLSerializer; import com.delcyon.capo.xml.XPath; import com.delcyon.capo.xml.cdom.VariableContainer; /** * @author jeremiah * */ @ControlElementProvider(name="remoteGroup") public class RemoteGroupElement extends GroupElement implements ClientSideControl,VariableContainer,ClientRequestProcessor { public enum Attributes { name, returns } @Override public Attributes[] getAttributes() { return Attributes.values(); } @Override public Attributes[] getRequiredAttributes() { return new Attributes[]{Attributes.name}; } @Override public String[] getSupportedNamespaces() { return null; } private String groupName; private Group group; private ServerControllerResponse serverControllerResponse; private String sessionID = null; private boolean isNewSession = true; public Group getGroup() { return group; } //Server side init @Override public void init(Element controlElementDeclaration, ControlElement parentControlElement, Group parentGroup,ControllerClientRequestProcessor controllerClientRequestProcessor) throws Exception { sessionID = ClientRequestProcessorSessionManager.generateSessionID(); ClientRequestProcessorSessionManager.registerClientRequestProcessor(this,sessionID); super.init(controlElementDeclaration, parentControlElement, parentGroup, controllerClientRequestProcessor); this.groupName = controlElementDeclaration.getAttribute(Attributes.name.toString()); this.group = new Group(groupName,parentGroup,this,controllerClientRequestProcessor); CapoServer.logger.log(Level.FINE, "init remote group = "+groupName); } @Override public boolean isStreamProcessor() { return false; } @Override public void setNewSession(boolean isNewSession) { this.isNewSession = isNewSession; } @Override public boolean isNewSession() { return isNewSession; } @Override public ServerControllerResponse getServerControllerResponse() { return this.serverControllerResponse; } @Override public Object processServerSideElement() throws Exception { Element groupElementCopy = (Element) getControlElementDeclaration().cloneNode(true); //make a message RemoteGroupMessage remoteGroupMessage = new RemoteGroupMessage(); remoteGroupMessage.setSessionID(sessionID); remoteGroupMessage.setControllerClientRequestProcessor(getControllerClientRequestProcessor()); //create an xml representation of our message object XMLSerializer xmlSerializer = new XMLSerializer(); xmlSerializer.export(remoteGroupMessage, groupElementCopy, 0); //send it to the server and WAIT for a response groupElementCopy = getControllerClientRequestProcessor().sendServerSideClientElement(groupElementCopy); //marshall the XML back into an instance of the message xmlSerializer.marshall(groupElementCopy, remoteGroupMessage); getGroup().setVariableHashMap(remoteGroupMessage.getVariableHashMap()); //then see if we have a returns attribute, and if so pull any matching vars from this group to the parent group if (getControlElementDeclaration().hasAttribute(Attributes.returns.toString()) && getParentGroup() != null) { String[] varnnames = getControlElementDeclaration().getAttribute(Attributes.returns.toString()).split(","); for (String varName : varnnames) { if (group.containsLocalKey(varName)) { getParentGroup().set(varName, group.getLocalValue(varName)); } } } //cleanup serialized XML XPath.removeNodes(groupElementCopy, "child::*[local-name() = 'controllerClientRequestProcessor' or local-name() = 'variableHashMap']"); getControlElementDeclaration().getParentNode().replaceChild(groupElementCopy, getControlElementDeclaration()); return null; } @Override public void destroy() throws Exception { //cleanup after ourselves ClientRequestProcessorSessionManager.removeClientRequestProcessor(getSessionId()); super.destroy(); } @Override public String getSessionId() { return sessionID; } //Client side init @Override public void init(Element controlElementDeclaration, ControlElement parentControlElement, Group parentGroup, ServerControllerResponse serverControllerResponse) throws Exception { RemoteGroupMessage remoteGroupMessage = new RemoteGroupMessage(); XMLSerializer xmlSerializer = new XMLSerializer(); xmlSerializer.marshall(controlElementDeclaration, remoteGroupMessage); sessionID = remoteGroupMessage.getSessionID(); //initialize this as a normal group super.init(controlElementDeclaration, parentControlElement, parentGroup, remoteGroupMessage.getControllerClientRequestProcessor()); //then initialize this as a client side group setParentGroup(parentGroup); setOriginalControlElementDeclaration(controlElementDeclaration); if (parentGroup != null) { parentGroup.setVariableContainer(this); setControlElementDeclaration((Element)parentGroup.replaceVarsInAttributeValues((controlElementDeclaration.cloneNode(true)))); } else { setControlElementDeclaration((Element) (controlElementDeclaration.cloneNode(true))); } setParentControlElement(parentControlElement); this.serverControllerResponse = serverControllerResponse; this.groupName = controlElementDeclaration.getAttribute(Attributes.name.toString()); this.group = new Group(groupName, parentGroup, this, getControllerClientRequestProcessor()); } @Override public Element processClientSideElement() throws Exception { //need session id //create a child group based on this group, and run it GroupElement groupElement = new GroupElement(); groupElement.init(getControlElementDeclaration(), this, getGroup(), getControllerClientRequestProcessor()); groupElement.processServerSideElement(); //get any variables that were made and send them back with the response XMLSerializer xmlSerializer = new XMLSerializer(); RemoteGroupMessage remoteGroupMessage = new RemoteGroupMessage(); remoteGroupMessage.setVariableHashMap(getGroup().getVariableHashMap()); xmlSerializer.export(remoteGroupMessage, getControlElementDeclaration(), 0); return getControlElementDeclaration(); } @Override public String getVarValue(String varName) { try { CapoConnection capoConnection = new CapoConnection(); RemoteResourceRequest request = new RemoteResourceRequest(capoConnection.getOutputStream(),capoConnection.getInputStream()); request.setType(MessageType.GET_VAR_VALUE); request.setVarName(varName); request.setSessionId(sessionID); request.send(); capoConnection.getInputStream(); ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); StreamUtil.readInputStreamIntoOutputStream(capoConnection.getInputStream(), byteArrayOutputStream); return new String(byteArrayOutputStream.toByteArray()); } catch (Exception exception) { exception.printStackTrace(); return null; } } @Override public void process(ClientRequest clientRequest) throws Exception { MessageType messageType = RemoteResourceRequest.getType(clientRequest); //process the request switch (messageType) { case GET_VAR_VALUE: String varName = RemoteResourceRequest.getVarName(clientRequest); if (getParentGroup() != null) { String value = getParentGroup().getVarValue(varName); if (value != null) { clientRequest.getOutputStream().write(value.getBytes()); } } break; default: throw new UnsupportedOperationException(messageType.toString()); } } //DO NOTHINGS @Override public Document readNextDocument() throws Exception { return null; } @Override public void init(ClientRequestXMLProcessor clientRequestXMLProcessor, String sessionID,HashMap<String, String> sessionHashMap,String requestName) throws Exception{} }