/*
 * Copyright (c) 2002, 2013, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */

package com.sun.corba.se.impl.orb ;

import java.net.URL ;
import java.net.InetSocketAddress;
import java.net.Socket ;
import java.net.ServerSocket ;

import java.io.IOException ;

import java.util.HashMap ;
import java.util.List;
import java.util.Map ;

import java.security.AccessController ;
import java.security.PrivilegedExceptionAction ;
import java.security.PrivilegedActionException ;

import org.omg.PortableInterceptor.ORBInitializer ;
import org.omg.PortableInterceptor.ORBInitInfo ;

import com.sun.corba.se.pept.broker.Broker;
import com.sun.corba.se.pept.encoding.InputObject;
import com.sun.corba.se.pept.encoding.OutputObject;
import com.sun.corba.se.pept.protocol.MessageMediator;
import com.sun.corba.se.pept.transport.Acceptor;
import com.sun.corba.se.pept.transport.Connection;
import com.sun.corba.se.pept.transport.ContactInfo;
import com.sun.corba.se.pept.transport.ContactInfoList;
import com.sun.corba.se.pept.transport.EventHandler;
import com.sun.corba.se.pept.transport.InboundConnectionCache;

import com.sun.corba.se.spi.ior.IOR ;
import com.sun.corba.se.spi.ior.ObjectKey ;
import com.sun.corba.se.spi.ior.iiop.GIOPVersion ;
import com.sun.corba.se.spi.logging.CORBALogDomains ;
import com.sun.corba.se.spi.orb.ORB;
import com.sun.corba.se.spi.orb.Operation ;
import com.sun.corba.se.spi.orb.OperationFactory ;
import com.sun.corba.se.spi.orb.ParserData ;
import com.sun.corba.se.spi.orb.ParserDataFactory ;
import com.sun.corba.se.spi.orb.StringPair ;
import com.sun.corba.se.spi.transport.CorbaContactInfoList;
import com.sun.corba.se.spi.transport.CorbaContactInfoListFactory;
import com.sun.corba.se.spi.transport.CorbaTransportManager;
import com.sun.corba.se.spi.transport.IORToSocketInfo;
import com.sun.corba.se.spi.transport.ReadTimeouts;
import com.sun.corba.se.spi.transport.SocketInfo;
import com.sun.corba.se.spi.transport.IIOPPrimaryToContactInfo;
import com.sun.corba.se.spi.transport.TransportDefault;

import com.sun.corba.se.impl.encoding.CodeSetComponentInfo ;
import com.sun.corba.se.impl.encoding.OSFCodeSetRegistry ;
import com.sun.corba.se.impl.legacy.connection.USLPort ;
import com.sun.corba.se.impl.logging.ORBUtilSystemException ;
import com.sun.corba.se.impl.oa.poa.BadServerIdHandler ;
import com.sun.corba.se.impl.orbutil.ORBConstants ;
import com.sun.corba.se.impl.protocol.giopmsgheaders.KeyAddr ;
import com.sun.corba.se.impl.protocol.giopmsgheaders.ProfileAddr ;
import com.sun.corba.se.impl.protocol.giopmsgheaders.ReferenceAddr ;
import com.sun.corba.se.impl.transport.DefaultIORToSocketInfoImpl;
import com.sun.corba.se.impl.transport.DefaultSocketFactoryImpl;

import sun.corba.SharedSecrets;

/** Initialize the parser data for the standard ORB parser.  This is used both
 * to implement ORBDataParserImpl and to provide the basic testing framework
 * for ORBDataParserImpl.
 */
public class ParserTable {
    private static String MY_CLASS_NAME = ParserTable.class.getName() ;

    private static ParserTable myInstance = new ParserTable() ;

    private ORBUtilSystemException wrapper ;

    public static ParserTable get()
    {
        return myInstance ;
    }

    private ParserData[] parserData ;

    public ParserData[] getParserData()
    {
        ParserData[] parserArray = new ParserData[parserData.length];
        System.arraycopy(parserData, 0, parserArray, 0, parserData.length);
        return parserArray;
    }

    private ParserTable() {
        wrapper = ORBUtilSystemException.get( CORBALogDomains.ORB_LIFECYCLE ) ;

        String codeSetTestString =
            OSFCodeSetRegistry.ISO_8859_1_VALUE + "," +
            OSFCodeSetRegistry.UTF_16_VALUE + "," +
            OSFCodeSetRegistry.ISO_646_VALUE ;

        String[] debugTestData = { "subcontract", "poa", "transport" } ;

        USLPort[] USLPorts = { new USLPort( "FOO", 2701 ), new USLPort( "BAR", 3333 ) } ;

        ReadTimeouts readTimeouts =
               TransportDefault.makeReadTimeoutsFactory().create(
                    ORBConstants.TRANSPORT_TCP_INITIAL_TIME_TO_WAIT,
                    ORBConstants.TRANSPORT_TCP_MAX_TIME_TO_WAIT,
                    ORBConstants.TRANSPORT_TCP_GIOP_HEADER_MAX_TIME_TO_WAIT,
                    ORBConstants.TRANSPORT_TCP_TIME_TO_WAIT_BACKOFF_FACTOR);

        ORBInitializer[] TestORBInitializers =
            { null,
              new TestORBInitializer1(),
              new TestORBInitializer2() }  ;
        StringPair[] TestORBInitData = {
            new StringPair( "foo.bar.blech.NonExistent", "dummy" ),
            new StringPair( MY_CLASS_NAME + "$TestORBInitializer1", "dummy" ),
            new StringPair( MY_CLASS_NAME + "$TestORBInitializer2", "dummy" ) } ;

        Acceptor[] TestAcceptors =
            { new TestAcceptor2(),
              new TestAcceptor1(),
              null }  ;
        // REVISIT: The test data gets put into a Properties object where
        // order is not guaranteed.  Thus the above array is in reverse.
        StringPair[] TestAcceptorData = {
            new StringPair( "foo.bar.blech.NonExistent", "dummy" ),
            new StringPair( MY_CLASS_NAME + "$TestAcceptor1", "dummy" ),
            new StringPair( MY_CLASS_NAME + "$TestAcceptor2", "dummy" ) } ;

        StringPair[] TestORBInitRefData =
            { new StringPair( "Foo", "ior:930492049394" ),
              new StringPair( "Bar", "ior:3453465785633576" ) } ;

        URL testServicesURL = null ;
        String testServicesString = "corbaloc::camelot/NameService" ;

        try {
            testServicesURL = new URL( testServicesString )  ;
        } catch (Exception exc) {
        }

        // propertyName,
        // operation,
        // fieldName, defaultValue,
        // testValue, testData (string or Pair[])
        ParserData[] pd = {
            ParserDataFactory.make( ORBConstants.DEBUG_PROPERTY,
                OperationFactory.listAction( ",", OperationFactory.stringAction()),
                "debugFlags", new String[0],
                debugTestData, "subcontract,poa,transport" ),
            ParserDataFactory.make( ORBConstants.INITIAL_HOST_PROPERTY,
                OperationFactory.stringAction(),
                "ORBInitialHost", null,
                "Foo", "Foo" ),
            ParserDataFactory.make( ORBConstants.INITIAL_PORT_PROPERTY,
                OperationFactory.integerAction(),
                "ORBInitialPort", null,
                new Integer( 27314 ), "27314" ),
            // Where did this come from?
            //ParserDataFactory.make( ORBConstants.INITIAL_PORT_PROPERTY,
                //OperationFactory.booleanAction(),
                //"ORBInitialPortInitialized", Boolean.FALSE,
                //Boolean.TRUE, "27314" ),
            ParserDataFactory.make( ORBConstants.SERVER_HOST_PROPERTY,
                OperationFactory.stringAction(),
                "ORBServerHost", "",
                "camelot", "camelot" ),
            ParserDataFactory.make( ORBConstants.SERVER_PORT_PROPERTY,
                OperationFactory.integerAction(),
                "ORBServerPort", new Integer( 0 ),
                new Integer( 38143 ), "38143" ),
            ParserDataFactory.make( ORBConstants.ORB_ID_PROPERTY,
                OperationFactory.stringAction(),
                "orbId", "",
                "foo", "foo" ),
            ParserDataFactory.make( ORBConstants.OLD_ORB_ID_PROPERTY,
                OperationFactory.stringAction(),
                "orbId", "",
                "foo", "foo" ),
            ParserDataFactory.make( ORBConstants.ORB_SERVER_ID_PROPERTY,
                OperationFactory.integerAction(),
                "persistentServerId", new Integer(-1),
                new Integer( 1234), "1234" ),
            ParserDataFactory.make(
                ORBConstants.ORB_SERVER_ID_PROPERTY,
                OperationFactory.setFlagAction(),
                "persistentServerIdInitialized", Boolean.FALSE,
                Boolean.TRUE, "1234" ),
            ParserDataFactory.make(
                ORBConstants.ORB_SERVER_ID_PROPERTY,
                OperationFactory.setFlagAction(),
                "orbServerIdPropertySpecified", Boolean.FALSE,
                Boolean.TRUE, "1234" ),
            // REVISIT after switch
            // ParserDataFactory.make( ORBConstants.INITIAL_SERVICES_PROPERTY,
                // OperationFactory.URLAction(),
                // "servicesURL", null,
                // testServicesURL, testServicesString ),
            // ParserDataFactory.make( ORBConstants.DEFAULT_INIT_REF_PROPERTY,
                // OperationFactory.stringAction(),
                // "defaultInitRef", null,
                // "Fooref", "Fooref" ),
            ParserDataFactory.make( ORBConstants.HIGH_WATER_MARK_PROPERTY,
                OperationFactory.integerAction(),
                "highWaterMark", new Integer( 240 ),
                new Integer( 3745 ), "3745" ),
            ParserDataFactory.make( ORBConstants.LOW_WATER_MARK_PROPERTY,
                OperationFactory.integerAction(),
                "lowWaterMark", new Integer( 100 ),
                new Integer( 12 ), "12" ),
            ParserDataFactory.make( ORBConstants.NUMBER_TO_RECLAIM_PROPERTY,
                OperationFactory.integerAction(),
                "numberToReclaim", new Integer( 5 ),
                new Integer( 231 ), "231" ),
            ParserDataFactory.make( ORBConstants.GIOP_VERSION,
                makeGVOperation(),
                "giopVersion", GIOPVersion.DEFAULT_VERSION,
                new GIOPVersion( 2, 3 ), "2.3" ),
            ParserDataFactory.make( ORBConstants.GIOP_FRAGMENT_SIZE,
                makeFSOperation(), "giopFragmentSize",
                new Integer( ORBConstants.GIOP_DEFAULT_FRAGMENT_SIZE ),
                new Integer( 65536 ), "65536" ),
            ParserDataFactory.make( ORBConstants.GIOP_BUFFER_SIZE,
                OperationFactory.integerAction(),
                "giopBufferSize", new Integer( ORBConstants.GIOP_DEFAULT_BUFFER_SIZE ),
                new Integer( 234000 ), "234000" ),
            ParserDataFactory.make( ORBConstants.GIOP_11_BUFFMGR,
                makeBMGROperation(),
                "giop11BuffMgr", new Integer( ORBConstants.DEFAULT_GIOP_11_BUFFMGR ),
                new Integer( 1 ), "CLCT" ),
            ParserDataFactory.make( ORBConstants.GIOP_12_BUFFMGR,
                makeBMGROperation(),
                "giop12BuffMgr", new Integer( ORBConstants.DEFAULT_GIOP_12_BUFFMGR ),
                new Integer( 0 ), "GROW" ),

            // Note that the same property is used to set two different
            // fields here.  This requires that both entries use the same test
            // data, or the test will fail.
            ParserDataFactory.make( ORBConstants.GIOP_TARGET_ADDRESSING,
                OperationFactory.compose( OperationFactory.integerRangeAction( 0, 3 ),
                    OperationFactory.convertIntegerToShort() ),
                "giopTargetAddressPreference",
                new Short( ORBConstants.ADDR_DISP_HANDLE_ALL ),
                new Short( (short)2 ), "2" ),
            ParserDataFactory.make( ORBConstants.GIOP_TARGET_ADDRESSING,
                makeADOperation(),
                "giopAddressDisposition", new Short( KeyAddr.value ),
                new Short( (short)2 ), "2" ),
            ParserDataFactory.make( ORBConstants.ALWAYS_SEND_CODESET_CTX_PROPERTY,
                OperationFactory.booleanAction(),
                "alwaysSendCodeSetCtx", Boolean.TRUE,
                Boolean.FALSE, "false"),
            ParserDataFactory.make( ORBConstants.USE_BOMS,
                OperationFactory.booleanAction(),
                "useByteOrderMarkers",
                    Boolean.valueOf( ORBConstants.DEFAULT_USE_BYTE_ORDER_MARKERS ),
                Boolean.FALSE, "false" ),
            ParserDataFactory.make( ORBConstants.USE_BOMS_IN_ENCAPS,
                OperationFactory.booleanAction(),
                "useByteOrderMarkersInEncaps",
                    Boolean.valueOf( ORBConstants.DEFAULT_USE_BYTE_ORDER_MARKERS_IN_ENCAPS ),
                Boolean.FALSE, "false" ),
            ParserDataFactory.make( ORBConstants.CHAR_CODESETS,
                makeCSOperation(),
                "charData", CodeSetComponentInfo.JAVASOFT_DEFAULT_CODESETS.getCharComponent(),
                CodeSetComponentInfo.createFromString( codeSetTestString ), codeSetTestString ),
            ParserDataFactory.make( ORBConstants.WCHAR_CODESETS,
                makeCSOperation(),
                "wcharData", CodeSetComponentInfo.JAVASOFT_DEFAULT_CODESETS.getWCharComponent(),
                CodeSetComponentInfo.createFromString( codeSetTestString ), codeSetTestString ),
            ParserDataFactory.make( ORBConstants.ALLOW_LOCAL_OPTIMIZATION,
                OperationFactory.booleanAction(),
                "allowLocalOptimization", Boolean.FALSE,
                Boolean.TRUE, "true" ),
            ParserDataFactory.make( ORBConstants.LEGACY_SOCKET_FACTORY_CLASS_PROPERTY,
                makeLegacySocketFactoryOperation(),
                // No default - must be set by user if they are using
                // legacy socket factory.
                "legacySocketFactory", null,
                new TestLegacyORBSocketFactory(),
                MY_CLASS_NAME + "$TestLegacyORBSocketFactory" ),
            ParserDataFactory.make( ORBConstants.SOCKET_FACTORY_CLASS_PROPERTY,
                makeSocketFactoryOperation(),
                "socketFactory", new DefaultSocketFactoryImpl(),
                new TestORBSocketFactory(),
                MY_CLASS_NAME + "$TestORBSocketFactory" ),
            ParserDataFactory.make( ORBConstants.LISTEN_SOCKET_PROPERTY,
                makeUSLOperation() ,
                "userSpecifiedListenPorts", new USLPort[0],
                USLPorts, "FOO:2701,BAR:3333" ),
            ParserDataFactory.make( ORBConstants.IOR_TO_SOCKET_INFO_CLASS_PROPERTY,
                makeIORToSocketInfoOperation(),
                "iorToSocketInfo", new DefaultIORToSocketInfoImpl(),
                new TestIORToSocketInfo(),
                MY_CLASS_NAME + "$TestIORToSocketInfo" ),
            ParserDataFactory.make( ORBConstants.IIOP_PRIMARY_TO_CONTACT_INFO_CLASS_PROPERTY,
                makeIIOPPrimaryToContactInfoOperation(),
                "iiopPrimaryToContactInfo", null,
                new TestIIOPPrimaryToContactInfo(),
                MY_CLASS_NAME + "$TestIIOPPrimaryToContactInfo" ),
            ParserDataFactory.make( ORBConstants.CONTACT_INFO_LIST_FACTORY_CLASS_PROPERTY,
                makeContactInfoListFactoryOperation(),
                "corbaContactInfoListFactory", null,
                new TestContactInfoListFactory(),
                MY_CLASS_NAME + "$TestContactInfoListFactory" ),
            ParserDataFactory.make( ORBConstants.PERSISTENT_SERVER_PORT_PROPERTY,
                OperationFactory.integerAction(),
                "persistentServerPort", new Integer( 0 ),
                new Integer( 2743 ), "2743" ),
            ParserDataFactory.make( ORBConstants.PERSISTENT_SERVER_PORT_PROPERTY,
                OperationFactory.setFlagAction(),
                "persistentPortInitialized", Boolean.FALSE,
                Boolean.TRUE, "2743" ),
            ParserDataFactory.make( ORBConstants.SERVER_ID_PROPERTY,
                OperationFactory.integerAction(),
                "persistentServerId", new Integer( 0 ),
                new Integer( 294 ), "294" ),
            ParserDataFactory.make( ORBConstants.SERVER_ID_PROPERTY,
                OperationFactory.setFlagAction(),
                "persistentServerIdInitialized", Boolean.FALSE,
                Boolean.TRUE, "294" ),
            ParserDataFactory.make( ORBConstants.SERVER_ID_PROPERTY,
                OperationFactory.setFlagAction(),
                "orbServerIdPropertySpecified", Boolean.FALSE,
                Boolean.TRUE, "294" ),
            ParserDataFactory.make( ORBConstants.ACTIVATED_PROPERTY,
                OperationFactory.booleanAction(),
                "serverIsORBActivated", Boolean.FALSE,
                Boolean.TRUE, "true" ),
            ParserDataFactory.make( ORBConstants.BAD_SERVER_ID_HANDLER_CLASS_PROPERTY,
                OperationFactory.classAction(),
                "badServerIdHandlerClass", null,
                TestBadServerIdHandler.class, MY_CLASS_NAME + "$TestBadServerIdHandler" ),
            ParserDataFactory.make( ORBConstants.PI_ORB_INITIALIZER_CLASS_PREFIX,
                makeROIOperation(),
                "orbInitializers", new ORBInitializer[0],
                TestORBInitializers, TestORBInitData, ORBInitializer.class ),
            ParserDataFactory.make( ORBConstants.ACCEPTOR_CLASS_PREFIX_PROPERTY,
                makeAcceptorInstantiationOperation(),
                "acceptors", new Acceptor[0],
                TestAcceptors, TestAcceptorData, Acceptor.class ),

            //
            // Socket/Channel control
            //

            // Acceptor:
            // useNIOSelector == true
            //   useSelectThreadToWait = true
            //   useWorkerThreadForEvent = false
            // else
            //   useSelectThreadToWait = false
            //   useWorkerThreadForEvent = true

            // Connection:
            // useNIOSelector == true
            //   useSelectThreadToWait = true
            //   useWorkerThreadForEvent = true
            // else
            //   useSelectThreadToWait = false
            //   useWorkerThreadForEvent = true

            ParserDataFactory.make( ORBConstants.ACCEPTOR_SOCKET_TYPE_PROPERTY,
                OperationFactory.stringAction(),
                "acceptorSocketType", ORBConstants.SOCKETCHANNEL,
                "foo", "foo" ),

            ParserDataFactory.make( ORBConstants.USE_NIO_SELECT_TO_WAIT_PROPERTY,
                OperationFactory.booleanAction(),
                "acceptorSocketUseSelectThreadToWait", Boolean.TRUE,
                Boolean.TRUE, "true" ),
            ParserDataFactory.make( ORBConstants.ACCEPTOR_SOCKET_USE_WORKER_THREAD_FOR_EVENT_PROPERTY,
                OperationFactory.booleanAction(),
                "acceptorSocketUseWorkerThreadForEvent", Boolean.TRUE,
                Boolean.TRUE, "true" ),
            ParserDataFactory.make( ORBConstants.CONNECTION_SOCKET_TYPE_PROPERTY,
                OperationFactory.stringAction(),
                "connectionSocketType", ORBConstants.SOCKETCHANNEL,
                "foo", "foo" ),
            ParserDataFactory.make( ORBConstants.USE_NIO_SELECT_TO_WAIT_PROPERTY,
                OperationFactory.booleanAction(),
                "connectionSocketUseSelectThreadToWait", Boolean.TRUE,
                Boolean.TRUE, "true" ),
            ParserDataFactory.make( ORBConstants.CONNECTION_SOCKET_USE_WORKER_THREAD_FOR_EVENT_PROPERTY,
                OperationFactory.booleanAction(),
                "connectionSocketUseWorkerThreadForEvent", Boolean.TRUE,
                Boolean.TRUE, "true" ),
            ParserDataFactory.make( ORBConstants.DISABLE_DIRECT_BYTE_BUFFER_USE_PROPERTY,
                OperationFactory.booleanAction(),
                "disableDirectByteBufferUse", Boolean.FALSE,
                Boolean.TRUE, "true" ),
            ParserDataFactory.make(ORBConstants.TRANSPORT_TCP_READ_TIMEOUTS_PROPERTY,
                makeTTCPRTOperation(),
                "readTimeouts",  TransportDefault.makeReadTimeoutsFactory().create(
                    ORBConstants.TRANSPORT_TCP_INITIAL_TIME_TO_WAIT,
                    ORBConstants.TRANSPORT_TCP_MAX_TIME_TO_WAIT,
                    ORBConstants.TRANSPORT_TCP_GIOP_HEADER_MAX_TIME_TO_WAIT,
                    ORBConstants.TRANSPORT_TCP_TIME_TO_WAIT_BACKOFF_FACTOR),
                readTimeouts, "100:3000:300:20" ),
            ParserDataFactory.make(
                ORBConstants.ENABLE_JAVA_SERIALIZATION_PROPERTY,
                OperationFactory.booleanAction(),
                "enableJavaSerialization", Boolean.FALSE,
                Boolean.FALSE, "false"),
            ParserDataFactory.make(
                ORBConstants.USE_REP_ID,
                OperationFactory.booleanAction(),
                "useRepId", Boolean.TRUE,
                Boolean.TRUE, "true"),
            ParserDataFactory.make( ORBConstants.ORB_INIT_REF_PROPERTY,
                OperationFactory.identityAction(),
                "orbInitialReferences", new StringPair[0],
                TestORBInitRefData, TestORBInitRefData, StringPair.class )
        } ;

        parserData = pd ;
    }

    public final class TestBadServerIdHandler implements BadServerIdHandler
    {
        public boolean equals( Object other )
        {
            return other instanceof TestBadServerIdHandler ;
        }

        public int hashCode() {
            return 1;
        }

        public void handle( ObjectKey objectKey )
        {
        }
    }

    private Operation makeTTCPRTOperation()
    {
        Operation[] fourIop = { OperationFactory.integerAction(),
                                OperationFactory.integerAction(),
                                OperationFactory.integerAction(),
                                OperationFactory.integerAction() } ;

        Operation op2 = OperationFactory.sequenceAction( ":", fourIop ) ;

        Operation rtOp = new Operation() {
            public Object operate(Object value)
            {
                Object[] values = (Object[])value ;
                Integer initialTime = (Integer)(values[0]) ;
                Integer maxGIOPHdrTime = (Integer)(values[1]) ;
                Integer maxGIOPBodyTime = (Integer)(values[2]) ;
                Integer backoffPercent = (Integer)(values[3]) ;
                return TransportDefault.makeReadTimeoutsFactory().create(
                                                   initialTime.intValue(),
                                                   maxGIOPHdrTime.intValue(),
                                                   maxGIOPBodyTime.intValue(),
                                                   backoffPercent.intValue());
            }
        } ;

        Operation ttcprtOp = OperationFactory.compose(op2, rtOp);
        return ttcprtOp;
    }

    private Operation makeUSLOperation()
    {
        Operation[] siop = { OperationFactory.stringAction(),
            OperationFactory.integerAction() } ;
        Operation op2 = OperationFactory.sequenceAction( ":", siop ) ;

        Operation uslop = new Operation() {
            public Object operate( Object value )
            {
                Object[] values = (Object[])value ;
                String type = (String)(values[0]) ;
                Integer port = (Integer)(values[1]) ;
                return new USLPort( type, port.intValue() ) ;
            }
        } ;

        Operation op3 = OperationFactory.compose( op2, uslop ) ;
        Operation listenop = OperationFactory.listAction( ",", op3 ) ;
        return listenop ;
    }

    public static final class TestLegacyORBSocketFactory
        implements com.sun.corba.se.spi.legacy.connection.ORBSocketFactory
    {
        public boolean equals( Object other )
        {
            return other instanceof TestLegacyORBSocketFactory ;
        }

        public int hashCode() {
            return 1;
        }

        public ServerSocket createServerSocket( String type, int port )
        {
            return null ;
        }

        public SocketInfo getEndPointInfo( org.omg.CORBA.ORB orb,
            IOR ior, SocketInfo socketInfo )
        {
            return null ;
        }

        public Socket createSocket( SocketInfo socketInfo )
        {
            return null ;
        }
    }

    public static final class TestORBSocketFactory
        implements com.sun.corba.se.spi.transport.ORBSocketFactory
    {
        public boolean equals( Object other )
        {
            return other instanceof TestORBSocketFactory ;
        }

        public int hashCode() {
            return 1;
        }

        public void setORB(ORB orb)
        {
        }

        public ServerSocket createServerSocket( String type, InetSocketAddress a )
        {
            return null ;
        }

        public Socket createSocket( String type, InetSocketAddress a )
        {
            return null ;
        }

        public void setAcceptedSocketOptions(Acceptor acceptor,
                                             ServerSocket serverSocket,
                                             Socket socket)
        {
        }
    }

    public static final class TestIORToSocketInfo
        implements IORToSocketInfo
    {
        public boolean equals( Object other )
        {
            return other instanceof TestIORToSocketInfo;
        }

        public int hashCode() {
            return 1;
        }

        public List getSocketInfo(IOR ior)
        {
            return null;
        }
    }

    public static final class TestIIOPPrimaryToContactInfo
        implements IIOPPrimaryToContactInfo
    {
        public void reset(ContactInfo primary)
        {
        }

        public boolean hasNext(ContactInfo primary,
                               ContactInfo previous,
                               List contactInfos)
        {
            return true;
        }

        public ContactInfo next(ContactInfo primary,
                                ContactInfo previous,
                                List contactInfos)
        {
            return null;
        }
    }

    public static final class TestContactInfoListFactory
        implements CorbaContactInfoListFactory
    {
        public boolean equals( Object other )
        {
            return other instanceof TestContactInfoListFactory;
        }

        public int hashCode() {
            return 1;
        }

        public void setORB(ORB orb) { }

        public CorbaContactInfoList create( IOR ior ) { return null; }
    }

    private Operation makeMapOperation( final Map map )
    {
        return new Operation() {
            public Object operate( Object value )
            {
                return map.get( value ) ;
            }
        } ;
    }

    private Operation makeBMGROperation()
    {
        Map map = new HashMap() ;
        map.put( "GROW", new Integer(0) ) ;
        map.put( "CLCT", new Integer(1) ) ;
        map.put( "STRM", new Integer(2) ) ;
        return makeMapOperation( map ) ;
    }

    private Operation makeLegacySocketFactoryOperation()
    {
        Operation sfop = new Operation() {
            public Object operate( Object value )
            {
                String param = (String)value ;

                try {
                    Class<?> legacySocketFactoryClass =
                        SharedSecrets.getJavaCorbaAccess().loadClass(param);
                    // For security reasons avoid creating an instance if
                    // this socket factory class is not one that would fail
                    // the class cast anyway.
                    if (com.sun.corba.se.spi.legacy.connection.ORBSocketFactory.class.isAssignableFrom(legacySocketFactoryClass)) {
                        return legacySocketFactoryClass.newInstance();
                    } else {
                        throw wrapper.illegalSocketFactoryType( legacySocketFactoryClass.toString() ) ;
                    }
                } catch (Exception ex) {
                    // ClassNotFoundException, IllegalAccessException,
                    // InstantiationException, SecurityException or
                    // ClassCastException
                    throw wrapper.badCustomSocketFactory( ex, param ) ;
                }
            }
        } ;

        return sfop ;
    }

    private Operation makeSocketFactoryOperation()
    {
        Operation sfop = new Operation() {
            public Object operate( Object value )
            {
                String param = (String)value ;

                try {
                    Class<?> socketFactoryClass =
                        SharedSecrets.getJavaCorbaAccess().loadClass(param);
                    // For security reasons avoid creating an instance if
                    // this socket factory class is not one that would fail
                    // the class cast anyway.
                    if (com.sun.corba.se.spi.transport.ORBSocketFactory.class.isAssignableFrom(socketFactoryClass)) {
                        return socketFactoryClass.newInstance();
                    } else {
                        throw wrapper.illegalSocketFactoryType( socketFactoryClass.toString() ) ;
                    }
                } catch (Exception ex) {
                    // ClassNotFoundException, IllegalAccessException,
                    // InstantiationException, SecurityException or
                    // ClassCastException
                    throw wrapper.badCustomSocketFactory( ex, param ) ;
                }
            }
        } ;

        return sfop ;
    }

    private Operation makeIORToSocketInfoOperation()
    {
        Operation op = new Operation() {
            public Object operate( Object value )
            {
                String param = (String)value ;

                try {
                    Class<?> iorToSocketInfoClass =
                        SharedSecrets.getJavaCorbaAccess().loadClass(param);
                    // For security reasons avoid creating an instance if
                    // this socket factory class is not one that would fail
                    // the class cast anyway.
                    if (IORToSocketInfo.class.isAssignableFrom(iorToSocketInfoClass)) {
                        return iorToSocketInfoClass.newInstance();
                    } else {
                        throw wrapper.illegalIorToSocketInfoType( iorToSocketInfoClass.toString() ) ;
                    }
                } catch (Exception ex) {
                    // ClassNotFoundException, IllegalAccessException,
                    // InstantiationException, SecurityException or
                    // ClassCastException
                    throw wrapper.badCustomIorToSocketInfo( ex, param ) ;
                }
            }
        } ;

        return op ;
    }

    private Operation makeIIOPPrimaryToContactInfoOperation()
    {
        Operation op = new Operation() {
            public Object operate( Object value )
            {
                String param = (String)value ;

                try {
                    Class<?> iiopPrimaryToContactInfoClass =
                        SharedSecrets.getJavaCorbaAccess().loadClass(param);
                    // For security reasons avoid creating an instance if
                    // this socket factory class is not one that would fail
                    // the class cast anyway.
                    if (IIOPPrimaryToContactInfo.class.isAssignableFrom(iiopPrimaryToContactInfoClass)) {
                        return iiopPrimaryToContactInfoClass.newInstance();
                    } else {
                        throw wrapper.illegalIiopPrimaryToContactInfoType( iiopPrimaryToContactInfoClass.toString() ) ;
                    }
                } catch (Exception ex) {
                    // ClassNotFoundException, IllegalAccessException,
                    // InstantiationException, SecurityException or
                    // ClassCastException
                    throw wrapper.badCustomIiopPrimaryToContactInfo( ex, param ) ;
                }
            }
        } ;

        return op ;
    }

    private Operation makeContactInfoListFactoryOperation()
    {
        Operation op = new Operation() {
            public Object operate( Object value )
            {
                String param = (String)value ;

                try {
                    Class<?> contactInfoListFactoryClass =
                        SharedSecrets.getJavaCorbaAccess().loadClass(param);
                    // For security reasons avoid creating an instance if
                    // this socket factory class is not one that would fail
                    // the class cast anyway.
                    if (CorbaContactInfoListFactory.class.isAssignableFrom(
                        contactInfoListFactoryClass)) {
                        return contactInfoListFactoryClass.newInstance();
                    } else {
                        throw wrapper.illegalContactInfoListFactoryType(
                            contactInfoListFactoryClass.toString() ) ;
                    }
                } catch (Exception ex) {
                    // ClassNotFoundException, IllegalAccessException,
                    // InstantiationException, SecurityException or
                    // ClassCastException
                    throw wrapper.badContactInfoListFactory( ex, param ) ;
                }
            }
        } ;

        return op ;
    }

    private Operation makeCSOperation()
    {
        Operation csop = new Operation() {
            public Object operate( Object value )
            {
                String val = (String)value ;
                return CodeSetComponentInfo.createFromString( val ) ;
            }
        } ;

        return csop ;
    }

    private Operation makeADOperation()
    {
        Operation admap = new Operation() {
            private Integer[] map = {
                new Integer( KeyAddr.value ),
                new Integer( ProfileAddr.value ),
                new Integer( ReferenceAddr.value ),
                new Integer( KeyAddr.value ) } ;

            public Object operate( Object value )
            {
                int val = ((Integer)value).intValue() ;
                return map[val] ;
            }
        } ;

        Operation rangeop = OperationFactory.integerRangeAction( 0, 3 ) ;
        Operation op1 = OperationFactory.compose( rangeop, admap ) ;
        Operation result = OperationFactory.compose( op1, OperationFactory.convertIntegerToShort() ) ;
        return result ;
    }

    private Operation makeFSOperation() {
        Operation fschecker = new Operation() {
            public Object operate( Object value )
            {
                int giopFragmentSize = ((Integer)value).intValue() ;
                if (giopFragmentSize < ORBConstants.GIOP_FRAGMENT_MINIMUM_SIZE){
                    throw wrapper.fragmentSizeMinimum( new Integer( giopFragmentSize ),
                        new Integer( ORBConstants.GIOP_FRAGMENT_MINIMUM_SIZE ) ) ;
                }

                if (giopFragmentSize % ORBConstants.GIOP_FRAGMENT_DIVISOR != 0)
                    throw wrapper.fragmentSizeDiv( new Integer( giopFragmentSize ),
                            new Integer( ORBConstants.GIOP_FRAGMENT_DIVISOR ) ) ;

                return value ;
            }
        } ;

        Operation result = OperationFactory.compose( OperationFactory.integerAction(),
            fschecker ) ;
        return result ;
    }

    private Operation makeGVOperation() {
        Operation gvHelper = OperationFactory.listAction( ".",
            OperationFactory.integerAction() ) ;
        Operation gvMain = new Operation() {
            public Object operate( Object value )
            {
                Object[] nums = (Object[])value ;
                int major = ((Integer)(nums[0])).intValue() ;
                int minor = ((Integer)(nums[1])).intValue() ;

                return new GIOPVersion( major, minor ) ;
            }
        } ;

        Operation result = OperationFactory.compose( gvHelper, gvMain );
        return result ;
    }

    public static final class TestORBInitializer1 extends org.omg.CORBA.LocalObject
        implements ORBInitializer
    {
        public boolean equals( Object other )
        {
            return other instanceof TestORBInitializer1 ;
        }

        public int hashCode() {
            return 1;
        }

        public void pre_init( ORBInitInfo info )
        {
        }

        public void post_init( ORBInitInfo info )
        {
        }
    }

    public static final class TestORBInitializer2 extends org.omg.CORBA.LocalObject
        implements ORBInitializer
    {
        public boolean equals( Object other )
        {
            return other instanceof TestORBInitializer2 ;
        }

        public int hashCode() {
            return 1;
        }

        public void pre_init( ORBInitInfo info )
        {
        }

        public void post_init( ORBInitInfo info )
        {
        }
    }

    private Operation makeROIOperation() {
        Operation clsop = OperationFactory.classAction() ;
        Operation indexOp = OperationFactory.suffixAction() ;
        Operation op1 = OperationFactory.compose( indexOp, clsop ) ;
        Operation mop = OperationFactory.maskErrorAction( op1 ) ;

        Operation mkinst = new Operation() {
            public Object operate( Object value )
            {
                final Class initClass = (Class)value ;
                if (initClass == null)
                    return null ;

                // For security reasons avoid creating an instance
                // if this class is one that would fail the class cast
                // to ORBInitializer anyway.
                if( org.omg.PortableInterceptor.ORBInitializer.class.isAssignableFrom(
                    initClass ) ) {
                    // Now that we have a class object, instantiate one and
                    // remember it:
                    ORBInitializer initializer = null ;

                    try {
                        initializer = (ORBInitializer)AccessController.doPrivileged(
                            new PrivilegedExceptionAction() {
                                public Object run()
                                    throws InstantiationException, IllegalAccessException
                                {
                                    return initClass.newInstance() ;
                                }
                            }
                        ) ;
                    } catch (PrivilegedActionException exc) {
                        // Unwrap the exception, as we don't care exc here
                        throw wrapper.orbInitializerFailure( exc.getException(),
                            initClass.getName() ) ;
                    } catch (Exception exc) {
                        throw wrapper.orbInitializerFailure( exc, initClass.getName() ) ;
                    }

                    return initializer ;
                } else {
                    throw wrapper.orbInitializerType( initClass.getName() ) ;
                }
            }
        } ;

        Operation result = OperationFactory.compose( mop, mkinst ) ;

        return result ;
    }

    public static final class TestAcceptor1
        implements Acceptor
    {
        public boolean equals( Object other )
        {
            return other instanceof TestAcceptor1 ;
        }

        public int hashCode() { return 1; }
        public boolean initialize() { return true; }
        public boolean initialized() { return true; }
        public String getConnectionCacheType() { return "FOO"; }
        public void setConnectionCache(InboundConnectionCache connectionCache){}
        public InboundConnectionCache getConnectionCache() { return null; }
        public boolean shouldRegisterAcceptEvent() { return true; }
        public void setUseSelectThreadForConnections(boolean x) { }
        public boolean shouldUseSelectThreadForConnections() { return true; }
        public void setUseWorkerThreadForConnections(boolean x) { }
        public boolean shouldUseWorkerThreadForConnections() { return true; }
        public void accept() { }
        public void close() { }
        public EventHandler getEventHandler() { return null; }
        public MessageMediator createMessageMediator(
            Broker xbroker, Connection xconnection) { return null; }
        public MessageMediator finishCreatingMessageMediator(
            Broker xbroker, Connection xconnection,
            MessageMediator messageMediator) { return null; }
        public InputObject createInputObject(
            Broker broker, MessageMediator messageMediator) { return null; }
        public OutputObject createOutputObject(
            Broker broker, MessageMediator messageMediator) { return null; }
    }

    public static final class TestAcceptor2
        implements Acceptor
    {
        public boolean equals( Object other )
        {
            return other instanceof TestAcceptor2 ;
        }
        public int hashCode() { return 1; }
        public boolean initialize() { return true; }
        public boolean initialized() { return true; }
        public String getConnectionCacheType() { return "FOO"; }
        public void setConnectionCache(InboundConnectionCache connectionCache){}
        public InboundConnectionCache getConnectionCache() { return null; }
        public boolean shouldRegisterAcceptEvent() { return true; }
        public void setUseSelectThreadForConnections(boolean x) { }
        public boolean shouldUseSelectThreadForConnections() { return true; }
        public void setUseWorkerThreadForConnections(boolean x) { }
        public boolean shouldUseWorkerThreadForConnections() { return true; }
        public void accept() { }
        public void close() { }
        public EventHandler getEventHandler() { return null; }
        public MessageMediator createMessageMediator(
            Broker xbroker, Connection xconnection) { return null; }
        public MessageMediator finishCreatingMessageMediator(
            Broker xbroker, Connection xconnection,
            MessageMediator messageMediator) { return null; }
        public InputObject createInputObject(
            Broker broker, MessageMediator messageMediator) { return null; }
        public OutputObject createOutputObject(
            Broker broker, MessageMediator messageMediator) { return null; }
    }

    // REVISIT - this is a cut and paste modification of makeROIOperation.
    private Operation makeAcceptorInstantiationOperation() {
        Operation clsop = OperationFactory.classAction() ;
        Operation indexOp = OperationFactory.suffixAction() ;
        Operation op1 = OperationFactory.compose( indexOp, clsop ) ;
        Operation mop = OperationFactory.maskErrorAction( op1 ) ;

        Operation mkinst = new Operation() {
            public Object operate( Object value )
            {
                final Class initClass = (Class)value ;
                if (initClass == null)
                    return null ;

                // For security reasons avoid creating an instance
                // if this class is one that would fail the class cast
                // to ORBInitializer anyway.
                if( Acceptor.class.isAssignableFrom( initClass ) ) {
                    // Now that we have a class object, instantiate one and
                    // remember it:
                    Acceptor acceptor = null ;

                    try {
                        acceptor = (Acceptor)AccessController.doPrivileged(
                            new PrivilegedExceptionAction() {
                                public Object run()
                                    throws InstantiationException, IllegalAccessException
                                {
                                    return initClass.newInstance() ;
                                }
                            }
                        ) ;
                    } catch (PrivilegedActionException exc) {
                        // Unwrap the exception, as we don't care exc here
                        throw wrapper.acceptorInstantiationFailure( exc.getException(),
                            initClass.getName() ) ;
                    } catch (Exception exc) {
                        throw wrapper.acceptorInstantiationFailure( exc, initClass.getName() ) ;
                    }

                    return acceptor ;
                } else {
                    throw wrapper.acceptorInstantiationTypeFailure( initClass.getName() ) ;
                }
            }
        } ;

        Operation result = OperationFactory.compose( mop, mkinst ) ;

        return result ;
    }

    private Operation makeInitRefOperation() {
        return new Operation() {
            public Object operate( Object value )
            {
                // Object is String[] of length 2.
                String[] values = (String[])value ;
                if (values.length != 2)
                    throw wrapper.orbInitialreferenceSyntax() ;

                return values[0] + "=" + values[1] ;
            }
        } ;
    }
}

// End of file.
