summaryrefslogtreecommitdiffstats
path: root/java/sca/modules/host-corba
diff options
context:
space:
mode:
authorrfeng <rfeng@13f79535-47bb-0310-9956-ffa450edef68>2008-06-27 23:06:58 +0000
committerrfeng <rfeng@13f79535-47bb-0310-9956-ffa450edef68>2008-06-27 23:06:58 +0000
commit80b6d4094bb47400e8cece9aee11ecd777cdf5f8 (patch)
tree82f88eca340d34415bf7b9c4c5e104796da3fc51 /java/sca/modules/host-corba
parentf98ec827ac1e63c55a3f84178b33f36c8c752a90 (diff)
Add a simple tnameserv so that we don't have to start the external tnameserv
git-svn-id: http://svn.us.apache.org/repos/asf/tuscany@672418 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'java/sca/modules/host-corba')
-rw-r--r--java/sca/modules/host-corba/src/main/java/org/apache/tuscany/sca/host/corba/naming/NamingContextBase.java863
-rw-r--r--java/sca/modules/host-corba/src/main/java/org/apache/tuscany/sca/host/corba/naming/TransientNameServer.java140
-rw-r--r--java/sca/modules/host-corba/src/main/java/org/apache/tuscany/sca/host/corba/naming/TransientNameService.java182
-rw-r--r--java/sca/modules/host-corba/src/main/java/org/apache/tuscany/sca/host/corba/naming/TransientNamingContext.java440
-rw-r--r--java/sca/modules/host-corba/src/main/java/org/apache/tuscany/sca/host/corba/naming/TransientServiceException.java38
-rw-r--r--java/sca/modules/host-corba/src/test/java/org/apache/tuscany/sca/host/corba/testing/DefaultCorbaHostTestCase.java26
6 files changed, 1689 insertions, 0 deletions
diff --git a/java/sca/modules/host-corba/src/main/java/org/apache/tuscany/sca/host/corba/naming/NamingContextBase.java b/java/sca/modules/host-corba/src/main/java/org/apache/tuscany/sca/host/corba/naming/NamingContextBase.java
new file mode 100644
index 0000000000..aae7bbecd7
--- /dev/null
+++ b/java/sca/modules/host-corba/src/main/java/org/apache/tuscany/sca/host/corba/naming/NamingContextBase.java
@@ -0,0 +1,863 @@
+/**
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+* contributor license agreements. See the NOTICE file distributed with
+* this work for additional information regarding copyright ownership.
+* The ASF licenses this file to You under the Apache License, Version 2.0
+* (the "License"); you may not use this file except in compliance with
+* the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * @version $Rev$ $Date$
+ */
+
+package org.apache.tuscany.sca.host.corba.naming;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import org.omg.CORBA.BAD_PARAM;
+import org.omg.CORBA.CompletionStatus;
+import org.omg.CORBA.ORB;
+import org.omg.CORBA.SystemException;
+import org.omg.CosNaming.BindingType;
+import org.omg.CosNaming.BindingTypeHolder;
+import org.omg.CosNaming.NameComponent;
+import org.omg.CosNaming.NamingContext;
+import org.omg.CosNaming.NamingContextExtPOA;
+import org.omg.CosNaming.NamingContextHelper;
+import org.omg.CosNaming.NamingContextExtPackage.InvalidAddress;
+import org.omg.CosNaming.NamingContextPackage.AlreadyBound;
+import org.omg.CosNaming.NamingContextPackage.InvalidName;
+import org.omg.CosNaming.NamingContextPackage.NotFound;
+import org.omg.CosNaming.NamingContextPackage.NotFoundReason;
+import org.omg.PortableServer.POA;
+
+public abstract class NamingContextBase extends NamingContextExtPOA {
+ // the real logger backing instance. We use the interface class as the locator
+ protected static final Logger logger = Logger.getLogger(NamingContext.class.getName());
+
+ // set of URL characters that don't require escaping when encoded.
+ protected final String nonEscaped = ";/?:@&=+$;-_.!~* ()";
+ // the orb we're attached to
+ protected ORB orb;
+ // the poa we're associated with
+ protected POA poa;
+
+ /**
+ * Create a new base NamingContext (super class constructor
+ * for the derived classes).
+ *
+ * @param orb The ORB this is hosted on.
+ *
+ * @exception java.lang.Exception
+ */
+ public NamingContextBase(ORB orb, POA poa) throws java.lang.Exception {
+ super();
+ this.orb = orb;
+ this.poa = poa;
+ }
+
+ /**
+ * Bind an object to a given name.
+ *
+ * @param n An array of NameComponents that are the target name.
+ * The last element in the array is binding name for the
+ * object. The remainder of the array is the path
+ * for resolving the naming context, relative to the
+ * current context. All path contexts must already be
+ * bound in the context tree.
+ * @param obj The object to be bound.
+ *
+ * @exception org.omg.CosNaming.NamingContextPackage.NotFound
+ * @exception org.omg.CosNaming.NamingContextPackage.CannotProceed
+ * @exception org.omg.CosNaming.NamingContextPackage.InvalidName
+ * @exception org.omg.CosNaming.NamingContextPackage.AlreadyBound
+ */
+ public void bind(org.omg.CosNaming.NameComponent[] n, org.omg.CORBA.Object obj)
+ throws org.omg.CosNaming.NamingContextPackage.NotFound, org.omg.CosNaming.NamingContextPackage.CannotProceed,
+ org.omg.CosNaming.NamingContextPackage.InvalidName, org.omg.CosNaming.NamingContextPackage.AlreadyBound {
+ // perform various name validations
+ validateName(n);
+
+ logNameComponent("bind() name", n);
+
+ // do we need to push through to a deeper naming context first?
+ if (n.length > 1) {
+ // resolve the top level name to a context, and have that context
+ // resolve the rest.
+ NamingContext context = resolveContext(n[0]);
+ NameComponent[] subName = extractSubName(n);
+
+ // now pass this along to the next context for the real bind operation.
+ context.bind(subName, obj);
+ } else {
+ NameComponent name = n[0];
+ // we need the resolveObject() and bindObject() calls to be consistent, so
+ // synchronize on this
+ synchronized (this) {
+ // see if we have this bound already...can't replace these.
+ BindingTypeHolder type = new BindingTypeHolder();
+ if (resolveObject(name, type) != null) {
+ throw new AlreadyBound();
+ }
+ type.value = BindingType.nobject;
+ // ok, this is a new binding, go do it.
+ bindObject(name, obj, type);
+ }
+ }
+ }
+
+ /**
+ * Rebind an object to a given name. If an object is
+ * already bound with this name, the new object replaces
+ * the bound object's value. If no object has been
+ * bound already, this is the same as a bind operation.
+ *
+ * @param n An array of NameComponents that are the target name.
+ * The last element in the array is binding name for the
+ * object. The remainder of the array is the path
+ * for resolving the naming context, relative to the
+ * current context. All path contexts must already be
+ * bound in the context tree.
+ * @param obj The new value for this binding.
+ *
+ * @exception org.omg.CosNaming.NamingContextPackage.NotFound
+ * @exception org.omg.CosNaming.NamingContextPackage.CannotProceed
+ * @exception org.omg.CosNaming.NamingContextPackage.InvalidName
+ * @exception org.omg.CosNaming.NamingContextPackage.AlreadyBound
+ */
+ public void rebind(org.omg.CosNaming.NameComponent[] n, org.omg.CORBA.Object obj)
+ throws org.omg.CosNaming.NamingContextPackage.NotFound, org.omg.CosNaming.NamingContextPackage.CannotProceed,
+ org.omg.CosNaming.NamingContextPackage.InvalidName {
+ // perform various name validations
+ validateName(n);
+
+ logNameComponent("rebind() name", n);
+
+ // do we need to push through to a deeper naming context first?
+ if (n.length > 1) {
+ // resolve the top level name to a context, and have that context
+ // resolve the rest.
+ NamingContext context = resolveContext(n[0]);
+ NameComponent[] subName = extractSubName(n);
+
+ // now pass this along to the next context for the real bind operation.
+ context.rebind(subName, obj);
+ } else {
+ NameComponent name = n[0];
+ // we need the resolveObject() and bindObject() calls to be consistent, so
+ // synchronize on this
+ synchronized (this) {
+ // see if we have this bound already...can't replace these.
+ BindingTypeHolder type = new BindingTypeHolder();
+ // for a rebind, we must have an object, and it must be a real object
+ if (resolveObject(name, type) != null) {
+ // it has to resolve to a real object. If it is a naming context,
+ // then this is the wrong binding operation.
+ if (type.value.value() == BindingType._ncontext) {
+ throw new NotFound(NotFoundReason.not_object, n);
+ }
+ // safe to unbind
+ unbindObject(name);
+ }
+ type.value = BindingType.nobject;
+ // now bind this object
+ bindObject(name, obj, type);
+ }
+ }
+ }
+
+ /**
+ * Bind a new context to a given name.
+ *
+ * @param n An array of NameComponents that are the target name.
+ * The last element in the array is binding name for the
+ * object. The remainder of the array is the path
+ * for resolving the naming context, relative to the
+ * current context. All path contexts must already be
+ * bound in the context tree.
+ * @param nc The new naming context added to the tree.
+ *
+ * @exception org.omg.CosNaming.NamingContextPackage.NotFound
+ * @exception org.omg.CosNaming.NamingContextPackage.CannotProceed
+ * @exception org.omg.CosNaming.NamingContextPackage.InvalidName
+ * @exception org.omg.CosNaming.NamingContextPackage.AlreadyBound
+ */
+ public void bind_context(org.omg.CosNaming.NameComponent[] n, org.omg.CosNaming.NamingContext nc)
+ throws org.omg.CosNaming.NamingContextPackage.NotFound, org.omg.CosNaming.NamingContextPackage.CannotProceed,
+ org.omg.CosNaming.NamingContextPackage.InvalidName, org.omg.CosNaming.NamingContextPackage.AlreadyBound {
+ // perform various name validations
+ validateName(n);
+
+ logNameComponent("bind_context() name", n);
+
+ // do we need to push through to a deeper naming context first?
+ if (n.length > 1) {
+ // resolve the top level name to a context, and have that context
+ // resolve the rest.
+ NamingContext context = resolveContext(n[0]);
+ NameComponent[] subName = extractSubName(n);
+
+ // now pass this along to the next context for the real bind operation.
+ context.bind_context(subName, nc);
+ } else {
+ NameComponent name = n[0];
+ // we need the resolveObject() and bindObject() calls to be consistent, so
+ // synchronize on this
+ synchronized (this) {
+ // see if we have this bound already...can't replace these.
+ BindingTypeHolder type = new BindingTypeHolder();
+ if (resolveObject(name, type) != null) {
+ throw new AlreadyBound();
+ }
+ type.value = BindingType.ncontext;
+ // ok, this is a new binding, go do it.
+ bindObject(name, nc, type);
+ }
+ }
+ }
+
+ /**
+ * Rebind a context to a given name. If a context is
+ * already bound with this name, the new context replaces
+ * the existing context. If no context has been
+ * bound already, this is the same as a bind operation.
+ *
+ * @param n An array of NameComponents that are the target name.
+ * The last element in the array is binding name for the
+ * object. The remainder of the array is the path
+ * for resolving the naming context, relative to the
+ * current context. All path contexts must already be
+ * bound in the context tree.
+ * @param nc The new context to be bound with the name.
+ *
+ * @exception org.omg.CosNaming.NamingContextPackage.NotFound
+ * @exception org.omg.CosNaming.NamingContextPackage.CannotProceed
+ * @exception org.omg.CosNaming.NamingContextPackage.InvalidName
+ * @exception org.omg.CosNaming.NamingContextPackage.AlreadyBound
+ */
+ public void rebind_context(org.omg.CosNaming.NameComponent[] n, org.omg.CosNaming.NamingContext nc)
+ throws org.omg.CosNaming.NamingContextPackage.NotFound, org.omg.CosNaming.NamingContextPackage.CannotProceed,
+ org.omg.CosNaming.NamingContextPackage.InvalidName {
+ // perform various name validations
+ validateName(n);
+
+ logNameComponent("rebind_context() name", n);
+
+ // do we need to push through to a deeper naming context first?
+ if (n.length > 1) {
+ // resolve the top level name to a context, and have that context
+ // resolve the rest.
+ NamingContext context = resolveContext(n[0]);
+ NameComponent[] subName = extractSubName(n);
+
+ // now pass this along to the next context for the real bind operation.
+ context.rebind_context(subName, nc);
+ } else {
+ NameComponent name = n[0];
+ // we need the resolveObject() and bindObject() calls to be consistent, so
+ // synchronize on this
+ synchronized (this) {
+ // see if we have this bound already...can't replace these.
+ BindingTypeHolder type = new BindingTypeHolder();
+ // for a rebind, we must have an object, and it must be a real object
+ if (resolveObject(name, type) != null) {
+ // it has to resolve to a real object. If it is a naming context,
+ // then this is the wrong binding operation.
+ if (type.value.value() != BindingType._ncontext) {
+ throw new NotFound(NotFoundReason.not_context, n);
+ }
+ // safe to unbind
+ unbindObject(name);
+ }
+ type.value = BindingType.ncontext;
+ // now bind this object
+ bindObject(name, nc, type);
+ }
+ }
+ }
+
+ /**
+ * Resolve an an entry in the context tree. The
+ * resolved object may be a bound object or another
+ * NamingContext. If the named entry is not found,
+ * a NotFound exception is thrown.
+ *
+ * @param n An array of NameComponents that are the target name.
+ * The last element in the array is binding name for the
+ * object. The remainder of the array is the path
+ * for resolving the naming context, relative to the
+ * current context. All path contexts must already be
+ * bound in the context tree.
+ *
+ * @return The object bound at the indicated location.
+ * @exception org.omg.CosNaming.NamingContextPackage.NotFound
+ * @exception org.omg.CosNaming.NamingContextPackage.CannotProceed
+ * @exception org.omg.CosNaming.NamingContextPackage.InvalidName
+ * @exception org.omg.CosNaming.NamingContextPackage.AlreadyBound
+ */
+ public org.omg.CORBA.Object resolve(org.omg.CosNaming.NameComponent[] n)
+ throws org.omg.CosNaming.NamingContextPackage.NotFound, org.omg.CosNaming.NamingContextPackage.CannotProceed,
+ org.omg.CosNaming.NamingContextPackage.InvalidName {
+ // perform various name validations
+ validateName(n);
+
+ logNameComponent("resolve() name", n);
+
+ // do we need to push through to a deeper naming context first?
+ if (n.length > 1) {
+ // resolve the top level name to a context, and have that context
+ // resolve the rest.
+ NamingContext context = resolveContext(n[0]);
+ NameComponent[] subName = extractSubName(n);
+
+ // now pass this along to the next context for the real bind operation.
+ return context.resolve(subName);
+ } else {
+ NameComponent name = n[0];
+ // see if we have this bound already...can't replace these.
+ BindingTypeHolder type = new BindingTypeHolder();
+ org.omg.CORBA.Object obj = resolveObject(name, type);
+ if (obj == null) {
+ // Object was not found
+ throw new NotFound(NotFoundReason.missing_node, n);
+ }
+ return obj;
+ }
+ }
+
+ /**
+ * Remove an entry from the context tree. The
+ * target object may be a bound object or another
+ * NamingContext. If the named entry is not found,
+ * a NotFound exception is thrown.
+ *
+ * @param n An array of NameComponents that are the target name.
+ * The last element in the array is binding name for the
+ * object. The remainder of the array is the path
+ * for resolving the naming context, relative to the
+ * current context. All path contexts must already be
+ * bound in the context tree.
+ *
+ * @exception org.omg.CosNaming.NamingContextPackage.NotFound
+ * @exception org.omg.CosNaming.NamingContextPackage.CannotProceed
+ * @exception org.omg.CosNaming.NamingContextPackage.InvalidName
+ * @exception org.omg.CosNaming.NamingContextPackage.AlreadyBound
+ */
+ public void unbind(org.omg.CosNaming.NameComponent[] n) throws org.omg.CosNaming.NamingContextPackage.NotFound,
+ org.omg.CosNaming.NamingContextPackage.CannotProceed, org.omg.CosNaming.NamingContextPackage.InvalidName {
+ // perform various name validations
+ validateName(n);
+
+ logNameComponent("unbind() name", n);
+
+ // do we need to push through to a deeper naming context first?
+ if (n.length > 1) {
+ // resolve the top level name to a context, and have that context
+ // resolve the rest.
+ NamingContext context = resolveContext(n[0]);
+ NameComponent[] subName = extractSubName(n);
+
+ // now pass this along to the next context for the real bind operation.
+ context.unbind(subName);
+ } else {
+ NameComponent name = n[0];
+ synchronized (this) {
+ // see if we have this bound already...can't replace these.
+ BindingTypeHolder type = new BindingTypeHolder();
+ org.omg.CORBA.Object obj = unbindObject(name);
+ if (obj == null) {
+ // Object was not found
+ throw new NotFound(NotFoundReason.missing_node, n);
+ }
+ }
+ }
+ }
+
+ /**
+ * Create a new context and bind it in at the target
+ * location.
+ *
+ * @param n An array of NameComponents that are the target name.
+ * The last element in the array is binding name for the
+ * object. The remainder of the array is the path
+ * for resolving the naming context, relative to the
+ * current context. All path contexts must already be
+ * bound in the context tree.
+ *
+ * @return The newly created context.
+ * @exception org.omg.CosNaming.NamingContextPackage.NotFound
+ * @exception org.omg.CosNaming.NamingContextPackage.CannotProceed
+ * @exception org.omg.CosNaming.NamingContextPackage.InvalidName
+ * @exception org.omg.CosNaming.NamingContextPackage.AlreadyBound
+ */
+ public synchronized org.omg.CosNaming.NamingContext bind_new_context(org.omg.CosNaming.NameComponent[] n)
+ throws org.omg.CosNaming.NamingContextPackage.NotFound, org.omg.CosNaming.NamingContextPackage.AlreadyBound,
+ org.omg.CosNaming.NamingContextPackage.CannotProceed, org.omg.CosNaming.NamingContextPackage.InvalidName {
+ logNameComponent("bind_new_context() name", n);
+
+ NamingContext context = new_context();
+ try {
+ bind_context(n, context);
+ NamingContext returnContext = context;
+ // transfer this to another variable so the finally block doesn't try to destroy this.
+ context = null;
+ return returnContext;
+ } finally {
+ // if there is a bind failure on this, we need to ensure the context has
+ // an opportunity to clean up any of its resources.
+ if (context != null) {
+ try {
+ context.destroy();
+ } catch (org.omg.CosNaming.NamingContextPackage.NotEmpty e) {
+ // new contexts should be empty.
+ }
+ }
+ }
+ }
+
+ /**
+ * Convert an array of NameComponents into the string
+ * form of a context name.
+ *
+ * @param n The array of NameComponents to convert.
+ *
+ * @return The context name, in string form.
+ * @exception org.omg.CosNaming.NamingContextPackage.InvalidName
+ */
+ public String to_string(org.omg.CosNaming.NameComponent[] n)
+ throws org.omg.CosNaming.NamingContextPackage.InvalidName {
+ validateName(n);
+
+ logNameComponent("to_string() name", n);
+
+ // convert the first part of the name
+ StringBuffer value = new StringBuffer();
+ ;
+ // convert the first component, then build up from there.
+ nameToString(n[0], value);
+
+ // the remainder need to get a separator
+ for (int i = 1; i < n.length; i++) {
+ value.append('/');
+ nameToString(n[i], value);
+ }
+ return value.toString();
+ }
+
+ /**
+ * Perform the reverse operation of the to_string() method,
+ * parsing a String context name into an array of
+ * NameComponents.
+ *
+ * @param sn The string form of the name.
+ *
+ * @return An array of NameComponents parsed from the String name.
+ * @exception org.omg.CosNaming.NamingContextPackage.InvalidName
+ */
+ public org.omg.CosNaming.NameComponent[] to_name(String sn)
+ throws org.omg.CosNaming.NamingContextPackage.InvalidName {
+ // must have a argument to parse
+ if (sn == null || sn.length() == 0) {
+ throw new InvalidName();
+ }
+
+ List components = new ArrayList();
+
+ StringBuffer component = new StringBuffer();
+
+ int index = 0;
+ String id = null;
+ String kind = null;
+ while (index < sn.length()) {
+ char ch = sn.charAt(index++);
+
+ // found an escape character or a delimiter?
+ if (ch == '\\') {
+ // nothing after the escape? Trouble
+ if (index >= sn.length()) {
+ throw new InvalidName();
+ }
+ // get the next character
+ ch = sn.charAt(index++);
+ component.append(ch);
+ }
+ // we need to process the periods here, to avoid getting
+ // mixed up with unescaped periods.
+ else if (ch == '.') {
+ // already seen a period while scanning? That's not allowed
+ if (id != null) {
+ throw new InvalidName();
+ }
+ // pull off the id piece and reset the buffer
+ id = component.toString();
+ component.setLength(0);
+ }
+ // found a component delimiter?
+ else if (ch == '/') {
+ // not seen a id/kind separator yet? This is an id with no kind
+ if (id == null) {
+ id = component.toString();
+ kind = "";
+ } else {
+ // we have an id already, pull off the kind
+ kind = component.toString();
+ }
+ // add the parsed name component
+ components.add(new NameComponent(id, kind));
+ // make sure these are all reset after pulling off a component
+ component.setLength(0);
+ id = null;
+ kind = null;
+ } else {
+ component.append(ch);
+ }
+ }
+
+ // parse the last section
+ // not seen a id/kind separator yet? This is an id with no kind
+ if (id == null) {
+ id = component.toString();
+ kind = "";
+ } else {
+ // we have an id already, pull off the kind
+ kind = component.toString();
+ }
+ // add the parsed name component
+ components.add(new NameComponent(id, kind));
+
+ // and turn this into a component array
+ return (NameComponent[])components.toArray(new NameComponent[components.size()]);
+ }
+
+ /**
+ * Create a URL name for accessing a component by name. The
+ * URL will have a corbaname: protocol.
+ *
+ * @param addr The address location for the naming service used
+ * to resolve the object. This is in "host:port" form,
+ * just line a corbaloc: URL.
+ * @param sn The string mae of the target object.
+ *
+ * @return A URL for accessing this object, in String form.
+ * @exception org.omg.CosNaming.NamingContextExtPackage.InvalidAddress
+ * @exception org.omg.CosNaming.NamingContextPackage.InvalidName
+ */
+ public String to_url(String addr, String sn) throws org.omg.CosNaming.NamingContextExtPackage.InvalidAddress,
+ org.omg.CosNaming.NamingContextPackage.InvalidName {
+ // basic validation
+ if (addr == null || addr.length() == 0) {
+ throw new InvalidAddress();
+ }
+
+ if (sn == null || sn.length() == 0) {
+ throw new InvalidName();
+ }
+
+ // TODO: What validation, if any, needs to be done here?
+ return "corbaname:" + addr + "#" + encodeRFC2396Name(sn);
+ }
+
+ /**
+ * Resolve a bound object or context using a name
+ * in String form.
+ *
+ * @param n The string name of the object context. This must
+ * be a form parseable by to_name().
+ *
+ * @return The bound object or context.
+ * @exception org.omg.CosNaming.NamingContextPackage.NotFound
+ * @exception org.omg.CosNaming.NamingContextPackage.CannotProceed
+ * @exception org.omg.CosNaming.NamingContextPackage.InvalidName
+ */
+ public org.omg.CORBA.Object resolve_str(String n) throws org.omg.CosNaming.NamingContextPackage.NotFound,
+ org.omg.CosNaming.NamingContextPackage.CannotProceed, org.omg.CosNaming.NamingContextPackage.InvalidName {
+ // this is just a simple convenience method
+ return resolve(to_name(n));
+ }
+
+ // abstract methods that are part of the NamingContext interface that need to be
+ // implemented by the subclasses.
+
+ /**
+ * Create a new context of the same type as the
+ * calling context.
+ *
+ * @return A new NamingContext item.
+ * @exception org.omg.CosNaming.NamingContextPackage.NotFound
+ * @exception SystemException
+ */
+ public abstract org.omg.CosNaming.NamingContext new_context() throws SystemException;
+
+ /**
+ * Destroy a context. This method should clean up
+ * any backing resources associated with the context.
+ *
+ * @exception org.omg.CosNaming.NamingContextPackage.NotEmpty
+ */
+ public abstract void destroy() throws org.omg.CosNaming.NamingContextPackage.NotEmpty;
+
+ /**
+ * Create a list of bound objects an contexts contained
+ * within this context.
+ *
+ * @param how_many The count of elements to return as a BindingList.
+ * @param bl A holder element for returning the source binding list.
+ * @param bi A holder for returning a BindingIterator. Any extra
+ * elements not returned in the BindingList are returned
+ * in the BindingIterator.
+ *
+ * @exception SystemException
+ */
+ public abstract void list(int how_many,
+ org.omg.CosNaming.BindingListHolder bl,
+ org.omg.CosNaming.BindingIteratorHolder bi) throws SystemException;
+
+ // abstract methods for the sub class to implement
+
+ /**
+ * Resolve an object in this context (single level
+ * resolution).
+ *
+ * @param n The name of the target object.
+ * @param type A type holder for returning the bound object type
+ * information.
+ *
+ * @return The bound object. Returns null if the object does not
+ * exist in the context.
+ * @exception SystemException
+ */
+ protected abstract org.omg.CORBA.Object resolveObject(NameComponent n, BindingTypeHolder type)
+ throws SystemException;
+
+ /**
+ * Bind an object into the current context. This can
+ * be either an object or a naming context.
+ *
+ * @param n The single-level name of the target object.
+ * @param obj The object or context to be bound.
+ * @param type
+ *
+ * @exception SystemException
+ */
+ protected abstract void bindObject(NameComponent n, org.omg.CORBA.Object obj, BindingTypeHolder type)
+ throws SystemException;
+
+ /**
+ * Unbind an object from the current context.
+ *
+ * @param n The name of the target object (single level).
+ *
+ * @return The object associated with the binding. Returns null
+ * if there was no binding currently associated with this
+ * name.
+ * @exception SystemException
+ */
+ protected abstract org.omg.CORBA.Object unbindObject(NameComponent n) throws SystemException;
+
+ // implementation specific routines
+
+ /**
+ * Resolve a name to a context object stored that has
+ * already been stored in this context. Throws an exception
+ * if the name cannot be resolved or if the resolved
+ * object is not a naming context.
+ *
+ * @param name The target name.
+ *
+ * @return The resolved NamingContext object.
+ * @exception org.omg.CosNaming.NamingContextPackage.NotFound
+ */
+ protected synchronized NamingContext resolveContext(NameComponent name)
+ throws org.omg.CosNaming.NamingContextPackage.NotFound {
+ BindingTypeHolder type = new BindingTypeHolder();
+ // Resolve this to an object. We must be able to resolve this.
+ org.omg.CORBA.Object resolvedReference = resolveObject(name, type);
+ if (resolvedReference == null) {
+ throw new NotFound(NotFoundReason.missing_node, new NameComponent[] {name});
+ }
+
+ // it has to resolve to a naming context
+ if (type.value.value() != BindingType._ncontext) {
+ throw new NotFound(NotFoundReason.not_context, new NameComponent[] {name});
+ }
+
+ // in theory, this is a naming context. Narrow it an return. Any
+ // errors just become a NotFound exception
+ try {
+ return NamingContextHelper.narrow(resolvedReference);
+ } catch (org.omg.CORBA.BAD_PARAM ex) {
+ throw new NotFound(NotFoundReason.not_context, new NameComponent[] {name});
+ }
+ }
+
+ /**
+ * Extract the tail portion of a name. This is used
+ * to strip off the first name element so we can recurse
+ * on the name resolutions with a resolved context.
+ *
+ * @param name The current name array (this MUST have 2 or more
+ * elements).
+ *
+ * @return An array of NameComponent items that is one element
+ * smaller than the argument array, with the elements
+ * shifted over.
+ */
+ protected NameComponent[] extractSubName(NameComponent[] name) {
+ NameComponent[] subName = new NameComponent[name.length - 1];
+ System.arraycopy(name, 1, subName, 0, name.length - 1);
+ return subName;
+ }
+
+ /**
+ * Perform common name validity checking.
+ *
+ * @param n The NameComponent array to check.
+ *
+ * @exception InvalidName
+ */
+ protected void validateName(NameComponent[] n) throws InvalidName {
+ // perform various name validations
+ if (n == null) {
+ throw new BAD_PARAM(27 | org.omg.CORBA.OMGVMCID.value, CompletionStatus.COMPLETED_NO);
+ }
+
+ // Valid name?
+ if (n.length < 1) {
+ throw new InvalidName();
+ }
+
+ // we have at least one name, so validate the toplevel item
+ NameComponent name = n[0];
+
+ // more name validation
+ if (name.id.length() == 0 && name.kind.length() == 0) {
+ throw new InvalidName();
+ }
+ }
+
+ /**
+ * Convert a NameComponent item into a string form,
+ * appending it to a StringBuffer.
+ *
+ * @param name The source NameComponent.
+ * @param out The StringBuffer location used to store the name
+ * value (appended to the end).
+ */
+ protected void nameToString(NameComponent name, StringBuffer out) {
+ // if the id is null, then we base off of the kind.
+ if (name.id == null || name.id.length() == 0) {
+ out.append(".");
+ // true null name element? That displays as a "."
+ if (name.kind != null && name.kind.length() != 0) {
+ escapeName(name.kind, out);
+ }
+ } else {
+ // escape the name
+ escapeName(name.id, out);
+ // have a kind qualifier to add on?
+ if (name.kind != null && name.kind.length() != 0) {
+ out.append(".");
+ escapeName(name.kind, out);
+ }
+ }
+ }
+
+ /**
+ * Process a name or kind element of a NameComponent,
+ * adding escape characters for '.' or '/' characters
+ * that might appear in the name.
+ *
+ * @param name The name element to process.
+ * @param out The StringBuffer to copy the escaped name into.
+ */
+ protected void escapeName(String name, StringBuffer out) {
+ // no characters requiring escapes (common)?
+ // use this directly
+ if (name.indexOf('.') == -1 && name.indexOf('/') == -1) {
+ out.append(name);
+ } else {
+ // scan the string adding the escapes
+ for (int i = 0; i < name.length(); i++) {
+ char ch = name.charAt(i);
+ if (ch == '.' || ch == '/') {
+ out.append('/');
+ }
+ out.append(ch);
+ }
+ }
+ }
+
+ /**
+ * Perform RFC 2396 escape encoding of a name value.
+ *
+ * @param name The input name value.
+ *
+ * @return An encoded name, with special characters converted
+ * into a hex encoded value.
+ */
+ protected String encodeRFC2396Name(String name) {
+ StringBuffer value = new StringBuffer();
+
+ for (int i = 0; i < name.length(); i++) {
+ char ch = name.charAt(i);
+
+ // Alphanumerics and the "acceptable" set of special characters just get copied
+ // without encoding.
+ if (Character.isLetterOrDigit(ch) || nonEscaped.indexOf(ch) != -1) {
+ value.append(ch);
+ } else {
+ // this gets converted into a hex value, marked by "%".
+ value.append('%');
+ value.append(Integer.toHexString((int)ch));
+ }
+ }
+ return value.toString();
+ }
+
+ /**
+ * Test if debug logging is currently available.
+ *
+ * @return True if debug level (FINE) logging is currently turned on.
+ */
+ protected boolean isDebugEnabled() {
+ return logger.isLoggable(Level.FINE);
+ }
+
+ /**
+ * Log a line of debug output
+ *
+ * @param message The message to log
+ */
+ protected void debug(String message) {
+ logger.fine(message);
+ }
+
+ /**
+ * Log the name components passed in for a request.
+ *
+ * @param message A message describing the request context.
+ * @param n The array of name components.
+ */
+ protected void logNameComponent(String message, NameComponent[] n) {
+ if (isDebugEnabled()) {
+ debug(message);
+ for (int i = 0; i < n.length; i++) {
+ debug(" NameComponent " + i + " id=" + n[i].id + " kind=" + n[i].kind);
+ }
+ }
+ }
+
+}
diff --git a/java/sca/modules/host-corba/src/main/java/org/apache/tuscany/sca/host/corba/naming/TransientNameServer.java b/java/sca/modules/host-corba/src/main/java/org/apache/tuscany/sca/host/corba/naming/TransientNameServer.java
new file mode 100644
index 0000000000..4b975fbfba
--- /dev/null
+++ b/java/sca/modules/host-corba/src/main/java/org/apache/tuscany/sca/host/corba/naming/TransientNameServer.java
@@ -0,0 +1,140 @@
+/**
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+* contributor license agreements. See the NOTICE file distributed with
+* this work for additional information regarding copyright ownership.
+* The ASF licenses this file to You under the Apache License, Version 2.0
+* (the "License"); you may not use this file except in compliance with
+* the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * @version $Rev$ $Date$
+ */
+package org.apache.tuscany.sca.host.corba.naming;
+
+import org.omg.CORBA.ORB;
+
+/**
+ * A stand-alone naming service launchable from a command line.
+ */
+public class TransientNameServer {
+ private final TransientNameService service;
+ private final Object flag = new Object();
+ private Boolean started;
+
+ public TransientNameServer(String host, int port, String serviceName) {
+ this.service = new TransientNameService(host, port, serviceName);
+ }
+
+ public ORB getORB() {
+ return service.getORB();
+ }
+
+ public Thread start() {
+ Thread t = new Thread() {
+ public void run() {
+ ORB orb = null;
+ synchronized (flag) {
+ try {
+ service.run();
+ orb = service.createdOrb;
+ started = Boolean.TRUE;
+ } catch (Throwable e) {
+ started = Boolean.FALSE;
+ throw new IllegalStateException(e);
+ } finally {
+ flag.notifyAll();
+ }
+ }
+ orb.run();
+ /*
+ // now we just sit and wait here.
+ synchronized (service) {
+ try {
+ service.wait();
+ } catch (InterruptedException e) {
+ throw new IllegalStateException(e);
+ }
+ }
+ */
+ }
+ };
+ t.start();
+ checkState();
+ return t.isAlive() ? t : null;
+ }
+
+ private Boolean checkState() {
+ synchronized (flag) {
+ while (started == null) {
+ try {
+ flag.wait();
+ } catch (InterruptedException e) {
+ return null;
+ }
+ }
+ return started;
+ }
+ }
+
+ public void stop() {
+ if (started == Boolean.TRUE) {
+ service.destroy();
+ }
+ }
+
+ /**
+ * Launch a name service as a stand alone process. The
+ * Host, port, and service name are controlled using
+ * program arguments.
+ *
+ * @param args The array of arguments for tailoring the service.
+ *
+ * @exception Exception
+ */
+ public static void main(String args[]) throws Exception {
+ int port = TransientNameService.DEFAULT_SERVICE_PORT;
+ String host = TransientNameService.DEFAULT_SERVICE_HOST;
+ String serviceName = TransientNameService.DEFAULT_SERVICE_NAME;
+
+ // see if we have
+ for (int i = 0; i < args.length; i++) {
+ if (args[i].equals("-ORBInitialPort")) {
+ i++;
+ if (i < args.length) {
+ port = java.lang.Integer.parseInt(args[i]);
+ } else {
+ throw new IllegalArgumentException("Invalid -ORBInitialPort option");
+ }
+ } else if (args[i].equals("-ORBInitialHost")) {
+ i++;
+ if (i < args.length) {
+ host = args[i];
+ } else {
+ throw new IllegalArgumentException("Invalid -ORBInitialHost option");
+ }
+ } else if (args[i].equals("-ORBServiceName")) {
+ i++;
+ if (i < args.length) {
+ serviceName = args[i];
+ } else {
+ throw new IllegalArgumentException("Invalid -ORBServiceName option");
+ }
+ }
+
+ }
+ // create a services, and just spin it off. We wait forever after that.
+ TransientNameServer server = new TransientNameServer(host, port, serviceName);
+ server.start().join();
+ }
+
+}
diff --git a/java/sca/modules/host-corba/src/main/java/org/apache/tuscany/sca/host/corba/naming/TransientNameService.java b/java/sca/modules/host-corba/src/main/java/org/apache/tuscany/sca/host/corba/naming/TransientNameService.java
new file mode 100644
index 0000000000..cf99fa908c
--- /dev/null
+++ b/java/sca/modules/host-corba/src/main/java/org/apache/tuscany/sca/host/corba/naming/TransientNameService.java
@@ -0,0 +1,182 @@
+/**
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+* contributor license agreements. See the NOTICE file distributed with
+* this work for additional information regarding copyright ownership.
+* The ASF licenses this file to You under the Apache License, Version 2.0
+* (the "License"); you may not use this file except in compliance with
+* the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * @version $Rev$ $Date$
+ */
+package org.apache.tuscany.sca.host.corba.naming;
+
+import java.lang.reflect.Method;
+import java.util.Properties;
+
+import org.omg.CORBA.ORB;
+import org.omg.CORBA.Policy;
+import org.omg.PortableServer.IdAssignmentPolicyValue;
+import org.omg.PortableServer.LifespanPolicyValue;
+import org.omg.PortableServer.POA;
+import org.omg.PortableServer.ServantRetentionPolicyValue;
+
+/**
+ * A transient name service attached to an ORB. This
+ * class manages all of the housekeeping for creating a
+ * TransientNamingContext and a exposing it using an
+ * ORB.
+ */
+public class TransientNameService {
+ // the default registered name service
+ static public final String DEFAULT_SERVICE_NAME = "TNameService";
+ // the default listening port
+ static public final int DEFAULT_SERVICE_PORT = 900;
+ // the default host name
+ static public final String DEFAULT_SERVICE_HOST = "localhost";
+
+ // the service root context
+ protected TransientNamingContext initialContext;
+ // initial listening port
+ protected int port;
+ // initial listening host
+ protected String host;
+ // the service name (used for registing for the corbaloc:: URL name
+ protected String serviceName;
+ // the orb instance we're running on
+ protected ORB createdOrb;
+
+
+ /**
+ * Create a new TransientNameService, using all default
+ * attributes.
+ */
+ public TransientNameService() {
+ this(DEFAULT_SERVICE_HOST, DEFAULT_SERVICE_PORT, DEFAULT_SERVICE_NAME);
+ }
+
+ /**
+ * Create a default-named name service using the specified
+ * host and port parameters.
+ *
+ * @param host The host to expose this under.
+ * @param port The initial listening port.
+ */
+ public TransientNameService(String host, int port) {
+ this(host, port, DEFAULT_SERVICE_NAME);
+ }
+
+ /**
+ * Create a specifically-named name service using the specified
+ * host and port parameters.
+ *
+ * @param host The host to expose this under.
+ * @param port The initial listening port.
+ * @param name The name to register this service under using the
+ * BootManager.
+ */
+ public TransientNameService(String host, int port, String name) {
+ this.port = port;
+ this.host = host;
+ this.serviceName = name;
+ }
+
+ /**
+ * Start up the name service, including creating an
+ * ORB instance to expose it under.
+ *
+ * @exception TransientServiceException
+ */
+ public void run() throws TransientServiceException {
+ // Create an ORB object
+ Properties props = new Properties();
+ props.putAll(System.getProperties());
+
+ String portStr = String.valueOf(port);
+ props.put("org.omg.CORBA.ORBServerId", "1000000");
+ props.put("org.omg.CORBA.ORBInitialHost", host);
+ props.put("org.omg.CORBA.ORBInitialPort", portStr);
+
+ // STEP 1: Set ORBPeristentServerPort property
+ // Set the proprietary property to open up a port to listen to
+ // INS requests.
+
+ props.put("com.sun.CORBA.POA.ORBPersistentServerPort", portStr);
+ props.put("com.ibm.CORBA.ListenerPort", portStr);
+ props.put("gnu.CORBA.ListenerPort", portStr);
+ // props.put("org.omg.CORBA.ORBClass", "org.apache.yoko.orb.CORBA.ORB");
+ // props.put("org.omg.CORBA.ORBSingletonClass", "org.apache.yoko.orb.CORBA.ORBSingleton");
+ props.put("yoko.orb.oa.endpoint", "iiop --host " + host + " --port " + port);
+ props.put("yoko.orb.poamanager.TNameService.endpoint", "iiop --host " + host);
+
+ String[] args = {"-ORBInitialHost", host, "-ORBInitialPort", "" + port};
+ createdOrb = ORB.init(args, props);
+
+ // now initialize the service
+ initialize(createdOrb);
+
+ }
+
+ /**
+ * Initialize a transient name service on a specific
+ * ORB.
+ *
+ * @param orb The ORB hosting the service.
+ *
+ * @exception TransientServiceException
+ */
+ public void initialize(ORB orb) throws TransientServiceException {
+ try {
+ // get the root POA. We're going to re
+ POA rootPOA = (POA)orb.resolve_initial_references("RootPOA");
+ rootPOA.the_POAManager().activate();
+
+ // we need to create a POA to manage this named instance, and then activate
+ // a context on it.
+ Policy[] policy = new Policy[3];
+ policy[0] = rootPOA.create_lifespan_policy(LifespanPolicyValue.TRANSIENT);
+ policy[1] = rootPOA.create_id_assignment_policy(IdAssignmentPolicyValue.SYSTEM_ID);
+ policy[2] = rootPOA.create_servant_retention_policy(ServantRetentionPolicyValue.RETAIN);
+
+ POA nameServicePOA = rootPOA.create_POA("TNameService", null, policy);
+ nameServicePOA.the_POAManager().activate();
+
+ // create our initial context, and register that with the ORB as the name service
+ initialContext = new TransientNamingContext(orb, nameServicePOA);
+ org.omg.CORBA.Object context = initialContext.getRootContext();
+ Method method =
+ orb.getClass().getMethod("register_initial_reference", String.class, org.omg.CORBA.Object.class);
+ method.invoke(orb, serviceName, context);
+ method.invoke(orb, "NamingService", context);
+ method.invoke(orb, "NameService", context);
+ } catch (Exception e) {
+ throw new TransientServiceException("Unable to initialize name service", e);
+ }
+ }
+
+ /**
+ * Destroy the created service.
+ */
+ public void destroy() {
+ // only destroy this if we created the orb instance.
+ if (createdOrb != null) {
+ createdOrb.destroy();
+ createdOrb = null;
+ }
+ }
+
+ public ORB getORB() {
+ return createdOrb;
+ }
+
+}
diff --git a/java/sca/modules/host-corba/src/main/java/org/apache/tuscany/sca/host/corba/naming/TransientNamingContext.java b/java/sca/modules/host-corba/src/main/java/org/apache/tuscany/sca/host/corba/naming/TransientNamingContext.java
new file mode 100644
index 0000000000..236bf6de90
--- /dev/null
+++ b/java/sca/modules/host-corba/src/main/java/org/apache/tuscany/sca/host/corba/naming/TransientNamingContext.java
@@ -0,0 +1,440 @@
+/**
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * @version $Rev$ $Date$
+ */
+
+package org.apache.tuscany.sca.host.corba.naming;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+
+import org.omg.CORBA.INTERNAL;
+import org.omg.CORBA.ORB;
+import org.omg.CORBA.SystemException;
+import org.omg.CosNaming.Binding;
+import org.omg.CosNaming.BindingHolder;
+import org.omg.CosNaming.BindingIteratorHelper;
+import org.omg.CosNaming.BindingIteratorPOA;
+import org.omg.CosNaming.BindingType;
+import org.omg.CosNaming.BindingTypeHolder;
+import org.omg.CosNaming.NameComponent;
+import org.omg.CosNaming.NamingContext;
+import org.omg.CosNaming.NamingContextHelper;
+import org.omg.CosNaming.NamingContextPackage.NotEmpty;
+import org.omg.PortableServer.POA;
+
+public class TransientNamingContext extends NamingContextBase {
+ // the bindings maintained by this context
+ protected HashMap bindings = new HashMap();
+ // the root context object
+ protected org.omg.CORBA.Object rootContext = null;
+
+ /**
+ * Create a top-level naming context.
+ *
+ * @param orb The orb hosting this context.
+ * @param poa The POA used to activate the object.
+ *
+ * @exception Exception
+ */
+ public TransientNamingContext(ORB orb, POA poa) throws Exception {
+ this(orb, poa, null);
+ // now get the initial root context as a corba object.
+
+ byte[] objectId = poa.activate_object(this);
+ rootContext = poa.id_to_reference(objectId);
+
+ }
+
+ /**
+ * Construct a TransientNamingContext subcontext.
+ *
+ * @param orb The orb this context is associated with.
+ * @param poa The POA the root context is activated under.
+ * @param root The root context.
+ *
+ * @exception Exception
+ */
+ public TransientNamingContext(ORB orb, POA poa, org.omg.CORBA.Object root) throws Exception {
+ super(orb, poa);
+ // save the root context link.
+ rootContext = root;
+ }
+
+ // abstract methods part of the interface contract that the implementation is required
+ // to supply.
+
+ /**
+ * Create a new context of the same type as the
+ * calling context.
+ *
+ * @return A new NamingContext item.
+ * @exception org.omg.CosNaming.NamingContextPackage.NotFound
+ * @exception SystemException
+ */
+ public NamingContext new_context() throws SystemException {
+ try {
+ // create a new context. Then we need to register this with the POA and activate it.
+ TransientNamingContext newContext = new TransientNamingContext(orb, poa, rootContext);
+
+ byte[] objectId = poa.activate_object(newContext);
+ org.omg.CORBA.Object obj = poa.id_to_reference(objectId);
+ return NamingContextHelper.narrow(obj);
+ } catch (SystemException e) {
+ // just propagate system exceptions
+ throw e;
+ } catch (Exception e) {
+ throw (INTERNAL)(new INTERNAL("Unable to create new naming context").initCause(e));
+ }
+ }
+
+ /**
+ * Destroy a context. This method should clean up
+ * any backing resources associated with the context.
+ *
+ * @exception org.omg.CosNaming.NamingContextPackage.NotEmpty
+ */
+ public synchronized void destroy() throws org.omg.CosNaming.NamingContextPackage.NotEmpty {
+ // still holding bound objects? Not allowed to destroy
+ if (!bindings.isEmpty()) {
+ throw new NotEmpty();
+ }
+
+ try {
+ // now detach ourselves from the POA
+ byte[] objectId = poa.servant_to_id(this);
+ if (objectId != null) {
+ poa.deactivate_object(objectId);
+ }
+ } catch (Exception e) {
+ // ignore
+ }
+ }
+
+ /**
+ * Create a list of bound objects an contexts contained
+ * within this context.
+ *
+ * @param how_many The count of elements to return as a BindingList.
+ * @param bl A holder element for returning the source binding list.
+ * @param bi A holder for returning a BindingIterator. Any extra
+ * elements not returned in the BindingList are returned
+ * in the BindingIterator.
+ *
+ * @exception SystemException
+ */
+ public synchronized void list(int how_many,
+ org.omg.CosNaming.BindingListHolder bl,
+ org.omg.CosNaming.BindingIteratorHolder bi) throws SystemException {
+ TransientBindingIterator iterator = new TransientBindingIterator(poa, (HashMap)bindings.clone());
+ // have the iterator fill in the entries here
+ iterator.next_n(how_many, bl);
+
+ // now it's necessary to activate this iterator with the poa. The value we pass
+ // back is the narrowed activated object
+ try {
+ byte[] objectId = poa.activate_object(iterator);
+ org.omg.CORBA.Object obj = poa.id_to_reference(objectId);
+
+ bi.value = BindingIteratorHelper.narrow(obj);
+ } catch (SystemException e) {
+ // just propagate system exceptions
+ throw e;
+ } catch (Exception e) {
+ throw (INTERNAL)(new INTERNAL("Unable to activate BindingIterator").initCause(e));
+ }
+ }
+
+ // lower level functions that are used by the base class
+
+ /**
+ * Resolve an object in this context (single level
+ * resolution).
+ *
+ * @param n The name of the target object.
+ * @param type A type holder for returning the bound object type
+ * information.
+ *
+ * @return The bound object. Returns null if the object does not
+ * exist in the context.
+ * @exception SystemException
+ */
+ protected org.omg.CORBA.Object resolveObject(NameComponent n, BindingTypeHolder type) throws SystemException {
+ // special call to resolve the root context. This is the only one that goes backwards.
+ if (n.id.length() == 0 && n.kind.length() == 0) {
+ // this is a name context item, so set it properly.
+ type.value = BindingType.ncontext;
+ return rootContext;
+ }
+
+ BindingKey key = new BindingKey(n);
+ BoundObject obj = (BoundObject)bindings.get(key);
+ // if not in the table, just return null
+ if (obj == null) {
+ return null;
+ }
+ // update the type information and return the bound object reference.
+ type.value = obj.type;
+ return obj.boundObject;
+ }
+
+ /**
+ * Bind an object into the current context. This can
+ * be either an object or a naming context.
+ *
+ * @param n The single-level name of the target object.
+ * @param obj The object or context to be bound.
+ * @param type
+ *
+ * @exception SystemException
+ */
+ protected void bindObject(NameComponent n, org.omg.CORBA.Object obj, BindingTypeHolder type) throws SystemException {
+ // fairly simple table put...
+ bindings.put(new BindingKey(n), new BoundObject(n, obj, type.value));
+ }
+
+ /**
+ * Unbind an object from the current context.
+ *
+ * @param n The name of the target object (single level).
+ *
+ * @return The object associated with the binding. Returns null
+ * if there was no binding currently associated with this
+ * name.
+ * @exception SystemException
+ */
+ protected org.omg.CORBA.Object unbindObject(NameComponent n) throws SystemException {
+ //remove the object from the hash table, returning the bound object if it exists.
+ BindingKey key = new BindingKey(n);
+ BoundObject obj = (BoundObject)bindings.remove(key);
+
+ if (obj != null) {
+ return obj.boundObject;
+ }
+ return null;
+ }
+
+ /**
+ * Retrieve the rootContext for this NamingContext.
+ *
+ * @return The rootContext CORBA object associated with this context.
+ */
+ public org.omg.CORBA.Object getRootContext() {
+ return rootContext;
+ }
+
+ /**
+ * Internal class used for HashMap lookup keys.
+ */
+ class BindingKey {
+ // the name component this is a HashMap key for.
+ public NameComponent name;
+ private int hashval = 0;
+
+ /**
+ * Create a new BindingKey for a NameComponent.
+ *
+ * @param n The lookup name.
+ */
+ public BindingKey(NameComponent n) {
+ name = n;
+ // create a hash value used for lookups
+ if (name.id != null) {
+ hashval += name.id.hashCode();
+ }
+ if (name.kind != null) {
+ hashval += name.kind.hashCode();
+ }
+ }
+
+ /**
+ * Return the hashcode associated with this binding key. The
+ * hashcode is created using the NameComponent id and
+ * kind fields.
+ *
+ * @return The lookup hashvalue associated with this key.
+ */
+ public int hashCode() {
+ return hashval;
+ }
+
+ /**
+ * Compare two BindingKeys for equality (used for HashMap
+ * lookups).
+ *
+ * @param other The comparison partner.
+ *
+ * @return True if the keys are equivalent, false otherwise.
+ */
+ public boolean equals(Object other) {
+ // if not given or the wrong type, this is false.
+ if (other == null || !(other instanceof BindingKey)) {
+ return false;
+ }
+
+ BindingKey otherKey = (BindingKey)other;
+
+ // verify first on the id name.
+ if (name.id != null) {
+ if (otherKey.name.id == null) {
+ return false;
+ }
+ if (!name.id.equals(otherKey.name.id)) {
+ return false;
+ }
+ } else {
+ if (otherKey.name.id != null) {
+ return false;
+ }
+ }
+ // this is a match so far...now compare the kinds
+ if (name.kind != null) {
+ if (otherKey.name.kind == null) {
+ return false;
+ }
+ if (!name.kind.equals(otherKey.name.kind)) {
+ return false;
+ }
+ } else {
+ if (otherKey.name.kind != null) {
+ return false;
+ }
+ }
+ return true;
+ }
+ }
+
+ /**
+ * Internal class used to store bound objects in the HashMap.
+ */
+ public class BoundObject {
+ // the name this object is bound under.
+ public NameComponent name;
+ // the type of binding (either nobject or ncontext).
+ public BindingType type;
+ // the actual bound object.
+ public org.omg.CORBA.Object boundObject;
+
+ /**
+ * Create a new object binding for our HashMap.
+ *
+ * @param name The bound object's name.
+ * @param boundObject
+ * The bound object (real object or NamingContext).
+ * @param type The type information associated with this binding.
+ */
+ public BoundObject(NameComponent name, org.omg.CORBA.Object boundObject, BindingType type) {
+ this.name = name;
+ this.boundObject = boundObject;
+ this.type = type;
+ }
+ }
+
+ /**
+ * Context implementation version of the BindingIterator
+ * object used to return list items.
+ */
+ public class TransientBindingIterator extends BindingIteratorPOA {
+ // the POA used to activate this object (required for destroy();
+ private POA poa;
+ // the binding set we're iterating over (this must be a snapshot copy)
+ private HashMap bindings;
+ // the iterator use to access the bindings
+ private Iterator iterator;
+
+ /**
+ * Create a new BindingIterator hosted by the given POA and
+ * iterating over the map of items.
+ *
+ * @param poa The hosting POA.
+ * @param bindings The HashMap of bound objects.
+ */
+ public TransientBindingIterator(POA poa, HashMap bindings) {
+ this.poa = poa;
+ this.bindings = bindings;
+ this.iterator = bindings.values().iterator();
+ }
+
+ /**
+ * Return the next object in the iteration sequence.
+ *
+ * @param b The BindingHolder used to return the next item. If
+ * we've reached the end of the sequence, an item
+ * with an empty name is returned.
+ *
+ * @return true if there is another item, false otherwise.
+ */
+ public boolean next_one(org.omg.CosNaming.BindingHolder b) {
+ if (iterator.hasNext()) {
+ // return this as a Binding value.
+ BoundObject obj = (BoundObject)iterator.next();
+ b.value = new Binding(new NameComponent[] {obj.name}, obj.type);
+ return true;
+ } else {
+ // return an empty element
+ b.value = new Binding(new NameComponent[0], BindingType.nobject);
+ return false;
+ }
+ }
+
+ /**
+ * Retrieve the next "n" items from the list, returned
+ * as a BindingList.
+ *
+ * @param how_many The count of items to retrieve.
+ * @param bl A holder for returning an array of Bindings for
+ * the returned items.
+ *
+ * @return true if any items were returned, false if there's
+ * nothing left to return.
+ */
+ public boolean next_n(int how_many, org.omg.CosNaming.BindingListHolder bl) {
+ List accum = new ArrayList();
+ BindingHolder holder = new BindingHolder();
+ int i = 0;
+ // Keep iterating as long as there are entries
+ while (i < how_many && next_one(holder)) {
+ accum.add(holder.value);
+ i++;
+ }
+
+ // convert to an array and return whether we found anything.
+ bl.value = (Binding[])accum.toArray(new Binding[accum.size()]);
+ return accum.isEmpty();
+ }
+
+ /**
+ * Destory this BindingIterator instance, which deativates
+ * it from the hosting POA.
+ */
+ public void destroy() {
+ try {
+ // we need to deactivate this from the POA.
+ byte[] objectId = poa.servant_to_id(this);
+ if (objectId != null) {
+ poa.deactivate_object(objectId);
+ }
+ } catch (Exception e) {
+ }
+ }
+ }
+}
diff --git a/java/sca/modules/host-corba/src/main/java/org/apache/tuscany/sca/host/corba/naming/TransientServiceException.java b/java/sca/modules/host-corba/src/main/java/org/apache/tuscany/sca/host/corba/naming/TransientServiceException.java
new file mode 100644
index 0000000000..4c1e9c33f1
--- /dev/null
+++ b/java/sca/modules/host-corba/src/main/java/org/apache/tuscany/sca/host/corba/naming/TransientServiceException.java
@@ -0,0 +1,38 @@
+/**
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+* contributor license agreements. See the NOTICE file distributed with
+* this work for additional information regarding copyright ownership.
+* The ASF licenses this file to You under the Apache License, Version 2.0
+* (the "License"); you may not use this file except in compliance with
+* the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * @version $Rev$ $Date$
+ */
+package org.apache.tuscany.sca.host.corba.naming;
+
+public class TransientServiceException extends Exception {
+
+ public TransientServiceException() {
+ super();
+ }
+
+ public TransientServiceException(String reason) {
+ super(reason);
+ }
+
+ public TransientServiceException(String reason, Exception cause) {
+ super(reason, cause);
+ }
+
+}
diff --git a/java/sca/modules/host-corba/src/test/java/org/apache/tuscany/sca/host/corba/testing/DefaultCorbaHostTestCase.java b/java/sca/modules/host-corba/src/test/java/org/apache/tuscany/sca/host/corba/testing/DefaultCorbaHostTestCase.java
index 5b9167122f..2c7a308769 100644
--- a/java/sca/modules/host-corba/src/test/java/org/apache/tuscany/sca/host/corba/testing/DefaultCorbaHostTestCase.java
+++ b/java/sca/modules/host-corba/src/test/java/org/apache/tuscany/sca/host/corba/testing/DefaultCorbaHostTestCase.java
@@ -28,6 +28,8 @@ import java.io.IOException;
import org.apache.tuscany.sca.host.corba.CorbaHost;
import org.apache.tuscany.sca.host.corba.CorbaHostException;
import org.apache.tuscany.sca.host.corba.DefaultCorbaHost;
+import org.apache.tuscany.sca.host.corba.naming.TransientNameServer;
+import org.apache.tuscany.sca.host.corba.naming.TransientNameService;
import org.apache.tuscany.sca.host.corba.testing.general.TestInterface;
import org.apache.tuscany.sca.host.corba.testing.general.TestInterfaceHelper;
import org.apache.tuscany.sca.host.corba.testing.servants.TestInterfaceServant;
@@ -87,6 +89,7 @@ public class DefaultCorbaHostTestCase {
}
}
+ /*
@BeforeClass
public static void start() {
try {
@@ -102,6 +105,29 @@ public class DefaultCorbaHostTestCase {
public static void stop() {
killProcess(tn);
}
+ */
+
+ private static TransientNameServer server;
+
+ @BeforeClass
+ public static void start() {
+ try {
+ server = new TransientNameServer(LOCALHOST, DEFAULT_PORT, TransientNameService.DEFAULT_SERVICE_NAME);
+ Thread t = server.start();
+ if (t == null) {
+ fail("The naming server cannot be started");
+ }
+ host = new DefaultCorbaHost();
+ } catch (Throwable e) {
+ e.printStackTrace();
+ fail(e.getMessage());
+ }
+ }
+
+ @AfterClass
+ public static void stop() {
+ server.stop();
+ }
/**
* Tests registering, getting and unregistering CORBA object