18.3.1 動的リクエスト用オブジェクトの設計例

コードサンプル18-3および18-4に,DSIを使用してインプリメントするC++およびJavaのAccountImplクラスの宣言を示します。これは,invokeメソッドを宣言するDynamicImplementationクラスから派生します。VisiBroker ORBは,そのinvokeメソッドを呼び出して,クライアントオペレーション要求をServerRequestオブジェクトの形でインプリメンテーションに引き渡します。

コードサンプル18-3にAccountクラスコンストラクタと_primary_interface関数を示します。

コードサンプル18-3 dynamicから派生するAccountImplクラスの例(C++)

class AccountImpl :
     public PortableServer::DynamicImplementation ,
             public virtual PortableServer::RefCountServantBase{
  public:
     AccountImpl(PortableServer::Current_ptr current,
           PortableServer::POA_ptr poa)
           : _poa_current(PortableServer::Current::_
                 duplicate(current)), _poa(poa)
     {}

     CORBA::Object_ptr get(const char *name) {
        CORBA::Float balance;
        // Check if account exists
        if (!_registry.get(name, balance)) {
           // simulate delay while creating new account
           VISPortable::vsleep(3);
           // Make up the account's balance,
                 between 0 and 1000 dollars
           balance = abs(rand()) % 100000 / 100.0;
           // Print out the new account
           cout << "Created " << name << "'s account: "
                 << balance << endl;
           _registry.put(name, balance);
        }
        // Return object reference
        PortableServer::ObjectId_var accountId =
        PortableServer::string_to_ObjectId(name);
        return _poa->create_reference_with_id(
              accountId, "IDL:Bank/Account:1.0");
     }
  private:
     AccountRegistry _registry;
     PortableServer::POA_ptr _poa;
     PortableServer::Current_var _poa_current;

     CORBA::RepositoryId _primary_interface(
           const PortableServer::ObjectId& oid,
                 PortableServer::POA_ptr poa) {
           return CORBA::string_dup(
                 (const char *)"IDL:Bank/Account:1.0");
     };

     void invoke(CORBA::ServerRequest_ptr request) {
     // Get the account name from the object id
     PortableServer::ObjectId_var oid =
           _poa_current->get_object_id();
     CORBA::String_var name;
     try {
        name = PortableServer::ObjectId_to_string(oid);
     } catch (const CORBA::Exception& e) {
        throw CORBA::OBJECT_NOT_EXIST();
     }
        // Ensure that the operation name is correct
        if (strcmp(request->operation(), "balance") != 0) {
           throw CORBA::BAD_OPERATION();
        }
        // Find out balance and fill out the result
        CORBA::NVList_ptr params = new CORBA::NVList(0);
        request->arguments(params);
        CORBA::Float balance;
        if (!_registry.get(name, balance))
           throw CORBA::OBJECT_NOT_EXIST();
        CORBA::Any result;
        result <<= balance;
        request->set_result(result);
        cout << "Checked " << name << "'s balance: "
              << balance << endl;
     }
};

コードサンプル18-4にAccountクラスコンストラクタの例を示します。

コードサンプル18-4 Dynamicから派生するAccountImplクラスの例(Java)

import java.util.*;
import org.omg.PortableServer.*;
public class AccountImpl extends DynamicImplementation {
  public AccountImpl(org.omg.CORBA.ORB orb, POA poa) {
     _orb = orb;
     _poa = poa;
  }

  public synchronized org.omg.CORBA.Object get(String name) {
     org.omg.CORBA.Object obj;
     // Check if account exists
     Float balance = (Float)_registry.get(name);
     if (balance == null) {
        // simulate delay while creating new account
        try {
           Thread.currentThread().sleep(3000);
        } catch (Exception e) {
           e.printStackTrace();
        }
        // Make up the account's balance, between 0 and 1000 dollars
        balance = new Float(Math.abs(_random.nextInt())
                                                  % 100000 / 100f);
        // Print out the new account
        System.out.println("Created " + name + "'s account: " +
               balance.floatValue());
        _registry.put(name, balance);
     }
     // Return object reference
     byte[ ] accountId = name.getBytes();
     try {
        obj = _poa.create_reference_with_id(accountId,
                                            "IDL:Bank/Account:1.0");
     } catch (org.omg.PortableServer.POAPackage.WrongPolicy e) {
        throw new org.omg.CORBA.INTERNAL(e.toString());
     }
     return obj;
  }

  public String[ ] _all_interfaces(POA poa, byte[ ] objectId) {
                                                     return null; }

  public void invoke(org.omg.CORBA.ServerRequest request) {
     Float balance;
     // Get the account name from the object id
     String name = new String(_object_id());
     // Ensure that the operation name is correct
     if (!request.operation().equals("balance")) {
        throw new org.omg.CORBA.BAD_OPERATION();
     }
     // Find out balance and fill out the result
     org.omg.CORBA.NVList params = _orb.create_list(0);
     request.arguments(params);
     balance = (Float)_registry.get(name);
     if (balance == null) {
        throw new org.omg.CORBA.OBJECT_NOT_EXIST();
     }
     org.omg.CORBA.Any result = _orb.create_any();
     result.insert_float(balance.floatValue());
     request.set_result(result);
     System.out.println("Checked " + name + "'s balance: " +
            balance.floatValue());
  }
  private Random _random = new Random();
  static private Hashtable _registry = new Hashtable();
  private POA _poa;
  private org.omg.CORBA.ORB _orb;
}

コードサンプル18-5および18-6に,DSIを使用してインプリメントする必要のあるAccountManagerImplクラスのインプリメンテーションを示します。これは,invokeメソッドを宣言するDynamicImplementationクラスからも派生します。VisiBroker ORBは,そのinvokeメソッドを呼び出して,クライアントオペレーション要求をServerRequestオブジェクトの形でインプリメンテーションに引き渡します。

コードサンプル18-5 Dynamicから派生するAccountManagerImplクラスの例(C++)

class AccountManagerImpl
     : public PortableServer::DynamicImplementation,
       public virtual PortableServer::RefCountServantBase {
  public:
     AccountManagerImpl(AccountImpl* accounts)
           { _accounts = accounts; }

     CORBA::Object_ptr open(const char* name) {
        return _accounts->get(name);
     }

  private:
     AccountImpl* _accounts;
     CORBA::RepositoryId _primary_interface
           (const PortableServer::ObjectId& oid,
           PortableServer::POA_ptr poa) {
        return CORBA::string_dup((const char *)
              "IDL:Bank/AccountManager:1.0");
     };
     void invoke(CORBA::ServerRequest_ptr request) {
        // Ensure that the operation name is correct
        if (strcmp(request->operation(), "open") !=0)
           throw CORBA::BAD_OPERATION();
        // Fetch the input parameter
        char *name = NULL;
        try {
           CORBA::NVList_ptr params = new CORBA::NVList(1);
           CORBA::Any any;
           any <<= (const char*) "";
           params->add_value("name", any, CORBA::ARG_IN);
           request->arguments(params);
           *(params->item(0)->value()) >>= name;
        } catch (const CORBA::Exception& e) {
           throw CORBA::BAD_PARAM();
        }
        // Invoke the actual implementation and
        // fill out the result
        CORBA::Object_var account = open(name);
        CORBA::Any result;
        result <<= account;
        request->set_result(result);
     }
};

コードサンプル18-6 Dynamicから派生するAccountManagerImplクラスの例(Java)

import org.omg.PortableServer.*;
public class AccountManagerImpl extends DynamicImplementation {
  public AccountManagerImpl(org.omg.CORBA.ORB orb, AccountImpl
     accounts) { _orb =orb; _accounts =accounts;
  }

  public synchronized org.omg.CORBA.Object open(String name) {
     return _accounts.get(name);
  }
  public String[ ] _all_interfaces(POA poa, byte[ ] objectId)
     { return null; }

  public void invoke(org.omg.CORBA.ServerRequest request) {
     // Ensure that the operation name is correct
     if (!request.operation().equals("open")) {
        throw new org.omg.CORBA.BAD_OPERATION();
     }

     // Fetch the input parameter
     String name = null;
     try {
        org.omg.CORBA.NVList params = _orb.create_list(1);
        org.omg.CORBA.Any any = _orb.create_any();
        any.insert_string(new String(""));
        params.add_value("name", any, org.omg.CORBA.ARG_IN.value);
        request.arguments(params);
        name = params.item(0).value().extract_string();
     } catch (Exception e) {
        throw new org.omg.CORBA.BAD_PARAM();
     }
     // Invoke the actual implementation and fill out the result
     org.omg.CORBA.Object account = open(name);
     org.omg.CORBA.Any result = _orb.create_any();
     result.insert_Object(account);
     request.set_result(result);
  }

  private AccountImpl _accounts;
  private org.omg.CORBA.ORB _orb;
}