/*
* Indiana University Extreme! Lab Software License, Version 1.2
*
* Copyright (C) 2002 The Trustees of Indiana University.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* 1) All redistributions of source code must retain the above
* copyright notice, the list of authors in the original source
* code, this list of conditions and the disclaimer listed in this
* license;
*
* 2) All redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the disclaimer
* listed in this license in the documentation and/or other
* materials provided with the distribution;
*
* 3) Any documentation included with all redistributions must include
* the following acknowledgement:
*
* "This product includes software developed by the Indiana
* University Extreme! Lab. For further information please visit
* http://www.extreme.indiana.edu/"
*
* Alternatively, this acknowledgment may appear in the software
* itself, and wherever such third-party acknowledgments normally
* appear.
*
* 4) The name "Indiana Univeristy" or "Indiana Univeristy
* Extreme! Lab" shall not be used to endorse or promote
* products derived from this software without prior written
* permission from Indiana University. For written permission,
* please contact http://www.extreme.indiana.edu/.
*
* 5) Products derived from this software may not use "Indiana
* Univeristy" name nor may "Indiana Univeristy" appear in their name,
* without prior written permission of the Indiana University.
*
* Indiana University provides no reassurances that the source code
* provided does not infringe the patent or any other intellectual
* property rights of any other entity. Indiana University disclaims any
* liability to any recipient for claims brought by any other entity
* based on infringement of intellectual property rights or otherwise.
*
* LICENSEE UNDERSTANDS THAT SOFTWARE IS PROVIDED "AS IS" FOR WHICH
* NO WARRANTIES AS TO CAPABILITIES OR ACCURACY ARE MADE. INDIANA
* UNIVERSITY GIVES NO WARRANTIES AND MAKES NO REPRESENTATION THAT
* SOFTWARE IS FREE OF INFRINGEMENT OF THIRD PARTY PATENT, COPYRIGHT, OR
* OTHER PROPRIETARY RIGHTS. INDIANA UNIVERSITY MAKES NO WARRANTIES THAT
* SOFTWARE IS FREE FROM "BUGS", "VIRUSES", "TROJAN HORSES", "TRAP
* DOORS", "WORMS", OR OTHER HARMFUL CODE. LICENSEE ASSUMES THE ENTIRE
* RISK AS TO THE PERFORMANCE OF SOFTWARE AND/OR ASSOCIATED MATERIALS,
* AND TO THE PERFORMANCE AND VALIDITY OF INFORMATION GENERATED USING
* SOFTWARE.
*/
/**
* @version $Revision: 1.26 $ $Author: srikrish $ $Date: 2004/09/07 23:21:40 $ (GMT)
* @author Sriram Krishnan [mailto:srikrish@extreme.indiana.edu]
*/
package xcat.mobile.ccacore;
import gov.cca.TypeMap;
import intf.ports.XCATPort;
import intf.ccacore.XCATConnectionID;
import intf.ccacore.XCATConnectionInfo;
import intf.mobile.ccacore.MobileServices;
import intf.mobile.ccacore.MobileComponent;
import intf.mobile.coordinator.AppCoordinatorCallback;
import xcat.types.TypeUtil;
import xcat.ccacore.XCATServicesImpl;
import xcat.ccacore.XCATConnectionIDImpl;
import xcat.ports.WSPortInfo;
import xcat.ports.UsesPortInfo;
import xcat.ports.ProvidesPortInfo;
import xcat.exceptions.UnexpectedException;
import xcat.exceptions.PortNotDefinedException;
import xcat.util.HandleResolver;
import java.io.StringReader;
import java.io.StringWriter;
import java.util.Hashtable;
import soaprmi.server.UnicastRemoteObject;
import org.gjt.xpp.XmlPullNode;
import org.gjt.xpp.XmlPullParser;
import org.gjt.xpp.XmlPullParserFactory;
/**
* The MobileServicesImpl implements the methods specified in the
* MobileServices class
*/
public class MobileServicesImpl extends XCATServicesImpl
implements MobileServices {
// a reference to a component associated with this services object
private MobileComponent component;
// holds the status of ports being used or released
MigrationStatus mStatus;
/**
* Constructor
*/
public MobileServicesImpl(String name)
throws gov.cca.CCAException {
logger.finest("called with name: " + name);
try {
componentID = new MobileComponentIDServerImpl(name, this);
// instantiate the Hashtables
usesPortMap = new Hashtable();
providesPortMap = new Hashtable();
wsPortMap = new Hashtable();
// initialize the properties
compProperties = createTypeMap();
// create an instance of mStatus
mStatus = new MigrationStatus();
} catch (Exception e) {
logger.severe("Can not instantiate ComponentID", e);
throw new UnexpectedException("Can not instantiate ComponentID", e);
}
}
//------------------------------------------------------//
// List of methods added to support migration //
//------------------------------------------------------//
/**
* An operation to notify the uses side that the provider component
* requests migration
* @param providesComponentName the name of the provides side requesting migration
* @param usingPortName the name of the uses port that is connected to
* the component requesting migration
* @param coordinatorHandle the GSH for the coordinator which is needed for
* a callback when the uses side has released the port
*/
public void requestMigration(final String providesComponentName,
final String usingPortName,
final String coordinatorHandle)
throws gov.cca.CCAException {
logger.finest("called for portName: " + usingPortName);
// call this in a separate thread as it needs to block
new Thread() {
public void run () {
UsesPortInfo uInfo = (UsesPortInfo) usesPortMap.get(usingPortName);
if (uInfo != null) {
synchronized(uInfo) {
if (uInfo.isUnregistered()) {
logger.severe("Uses port: " + usingPortName +
" has been unregistered");
// callback the AppCoordinator with an exception
try {
AppCoordinatorCallback coord = (AppCoordinatorCallback)
HandleResolver.resolveHandle(coordinatorHandle,
AppCoordinatorCallback.class.getName());
coord.migrationApproval(providesComponentName,
getComponentID().getInstanceName(),
usingPortName,
AppCoordinatorCallback.EXCEPTION);
} catch (gov.cca.CCAException ce) {
logger.severe("Can't invoke notification on remote AppCoordinator",
ce);
}
return;
}
// wait till the port is released
while (uInfo.getInUse()) {
try {
logger.finest("wait till the port is released");
uInfo.wait();
} catch (InterruptedException ie) {
logger.severe("Caught InterruptedException while waiting", ie);
}
}
// notify that this port requests migration
uInfo.requestMigration();
// Callback the App Coordinator notifying that the uses
// side is ready for migration
try {
AppCoordinatorCallback coord = (AppCoordinatorCallback)
HandleResolver.resolveHandle(coordinatorHandle,
AppCoordinatorCallback.class.getName());
coord.migrationApproval(providesComponentName,
getComponentID().getInstanceName(),
usingPortName,
AppCoordinatorCallback.READY);
} catch (gov.cca.CCAException ce) {
logger.severe("Can't invoke notification on remote AppCoordinator",
ce);
}
}
} else {
logger.severe("Port " + usingPortName + " not defined");
// callback the AppCoordinator with an exception
try {
AppCoordinatorCallback coord = (AppCoordinatorCallback)
HandleResolver.resolveHandle(coordinatorHandle,
AppCoordinatorCallback.class.getName());
coord.migrationApproval(providesComponentName,
getComponentID().getInstanceName(),
usingPortName,
AppCoordinatorCallback.EXCEPTION);
} catch (gov.cca.CCAException ce) {
logger.severe("Can't invoke notification on remote AppCoordinator",
ce);
}
return;
}
}
}.start();
}
/**
* A notification that the component connected to this via the uses port is
* currently in migration
* @param usingPortName the name of the uses port that is connected to
* the component undergoing migration
*/
public void confirmMigration(String usingPortName)
throws gov.cca.CCAException {
logger.finest("called for portName: " + usingPortName);
UsesPortInfo uInfo = (UsesPortInfo) usesPortMap.get(usingPortName);
if (uInfo != null) {
synchronized(uInfo) {
if (uInfo.isUnregistered())
throw new PortNotDefinedException("Uses port: " + usingPortName +
" has been unregistered");
// confirm that this port is migrating
uInfo.confirmMigration();
}
} else {
logger.severe("Port " + usingPortName + " not defined");
throw new PortNotDefinedException("Port " + usingPortName + " not defined");
}
}
/**
* A notification that the component connected to this via the uses port
* has completed its migration and is ready for use
* @param usingPortName the name of the uses port that is connected to
* the component undergoing migration
*/
public void migrationComplete(String usingPortName)
throws gov.cca.CCAException {
logger.finest("called for portName: " + usingPortName);
UsesPortInfo uInfo = (UsesPortInfo) usesPortMap.get(usingPortName);
if (uInfo != null) {
synchronized(uInfo) {
if (uInfo.isUnregistered())
throw new PortNotDefinedException("Uses port: " + usingPortName +
" has been unregistered");
// confirm that this port has finished migrating
uInfo.migrationComplete();
// notify sleepers waiting for this port to finish migrating
uInfo.notify();
}
} else {
logger.severe("Port " + usingPortName + " not defined");
throw new PortNotDefinedException("Port " + usingPortName + " not defined");
}
}
//-------------------------------------------------------//
// List of methods added to store and retrieve state //
//-------------------------------------------------------//
/**
* Returns the state of the Services object
*/
public String getState()
throws gov.cca.CCAException {
logger.finest("called");
// initialize the String buffer
StringBuffer sInfoBuffer = new StringBuffer();
sInfoBuffer.append("<servicesInfo>");
// create information about the ComponentID
sInfoBuffer.append("<componentIDInfo>");
sInfoBuffer.append("<instanceName>" +
getComponentID().getInstanceName() +
"</instanceName>");
sInfoBuffer.append("<portGSH>" +
getComponentID().getSerialization() +
"</portGSH>");
sInfoBuffer.append("</componentIDInfo>");
// copy over the compProperties TypeMap
sInfoBuffer.append("<properties>");
String[] compMapKeys = compProperties.getAllKeys();
for (int j = 0; j < compMapKeys.length; j++) {
sInfoBuffer.append("<propertiesEntry>");
sInfoBuffer.append("<key>" +
compMapKeys[j] +
"</key>");
sInfoBuffer.append("<type>" +
TypeUtil.toString(compProperties.typeOf(compMapKeys[j])) +
"</type>");
sInfoBuffer.append("<value>" +
compProperties.getAsString(compMapKeys[j]) +
"</value>");
sInfoBuffer.append("</propertiesEntry>");
}
sInfoBuffer.append("</properties>");
// create a list of uses ports
sInfoBuffer.append("<usesPortMap>");
Object[] userKeys = usesPortMap.keySet().toArray();
// add an entry for every uses port
for (int i = 0; i < userKeys.length; i++) {
// create an entry for each Uses Port
sInfoBuffer.append("<usesPortEntry>");
sInfoBuffer.append("<portName>" +
(String) userKeys[i] +
"</portName>");
// copy over information from UsesPortInfo to UsesPortRecord
UsesPortInfo uInfo = (UsesPortInfo) usesPortMap.get(userKeys[i]);
sInfoBuffer.append("<usesPortRecord>");
sInfoBuffer.append("<portName>" +
uInfo.getPortName() +
"</portName>");
sInfoBuffer.append("<portType>" +
uInfo.getPortType() +
"</portType>");
sInfoBuffer.append("<inUse>" +
false +
"</inUse>"); // inUse is always false before & after migration
sInfoBuffer.append("<unregistered>" +
uInfo.isUnregistered() +
"</unregistered>");
sInfoBuffer.append("<migrationStatus>" +
uInfo.getMigrationStatus() +
"</migrationStatus>");
// copy over the TypeMap object
sInfoBuffer.append("<properties>");
TypeMap tMap = uInfo.getProperties();
String[] mapKeys = tMap.getAllKeys();
for (int j = 0; j < mapKeys.length; j++) {
sInfoBuffer.append("<propertiesEntry>");
sInfoBuffer.append("<key>" +
mapKeys[j] +
"</key>");
sInfoBuffer.append("<type>" +
TypeUtil.toString(tMap.typeOf(mapKeys[j])) +
"</type>");
sInfoBuffer.append("<value>" +
tMap.getAsString(mapKeys[j]) +
"</value>");
sInfoBuffer.append("</propertiesEntry>");
}
sInfoBuffer.append("</properties>");
// copy over information from the ConnectionID
XCATConnectionID connID = uInfo.getConnectionID();
if (connID != null) {
sInfoBuffer.append("<connectionID>");
sInfoBuffer.append("<providerIntfName>" +
connID.getProviderIntfName() +
"</providerIntfName>");
sInfoBuffer.append("<userIntfName>" +
connID.getUserIntfName() +
"</userIntfName>");
// fill in the state of the connection
sInfoBuffer.append("<connectionIDInfo>");
XCATConnectionInfo xconnInfo = connID.getConnectionInfo();
sInfoBuffer.append("<providerIDHandle>" +
xconnInfo.getProviderIDHandle() +
"</providerIDHandle>");
sInfoBuffer.append("<userIDHandle>" +
xconnInfo.getUserIDHandle() +
"</userIDHandle>");
sInfoBuffer.append("<providerName>" +
xconnInfo.getProviderName() +
"</providerName>");
sInfoBuffer.append("<userName>" +
xconnInfo.getUserName() +
"</userName>");
sInfoBuffer.append("<providerPortName>" +
xconnInfo.getProviderPortName() +
"</providerPortName>");
sInfoBuffer.append("<userPortName>" +
xconnInfo.getUserPortName() +
"</userPortName>");
sInfoBuffer.append("<providesPortHandle>" +
xconnInfo.getProvidesPortHandle() +
"</providesPortHandle>");
sInfoBuffer.append("</connectionIDInfo>");
sInfoBuffer.append("</connectionID>");
}
sInfoBuffer.append("</usesPortRecord>");
sInfoBuffer.append("</usesPortEntry>");
}
sInfoBuffer.append("</usesPortMap>");
// create a list of WS ports
sInfoBuffer.append("<wsPortMap>");
Object[] wsKeys = wsPortMap.keySet().toArray();
// add an entry for every ws port
for (int i = 0; i < wsKeys.length; i++) {
// create an entry for each Ws Port
sInfoBuffer.append("<wsPortEntry>");
sInfoBuffer.append("<portName>" +
(String) wsKeys[i] +
"</portName>");
// copy over information from WSPortInfo to WsPortRecord
WSPortInfo wInfo = (WSPortInfo) wsPortMap.get(wsKeys[i]);
sInfoBuffer.append("<wsPortRecord>");
sInfoBuffer.append("<portName>" +
wInfo.getPortName() +
"</portName>");
sInfoBuffer.append("<portType>" +
wInfo.getPortType() +
"</portType>");
sInfoBuffer.append("<inUse>" +
false +
"</inUse>"); // inUse is always false before & after migration
sInfoBuffer.append("<unregistered>" +
wInfo.isUnregistered() +
"</unregistered>");
if (wInfo.isConnected())
sInfoBuffer.append("<endPointLocation>" +
wInfo.getEndPointLocation() +
"</endPointLocation>");
// copy over the TypeMap object
sInfoBuffer.append("<properties>");
TypeMap tMap = wInfo.getProperties();
String[] mapKeys = tMap.getAllKeys();
for (int j = 0; j < mapKeys.length; j++) {
sInfoBuffer.append("<propertiesEntry>");
sInfoBuffer.append("<key>" +
mapKeys[j] +
"</key>");
sInfoBuffer.append("<type>" +
TypeUtil.toString(tMap.typeOf(mapKeys[j])) +
"</type>");
sInfoBuffer.append("<value>" +
tMap.getAsString(mapKeys[j]) +
"</value>");
sInfoBuffer.append("</propertiesEntry>");
}
sInfoBuffer.append("</properties>");
// end of wsPortRecord
sInfoBuffer.append("</wsPortRecord>");
sInfoBuffer.append("</wsPortEntry>");
}
sInfoBuffer.append("</wsPortMap>");
// create a list of provides ports
sInfoBuffer.append("<providesPortMap>");
Object[] providerKeys = providesPortMap.keySet().toArray();
// add an entry for every provides port
for (int i = 0; i < providerKeys.length; i++) {
// create a entry for a Provides Port
sInfoBuffer.append("<providesPortEntry>");
sInfoBuffer.append("<portName>" +
(String) providerKeys[i] +
"</portName>");
// copy over information from ProvidesPortInfo
sInfoBuffer.append("<providesPortRecord>");
ProvidesPortInfo pInfo = (ProvidesPortInfo) providesPortMap.get(providerKeys[i]);
sInfoBuffer.append("<portName>" +
pInfo.getPortName() +
"</portName>");
sInfoBuffer.append("<portType>" +
pInfo.getPortType() +
"</portType>");
sInfoBuffer.append("<inUse>" +
pInfo.getInUse() +
"</inUse>");
sInfoBuffer.append("<numConnections>" +
pInfo.getNumConnections() +
"</numConnections>");
sInfoBuffer.append("<providesPortHandle>" +
pInfo.getProvidesPortHandle() +
"</providesPortHandle>");
sInfoBuffer.append("<removed>" +
pInfo.isRemoved() +
"</removed>");
// copy over the TypeMap object
sInfoBuffer.append("<properties>");
TypeMap tMap = pInfo.getProperties();
String[] mapKeys = tMap.getAllKeys();
for (int j = 0; j < mapKeys.length; j++) {
sInfoBuffer.append("<propertiesEntry>");
sInfoBuffer.append("<key>" +
mapKeys[j] +
"</key>");
sInfoBuffer.append("<type>" +
TypeUtil.toString(tMap.typeOf(mapKeys[j])) +
"</type>");
sInfoBuffer.append("<value>" +
tMap.getAsString(mapKeys[j]) +
"</value>");
sInfoBuffer.append("</propertiesEntry>");
}
sInfoBuffer.append("</properties>");
sInfoBuffer.append("</providesPortRecord>");
sInfoBuffer.append("</providesPortEntry>");
}
sInfoBuffer.append("</providesPortMap>");
// return the ServicesInfo object
sInfoBuffer.append("</servicesInfo>");
return sInfoBuffer.toString();
}
/**
* Sets the state of this Services Object from the ServicesInfo object
* @param sInfo the state of the Services Object as XML string
*/
public void setState(String sInfo)
throws gov.cca.CCAException {
logger.finest("called");
try {
XmlPullParserFactory factory = XmlPullParserFactory.newInstance();
XmlPullParser pp = factory.newPullParser();
pp.setInput(new StringReader(sInfo));
pp.next();
XmlPullNode stateTree = factory.newPullNode(pp);
while(true) {
// get the next child and check if we are done
XmlPullNode nextChild = (XmlPullNode) stateTree.readNextChild();
if (nextChild == null)
break;
// check the type of the child node, and act appropriately
if (nextChild.getLocalName().equals("componentIDInfo")) {
// ignore, because this information has already been set
} else if (nextChild.getLocalName().equals("properties")) {
// set the compProperties TypeMap from XML
setPropertiesFromXML(nextChild, compProperties);
} else if (nextChild.getLocalName().equals("usesPortMap")) {
// add an entry for every uses port
while (true) {
// get the next entry
XmlPullNode entryNode = (XmlPullNode) nextChild.readNextChild();
if (entryNode == null)
break;
// parse every <usesPortEntry/>
while (true) {
// get the next child for the usesPortEntry
XmlPullNode entryChild = (XmlPullNode) entryNode.readNextChild();
if (entryChild == null)
break;
// initialize values
String portName = null;
String portType = null;
TypeMap tMap = createTypeMap();
boolean inUse = false;
XCATConnectionID connID = null;
boolean unregistered = false;
int migrationStatus = 0;
if (entryChild.getLocalName().equals("portName")) {
// get the portName
portName = (String) entryChild.readNextChild();
} else { // is a <usesPortRecord/>
// read all the values for the UsesPortInfo object
while (true) {
XmlPullNode nextItem = (XmlPullNode) entryChild.readNextChild();
if (nextItem == null)
break;
if (nextItem.getLocalName().equals("portName")) {
portName = (String) nextItem.readNextChild();
} else if (nextItem.getLocalName().equals("portType")) {
portType = (String) nextItem.readNextChild();
} else if (nextItem.getLocalName().equals("properties")) {
setPropertiesFromXML(nextItem, tMap);
} else if (nextItem.getLocalName().equals("inUse")) {
inUse = Boolean.valueOf((String) nextItem.readNextChild()).booleanValue();
} else if (nextItem.getLocalName().equals("connectionID")) {
connID = xmlToConnectionID(nextItem);
} else if (nextItem.getLocalName().equals("unregistered")) {
unregistered =
Boolean.valueOf((String) nextItem.readNextChild()).booleanValue();
} else { // (nextItem.getLocalName().equals("migrationStatus"))
migrationStatus = Integer.parseInt((String) nextItem.readNextChild());
}
}
// create a UsesPortInfo entry
UsesPortInfo uInfo = new UsesPortInfo(portName,
portType,
tMap);
uInfo.setInUse(inUse);
if (unregistered)
uInfo.unregisterPort();
uInfo.setMigrationStatus(migrationStatus);
if (connID != null)
uInfo.setConnectionID(connID);
// add this uses port to the HashMap
usesPortMap.put(portName, uInfo);
}
}
}
} else if (nextChild.getLocalName().equals("wsPortMap")) {
// add an entry for every WS port
while (true) {
// get the next entry
XmlPullNode entryNode = (XmlPullNode) nextChild.readNextChild();
if (entryNode == null)
break;
// parse every <wsPortEntry/>
while (true) {
// get the next child for the wsPortEntry
XmlPullNode entryChild = (XmlPullNode) entryNode.readNextChild();
if (entryChild == null)
break;
// initialize values
String portName = null;
String portType = null;
TypeMap tMap = createTypeMap();
boolean inUse = false;
boolean unregistered = false;
String endPointLocation = null;
if (entryChild.getLocalName().equals("portName")) {
// get the portName
portName = (String) entryChild.readNextChild();
} else { // is a <wsPortRecord/>
// read all the values for the WSPortInfo object
while (true) {
XmlPullNode nextItem = (XmlPullNode) entryChild.readNextChild();
if (nextItem == null)
break;
if (nextItem.getLocalName().equals("portName")) {
portName = (String) nextItem.readNextChild();
} else if (nextItem.getLocalName().equals("portType")) {
portType = (String) nextItem.readNextChild();
} else if (nextItem.getLocalName().equals("properties")) {
setPropertiesFromXML(nextItem, tMap);
} else if (nextItem.getLocalName().equals("inUse")) {
inUse = Boolean.valueOf((String) nextItem.readNextChild()).booleanValue();
} else if (nextItem.getLocalName().equals("endPointLocation")) {
endPointLocation = (String) nextItem.readNextChild();
} else { // if (nextItem.getLocalName().equals("unregistered")) {
unregistered =
Boolean.valueOf((String) nextItem.readNextChild()).booleanValue();
}
}
// create a WSPortInfo entry
WSPortInfo wInfo = new WSPortInfo(portName,
portType,
tMap);
wInfo.setInUse(inUse);
if (unregistered)
wInfo.unregisterPort();
if (endPointLocation != null)
wInfo.setEndPointLocation(endPointLocation);
// add this WS port to the HashMap
wsPortMap.put(portName, wInfo);
}
}
}
} else { // (nextChild.getLocalName().equals("providesPortMap"))
// add an entry for every provides port
while (true) {
// get the next entry
XmlPullNode entryNode = (XmlPullNode) nextChild.readNextChild();
if (entryNode == null)
break;
// parse every <providesPortEntry/>
while (true) {
// get the next child for the providesPortEntry
XmlPullNode entryChild = (XmlPullNode) entryNode.readNextChild();
if (entryChild == null)
break;
// initialize values
String portName = null;
String portType = null;
TypeMap tMap = createTypeMap();
boolean inUse = false;
int numConnections = 0;
String providesPortHandle = null;
boolean removed = false;
if (entryChild.getLocalName().equals("portName")) {
// get the portName
portName = (String) entryChild.readNextChild();
} else { // is a <providesPortRecord/>
// read all the values for the ProvidesPortInfo object
while (true) {
XmlPullNode nextItem = (XmlPullNode) entryChild.readNextChild();
if (nextItem == null)
break;
if (nextItem.getLocalName().equals("portName")) {
portName = (String) nextItem.readNextChild();
} else if (nextItem.getLocalName().equals("portType")) {
portType = (String) nextItem.readNextChild();
} else if (nextItem.getLocalName().equals("properties")) {
setPropertiesFromXML(nextItem, tMap);
} else if (nextItem.getLocalName().equals("inUse")) {
inUse = Boolean.valueOf((String) nextItem.readNextChild()).booleanValue();
} else if (nextItem.getLocalName().equals("numConnections")) {
numConnections = Integer.parseInt((String) nextItem.readNextChild());
} else if (nextItem.getLocalName().equals("providesPortHandle")) {
providesPortHandle = (String) nextItem.readNextChild();
} else { // (nextItem.getLocalName().equals("removed"))
removed = Boolean.valueOf((String) nextItem.readNextChild()).booleanValue();
}
}
// create a ProvidesPortInfo entry
ProvidesPortInfo pInfo = new ProvidesPortInfo(portName,
portType,
tMap,
providesPortHandle);
pInfo.setInUse(inUse);
pInfo.setNumConnections(numConnections);
if (removed)
pInfo.removePort();
// export this port as a grid service
String portImpl = tMap.getString("cca.portImpl", "None");
if (portImpl.equals("None"))
throw new UnexpectedException("Can't find FQN for provides port: " + portName);
Class portClass = Class.forName(portImpl);
// assumption here that a void constructor exists
Object portInstance = portClass.newInstance();
String intfClassName = tMap.getString("portClass", "None");
UnicastRemoteObject.exportObject((XCATPort) portInstance,
new Class[]{Class.forName(intfClassName)});
// add a reference to the Handle Resolver
String portGSH = pInfo.getProvidesPortHandle();
((XCATPort) portInstance).setGSH(portGSH);
HandleResolver.addReference(portGSH, (XCATPort) portInstance);
// add this provides port to the hashMap
providesPortMap.put(portName, pInfo);
}
}
}
}
}
} catch (Exception e) {
logger.severe("Can't convert state of Services Object to XML", e);
throw new UnexpectedException("Can't convert state of Services Object to XML", e);
}
}
/**
* Gets a reference to the component associated with this services object
*/
public MobileComponent getComponent() {
return component;
}
/**
* Sets the component for this services object
* @param component a reference to a component for this services object
*/
public void setComponent(MobileComponent component) {
this.component = component;
}
/**
* A request from the Application Coordinator to freeze THIS component.
* Sends a notification to the coordinator after all outgoing calls are complete,
* and the component is frozen.
* @param coordinatorHandle the GSH for the coordinator to callback after
* the component is frozen
*/
public void freezeComponent(final String coordinatorHandle)
throws gov.cca.CCAException {
logger.finest("called");
synchronized(mStatus) {
// set a flag signifying that the component needs to be frozen
mStatus.setFreezeRequested(true);
// if there are any unreleased ports, block
if (mStatus.getNumUnreleasedPorts() != 0) {
try {
mStatus.wait();
} catch (Exception e) {
logger.severe("Caught exception while waiting on mStatus", e);
// Send a notification to the AppCoordinator that an exception was caught
AppCoordinatorCallback coord = (AppCoordinatorCallback)
HandleResolver.resolveHandle(coordinatorHandle,
AppCoordinatorCallback.class.getName());
coord.componentFrozen(getComponentID().getInstanceName(),
AppCoordinatorCallback.EXCEPTION);
throw new UnexpectedException("Caught exception while waiting on mStatus", e);
}
} else {
// set that the component is frozen
mStatus.setIsFrozen(true);
}
// unset the freeze requested flag
mStatus.setFreezeRequested(false);
}
// Send a notification to the AppCoordinator that the component is frozen
AppCoordinatorCallback coord = (AppCoordinatorCallback)
HandleResolver.resolveHandle(coordinatorHandle,
AppCoordinatorCallback.class.getName());
coord.componentFrozen(getComponentID().getInstanceName(),
AppCoordinatorCallback.FROZEN);
}
/**
* Resumes execution of a component that has been frozen
*/
public void unfreezeComponent()
throws gov.cca.CCAException {
logger.finest("called");
synchronized(mStatus) {
// set the state of the component to be not frozen
mStatus.setIsFrozen(false);
// wake up all threads waiting for component to unfreeze
mStatus.notifyAll();
}
}
//----------------------------------------------------------//
// Following are wrapper methods that help with migration //
//----------------------------------------------------------//
/**
* Wraps up the superclass getPort to provide an ability to
* freeze outgoing calls
*/
public gov.cca.Port getPort(java.lang.String portName)
throws gov.cca.CCAException {
logger.finest("called for portName: " + portName);
// get the port from the superclass
gov.cca.Port retValue = super.getPort(portName);
// block if component has been frozen
synchronized(mStatus) {
if (mStatus.getIsFrozen()) {
try {
mStatus.wait();
} catch (Exception e) {
logger.severe("Caught exception while waiting on mStatus", e);
throw new UnexpectedException("Caught exception while waiting on mStatus", e);
}
}
// increment number of unreleased ports
mStatus.incrNumUnreleasedPorts();
}
// return the port
return retValue;
}
/**
* Wraps up the superclass getPortNonblocking to provide an ability to
* freeze outgoing calls
*/
public gov.cca.Port getPortNonblocking(java.lang.String portName)
throws gov.cca.CCAException {
logger.finest("called for portName: " + portName);
// get the port from the superclass
gov.cca.Port retValue = super.getPortNonblocking(portName);
if (retValue == null)
return retValue;
// block if component has been frozen
synchronized(mStatus) {
if (mStatus.getIsFrozen()) {
try {
mStatus.wait();
} catch (Exception e) {
logger.severe("Caught exception while waiting on mStatus", e);
throw new UnexpectedException("Caught exception while waiting on mStatus", e);
}
}
// increment number of unreleased ports
mStatus.incrNumUnreleasedPorts();
}
// return the port
return retValue;
}
/**
* Wraps up the superclass releasePort to provide an ability to
* freeze outgoing calls
*/
public void releasePort(java.lang.String portName)
throws gov.cca.CCAException {
logger.finest("called for portName: " + portName);
// release the port
super.releasePort(portName);
// processing for migration purposes
synchronized(mStatus) {
// decrement the number of used ports
mStatus.decrNumUnreleasedPorts();
// wake up sleeper if componentFrozen flag is set
// and all ports have been released
if ((mStatus.getNumUnreleasedPorts() == 0) &&
(mStatus.getFreezeRequested())) {
// set that the component is frozen
mStatus.setIsFrozen(true);
mStatus.notify();
}
}
}
//------------------------------------------------------//
// Private utility methods for parsing XML-ised state //
//------------------------------------------------------//
/**
* Utility method to convert XML form of a typeMap to an object representation
*/
private void setPropertiesFromXML(XmlPullNode propertiesNode,
TypeMap tMap)
throws Exception {
while (true) {
// read the next <propertiesEntry/>
XmlPullNode entryNode = (XmlPullNode) propertiesNode.readNextChild();
if (entryNode == null)
break;
String key = null;
String value = null;
String type = null;
// process the entry
while (true) {
XmlPullNode nextChild = (XmlPullNode) entryNode.readNextChild();
if (nextChild == null)
break;
// get the key, value, and type
if (nextChild.getLocalName().equals("key")) {
key = (String) nextChild.readNextChild();
} else if (nextChild.getLocalName().equals("value")) {
value = (String) nextChild.readNextChild();
} else { // (nextChild.getLocalName().equals("type"))
type = (String) nextChild.readNextChild();
}
}
// add the entry to the typeMap
TypeUtil.put(tMap, key, value, type);
}
}
/**
* Convert the XML representation to a ConnectionID object
*/
private XCATConnectionID xmlToConnectionID (XmlPullNode connNode)
throws Exception {
while (true) {
XmlPullNode nextNode = (XmlPullNode) connNode.readNextChild();
if (nextNode == null)
break;
if (nextNode.getLocalName().equals("providerIntfName")) {
// ignore - for mobile components, this is always MobileComponentID
} else if (nextNode.getLocalName().equals("userIntfName")) {
// ignore - for mobile components, this is always MobileComponentID
} else { // nextNode.getLocalName().equals("connectionIDInfo")
String providerName = null;
String providerIDHandle = null;
String userName = null;
String userIDHandle = null;
String providerPortName = null;
String userPortName = null;
String providesPortHandle = null;
while (true) {
XmlPullNode nextItem = (XmlPullNode) nextNode.readNextChild();
if (nextItem == null)
break;
if (nextItem.getLocalName().equals("providerName")) {
providerName = (String) nextItem.readNextChild();
} else if (nextItem.getLocalName().equals("providerIDHandle")) {
providerIDHandle = (String) nextItem.readNextChild();
} else if (nextItem.getLocalName().equals("userName")) {
userName = (String) nextItem.readNextChild();
} else if (nextItem.getLocalName().equals("userIDHandle")) {
userIDHandle = (String) nextItem.readNextChild();
} else if (nextItem.getLocalName().equals("providerPortName")) {
providerPortName = (String) nextItem.readNextChild();
} else if (nextItem.getLocalName().equals("userPortName")) {
userPortName = (String) nextItem.readNextChild();
} else { // nextItem.getLocalName().equals("providesPortHandle")
providesPortHandle = (String) nextItem.readNextChild();
}
}
MobileComponentIDClientImpl provider =
new MobileComponentIDClientImpl(providerName, providerIDHandle);
MobileComponentIDClientImpl user =
new MobileComponentIDClientImpl(userName, userIDHandle);
XCATConnectionID connID =
new XCATConnectionIDImpl(provider,
user,
providerPortName,
userPortName,
providesPortHandle);
return connID;
}
}
// should never get here
return null;
}
}