/*
* 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.29 $ $Author: srikrish $ $Date: 2004/09/07 23:21:24 $ (GMT)
* @author Sriram Krishnan [mailto:srikrish@extreme.indiana.edu]
*/
package xcat.ccacore;
import gov.cca.Services;
import gov.cca.TypeMap;
import gov.cca.ComponentID;
import intf.ports.XCATPort;
import intf.ccacore.XCATServices;
import intf.ccacore.XCATComponentID;
import intf.ccacore.XCATConnectionID;
import intf.ccacore.XCATConnectionInfo;
import xcat.types.TypeMapImpl;
import xcat.ports.WSPortInfo;
import xcat.ports.UsesPortInfo;
import xcat.ports.ProvidesPortInfo;
import xcat.util.HandleResolver;
import xcat.exceptions.UsesPortNotReleasedException;
import xcat.exceptions.PortAlreadyDefinedException;
import xcat.exceptions.PortNotConnectedException;
import xcat.exceptions.PortNotDefinedException;
import xcat.exceptions.PortNotInUseException;
import xcat.exceptions.NonstandardException;
import xcat.exceptions.UnexpectedException;
import soaprmi.Remote;
import soaprmi.util.logging.Logger;
import soaprmi.server.UnicastRemoteObject;
import java.util.Hashtable;
/**
* Implementation of the XCATServices interface
*/
public class XCATServicesImpl
implements XCATServices {
protected static Logger logger = Logger.getLogger();
protected Hashtable usesPortMap; // map of registered uses ports
protected Hashtable providesPortMap; // map of added provides ports
protected Hashtable wsPortMap; // map of registered WS ports
protected XCATComponentID componentID; // componentID associated with this object
protected TypeMap compProperties; // properties for the component, set by the user
/**
* Default constructor, needed by subclasses
*/
protected XCATServicesImpl() {
logger.finest("called");
}
/**
* Constructor
* @param name The name given to this services object by the Builder service
*/
public XCATServicesImpl(String name)
throws gov.cca.CCAException {
logger.finest("called with name: " + name);
try {
// initialize componentID
componentID = new XCATComponentIDServerImpl(name, this);
// instantiate the Hashtables
usesPortMap = new Hashtable();
providesPortMap = new Hashtable();
wsPortMap = new Hashtable();
// initialize the properties
compProperties = createTypeMap();
} catch (Exception e) {
logger.severe("Can not instantiate ComponentID", e);
throw new UnexpectedException("Can not instantiate ComponentID", e);
}
}
/**
* Fetch a previously registered Port (defined by either
* addProvidePort or (more typically) registerUsesPort).
* @return Will return the Port (possibly waiting forever while
* attempting to acquire it) or throw an exception. Does not return
* NULL, even in the case where no connection has been made.
* If a Port is returned,
* there is then a contract that the port will remain valid for use
* by the caller until the port is released via releasePort(), or a
* Disconnect Event is successfully dispatched to the caller,
* or a runtime exception (such as network failure) occurs during
* invocation of some function in the Port.
* <p>
* Subtle interpretation: If the Component is not listening for
* Disconnect events, then the framework has no clean way to
* break the connection until after the component calls releasePort.
* </p>
* <p>The framework may go through some machinations to obtain
* the port, possibly involving an interactive user or network
* queries, before giving up and throwing an exception.
* </p>
*
* @param portName The previously registered or provide port which
* the component now wants to use.
* @exception CCAException with following types: PortNotConnected, PortNotDefined,
* NetworkError, OutOfMemory.
*/
public gov.cca.Port getPort(java.lang.String portName)
throws gov.cca.CCAException {
logger.finest("called for portName: " + portName);
// For provides ports
ProvidesPortInfo pInfo =
(ProvidesPortInfo) providesPortMap.get(portName);
if (pInfo != null) {
synchronized(pInfo) {
while (pInfo.getInUse()) {
try {
logger.finest("wait till the port is released");
pInfo.wait();
} catch (InterruptedException ie) {
logger.severe("Exception while waiting for port to be released", ie);
}
}
if (pInfo.isRemoved())
throw new PortNotDefinedException("Provides port : " + portName +
" has been removed");
pInfo.setInUse(true);
return pInfo.getProvidesPortReference();
}
}
// For uses ports
UsesPortInfo uInfo =
(UsesPortInfo) usesPortMap.get(portName);
if (uInfo != null) {
synchronized(uInfo) {
while (uInfo.getInUse() || uInfo.getInMigration()) {
try {
logger.finest("wait till the port is available");
uInfo.wait();
} catch (InterruptedException ie) {
logger.severe("Exception while waiting for port to be released", ie);
}
}
if (uInfo.isUnregistered())
throw new PortNotDefinedException("Uses port: " + portName +
" has been unregistered");
if (uInfo.getConnectionID() == null)
throw new PortNotConnectedException("Port " + portName
+ " not connected");
uInfo.setInUse(true);
return uInfo.getProvidesPortReference();
}
}
logger.severe("Port " + portName + " not defined");
throw new PortNotDefinedException("Port " + portName + " not defined");
}
/**
* Get a previously registered Port (defined by
* either addProvide or registerUses) and return that
* Port if it is available immediately (already connected
* without further connection machinations).
* There is an contract that the
* port will remain valid per the description of getPort.
* @return The named port, if it exists and is connected or self-provided,
* or NULL if it is registered and is not yet connected. Does not
* return if the Port is neither registered nor provided, but rather
* throws an exception.
* @param portName registered or provided port that
* the component now wants to use.
* @exception CCAException with the following types: PortNotConnected,
* PortNotDefined, OutOfMemory.
*/
public gov.cca.Port getPortNonblocking(java.lang.String portName)
throws gov.cca.CCAException {
logger.finest("called for portName: " + portName);
// For provides ports
ProvidesPortInfo pInfo =
(ProvidesPortInfo) providesPortMap.get(portName);
if (pInfo != null) {
synchronized(pInfo) {
if (pInfo.isRemoved())
throw new PortNotDefinedException("Provides port : " + portName +
" has been removed");
if (pInfo.getInUse()) {
logger.finest("port is in use");
return null;
}
else {
pInfo.setInUse(true);
return pInfo.getProvidesPortReference();
}
}
}
// For uses ports
UsesPortInfo uInfo =
(UsesPortInfo) usesPortMap.get(portName);
if (uInfo != null) {
synchronized(uInfo) {
if (uInfo.isUnregistered())
throw new PortNotDefinedException("Uses port: " + portName +
" has been unregistered");
if (uInfo.getInUse() || uInfo.getInMigration()) {
logger.finest("port not available");
return null;
}
else if (uInfo.getConnectionID() == null)
throw new PortNotConnectedException("Port " + portName + " not connected");
else {
uInfo.setInUse(true);
// return the reference to the provides port
return uInfo.getProvidesPortReference();
}
}
}
logger.severe("Port " + portName + " not defined");
throw new PortNotDefinedException("Port " + portName + " not defined");
}
/**
* Notifies the framework that this component is finished
* using the previously fetched Port that is named.
* The releasePort() method calls should be paired with
* getPort() method calls; however, an extra call to releasePort()
* for the same name may (is not required to) generate an exception.
* Calls to release ports which are not defined or have never be fetched
* with one of the getPort functions generate exceptions.
* @param portName The name of a port.
* @exception CCAException with the following types: PortNotDefined, PortNotInUse.
*/
public void releasePort(java.lang.String portName)
throws gov.cca.CCAException {
logger.finest("called for portName: " + portName);
// For provides ports
ProvidesPortInfo pInfo =
(ProvidesPortInfo) providesPortMap.get(portName);
if (pInfo != null) {
synchronized(pInfo) {
if (pInfo.isRemoved())
throw new PortNotDefinedException("Provides port : " + portName +
" has been removed");
if (pInfo.getInUse()) {
pInfo.setInUse(false);
logger.finest("wake up sleeper waiting for port to be released");
pInfo.notify();
return;
}
else
throw new PortNotInUseException("Port " + portName + " not in use");
}
}
// For uses ports
UsesPortInfo uInfo =
(UsesPortInfo) usesPortMap.get(portName);
if (uInfo != null) {
synchronized(uInfo) {
if (uInfo.isUnregistered())
throw new PortNotDefinedException("Uses port: " + portName +
" has been unregistered");
if (uInfo.getInUse()) {
uInfo.setInUse(false);
logger.finest("wake up sleeper waiting for port to be released");
uInfo.notify();
return;
}
else
throw new PortNotInUseException("Port " + portName + " not in use");
}
}
logger.severe("Port " + portName + " not defined");
throw new PortNotDefinedException("Port " + portName + " not defined");
}
/**
* Creates a TypeMap, potentially to be used in subsequent
* calls to describe a Port. Initially, this map is empty.
*/
public gov.cca.TypeMap createTypeMap()
throws gov.cca.CCAException {
return new xcat.types.TypeMapImpl();
}
/**
* Register a request for a Port that will be retrieved subsequently
* with a call to getPort().
* @param portName A string uniquely describing this port. This string
* must be unique for this component, over both uses and provides ports.
* @param type A string describing the type of this port (a namespace in XCAT3)
* @param properties A TypeMap describing properties associated with this port.
*
* Required properties for XCAT3 are:
* portClass: Fully qualified class name for the interface defining the port
* @exception CCAException with the following types: PortAlreadyDefined, OutOfMemory.
*/
public void registerUsesPort(java.lang.String portName,
java.lang.String type,
gov.cca.TypeMap properties)
throws gov.cca.CCAException {
logger.finest(" called with parameters: " +
" portName = " + portName +
" type = " + type +
" properties = " + properties);
synchronized(this) {
if (usesPortMap.containsKey(portName) ||
(providesPortMap.containsKey(portName)))
throw new PortAlreadyDefinedException("Port " + portName +
" already defined");
else {
// check if the portClass property is present
if (properties == null)
throw new NonstandardException("TypeMap should not be empty: " +
"need property portClass");
String intfClassName = properties.getString("portClass",
"None");
if (intfClassName.equals("None"))
throw new NonstandardException("TypeMap should contain property " +
"portClass");
// add a couple of standard properties
properties.putString("cca.portName", portName);
properties.putString("cca.portType", type);
// create a new UsesPortInfo object and add it to usesPortMap
UsesPortInfo uInfo = new UsesPortInfo(portName, type, properties);
usesPortMap.put(portName, uInfo);
}
}
}
/**
* Notify the framework that a Port, previously registered by this
* component but currently not in use, is no longer desired.
* Unregistering a port that is currently
* in use (i.e. an unreleased getPort() being outstanding)
* is an error.
* @param portName The name of a registered Port.
* @exception CCAException with the following types: UsesPortNotReleased, PortNotDefined.
*/
public void unregisterUsesPort(java.lang.String portName)
throws gov.cca.CCAException {
logger.finest("called with portName: " + portName);
UsesPortInfo uInfo = (UsesPortInfo) usesPortMap.get(portName);
if (uInfo != null) {
synchronized(uInfo) {
if (uInfo.getInUse())
throw new UsesPortNotReleasedException("Port " + portName + " still in use");
else {
uInfo.unregisterPort();
usesPortMap.remove(portName);
}
}
} else
throw new PortNotDefinedException("Port " + portName + " not defined");
}
/**
* Exposes a Port from this component to the framework.
* This Port is now available for the framework to connect
* to other components.
* @param inPort An abstract interface (tagged with CCA-ness
* by inheriting from gov.cca.Port) the framework will
* make available to other components.
*
* @param portName string uniquely describing this port. This string
* must be unique for this component, over both uses and provides ports.
*
* @param type string describing the type (class) of this port.
*
* @param properties A TypeMap describing properties associated with this port.
*
* Required properties for XCAT3 are:
* portClass: Fully qualified class name for the interface defining the port
*
* @exception CCAException with the following types: PortAlreadyDefined, OutOfMemory.
*/
public void addProvidesPort(gov.cca.Port inPort,
java.lang.String portName,
java.lang.String type,
gov.cca.TypeMap properties)
throws gov.cca.CCAException {
logger.finest("called with parameters: " +
" portName = " + portName +
" type = " + type +
" properties = " + properties);
synchronized(this) {
if (providesPortMap.containsKey(portName) ||
(usesPortMap.containsKey(portName)))
throw new PortAlreadyDefinedException("Port " + portName +
" already defined");
else {
// check if the TypeMap is null
if (properties == null)
throw new NonstandardException("TypeMap should not be empty: " +
"need property portClass");
// add two special properties to typeMap
properties.putString("cca.portName", portName);
properties.putString("cca.portType", type);
// add the classname of the port implementation as a property
properties.putString("cca.portImpl", inPort.getClass().getName());
// extract the class for the interface describing the port
String intfClassName = properties.getString("portClass",
"None");
if (intfClassName.equals("None"))
throw new NonstandardException("TypeMap should contain property " +
"portClass");
// export the provides port as a Grid service
try {
UnicastRemoteObject.exportObject(inPort,
new Class[]{Class.forName(intfClassName)});
} catch (Exception e) {
logger.severe("Can't export the port as a Grid service", e);
throw new NonstandardException("Can't export the port as a Grid service", e);
}
// create an entry for this port in the providesPortMap
if (!(inPort instanceof XCATPort))
throw new NonstandardException("Port to be added not an instance of XCATPort");
// Set the GSH for the provides port
String providesPortHandle = HandleResolver.createGSH(portName);
((XCATPort) inPort).setGSH(providesPortHandle);
logger.finest("adding port with handle: " + providesPortHandle);
ProvidesPortInfo pInfo = new ProvidesPortInfo(portName,
type,
properties,
providesPortHandle);
providesPortMap.put(portName, pInfo);
// create an entry for this port in the handle resolver
HandleResolver.addReference(providesPortHandle, (XCATPort) inPort);
}
}
}
/**
* Returns the complete list of the properties for a Port. This
* includes the properties defined when the port was registered
* (these properties can be modified by the framework), two special
* properties "cca.portName" and "cca.portType", and any other
* properties that the framework wishes to disclose to the component.
* The framework may also choose to provide only the subset of input
* properties (i.e. from addProvidesPort/registerUsesPort) that it
* will honor.
*/
public gov.cca.TypeMap getPortProperties(java.lang.String name)
throws gov.cca.CCAException {
logger.finest("called for portName: " + name);
// provides ports
if (providesPortMap.containsKey(name)) {
ProvidesPortInfo pInfo = (ProvidesPortInfo) providesPortMap.get(name);
return pInfo.getProperties();
}
// uses ports
if (usesPortMap.containsKey(name)) {
UsesPortInfo uInfo = (UsesPortInfo) usesPortMap.get(name);
return uInfo.getProperties();
}
// port not found
throw new PortNotDefinedException("Port " + name + " not defined");
}
/**
* Notifies the framework that a previously exposed Port is no longer
* available for use. The Port being removed must exist
* until this call returns, or a CCAException may occur.
* @param portName The name of a provided Port.
* @exception PortNotDefined. In general, the framework will not dictate
* when the component chooses to stop offering services.
*/
public void removeProvidesPort(java.lang.String portName)
throws gov.cca.CCAException {
logger.finest("called for portName: " + portName);
ProvidesPortInfo pInfo = (ProvidesPortInfo) providesPortMap.get(portName);
if (pInfo != null) {
synchronized(pInfo) {
if (pInfo.getInUse())
// Can't remove if port is still in use
throw new NonstandardException("ProvidesPort " + portName + " still in use");
else if (pInfo.getNumConnections() != 0)
// Can't remove if port is still connected remotely
throw new NonstandardException("ProvidesPort " + portName + " still connected");
else {
pInfo.removePort();
// NOTE: SHOULD I SHUTDOWN THE XSOAP SERVICE HERE?
providesPortMap.remove(portName);
}
}
} else
throw new PortNotDefinedException("Port " + portName + " not defined");
}
/**
* Get a reference to the component to which this
* Services object belongs.
*/
public gov.cca.ComponentID getComponentID() {
return componentID;
}
//------------------------------------------------------//
// List of methods added by the XCATServices interface //
//------------------------------------------------------//
/**
* Returns an array of registered provides ports
*/
public String[] getProvidedPortNames()
throws gov.cca.CCAException {
Object[] keyObjArray = providesPortMap.keySet().toArray();
String[] keyStrArray = new String[keyObjArray.length];
for (int i = 0; i < keyObjArray.length; i++)
keyStrArray[i] = (String) keyObjArray[i];
return keyStrArray;
}
/**
* Returns an array of registered uses ports
*/
public String[] getUsedPortNames()
throws gov.cca.CCAException {
Object[] keyObjArray = usesPortMap.keySet().toArray();
String[] keyStrArray = new String[keyObjArray.length];
for (int i = 0; i < keyObjArray.length; i++)
keyStrArray[i] = (String) keyObjArray[i];
return keyStrArray;
}
/**
* Returns the type of the port specified
* @param providesPortName the name of the provides port whose type is desired
*/
public String getProvidesPortType(String providesPortName)
throws gov.cca.CCAException {
logger.finest("called for port: " + providesPortName);
ProvidesPortInfo pInfo = (ProvidesPortInfo) providesPortMap.get(providesPortName);
if (pInfo != null) {
synchronized(pInfo) {
TypeMap pMap = pInfo.getProperties();
return pMap.getString("cca.portType", "None");
}
} else
throw new PortNotDefinedException("Port " + providesPortName + " not defined");
}
/**
* Returns the type of the port specified
* @param usesPortName the name of the uses port whose type is desired
*/
public String getUsesPortType(String usesPortName)
throws gov.cca.CCAException {
logger.finest("called for port: " + usesPortName);
UsesPortInfo uInfo = (UsesPortInfo) usesPortMap.get(usesPortName);
if (uInfo != null) {
synchronized(uInfo) {
TypeMap uMap = uInfo.getProperties();
return uMap.getString("cca.portType", "None");
}
} else
throw new PortNotDefinedException("Port " + usesPortName + " not defined");
}
/**
* Returns the GSH for the specified provides port
* @param providesPortName the name by which the Provides Port is registered
*/
public String getPortHandle(String providesPortName)
throws gov.cca.CCAException {
logger.finest("called for provides port: " + providesPortName);
ProvidesPortInfo pInfo =
(ProvidesPortInfo) providesPortMap.get(providesPortName);
if (pInfo != null) {
synchronized(pInfo) {
if (pInfo.isRemoved())
throw new PortNotDefinedException("Provides Port : " + providesPortName +
" has been removed");
String retVal = pInfo.getProvidesPortHandle();
return retVal;
}
} else
throw new PortNotDefinedException("Provides Port : " + providesPortName +
" not defined");
}
/**
* Returns a GSH for the requested portName, and increments the number of users
* for this port
* @param providesPortName the name by which the Provides Port is registered
*/
public String incrementUsers(String providesPortName)
throws gov.cca.CCAException {
logger.finest("called for provides port: " + providesPortName);
ProvidesPortInfo pInfo =
(ProvidesPortInfo) providesPortMap.get(providesPortName);
if (pInfo != null) {
synchronized(pInfo) {
if (pInfo.isRemoved())
throw new PortNotDefinedException("Provides Port : " + providesPortName +
" has been removed");
String retVal = pInfo.getProvidesPortHandle();
pInfo.incrNumConnections();
return retVal;
}
} else
throw new PortNotDefinedException("Provides Port : " + providesPortName +
" not defined");
}
/**
* Sets the Provides Port GSH for a uses port during a connect call
* @param providerComponentName the instanceName of the component providing the port
* @param providerComponentHandle the GSH for the providing component
* @param userComponentName the instanceName of the component using the port
* @param userComponentHandle the GSH for the using component
* @param providingPortName the name by which the Provides Port is registered
* @param usingPortName the name by which the Uses Port is registered
* @param providesPortHandle GSH for the Provides Port after the connect
*/
public void addUsesConnection(String providerComponentName,
String providerComponentHandle,
String userComponentName,
String userComponentHandle,
String providingPortName,
String usingPortName,
String providesPortHandle)
throws gov.cca.CCAException {
logger.finest("called with parameters: " +
" provider component = " + providerComponentName +
" user component = " + userComponentName +
" provides port name = " + providingPortName +
" uses port name = " + usingPortName);
// Create ComponentID objects for the provider and user
XCATComponentIDClientImpl provider =
new XCATComponentIDClientImpl(providerComponentName,
providerComponentHandle);
XCATComponentIDClientImpl user =
new XCATComponentIDClientImpl(userComponentName,
userComponentHandle);
// Add a ConnectionID object if all checks are successful
UsesPortInfo uInfo =
(UsesPortInfo) usesPortMap.get(usingPortName);
if (uInfo != null) {
synchronized(uInfo) {
if (uInfo.isUnregistered())
throw new PortNotDefinedException("Uses port: " + usingPortName +
" has been unregistered");
if (uInfo.getConnectionID() != null)
throw new NonstandardException("Uses Port : " + usingPortName +
" is already connected");
XCATConnectionID connectionID =
new XCATConnectionIDImpl(provider,
user,
providingPortName,
usingPortName,
providesPortHandle);
uInfo.setConnectionID(connectionID);
}
} else
throw new PortNotDefinedException("Uses Port : " + usingPortName +
" not defined");
}
/**
* Disconnects the uses side from a connection
* @param usingPortName the name of the uses port which is connected
*/
public void disconnectProvider(String usingPortName)
throws gov.cca.CCAException {
logger.finest("called with uses port: " + usingPortName);
UsesPortInfo uInfo =
(UsesPortInfo) usesPortMap.get(usingPortName);
if (uInfo != null) {
synchronized(uInfo) {
if (uInfo.isUnregistered())
throw new PortNotDefinedException("Uses port: " + usingPortName +
" has been unregistered");
if (uInfo.getInUse())
throw new NonstandardException("Uses Port : " + usingPortName +
" still in use");
uInfo.setConnectionID(null);
}
} else
throw new PortNotDefinedException("Uses Port : " + usingPortName +
" not defined");
}
/**
* Disconnects the provides side from a connection
* @param providingPortName the name of the provides port which is connected
*/
public void disconnectUser(String providingPortName)
throws gov.cca.CCAException {
logger.finest("called with provides port: " + providingPortName);
ProvidesPortInfo pInfo =
(ProvidesPortInfo) providesPortMap.get(providingPortName);
if (pInfo != null) {
synchronized(pInfo) {
if (pInfo.isRemoved())
throw new PortNotDefinedException("Provides Port : " + providingPortName +
" has been removed");
pInfo.decrNumConnections();
}
} else
throw new PortNotDefinedException("Provides Port : " + providingPortName +
" not defined");
}
/**
* Returns the connection information for this uses port
* @param usingPortName the name of the uses port which is connected
*/
public XCATConnectionInfo getConnectionInfo(String usingPortName)
throws gov.cca.CCAException {
logger.finest("called with uses port: " + usingPortName);
if (!usesPortMap.containsKey(usingPortName))
throw new NonstandardException("Uses Port: " + usingPortName +
" not defined");
UsesPortInfo uInfo =
(UsesPortInfo) usesPortMap.get(usingPortName);
if (uInfo.getConnectionID() == null)
return null;
else
return uInfo.getConnectionID().getConnectionInfo();
}
/**
* Sets the TypeMap properties for the component
* @param properties the TypeMap properties object for the component
*/
public void setProperties(gov.cca.TypeMap properties)
throws gov.cca.CCAException {
logger.finest("called");
compProperties = properties;
}
/**
* Gets the TypeMap properties for the component
*/
public gov.cca.TypeMap getProperties()
throws gov.cca.CCAException {
logger.finest("called");
return compProperties;
}
//-------------------------------------------------------------------/
// Methods for additions of connections to standard Web services /
//-------------------------------------------------------------------/
/**
* Register a request for a Port that will be retrieved subsequently
* with a call to getPort().
* @param portName A string uniquely describing this port. This string
* must be unique for this component, over WS, uses and provides ports.
* @param type A string desribing the type of this port.
* @param properties A TypeMap describing properties
* associated with this port. The property "portClass" which specifies
* the fully qualified class name of the interface is mandatory
*/
public void registerWSPort(java.lang.String portName,
java.lang.String type,
gov.cca.TypeMap properties)
throws gov.cca.CCAException {
logger.finest(" called with parameters: " +
" portName = " + portName +
" type = " + type +
" properties = " + properties);
synchronized(this) {
if (usesPortMap.containsKey(portName) ||
(providesPortMap.containsKey(portName)) ||
(wsPortMap.containsKey(portName)))
throw new PortAlreadyDefinedException("Port " + portName +
" already defined");
else {
// check if the portClass property is present
if (properties == null)
throw new NonstandardException("TypeMap should not be empty: " +
"need property portClass");
String intfClassName = properties.getString("portClass",
"None");
if (intfClassName.equals("None"))
throw new NonstandardException("TypeMap should contain property " +
"portClass");
// add a couple of standard properties
properties.putString("cca.portName", portName);
properties.putString("cca.portType", type);
// create a new WSPortInfo object and add it to wsPortMap
WSPortInfo wsInfo = new WSPortInfo(portName, type, properties);
wsPortMap.put(portName, wsInfo);
}
}
}
/**
* Notify the framework that a Port, previously registered by this
* component but currently not in use, is no longer desired.
* @param portName The name of a registered Port.
*/
public void unregisterWSPort(java.lang.String portName)
throws gov.cca.CCAException {
logger.finest("called with portName: " + portName);
WSPortInfo wsInfo = (WSPortInfo) wsPortMap.get(portName);
if (wsInfo != null) {
synchronized(wsInfo) {
if (wsInfo.getInUse())
throw new UsesPortNotReleasedException("Port " + portName + " still in use");
else {
wsInfo.unregisterPort();
wsPortMap.remove(portName);
}
}
} else
throw new PortNotDefinedException("Port " + portName + " not defined");
}
/**
* Sets the connection information for a Web service connection
* @param wsPortName the name that a WS port has been registered as
* @param endPointLocation the URL for the Web service to connect to
*/
public void addWSConnection(String wsPortName,
String endPointLocation)
throws gov.cca.CCAException {
logger.finest("called with parameters: " +
" WS port name: " + wsPortName +
" endpoint location: " + endPointLocation);
// Add connection information if all checks are successful
WSPortInfo wsInfo =
(WSPortInfo) wsPortMap.get(wsPortName);
if (wsInfo != null) {
synchronized(wsInfo) {
if (wsInfo.isUnregistered())
throw new PortNotDefinedException("WS port: " + wsPortName +
" has been unregistered");
if (wsInfo.isConnected())
throw new NonstandardException("WS Port : " + wsPortName +
" is already connected");
wsInfo.setEndPointLocation(endPointLocation);
}
} else
throw new PortNotDefinedException("WS Port : " + wsPortName +
" not defined");
}
/**
* Disconnects the Web services connection
* @param wsPortName the name that a WS port has been registered as
*/
public void disconnectWS(String wsPortName)
throws gov.cca.CCAException {
logger.finest("called with WS port: " + wsPortName);
WSPortInfo wsInfo =
(WSPortInfo) wsPortMap.get(wsPortName);
if (wsInfo != null) {
synchronized(wsInfo) {
if (wsInfo.isUnregistered())
throw new PortNotDefinedException("WS port: " + wsPortName +
" has been unregistered");
if (wsInfo.getInUse())
throw new NonstandardException("WS Port : " + wsPortName +
" still in use");
wsInfo.disconnectPort();
}
} else
throw new PortNotDefinedException("WS Port : " + wsPortName +
" not defined");
}
/**
* Fetch a remote reference for a previously register port (defined by either
* addProvidesPort or (more typically) registerUsesPort, registerWSPort).
* @param portName The previously registered uses/provides/WS port which
* the component now wants to use.
*/
public Remote getRemoteRef(String portName)
throws gov.cca.CCAException {
// For WS ports
WSPortInfo wsInfo =
(WSPortInfo) wsPortMap.get(portName);
if (wsInfo != null) {
synchronized(wsInfo) {
while (wsInfo.getInUse()) {
try {
logger.finest("wait till the port is available");
wsInfo.wait();
} catch (InterruptedException ie) {
logger.severe("Exception while waiting for port to be released", ie);
}
}
if (wsInfo.isUnregistered())
throw new PortNotDefinedException("WS port: " + portName +
" has been unregistered");
if (!wsInfo.isConnected())
throw new PortNotConnectedException("WS Port " + portName
+ " not connected");
wsInfo.setInUse(true);
return wsInfo.getRemoteReference();
}
}
// if it is not a WS port, check if it is a regular CCA port
return getPort(portName);
}
/**
* Release a remote reference being held by a getPort/getRemoteRef invocation
* @param portName The previously fetched remote reference that needs to be
* released
*/
public void releaseRemoteRef(String portName)
throws gov.cca.CCAException {
// For WS ports
WSPortInfo wsInfo =
(WSPortInfo) wsPortMap.get(portName);
if (wsInfo != null) {
synchronized(wsInfo) {
if (wsInfo.isUnregistered())
throw new PortNotDefinedException("WS port: " + portName +
" has been unregistered");
if (wsInfo.getInUse()) {
wsInfo.setInUse(false);
logger.finest("wake up sleeper waiting for port to be released");
wsInfo.notify();
return;
}
else
throw new PortNotInUseException("WS Port " + portName + " not in use");
}
}
// if it is not a WS port, check to see if it is regular CCA port
releasePort(portName);
}
}