1 /*
   2  * Copyright (c) 2002, 2013, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 package com.sun.corba.se.impl.orb ;
  27 
  28 import java.net.URL ;
  29 import java.net.InetSocketAddress;
  30 import java.net.Socket ;
  31 import java.net.ServerSocket ;
  32 
  33 import java.io.IOException ;
  34 
  35 import java.util.HashMap ;
  36 import java.util.List;
  37 import java.util.Map ;
  38 
  39 import java.security.AccessController ;
  40 import java.security.PrivilegedExceptionAction ;
  41 import java.security.PrivilegedActionException ;
  42 
  43 import org.omg.PortableInterceptor.ORBInitializer ;
  44 import org.omg.PortableInterceptor.ORBInitInfo ;
  45 
  46 import com.sun.corba.se.pept.broker.Broker;
  47 import com.sun.corba.se.pept.encoding.InputObject;
  48 import com.sun.corba.se.pept.encoding.OutputObject;
  49 import com.sun.corba.se.pept.protocol.MessageMediator;
  50 import com.sun.corba.se.pept.transport.Acceptor;
  51 import com.sun.corba.se.pept.transport.Connection;
  52 import com.sun.corba.se.pept.transport.ContactInfo;
  53 import com.sun.corba.se.pept.transport.ContactInfoList;
  54 import com.sun.corba.se.pept.transport.EventHandler;
  55 import com.sun.corba.se.pept.transport.InboundConnectionCache;
  56 
  57 import com.sun.corba.se.spi.ior.IOR ;
  58 import com.sun.corba.se.spi.ior.ObjectKey ;
  59 import com.sun.corba.se.spi.ior.iiop.GIOPVersion ;
  60 import com.sun.corba.se.spi.logging.CORBALogDomains ;
  61 import com.sun.corba.se.spi.orb.ORB;
  62 import com.sun.corba.se.spi.orb.Operation ;
  63 import com.sun.corba.se.spi.orb.OperationFactory ;
  64 import com.sun.corba.se.spi.orb.ParserData ;
  65 import com.sun.corba.se.spi.orb.ParserDataFactory ;
  66 import com.sun.corba.se.spi.orb.StringPair ;
  67 import com.sun.corba.se.spi.transport.CorbaContactInfoList;
  68 import com.sun.corba.se.spi.transport.CorbaContactInfoListFactory;
  69 import com.sun.corba.se.spi.transport.CorbaTransportManager;
  70 import com.sun.corba.se.spi.transport.IORToSocketInfo;
  71 import com.sun.corba.se.spi.transport.ReadTimeouts;
  72 import com.sun.corba.se.spi.transport.SocketInfo;
  73 import com.sun.corba.se.spi.transport.IIOPPrimaryToContactInfo;
  74 import com.sun.corba.se.spi.transport.TransportDefault;
  75 
  76 import com.sun.corba.se.impl.encoding.CodeSetComponentInfo ;
  77 import com.sun.corba.se.impl.encoding.OSFCodeSetRegistry ;
  78 import com.sun.corba.se.impl.legacy.connection.USLPort ;
  79 import com.sun.corba.se.impl.logging.ORBUtilSystemException ;
  80 import com.sun.corba.se.impl.oa.poa.BadServerIdHandler ;
  81 import com.sun.corba.se.impl.orbutil.ORBConstants ;
  82 import com.sun.corba.se.impl.protocol.giopmsgheaders.KeyAddr ;
  83 import com.sun.corba.se.impl.protocol.giopmsgheaders.ProfileAddr ;
  84 import com.sun.corba.se.impl.protocol.giopmsgheaders.ReferenceAddr ;
  85 import com.sun.corba.se.impl.transport.DefaultIORToSocketInfoImpl;
  86 import com.sun.corba.se.impl.transport.DefaultSocketFactoryImpl;
  87 
  88 import sun.corba.SharedSecrets;
  89 
  90 /** Initialize the parser data for the standard ORB parser.  This is used both
  91  * to implement ORBDataParserImpl and to provide the basic testing framework
  92  * for ORBDataParserImpl.
  93  */
  94 public class ParserTable {
  95     private static String MY_CLASS_NAME = ParserTable.class.getName() ;
  96 
  97     private static ParserTable myInstance = new ParserTable() ;
  98 
  99     private ORBUtilSystemException wrapper ;
 100 
 101     public static ParserTable get()
 102     {
 103         return myInstance ;
 104     }
 105 
 106     private ParserData[] parserData ;
 107 
 108     public ParserData[] getParserData()
 109     {
 110         ParserData[] parserArray = new ParserData[parserData.length];
 111         System.arraycopy(parserData, 0, parserArray, 0, parserData.length);
 112         return parserArray;
 113     }
 114 
 115     private ParserTable() {
 116         wrapper = ORBUtilSystemException.get( CORBALogDomains.ORB_LIFECYCLE ) ;
 117 
 118         String codeSetTestString =
 119             OSFCodeSetRegistry.ISO_8859_1_VALUE + "," +
 120             OSFCodeSetRegistry.UTF_16_VALUE + "," +
 121             OSFCodeSetRegistry.ISO_646_VALUE ;
 122 
 123         String[] debugTestData = { "subcontract", "poa", "transport" } ;
 124 
 125         USLPort[] USLPorts = { new USLPort( "FOO", 2701 ), new USLPort( "BAR", 3333 ) } ;
 126 
 127         ReadTimeouts readTimeouts =
 128                TransportDefault.makeReadTimeoutsFactory().create(
 129                     ORBConstants.TRANSPORT_TCP_INITIAL_TIME_TO_WAIT,
 130                     ORBConstants.TRANSPORT_TCP_MAX_TIME_TO_WAIT,
 131                     ORBConstants.TRANSPORT_TCP_GIOP_HEADER_MAX_TIME_TO_WAIT,
 132                     ORBConstants.TRANSPORT_TCP_TIME_TO_WAIT_BACKOFF_FACTOR);
 133 
 134         ORBInitializer[] TestORBInitializers =
 135             { null,
 136               new TestORBInitializer1(),
 137               new TestORBInitializer2() }  ;
 138         StringPair[] TestORBInitData = {
 139             new StringPair( "foo.bar.blech.NonExistent", "dummy" ),
 140             new StringPair( MY_CLASS_NAME + "$TestORBInitializer1", "dummy" ),
 141             new StringPair( MY_CLASS_NAME + "$TestORBInitializer2", "dummy" ) } ;
 142 
 143         Acceptor[] TestAcceptors =
 144             { new TestAcceptor2(),
 145               new TestAcceptor1(),
 146               null }  ;
 147         // REVISIT: The test data gets put into a Properties object where
 148         // order is not guaranteed.  Thus the above array is in reverse.
 149         StringPair[] TestAcceptorData = {
 150             new StringPair( "foo.bar.blech.NonExistent", "dummy" ),
 151             new StringPair( MY_CLASS_NAME + "$TestAcceptor1", "dummy" ),
 152             new StringPair( MY_CLASS_NAME + "$TestAcceptor2", "dummy" ) } ;
 153 
 154         StringPair[] TestORBInitRefData =
 155             { new StringPair( "Foo", "ior:930492049394" ),
 156               new StringPair( "Bar", "ior:3453465785633576" ) } ;
 157 
 158         URL testServicesURL = null ;
 159         String testServicesString = "corbaloc::camelot/NameService" ;
 160 
 161         try {
 162             testServicesURL = new URL( testServicesString )  ;
 163         } catch (Exception exc) {
 164         }
 165 
 166         // propertyName,
 167         // operation,
 168         // fieldName, defaultValue,
 169         // testValue, testData (string or Pair[])
 170         ParserData[] pd = {
 171             ParserDataFactory.make( ORBConstants.DEBUG_PROPERTY,
 172                 OperationFactory.listAction( ",", OperationFactory.stringAction()),
 173                 "debugFlags", new String[0],
 174                 debugTestData, "subcontract,poa,transport" ),
 175             ParserDataFactory.make( ORBConstants.INITIAL_HOST_PROPERTY,
 176                 OperationFactory.stringAction(),
 177                 "ORBInitialHost", "",
 178                 "Foo", "Foo" ),
 179             ParserDataFactory.make( ORBConstants.INITIAL_PORT_PROPERTY,
 180                 OperationFactory.integerAction(),
 181                 "ORBInitialPort", new Integer( ORBConstants.DEFAULT_INITIAL_PORT ),
 182                 new Integer( 27314 ), "27314" ),
 183             // Where did this come from?
 184             //ParserDataFactory.make( ORBConstants.INITIAL_PORT_PROPERTY,
 185                 //OperationFactory.booleanAction(),
 186                 //"ORBInitialPortInitialized", Boolean.FALSE,
 187                 //Boolean.TRUE, "27314" ),
 188             ParserDataFactory.make( ORBConstants.SERVER_HOST_PROPERTY,
 189                 OperationFactory.stringAction(),
 190                 "ORBServerHost", "",
 191                 "camelot", "camelot" ),
 192             ParserDataFactory.make( ORBConstants.SERVER_PORT_PROPERTY,
 193                 OperationFactory.integerAction(),
 194                 "ORBServerPort", new Integer( 0 ),
 195                 new Integer( 38143 ), "38143" ),
 196             // NOTE: We are putting SERVER_HOST_NAME configuration info into
 197             // DataCollectorBase to avoid a security hole.  However, that forces
 198             // us to also set LISTEN_ON_ALL_INTERFACES at the same time.
 199             // This all needs to be cleaned up for two reasons: to get configuration
 200             // out of DataCollectorBase and to correctly support multihoming.
 201             ParserDataFactory.make( ORBConstants.LISTEN_ON_ALL_INTERFACES,
 202                 OperationFactory.stringAction(),
 203                 "listenOnAllInterfaces", ORBConstants.LISTEN_ON_ALL_INTERFACES,
 204                 "foo", "foo" ),
 205             ParserDataFactory.make( ORBConstants.ORB_ID_PROPERTY,
 206                 OperationFactory.stringAction(),
 207                 "orbId", "",
 208                 "foo", "foo" ),
 209             ParserDataFactory.make( ORBConstants.OLD_ORB_ID_PROPERTY,
 210                 OperationFactory.stringAction(),
 211                 "orbId", "",
 212                 "foo", "foo" ),
 213             ParserDataFactory.make( ORBConstants.ORB_SERVER_ID_PROPERTY,
 214                 OperationFactory.integerAction(),
 215                 "persistentServerId", new Integer(-1),
 216                 new Integer( 1234), "1234" ),
 217             ParserDataFactory.make(
 218                 ORBConstants.ORB_SERVER_ID_PROPERTY,
 219                 OperationFactory.setFlagAction(),
 220                 "persistentServerIdInitialized", Boolean.FALSE,
 221                 Boolean.TRUE, "1234" ),
 222             ParserDataFactory.make(
 223                 ORBConstants.ORB_SERVER_ID_PROPERTY,
 224                 OperationFactory.setFlagAction(),
 225                 "orbServerIdPropertySpecified", Boolean.FALSE,
 226                 Boolean.TRUE, "1234" ),
 227             // REVISIT after switch
 228             // ParserDataFactory.make( ORBConstants.INITIAL_SERVICES_PROPERTY,
 229                 // OperationFactory.URLAction(),
 230                 // "servicesURL", null,
 231                 // testServicesURL, testServicesString ),
 232             // ParserDataFactory.make( ORBConstants.DEFAULT_INIT_REF_PROPERTY,
 233                 // OperationFactory.stringAction(),
 234                 // "defaultInitRef", null,
 235                 // "Fooref", "Fooref" ),
 236             ParserDataFactory.make( ORBConstants.HIGH_WATER_MARK_PROPERTY,
 237                 OperationFactory.integerAction(),
 238                 "highWaterMark", new Integer( 240 ),
 239                 new Integer( 3745 ), "3745" ),
 240             ParserDataFactory.make( ORBConstants.LOW_WATER_MARK_PROPERTY,
 241                 OperationFactory.integerAction(),
 242                 "lowWaterMark", new Integer( 100 ),
 243                 new Integer( 12 ), "12" ),
 244             ParserDataFactory.make( ORBConstants.NUMBER_TO_RECLAIM_PROPERTY,
 245                 OperationFactory.integerAction(),
 246                 "numberToReclaim", new Integer( 5 ),
 247                 new Integer( 231 ), "231" ),
 248             ParserDataFactory.make( ORBConstants.GIOP_VERSION,
 249                 makeGVOperation(),
 250                 "giopVersion", GIOPVersion.DEFAULT_VERSION,
 251                 new GIOPVersion( 2, 3 ), "2.3" ),
 252             ParserDataFactory.make( ORBConstants.GIOP_FRAGMENT_SIZE,
 253                 makeFSOperation(), "giopFragmentSize",
 254                 new Integer( ORBConstants.GIOP_DEFAULT_FRAGMENT_SIZE ),
 255                 new Integer( 65536 ), "65536" ),
 256             ParserDataFactory.make( ORBConstants.GIOP_BUFFER_SIZE,
 257                 OperationFactory.integerAction(),
 258                 "giopBufferSize", new Integer( ORBConstants.GIOP_DEFAULT_BUFFER_SIZE ),
 259                 new Integer( 234000 ), "234000" ),
 260             ParserDataFactory.make( ORBConstants.GIOP_11_BUFFMGR,
 261                 makeBMGROperation(),
 262                 "giop11BuffMgr", new Integer( ORBConstants.DEFAULT_GIOP_11_BUFFMGR ),
 263                 new Integer( 1 ), "CLCT" ),
 264             ParserDataFactory.make( ORBConstants.GIOP_12_BUFFMGR,
 265                 makeBMGROperation(),
 266                 "giop12BuffMgr", new Integer( ORBConstants.DEFAULT_GIOP_12_BUFFMGR ),
 267                 new Integer( 0 ), "GROW" ),
 268 
 269             // Note that the same property is used to set two different
 270             // fields here.  This requires that both entries use the same test
 271             // data, or the test will fail.
 272             ParserDataFactory.make( ORBConstants.GIOP_TARGET_ADDRESSING,
 273                 OperationFactory.compose( OperationFactory.integerRangeAction( 0, 3 ),
 274                     OperationFactory.convertIntegerToShort() ),
 275                 "giopTargetAddressPreference",
 276                 new Short( ORBConstants.ADDR_DISP_HANDLE_ALL ),
 277                 new Short( (short)2 ), "2" ),
 278             ParserDataFactory.make( ORBConstants.GIOP_TARGET_ADDRESSING,
 279                 makeADOperation(),
 280                 "giopAddressDisposition", new Short( KeyAddr.value ),
 281                 new Short( (short)2 ), "2" ),
 282             ParserDataFactory.make( ORBConstants.ALWAYS_SEND_CODESET_CTX_PROPERTY,
 283                 OperationFactory.booleanAction(),
 284                 "alwaysSendCodeSetCtx", Boolean.TRUE,
 285                 Boolean.FALSE, "false"),
 286             ParserDataFactory.make( ORBConstants.USE_BOMS,
 287                 OperationFactory.booleanAction(),
 288                 "useByteOrderMarkers",
 289                     Boolean.valueOf( ORBConstants.DEFAULT_USE_BYTE_ORDER_MARKERS ),
 290                 Boolean.FALSE, "false" ),
 291             ParserDataFactory.make( ORBConstants.USE_BOMS_IN_ENCAPS,
 292                 OperationFactory.booleanAction(),
 293                 "useByteOrderMarkersInEncaps",
 294                     Boolean.valueOf( ORBConstants.DEFAULT_USE_BYTE_ORDER_MARKERS_IN_ENCAPS ),
 295                 Boolean.FALSE, "false" ),
 296             ParserDataFactory.make( ORBConstants.CHAR_CODESETS,
 297                 makeCSOperation(),
 298                 "charData", CodeSetComponentInfo.JAVASOFT_DEFAULT_CODESETS.getCharComponent(),
 299                 CodeSetComponentInfo.createFromString( codeSetTestString ), codeSetTestString ),
 300             ParserDataFactory.make( ORBConstants.WCHAR_CODESETS,
 301                 makeCSOperation(),
 302                 "wcharData", CodeSetComponentInfo.JAVASOFT_DEFAULT_CODESETS.getWCharComponent(),
 303                 CodeSetComponentInfo.createFromString( codeSetTestString ), codeSetTestString ),
 304             ParserDataFactory.make( ORBConstants.ALLOW_LOCAL_OPTIMIZATION,
 305                 OperationFactory.booleanAction(),
 306                 "allowLocalOptimization", Boolean.FALSE,
 307                 Boolean.TRUE, "true" ),
 308             ParserDataFactory.make( ORBConstants.LEGACY_SOCKET_FACTORY_CLASS_PROPERTY,
 309                 makeLegacySocketFactoryOperation(),
 310                 // No default - must be set by user if they are using
 311                 // legacy socket factory.
 312                 "legacySocketFactory", null,
 313                 new TestLegacyORBSocketFactory(),
 314                 MY_CLASS_NAME + "$TestLegacyORBSocketFactory" ),
 315             ParserDataFactory.make( ORBConstants.SOCKET_FACTORY_CLASS_PROPERTY,
 316                 makeSocketFactoryOperation(),
 317                 "socketFactory", new DefaultSocketFactoryImpl(),
 318                 new TestORBSocketFactory(),
 319                 MY_CLASS_NAME + "$TestORBSocketFactory" ),
 320             ParserDataFactory.make( ORBConstants.LISTEN_SOCKET_PROPERTY,
 321                 makeUSLOperation() ,
 322                 "userSpecifiedListenPorts", new USLPort[0],
 323                 USLPorts, "FOO:2701,BAR:3333" ),
 324             ParserDataFactory.make( ORBConstants.IOR_TO_SOCKET_INFO_CLASS_PROPERTY,
 325                 makeIORToSocketInfoOperation(),
 326                 "iorToSocketInfo", new DefaultIORToSocketInfoImpl(),
 327                 new TestIORToSocketInfo(),
 328                 MY_CLASS_NAME + "$TestIORToSocketInfo" ),
 329             ParserDataFactory.make( ORBConstants.IIOP_PRIMARY_TO_CONTACT_INFO_CLASS_PROPERTY,
 330                 makeIIOPPrimaryToContactInfoOperation(),
 331                 "iiopPrimaryToContactInfo", null,
 332                 new TestIIOPPrimaryToContactInfo(),
 333                 MY_CLASS_NAME + "$TestIIOPPrimaryToContactInfo" ),
 334             ParserDataFactory.make( ORBConstants.CONTACT_INFO_LIST_FACTORY_CLASS_PROPERTY,
 335                 makeContactInfoListFactoryOperation(),
 336                 "corbaContactInfoListFactory", null,
 337                 new TestContactInfoListFactory(),
 338                 MY_CLASS_NAME + "$TestContactInfoListFactory" ),
 339             ParserDataFactory.make( ORBConstants.PERSISTENT_SERVER_PORT_PROPERTY,
 340                 OperationFactory.integerAction(),
 341                 "persistentServerPort", new Integer( 0 ),
 342                 new Integer( 2743 ), "2743" ),
 343             ParserDataFactory.make( ORBConstants.PERSISTENT_SERVER_PORT_PROPERTY,
 344                 OperationFactory.setFlagAction(),
 345                 "persistentPortInitialized", Boolean.FALSE,
 346                 Boolean.TRUE, "2743" ),
 347             ParserDataFactory.make( ORBConstants.SERVER_ID_PROPERTY,
 348                 OperationFactory.integerAction(),
 349                 "persistentServerId", new Integer( 0 ),
 350                 new Integer( 294 ), "294" ),
 351             ParserDataFactory.make( ORBConstants.SERVER_ID_PROPERTY,
 352                 OperationFactory.setFlagAction(),
 353                 "persistentServerIdInitialized", Boolean.FALSE,
 354                 Boolean.TRUE, "294" ),
 355             ParserDataFactory.make( ORBConstants.SERVER_ID_PROPERTY,
 356                 OperationFactory.setFlagAction(),
 357                 "orbServerIdPropertySpecified", Boolean.FALSE,
 358                 Boolean.TRUE, "294" ),
 359             ParserDataFactory.make( ORBConstants.ACTIVATED_PROPERTY,
 360                 OperationFactory.booleanAction(),
 361                 "serverIsORBActivated", Boolean.FALSE,
 362                 Boolean.TRUE, "true" ),
 363             ParserDataFactory.make( ORBConstants.BAD_SERVER_ID_HANDLER_CLASS_PROPERTY,
 364                 OperationFactory.classAction(),
 365                 "badServerIdHandlerClass", null,
 366                 TestBadServerIdHandler.class, MY_CLASS_NAME + "$TestBadServerIdHandler" ),
 367             ParserDataFactory.make( ORBConstants.PI_ORB_INITIALIZER_CLASS_PREFIX,
 368                 makeROIOperation(),
 369                 "orbInitializers", new ORBInitializer[0],
 370                 TestORBInitializers, TestORBInitData, ORBInitializer.class ),
 371             ParserDataFactory.make( ORBConstants.ACCEPTOR_CLASS_PREFIX_PROPERTY,
 372                 makeAcceptorInstantiationOperation(),
 373                 "acceptors", new Acceptor[0],
 374                 TestAcceptors, TestAcceptorData, Acceptor.class ),
 375 
 376             //
 377             // Socket/Channel control
 378             //
 379 
 380             // Acceptor:
 381             // useNIOSelector == true
 382             //   useSelectThreadToWait = true
 383             //   useWorkerThreadForEvent = false
 384             // else
 385             //   useSelectThreadToWait = false
 386             //   useWorkerThreadForEvent = true
 387 
 388             // Connection:
 389             // useNIOSelector == true
 390             //   useSelectThreadToWait = true
 391             //   useWorkerThreadForEvent = true
 392             // else
 393             //   useSelectThreadToWait = false
 394             //   useWorkerThreadForEvent = true
 395 
 396             ParserDataFactory.make( ORBConstants.ACCEPTOR_SOCKET_TYPE_PROPERTY,
 397                 OperationFactory.stringAction(),
 398                 "acceptorSocketType", ORBConstants.SOCKETCHANNEL,
 399                 "foo", "foo" ),
 400 
 401             ParserDataFactory.make( ORBConstants.USE_NIO_SELECT_TO_WAIT_PROPERTY,
 402                 OperationFactory.booleanAction(),
 403                 "acceptorSocketUseSelectThreadToWait", Boolean.TRUE,
 404                 Boolean.TRUE, "true" ),
 405             ParserDataFactory.make( ORBConstants.ACCEPTOR_SOCKET_USE_WORKER_THREAD_FOR_EVENT_PROPERTY,
 406                 OperationFactory.booleanAction(),
 407                 "acceptorSocketUseWorkerThreadForEvent", Boolean.TRUE,
 408                 Boolean.TRUE, "true" ),
 409             ParserDataFactory.make( ORBConstants.CONNECTION_SOCKET_TYPE_PROPERTY,
 410                 OperationFactory.stringAction(),
 411                 "connectionSocketType", ORBConstants.SOCKETCHANNEL,
 412                 "foo", "foo" ),
 413             ParserDataFactory.make( ORBConstants.USE_NIO_SELECT_TO_WAIT_PROPERTY,
 414                 OperationFactory.booleanAction(),
 415                 "connectionSocketUseSelectThreadToWait", Boolean.TRUE,
 416                 Boolean.TRUE, "true" ),
 417             ParserDataFactory.make( ORBConstants.CONNECTION_SOCKET_USE_WORKER_THREAD_FOR_EVENT_PROPERTY,
 418                 OperationFactory.booleanAction(),
 419                 "connectionSocketUseWorkerThreadForEvent", Boolean.TRUE,
 420                 Boolean.TRUE, "true" ),
 421             ParserDataFactory.make( ORBConstants.DISABLE_DIRECT_BYTE_BUFFER_USE_PROPERTY,
 422                 OperationFactory.booleanAction(),
 423                 "disableDirectByteBufferUse", Boolean.FALSE,
 424                 Boolean.TRUE, "true" ),
 425             ParserDataFactory.make(ORBConstants.TRANSPORT_TCP_READ_TIMEOUTS_PROPERTY,
 426                 makeTTCPRTOperation(),
 427                 "readTimeouts",  TransportDefault.makeReadTimeoutsFactory().create(
 428                     ORBConstants.TRANSPORT_TCP_INITIAL_TIME_TO_WAIT,
 429                     ORBConstants.TRANSPORT_TCP_MAX_TIME_TO_WAIT,
 430                     ORBConstants.TRANSPORT_TCP_GIOP_HEADER_MAX_TIME_TO_WAIT,
 431                     ORBConstants.TRANSPORT_TCP_TIME_TO_WAIT_BACKOFF_FACTOR),
 432                 readTimeouts, "100:3000:300:20" ),
 433             ParserDataFactory.make(
 434                 ORBConstants.ENABLE_JAVA_SERIALIZATION_PROPERTY,
 435                 OperationFactory.booleanAction(),
 436                 "enableJavaSerialization", Boolean.FALSE,
 437                 Boolean.FALSE, "false"),
 438             ParserDataFactory.make(
 439                 ORBConstants.USE_REP_ID,
 440                 OperationFactory.booleanAction(),
 441                 "useRepId", Boolean.TRUE,
 442                 Boolean.TRUE, "true"),
 443             ParserDataFactory.make( ORBConstants.ORB_INIT_REF_PROPERTY,
 444                 OperationFactory.identityAction(),
 445                 "orbInitialReferences", new StringPair[0],
 446                 TestORBInitRefData, TestORBInitRefData, StringPair.class )
 447         } ;
 448 
 449         parserData = pd ;
 450     }
 451 
 452     public final class TestBadServerIdHandler implements BadServerIdHandler
 453     {
 454         public boolean equals( Object other )
 455         {
 456             return other instanceof TestBadServerIdHandler ;
 457         }
 458 
 459         public int hashCode() {
 460             return 1;
 461         }
 462 
 463         public void handle( ObjectKey objectKey )
 464         {
 465         }
 466     }
 467 
 468     private Operation makeTTCPRTOperation()
 469     {
 470         Operation[] fourIop = { OperationFactory.integerAction(),
 471                                 OperationFactory.integerAction(),
 472                                 OperationFactory.integerAction(),
 473                                 OperationFactory.integerAction() } ;
 474 
 475         Operation op2 = OperationFactory.sequenceAction( ":", fourIop ) ;
 476 
 477         Operation rtOp = new Operation() {
 478             public Object operate(Object value)
 479             {
 480                 Object[] values = (Object[])value ;
 481                 Integer initialTime = (Integer)(values[0]) ;
 482                 Integer maxGIOPHdrTime = (Integer)(values[1]) ;
 483                 Integer maxGIOPBodyTime = (Integer)(values[2]) ;
 484                 Integer backoffPercent = (Integer)(values[3]) ;
 485                 return TransportDefault.makeReadTimeoutsFactory().create(
 486                                                    initialTime.intValue(),
 487                                                    maxGIOPHdrTime.intValue(),
 488                                                    maxGIOPBodyTime.intValue(),
 489                                                    backoffPercent.intValue());
 490             }
 491         } ;
 492 
 493         Operation ttcprtOp = OperationFactory.compose(op2, rtOp);
 494         return ttcprtOp;
 495     }
 496 
 497     private Operation makeUSLOperation()
 498     {
 499         Operation[] siop = { OperationFactory.stringAction(),
 500             OperationFactory.integerAction() } ;
 501         Operation op2 = OperationFactory.sequenceAction( ":", siop ) ;
 502 
 503         Operation uslop = new Operation() {
 504             public Object operate( Object value )
 505             {
 506                 Object[] values = (Object[])value ;
 507                 String type = (String)(values[0]) ;
 508                 Integer port = (Integer)(values[1]) ;
 509                 return new USLPort( type, port.intValue() ) ;
 510             }
 511         } ;
 512 
 513         Operation op3 = OperationFactory.compose( op2, uslop ) ;
 514         Operation listenop = OperationFactory.listAction( ",", op3 ) ;
 515         return listenop ;
 516     }
 517 
 518     public static final class TestLegacyORBSocketFactory
 519         implements com.sun.corba.se.spi.legacy.connection.ORBSocketFactory
 520     {
 521         public boolean equals( Object other )
 522         {
 523             return other instanceof TestLegacyORBSocketFactory ;
 524         }
 525 
 526         public int hashCode() {
 527             return 1;
 528         }
 529 
 530         public ServerSocket createServerSocket( String type, int port )
 531         {
 532             return null ;
 533         }
 534 
 535         public SocketInfo getEndPointInfo( org.omg.CORBA.ORB orb,
 536             IOR ior, SocketInfo socketInfo )
 537         {
 538             return null ;
 539         }
 540 
 541         public Socket createSocket( SocketInfo socketInfo )
 542         {
 543             return null ;
 544         }
 545     }
 546 
 547     public static final class TestORBSocketFactory
 548         implements com.sun.corba.se.spi.transport.ORBSocketFactory
 549     {
 550         public boolean equals( Object other )
 551         {
 552             return other instanceof TestORBSocketFactory ;
 553         }
 554 
 555         public int hashCode() {
 556             return 1;
 557         }
 558 
 559         public void setORB(ORB orb)
 560         {
 561         }
 562 
 563         public ServerSocket createServerSocket( String type, InetSocketAddress a )
 564         {
 565             return null ;
 566         }
 567 
 568         public Socket createSocket( String type, InetSocketAddress a )
 569         {
 570             return null ;
 571         }
 572 
 573         public void setAcceptedSocketOptions(Acceptor acceptor,
 574                                              ServerSocket serverSocket,
 575                                              Socket socket)
 576         {
 577         }
 578     }
 579 
 580     public static final class TestIORToSocketInfo
 581         implements IORToSocketInfo
 582     {
 583         public boolean equals( Object other )
 584         {
 585             return other instanceof TestIORToSocketInfo;
 586         }
 587 
 588         public int hashCode() {
 589             return 1;
 590         }
 591 
 592         public List getSocketInfo(IOR ior)
 593         {
 594             return null;
 595         }
 596     }
 597 
 598     public static final class TestIIOPPrimaryToContactInfo
 599         implements IIOPPrimaryToContactInfo
 600     {
 601         public void reset(ContactInfo primary)
 602         {
 603         }
 604 
 605         public boolean hasNext(ContactInfo primary,
 606                                ContactInfo previous,
 607                                List contactInfos)
 608         {
 609             return true;
 610         }
 611 
 612         public ContactInfo next(ContactInfo primary,
 613                                 ContactInfo previous,
 614                                 List contactInfos)
 615         {
 616             return null;
 617         }
 618     }
 619 
 620     public static final class TestContactInfoListFactory
 621         implements CorbaContactInfoListFactory
 622     {
 623         public boolean equals( Object other )
 624         {
 625             return other instanceof TestContactInfoListFactory;
 626         }
 627 
 628         public int hashCode() {
 629             return 1;
 630         }
 631 
 632         public void setORB(ORB orb) { }
 633 
 634         public CorbaContactInfoList create( IOR ior ) { return null; }
 635     }
 636 
 637     private Operation makeMapOperation( final Map map )
 638     {
 639         return new Operation() {
 640             public Object operate( Object value )
 641             {
 642                 return map.get( value ) ;
 643             }
 644         } ;
 645     }
 646 
 647     private Operation makeBMGROperation()
 648     {
 649         Map map = new HashMap() ;
 650         map.put( "GROW", new Integer(0) ) ;
 651         map.put( "CLCT", new Integer(1) ) ;
 652         map.put( "STRM", new Integer(2) ) ;
 653         return makeMapOperation( map ) ;
 654     }
 655 
 656     private Operation makeLegacySocketFactoryOperation()
 657     {
 658         Operation sfop = new Operation() {
 659             public Object operate( Object value )
 660             {
 661                 String param = (String)value ;
 662 
 663                 try {
 664                     Class<?> legacySocketFactoryClass =
 665                         SharedSecrets.getJavaCorbaAccess().loadClass(param);
 666                     // For security reasons avoid creating an instance if
 667                     // this socket factory class is not one that would fail
 668                     // the class cast anyway.
 669                     if (com.sun.corba.se.spi.legacy.connection.ORBSocketFactory.class.isAssignableFrom(legacySocketFactoryClass)) {
 670                         return legacySocketFactoryClass.newInstance();
 671                     } else {
 672                         throw wrapper.illegalSocketFactoryType( legacySocketFactoryClass.toString() ) ;
 673                     }
 674                 } catch (Exception ex) {
 675                     // ClassNotFoundException, IllegalAccessException,
 676                     // InstantiationException, SecurityException or
 677                     // ClassCastException
 678                     throw wrapper.badCustomSocketFactory( ex, param ) ;
 679                 }
 680             }
 681         } ;
 682 
 683         return sfop ;
 684     }
 685 
 686     private Operation makeSocketFactoryOperation()
 687     {
 688         Operation sfop = new Operation() {
 689             public Object operate( Object value )
 690             {
 691                 String param = (String)value ;
 692 
 693                 try {
 694                     Class<?> socketFactoryClass =
 695                         SharedSecrets.getJavaCorbaAccess().loadClass(param);
 696                     // For security reasons avoid creating an instance if
 697                     // this socket factory class is not one that would fail
 698                     // the class cast anyway.
 699                     if (com.sun.corba.se.spi.transport.ORBSocketFactory.class.isAssignableFrom(socketFactoryClass)) {
 700                         return socketFactoryClass.newInstance();
 701                     } else {
 702                         throw wrapper.illegalSocketFactoryType( socketFactoryClass.toString() ) ;
 703                     }
 704                 } catch (Exception ex) {
 705                     // ClassNotFoundException, IllegalAccessException,
 706                     // InstantiationException, SecurityException or
 707                     // ClassCastException
 708                     throw wrapper.badCustomSocketFactory( ex, param ) ;
 709                 }
 710             }
 711         } ;
 712 
 713         return sfop ;
 714     }
 715 
 716     private Operation makeIORToSocketInfoOperation()
 717     {
 718         Operation op = new Operation() {
 719             public Object operate( Object value )
 720             {
 721                 String param = (String)value ;
 722 
 723                 try {
 724                     Class<?> iorToSocketInfoClass =
 725                         SharedSecrets.getJavaCorbaAccess().loadClass(param);
 726                     // For security reasons avoid creating an instance if
 727                     // this socket factory class is not one that would fail
 728                     // the class cast anyway.
 729                     if (IORToSocketInfo.class.isAssignableFrom(iorToSocketInfoClass)) {
 730                         return iorToSocketInfoClass.newInstance();
 731                     } else {
 732                         throw wrapper.illegalIorToSocketInfoType( iorToSocketInfoClass.toString() ) ;
 733                     }
 734                 } catch (Exception ex) {
 735                     // ClassNotFoundException, IllegalAccessException,
 736                     // InstantiationException, SecurityException or
 737                     // ClassCastException
 738                     throw wrapper.badCustomIorToSocketInfo( ex, param ) ;
 739                 }
 740             }
 741         } ;
 742 
 743         return op ;
 744     }
 745 
 746     private Operation makeIIOPPrimaryToContactInfoOperation()
 747     {
 748         Operation op = new Operation() {
 749             public Object operate( Object value )
 750             {
 751                 String param = (String)value ;
 752 
 753                 try {
 754                     Class<?> iiopPrimaryToContactInfoClass =
 755                         SharedSecrets.getJavaCorbaAccess().loadClass(param);
 756                     // For security reasons avoid creating an instance if
 757                     // this socket factory class is not one that would fail
 758                     // the class cast anyway.
 759                     if (IIOPPrimaryToContactInfo.class.isAssignableFrom(iiopPrimaryToContactInfoClass)) {
 760                         return iiopPrimaryToContactInfoClass.newInstance();
 761                     } else {
 762                         throw wrapper.illegalIiopPrimaryToContactInfoType( iiopPrimaryToContactInfoClass.toString() ) ;
 763                     }
 764                 } catch (Exception ex) {
 765                     // ClassNotFoundException, IllegalAccessException,
 766                     // InstantiationException, SecurityException or
 767                     // ClassCastException
 768                     throw wrapper.badCustomIiopPrimaryToContactInfo( ex, param ) ;
 769                 }
 770             }
 771         } ;
 772 
 773         return op ;
 774     }
 775 
 776     private Operation makeContactInfoListFactoryOperation()
 777     {
 778         Operation op = new Operation() {
 779             public Object operate( Object value )
 780             {
 781                 String param = (String)value ;
 782 
 783                 try {
 784                     Class<?> contactInfoListFactoryClass =
 785                         SharedSecrets.getJavaCorbaAccess().loadClass(param);
 786                     // For security reasons avoid creating an instance if
 787                     // this socket factory class is not one that would fail
 788                     // the class cast anyway.
 789                     if (CorbaContactInfoListFactory.class.isAssignableFrom(
 790                         contactInfoListFactoryClass)) {
 791                         return contactInfoListFactoryClass.newInstance();
 792                     } else {
 793                         throw wrapper.illegalContactInfoListFactoryType(
 794                             contactInfoListFactoryClass.toString() ) ;
 795                     }
 796                 } catch (Exception ex) {
 797                     // ClassNotFoundException, IllegalAccessException,
 798                     // InstantiationException, SecurityException or
 799                     // ClassCastException
 800                     throw wrapper.badContactInfoListFactory( ex, param ) ;
 801                 }
 802             }
 803         } ;
 804 
 805         return op ;
 806     }
 807 
 808     private Operation makeCSOperation()
 809     {
 810         Operation csop = new Operation() {
 811             public Object operate( Object value )
 812             {
 813                 String val = (String)value ;
 814                 return CodeSetComponentInfo.createFromString( val ) ;
 815             }
 816         } ;
 817 
 818         return csop ;
 819     }
 820 
 821     private Operation makeADOperation()
 822     {
 823         Operation admap = new Operation() {
 824             private Integer[] map = {
 825                 new Integer( KeyAddr.value ),
 826                 new Integer( ProfileAddr.value ),
 827                 new Integer( ReferenceAddr.value ),
 828                 new Integer( KeyAddr.value ) } ;
 829 
 830             public Object operate( Object value )
 831             {
 832                 int val = ((Integer)value).intValue() ;
 833                 return map[val] ;
 834             }
 835         } ;
 836 
 837         Operation rangeop = OperationFactory.integerRangeAction( 0, 3 ) ;
 838         Operation op1 = OperationFactory.compose( rangeop, admap ) ;
 839         Operation result = OperationFactory.compose( op1, OperationFactory.convertIntegerToShort() ) ;
 840         return result ;
 841     }
 842 
 843     private Operation makeFSOperation() {
 844         Operation fschecker = new Operation() {
 845             public Object operate( Object value )
 846             {
 847                 int giopFragmentSize = ((Integer)value).intValue() ;
 848                 if (giopFragmentSize < ORBConstants.GIOP_FRAGMENT_MINIMUM_SIZE){
 849                     throw wrapper.fragmentSizeMinimum( new Integer( giopFragmentSize ),
 850                         new Integer( ORBConstants.GIOP_FRAGMENT_MINIMUM_SIZE ) ) ;
 851                 }
 852 
 853                 if (giopFragmentSize % ORBConstants.GIOP_FRAGMENT_DIVISOR != 0)
 854                     throw wrapper.fragmentSizeDiv( new Integer( giopFragmentSize ),
 855                             new Integer( ORBConstants.GIOP_FRAGMENT_DIVISOR ) ) ;
 856 
 857                 return value ;
 858             }
 859         } ;
 860 
 861         Operation result = OperationFactory.compose( OperationFactory.integerAction(),
 862             fschecker ) ;
 863         return result ;
 864     }
 865 
 866     private Operation makeGVOperation() {
 867         Operation gvHelper = OperationFactory.listAction( ".",
 868             OperationFactory.integerAction() ) ;
 869         Operation gvMain = new Operation() {
 870             public Object operate( Object value )
 871             {
 872                 Object[] nums = (Object[])value ;
 873                 int major = ((Integer)(nums[0])).intValue() ;
 874                 int minor = ((Integer)(nums[1])).intValue() ;
 875 
 876                 return new GIOPVersion( major, minor ) ;
 877             }
 878         } ;
 879 
 880         Operation result = OperationFactory.compose( gvHelper, gvMain );
 881         return result ;
 882     }
 883 
 884     public static final class TestORBInitializer1 extends org.omg.CORBA.LocalObject
 885         implements ORBInitializer
 886     {
 887         public boolean equals( Object other )
 888         {
 889             return other instanceof TestORBInitializer1 ;
 890         }
 891 
 892         public int hashCode() {
 893             return 1;
 894         }
 895 
 896         public void pre_init( ORBInitInfo info )
 897         {
 898         }
 899 
 900         public void post_init( ORBInitInfo info )
 901         {
 902         }
 903     }
 904 
 905     public static final class TestORBInitializer2 extends org.omg.CORBA.LocalObject
 906         implements ORBInitializer
 907     {
 908         public boolean equals( Object other )
 909         {
 910             return other instanceof TestORBInitializer2 ;
 911         }
 912 
 913         public int hashCode() {
 914             return 1;
 915         }
 916 
 917         public void pre_init( ORBInitInfo info )
 918         {
 919         }
 920 
 921         public void post_init( ORBInitInfo info )
 922         {
 923         }
 924     }
 925 
 926     private Operation makeROIOperation() {
 927         Operation clsop = OperationFactory.classAction() ;
 928         Operation indexOp = OperationFactory.suffixAction() ;
 929         Operation op1 = OperationFactory.compose( indexOp, clsop ) ;
 930         Operation mop = OperationFactory.maskErrorAction( op1 ) ;
 931 
 932         Operation mkinst = new Operation() {
 933             public Object operate( Object value )
 934             {
 935                 final Class initClass = (Class)value ;
 936                 if (initClass == null)
 937                     return null ;
 938 
 939                 // For security reasons avoid creating an instance
 940                 // if this class is one that would fail the class cast
 941                 // to ORBInitializer anyway.
 942                 if( org.omg.PortableInterceptor.ORBInitializer.class.isAssignableFrom(
 943                     initClass ) ) {
 944                     // Now that we have a class object, instantiate one and
 945                     // remember it:
 946                     ORBInitializer initializer = null ;
 947 
 948                     try {
 949                         initializer = (ORBInitializer)AccessController.doPrivileged(
 950                             new PrivilegedExceptionAction() {
 951                                 public Object run()
 952                                     throws InstantiationException, IllegalAccessException
 953                                 {
 954                                     return initClass.newInstance() ;
 955                                 }
 956                             }
 957                         ) ;
 958                     } catch (PrivilegedActionException exc) {
 959                         // Unwrap the exception, as we don't care exc here
 960                         throw wrapper.orbInitializerFailure( exc.getException(),
 961                             initClass.getName() ) ;
 962                     } catch (Exception exc) {
 963                         throw wrapper.orbInitializerFailure( exc, initClass.getName() ) ;
 964                     }
 965 
 966                     return initializer ;
 967                 } else {
 968                     throw wrapper.orbInitializerType( initClass.getName() ) ;
 969                 }
 970             }
 971         } ;
 972 
 973         Operation result = OperationFactory.compose( mop, mkinst ) ;
 974 
 975         return result ;
 976     }
 977 
 978     public static final class TestAcceptor1
 979         implements Acceptor
 980     {
 981         public boolean equals( Object other )
 982         {
 983             return other instanceof TestAcceptor1 ;
 984         }
 985 
 986         public int hashCode() { return 1; }
 987         public boolean initialize() { return true; }
 988         public boolean initialized() { return true; }
 989         public String getConnectionCacheType() { return "FOO"; }
 990         public void setConnectionCache(InboundConnectionCache connectionCache){}
 991         public InboundConnectionCache getConnectionCache() { return null; }
 992         public boolean shouldRegisterAcceptEvent() { return true; }
 993         public void setUseSelectThreadForConnections(boolean x) { }
 994         public boolean shouldUseSelectThreadForConnections() { return true; }
 995         public void setUseWorkerThreadForConnections(boolean x) { }
 996         public boolean shouldUseWorkerThreadForConnections() { return true; }
 997         public void accept() { }
 998         public void close() { }
 999         public EventHandler getEventHandler() { return null; }
1000         public MessageMediator createMessageMediator(
1001             Broker xbroker, Connection xconnection) { return null; }
1002         public MessageMediator finishCreatingMessageMediator(
1003             Broker xbroker, Connection xconnection,
1004             MessageMediator messageMediator) { return null; }
1005         public InputObject createInputObject(
1006             Broker broker, MessageMediator messageMediator) { return null; }
1007         public OutputObject createOutputObject(
1008             Broker broker, MessageMediator messageMediator) { return null; }
1009     }
1010 
1011     public static final class TestAcceptor2
1012         implements Acceptor
1013     {
1014         public boolean equals( Object other )
1015         {
1016             return other instanceof TestAcceptor2 ;
1017         }
1018         public int hashCode() { return 1; }
1019         public boolean initialize() { return true; }
1020         public boolean initialized() { return true; }
1021         public String getConnectionCacheType() { return "FOO"; }
1022         public void setConnectionCache(InboundConnectionCache connectionCache){}
1023         public InboundConnectionCache getConnectionCache() { return null; }
1024         public boolean shouldRegisterAcceptEvent() { return true; }
1025         public void setUseSelectThreadForConnections(boolean x) { }
1026         public boolean shouldUseSelectThreadForConnections() { return true; }
1027         public void setUseWorkerThreadForConnections(boolean x) { }
1028         public boolean shouldUseWorkerThreadForConnections() { return true; }
1029         public void accept() { }
1030         public void close() { }
1031         public EventHandler getEventHandler() { return null; }
1032         public MessageMediator createMessageMediator(
1033             Broker xbroker, Connection xconnection) { return null; }
1034         public MessageMediator finishCreatingMessageMediator(
1035             Broker xbroker, Connection xconnection,
1036             MessageMediator messageMediator) { return null; }
1037         public InputObject createInputObject(
1038             Broker broker, MessageMediator messageMediator) { return null; }
1039         public OutputObject createOutputObject(
1040             Broker broker, MessageMediator messageMediator) { return null; }
1041     }
1042 
1043     // REVISIT - this is a cut and paste modification of makeROIOperation.
1044     private Operation makeAcceptorInstantiationOperation() {
1045         Operation clsop = OperationFactory.classAction() ;
1046         Operation indexOp = OperationFactory.suffixAction() ;
1047         Operation op1 = OperationFactory.compose( indexOp, clsop ) ;
1048         Operation mop = OperationFactory.maskErrorAction( op1 ) ;
1049 
1050         Operation mkinst = new Operation() {
1051             public Object operate( Object value )
1052             {
1053                 final Class initClass = (Class)value ;
1054                 if (initClass == null)
1055                     return null ;
1056 
1057                 // For security reasons avoid creating an instance
1058                 // if this class is one that would fail the class cast
1059                 // to ORBInitializer anyway.
1060                 if( Acceptor.class.isAssignableFrom( initClass ) ) {
1061                     // Now that we have a class object, instantiate one and
1062                     // remember it:
1063                     Acceptor acceptor = null ;
1064 
1065                     try {
1066                         acceptor = (Acceptor)AccessController.doPrivileged(
1067                             new PrivilegedExceptionAction() {
1068                                 public Object run()
1069                                     throws InstantiationException, IllegalAccessException
1070                                 {
1071                                     return initClass.newInstance() ;
1072                                 }
1073                             }
1074                         ) ;
1075                     } catch (PrivilegedActionException exc) {
1076                         // Unwrap the exception, as we don't care exc here
1077                         throw wrapper.acceptorInstantiationFailure( exc.getException(),
1078                             initClass.getName() ) ;
1079                     } catch (Exception exc) {
1080                         throw wrapper.acceptorInstantiationFailure( exc, initClass.getName() ) ;
1081                     }
1082 
1083                     return acceptor ;
1084                 } else {
1085                     throw wrapper.acceptorInstantiationTypeFailure( initClass.getName() ) ;
1086                 }
1087             }
1088         } ;
1089 
1090         Operation result = OperationFactory.compose( mop, mkinst ) ;
1091 
1092         return result ;
1093     }
1094 
1095     private Operation makeInitRefOperation() {
1096         return new Operation() {
1097             public Object operate( Object value )
1098             {
1099                 // Object is String[] of length 2.
1100                 String[] values = (String[])value ;
1101                 if (values.length != 2)
1102                     throw wrapper.orbInitialreferenceSyntax() ;
1103 
1104                 return values[0] + "=" + values[1] ;
1105             }
1106         } ;
1107     }
1108 }
1109 
1110 // End of file.