PROGRAMMING

ビデオ: RadPHP XE2でiPhoneアプリケーションを開発�...

Written by Tomohiro T1465 on . Posted in PROGRAMMING

このチュートリアルでは、アプリケーションにおける、jQuery Mobileコンポーネント、モバイルテーマ、埋め込み画像の使い方や、加速度センサー/カメラ/コンパスなどのモバイル端末のハードウェアへのアクセス方法について解説します。また、アプリケーションをXcodeのシミュレータや実際のiPhoneで動作させる方法についても解説します。


Developing iPhone Applications using RadPHP XE2

Written by Super user Admin A73 on . Posted in PROGRAMMING

The tutorial covers using jQuery mobile components, mobile themes, embedding images and accessing mobile hardware such as the accelerometer, camera, compass etc. in your application.You will also see how to run the application in the simulator in Xcode and on your iPhone.


ホームコンテンツ

Written by Hitoshi Fujii on . Posted in PROGRAMMING

 

新着ビデオ:

第29回 エンバカデロ・デベロッパーキャンプ
「マルチデバイス対応アプリ開発の勘所」

RAD Studio XE7で搭載されたFireUIデザイナを使いながら、最新のiOSやAndroid Wearなどでも動作するマルチデバイス対応アプリの作成方法を解説

第29回 エンバカデロ・デベロッパーキャンプ
「マルチデバイス向けアプリ開発・構築におけるデータハンドリングのいろいろ」

マルチデバイス向けアプリ開発・構築におい­て、データの取り扱いについての様々な話題をあげ、関連する情報や注意を紹介

第29回 エンバカデロ・デベロッパーキャンプ
「着飾らない IoT」

開発者が IoT(モノのインターネット)を活用する上で知っておかなければならない技術的な知­識を紹介

「RAD Studio XE7の新機能 - FireUIマルチデバイスデザイナ」

FireUIマルチデバイスデザイナを用いれば、異なる種類のデバイス、フォームファ­クター、OSに適合するユーザーインターフェイスを一元的に設計できます。UIを一度­作成すれば、それを個々のデバイス向けに適合させたり、カスタマイズを行うことができ­ます。

エンバカデロのイベント・セミナー情報は、こちらのページをご覧ください。
エンバカデロの最新情報は、Twitter | Facebook でも配信しています。ご活用ください。


VisiBrokerでの単純なファイアウォール設定(ポー�...

Written by Embarcadero USA on . Posted in PROGRAMMING

VisiBroker製品を利用して開発されたCORBAクライアントオブジェクトとサーバオブジェクト間にファイアウォールを設置する場合、開放する通信ポートに関するファイアウォール設定が必要です。ここではスマートエージェントを利用したオブジェクト間通信そして最も単純なポートフィルタリングを利用する方法を説明します。

ここでは、クライアントホストとサーバホストがあり、その間にファイアウォールが配置されている構成を考えます。なお、サーバオブジェクトとスマートエージェントは同一のホストもしくは同一セグメント内にて稼働するものとします。

    ファイアウォール設定

スマートエージェントが利用するポートは以下の2つとなります。これら2つのポートに対して双方向通信ができるようファイアウォール設定を行います。

・スマートエージェントポート(環境変数OSAGENT_PORT)
 UDPのみ双方向で開放

・管理ポート(環境変数OSAGENT_CLIENT_HANDLER_PORT)
 TCP/UDP双方向で開放

またクライアントとサーバオブジェクトがIIOP通信で利用するポートもTCPのみ双方向で開放します。

    サーバ側設定

スマートエージェントとサーバオブジェクトは同一ホストもしくは同一セグメントで稼働するためサーバオブジェクトはUDPブロードキャストによる自動検出を行うことができます。したがってサーバオブジェクト側では特にスマートエージェントの位置情報を指定する必要はありません。

但し、クライアントとサーバオブジェクトがIIOP通信で利用するポートを指定する必要があります。通常、このポートは動的に変更されるものですが、ここでは以下のプロパティによって明示的にポートを固定します。

vbroker.se.iiop_tp.scm.iiop_tp.listener.port 

ここで指定されるポートにてクライアントとサーバオブジェクト間でのIIOP通信が行われることとなります。

アクセスコントロールサービスを以下のプロパティにて指定します。

vbroker.orb.dynamicLibs 

    クライアント側設定

ファイアウォールの外側に配置されるクライアントオブジェクトに対して、スマートエージェントの位置を指定する必要があります。以下のプロパティによって指定をすることができます。

vbroker.agent.addr (スマートエージェントが稼働するホスト名) 
vbroker.agent.port (スマートエージェントが利用するスマートエージェントポート) 

クライアントとサーバオブジェクトがIIOP通信で利用するポートは指定する必要はありません。これはスマートエージェントから取得することができるためです。

サーバ側設定と同様にアクセスコントロールサービスを以下のプロパティにて指定します。

vbroker.orb.dynamicLibs 

    実際の構成例

ここでは以下の構成での起動方法について挙げています。(UNIXプラットフォーム)

スマートエージェント及びサーバオブジェクト稼働ホスト

myhost.acme.com

スマートエージェントポート

18000

スマートエージェント管理ポート

20000

IIOP通信ポート

19000


各オブジェクトの起動方法は以下の通りです。

オブジェクト

起動方法

サーバ側

スマートエージェントの起動

OSAGENT_PORT=18000 ; export OSAGENT_PORT
OSAGENT_CLIENT_HANDLER_PORT=20000 ; export OSAGENT_CLIENT_HANDLER_PORT
osagent

サーバオブジェクトの起動

OSAGENT_PORT=18000 ; export OSAGENT_PORT
OSAGENT_CLIENT_HANDLER_PORT=20000 ; export OSAGENT_CLIENT_HANDLER_PORT
vbj -Dvbroker.orb.dynamicLibs=com.inprise.vbroker.firewall.Init \
-Dvbroker.se.iiop_tp.scm.iiop_tp.listener.port=19000 Server

クライアント側

クライアントオブジェクトの起動

vbj -Dvbroker.orb.dynamicLibs=com.inprise.vbroker.firewall.Init \
-Dvbroker.agent.port=18000 \
-Dvbroker.agent.addr=myhost.acme.com Client




Article originally contributed by Yoshiko Shinoda


Problem running idl2cpp on AIX 4.X

Written by Embarcadero USA on . Posted in PROGRAMMING

Problem running idl2cpp on AIX 4.X

Problem Description

When we compile a VBC 333 example on AIX 4.X the JDK 1.1.x

environment we get the following error ...

$ make

../../bin/idl2cpp Test.idl

IDL preprocessor: fatal error: a read or write operation failed;

processing abor

ted

make: *** [Test_c.cc] Error 1

$

Resolution

If using JDK 1.1.6, turn off JIT by as follows:

export JAVA_COMPILER=off

Alternatively use JDK 1.1.8.



Article originally contributed by Jimmy Maher


VisiBroker 4.x GateKeeper FAQ

Written by Embarcadero USA on . Posted in PROGRAMMING

VisiBroker GateKeeper FAQ

VisiBroker GateKeeper FAQ

Table of Contents

1: General

Q1.1: What is GateKeeper?

GateKeeper is an IIOP Proxy Server. Similar to HTTP Proxy Server, GateKeeper relays the messages between the client and the server.

Q1.2: Is GateKeeper fully compliant to the CORBA firewall specification?

GateKeeper is compliant to the CORBA firewall specification. Bi-directional GIOP is not fully supported in this release because the details of the Bi-directional GIOP are still changing.

Q1.3: Why do I need GateKeeper?

Usually you need GateKeeper in following situation: 1. You don't want expose the server directly to the clients for security concerns. 2. The clients have restricted access to the server, for example, unsigned applets or firewall.

Q1.4: Do I have to use GateKeeper when I have an unsigned applet client?

No, you don't have to. There are three restriction imposed by Java sandbox: 1. the applet can only connects back to the host where the code is downloaded. 2. the applet can not receive incoming connections. 3. No broadcast UDP message can be sent out from applet.

So if the server is at the host where the applet is downloaded and there is no callback involved and client doesn't use OSAGENT to do bind, the client can communicate to the server without GateKeeper.

Q1.5: Do I have to use GateKeeper when I have a firewall?

No, you don't have to, as long as the firewall allows the TCP traffic from the client to the server at certain hosts or ports. You can configure the server to run on these hosts or ports.

Q1.6: Can I use GateKeeper 4.0 with VisiBroker 3.x client or server?

If you are not using HTTP tunneling, you can use GateKeeper 4.0 with VisiBroker 3.x client and server.

If you are using HTTP tunneling, Gatekeeper 4.0 can support VisiBroker 3.x client only if all the client are using HTTP tunneling. That is you have to configure the GateKeeper 4.0 to support HTTP tunneling only and configure the client to use HTTP tunneling only.

First you have to mask the IIOP port in GateKeeper with the HTTP port. This can be done in Tab of <Request Forwarding Service> of Panel of <IIOP Proxy Services>, where you should set port number of IIOP listener be the same as port number of HIOP listener. This will set "vbroker.se.exterior.scm.ex-iiop.listener.proxyPort=8088"

Then you have to the following 3.x properties at your 3.x client: ORBgatekeeperIOR= true and ORBalwaysTunnel=true

2: Installation and Configuration

Q2.1: How to install GateKeeper?

GateKeeper is installed with VisiBroker for Java.

Q2.2: How to start GateKeeper?

You can start GateKeeper from command line: "gatekeeper". GateKeeper will look for "gatekeeper.properties" file in the current directory.

You can also start GateKeeper with a different property file from command line: "gatekeeper -props <property file>".

You can also start GateKeeper as a NT service on MS Windows NT. To run GateKeeper as a NT service, you need to install GateKeeper as NT service first. This can be done the following command "gatekeeper -install <Service Name> [-props <Full Path of Property File>]". Then you can start GateKeeper from Service Control Manager. The following command is to remove GateKeeper as a NT service, "gatekeeper -remove <Service Name>". Please verify that the command without "-install option" is able to run without any error first before installing Gatekeeper as a NT service, because once Gatekeeper running as a NT service, you won't see any error output and can't be shutdown from Gatekeeper Console any more.

Q2.3: How to configure GateKeeper?

GateKeeper can be configured through GateKeeper Console, which is part of VisiBroker Console. For the detail on how to use GateKeeper Console, please refer to "GateKeeper for VisiBroker Guide".

3: How to configure VisiBroker client and server to use GateKeeper?

Q3.1: Do I have to change my server to work with GateKeeper?

There are two ways you can configure the system to use the GateKeeper.

One way is to embed GateKeeper information in the server's object reference. This is portable and can support more complex firewall configuration. However, this requires code changes and complex to configure when you have callback involved.

The other way is to configure the client only, which is similar to VisiBroker 3.x. This is very easy to configure. However, it doesn't support complex firewall configuration. For example, in this configuration, the client can't talk to the server behind different GateKeepers.

To use the first configuration, and you only want to expose server object on a special POA, the you have to export FirewallPolicy on that POA:
      org.omg.CORBA.Any fw_policy_value = orb.create_any();
      com.inprise.vbroker.firewall.FirewallPolicyValueHelper.insert(fw_policy_value, com.inprise.vbroker.firewall.EXPORT.value);
      org.omg.CORBA.Policy firewall_policy = orb.create_policy(com.inprise.vbroker.firewall.FIREWALL_POLICY_TYPE.value, fw_policy_value);
      POA poa = rootPOA.create_POA("name", rootPOA.the_POAManager(), new org.omg.CORBA.Policy[]\{firewall_policy\});

You have to configure the server engine properties for this POA to include the firewall information. For example, you have one GateKeeper in front of the server. First, you have to specify a list of paths to the server: vbroker.se.iiop.firewallPaths = internet. Second, you have to specify the firewalls in each path: vbroker.firewall-path.internet=proxy. Third, you have to describe each firewall: vbroker.firewall.proxy.type=PROXY vbroker.firewall.proxy.ior=http://host:port/gatekeeper.ior.

If you need to export server objects on all POAs, you can simply specify another property and without adding code in your Java source code: vbroker.orb.exportFirewallPath=true

Q3.2: Do I have to change my client to work with GateKeeper?

There are two ways you can configure the system to use the GateKeeper.

One way is to embed GateKeeper information in the server's object reference. This is portable and can support more complex firewall configuration. However, this requires code changes and complex to configure when you have callback involved.

The other way is to configure the client only, which is similar to VisiBroker 3.x. This is very easy to configure. However, it doesn't support complex firewall configuration. For example, in this configuration, the client can't talk to the server behind different GateKeepers.

To use the second configuration, all you have to do is to specify the URL to the GateKeeper's reference in the client:

vbroker.gatekeeper.ior = http://host/gatekeeper.ior

This will automatically enable you to do bind and callback via GateKeeper if Gatekeeper is set to enable callback service. In another word, this property will automatically set vbroker.orb.alwaysProxy=true and vbroker.locator.ior=vbroker.gatekeeper.ior. In case of client is Java Applet, if vbroker.gatekeeper.ior is set to "", this means vbroker.gatekeeper.ior is set to <CODE BASE>/gatekeeper.ior by default.

Q3.3: What can GateKeeper for Java Applet?

GateKeeper is a web server, i.e., GateKeeper can load all resource needed by a Java Applet. But GateKeeper is not a high performance and scalable web server. In fact, it is never a goal to develop GateKeeper as a web server to replace current commercial web server. So the correct way to use Gatekeeper for Java Applet is to use commercial web server to start Applet and use Gatekeeper only for HTTP tunneled IIOP request. In order to do so, Gatekeeper needs to run the same host of web server and its stringified IOR should be publishable by web server.

In case Applet needs to do "bind", GateKeeper can do binding for the Applet. All Applet needs to do is specify vbroker.locator.ior=http://host:port/gatekeeper.ior.

GateKeeper supports the following HTTP proxy servers, MS Proxy Server 2.0, Netscape Proxy Server 3.5, and WinGate Proxy Server 3.0.5.

GateKeeper supports the following web browser, Netscape Communicator 4.6 and Internet Explore 5.0. GateKeeper also supports JavaPlugin 1.1 and 1.2.

Q3.4: How to set callback channel via GateKeeper?

If client has callback objects but is blocked by firewall or client is an Applet, then GateKeeper is needed in this case to create a callback channel for the client. GateKeeper 4.0 has not fully implemented BiDirectional GIOP, callback service is still in 3.X style. Here are what need to set on GateKeeper,

vbroker.gatekeeper.callbackEnabled=true
vbroker.gatekeeper.backcompat.callback=true

and what need to set on client,

vbroker.orb.dynamicLibs=com.inprise.vbroker.firewall.Init
vbroker.orb.alwaysProxy=true
vbroker.se.iiop_tp.scm.iiop_tp.listener.type=Callback-IIOP
vbroker.se.iiop_tp.scm.iiop_tp.listener.gatekeeper=http://<GateKeeper host>:8088/gatekeeper.ior

4: Firewall

Q4.1: How to use GateKeeper on dual-home firewall?

Many software firewalls run on dual-home machines to forward network traffic from one side to the other side. GateKeeper can be configured to run in such environment too.

For example, the dual-home machine has two IP address: 172.20.10.1 and 171.64.10.1. The 172.20.10.1 is the client side network or the Internet and the 171.64.10.1 is the server side network or the Intranet. You can specify the following setting in the <Basic Properties> Panel, where can set the exterior port and interior host address separately to 172.20.10.1 and 172.64.10.1.

The above operation is mapped to set values of the following properties: vbroker.se.exterior.host=172.20.10.1 and vbroker.se.interior.host=171.64.10.1

If you have callback enabled, you also have to check <Enable Callback Service>, which will automatically set the callback host to be the same as the exterior IP address. This is mapped to set the property of vbroker.gatekeeper.backcompat.callback.host=172.20.10.1.

Q4.2: How to use GateKeeper with Network Address Translation (NAT) device?

NAT devices hide the actual IP address and/or port number in the network by changing the IP address and/or in the IP packet and Gatekeeper does not have to be used in this case.

Usually the NAT device is deployed in front of the GateKeeper to protect the GateKeeper.

For instance, if GateKeeper is running at host 172.20.10.1 and NAT device hides 172.20.10.1 with 171.64.10.1. You can set "Exterior Proxy Host" in "Basic Property" Panel to 171.64.10.1. This is mapped to set the property of vbroker.se.exterior.proxyHost=171.64.10.1.

If you have a NAT running between GateKeeper and server to hide server host's address, you can set "Interior Proxy Host" in Basic Property" Panel.

When you have callback enabled, callback proxy host will be set to be the same as exterior proxy host automatically, i.e., vbroker.gatekeeper.backcompat.callback.proxyHost=171.64.10.1.

If the NAT device also hides the ports, you have to set the proxyPort property for all the listeners started on the exterior side. By default, GateKeeper starts two listeners on the exterior side: IIOP at port 683 and HTTP at port 8080. This can set at "Request Forwarding Service" Tab of "IIOP Proxy Services" Panel.

To hide the IIOP port, you have to set:

vbroker.se.exterior.scm.ex-iiop.listener.proxyPort, which is the Proxy Port for IIOP listener.

To hide the HTTP port, you have to set:

vbroker.se.exterior.scm.ex-hiop.listener.proxyPort, which is the Proxy Port for HIOP listener.

If you have callback enabled and you want to hide the callback port, you have to set the following properties:

vbroker.gatekeeper.backcompat.callback.listener.iiop.port

vbroker.gatekeeper.backcompat.callback.listener.iiop.proxyPort

These two properties can be set "Callback Service" Tab of "IIOP Proxy Services" Panel.

Here are three examples on how to run with NAT service firewall:

1. If NAT is sitting between client and server, and Gatekeeper is not used, here is the setting for your client and server:
server.properties,
vbroker.orb.dynamicLibs=com.inprise.vbroker.firewall.Init
vbroker.se.iiop_tp.firewallPaths=internet
vbroker.firewall-path.internet=nat
vbroker.firewall.nat.type=TCP
vbroker.firewall.nat.host=<public translated IP>
vbroker.firewall.nat.iiop_port=2048
vbroker.firewall.nat.hiop_port=0
vbroker.se.iiop_tp.scm.iiop_tp.listener.port=2048

client.properties
vbroker.orb.dynamicLibs=com.inprise.vbroker.firewall.Init
vbroker.orb.alwaysProxy=true

2. There is NAT between client and Gatekeeper, where Gatekeeper is running on server side.
server.properties,
vbroker.orb.dynamicLibs=com.inprise.vbroker.firewall.Init
vbroker.se.iiop_tp.firewallPaths=internet
vbroker.firewall-path.internet=proxy
vbroker.firewall.proxy.type=PROXY
vbroker.firewall.proxy.ior=http://localhost:9091/gatekeeper.ior

gatekeeper.properties:
vbroker.se.exterior.proxyHost=<gatekeeper's host public translated IP>

client.properties,
vbroker.orb.dynamicLibs=com.inprise.vbroker.firewall.Init
vbroker.orb.alwaysProxy=true

3. There is NAT between Gatekeeper and server,
server.properties,
vbroker.orb.dynamicLibs=com.inprise.vbroker.firewall.Init
vbroker.se.iiop_tp.firewallPaths=internet,intranet
vbroker.firewall-path.internet=nat
vbroker.firewall-path.intranet=proxy
vbroker.firewall.nat.type=TCP
vbroker.firewall.nat.host=localhost
vbroker.firewall.nat.iiop_port=2048
vbroker.firewall.nat.hiop_port=0
vbroker.se.iiop_tp.scm.iiop_tp.listener.port=2048
vbroker.firewall.proxy.type=PROXY
vbroker.firewall.proxy.ior=http://<Gatekeeper's host>:9091/gatekeeper.ior

client and gatekeeper.properties:
vbroker.orb.dynamicLibs=com.inprise.vbroker.firewall.Init
vbroker.orb.alwaysProxy=true

If callback is involved with NAT service, depends where is NAT, you can configure GateKeeper to set up callback channel via NAT. If NAT is between GateKeeper and server, you need to set vbroker.se.interior.proxyHost. If NAT is between GateKeeper and client, you need to set vbroker.gatekeeper.backcompat.callback.proxyHost.

Q4.3: How to use GateKeeper with port filtering firewalls?

Port filtering firewalls make access decision based on the port number or IP address in the IP packets. In order to work with these firewalls, GateKeeper has to start on the fixed ports. By default, all the listeners on the exterior side is started on the fixed ports. For example, IIOP is started at port 683 and HTTP is started at port 8088. To change the port numbers, you have to set the following properties in the gatekeeper property file:

vbroker.se.exterior.scm.ex-iiop.listener.port

vbroker.se.exterior.scm.ex-hiop.listener.port

If you have callback enabled, the callback listener by default listens on a dynamic port. You have to set the following property to a non-zero value so the callback listener will start at a fixed port:

vbroker.gatekeeper.backcompat.callback.listener.iiop.port

Q4.4: How to use HTTP tunneling feature?

HTTP tunneling is useful in the case of firewall does messaging filtering, for example, firewall only also HTTP message go through. HIOP (IIOP over HTTP) package is designed as a plug in for VBJ, i.e., this feature can be used by both Java application and Java applet. So users can just configure their client and server only talk with HIOP rather than IIOP if there is a message filtering firewall between and in this case, GateKeeper is not necessary.

But HIOP is much less efficient and scalable protocol than IIOP. The threshold of HIOP is introduced by two factors. If URLConnection's
implementation does not support Keep-Alive, (this is JDK's case), then each request and its reply will have a new connection. Then the number
new connection the listener can accept at the same time determines how scale the server can be, also majority of time is spent on connection
creation and network latency. In case of browsers support Keep-Alive for URLConnection, like IE and NC, performance is restricted by the
URLConnection implementation of browsers and HTTP protocol its self. HTTP protocol decides that requests can not be multiplexed on the same
connection. The benchmark test result we did shows that HIOP for Java Application's performance profile closes IIOP's performance profile with multiple
clients case. It is about 1.5~2 times slower the IIOP case. HIOP for Java Applet case varies with different browser, but is much worse than Java Application case, about 5~10 times worse than HIOP for Java application case. It is also found that if Gatekeeper needs to reply extensive HIOP request, it is better set ORB garbage collection timeout to shorter time to avoid OutOfMemory error.

To use HTTP tunneling, you need to set vbroker.orb.alwaysTunnel=true and for Java Application, you need also to set vbroker.orb.dynamicLibs=com.inprise.vbroker.firewall.Init,com.inprise.vbroker.HIOP.Init.

Q4.4: How to chain GateKeeper in case of multiple enclaves of firewalls?

In case of there are multiple layers of firewalls between client and server, multiple GateKeepers need to run for each firewall. The most common case is client is blocked by outbound firewall and server is blocked by inbound firewall. The easiest way to configure for this case is running a GateKeeper outside client-side firewall and another GateKeeper outside server-side firewall; configure client always go through first GateKeeper for IIOP request by specify vbroker.orb.gatekeeper.ior; load firewall package on first GateKeeper and set vbroker.orb.alwaysProxy so that it will always talk to the second GateKeeper; configure a firewall path on server so that server can be accessed via the server-side GateKeeper.

In case of there are multiple firewall on server side, you can configure server with the closest GateKeeper as its firewall path, and configure another firewall path with the second closet GateKeeper for the above GateKeeper. Or, you can configure server with the furthest GateKeeper as its firewall path, and configure each GateKeeper to access the next GateKeeper, so that finally the request can be relayed to server. And the third option is that set multiple firewall paths according the order from outer to inner on server, and let each GateKeeper figure out its messaging route by themselves. On thing you need to pay attention to is except the closest GateKeeper, you need to set vbroker.orb.alwaysProxy for all other GateKeepers.

In case of there are multiple firewalls on client side and you need to set callback channel along these GateKeeper, what you should do is except the most outer GateKeeper, you need to set callback listener for each other GateKeepers just like what you have to set on client.

5: Access Control

Q5.1: What kind of Access Control does GateKeeper supports?

Right now GateKeeper supports access control based on client's IP address/subnet and/or server's IP address/subnet. In the future, GateKeeper will integrate with Inprise Authorization Service to provide finer grade access control.

Q5.2: How do I turn on the access control in GateKeeper?

By default, GateKeeper does not have access control service installed. You have to install the access control service by specifying the following property:

vbroker.orb.dynamicLibs=com.inprise.vbroker.gatekeeper.security.Init, This property will be automatically added if user set at least one access rule in "Access Controllers" Tab of "Security" Panel.

Q5.3: How does the access control work?

You can specify a list of rules. Each rule specifies some matching criteria based on client or server information, as well as the action. There two actions available: grant or deny. When a request coming in, the rules are evaluated in the order you specified. The action is taken based on the first matching rule. If there is no matching rule found, the default action is taken. By default, the default action is always to grant the access.

Because the rules are evaluated in the order you specify, you always want to put the most restrictive rules in the front.

Q5.4: How does the access control looks like?

Due to the concern of future integration with Authorization Service or EJB Container, the default definition and regular expression of access control rules are not public to users and will be changed if necessary. To define an access control rule, users have to use GateKeeper Console. For the detail on how to define access control, please refer to "Gatekeeper for VisiBroker Guide".

Q5.5: How do I specify access control rules?

When users specify a rule, one thing they should pay attention to is the default rule. Suppose users want to only grant access on a on a client-side subnet. Besides they need define a rule to grant the access, they should also define the default rule as to "deny" for the purpose of safety.

6: Scalability

Q6.1: What do I do when GateKeeper runs out of memory?

GateKeeper is running as a stateless server now. Memory usage has been reduced significantly compared to the previous version. Memory usage mainly depends on how big the cache is. When you run into OutOfMemoryError, you can increase the Java VM memory by using -mx or -ms option. Or you can reduce the cache size by change the following property: vbroker.gatekeeper.cache.size. This property can be found at "GateKeeper" Tab of "Performance" Panel.Setting the cache size to -1 means disabling the cache, which will decrease the performance.

Another reason for OutOfMemoryError you might find is in HTTP tunneling case, the connections are not collected fast enough when there are a huge number of request in very short time period. For this case, you need set vbroker.orb.gcTimeout=5 or even shorter period.

Q6.2: What do I do when GateKeeper's performance slows down when the there is a large number of clients?

There are a few possibilities that could slow down GateKeeper when there is a large number of clients.

One possibility is that, if all the clients goes to a single server, the connection from the GateKeeper to the server might be congested. You can set the following properties to increase the number of connections from the GateKeeper to the server:

vbroker.ce.iiop.cm.connectionSize

Another possibility is that, if servers take long time to respond, the number of threads blocked in the GateKeeper might be too high. You can turn on the asynchronized IO mode in the GateKeeper to reduce the number of threads blocked for replies:

vbroker.gatekeeper.asynchronziedIO=true

We are currently looking into other ways, for example, native IO, to reduce the thread usage in the GateKeeper.

When the number of the clients reach to a point, you have to use multiple GateKeepers and do load balance among them. From the benchmark test we did, we found the above two operations don't have very much affect on throughput, the best way to increase performance is to use load balancing feature of GateKeeper.

All these properties can be found at the "GateKeeper" Tab of "Performance" Panel.

Q6.3: How do I do load balance for GateKeeper?

There are at least two ways you can do load balance for GateKeeper.

One is to use low-level devices to redirect TCP traffic among an array of GateKeepers when there is no callback involved. It is made possible in GateKeeper 4.0 because GateKeeper doesn't keep states anymore except for callbacks.

Another way is to use GateKeeper build-in load balance mechanism. Currently you can set a master GateKeeper and a set of slave GateKeepers and cluster them together through property file. Both the server or the client only has to know the master GateKeeper. The master GateKeeper will do round-robin load balance among the set of slave GateKeepers. The load balance is done at object level. That is each object will be redirected to one of the slave GateKeepers at the first request. You can also use GateKeeper 4.0 to do load balancing for VBJ 3.4 clients and servers. The other benefits coming along clustering GateKeeper is provide fault tolerance on those slave GateKeepers.

To configure the master GateKeeper, you have to load the extension first:

vbroker.orb.dynamicLibs=com.inprise.vbroker.gatekeeper.ext.Init

Then you have to specify a list of names of the slave GateKeepers. For examples:

vbroker.gatekeeper.load.slaves=slave1,slave2

For each slave GateKeeper, you have to specify their IOR or the URL to the IOR:

vbroker.gatekeeper.load.slave.slave1=http://host1:8080/slave1.ior

vbroker.gatekeeper.load.slave.slave2=http://host2:8080/slave2.ior

To set these properties, user can look at the "Load Balancing" Tab of "Performance" Panel.

Q6.4: How do I configure server to provide high availability in case GateKeeper fails over?

You can configure multiple firewall paths on your server via different GateKeeper. Following is an example configuration,

vbroker.orb.dynamicLibs=com.inprise.vbroker.firewall.Init
vbroker.se.iiop_tp.firewallPaths=internet
vbroker.firewall-path.internet=first,second
vbroker.firewall.first.type=PROXY
vbroker.firewall.first.ior=http://host1:9091/first.ior
vbroker.firewall.second.type=PROXY
vbroker.firewall.second.ior=http://host2:9091/second.ior

7: Security Features

Q7.1 How does GateKeeper relay IIOP/SSL connection?

GateKeeper shipped with VBJ is "security" aware, that means if Security Service is installed then all security features of GateKeeper will be turned on. GateKeeper only support IIOP/SSL for Java Application, not Java Applet. Here is one example to set GateKeeper talk with client via IIOP/SSL and IIOP to server.

vbroker.orb.dynamicLibs=com.inprise.security.ssl.Init,security.server._512.Init,com.inprise.vbroker.gatekeeper.ssl.Init
vbroker.security.peerAuthenticationMode=require_and_trust
vbroker.se.exterior.scms=ex-iiop,ex-ssl
vbroker.se.exterior.scm.ex-iiop.listener.type=Disabled-IIOP // this disables IIOP listener and force client communicates with GateKeeper only via SSL.

where server._512.Init is the initializer to install certificates and trustpoint on GateKeeper, it is one way to install certificates on GateKeeper. And because initializer also install trustpoints, GateKeeper can authentication on behalf server. Note, if multiple servers have different trustpoints, there must be multiple GateKeeper to run for each server to avoid security hole. Here is the source code of that initializer:


import java.util.*;
import com.inprise.security.ssl.*;
import com.inprise.security.util.RandomSeedGenerator;
import com.inprise.vbroker.orb.ORB;

public class Init implements com.inprise.vbroker.interceptor.ServiceLoader \{
public void init(org.omg.CORBA.ORB o) \{
final ORB orb = (ORB)o;
Current current = null;
try \{
current = CurrentHelper.narrow(
orb.resolve_initial_references("SSLCurrent"));
\}
catch (org.omg.CORBA.ORBPackage.InvalidName e) \{
System.out.println(e);
System.exit(-1);
\}

// Generate a seed for the PRNG.
RandomSeedGenerator generator = new RandomSeedGenerator();
byte[] seed = generator.getSeed();
current.setPRNGSeed(seed);
seed = null;

// Set my certificate chain, ordered from user to CA.
byte[][] certificates = \{
user_cert_1.getBytes(),
user_cert_2.getBytes(),
ca_cert.getBytes()
\};

byte[] privateKey = encrypted_private_key.getBytes();

current.setPKprincipal(certificates,privateKey,"Kevin$$$");

com.inprise.security.trust.Trustpoints tpo =current.getTrustpointsObject();

byte[][] temp_list = new byte[1][];
temp_list[0] = ca_cert.getBytes( );
tpo.addLocalTrustpoints(temp_list);

\}

public void init_complete(org.omg.CORBA.ORB orb) \{
// do nothing
\}

public void shutdown(org.omg.CORBA.ORB orb) \{
// do nothing
\}

private static String user_cert_1 =
"-----BEGIN CERTIFICATE-----n" +
"MIIBxDCCAW4CBQCtPRI3MA0GCSqGSIb3DQEBBAUAMGsxCzAJBgNVBAYTAlVTMRMwn" +
"EQYDVQQIEwpDYWxpZm9ybmlhMRIwEAYDVQQHEwlTYW4gTWF0ZW8xEDAOBgNVBAoTn" +
"B0lucHJpc2UxETAPBgNVBAsTCFNlY3VyaXR5MQ4wDAYDVQQDEwVBbmRyZTAeFw05n" +
"OTA0MTIxODM4MzZaFw0wOTA0MDkxODM4MzZaMGsxCzAJBgNVBAYTAlVTMRMwEQYDn" +
"VQQIEwpDYWxpZm9ybmlhMRIwEAYDVQQHEwlTYW4gTWF0ZW8xEDAOBgNVBAoTB0lun" +
"cHJpc2UxETAPBgNVBAsTCFNlY3VyaXR5MQ4wDAYDVQQDEwVLZXZpbjBcMA0GCSqGn" +
"SIb3DQEBAQUAA0sAMEgCQQDZXiwJ94pxiRYyDRRdIDBjGDGHsx+UKvrZvLoJWaumn" +
"8J8LC3dRMOe31yifFCsezoure/bnqh5i7gpV4RTBFiEnAgMBAAEwDQYJKoZIhvcNn" +
"AQEEBQADQQBERydPwOQ889thS0pYO6tAOI1LMFN/09g34PMi7LoDgiyi4Cc7FDZvn" +
"lcWL2Jk0C7LlgCeL4U18aFDDbJzcQul3n" +
"-----END CERTIFICATE-----";

private static String user_cert_2 =
"-----BEGIN CERTIFICATE-----n" +
"MIIB0TCCAXsCBQCsPRI3MA0GCSqGSIb3DQEBBAUAMHgxCzAJBgNVBAYTAlVTMRMwn" +
"EQYDVQQIEwpDYWxpZm9ybmlhMRIwEAYDVQQHEwlTYW4gTWF0ZW8xEDAOBgNVBAoTn" +
"B0lucHJpc2UxFDASBgNVBAsTC0RldmVsb3BtZW50MRgwFgYDVQQDEw9JbnByaXNln" +
"IERlbW8gQ0EwHhcNOTkwNDEyMTgzODM2WhcNMDkwNDA5MTgzODM2WjBrMQswCQYDn" +
"VQQGEwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTESMBAGA1UEBxMJU2FuIE1hdGVvn" +
"MRAwDgYDVQQKEwdJbnByaXNlMREwDwYDVQQLEwhTZWN1cml0eTEOMAwGA1UEAxMFn" +
"QW5kcmUwXDANBgkqhkiG9w0BAQEFAANLADBIAkEAysBe59/h7viigbcsgPK8itVPn" +
"FGY/xSvZB14tS+/KlN6SJaq8wiiXuoGuWAEygPZRpM6sLC/Ns6p10/FJhvepUwIDn" +
"AQABMA0GCSqGSIb3DQEBBAUAA0EAyokBN143FZAT0gYnMIg4UzOZmtJrwUJsI/cgn" +
"tzwcLLfFjEqlm9/b+QAJcrz994PN97ql09Goqc0a+2+ku5bC4A==n" +
"-----END CERTIFICATE-----";

private static String ca_cert =
"-----BEGIN CERTIFICATE-----n" +
"MIIB3jCCAYgCBQCrPRI3MA0GCSqGSIb3DQEBBAUAMHgxCzAJBgNVBAYTAlVTMRMwn" +
"EQYDVQQIEwpDYWxpZm9ybmlhMRIwEAYDVQQHEwlTYW4gTWF0ZW8xEDAOBgNVBAoTn" +
"B0lucHJpc2UxFDASBgNVBAsTC0RldmVsb3BtZW50MRgwFgYDVQQDEw9JbnByaXNln" +
"IERlbW8gQ0EwHhcNOTkwNDEyMTgzODM1WhcNMDkwNDA5MTgzODM1WjB4MQswCQYDn" +
"VQQGEwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTESMBAGA1UEBxMJU2FuIE1hdGVvn" +
"MRAwDgYDVQQKEwdJbnByaXNlMRQwEgYDVQQLEwtEZXZlbG9wbWVudDEYMBYGA1UEn" +
"AxMPSW5wcmlzZSBEZW1vIENBMFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAOXhYpU3n" +
"SJSfuhJoG6oiZpMcfmMQB9Y6aMsMupmf0jC6YPUr5qCkTFAUq7dZxCIouC9J9rM+n" +
"+1XfrQKghW5WWmMCAwEAATANBgkqhkiG9w0BAQQFAANBAJbNVUJfD6+n8kDLw6Fgn" +
"GnQDBvUCTO0TvXmuVIGSUCUtk5UHT5Xx5fQV58ACgmKnHYzaS9DNC8pnuQqCyXNMn" +
"6uY=n" +
"-----END CERTIFICATE-----";

private static String encrypted_private_key =
"-----BEGIN ENCRYPTED PRIVATE KEY-----n" +
"MIIBgDAaBgkqhkiG9w0BBQMwDQQIyv66vrqtEjQCAQMEggFgiakb6BJpD9f9+etBn" +
"DV9rm+MSjqHa3Mh1HzCEXsHzfR8Jr9cztszMnDQTVq8IZ3mf/a7oohfOatmQbPofn" +
"ufO838uLlk110/qKbsP7EKoxm+tqnQiMm+/YilslvpevbGgNa8DyztVT4FtgLoMDn" +
"V2Sr5cP4Ef7/wRwgz+LJY3kmMZnstwF3/s5//HGp6Lq5+bWfj8TjXCDXaWmjcNlrn" +
"DGEMesfeGaY0FCVBMNZDC1xbYrDyMfDCpBQ38ZyQ9SHiC+yjt6JDy886UVXI+0Phn" +
"66B+rA2Zg/XX+8zm6q6kO61/UKLQv50oXZ/BTz++7SJyiaZavi0CF+iiNiV6JyxJn" +
"dlMi/gpUHNhdLW7lhiDjhhr8Z1f5/ZlJsg5XCHuv/fszG9INroxCfDMhsz0+oRSjn" +
"f0SXT42fZsx/ecrRQcEcUyn61PS6BRmzj/G5xdsi3HskFfiPW3gsX0n5cFtJHiaNn" +
"5bOxqA==n" +
"-----END ENCRYPTED PRIVATE KEY-----";
\}

Q7.2: Does GateKeeper support HTTPS?

GateKeeper supports HTTPS for Java Applets only. Here is the configuration on GateKeeper:

vbroker.orb.dynamicLibs=com.inprise.security.ssl.Init, com.inprise.security.hiops.Init,security.server._512.Init,com.inprise.vbroker.gatekeeper.ssl.Init
vbroker.security.peerAuthenticationMode=require_and_trust
vbroker.se.exterior.scms=ex-iiop,ex-hiops
vbroker.se.exterior.scm.ex-iiop.listener.type=Disabled-IIOP

And here are what need to set on client applet side, note that URL naming doesn't support https prefix, so it has to be named specifically.

<param name="org.omg.CORBA.ORBClass" value="com.inprise.vbroker.orb.ORB">
<param name="vbroker.orb.dynamicLibs" value="com.inprise.security.hiops.Init">
<param name="vbroker.orb.alwaysTunnel" value="true">
<param name="vbroker.orb.alwaysProxy" value="true">
<param name="vbroker.locator.ior" value="http://<gatekeeper host>:8088/gatekeeper.ior">

Q7.3: How to install SSL certificates on GateKeeper?

There are two ways to install SSL certificates on GateKeeper, one is via Initializer, which is illustrated above.

The other way to package certificates in "wallet" and installed from GateKeeper console.Here is directory structure:

.../identities
.../identities/paul
.../identities/paul/cert1
.../identities/paul/cert2
.../identities/paul/privatekey

Then you can use GateKeeper Console to install certificates on GateKeeper.

8: Miscellaneous

Q8.1 What do I need to run GateKeeper?

GateKeeper 4.0 depends JSDK which supprot Servsupports 1.x. Users can just download JSDK2.1 from JavaSoft web site and put the servlet.jar in the CLASSPATH of GateKeeper.

I got the following exception, when I use JSDK2.1 and JDK1.1.8.
java.lang.IncompatibleClassChangeError: Unimplemented interface method
at com.inprise.vbroker.HIOP.Listener.<init>(Listener.java:81)
at com.inprise.vbroker.HIOP.Init$2.create(Init.java:24)
at com.inprise.vbroker.ProtocolEngine.GenericSCM.<init>(GenericSCM.java:60)
at com.inprise.vbroker.orb.SocketSCM.<init>(SocketSCM.java:132)
at com.inprise.vbroker.orb.ORB$4.create(ORB.java:675)
at com.inprise.vbroker.ProtocolEngine.ServerEngineImpl.<init>(Compiled Code)
at com.inprise.vbroker.ProtocolEngine.ManagerImpl.getServerEngine(ManagerImpl.java:110)
at com.inprise.vbroker.poa.POAImpl.<init>(Compiled Code)
at com.inprise.vbroker.poa.AdapterManager.vbRootPOA(AdapterManager.java:87)
at com.inprise.vbroker.poa.AdapterManager$2.resolve(AdapterManager.java:244)
at com.inprise.vbroker.interceptor.InterceptorManagerImpl$ServiceManager.resolve(InterceptorManagerImpl.java:87)
at com.inprise.vbroker.orb.ORB.resolve_initial_references(ORB.java:579)
at com.inprise.vbroker.gatekeeper.GateKeeper.start(GateKeeper.java:89)
at com.inprise.vbroker.gatekeeper.GateKeeper.start(Compiled Code)
at com.inprise.vbroker.gatekeeper.GateKeeper.main(Compiled Code)

This is because the incompatibility between JSDK2.1 ad JSDK1.2. JSDK2.1 won't run with JDK1.1.

You can download JSDK1.2 from Java Soft and use the servlet.jar of it. Then you can use both JDK1.1.8 and JDK1.2.1. If you stay with JSDK2.1, you have to run Gatekeeper with JDK1.2.1.

Q8.2: I've got binding failure running GateKeeper on Solaris?

This is because the default exterior IIOP port of GateKeeper is 683, which is restricted on Unix platform. To run GateKeeper on Solaris, users can either run GateKeeper as superuser or change the exterior IIOP port to some number bigger than 1024. Ths can be dThis the "Request Forward Service" Tab of "IIOP Proxy Services" Panel.

Q8.3: I've got exception when I use Netscape Communicator 4.6 to run applet?

I got the following exception what I use NC 4.6 to run the applet client.

java.lang.NoSuchMethodError: org.omg.CORBA.Object: method_set_policy_override ([Lorg/omg/CORBA/Policy;Lorg/omg/CORBA/SetOverrideType;)Lorg/omg/CORBA/Object;not found
at com.inprise.vbroker.firewall.BindInterceptor.bind(Compiled Code)
at com.inprise.vbroker.interceptor.ChainBindInterceptorImpl.bind(Compiled Code)
at com.inprise.vbroker.orb.DelegateImpl._bind(Compiled Code)
at com.inprise.vbroker.orb.DelegateImpl.bind(Compiled Code)
at com.inprise.vbroker.CORBA.portable.ObjectImpl._bind(Compiled Code)
at com.inprise.vbroker.orb.ORB.bind(Compiled Code)
at Bank.AccountManagerHelper.bind(Compiled Code)
at Bank.AccountManagerHelper.bind(Compiled Code)
at ClientApplet.init(Compiled Code)
at netscape.applet.DerivedAppletFrame$InitAppletEvent.dispatch(Compiled Code)
at java.awt.EventDispatchThread$EventPump.dispatchEvents(Compiled Code)
at java.awt.EventDispatchThread.run(Compiled Code)
at netscape.applet.DerivedAppletFrame$AppletEventDispatchThread.run(Compiled Code)

This is because there is a VBJ2.5 bundled with NC, which is a result of an agreement between Inprise and Netscape. This VBJ2.5 jar file also package some OMG standard interface which has been changed, that is why you see the NoSuchMethodError exception.

The way to fix the problem is to remove the VBJ2.5 jar file and then restart your browser. The jar file is at <NC installation
path>/Communicator/Program/Java/Classes/iiop10.jar

Q8.4: How can I run GateKeeper as a servlet with web server?

GateKeeper can be run as a servlet, but in this case it won't register with OSAGENT, so it can't be managed by Console.

To run GateKeeper with JWS 2.0, Here are what you need to set:
1. copy vbjorb.jar to <JWS HOME>/lib and start JWS with the following command, <JWS HOME>binhttpdnojre -javahome D:jdk1.2.2 -Dorb.omg.CORBA.ORBClass=com.inprise.vbroker.orb.ORB -Dorg.omg.CORBA.ORBSingletonClass=com.inprise.vbroker.orb.ORB
2. run <JWS HOME>binadmin.
3. double-click "Web Service" and select "Servlets" in Web Service, and double-click "Add".
Then type "gatekeeper" in Servlet Name and "com.inprise.vbroker.gatekeeper.servlet.Servlet" in Servlet Class.
4. select Yes on "Load at Startup", then add the following properties to gatekeeper servlet:

  • vbroker.gatekeeper.referenceStore = public_html/gatekeeper.ior
  • vbroker.se.exterior.scm.ex-hiop.listener.path = servlet/gatekeeper
  • vbroker.se.exterior.scm.ex-hiop.listener.port = 8080
  • vbroker.se.iiop_tp.scms = iiop_tp

and at last click Load Button.

To run GateKeeper with Inprise Application Server, here are what your need to set.

1. start ias by typinIAShe command of "<IAS HOME>binias
2. start admin tool by point browser to http://<IAS host>:9090/
3. double-click "Web Service" and select "Servlets" in Web Service, and double-click "Add".
Then type "gatekeeper" in Servlet Name and "com.inprise.vbroker.gatekeeper.servlet.Servlet" in Servlet Class.
4. select Yes on "Load at Startup", then add the following properties to gatekeeper servlet:

  • vbroker.gatekeeper.referenceStore = html/public_html/gatekeeper.ior
  • vbroker.se.exterior.scm.ex-hiop.listener.path = servlet/gatekeeper
  • vbroker.se.exterior.scm.ex-hiop.listener.port = 8080
  • vbroker.se.iiop_tp.scms = iiop_tp

Q8.5: What are the default ports GateKeeper listening on?

By default GateKeeper listens on the following port:

  • exterior IIOP port, vbroker.se.exterior.scm.ex-iiop.listener.port=683
  • exterior HIOP port, vbroker.se.exterior,scm.ex-hiop.listener.port=8088, used for HTTP tunneling and web server
  • management HTTP port, vbroker.se.iiop_tp.scm.hiop_ts.listener.port=9091, used for management
  • exterior SSL port, vbroker.se.exterior.scm.ex-ssl.listner.portlistenerf security service is turned on
  • exterior HTTPS port, vbroker.se.exterior.scm.ex-hiops.listener.port=8089, used security server is turned on.


Article originally contributed by Jimmy Maher


strdup under Turbo Vision

Written by David W1379 on . Posted in PROGRAMMING

 Technical Notes Database

TN3189C.txt   strdup under Turbo Vision
Category   :TURBO VISION
Platform    :All
Product    :TV  1.00-

Description:
strdup does not work under Turbo Vision, because strdup's allocation of 
memory does not go though global new.  The global delete operator looks 
for a signature that the global new places in the allocated block.  A 
work around is
char *strdup(char *S)
{
     return strcpy(new char[strlen(S) +1], S);
}


Reference:


7/2/98 10:43:28 AM
 

Using Bounds Checker or MemCheck with Turbo Vision

Written by Embarcadero USA on . Posted in PROGRAMMING

 Technical Notes Database

TN3188C.txt   Using Bounds Checker or MemCheck with Turbo Vision
Category   :TURBO VISION
Platform    :All
Product    :TV  1.03-

Description:

Some precautions need to be taken when using a memory check utility (such as
Bounds Checker or MemCheck) on a Turbo Vision application.
In a Turbo Vision application, the main program normall looks something like
this:
void main(void) {
  TMyApp  myapp;
  myapp.run()
}
Since the destructor of a TV object does not call shutdown(), you will have
memory leaks unless you do this:
void main(void) {               
  TMyApp *myapp;
  myapp = new TMyApp();
  myapp->run();
  destroy(myapp);
}
or
void main(void) {
  TMyApp myapp;
   myapp.run();
   myapp.shutdown();
}


Reference:


7/2/98 10:43:28 AM
 


Article originally contributed by


Protogen produces OWL projects by default

Written by Embarcadero USA on . Posted in PROGRAMMING

 Technical Notes Database

TN3181C.txt   Protogen produces OWL projects by default
Category   :OTHER
Platform    :All
Product    :BCW  3.1

Description:
Q: Why, when I use Protogen do I get " unable to find include file 
owl.h "? When I look on my hard drive I don't even have this file.
A: You have BC++ without Application Frameworks and ProtoGen is set up to
produce an OWL application, by default. The setting you want to make is in
the " Set  Compiler Options " dialog box that is presented after hitting 
" generate " ( see page 50 in the ProtoGen users guide ). Change the 
" Generate Options " setting from " Borland C++ Generation " to " ANSI C
Generation "


Reference:


7/2/98 10:43:26 AM
 


Article originally contributed by


Is there any problem running overlayed programs on

Written by Embarcadero USA on . Posted in PROGRAMMING

 Technical Notes Database

TN3182C.txt   Is there any problem running overlayed programs on
Category   :OTHER
Platform    :All
Product    :BCW  3.10-

Description:
Is there any problem running overlayed programs on a network?
VROOM applications open the executable in READ ONLY mode.  If the 
network handles this as SHAREABLE then multiple users can run the 
.EXE off the net.  This has been tested with Novell Netware and 
it works properly, but some networks have been found to not handle 
this incorrectly.


Reference:


7/2/98 10:43:26 AM
 


Article originally contributed by Borland Staff


Check out more tips and tricks in this development video: