Fields Summary |
---|
static Logger | logger |
private static final boolean | debug |
private static final String | ORB_CLASS |
private static final String | ORB_SINGLETON_CLASS |
private static final String | ORB_SE_CLASS |
private static final String | ORB_SE_SINGLETON_CLASS |
private static final String | PEORB_CONFIG_CLASS |
private static final String | IIOP_SSL_SOCKET_FACTORY_CLASS |
private static final String | RMI_UTIL_CLASS |
private static final String | RMI_STUB_CLASS |
private static final String | RMI_PRO_CLASS |
public static final String | JNDI_PROVIDER_URL_PROPERTY |
public static final String | JNDI_CORBA_ORB_PROPERTY |
public static final String | ORB_UTIL_CLASS_PROPERTY |
public static final String | RMIIIOP_STUB_DELEGATE_CLASS_PROPERTY |
public static final String | RMIIIOP_PRO_DELEGATE_CLASS_PROPERTY |
public static final String | OMG_ORB_CLASS_PROPERTY |
public static final String | OMG_ORB_SINGLETON_CLASS_PROPERTY |
public static final String | OMG_ORB_INIT_HOST_PROPERTY |
public static final String | OMG_ORB_INIT_PORT_PROPERTY |
private static final String | PI_ORB_INITIALIZER_CLASS_PREFIX |
public static final String | SUN_USER_CONFIGURATOR_PREFIX |
public static final String | SUN_ORB_ID_PROPERTY |
public static final String | SUN_ORB_SERVER_HOST_PROPERTY |
public static final String | SUN_ORB_SERVER_PORT_PROPERTY |
public static final String | SUN_ORB_SOCKET_FACTORY_CLASS_PROPERTY |
public static final String | SUN_ORB_IOR_TO_SOCKETINFO_CLASS_PROPERTY |
public static final String | SUN_MAX_CONNECTIONS_PROPERTY |
public static final String | ORB_LISTEN_SOCKET_PROPERTY |
public static final String | ORB_DISABLED_PORTS_PROPERTY |
private static final String | SUN_LISTEN_ADDR_ANY_ADDRESS |
private static final String | ORB_IOR_ADDR_ANY_INITIALIZER |
private static final String | DEFAULT_SERVER_ID |
private static final String | DEFAULT_MAX_CONNECTIONS |
private static final String | J2EE_INITIALIZER |
private static final String | SUN_GIOP_DEFAULT_FRAGMENT_SIZE |
private static final String | SUN_GIOP_DEFAULT_BUFFER_SIZE |
private static final String | IIOP_CLEAR_TEXT_CONNECTION |
private static final String | DEFAULT_ORB_INIT_HOST |
private static final String | DEFAULT_ORB_INIT_PORT |
private static final String | SSL |
private static final String | SSL_MUTUALAUTH |
private static final String | ORB_SSL_CERTDB_PATH |
private static final String | ORB_SSL_CERTDB_PASSWORD |
public static final String | SUN_GIOP_FRAGMENT_SIZE_PROPERTY |
public static final String | SUN_GIOP_BUFFER_SIZE_PROPERTY |
public static final String | ORB_SSL_CLIENT_REQUIRED |
public static final String | ORB_SSL_SERVER_REQUIRED |
public static final String | ORB_CLIENT_AUTH_REQUIRED |
public static final String | S1AS_ORB_ID |
private static boolean | propertiesInitialized |
private static org.omg.CORBA.ORB | orb |
private static com.sun.corba.ee.spi.oa.rfm.ReferenceFactoryManager | rfm |
private static int | orbInitialPort |
private static com.sun.enterprise.config.serverbeans.IiopListener[] | iiopListenerBeans |
private static com.sun.enterprise.config.serverbeans.Orb | orbBean |
private static com.sun.enterprise.config.serverbeans.IiopService | iiopServiceBean |
private static Properties | csiv2Props |
private static final Properties | EMPTY_PROPERTIES |
Methods Summary |
---|
private static void | checkAdditionalORBListeners(java.util.Properties props)
// REVISIT: Having to do the null check because this code is shared by the ACC
if (iiopListenerBeans != null) {
// This should be the only place we set additional ORB listeners.
// So there is no need to check if the property is already set.
StringBuffer listenSockets = new StringBuffer("");
for (int i=0; i<iiopListenerBeans.length; i++) {
if ( i==0 && iiopListenerBeans[0].getSsl() == null ) {
// Ignore first listener if its non-SSL, because it
// gets created by default using ORBInitialHost/Port.
continue;
}
if (iiopListenerBeans[i].isEnabled()) {
if (!iiopListenerBeans[i].isSecurityEnabled() ||
iiopListenerBeans[i].getSsl() == null) {
checkForAddrAny(props, iiopListenerBeans[i].getAddress());
listenSockets.append((listenSockets.length()>0 ? "," : "")
+ IIOP_CLEAR_TEXT_CONNECTION
+ ":" + iiopListenerBeans[i].getPort());
} else {
Ssl sslBean = null;
sslBean = iiopListenerBeans[i].getSsl();
assert sslBean != null;
// parse clientAuth
String type;
boolean clientAuth = sslBean.isClientAuthEnabled();
if (clientAuth)
type = SSL_MUTUALAUTH;
else
type = SSL;
// Ignoring cert alias etc.
listenSockets.append((listenSockets.length()>0 ? ",":"")
+ type+":"+iiopListenerBeans[i].getPort());
}
}
}
// Set the value both in the props object and in the system properties.
props.setProperty(ORB_LISTEN_SOCKET_PROPERTY, listenSockets.toString());
}
return;
|
private static void | checkConnectionSettings(java.util.Properties props)
if (orbBean != null) {
String maxConnections;
try {
maxConnections = orbBean.getMaxConnections();
// Validate number formats
Integer.parseInt(maxConnections);
} catch (NumberFormatException nfe) {
if(logger.isLoggable(Level.WARNING)) {
logger.log(Level.WARNING,"enterprise_util.excep_orbmgr_numfmt", nfe);
}
maxConnections = DEFAULT_MAX_CONNECTIONS;
}
props.setProperty(SUN_MAX_CONNECTIONS_PROPERTY, maxConnections);
}
return;
|
private static java.lang.String | checkForAddrAny(java.util.Properties props, java.lang.String orbInitialHost)
if ((orbInitialHost.equals("0.0.0.0")) || (orbInitialHost.equals("::"))
|| (orbInitialHost.equals("::ffff:0.0.0.0"))) {
/* FIXME -DHIRU
props.setProperty(SUN_LISTEN_ADDR_ANY_ADDRESS, orbInitialHost);
props.put(PI_ORB_INITIALIZER_CLASS_PREFIX + ORB_IOR_ADDR_ANY_INITIALIZER, "");
*/
try {
String localAddress = java.net.InetAddress.getLocalHost().getHostAddress();
return localAddress;
} catch (java.net.UnknownHostException uhe) {
logger.log(Level.WARNING,"Unknown host exception - Setting host to localhost");
return DEFAULT_ORB_INIT_HOST;
}
} else {
// Set com.sun.CORBA.ORBServerHost only if it's not one of "0.0.0.0",
// "::" or "::ffff:0.0.0.0"
props.setProperty(SUN_ORB_SERVER_HOST_PROPERTY, orbInitialHost);
return orbInitialHost;
}
|
private static void | checkForOrbPropertyValues(java.util.Properties props)
if (orbBean != null) {
ElementProperty[] ep = orbBean.getElementProperty() ;
if (ep != null) {
for (int i = 0; i < ep.length; i++) {
props.setProperty(ep[i].getName(), ep[i].getValue());
}
}
}
|
private static void | checkMessageFragmentSize(java.util.Properties props)
if (orbBean != null) {
String fragmentSize, bufferSize;
try {
int fsize = ((Integer.parseInt(orbBean.getMessageFragmentSize().trim()))/8) * 8;
if (fsize < 32) {
fragmentSize = "32";
logger.log(Level.INFO,"Setting ORB Message Fragment size to " + fragmentSize);
}
else {
fragmentSize = String.valueOf(fsize);
}
bufferSize = fragmentSize;
} catch (NumberFormatException nfe) {
// Print stack trace and use default values
logger.log(Level.WARNING,"enterprise_util.excep_in_reading_fragment_size", nfe);
logger.log(Level.INFO,"Setting ORB Message Fragment size to Default " +
SUN_GIOP_DEFAULT_FRAGMENT_SIZE);
fragmentSize = SUN_GIOP_DEFAULT_FRAGMENT_SIZE;
bufferSize = SUN_GIOP_DEFAULT_BUFFER_SIZE;
}
props.setProperty(SUN_GIOP_FRAGMENT_SIZE_PROPERTY, fragmentSize);
props.setProperty(SUN_GIOP_BUFFER_SIZE_PROPERTY, bufferSize);
}
|
private static java.lang.String | checkORBInitialHost(java.util.Properties props)
// Host setting in system properties always takes precedence.
String orbInitialHost = System.getProperty(OMG_ORB_INIT_HOST_PROPERTY);
if ( orbInitialHost == null )
orbInitialHost = props.getProperty(OMG_ORB_INIT_HOST_PROPERTY);
if ( orbInitialHost == null ) {
try {
orbInitialHost = iiopListenerBeans[0].getAddress();
orbInitialHost = checkForAddrAny(props, orbInitialHost);
} catch (NullPointerException npe) {
// REVISIT: Ignoring the NPE because the appclient container shares this code
logger.log(Level.FINE,"IIOP listener element is null. Ignoring and proceeding.");
}
}
if( orbInitialHost == null )
orbInitialHost = DEFAULT_ORB_INIT_HOST;
props.setProperty(OMG_ORB_INIT_HOST_PROPERTY, orbInitialHost);
if ( debug ) {
if (logger.isLoggable(Level.FINE))
logger.log(Level.FINE,"Setting orb initial host to " + orbInitialHost);
}
return orbInitialHost;
|
private static java.lang.String | checkORBInitialPort(java.util.Properties props)
// Port setting in system properties always takes precedence.
String initialPort = System.getProperty(OMG_ORB_INIT_PORT_PROPERTY);
if ( initialPort == null )
initialPort = props.getProperty(OMG_ORB_INIT_PORT_PROPERTY);
if ( initialPort == null ) {
try {
initialPort = iiopListenerBeans[0].getPort();
if (!iiopListenerBeans[0].isEnabled()) {
props.setProperty(ORB_DISABLED_PORTS_PROPERTY, initialPort);
}
// Set the default server port to equal the initial port.
// This will be the port that is used both for object refs and
// for the name service
// REVISIT: For now setting this value only if we have a valid
// server configuration. This is meant to circumvent a client-side
// problem. The ACC uses the same ORBManager and hence ends up
// creating a listener (yuk!) during root POA initialization (yuk!).
// It is best to let this listener not come up on any fixed port.
// Once this problem is fixed we can move this property setting
// outside.
if (!iiopListenerBeans[0].isEnabled()) {
// If the plain iiop listener is disabled do not create
// a listener on this port - bug 4927187
props.setProperty(SUN_ORB_SERVER_PORT_PROPERTY, "-1");
} else {
props.setProperty(SUN_ORB_SERVER_PORT_PROPERTY, initialPort);
}
} catch (NullPointerException npe) {
logger.log(Level.FINE,"IIOP listener element is null. Ignoring and proceeding.");
}
}
if( initialPort == null )
initialPort = DEFAULT_ORB_INIT_PORT;
// Make sure we set initial port in System properties so that
// any instantiations of com.sun.jndi.cosnaming.CNCtxFactory
// use same port.
props.setProperty(OMG_ORB_INIT_PORT_PROPERTY, initialPort);
// Done to initialize the Persistent Server Port, before any
// POAs are created. This was earlier done in POAEJBORB
// Do it only in the appserver, not on appclient
if (Switch.getSwitch().getContainerType() == Switch.EJBWEB_CONTAINER) {
props.setProperty(ORBConstants.PERSISTENT_SERVER_PORT_PROPERTY,
initialPort);
}
if ( debug ) {
if (logger.isLoggable(Level.FINE))
logger.log(Level.FINE,"Setting orb initial port to " + initialPort);
}
orbInitialPort = new Integer(initialPort).intValue();
return initialPort;
|
private static void | checkServerSSLOutboundSettings(java.util.Properties props)
if (iiopServiceBean != null) {
SslClientConfig sslClientConfigBean = iiopServiceBean.getSslClientConfig();
if (sslClientConfigBean != null) {
Ssl ssl = sslClientConfigBean.getSsl();
assert(ssl != null);
}
}
|
public static synchronized java.util.Properties | getCSIv2Props()
initProperties() ;
return csiv2Props;
|
public static synchronized org.omg.CORBA.ORB | getORB(java.util.Properties props)Return the shared ORB instance for the app server.
If the ORB is not already initialized, it is created
with the standard server properties, which can be
overridden by Properties passed in the props argument.
try {
if(logger.isLoggable(Level.FINEST)) {
logger.log(Level.FINEST, "ORBManager.getORB->: " + orb);
}
initProperties() ;
if (orb == null)
initORB( props ) ;
return orb;
} finally {
if(logger.isLoggable(Level.FINEST)) {
logger.log(Level.FINEST, "ORBManager.getORB<-: " + orb);
}
}
|
public static org.omg.CORBA.ORB | getORB()
return getORB( EMPTY_PROPERTIES ) ;
|
private static java.lang.String[] | getORBInitRef(java.lang.String orbInitialHost, java.lang.String initialPort)
// Add -ORBInitRef NameService=....
// This ensures that INS will be used to talk with the NameService.
String[] newArgs = new String[]{
"-ORBInitRef",
"NameService=corbaloc:iiop:1.2@"
+ orbInitialHost + ":"
+ initialPort + "/NameService"
} ;
return newArgs;
|
private static java.lang.String[] | getORBInitRef(java.lang.String endpoints)
String[] list = (String[])endpoints.split(",");
String corbalocURL = S1ASCtxFactory.getCorbalocURL(list);
logger.fine("ORBManager.getORBInitRef = " + corbalocURL );
// Add -ORBInitRef NameService=....
// This ensures that INS will be used to talk with the NameService.
String[] newArgs = new String[]{
"-ORBInitRef",
"NameService=corbaloc:" + corbalocURL + "/NameService"
} ;
return newArgs;
|
public static synchronized int | getORBInitialPort()
initProperties() ;
return orbInitialPort;
|
private static void | initORB(java.util.Properties props)
try {
if(logger.isLoggable(Level.FINE)) {
logger.log(Level.FINE, ".initORB->: " );
}
//setORBSystemProperties() ;
Properties orbInitProperties = new Properties();
orbInitProperties.putAll(props);
orbInitProperties.put(ORBConstants.APPSERVER_MODE, "true");
// The main configurator.
orbInitProperties.put(SUN_USER_CONFIGURATOR_PREFIX
+ PEORB_CONFIG_CLASS, "dummy" );
setFOLBProperties( orbInitProperties ) ;
// Standard OMG Properties.
orbInitProperties.put(ORBConstants.ORB_SERVER_ID_PROPERTY,
DEFAULT_SERVER_ID ) ;
orbInitProperties.put( OMG_ORB_CLASS_PROPERTY, ORB_CLASS);
orbInitProperties.put(
PI_ORB_INITIALIZER_CLASS_PREFIX + J2EE_INITIALIZER, "");
orbInitProperties.put(ORBConstants.ALLOW_LOCAL_OPTIMIZATION,
"true" ) ;
orbInitProperties.put(ORBConstants.GET_SERVICE_CONTEXT_RETURNS_NULL, "true");
orbInitProperties.put(SUN_ORB_ID_PROPERTY, S1AS_ORB_ID);
orbInitProperties.put(ORBConstants.SHOW_INFO_MESSAGES, "true");
// Do this even if propertiesInitialized, since props may override
// ORBInitialHost and port.
String initialPort = checkORBInitialPort(orbInitProperties);
String orbInitialHost = checkORBInitialHost(orbInitProperties);
String[] args;
if (System.getProperty(S1ASCtxFactory.IIOP_ENDPOINTS_PROPERTY) != null &&
!System.getProperty(S1ASCtxFactory.IIOP_ENDPOINTS_PROPERTY).equals("")) {
args = getORBInitRef(System.getProperty(S1ASCtxFactory.IIOP_ENDPOINTS_PROPERTY));
} else {
// Add -ORBInitRef for INS to work
args = getORBInitRef(orbInitialHost, initialPort);
}
checkAdditionalORBListeners(orbInitProperties);
checkConnectionSettings(orbInitProperties);
checkMessageFragmentSize(orbInitProperties);
checkServerSSLOutboundSettings(orbInitProperties);
checkForOrbPropertyValues(orbInitProperties);
// The following is done only on the Server Side to set the
// ThreadPoolManager in the ORB. ThreadPoolManager on the server
// is initialized based on configuration parameters found in
// domain.xml. On the client side this is not done
if (Switch.getSwitch().getContainerType() == Switch.EJBWEB_CONTAINER) {
PEORBConfigurator.setThreadPoolManager();
}
// orb MUST be set before calling getFVDCodeBaseIOR, or we can
// recurse back into initORB due to interceptors that run
// when the TOA supporting the FVD is created!
// DO NOT MODIFY initORB to return ORB!!!
/**
* we can't create object adapters inside the ORB init path, or else we'll get this same problem
* in slightly different ways. (address in use exception)
* Having an IORInterceptor (TxSecIORInterceptor) get called during ORB init always results in a
* nested ORB.init call because of the call to getORB in the IORInterceptor.
*/
orb = ORB.init(args, orbInitProperties);
rfm = (ReferenceFactoryManager)orb.resolve_initial_references(
ORBConstants.REFERENCE_FACTORY_MANAGER ) ;
ASORBUtilities.initGIS(orb);
// SeeBeyond fix for 6325988: needs testing.
// Still do not know why this might make any difference.
// Invoke this for its side-effects: ignore returned IOR.
((com.sun.corba.ee.spi.orb.ORB)orb).getFVDCodeBaseIOR() ;
} catch ( Exception ex ) {
logger.log(Level.SEVERE,"enterprise_util.excep_in_createorb",ex);
throw new RuntimeException( ex ) ;
} finally {
if(logger.isLoggable(Level.FINE)) {
logger.log(Level.FINE, ".initORB<-: " );
}
}
|
private static void | initProperties()
try {
if (logger.isLoggable(Level.FINE)) {
logger.log(Level.FINE, "ORBManager.initProperties->: " + orb);
}
if (propertiesInitialized)
return ;
try {
ServerContext serverContext = ApplicationServer.getServerContext();
if (serverContext == null) {
// serverContext is null inside the ACC.
String initialPort = checkORBInitialPort( EMPTY_PROPERTIES ) ;
return ;
} else {
ConfigContext configContext = serverContext.getConfigContext();
assert(configContext != null);
Server serverBean = ServerBeansFactory.getServerBean(configContext);
assert(serverBean != null);
iiopServiceBean = ServerBeansFactory.getIiopServiceBean(configContext);
assert(iiopServiceBean != null);
iiopListenerBeans = iiopServiceBean.getIiopListener();
assert (iiopListenerBeans != null && iiopListenerBeans.length > 0);
// checkORBInitialPort looks at iiopListenerBeans, if present
String initialPort = checkORBInitialPort( EMPTY_PROPERTIES ) ;
orbBean = iiopServiceBean.getOrb();
assert (orbBean != null);
// Initialize IOR security config for non-EJB CORBA objects
//iiopServiceBean.isClientAuthenticationRequired()));
csiv2Props.put(ORB_CLIENT_AUTH_REQUIRED, String.valueOf(
iiopServiceBean.isClientAuthenticationRequired()));
boolean corbaSSLRequired = true;
// If there is at least one non-SSL listener, then it means
// SSL is not required for CORBA objects.
for ( int i=0; i<iiopListenerBeans.length; i++ ) {
if ( iiopListenerBeans[i].getSsl() == null ) {
corbaSSLRequired = false;
break;
}
}
csiv2Props.put(ORB_SSL_SERVER_REQUIRED, String.valueOf(
corbaSSLRequired));
}
} catch (ConfigException cfe) {
logger.log(Level.SEVERE,"enterprise_util.orbmgr_config_excep", cfe);
} catch (NullPointerException npe) {
// REVISIT: Ignoring the NPE because the appclient container shares this code
logger.log(Level.FINE,"Server Context is NULL. Ignoring and proceeding.");
}
} finally {
// Whether this succeeds or not, only do initProperties once.
propertiesInitialized = true ;
if(logger.isLoggable(Level.FINE)) {
logger.log(Level.FINE, "ORBManager.initProperties<-: " + orb);
}
}
|
public static boolean | isEjbAdapterName(java.lang.String[] adapterName)Returns whether an adapterName (from ServerRequestInfo.adapter_name)
represents an EJB or not.
boolean result = false ;
if (rfm != null)
result = rfm.isRfmName( adapterName ) ;
return result ;
|
public static boolean | isIsACall(java.lang.String operationName)Returns whether the operationName corresponds to an "is_a" call
or not (used to implement PortableRemoteObject.narrow.
return operationName.equals( "_is_a" ) ;
|
private static void | setFOLBProperties(java.util.Properties orbInitProperties)Set the ORB properties for IIOP failover and load balancing.
orbInitProperties.put(ORBConstants.RFM_PROPERTY,"dummy");
orbInitProperties.put(SUN_ORB_SOCKET_FACTORY_CLASS_PROPERTY,
IIOP_SSL_SOCKET_FACTORY_CLASS ) ;
// ClientGroupManager.
// Registers itself as
// ORBInitializer (that registers ClientRequestInterceptor)
// IIOPPrimaryToContactInfo
// IORToSocketInfo
orbInitProperties.setProperty(
ORBConstants.USER_CONFIGURATOR_PREFIX
+ com.sun.corba.ee.impl.folb.ClientGroupManager.class.getName(),
"dummy");
// This configurator registers the CSIv2SSLTaggedComponentHandler
orbInitProperties.setProperty(
ORBConstants.USER_CONFIGURATOR_PREFIX
+ CSIv2SSLTaggedComponentHandlerImpl.class.getName(),
"dummy");
if (ASORBUtilities.isGMSAvailableAndClusterHeartbeatEnabled()) {
if(logger.isLoggable(Level.FINE)) {
logger.log(Level.FINE, "GMS available and enabled - doing EE initialization");
}
// Register ServerGroupManager.
// Causes it to register itself as an ORBInitializer
// that then registers it as
// IOR and ServerRequest Interceptors.
orbInitProperties.setProperty(
ORBConstants.USER_CONFIGURATOR_PREFIX
+ com.sun.corba.ee.impl.folb.ServerGroupManager.class.getName(),
"dummy");
if(logger.isLoggable(Level.FINE)) {
logger.log(Level.FINE, "Did EE property initialization");
}
} else {
if(logger.isLoggable(Level.FINE)) {
logger.log(Level.FINE, "Doing PE initialization");
}
orbInitProperties.put(ORBConstants.PI_ORB_INITIALIZER_CLASS_PREFIX
+ FailoverIORInterceptor.class.getName(), "dummy");
if(logger.isLoggable(Level.FINE)) {
logger.log(Level.FINE, "Did PE property initialization");
}
}
|
public static void | setORBSystemProperties()Set ORB-related system properties that are required in case
user code in the app server or app client container creates a
new ORB instance. The default result of calling
ORB.init( String[], Properties ) must be a fully usuable, consistent
ORB. This avoids difficulties with having the ORB class set
to a different ORB than the RMI-IIOP delegates.
java.security.AccessController.doPrivileged(
new java.security.PrivilegedAction() {
public java.lang.Object run() {
if (System.getProperty(OMG_ORB_CLASS_PROPERTY) == null) {
// set ORB based on JVM vendor
if(System.getProperty("java.vendor").equals("Sun Microsystems Inc.")) {
System.setProperty(OMG_ORB_CLASS_PROPERTY, ORB_SE_CLASS);
} else {
// if not Sun, then set to EE class
System.setProperty(OMG_ORB_CLASS_PROPERTY, ORB_CLASS);
}
}
if (System.getProperty(OMG_ORB_SINGLETON_CLASS_PROPERTY) == null) {
// set ORBSingleton based on JVM vendor
if(System.getProperty("java.vendor").equals("Sun Microsystems Inc.")) {
System.setProperty(OMG_ORB_SINGLETON_CLASS_PROPERTY, ORB_SE_SINGLETON_CLASS);
} else {
// if not Sun, then set to EE class
System.setProperty(OMG_ORB_SINGLETON_CLASS_PROPERTY, ORB_SINGLETON_CLASS);
}
}
System.setProperty(ORB_UTIL_CLASS_PROPERTY,
RMI_UTIL_CLASS ) ;
System.setProperty(RMIIIOP_STUB_DELEGATE_CLASS_PROPERTY,
RMI_STUB_CLASS ) ;
System.setProperty(RMIIIOP_PRO_DELEGATE_CLASS_PROPERTY,
RMI_PRO_CLASS ) ;
return null;
}
}
);
|