summaryrefslogtreecommitdiffstats
path: root/branches/sca-java-0.91/modules/binding-ejb/src/main
diff options
context:
space:
mode:
Diffstat (limited to 'branches/sca-java-0.91/modules/binding-ejb/src/main')
-rw-r--r--branches/sca-java-0.91/modules/binding-ejb/src/main/java/org/apache/tuscany/sca/binding/ejb/EJBBinding.java102
-rw-r--r--branches/sca-java-0.91/modules/binding-ejb/src/main/java/org/apache/tuscany/sca/binding/ejb/EJBBindingActivator.java53
-rw-r--r--branches/sca-java-0.91/modules/binding-ejb/src/main/java/org/apache/tuscany/sca/binding/ejb/EJBTargetInvoker.java79
-rw-r--r--branches/sca-java-0.91/modules/binding-ejb/src/main/java/org/apache/tuscany/sca/binding/ejb/java2idl/AttributeMode.java62
-rw-r--r--branches/sca-java-0.91/modules/binding-ejb/src/main/java/org/apache/tuscany/sca/binding/ejb/java2idl/AttributeType.java136
-rw-r--r--branches/sca-java-0.91/modules/binding-ejb/src/main/java/org/apache/tuscany/sca/binding/ejb/java2idl/ClassType.java61
-rw-r--r--branches/sca-java-0.91/modules/binding-ejb/src/main/java/org/apache/tuscany/sca/binding/ejb/java2idl/ConstantType.java68
-rw-r--r--branches/sca-java-0.91/modules/binding-ejb/src/main/java/org/apache/tuscany/sca/binding/ejb/java2idl/ContainerType.java791
-rw-r--r--branches/sca-java-0.91/modules/binding-ejb/src/main/java/org/apache/tuscany/sca/binding/ejb/java2idl/ExceptionType.java73
-rw-r--r--branches/sca-java-0.91/modules/binding-ejb/src/main/java/org/apache/tuscany/sca/binding/ejb/java2idl/IDLType.java65
-rw-r--r--branches/sca-java-0.91/modules/binding-ejb/src/main/java/org/apache/tuscany/sca/binding/ejb/java2idl/IDLUtil.java464
-rw-r--r--branches/sca-java-0.91/modules/binding-ejb/src/main/java/org/apache/tuscany/sca/binding/ejb/java2idl/IDLViolationException.java50
-rw-r--r--branches/sca-java-0.91/modules/binding-ejb/src/main/java/org/apache/tuscany/sca/binding/ejb/java2idl/InterfaceType.java158
-rw-r--r--branches/sca-java-0.91/modules/binding-ejb/src/main/java/org/apache/tuscany/sca/binding/ejb/java2idl/Java2IDL.java51
-rw-r--r--branches/sca-java-0.91/modules/binding-ejb/src/main/java/org/apache/tuscany/sca/binding/ejb/java2idl/Java2IDLUtil.java403
-rw-r--r--branches/sca-java-0.91/modules/binding-ejb/src/main/java/org/apache/tuscany/sca/binding/ejb/java2idl/OperationType.java106
-rw-r--r--branches/sca-java-0.91/modules/binding-ejb/src/main/java/org/apache/tuscany/sca/binding/ejb/java2idl/ParameterType.java63
-rw-r--r--branches/sca-java-0.91/modules/binding-ejb/src/main/java/org/apache/tuscany/sca/binding/ejb/java2idl/PrimitiveType.java66
-rw-r--r--branches/sca-java-0.91/modules/binding-ejb/src/main/java/org/apache/tuscany/sca/binding/ejb/java2idl/ValueMemberType.java55
-rw-r--r--branches/sca-java-0.91/modules/binding-ejb/src/main/java/org/apache/tuscany/sca/binding/ejb/java2idl/ValueType.java271
-rw-r--r--branches/sca-java-0.91/modules/binding-ejb/src/main/java/org/apache/tuscany/sca/binding/ejb/util/EJBHandler.java420
-rw-r--r--branches/sca-java-0.91/modules/binding-ejb/src/main/java/org/apache/tuscany/sca/binding/ejb/util/EJBLocator.java511
-rw-r--r--branches/sca-java-0.91/modules/binding-ejb/src/main/java/org/apache/tuscany/sca/binding/ejb/util/EJBObjectFactory.java188
-rw-r--r--branches/sca-java-0.91/modules/binding-ejb/src/main/java/org/apache/tuscany/sca/binding/ejb/util/EJBStubHelper.java69
-rw-r--r--branches/sca-java-0.91/modules/binding-ejb/src/main/java/org/apache/tuscany/sca/binding/ejb/util/InterfaceInfo.java125
-rw-r--r--branches/sca-java-0.91/modules/binding-ejb/src/main/java/org/apache/tuscany/sca/binding/ejb/util/JavaReflectionAdapter.java155
-rw-r--r--branches/sca-java-0.91/modules/binding-ejb/src/main/java/org/apache/tuscany/sca/binding/ejb/util/MethodInfo.java176
-rw-r--r--branches/sca-java-0.91/modules/binding-ejb/src/main/java/org/apache/tuscany/sca/binding/ejb/util/NamingEndpoint.java118
-rw-r--r--branches/sca-java-0.91/modules/binding-ejb/src/main/resources/META-INF/services/org.apache.tuscany.sca.spi.BindingActivator19
29 files changed, 4958 insertions, 0 deletions
diff --git a/branches/sca-java-0.91/modules/binding-ejb/src/main/java/org/apache/tuscany/sca/binding/ejb/EJBBinding.java b/branches/sca-java-0.91/modules/binding-ejb/src/main/java/org/apache/tuscany/sca/binding/ejb/EJBBinding.java
new file mode 100644
index 0000000000..c4b72ed274
--- /dev/null
+++ b/branches/sca-java-0.91/modules/binding-ejb/src/main/java/org/apache/tuscany/sca/binding/ejb/EJBBinding.java
@@ -0,0 +1,102 @@
+/*
+ * 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.
+ */
+package org.apache.tuscany.sca.binding.ejb;
+
+
+
+/**
+ * An implementation of EJBBinding.
+ */
+public class EJBBinding {
+
+ /**
+ * corba location For exmaple,
+ * "corbaname:iiop:localhost:2809/NameServiceServerRoot#ejb/MyEJBHome"
+ */
+ private String uri;
+
+ /**
+ * homeInterface. remote or local
+ */
+ private String homeInterface;
+
+ /**
+ * The ejb-link-name attribute allows a SCA client to bind to an EJB that is
+ * packaged in the same JEE EAR file as the SCA client. This is functionally
+ * equivalent to using the <ejb-link/> subelement of the <ejb-ref/> element
+ * in s EJB deployment descriptor. Used only for Service binding
+ */
+ private String ejbLinkName;
+
+ /**
+ * Gets the homeInterface.
+ *
+ * @return home interface of the service binding
+ */
+ public String getHomeInterface() {
+ return homeInterface;
+ }
+
+ /**
+ * Set homeInterface
+ *
+ * @param homeInterface
+ */
+ public void setHomeInterface(String homeInterface) {
+ this.homeInterface = homeInterface;
+ }
+
+ /**
+ * get ejb-link-name
+ *
+ * @return ejb-link-name
+ */
+ public String getEjbLinkName() {
+ return ejbLinkName;
+ }
+
+ /**
+ * Set ejb-link-name
+ *
+ * @param ejb-link-name
+ */
+ public void setEjbLinkName(String ejbLinkName) {
+ this.ejbLinkName = ejbLinkName;
+ }
+
+ // TODO: uri needs to be part of runtime extension helper
+
+ /**
+ * Sets binding URI.
+ *
+ * @param value the binding uri
+ */
+ public void setUri(String value) {
+ this.uri = value;
+ }
+
+ /**
+ * gets binding URI.
+ *
+ * @return value the binding uri
+ */
+ public String getUri() {
+ return uri;
+ }
+}
diff --git a/branches/sca-java-0.91/modules/binding-ejb/src/main/java/org/apache/tuscany/sca/binding/ejb/EJBBindingActivator.java b/branches/sca-java-0.91/modules/binding-ejb/src/main/java/org/apache/tuscany/sca/binding/ejb/EJBBindingActivator.java
new file mode 100644
index 0000000000..5538186dc4
--- /dev/null
+++ b/branches/sca-java-0.91/modules/binding-ejb/src/main/java/org/apache/tuscany/sca/binding/ejb/EJBBindingActivator.java
@@ -0,0 +1,53 @@
+/*
+ * 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.
+ */
+
+package org.apache.tuscany.sca.binding.ejb;
+
+import org.apache.tuscany.sca.assembly.Binding;
+import org.apache.tuscany.sca.interfacedef.Operation;
+import org.apache.tuscany.sca.interfacedef.java.JavaInterface;
+import org.apache.tuscany.sca.invocation.Invoker;
+import org.apache.tuscany.sca.runtime.RuntimeComponent;
+import org.apache.tuscany.sca.runtime.RuntimeComponentReference;
+import org.apache.tuscany.sca.runtime.RuntimeComponentService;
+import org.apache.tuscany.sca.spi.BindingActivator;
+import org.apache.tuscany.sca.spi.ComponentLifecycle;
+import org.apache.tuscany.sca.spi.InvokerFactory;
+import org.osoa.sca.ServiceRuntimeException;
+
+public class EJBBindingActivator implements BindingActivator<EJBBinding> {
+
+ public InvokerFactory createInvokerFactory(RuntimeComponent rc, RuntimeComponentReference rcr, final Binding b, final EJBBinding binding) {
+ // TODO: assumes a Java interface, need to support tuscany generic Interface
+ final Class si = ((JavaInterface)rcr.getInterfaceContract().getInterface()).getJavaClass();
+ return new InvokerFactory() {
+ public Invoker createInvoker(Operation operation) {
+ return new EJBTargetInvoker((EJBBinding)binding, si, operation);
+ }
+ };
+ }
+
+ public ComponentLifecycle createService(RuntimeComponent rc, RuntimeComponentService rcs, Binding b, EJBBinding binding) {
+ throw new ServiceRuntimeException("services not yet implemented for binding.ejb");
+ }
+
+ public Class<EJBBinding> getBindingClass() {
+ return EJBBinding.class;
+ }
+}
diff --git a/branches/sca-java-0.91/modules/binding-ejb/src/main/java/org/apache/tuscany/sca/binding/ejb/EJBTargetInvoker.java b/branches/sca-java-0.91/modules/binding-ejb/src/main/java/org/apache/tuscany/sca/binding/ejb/EJBTargetInvoker.java
new file mode 100644
index 0000000000..0c384c2c7b
--- /dev/null
+++ b/branches/sca-java-0.91/modules/binding-ejb/src/main/java/org/apache/tuscany/sca/binding/ejb/EJBTargetInvoker.java
@@ -0,0 +1,79 @@
+/*
+ * 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.
+ */
+package org.apache.tuscany.sca.binding.ejb;
+
+import org.apache.tuscany.sca.binding.ejb.util.EJBHandler;
+import org.apache.tuscany.sca.binding.ejb.util.NamingEndpoint;
+import org.apache.tuscany.sca.interfacedef.Operation;
+import org.apache.tuscany.sca.invocation.Invoker;
+import org.apache.tuscany.sca.invocation.Message;
+
+/**
+ * EJBTargetInvoker
+ */
+public class EJBTargetInvoker implements Invoker {
+
+ private Operation operation;
+ private String location;
+ private Class serviceInterface;
+
+ public EJBTargetInvoker(EJBBinding ejbBinding, Class serviceInterface, Operation operation) {
+ this.serviceInterface = serviceInterface;
+ this.location = ejbBinding.getUri();
+ this.operation = operation;
+ }
+
+ public Message invoke(Message msg) {
+ try {
+ Object resp = doInvoke(msg.getBody());
+ msg.setBody(resp);
+ } catch (Throwable e) {
+ e.printStackTrace();
+ msg.setBody(e);
+ }
+ return msg;
+ }
+
+ /**
+ * Invoke a EJB operation
+ *
+ * @param payload
+ * @return
+ */
+ public Object doInvoke(final Object payload) {
+
+ // construct NamingendPoint
+ NamingEndpoint endpoint = getNamingEndpoint();
+
+ // lookup home and ejb stub
+ EJBHandler ejbHandler = new EJBHandler(endpoint, serviceInterface);
+
+ String methodName = operation.getName();
+
+ // invoke business method on ejb
+ Object response = ejbHandler.invoke(methodName, (Object[])payload);
+
+ return response;
+ }
+
+ protected NamingEndpoint getNamingEndpoint() {
+ return new NamingEndpoint(location);
+ }
+
+}
diff --git a/branches/sca-java-0.91/modules/binding-ejb/src/main/java/org/apache/tuscany/sca/binding/ejb/java2idl/AttributeMode.java b/branches/sca-java-0.91/modules/binding-ejb/src/main/java/org/apache/tuscany/sca/binding/ejb/java2idl/AttributeMode.java
new file mode 100644
index 0000000000..437debd2e4
--- /dev/null
+++ b/branches/sca-java-0.91/modules/binding-ejb/src/main/java/org/apache/tuscany/sca/binding/ejb/java2idl/AttributeMode.java
@@ -0,0 +1,62 @@
+/*
+ * 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.
+ */
+package org.apache.tuscany.sca.binding.ejb.java2idl;
+
+import java.io.ObjectStreamException;
+import org.omg.CORBA.BAD_PARAM;
+import org.omg.CORBA.portable.IDLEntity;
+
+/**
+ * Mode of an IDL attribute
+ */
+public final class AttributeMode implements IDLEntity {
+ private static final long serialVersionUID = 4193442157999151834L;
+
+ private int value;
+
+ public static final int _ATTR_NORMAL = 0;
+
+ public static final AttributeMode ATTR_NORMAL = new AttributeMode(_ATTR_NORMAL);
+
+ public static final int _ATTR_READONLY = 1;
+
+ public static final AttributeMode ATTR_READONLY = new AttributeMode(_ATTR_READONLY);
+
+ public int value() {
+ return value;
+ }
+
+ public static AttributeMode from_int(int i) {
+ switch (i) {
+ case _ATTR_NORMAL:
+ return ATTR_NORMAL;
+ case _ATTR_READONLY:
+ return ATTR_READONLY;
+ }
+ throw new BAD_PARAM();
+ }
+
+ private AttributeMode(int i) {
+ value = i;
+ }
+
+ Object readResolve() throws ObjectStreamException {
+ return from_int(value());
+ }
+}
diff --git a/branches/sca-java-0.91/modules/binding-ejb/src/main/java/org/apache/tuscany/sca/binding/ejb/java2idl/AttributeType.java b/branches/sca-java-0.91/modules/binding-ejb/src/main/java/org/apache/tuscany/sca/binding/ejb/java2idl/AttributeType.java
new file mode 100644
index 0000000000..0aa94b087e
--- /dev/null
+++ b/branches/sca-java-0.91/modules/binding-ejb/src/main/java/org/apache/tuscany/sca/binding/ejb/java2idl/AttributeType.java
@@ -0,0 +1,136 @@
+/*
+ * 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.
+ */
+package org.apache.tuscany.sca.binding.ejb.java2idl;
+
+import java.lang.reflect.Method;
+import java.rmi.Remote;
+
+/**
+ * IDL Attribute
+ */
+public class AttributeType extends IDLType {
+
+ /**
+ * Attribute mode.
+ */
+ private AttributeMode mode;
+
+ /**
+ * Read Method.
+ */
+ private Method readMethod = null;
+ /**
+ * Write Method. This is null for read-only attributes.
+ */
+ private Method writeMethod = null;
+ /**
+ * Read method type.
+ */
+ private OperationType readOperationType = null;
+ /**
+ * Write method type. This is null for read-only attributes.
+ */
+ private OperationType writeOperationType = null;
+
+ /**
+ * Create an attribute type.
+ */
+ private AttributeType(String javaName, AttributeMode mode, Method readMethod, Method writeMethod) {
+ super(IDLUtil.javaToIDLName(javaName), javaName);
+ this.mode = mode;
+ // this.cls = readMethod.getReturnType();
+ this.readMethod = readMethod;
+ this.writeMethod = writeMethod;
+ // Only do operation type if the attribute is in a remote interface.
+ if (readMethod.getDeclaringClass().isInterface() && Remote.class.isAssignableFrom(readMethod
+ .getDeclaringClass())) {
+ readOperationType = new OperationType(readMethod);
+ if (writeMethod != null)
+ writeOperationType = new OperationType(writeMethod);
+ setIDLName(getIDLName()); // Fixup operation names
+ }
+ }
+
+ /**
+ * Create an attribute type for a read-only attribute.
+ */
+ AttributeType(String javaName, Method accessor) {
+ this(javaName, AttributeMode.ATTR_READONLY, accessor, null);
+ }
+
+ /**
+ * Create an attribute type for a read-write attribute.
+ */
+ AttributeType(String javaName, Method accessor, Method mutator) {
+ this(javaName, AttributeMode.ATTR_NORMAL, accessor, mutator);
+ }
+
+ /**
+ * Return the attribute mode.
+ */
+ public AttributeMode getMode() {
+ return mode;
+ }
+
+ /**
+ * Return the accessor method
+ */
+ public Method getReadMethod() {
+ return readMethod;
+ }
+
+ /**
+ * Return the mutator method
+ */
+ public Method getWriteMethod() {
+ return writeMethod;
+ }
+
+ /**
+ * Return the accessor operation type
+ */
+ public OperationType getReadOperationType() {
+ return readOperationType;
+ }
+
+ /**
+ * Return the mutator operation type
+ */
+ public OperationType getWriteOperationType() {
+ return writeOperationType;
+ }
+
+ /**
+ * Set the unqualified IDL name. This also sets the names of the associated
+ * operations.
+ */
+ void setIDLName(String idlName) {
+ super.setIDLName(idlName);
+ // If the first char is an uppercase letter and the second char is not
+ // an uppercase letter, then convert the first char to lowercase.
+ char ch0 = idlName.charAt(0);
+ if (Character.isUpperCase(ch0) && (idlName.length() <= 1 || (!Character.isUpperCase(idlName.charAt(1))))) {
+ idlName = Character.toLowerCase(ch0) + idlName.substring(1);
+ }
+ if (readOperationType != null)
+ readOperationType.setIDLName("_get_" + idlName);
+ if (writeOperationType != null)
+ writeOperationType.setIDLName("_set_" + idlName);
+ }
+}
diff --git a/branches/sca-java-0.91/modules/binding-ejb/src/main/java/org/apache/tuscany/sca/binding/ejb/java2idl/ClassType.java b/branches/sca-java-0.91/modules/binding-ejb/src/main/java/org/apache/tuscany/sca/binding/ejb/java2idl/ClassType.java
new file mode 100644
index 0000000000..b6e2dba87e
--- /dev/null
+++ b/branches/sca-java-0.91/modules/binding-ejb/src/main/java/org/apache/tuscany/sca/binding/ejb/java2idl/ClassType.java
@@ -0,0 +1,61 @@
+/*
+ * 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.
+ */
+package org.apache.tuscany.sca.binding.ejb.java2idl;
+
+/**
+ * IDL types.
+ */
+public class ClassType extends IDLType {
+
+ /**
+ * java class.
+ */
+ protected Class javaClass;
+
+ private static String getJavaName(Class cls) {
+ if (cls == null)
+ throw new IllegalArgumentException("Class cannot be null.");
+ String s = cls.getName();
+ int index = s.lastIndexOf('.');
+ if (index == -1)
+ return s;
+ else
+ return s.substring(index + 1);
+ }
+
+ public ClassType(Class cls, String idlName, String javaName) {
+ super(idlName, javaName);
+ this.javaClass = cls;
+ }
+
+ public ClassType(Class cls, String javaName) {
+ this(cls, IDLUtil.javaToIDLName(javaName), javaName);
+ }
+
+ public ClassType(Class cls) {
+ this(cls, getJavaName(cls));
+ }
+
+ /**
+ * Return java class.
+ */
+ public Class getJavaClass() {
+ return javaClass;
+ }
+}
diff --git a/branches/sca-java-0.91/modules/binding-ejb/src/main/java/org/apache/tuscany/sca/binding/ejb/java2idl/ConstantType.java b/branches/sca-java-0.91/modules/binding-ejb/src/main/java/org/apache/tuscany/sca/binding/ejb/java2idl/ConstantType.java
new file mode 100644
index 0000000000..5a6cc78317
--- /dev/null
+++ b/branches/sca-java-0.91/modules/binding-ejb/src/main/java/org/apache/tuscany/sca/binding/ejb/java2idl/ConstantType.java
@@ -0,0 +1,68 @@
+/*
+ * 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.
+ */
+package org.apache.tuscany.sca.binding.ejb.java2idl;
+
+import org.omg.CORBA.Any;
+
+/**
+ * IDL Constant
+ */
+public class ConstantType extends IDLType {
+
+ /**
+ * Java type of constant.
+ */
+ private Class type;
+ /**
+ * The value of the constant.
+ */
+ private Object value;
+
+ ConstantType(String javaName, Class type, Object value) {
+ super(javaName);
+ if (type == void.class || (!type.isPrimitive()) && type != java.lang.String.class)
+ throw new IllegalArgumentException("Illegal type for constant: " + type.getName());
+ this.type = type;
+ this.value = value;
+ }
+
+ /**
+ * Return my Java type.
+ */
+ public Class getType() {
+ return type;
+ }
+
+ /**
+ * Return my value.
+ */
+ public Object getValue() {
+ return value;
+ }
+
+ /**
+ * Insert the constant value into the argument Any.
+ */
+ public void insertValue(Any any) {
+ if (type == String.class)
+ any.insert_wstring((String)value); // 1.3.5.10 Map to wstring
+ else
+ IDLUtil.insertAnyPrimitive(any, value);
+ }
+}
diff --git a/branches/sca-java-0.91/modules/binding-ejb/src/main/java/org/apache/tuscany/sca/binding/ejb/java2idl/ContainerType.java b/branches/sca-java-0.91/modules/binding-ejb/src/main/java/org/apache/tuscany/sca/binding/ejb/java2idl/ContainerType.java
new file mode 100644
index 0000000000..18216db742
--- /dev/null
+++ b/branches/sca-java-0.91/modules/binding-ejb/src/main/java/org/apache/tuscany/sca/binding/ejb/java2idl/ContainerType.java
@@ -0,0 +1,791 @@
+/*
+ * 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.
+ */
+package org.apache.tuscany.sca.binding.ejb.java2idl;
+
+import java.io.Externalizable;
+import java.io.ObjectStreamClass;
+import java.io.Serializable;
+import java.lang.ref.SoftReference;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.rmi.RemoteException;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.WeakHashMap;
+
+/**
+ * Common base class of ValueType and InterfaceType.
+ */
+public abstract class ContainerType extends ClassType {
+
+ /** Flags a method as overloaded. */
+ protected final byte M_OVERLOADED = 1;
+ /** Flags a method as the accessor of a read-write property. */
+ protected final byte M_READ = 2;
+ /** Flags a method as the mutator of a read-write property. */
+ protected final byte M_WRITE = 4;
+ /** Flags a method as the accessor of a read-only property. */
+ protected final byte M_READONLY = 8;
+ /** Flags a method as being inherited. */
+ protected final byte M_INHERITED = 16;
+ /**
+ * Flags a method as being the writeObject() method used for serialization.
+ */
+ protected final byte M_WRITEOBJECT = 32;
+ /** Flags a field as being a constant (public final static). */
+ protected final byte F_CONSTANT = 1;
+ /**
+ * Flags a field as being the special <code> public final static
+ * java.io.ObjectStreamField[] serialPersistentFields</code>
+ * field.
+ */
+ protected final byte F_SPFFIELD = 2;
+
+ /**
+ * Array of all java methods.
+ */
+ protected Method[] methods;
+ /**
+ * Array with flags for all java methods.
+ */
+ protected byte[] m_flags;
+ /**
+ * Index of the mutator for read-write attributes. Only entries
+ * <code>i</code> where <code>(m_flags[i]&M_READ) != 0</code> are used.
+ * These entries contain the index of the mutator method corresponding to
+ * the accessor method.
+ */
+ protected int[] setters;
+ /**
+ * Array of all java fields.
+ */
+ protected Field[] fields;
+ /**
+ * Array with flags for all java fields.
+ */
+ protected byte[] f_flags;
+ /**
+ * The class hash code, as specified in "The Common Object Request Broker:
+ * Architecture and Specification" (01-02-33), section 10.6.2.
+ */
+ protected long classHashCode = 0;
+ /**
+ * The repository ID. This is in the RMI hashed format, like
+ * "RMI:java.util.Hashtable:C03324C0EA357270:13BB0F25214AE4B8".
+ */
+ protected String repositoryId;
+ /**
+ * The prefix and postfix of members repository ID. These are used to
+ * calculate member repository IDs and are like "RMI:java.util.Hashtable."
+ * and ":C03324C0EA357270:13BB0F25214AE4B8".
+ */
+ protected String memberPrefix, memberPostfix;
+ /**
+ * Array of type of the interfaces implemented/extended here.
+ */
+ protected InterfaceType[] interfaces;
+ /**
+ * Array of type of the abstract base valuetypes implemented/extended here.
+ */
+ protected ValueType[] abstractBaseValuetypes;
+ /**
+ * Array of attributes.
+ */
+ protected AttributeType[] attributes;
+ /**
+ * Array of Constants.
+ */
+ protected ConstantType[] constants;
+ /**
+ * Array of operations.
+ */
+ protected OperationType[] operations;
+
+ /**
+ * A cache for the fully qualified IDL name of the IDL module we belong to.
+ */
+ private String idlModuleName = null;
+
+ protected ContainerType(Class cls) {
+ super(cls);
+ if (cls == java.lang.Object.class || cls == java.io.Serializable.class || cls == java.io.Externalizable.class)
+ throw new IllegalArgumentException("Cannot parse special class: " + cls.getName());
+ this.javaClass = cls;
+ }
+
+ protected void parse() {
+ parseInterfaces();
+ parseMethods();
+ parseFields();
+ calculateClassHashCode();
+ calculateRepositoryId();
+ parseAttributes();
+ parseConstants();
+ parseOperations();
+ fixupOverloadedOperationNames();
+ }
+
+ /**
+ * Return the interfaces.
+ */
+ public InterfaceType[] getInterfaces() {
+ return (InterfaceType[])interfaces.clone();
+ }
+
+ /**
+ * Return the abstract base valuetypes.
+ */
+ public ValueType[] getAbstractBaseValuetypes() {
+ return (ValueType[])abstractBaseValuetypes.clone();
+ }
+
+ /**
+ * Return the attributes.
+ */
+ public AttributeType[] getAttributes() {
+ return (AttributeType[])attributes.clone();
+ }
+
+ /**
+ * Return the constants.
+ */
+ public ConstantType[] getConstants() {
+ return (ConstantType[])constants.clone();
+ }
+
+ /**
+ * Return the operations.
+ */
+ public OperationType[] getOperations() {
+ return (OperationType[])operations.clone();
+ }
+
+ /**
+ * Return the repository ID.
+ */
+ public String getRepositoryId() {
+ return repositoryId;
+ }
+
+ /**
+ * Return a repository ID for a member.
+ *
+ * @param memberName The Java name of the member.
+ */
+ public String getMemberRepositoryId(String memberName) {
+ return memberPrefix + escapeIRName(memberName) + memberPostfix;
+ }
+
+ /**
+ * Return the fully qualified IDL module name that this type should be
+ * placed in.
+ */
+ public String getIDLModuleName() {
+ if (idlModuleName == null) {
+ String pkgName = javaClass.getPackage().getName();
+ StringBuffer b = new StringBuffer();
+ while (!"".equals(pkgName)) {
+ int idx = pkgName.indexOf('.');
+ String n = (idx == -1) ? pkgName : pkgName.substring(0, idx);
+ b.append("::").append(IDLUtil.javaToIDLName(n));
+ pkgName = (idx == -1) ? "" : pkgName.substring(idx + 1);
+ }
+ idlModuleName = b.toString();
+ }
+ return idlModuleName;
+ }
+
+ // Protected -----------------------------------------------------
+ /**
+ * Convert an integer to a 16-digit hex string.
+ */
+ protected String toHexString(int i) {
+ String s = Integer.toHexString(i).toUpperCase();
+ if (s.length() < 8)
+ return "00000000".substring(0, 8 - s.length()) + s;
+ else
+ return s;
+ }
+
+ /**
+ * Convert a long to a 16-digit hex string.
+ */
+ protected String toHexString(long l) {
+ String s = Long.toHexString(l).toUpperCase();
+ if (s.length() < 16)
+ return "0000000000000000".substring(0, 16 - s.length()) + s;
+ else
+ return s;
+ }
+
+ /**
+ * Check if a method is an accessor.
+ */
+ protected boolean isReadMethod(Method m) {
+ Class returnType = m.getReturnType();
+ if (!m.getName().startsWith("get"))
+ if (!m.getName().startsWith("is") || !(returnType == boolean.class))
+ return false;
+ if (returnType == void.class)
+ return false;
+ if (m.getParameterTypes().length != 0)
+ return false;
+ return hasNonAppExceptions(m);
+ }
+
+ /**
+ * Check if a method is a mutator.
+ */
+ protected boolean isWriteMethod(Method m) {
+ if (!m.getName().startsWith("set"))
+ return false;
+ if (m.getReturnType() != void.class)
+ return false;
+ if (m.getParameterTypes().length != 1)
+ return false;
+ return hasNonAppExceptions(m);
+ }
+
+ private static boolean isCheckedException(Class type) {
+ /*
+ * Is a checked exception
+ */
+ if (!Throwable.class.isAssignableFrom(type))
+ return false;
+
+ if (Error.class.isAssignableFrom(type))
+ return false;
+
+ if (RuntimeException.class.isAssignableFrom(type))
+ return false;
+ return true;
+ }
+
+ /**
+ * Check if a method throws anything checked other than
+ * java.rmi.RemoteException and its subclasses.
+ */
+ protected boolean hasNonAppExceptions(Method m) {
+ Class[] ex = m.getExceptionTypes();
+ for (int i = 0; i < ex.length; ++i) {
+ if (!isCheckedException(ex[i]))
+ continue;
+ if (!RemoteException.class.isAssignableFrom(ex[i]))
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * Analyse the fields of the class. This will fill in the
+ * <code>fields</code> and <code>f_flags</code> arrays.
+ */
+ protected void parseFields() {
+ fields = javaClass.getDeclaredFields();
+ f_flags = new byte[fields.length];
+ for (int i = 0; i < fields.length; ++i) {
+ int mods = fields[i].getModifiers();
+ if (Modifier.isFinal(mods) && Modifier.isStatic(mods) && Modifier.isPublic(mods))
+ f_flags[i] |= F_CONSTANT;
+ }
+ }
+
+ /**
+ * Analyse the interfaces of the class. This will fill in the
+ * <code>interfaces</code> array.
+ */
+ protected void parseInterfaces() {
+ Class[] intfs = javaClass.getInterfaces();
+ ArrayList a = new ArrayList();
+ ArrayList b = new ArrayList();
+ for (int i = 0; i < intfs.length; ++i) {
+ // Ignore java.rmi.Remote
+ if (intfs[i] == java.rmi.Remote.class)
+ continue;
+ // Ignore java.io.Serializable
+ if (intfs[i] == java.io.Serializable.class)
+ continue;
+ // Ignore java.io.Externalizable
+ if (intfs[i] == java.io.Externalizable.class)
+ continue;
+ if (!Java2IDLUtil.isAbstractValueType(intfs[i])) {
+ a.add(InterfaceType.getInterfaceType(intfs[i]));
+ } else {
+ b.add(ValueType.getValueType(intfs[i]));
+ }
+ }
+ interfaces = new InterfaceType[a.size()];
+ interfaces = (InterfaceType[])a.toArray(interfaces);
+ abstractBaseValuetypes = new ValueType[b.size()];
+ abstractBaseValuetypes = (ValueType[])b.toArray(abstractBaseValuetypes);
+ }
+
+ /**
+ * Analyse the methods of the class. This will fill in the
+ * <code>methods</code> and <code>m_flags</code> arrays.
+ */
+ protected void parseMethods() {
+ // The dynamic stub and skeleton strategy generation mechanism
+ // requires the inclusion of inherited methods in the type of
+ // remote interfaces. To speed things up, inherited methods are
+ // not considered in the type of a class or non-remote interface.
+ if (javaClass.isInterface() && java.rmi.Remote.class.isAssignableFrom(javaClass))
+ methods = javaClass.getMethods();
+ else
+ methods = javaClass.getDeclaredMethods();
+ m_flags = new byte[methods.length];
+ setters = new int[methods.length];
+ // Find read-write properties
+ for (int i = 0; i < methods.length; ++i)
+ setters[i] = -1; // no mutator here
+ for (int i = 0; i < methods.length; ++i) {
+ if (isReadMethod(methods[i]) && (m_flags[i] & M_READ) == 0) {
+ String attrName = attributeReadName(methods[i].getName());
+ Class iReturn = methods[i].getReturnType();
+ for (int j = i + 1; j < methods.length; ++j) {
+ if (isWriteMethod(methods[j]) && (m_flags[j] & M_WRITE) == 0
+ && attrName.equals(attributeWriteName(methods[j].getName()))) {
+ Class[] jParams = methods[j].getParameterTypes();
+ if (jParams.length == 1 && jParams[0] == iReturn) {
+ m_flags[i] |= M_READ;
+ m_flags[j] |= M_WRITE;
+ setters[i] = j;
+ break;
+ }
+ }
+ }
+ } else if (isWriteMethod(methods[i]) && (m_flags[i] & M_WRITE) == 0) {
+ String attrName = attributeWriteName(methods[i].getName());
+ Class[] iParams = methods[i].getParameterTypes();
+ for (int j = i + 1; j < methods.length; ++j) {
+ if (isReadMethod(methods[j]) && (m_flags[j] & M_READ) == 0
+ && attrName.equals(attributeReadName(methods[j].getName()))) {
+ Class jReturn = methods[j].getReturnType();
+ if (iParams.length == 1 && iParams[0] == jReturn) {
+ m_flags[i] |= M_WRITE;
+ m_flags[j] |= M_READ;
+ setters[j] = i;
+ break;
+ }
+ }
+ }
+ }
+ }
+ // Find read-only properties
+ for (int i = 0; i < methods.length; ++i)
+ if ((m_flags[i] & (M_READ | M_WRITE)) == 0 && isReadMethod(methods[i]))
+ m_flags[i] |= M_READONLY;
+ // Check for overloaded and inherited methods
+ for (int i = 0; i < methods.length; ++i) {
+ if ((m_flags[i] & (M_READ | M_WRITE | M_READONLY)) == 0) {
+ String iName = methods[i].getName();
+ for (int j = i + 1; j < methods.length; ++j) {
+ if (iName.equals(methods[j].getName())) {
+ m_flags[i] |= M_OVERLOADED;
+ m_flags[j] |= M_OVERLOADED;
+ }
+ }
+ }
+ if (methods[i].getDeclaringClass() != javaClass)
+ m_flags[i] |= M_INHERITED;
+ }
+ }
+
+ /**
+ * Convert an attribute read method name in Java format to an attribute name
+ * in Java format.
+ */
+ protected String attributeReadName(String name) {
+ if (name.startsWith("get"))
+ name = name.substring(3);
+ else if (name.startsWith("is"))
+ name = name.substring(2);
+ else
+ throw new IllegalArgumentException("Not an accessor: " + name);
+ return name;
+ }
+
+ /**
+ * Convert an attribute write method name in Java format to an attribute
+ * name in Java format.
+ */
+ protected String attributeWriteName(String name) {
+ if (name.startsWith("set"))
+ name = name.substring(3);
+ else
+ throw new IllegalArgumentException("Not an accessor: " + name);
+ return name;
+ }
+
+ /**
+ * Analyse constants. This will fill in the <code>constants</code> array.
+ */
+ protected void parseConstants() {
+ ArrayList a = new ArrayList();
+ for (int i = 0; i < fields.length; ++i) {
+ if ((f_flags[i] & F_CONSTANT) == 0)
+ continue;
+ Class type = fields[i].getType();
+ // Only map primitives and java.lang.String
+ if (!type.isPrimitive() && type != java.lang.String.class) {
+ // It is an RMI/IIOP violation for interfaces.
+ if (javaClass.isInterface())
+ throw new IDLViolationException("Field \"" + fields[i].getName()
+ + "\" of interface \""
+ + javaClass.getName()
+ + "\" is a constant, but not of one "
+ + "of the primitive types, or String.", "1.2.3");
+ continue;
+ }
+ String name = fields[i].getName();
+ Object value;
+ try {
+ value = fields[i].get(null);
+ } catch (Exception ex) {
+ throw new RuntimeException(ex.toString());
+ }
+ a.add(new ConstantType(name, type, value));
+ }
+ constants = new ConstantType[a.size()];
+ constants = (ConstantType[])a.toArray(constants);
+ }
+
+ /**
+ * Analyse attributes. This will fill in the <code>attributes</code>
+ * array.
+ */
+ protected void parseAttributes() {
+ ArrayList a = new ArrayList();
+ for (int i = 0; i < methods.length; ++i) {
+ // if ((m_flags[i]&M_INHERITED) != 0)
+ // continue;
+ if ((m_flags[i] & (M_READ | M_READONLY)) != 0) {
+ // Read method of an attribute.
+ String name = attributeReadName(methods[i].getName());
+ if ((m_flags[i] & M_READONLY) != 0)
+ a.add(new AttributeType(name, methods[i]));
+ else
+ a.add(new AttributeType(name, methods[i], methods[setters[i]]));
+ }
+ }
+
+ attributes = new AttributeType[a.size()];
+ attributes = (AttributeType[])a.toArray(attributes);
+ }
+
+ /**
+ * Analyse operations. This will fill in the <code>operations</code>
+ * array. This implementation just creates an empty array; override in
+ * subclasses for a real type.
+ */
+ protected void parseOperations() {
+ operations = new OperationType[0];
+ }
+
+ /**
+ * Fixup overloaded operation names. As specified in section 1.3.2.6.
+ */
+ protected void fixupOverloadedOperationNames() {
+ for (int i = 0; i < methods.length; ++i) {
+ if ((m_flags[i] & M_OVERLOADED) == 0)
+ continue;
+ // Find the operation
+ OperationType oa = null;
+ for (int opIdx = 0; oa == null && opIdx < operations.length; ++opIdx)
+ if (operations[opIdx].getMethod().equals(methods[i]))
+ oa = operations[opIdx];
+ if (oa == null)
+ continue; // This method is not mapped.
+ // Calculate new IDL name
+ ParameterType[] parms = oa.getParameters();
+ StringBuffer b = new StringBuffer(oa.getIDLName());
+ if (parms.length == 0)
+ b.append("__");
+ for (int j = 0; j < parms.length; ++j) {
+ String s = parms[j].getTypeIDLName();
+ if (s.startsWith("::"))
+ s = s.substring(2);
+ b.append('_');
+ while (!"".equals(s)) {
+ int idx = s.indexOf("::");
+ b.append('_');
+ if (idx == -1) {
+ b.append(s);
+ s = "";
+ } else {
+ b.append(s.substring(0, idx));
+ s = s.substring(idx + 2);
+ }
+ }
+ }
+ // Set new IDL name
+ oa.setIDLName(b.toString());
+ }
+ }
+
+ /**
+ * Fixup names differing only in case. As specified in section 1.3.2.7.
+ */
+ protected void fixupCaseNames() {
+ ArrayList entries = getContainedEntries();
+ boolean[] clash = new boolean[entries.size()];
+ String[] upperNames = new String[entries.size()];
+ for (int i = 0; i < entries.size(); ++i) {
+ IDLType aa = (IDLType)entries.get(i);
+ clash[i] = false;
+ upperNames[i] = aa.getIDLName().toUpperCase();
+ for (int j = 0; j < i; ++j) {
+ if (upperNames[i].equals(upperNames[j])) {
+ clash[i] = true;
+ clash[j] = true;
+ }
+ }
+ }
+ for (int i = 0; i < entries.size(); ++i) {
+ if (!clash[i])
+ continue;
+ IDLType aa = (IDLType)entries.get(i);
+ boolean noUpper = true;
+ String name = aa.getIDLName();
+ StringBuffer b = new StringBuffer(name);
+ b.append('_');
+ for (int j = 0; j < name.length(); ++j) {
+ if (!Character.isUpperCase(name.charAt(j)))
+ continue;
+ if (noUpper)
+ noUpper = false;
+ else
+ b.append('_');
+ b.append(j);
+ }
+ aa.setIDLName(b.toString());
+ }
+ }
+
+ /**
+ * Return a list of all the entries contained here.
+ *
+ * @param entries The list of entries contained here. Entries in this list
+ * must be subclasses of <code>AbstractType</code>.
+ */
+ abstract protected ArrayList getContainedEntries();
+
+ /**
+ * Return the class hash code, as specified in "The Common Object Request
+ * Broker: Architecture and Specification" (01-02-33), section 10.6.2.
+ */
+ protected void calculateClassHashCode() {
+ // The simple cases
+ if (javaClass.isInterface())
+ classHashCode = 0;
+ else if (!Serializable.class.isAssignableFrom(javaClass))
+ classHashCode = 0;
+ else if (Externalizable.class.isAssignableFrom(javaClass))
+ classHashCode = 1;
+ else
+ // Go ask Util class for the hash code
+ classHashCode = IDLUtil.getClassHashCode(javaClass);
+ }
+
+ /**
+ * Escape non-ISO characters for an IR name.
+ */
+ protected String escapeIRName(String name) {
+ StringBuffer b = new StringBuffer();
+ for (int i = 0; i < name.length(); ++i) {
+ char c = name.charAt(i);
+ if (c < 256)
+ b.append(c);
+ else
+ b.append("\\U").append(toHexString((int)c));
+ }
+ return b.toString();
+ }
+
+ /**
+ * Return the IR global ID of the given class or interface. This is
+ * described in section 1.3.5.7. The returned string is in the RMI hashed
+ * format, like "RMI:java.util.Hashtable:C03324C0EA357270:13BB0F25214AE4B8".
+ */
+ protected void calculateRepositoryId() {
+ if (javaClass.isArray() || javaClass.isPrimitive())
+ throw new IllegalArgumentException("Not a class or interface.");
+ if (javaClass.isInterface() && org.omg.CORBA.Object.class.isAssignableFrom(javaClass)
+ && org.omg.CORBA.portable.IDLEntity.class.isAssignableFrom(javaClass)) {
+ StringBuffer b = new StringBuffer("IDL:");
+ b.append(javaClass.getPackage().getName().replace('.', '/'));
+ b.append('/');
+ String base = javaClass.getName();
+ base = base.substring(base.lastIndexOf('.') + 1);
+ b.append(base).append(":1.0");
+ repositoryId = b.toString();
+ } else {
+ StringBuffer b = new StringBuffer("RMI:");
+ b.append(escapeIRName(javaClass.getName()));
+ memberPrefix = b.toString() + ".";
+ String hashStr = toHexString(classHashCode);
+ b.append(':').append(hashStr);
+ ObjectStreamClass osClass = ObjectStreamClass.lookup(javaClass);
+ if (osClass != null) {
+ long serialVersionUID = osClass.getSerialVersionUID();
+ String SVUID = toHexString(serialVersionUID);
+ if (classHashCode != serialVersionUID)
+ b.append(':').append(SVUID);
+ memberPostfix = ":" + hashStr + ":" + SVUID;
+ } else
+ memberPostfix = ":" + hashStr;
+ repositoryId = b.toString();
+ }
+ }
+
+ /**
+ * A simple aggregate of work-in-progress, and the thread doing the work.
+ */
+ private static class Task {
+ ContainerType type;
+ Thread thread;
+
+ Task(ContainerType type, Thread thread) {
+ this.type = type;
+ this.thread = thread;
+ }
+ }
+
+ /**
+ * Instances of this class cache the most complex types. The types cached
+ * are:
+ * <ul>
+ * <li><code>InterfaceType</code> for interfaces.</li>
+ * <li><code>ValueType</code> for value types.</li>
+ * <li><code>ExceptionType</code> for exceptions.</li>
+ * </ul>
+ * Besides caching work already done, this caches work in progress, as we
+ * need to know about this to handle cyclic graphs of parses. When a thread
+ * re-enters the <code>getType()</code> metohd, an unfinished type will be
+ * returned if the same thread is already working on this type.
+ */
+ protected static class WorkCache {
+ /**
+ * The type constructor of our type class. This constructor takes a
+ * single argument of type <code>Class</code>.
+ */
+ private Constructor constructor;
+
+ /**
+ * This maps the classes of completely done parses to soft references of
+ * their type.
+ */
+ private Map workDone;
+
+ /**
+ * This maps the classes of parses in progress to their type.
+ */
+ private Map workInProgress;
+
+ /**
+ * Create a new work cache manager.
+ *
+ * @param containerType The class of the type type we cache here.
+ */
+ WorkCache(Class containerType) {
+ // Find the constructor and initializer.
+ try {
+ constructor = containerType.getDeclaredConstructor(new Class[] {Class.class});
+ } catch (NoSuchMethodException ex) {
+ throw new IllegalArgumentException("Bad Class: " + ex.toString());
+ }
+ workDone = new WeakHashMap();
+ workInProgress = new HashMap();
+ }
+
+ /**
+ * Returns an type. If the calling thread is currently doing an type of
+ * this class, an unfinished type is returned.
+ */
+ ContainerType getType(Class cls) {
+ ContainerType ret;
+ synchronized (this) {
+ ret = lookupDone(cls);
+ if (ret != null)
+ return ret;
+ // is it work-in-progress?
+ Task inProgress = (Task)workInProgress.get(cls);
+ if (inProgress != null) {
+ if (inProgress.thread == Thread.currentThread())
+ return inProgress.type; // return unfinished
+ // Do not wait for the other thread: We may deadlock
+ // Double work is better than deadlock...
+ }
+ ret = createTask(cls);
+ }
+ // Do the work
+ parse(cls, ret);
+ // We did it
+ synchronized (this) {
+ workInProgress.remove(cls);
+ workDone.put(cls, new SoftReference(ret));
+ notifyAll();
+ }
+ return ret;
+ }
+
+ /**
+ * Lookup an type in the fully done map.
+ */
+ private ContainerType lookupDone(Class cls) {
+ SoftReference ref = (SoftReference)workDone.get(cls);
+ if (ref == null)
+ return null;
+ ContainerType ret = (ContainerType)ref.get();
+ if (ret == null)
+ workDone.remove(cls); // clear map entry if soft ref. was
+ // cleared.
+ return ret;
+ }
+
+ /**
+ * Create new work-in-progress.
+ */
+ private ContainerType createTask(Class cls) {
+ try {
+ ContainerType type = (ContainerType)constructor.newInstance(new Object[] {cls});
+ workInProgress.put(cls, new Task(type, Thread.currentThread()));
+ return type;
+ } catch (Exception ex) {
+ // Ignore it
+ return null;
+ }
+ }
+
+ private void parse(Class cls, ContainerType ret) {
+ try {
+ ret.parse();
+ } finally {
+ synchronized (this) {
+ workInProgress.remove(cls);
+ }
+ }
+ }
+
+ }
+
+}
diff --git a/branches/sca-java-0.91/modules/binding-ejb/src/main/java/org/apache/tuscany/sca/binding/ejb/java2idl/ExceptionType.java b/branches/sca-java-0.91/modules/binding-ejb/src/main/java/org/apache/tuscany/sca/binding/ejb/java2idl/ExceptionType.java
new file mode 100644
index 0000000000..d3b47802cb
--- /dev/null
+++ b/branches/sca-java-0.91/modules/binding-ejb/src/main/java/org/apache/tuscany/sca/binding/ejb/java2idl/ExceptionType.java
@@ -0,0 +1,73 @@
+/*
+ * 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.
+ */
+package org.apache.tuscany.sca.binding.ejb.java2idl;
+
+import java.util.StringTokenizer;
+
+/**
+ * IDL Exception
+ */
+public class ExceptionType extends ValueType {
+
+ private static WorkCache cache = new WorkCache(ExceptionType.class);
+
+ private String repositoryId;
+
+ public static ExceptionType getExceptionType(Class cls) {
+ return (ExceptionType)cache.getType(cls);
+ }
+
+ protected ExceptionType(Class cls) {
+ super(cls);
+ }
+
+ protected void parse() {
+ super.parse();
+ if (!Exception.class.isAssignableFrom(javaClass) || RuntimeException.class.isAssignableFrom(javaClass))
+ throw new IDLViolationException("Exception type " + javaClass.getName() + " must be a checked exception.",
+ "1.2.6");
+ // calculate exceptionRepositoryId
+ StringBuffer b = new StringBuffer("IDL:");
+ String base = javaClass.getName();
+ if (base.endsWith("Exception"))
+ base = base.substring(0, base.length() - 9);
+ StringTokenizer tokenizer = new StringTokenizer(base, ".");
+ while (tokenizer.hasMoreTokens()) {
+ String token = tokenizer.nextToken();
+ if (tokenizer.hasMoreTokens()) {
+ // Defect 281395
+ b.append(IDLUtil.javaToIDLName(token));
+ b.append('/');
+ } else {
+ b.append(IDLUtil.javaToIDLName(token + "Ex"));
+ }
+ }
+ b.append(":1.0");
+ repositoryId = b.toString();
+ }
+
+ /**
+ * Return the repository ID for the mapping of this analysis to an
+ * exception.
+ */
+ public String getExceptionRepositoryId() {
+ return repositoryId;
+ }
+
+}
diff --git a/branches/sca-java-0.91/modules/binding-ejb/src/main/java/org/apache/tuscany/sca/binding/ejb/java2idl/IDLType.java b/branches/sca-java-0.91/modules/binding-ejb/src/main/java/org/apache/tuscany/sca/binding/ejb/java2idl/IDLType.java
new file mode 100644
index 0000000000..eae70245ca
--- /dev/null
+++ b/branches/sca-java-0.91/modules/binding-ejb/src/main/java/org/apache/tuscany/sca/binding/ejb/java2idl/IDLType.java
@@ -0,0 +1,65 @@
+/*
+ * 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.
+ */
+package org.apache.tuscany.sca.binding.ejb.java2idl;
+
+/**
+ * Abstract base class for all IDL types.
+ */
+abstract class IDLType {
+
+ /**
+ * Unqualified IDL name.
+ */
+ protected String idlName;
+ /**
+ * Unqualified java name.
+ */
+ protected String javaName;
+
+ IDLType(String idlName, String javaName) {
+ this.idlName = idlName;
+ this.javaName = javaName;
+ }
+
+ IDLType(String javaName) {
+ this(IDLUtil.javaToIDLName(javaName), javaName);
+ }
+
+ /**
+ * Return my unqualified IDL name.
+ */
+ public String getIDLName() {
+ return idlName;
+ }
+
+ /**
+ * Return unqualified java name.
+ */
+ public String getJavaName() {
+ return javaName;
+ }
+
+ /**
+ * Set unqualified IDL name.
+ */
+ void setIDLName(String idlName) {
+ this.idlName = idlName;
+ }
+
+}
diff --git a/branches/sca-java-0.91/modules/binding-ejb/src/main/java/org/apache/tuscany/sca/binding/ejb/java2idl/IDLUtil.java b/branches/sca-java-0.91/modules/binding-ejb/src/main/java/org/apache/tuscany/sca/binding/ejb/java2idl/IDLUtil.java
new file mode 100644
index 0000000000..fe8698122c
--- /dev/null
+++ b/branches/sca-java-0.91/modules/binding-ejb/src/main/java/org/apache/tuscany/sca/binding/ejb/java2idl/IDLUtil.java
@@ -0,0 +1,464 @@
+/*
+ * 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.
+ */
+package org.apache.tuscany.sca.binding.ejb.java2idl;
+
+import java.io.ByteArrayOutputStream;
+import java.io.DataOutputStream;
+import java.io.Externalizable;
+import java.io.IOException;
+import java.io.ObjectOutputStream;
+import java.io.ObjectStreamClass;
+import java.io.Serializable;
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.rmi.Remote;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Set;
+import java.util.SortedSet;
+import java.util.TreeSet;
+import java.util.WeakHashMap;
+
+import org.omg.CORBA.Any;
+
+/**
+ * This is a RMI/IIOP metadata conversion utility class.
+ */
+public class IDLUtil {
+
+ /**
+ * Return the IDL type name for the given class. Here we use the mapping for
+ * parameter types and return values.
+ */
+ public static String getTypeIDLName(Class cls) {
+ if (cls.isPrimitive())
+ return PrimitiveType.getPrimitiveType(cls).getIDLName();
+ if (cls.isArray()) {
+ int dimension = 0;
+ Class type = cls;
+ while (type.isArray()) {
+ dimension++;
+ type = type.getComponentType();
+ }
+ String baseName = getTypeIDLName(type);
+ int index = baseName.lastIndexOf("::");
+ String prefix = "";
+ String suffix = baseName;
+ if (index != -1) {
+ prefix = baseName.substring(0, index);
+ suffix = baseName.substring(index + 2);
+ }
+ String name = "::org::omg::boxedRMI" + prefix + "::seq" + dimension + "_" + suffix;
+ return name;
+ }
+
+ // special classes
+ if (cls == java.lang.String.class)
+ return "::CORBA::WStringValue";
+ if (cls == java.lang.Object.class)
+ return "::java::lang::_Object";
+ if (cls == java.lang.Class.class)
+ return "::javax::rmi::CORBA::ClassDesc";
+ if (cls == java.io.Serializable.class)
+ return "::java::io::Serializable";
+ if (cls == java.io.Externalizable.class)
+ return "::java::io::Externalizable";
+ if (cls == java.rmi.Remote.class)
+ return "::java::rmi::Remote";
+ if (cls == org.omg.CORBA.Object.class)
+ return "::CORBA::Object";
+ // remote interface?
+ if (cls.isInterface() && java.rmi.Remote.class.isAssignableFrom(cls)) {
+ InterfaceType ia = InterfaceType.getInterfaceType(cls);
+ return ia.getIDLModuleName() + "::" + ia.getIDLName();
+ }
+ // IDL interface?
+ if (cls.isInterface() && org.omg.CORBA.Object.class.isAssignableFrom(cls)
+ && org.omg.CORBA.portable.IDLEntity.class.isAssignableFrom(cls)) {
+ InterfaceType ia = InterfaceType.getInterfaceType(cls);
+ return ia.getIDLModuleName() + "::" + ia.getIDLName();
+ }
+ // exception?
+ if (Throwable.class.isAssignableFrom(cls)) {
+ if (Exception.class.isAssignableFrom(cls) && !RuntimeException.class.isAssignableFrom(cls)) {
+ ExceptionType ea = ExceptionType.getExceptionType(cls);
+ return ea.getIDLModuleName() + "::" + ea.getIDLName();
+ }
+ }
+ // got to be value
+ ValueType va = ValueType.getValueType(cls);
+ return va.getIDLModuleName() + "::" + va.getIDLName();
+ }
+
+ /**
+ * Check if this class is valid for RMI/IIOP mapping. This method will
+ * either throw an exception or return true.
+ */
+ public static boolean isValidRMIIIOP(Class cls) {
+ if (cls.isPrimitive())
+ return true;
+ if (cls.isArray())
+ return isValidRMIIIOP(cls.getComponentType());
+ // special interfaces
+ if (cls == Serializable.class || cls == Externalizable.class)
+ return true;
+ // interface?
+ if (cls.isInterface() && Remote.class.isAssignableFrom(cls)) {
+ InterfaceType.getInterfaceType(cls);
+ return true;
+ }
+ // exception?
+ if (Throwable.class.isAssignableFrom(cls)) {
+ if (Exception.class.isAssignableFrom(cls) && (!RuntimeException.class.isAssignableFrom(cls))) {
+ ExceptionType.getExceptionType(cls);
+ }
+ return true;
+ }
+ // special values
+ if (cls == Object.class || cls == String.class || cls == Class.class)
+ return true;
+ // got to be value
+ ValueType.getValueType(cls);
+ return true;
+ }
+
+ /**
+ * Insert a java primitive into an Any. The primitive is assumed to be
+ * wrapped in one of the primitive wrapper classes.
+ */
+ public static void insertAnyPrimitive(Any any, Object primitive) {
+ Class type = primitive.getClass();
+ if (type == Boolean.class)
+ any.insert_boolean(((Boolean)primitive).booleanValue());
+ else if (type == Character.class)
+ any.insert_wchar(((Character)primitive).charValue());
+ else if (type == Byte.class)
+ any.insert_octet(((Byte)primitive).byteValue());
+ else if (type == Short.class)
+ any.insert_short(((Short)primitive).shortValue());
+ else if (type == Integer.class)
+ any.insert_long(((Integer)primitive).intValue());
+ else if (type == Long.class)
+ any.insert_longlong(((Long)primitive).longValue());
+ else if (type == Float.class)
+ any.insert_float(((Float)primitive).floatValue());
+ else if (type == Double.class)
+ any.insert_double(((Double)primitive).doubleValue());
+ else
+ throw new IllegalArgumentException(type.getName() + "is not a primitive type");
+ }
+
+ /**
+ * Map Java name to IDL name, as per sections 1.3.2.3, 1.3.2.4 and 1.3.2.2.
+ * This only works for a single name component, without a qualifying dot.
+ */
+ public static String javaToIDLName(String name) {
+ if (name == null || "".equals(name))
+ throw new IllegalArgumentException("Illegal name: " + name);
+ if (name.indexOf('.') != -1)
+ throw new IllegalArgumentException("Qualified name is not supported: " + name);
+ StringBuffer res = new StringBuffer(name.length());
+ if (name.charAt(0) == '_')
+ res.append('J'); // 1.3.2.3
+ for (int i = 0; i < name.length(); ++i) {
+ char c = name.charAt(i);
+ if (isLegalIDLIdentifierChar(c))
+ res.append(c);
+ else
+ // 1.3.2.4
+ res.append('U').append(toHexString((int)c));
+ }
+ String s = res.toString();
+ if (isReservedIDLKeyword(s))
+ return "_" + s;
+ else
+ return s;
+ }
+
+ /**
+ * Return the IR global ID of the given class or interface. This is
+ * described in section 1.3.5.7.
+ */
+ public static String getIRIdentifier(Class cls) {
+ if (cls.isPrimitive())
+ throw new IllegalArgumentException("Primitive type doesn't have IR IDs.");
+ String result = (String)classIRIdentifierCache.get(cls);
+ if (result != null)
+ return result;
+ String name = cls.getName();
+ StringBuffer b = new StringBuffer("RMI:");
+ for (int i = 0; i < name.length(); ++i) {
+ char c = name.charAt(i);
+ if (c < 256)
+ b.append(c);
+ else
+ b.append("\\U").append(toHexString((int)c));
+ }
+ long clsHash = getClassHashCode(cls);
+ b.append(':').append(toHexString(clsHash));
+ ObjectStreamClass osClass = ObjectStreamClass.lookup(cls);
+ if (osClass != null) {
+ long serialVersionUID = osClass.getSerialVersionUID();
+ if (clsHash != serialVersionUID)
+ b.append(':').append(toHexString(serialVersionUID));
+ }
+ result = b.toString();
+ classIRIdentifierCache.put(cls, result);
+ return result;
+ }
+
+ /**
+ * A cache for calculated class hash codes.
+ */
+ private static Map classHashCodeCache = Collections.synchronizedMap(new WeakHashMap());
+ /**
+ * A cache for class IR identifiers.
+ */
+ private static Map classIRIdentifierCache = Collections.synchronizedMap(new WeakHashMap());
+ /**
+ * Reserved IDL keywords. Section 1.3.2.2 says that Java identifiers with
+ * these names should have prepended an underscore.
+ */
+
+ private static final Set reservedIDLKeywordSet = new HashSet();
+ static {
+ String[] reservedIDLKeywords = new String[] {"abstract", "any", "attribute", "boolean", "case", "char",
+ "const", "context", "custom", "default", "double", "exception",
+ "enum", "factory", "FALSE", "fixed", "float", "in", "inout",
+ "interface", "local", "long", "module", "native", "Object",
+ "octet", "oneway", "out", "private", "public", "raises",
+ "readonly", "sequence", "short", "string", "struct", "supports",
+ "switch", "TRUE", "truncatable", "typedef", "unsigned", "union",
+ "ValueBase", "valuetype", "void", "wchar", "wstring"};
+ for (int i = 0; i < reservedIDLKeywords.length; i++)
+ reservedIDLKeywordSet.add(reservedIDLKeywords[i]);
+ }
+
+ /**
+ * Convert an integer to a 16-digit hex string.
+ */
+ private static String toHexString(int i) {
+ String s = Integer.toHexString(i).toUpperCase();
+ if (s.length() < 8)
+ return "00000000".substring(8 - s.length()) + s;
+ else
+ return s;
+ }
+
+ /**
+ * Convert a long to a 16-digit hex string.
+ */
+ private static String toHexString(long l) {
+ String s = Long.toHexString(l).toUpperCase();
+ if (s.length() < 16)
+ return "0000000000000000".substring(16 - s.length()) + s;
+ else
+ return s;
+ }
+
+ /**
+ * Determine if the argument is a reserved IDL keyword.
+ */
+ private static boolean isReservedIDLKeyword(String s) {
+ return reservedIDLKeywordSet.contains(s);
+ /*
+ * // TODO: faster lookup for (int i = 0; i <
+ * reservedIDLKeywords.length; ++i) if
+ * (reservedIDLKeywords[i].equals(s)) return true; return false;
+ */
+ }
+
+ /**
+ * Determine if a <code>char</code> is a legal IDL identifier character.
+ */
+ private static boolean isLegalIDLIdentifierChar(char c) {
+ if (c >= 0x61 && c <= 0x7a)
+ return true; // lower case letter
+ if (c >= 0x30 && c <= 0x39)
+ return true; // digit
+ if (c >= 0x41 && c <= 0x5a)
+ return true; // upper case letter
+ if (c == '_')
+ return true; // underscore
+ return false;
+ }
+
+ /**
+ * Return the class hash code, as specified in "The Common Object Request
+ * Broker: Architecture and Specification" (01-02-33), section 10.6.2.
+ */
+ static long getClassHashCode(Class cls) {
+ // The simple cases
+ if (cls.isInterface())
+ return 0;
+ if (!Serializable.class.isAssignableFrom(cls))
+ return 0;
+ if (Externalizable.class.isAssignableFrom(cls))
+ return 1;
+ // Try cache
+ Long l = (Long)classHashCodeCache.get(cls);
+ if (l != null)
+ return l.longValue();
+ // Has to calculate the hash.
+ ByteArrayOutputStream baos = new ByteArrayOutputStream(256);
+ DataOutputStream dos = new DataOutputStream(baos);
+ // Step 1
+ Class superClass = cls.getSuperclass();
+ if (superClass != null && superClass != Object.class) {
+ try {
+ dos.writeLong(getClassHashCode(superClass));
+ } catch (IOException ex) {
+ throw new RuntimeException("Unexpected IOException: " + ex);
+ }
+ }
+ // Step 2
+ boolean hasWriteObject = false;
+ try {
+ Method m;
+ int mods;
+ m = cls.getDeclaredMethod("writeObject", new Class[] {ObjectOutputStream.class});
+ mods = m.getModifiers();
+ if (!Modifier.isPrivate(mods) && !Modifier.isStatic(mods))
+ hasWriteObject = true;
+ } catch (NoSuchMethodException ex) {
+ // ignore
+ }
+ try {
+ dos.writeInt(hasWriteObject ? 2 : 1);
+ } catch (IOException ex) {
+ throw new RuntimeException("Unexpected IOException: " + ex);
+ }
+ // Step 3
+ Field[] fields = cls.getDeclaredFields();
+ SortedSet set = new TreeSet(new FieldComparator());
+ for (int i = 0; i < fields.length; ++i) {
+ int mods = fields[i].getModifiers();
+ if (!Modifier.isStatic(mods) && !Modifier.isTransient(mods))
+ set.add(fields[i]);
+ }
+ Iterator iter = set.iterator();
+ try {
+ while (iter.hasNext()) {
+ Field f = (Field)iter.next();
+ dos.writeUTF(f.getName());
+ dos.writeUTF(getSignature(f.getType()));
+ }
+ } catch (IOException ex) {
+ throw new RuntimeException("Unexpected IOException: " + ex);
+ }
+ // Convert to byte[]
+ try {
+ dos.flush();
+ } catch (IOException ex) {
+ throw new RuntimeException("Unexpected IOException: " + ex);
+ }
+ byte[] bytes = baos.toByteArray();
+ // Calculate SHA digest
+ MessageDigest digest;
+ try {
+ digest = MessageDigest.getInstance("SHA");
+ } catch (NoSuchAlgorithmException ex) {
+ throw new RuntimeException("No SHA MEssageDigest: " + ex);
+ }
+ digest.update(bytes);
+ byte[] sha = digest.digest();
+ // Calculate hash as per section 10.6.2
+ long hash = 0;
+ for (int i = 0; i < Math.min(8, sha.length); i++) {
+ hash += (long)(sha[i] & 255) << (i * 8);
+ }
+ // Save in cache
+ classHashCodeCache.put(cls, new Long(hash));
+ return hash;
+ }
+
+ /**
+ * Calculate the signature of a class, according to the Java VM
+ * specification, section 4.3.2.
+ */
+ private static String getSignature(Class cls) {
+ if (cls.isArray())
+ return "[" + cls.getComponentType();
+ if (cls.isPrimitive()) {
+ if (cls == Byte.TYPE)
+ return "B";
+ if (cls == Character.TYPE)
+ return "C";
+ if (cls == Double.TYPE)
+ return "D";
+ if (cls == Float.TYPE)
+ return "F";
+ if (cls == Integer.TYPE)
+ return "I";
+ if (cls == Long.TYPE)
+ return "J";
+ if (cls == Short.TYPE)
+ return "S";
+ if (cls == Boolean.TYPE)
+ return "Z";
+ throw new RuntimeException("Unknown primitive class.");
+ }
+ return "L" + cls.getName().replace('.', '/') + ";";
+ }
+
+ /**
+ * Handle mappings for primitive types, as per section 1.3.3.
+ */
+ static String primitiveTypeIDLName(Class type) {
+ if (type == Void.TYPE)
+ return "void";
+ if (type == Boolean.TYPE)
+ return "boolean";
+ if (type == Character.TYPE)
+ return "wchar";
+ if (type == Byte.TYPE)
+ return "octet";
+ if (type == Short.TYPE)
+ return "short";
+ if (type == Integer.TYPE)
+ return "long";
+ if (type == Long.TYPE)
+ return "long long";
+ if (type == Float.TYPE)
+ return "float";
+ if (type == Double.TYPE)
+ return "double";
+ throw new IllegalArgumentException(type + "is not a primitive type.");
+ }
+
+ /**
+ * A <code>Comparator</code> for <code>Field</code>s, ordering the
+ * fields according to the lexicographic ordering of their Java names.
+ */
+ private static class FieldComparator implements Comparator {
+ public int compare(Object o1, Object o2) {
+ if (o1 == o2)
+ return 0;
+ String n1 = ((Field)o1).getName();
+ String n2 = ((Field)o2).getName();
+ return n1.compareTo(n2);
+ }
+ }
+}
diff --git a/branches/sca-java-0.91/modules/binding-ejb/src/main/java/org/apache/tuscany/sca/binding/ejb/java2idl/IDLViolationException.java b/branches/sca-java-0.91/modules/binding-ejb/src/main/java/org/apache/tuscany/sca/binding/ejb/java2idl/IDLViolationException.java
new file mode 100644
index 0000000000..712a284b09
--- /dev/null
+++ b/branches/sca-java-0.91/modules/binding-ejb/src/main/java/org/apache/tuscany/sca/binding/ejb/java2idl/IDLViolationException.java
@@ -0,0 +1,50 @@
+/*
+ * 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.
+ */
+package org.apache.tuscany.sca.binding.ejb.java2idl;
+
+import org.osoa.sca.ServiceRuntimeException;
+
+/**
+ * Exception denoting an RMI/IIOP Java-To-IDL mapping spec violation.
+ */
+public class IDLViolationException extends ServiceRuntimeException {
+
+ private static final long serialVersionUID = 3334304081465286631L;
+
+ /**
+ * The section violated.
+ */
+ private String section;
+
+ public IDLViolationException(String msg) {
+ super(msg);
+ }
+
+ public IDLViolationException(String msg, String section) {
+ this(msg);
+ this.section = section;
+ }
+
+ /**
+ * Return the section violated.
+ */
+ public String getSection() {
+ return section;
+ }
+}
diff --git a/branches/sca-java-0.91/modules/binding-ejb/src/main/java/org/apache/tuscany/sca/binding/ejb/java2idl/InterfaceType.java b/branches/sca-java-0.91/modules/binding-ejb/src/main/java/org/apache/tuscany/sca/binding/ejb/java2idl/InterfaceType.java
new file mode 100644
index 0000000000..6943eb7a6f
--- /dev/null
+++ b/branches/sca-java-0.91/modules/binding-ejb/src/main/java/org/apache/tuscany/sca/binding/ejb/java2idl/InterfaceType.java
@@ -0,0 +1,158 @@
+/*
+ * 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.
+ */
+package org.apache.tuscany.sca.binding.ejb.java2idl;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * IDL Interface Routines here are conforming to the "Java(TM) Language to IDL
+ * Mapping Specification", version 1.1 (01-06-07).
+ */
+public class InterfaceType extends ContainerType {
+
+ private boolean abstractInterface;
+ private String[] typeIDs;
+
+ /**
+ * Map of IDL operation names to operation parses.
+ */
+ private Map operationTypeMap;
+
+ private static WorkCache cache = new WorkCache(InterfaceType.class);
+
+ public static InterfaceType getInterfaceType(Class cls) {
+ return (InterfaceType)cache.getType(cls);
+ }
+
+ protected InterfaceType(Class cls) {
+ super(cls);
+ }
+
+ protected void parse() {
+ super.parse();
+ if (!javaClass.isInterface())
+ throw new IllegalArgumentException("Class [" + javaClass.getName() + "] is not an interface.");
+ abstractInterface = Java2IDLUtil.isAbstractInterface(javaClass);
+ calculateOperationTypeMap();
+ calculateAllTypeIds();
+ fixupCaseNames();
+ }
+
+ public boolean isAbstractInterface() {
+ return abstractInterface;
+ }
+
+ private boolean isRemoteInterface() {
+ return (!abstractInterface);
+ }
+
+ public String[] getTypeIDs() {
+ return (String[])typeIDs.clone();
+ }
+
+ /**
+ * Return a list of all the entries contained here.
+ *
+ * @param entries The list of entries contained here. Entries in this list
+ * are subclasses of <code>AbstractType</code>.
+ */
+ protected ArrayList getContainedEntries() {
+ ArrayList ret = new ArrayList(constants.length + attributes.length + operations.length);
+ for (int i = 0; i < constants.length; ++i)
+ ret.add(constants[i]);
+ for (int i = 0; i < attributes.length; ++i)
+ ret.add(attributes[i]);
+ for (int i = 0; i < operations.length; ++i)
+ ret.add(operations[i]);
+ return ret;
+ }
+
+ /**
+ * Analyse operations. This will fill in the <code>operations</code>
+ * array.
+ */
+ protected void parseOperations() {
+ int operationCount = 0;
+ for (int i = 0; i < methods.length; ++i)
+ if ((m_flags[i] & (M_READ | M_WRITE | M_READONLY)) == 0)
+ ++operationCount;
+ operations = new OperationType[operationCount];
+ operationCount = 0;
+ for (int i = 0; i < methods.length; ++i) {
+ if ((m_flags[i] & (M_READ | M_WRITE | M_READONLY)) == 0) {
+ operations[operationCount] = new OperationType(methods[i]);
+ ++operationCount;
+ }
+ }
+ }
+
+ /**
+ * Calculate the map that maps IDL operation names to operation parses.
+ * Besides mapped operations, this map also contains the attribute accessor
+ * and mutator operations.
+ */
+ protected void calculateOperationTypeMap() {
+ operationTypeMap = new HashMap();
+ OperationType oa;
+ // Map the operations
+ for (int i = 0; i < operations.length; ++i) {
+ oa = operations[i];
+ operationTypeMap.put(oa.getIDLName(), oa);
+ }
+ // Map the attributes
+ for (int i = 0; i < attributes.length; ++i) {
+ AttributeType attr = attributes[i];
+ oa = attr.getReadOperationType();
+ // Not having an accessor analysis means that
+ // the attribute is not in a remote interface
+ if (oa != null) {
+ operationTypeMap.put(oa.getIDLName(), oa);
+ oa = attr.getWriteOperationType();
+ if (oa != null)
+ operationTypeMap.put(oa.getIDLName(), oa);
+ }
+ }
+ }
+
+ /**
+ * Calculate the array containing all type ids of this interface, in the
+ * format that org.omg.CORBA.portable.Servant._all_interfaces() is expected
+ * to return.
+ */
+ protected void calculateAllTypeIds() {
+ if (!isRemoteInterface()) {
+ typeIDs = new String[0];
+ } else {
+ ArrayList a = new ArrayList();
+ InterfaceType[] intfs = getInterfaces();
+ for (int i = 0; i < intfs.length; ++i) {
+ String[] ss = intfs[i].getTypeIDs();
+ for (int j = 0; j < ss.length; ++j)
+ if (!a.contains(ss[j]))
+ a.add(ss[j]);
+ }
+ typeIDs = new String[a.size() + 1];
+ typeIDs[0] = getRepositoryId();
+ for (int i = 1; i <= a.size(); ++i)
+ typeIDs[i] = (String)a.get(a.size() - i);
+ }
+ }
+}
diff --git a/branches/sca-java-0.91/modules/binding-ejb/src/main/java/org/apache/tuscany/sca/binding/ejb/java2idl/Java2IDL.java b/branches/sca-java-0.91/modules/binding-ejb/src/main/java/org/apache/tuscany/sca/binding/ejb/java2idl/Java2IDL.java
new file mode 100644
index 0000000000..79cbce55b8
--- /dev/null
+++ b/branches/sca-java-0.91/modules/binding-ejb/src/main/java/org/apache/tuscany/sca/binding/ejb/java2idl/Java2IDL.java
@@ -0,0 +1,51 @@
+/*
+ * 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.
+ */
+package org.apache.tuscany.sca.binding.ejb.java2idl;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * Utility class responsible for Java To IDL Mapping
+ */
+public class Java2IDL {
+
+ public static Map getIDLMapping(Class type) {
+ InterfaceType interfaceType = InterfaceType.getInterfaceType(type);
+ Map names = new HashMap();
+ AttributeType[] attrs = interfaceType.getAttributes();
+ for (int i = 0; i < attrs.length; i++) {
+ OperationType op = attrs[i].getReadOperationType();
+ if (op != null) {
+ names.put(op.getMethod(), op);
+ }
+ op = attrs[i].getWriteOperationType();
+ if (op != null) {
+ names.put(op.getMethod(), op);
+ }
+ }
+ OperationType[] ops = interfaceType.getOperations();
+ for (int i = 0; i < ops.length; i++) {
+ names.put(ops[i].getMethod(), ops[i]);
+ }
+ // Generate the method _ids(), declared as abstract in ObjectImpl
+ interfaceType.getTypeIDs();
+ return names;
+ }
+}
diff --git a/branches/sca-java-0.91/modules/binding-ejb/src/main/java/org/apache/tuscany/sca/binding/ejb/java2idl/Java2IDLUtil.java b/branches/sca-java-0.91/modules/binding-ejb/src/main/java/org/apache/tuscany/sca/binding/ejb/java2idl/Java2IDLUtil.java
new file mode 100644
index 0000000000..b50ec4a04b
--- /dev/null
+++ b/branches/sca-java-0.91/modules/binding-ejb/src/main/java/org/apache/tuscany/sca/binding/ejb/java2idl/Java2IDLUtil.java
@@ -0,0 +1,403 @@
+/*
+ * 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.
+ */
+package org.apache.tuscany.sca.binding.ejb.java2idl;
+
+import java.io.Serializable;
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.rmi.Remote;
+import java.rmi.RemoteException;
+
+/**
+ * Java to IDL Language Mapping Specificiation v1.3 (formal/03-09-04) IDL
+ * Utilities
+ */
+public class Java2IDLUtil {
+
+ /*
+ * checks if the method includes java.rmi.RemoteException or its subclass in
+ * its throws clause.
+ */
+ private static boolean throwsRemoteException(Method method) {
+ Class[] exTypes = method.getExceptionTypes();
+ for (int i = 0; i < exTypes.length; ++i) {
+ if (RemoteException.class.isAssignableFrom(exTypes[i]))
+ return true;
+ }
+ return false;
+ }
+
+ /*
+ * checks if the given class is declared as static (inner classes only)
+ */
+ private static boolean isStatic(Class c) {
+ return (Modifier.isStatic(c.getModifiers()));
+ }
+
+ /**
+ * 1.2.1 Overview of Conforming RMI/IDL Types A conforming RMI/IDL type is a
+ * Java type whose values may be transmitted across an RMI/IDL remote
+ * interface at run-time. A Java data type is a conforming RMI/IDL type if
+ * it is: one of the Java primitive types (see Section 1.2.2, "Primitive
+ * Types," on page 1-2). a conforming remote interface (as defined in
+ * Section 1.2.3, "RMI/IDL Remote Interfaces," on page 1-3). a conforming
+ * value type (as defined in Section 1.2.4, "RMI/IDL Value Types," on page
+ * 1-4). an array of conforming RMI/IDL types (see Section 1.2.5, "RMI/IDL
+ * Arrays," on page 1-5). a conforming exception type (see Section 1.2.6,
+ * "RMI/IDL Exception Types," on page 1-5). a conforming CORBA object
+ * reference type (see Section 1.2.7, "CORBA Object Reference Types," on
+ * page 1-6). a conforming IDL entity type (see Section 1.2.8, "IDL Entity
+ * Types," on page 1-6).
+ *
+ * @param type
+ * @return
+ */
+ public static boolean isIDLType(Class type) {
+ /*
+ * Primitive types. Spec 28.2.2
+ */
+ if (isPrimitiveType(type))
+ return true;
+
+ /*
+ * Conforming array. Spec 28.2.5
+ */
+ if (isIDLArray(type))
+ return true;
+
+ /*
+ * Conforming CORBA reference type. Spec 28.2.7
+ */
+ if (isCORBAObjectType(type))
+ return true;
+
+ /*
+ * Conforming IDL Entity type. Spec 28.2.8
+ */
+ if (isEntityType(type))
+ return true;
+
+ /*
+ * Conforming remote interface. Spec 28.2.3
+ */
+ if (isRemoteInterface(type))
+ return true;
+
+ /*
+ * Conforming exception. Spec 28.2.6
+ */
+ if (isExceptionType(type))
+ return true;
+
+ /*
+ * Conforming value type. Spec 28.2.4
+ */
+ if (isValueType(type))
+ return true;
+
+ return false;
+ }
+
+ /**
+ * Section 1.2.3 RMI/IDL Remote Interfaces
+ *
+ * @param type
+ * @return
+ */
+ public static boolean isRemoteInterface(Class type) {
+
+ /*
+ * The interface is or inherits from java.rmi.Remote either directly or
+ * indirectly.
+ */
+ if (!Remote.class.isAssignableFrom(type))
+ return false;
+
+ /*
+ * All methods in the interface are defined to throw
+ * java.rmi.RemoteException or a superclass of java.rmi.RemoteException.
+ * Throughout this section, references to methods in the interface
+ * include methods in any inherited interfaces
+ */
+ Method[] methods = type.getMethods();
+ for (int i = 0; i < methods.length; i++) {
+ if (!throwsRemoteException(methods[i])) {
+ return false;
+ }
+
+ /*
+ * All checked exception classes used in method declarations (other
+ * than java.rmi.RemoteException and its subclasses) are conforming
+ * RMI/IDL exception types (see Section 1.2.6, "RMI/IDL Exception
+ * Types," on page 1-5).1
+ */
+ Class[] exTypes = methods[i].getExceptionTypes();
+ for (int j = 0; j < exTypes.length; j++) {
+ if (!isExceptionType(exTypes[j]))
+ return false;
+ }
+ }
+
+ // TODO: Check method overloading from inherited interfaces
+ /*
+ * Method names may be overloaded. However, when an interface directly
+ * inherits from several base interfaces, it is forbidden for there to
+ * be method name conflicts between the inherited interfaces. This
+ * outlaws the case where an interface A defines a method "foo," an
+ * interface B also defines a method "foo," and an interface C tries to
+ * inherit from both A and B.
+ */
+
+ /*
+ * Constant definitions in the form of interface variables are
+ * permitted. The constant value must be a compile-time constant of one
+ * of the RMI/IDL primitive types or String.
+ */
+ Field[] fields = type.getFields();
+ for (int k = 0; k < fields.length; k++) {
+ Class fieldType = fields[k].getType();
+ if (fieldType.isPrimitive() || fieldType == String.class)
+ continue;
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * Section 1.3.11
+ *
+ * @param type The java class
+ * @return true if it is an IDL abstract interface
+ */
+ public static boolean isAbstractInterface(Class type) {
+ /*
+ * It must be a Java interface.
+ */
+ if (!type.isInterface())
+ return false;
+
+ /*
+ * It must not be the interface of a CORBA object.
+ */
+ if (org.omg.CORBA.Object.class.isAssignableFrom(type))
+ return false;
+
+ /*
+ * It must not extend java.rmi.Remote directly or indirectly.
+ */
+ if (Remote.class.isAssignableFrom(type))
+ return false;
+
+ Method[] methods = type.getMethods();
+
+ for (int i = 0; i < methods.length; i++) {
+ /*
+ * All methods MUST throw java.rmi.RemoteException or a subclass.
+ */
+ if (!throwsRemoteException(methods[i])) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ /**
+ * 1.2.6 RMI/IDL Exception Types An RMI/IDL exception type is a checked
+ * exception class (as defined by the Java Language Specification). Since
+ * checked exception classes extend java.lang.Throwable, which implements
+ * java.io.Serializable, it is unnecessary for an RMI/IDL exception class to
+ * directly implement java.io.Serializable.
+ */
+ public static boolean isExceptionType(Class type) {
+
+ /*
+ * Is a checked exception
+ */
+ if (!Throwable.class.isAssignableFrom(type))
+ return false;
+
+ if (Error.class.isAssignableFrom(type))
+ return false;
+
+ if (RuntimeException.class.isAssignableFrom(type))
+ return false;
+
+ /*
+ * meets the requirements for RMI/IDL value types defined in Section
+ * 1.2.4, "RMI/IDL Value Types," on page 1-4.
+ */
+ if (!isValueType(type))
+ return false;
+
+ return true;
+ }
+
+ /**
+ * 1.2.4 RMI/IDL Value Types An RMI/IDL value type represents a class whose
+ * values can be moved between systems. So rather than transmitting a
+ * reference between systems, the actual state of the object is transmitted
+ * between systems. This requires that the receiving system have an
+ * analogous class that can be used to hold the received value. Value types
+ * may be passed as arguments or results of remote methods, or as fields
+ * within other objects that are passed remotely.
+ */
+ public static boolean isValueType(Class type) {
+ /*
+ * The class must implement the java.io.Serializable interface, either
+ * directly or indirectly, and must be serializable at run-time. It may
+ * serialize references to other RMI/IDL types, including value types
+ * and remote interfaces.
+ */
+ if (!Serializable.class.isAssignableFrom(type))
+ return false;
+
+ /*
+ * A value type must not either directly or indirectly implement the
+ * java.rmi.Remote interface. (If this were allowed, then there would be
+ * potential confusion between value types and remote interface
+ * references.)
+ */
+ if (Remote.class.isAssignableFrom(type))
+ return false;
+
+ /*
+ * It cannot be a CORBA object.
+ */
+ if (org.omg.CORBA.Object.class.isAssignableFrom(type))
+ return false;
+
+ /*
+ * If the class is a non-static inner class, then its containing class
+ * must also be a conforming RMI/IDL value type.
+ */
+ if ((type.getDeclaringClass() != null) && (!isStatic(type)))
+ if (!isValueType(type.getDeclaringClass()))
+ return false;
+
+ return true;
+ }
+
+ public static boolean isAbstractValueType(Class type) {
+ if (!type.isInterface())
+ return false;
+
+ if (org.omg.CORBA.Object.class.isAssignableFrom(type))
+ return false;
+
+ boolean cannotBeRemote = false;
+ boolean cannotBeAbstractInterface = false;
+
+ if (java.rmi.Remote.class.isAssignableFrom(type)) {
+ cannotBeAbstractInterface = true;
+ } else {
+ cannotBeRemote = true;
+ }
+
+ Method[] methods = type.getMethods();
+ for (int i = 0; i < methods.length; i++) {
+ if (!throwsRemoteException(methods[i])) {
+ cannotBeAbstractInterface = true;
+ cannotBeRemote = true;
+ break;
+ }
+
+ Class[] exTypes = methods[i].getExceptionTypes();
+ for (int j = 0; j < exTypes.length; j++) {
+ if (!isExceptionType(exTypes[j])) {
+ cannotBeRemote = true;
+ break;
+ }
+ }
+ }
+
+ if (!cannotBeRemote) {
+ Field[] fields = type.getFields();
+ for (int k = 0; k < fields.length; k++) {
+ if (fields[k].getType().isPrimitive())
+ continue;
+ if (fields[k].getType().equals(java.lang.String.class))
+ continue;
+ cannotBeRemote = true;
+ break;
+ }
+ }
+ return cannotBeRemote && cannotBeAbstractInterface;
+ }
+
+ /**
+ * 1.2.2 Primitive Types All the standard Java primitive types are supported
+ * as part of RMI/IDL. These are: void, boolean, byte, char, short, int,
+ * long, float, double
+ *
+ * @param type
+ * @return
+ */
+ public static boolean isPrimitiveType(Class type) {
+ return (type != null && type.isPrimitive());
+ }
+
+ /**
+ * 1.2.7 CORBA Object Reference Types A conforming CORBA object reference
+ * type is either
+ * <ul>
+ * <li>the Java interface org.omg.CORBA.Object, or
+ * <li>a Java interface that extends org.omg.CORBA.Object directly or
+ * indirectly and conforms to the rules specified in the Java Language
+ * Mapping (i.e., could have been generated by applying the mapping to an
+ * OMG IDL definition).
+ * </ul>
+ */
+ public static boolean isCORBAObjectType(Class type) {
+ if (type == org.omg.CORBA.Object.class)
+ return true;
+ if (type.isInterface() && org.omg.CORBA.Object.class.isAssignableFrom(type))
+ return true;
+ return false;
+ }
+
+ /**
+ * 1.2.8 IDL Entity Types A Java class is a conforming IDL entity type if it
+ * extends org.omg.CORBA.portable.IDLEntity and conforms to the rules
+ * specified in the Java Language Mapping (i.e., could have been generated
+ * by applying the mapping to an OMG IDL definition) and is not an OMG IDL
+ * user exception.
+ */
+ public static boolean isEntityType(Class type) {
+ if (!org.omg.CORBA.portable.IDLEntity.class.isAssignableFrom(type))
+ return false;
+ if (isExceptionType(type))
+ return false;
+ return true;
+ }
+
+ /**
+ * 1.2.5 RMI/IDL Arrays Arrays of any conforming RMI/IDL type are also
+ * conforming RMI/IDL types. So int[] and String[][][] are conforming
+ * RMI/IDL types. Similarly if Wombat is a conforming RMI/IDL interface
+ * type, then Wombat[] is a conforming RMI/IDL type.
+ */
+ public static boolean isIDLArray(Class type) {
+ if (!type.isArray())
+ return false;
+ Class componentType = type.getComponentType();
+ return isIDLType(componentType);
+ }
+
+}
diff --git a/branches/sca-java-0.91/modules/binding-ejb/src/main/java/org/apache/tuscany/sca/binding/ejb/java2idl/OperationType.java b/branches/sca-java-0.91/modules/binding-ejb/src/main/java/org/apache/tuscany/sca/binding/ejb/java2idl/OperationType.java
new file mode 100644
index 0000000000..f10a66d72d
--- /dev/null
+++ b/branches/sca-java-0.91/modules/binding-ejb/src/main/java/org/apache/tuscany/sca/binding/ejb/java2idl/OperationType.java
@@ -0,0 +1,106 @@
+/*
+ * 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.
+ */
+package org.apache.tuscany.sca.binding.ejb.java2idl;
+
+import java.lang.reflect.Method;
+import java.rmi.Remote;
+import java.rmi.RemoteException;
+import java.util.ArrayList;
+
+/**
+ * IDL Operation.
+ */
+public class OperationType extends IDLType {
+
+ /**
+ * The Method that this OperationType is mapping.
+ */
+ private Method method;
+ /**
+ * The mapped exceptions of this operation.
+ */
+ private ExceptionType[] mappedExceptions;
+ /**
+ * The parameters of this operation.
+ */
+ private ParameterType[] parameters;
+
+ OperationType(Method method) {
+ super(method.getName());
+ this.method = method;
+ // Check if valid return type, IF it is a remote interface.
+ Class retCls = method.getReturnType();
+ if (retCls.isInterface() && Remote.class.isAssignableFrom(retCls))
+ IDLUtil.isValidRMIIIOP(retCls);
+ // Analyze exceptions
+ Class[] ex = method.getExceptionTypes();
+ boolean gotRemoteException = false;
+ ArrayList a = new ArrayList();
+ for (int i = 0; i < ex.length; ++i) {
+ if (ex[i].isAssignableFrom(java.rmi.RemoteException.class))
+ gotRemoteException = true;
+ if (Exception.class.isAssignableFrom(ex[i]) && !RuntimeException.class.isAssignableFrom(ex[i])
+ && !RemoteException.class.isAssignableFrom(ex[i]))
+ a.add(ExceptionType.getExceptionType(ex[i])); // map this
+ }
+ if (!gotRemoteException && Remote.class.isAssignableFrom(method.getDeclaringClass()))
+ throw new IDLViolationException(
+ "All interface methods must throw java.rmi.RemoteException, " + "or a superclass of java.rmi.RemoteException, but method "
+ + getJavaName()
+ + " of interface "
+ + method.getDeclaringClass().getName()
+ + " does not.", "1.2.3");
+ mappedExceptions = new ExceptionType[a.size()];
+ mappedExceptions = (ExceptionType[])a.toArray(mappedExceptions);
+ // Analyze parameters
+ Class[] params = method.getParameterTypes();
+ parameters = new ParameterType[params.length];
+ for (int i = 0; i < params.length; ++i) {
+ parameters[i] = new ParameterType("param" + (i + 1), params[i]);
+ }
+ }
+
+ /**
+ * Return my Java return type.
+ */
+ public Class getReturnType() {
+ return method.getReturnType();
+ }
+
+ /**
+ * Return my mapped Method.
+ */
+ public Method getMethod() {
+ return method;
+ }
+
+ /**
+ * Return my mapped exceptions.
+ */
+ public ExceptionType[] getMappedExceptions() {
+ return (ExceptionType[])mappedExceptions.clone();
+ }
+
+ /**
+ * Return my parameters.
+ */
+ public ParameterType[] getParameters() {
+ return (ParameterType[])parameters.clone();
+ }
+}
diff --git a/branches/sca-java-0.91/modules/binding-ejb/src/main/java/org/apache/tuscany/sca/binding/ejb/java2idl/ParameterType.java b/branches/sca-java-0.91/modules/binding-ejb/src/main/java/org/apache/tuscany/sca/binding/ejb/java2idl/ParameterType.java
new file mode 100644
index 0000000000..09d48ad169
--- /dev/null
+++ b/branches/sca-java-0.91/modules/binding-ejb/src/main/java/org/apache/tuscany/sca/binding/ejb/java2idl/ParameterType.java
@@ -0,0 +1,63 @@
+/*
+ * 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.
+ */
+package org.apache.tuscany.sca.binding.ejb.java2idl;
+
+import org.omg.CORBA.ParameterMode;
+
+/**
+ * IDL Parameter
+ */
+public class ParameterType extends IDLType {
+
+ /**
+ * Java type of parameter.
+ */
+ private Class javaClass;
+ /**
+ * IDL type name of parameter type.
+ */
+ private String typeIDLName;
+
+ ParameterType(String javaName, Class cls) {
+ super(javaName);
+ this.javaClass = cls;
+ this.typeIDLName = IDLUtil.getTypeIDLName(cls);
+ }
+
+ /**
+ * Return the attribute mode.
+ */
+ public ParameterMode getMode() {
+ return ParameterMode.PARAM_IN;
+ }
+
+ /**
+ * Return the Java type.
+ */
+ public Class getJavaClass() {
+ return javaClass;
+ }
+
+ /**
+ * Return the IDL type name of the parameter type.
+ */
+ public String getTypeIDLName() {
+ return typeIDLName;
+ }
+}
diff --git a/branches/sca-java-0.91/modules/binding-ejb/src/main/java/org/apache/tuscany/sca/binding/ejb/java2idl/PrimitiveType.java b/branches/sca-java-0.91/modules/binding-ejb/src/main/java/org/apache/tuscany/sca/binding/ejb/java2idl/PrimitiveType.java
new file mode 100644
index 0000000000..c48188112e
--- /dev/null
+++ b/branches/sca-java-0.91/modules/binding-ejb/src/main/java/org/apache/tuscany/sca/binding/ejb/java2idl/PrimitiveType.java
@@ -0,0 +1,66 @@
+/*
+ * 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.
+ */
+package org.apache.tuscany.sca.binding.ejb.java2idl;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * Type class for primitive types.
+ */
+public class PrimitiveType extends ClassType {
+
+ public final static PrimitiveType voidType = new PrimitiveType(void.class, "void", "void");
+ public final static PrimitiveType booleanType = new PrimitiveType(boolean.class, "boolean", "boolean");
+ public final static PrimitiveType charType = new PrimitiveType(char.class, "wchar", "char");
+ public final static PrimitiveType byteType = new PrimitiveType(byte.class, "octet", "byte");
+ public final static PrimitiveType shortType = new PrimitiveType(short.class, "short", "short");
+ public final static PrimitiveType intType = new PrimitiveType(int.class, "long", "int");
+ public final static PrimitiveType longType = new PrimitiveType(long.class, "long_long", "long");
+ public final static PrimitiveType floatType = new PrimitiveType(float.class, "float", "float");
+ public final static PrimitiveType doubleType = new PrimitiveType(double.class, "double", "double");
+
+ private final static Map types = new HashMap();
+ static {
+ types.put(void.class, voidType);
+ types.put(boolean.class, booleanType);
+ types.put(byte.class, byteType);
+ types.put(char.class, charType);
+ types.put(short.class, shortType);
+ types.put(int.class, intType);
+ types.put(long.class, longType);
+ types.put(float.class, floatType);
+ types.put(double.class, doubleType);
+ }
+
+ private PrimitiveType(Class cls, String idlName, String javaName) {
+ super(cls, idlName, javaName);
+ }
+
+ /**
+ * Get a singleton instance representing one of the peimitive types.
+ */
+ public final static PrimitiveType getPrimitiveType(Class cls) {
+ PrimitiveType type = (PrimitiveType)types.get(cls);
+ if (type == null)
+ throw new IllegalArgumentException(cls + " is not a primitive type");
+ return type;
+ }
+
+}
diff --git a/branches/sca-java-0.91/modules/binding-ejb/src/main/java/org/apache/tuscany/sca/binding/ejb/java2idl/ValueMemberType.java b/branches/sca-java-0.91/modules/binding-ejb/src/main/java/org/apache/tuscany/sca/binding/ejb/java2idl/ValueMemberType.java
new file mode 100644
index 0000000000..3e152301a7
--- /dev/null
+++ b/branches/sca-java-0.91/modules/binding-ejb/src/main/java/org/apache/tuscany/sca/binding/ejb/java2idl/ValueMemberType.java
@@ -0,0 +1,55 @@
+/*
+ * 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.
+ */
+package org.apache.tuscany.sca.binding.ejb.java2idl;
+
+/**
+ * Value member type.
+ */
+public class ValueMemberType extends IDLType {
+
+ /**
+ * Java type.
+ */
+ private Class javaClass;
+ /**
+ * Flags that this member is public.
+ */
+ private boolean isPublic;
+
+ ValueMemberType(String javaName, Class cls, boolean isPublic) {
+ super(javaName);
+ this.javaClass = cls;
+ this.isPublic = isPublic;
+ }
+
+ /**
+ * Return my Java type.
+ */
+ public Class getJavaClass() {
+ return javaClass;
+ }
+
+ /**
+ * Returns true iff this member has private visibility.
+ */
+ public boolean isPublic() {
+ return isPublic;
+ }
+
+}
diff --git a/branches/sca-java-0.91/modules/binding-ejb/src/main/java/org/apache/tuscany/sca/binding/ejb/java2idl/ValueType.java b/branches/sca-java-0.91/modules/binding-ejb/src/main/java/org/apache/tuscany/sca/binding/ejb/java2idl/ValueType.java
new file mode 100644
index 0000000000..3d2c8935cf
--- /dev/null
+++ b/branches/sca-java-0.91/modules/binding-ejb/src/main/java/org/apache/tuscany/sca/binding/ejb/java2idl/ValueType.java
@@ -0,0 +1,271 @@
+/*
+ * 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.
+ */
+package org.apache.tuscany.sca.binding.ejb.java2idl;
+
+import java.io.Externalizable;
+import java.io.ObjectStreamField;
+import java.io.Serializable;
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.rmi.Remote;
+import java.util.ArrayList;
+import java.util.Comparator;
+import java.util.SortedSet;
+import java.util.TreeSet;
+
+import org.osoa.sca.ServiceRuntimeException;
+
+/**
+ * Value Type.
+ */
+public class ValueType extends ContainerType {
+
+ private static WorkCache cache = new WorkCache(ValueType.class);
+
+ /**
+ * Type of our superclass, of null if our superclass is java.lang.Object.
+ */
+ ValueType superType;
+ /**
+ * Flags that this is an abstract value.
+ */
+ private boolean abstractValue = false;
+ /**
+ * Flags that this implements <code>java.io.Externalizable</code>.
+ */
+ private boolean externalizable = false;
+ /**
+ * Flags that this has a <code>writeObject()</code> method.
+ */
+ private boolean hasWriteObjectMethod = false;
+ /**
+ * The <code>serialPersistentFields of the value, or <code>null</code>
+ * if the value does not have this field.
+ */
+ private ObjectStreamField[] serialPersistentFields;
+ /**
+ * The value members of this value class.
+ */
+ private ValueMemberType[] members;
+
+ public static ValueType getValueType(Class cls) {
+ return (ValueType)cache.getType(cls);
+ }
+
+ protected ValueType(Class cls) {
+ super(cls);
+ }
+
+ protected void parse() {
+ super.parse();
+ if (javaClass == String.class)
+ throw new IllegalArgumentException("Cannot parse java.lang.String here: It is a " + "special case."); // 1.3.5.11
+ if (javaClass == Class.class)
+ throw new IllegalArgumentException("Cannot parse java.lang.Class here: It is a " + "special case."); // 1.3.5.10
+ if (Remote.class.isAssignableFrom(javaClass))
+ throw new IDLViolationException("Value type " + javaClass.getName() + " cannot implement java.rmi.Remote.",
+ "1.2.4");
+ if (javaClass.getName().indexOf('$') != -1)
+ throw new ServiceRuntimeException(javaClass.getName() + " is not supported (proxy or inner classes).");
+ externalizable = Externalizable.class.isAssignableFrom(javaClass);
+ if (!externalizable) {
+ // Look for serialPersistentFields field.
+ Field spf = null;
+ try {
+ spf = javaClass.getField("serialPersistentFields");
+ } catch (NoSuchFieldException ex) {
+ // ignore
+ }
+ if (spf != null) { // Right modifiers?
+ int mods = spf.getModifiers();
+ if (!Modifier.isFinal(mods) || !Modifier.isStatic(mods) || !Modifier.isPrivate(mods))
+ spf = null; // wrong modifiers
+ }
+ if (spf != null) { // Right type?
+ Class type = spf.getType();
+ if (type.isArray()) {
+ type = type.getComponentType();
+ if (type != ObjectStreamField.class)
+ spf = null; // Array of wrong type
+ } else
+ spf = null; // Wrong type: Not an array
+ }
+ if (spf != null) {
+ // We have the serialPersistentFields field
+ // Get this constant
+ try {
+ serialPersistentFields = (ObjectStreamField[])spf.get(null);
+ } catch (IllegalAccessException ex) {
+ throw new RuntimeException("Unexpected IllegalException: " + ex.toString());
+ }
+ // Mark this in the fields array
+ for (int i = 0; i < fields.length; ++i) {
+ if (fields[i] == spf) {
+ f_flags[i] |= F_SPFFIELD;
+ break;
+ }
+ }
+ }
+ // Look for a writeObject Method
+ Method wo = null;
+ try {
+ wo = javaClass.getMethod("writeObject", new Class[] {java.io.OutputStream[].class});
+ } catch (NoSuchMethodException ex) {
+ // ignore
+ }
+ if (wo != null) { // Right return type?
+ if (wo.getReturnType() != Void.TYPE)
+ wo = null; // Wrong return type
+ }
+ if (wo != null) { // Right modifiers?
+ int mods = spf.getModifiers();
+ if (!Modifier.isPrivate(mods))
+ wo = null; // wrong modifiers
+ }
+ if (wo != null) { // Right arguments?
+ Class[] paramTypes = wo.getParameterTypes();
+ if (paramTypes.length != 1)
+ wo = null; // Bad number of parameters
+ else if (paramTypes[0] != java.io.OutputStream.class)
+ wo = null; // Bad parameter type
+ }
+ if (wo != null) {
+ // We have the writeObject() method.
+ hasWriteObjectMethod = true;
+ // Mark this in the methods array
+ for (int i = 0; i < methods.length; ++i) {
+ if (methods[i] == wo) {
+ m_flags[i] |= M_WRITEOBJECT;
+ break;
+ }
+ }
+ }
+ }
+ // Map all fields not flagged constant or serialPersistentField.
+ SortedSet m = new TreeSet(new ValueMemberComparator());
+ for (int i = 0; i < fields.length; ++i) {
+ if (f_flags[i] != 0)
+ continue; // flagged
+ int mods = fields[i].getModifiers();
+ if (Modifier.isStatic(mods) || Modifier.isTransient(mods))
+ continue; // don't map this
+ ValueMemberType vma =
+ new ValueMemberType(fields[i].getName(), fields[i].getType(), Modifier.isPublic(mods));
+ m.add(vma);
+ }
+ members = new ValueMemberType[m.size()];
+ members = (ValueMemberType[])m.toArray(members);
+ // Get superclass analysis
+ Class superClass = javaClass.getSuperclass();
+ if (superClass == java.lang.Object.class)
+ superClass = null;
+ if (superClass == null)
+ superType = null;
+ else {
+ superType = getValueType(superClass);
+ }
+ if (!Serializable.class.isAssignableFrom(javaClass))
+ abstractValue = true;
+ fixupCaseNames();
+ }
+
+ /**
+ * Returns the superclass analysis, or null if this inherits from
+ * java.lang.Object.
+ */
+ public ValueType getSuperType() {
+ return superType;
+ }
+
+ /**
+ * Returns true if this value is abstract.
+ */
+ public boolean isAbstractValue() {
+ return abstractValue;
+ }
+
+ /**
+ * Returns true if this value is custom.
+ */
+ public boolean isCustom() {
+ return externalizable || hasWriteObjectMethod;
+ }
+
+ /**
+ * Returns true if this value implements java.io.Externalizable.
+ */
+ public boolean isExternalizable() {
+ return externalizable;
+ }
+
+ /**
+ * Return the value members of this value class.
+ */
+ public ValueMemberType[] getMembers() {
+ return (ValueMemberType[])members.clone();
+ }
+
+ /**
+ * Analyse attributes. This will fill in the <code>attributes</code>
+ * array. Here we override the implementation in ContainerType and create an
+ * empty array, because for valuetypes we don't want to parse IDL attributes
+ * or operations (as in "rmic -idl -noValueMethods").
+ */
+ protected void parseAttributes() {
+ attributes = new AttributeType[0];
+ }
+
+ /**
+ * Return a list of all the entries contained here.
+ *
+ * @param entries The list of entries contained here. Entries in this list
+ * are subclasses of <code>AbstractType</code>.
+ */
+ protected ArrayList getContainedEntries() {
+ ArrayList ret = new ArrayList(constants.length + attributes.length + members.length);
+ for (int i = 0; i < constants.length; ++i)
+ ret.add(constants[i]);
+ for (int i = 0; i < attributes.length; ++i)
+ ret.add(attributes[i]);
+ for (int i = 0; i < members.length; ++i)
+ ret.add(members[i]);
+ return ret;
+ }
+
+ /**
+ * A <code>Comparator</code> for the field ordering specified at the end
+ * of section 1.3.5.6.
+ */
+ private static class ValueMemberComparator implements Comparator {
+ public int compare(Object o1, Object o2) {
+ if (o1 == o2)
+ return 0;
+ ValueMemberType m1 = (ValueMemberType)o1;
+ ValueMemberType m2 = (ValueMemberType)o2;
+ boolean p1 = m1.getJavaClass().isPrimitive();
+ boolean p2 = m2.getJavaClass().isPrimitive();
+ if (p1 && !p2)
+ return -1;
+ if (!p1 && p2)
+ return 1;
+ return m1.getJavaName().compareTo(m2.getJavaName());
+ }
+ }
+}
diff --git a/branches/sca-java-0.91/modules/binding-ejb/src/main/java/org/apache/tuscany/sca/binding/ejb/util/EJBHandler.java b/branches/sca-java-0.91/modules/binding-ejb/src/main/java/org/apache/tuscany/sca/binding/ejb/util/EJBHandler.java
new file mode 100644
index 0000000000..8d0d309aef
--- /dev/null
+++ b/branches/sca-java-0.91/modules/binding-ejb/src/main/java/org/apache/tuscany/sca/binding/ejb/util/EJBHandler.java
@@ -0,0 +1,420 @@
+/*
+ * 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.
+ */
+package org.apache.tuscany.sca.binding.ejb.util;
+
+import java.io.Externalizable;
+import java.io.Serializable;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.rmi.RemoteException;
+import java.rmi.UnexpectedException;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.ejb.EJBObject;
+import javax.rmi.CORBA.Util;
+
+import org.apache.tuscany.sca.binding.ejb.java2idl.ExceptionType;
+import org.apache.tuscany.sca.binding.ejb.java2idl.Java2IDLUtil;
+import org.omg.CORBA.ORB;
+import org.omg.CORBA.SystemException;
+import org.omg.CORBA.portable.ApplicationException;
+import org.omg.CORBA.portable.ObjectImpl;
+import org.omg.CORBA.portable.RemarshalException;
+import org.omg.CORBA.portable.ServantObject;
+import org.omg.CORBA_2_3.portable.InputStream;
+import org.omg.CORBA_2_3.portable.OutputStream;
+import org.osoa.sca.ServiceRuntimeException;
+
+/**
+ * EJBMessageHandler
+ */
+public class EJBHandler {
+ private Object ejbStub;
+
+ private InterfaceInfo interfaceInfo;
+ private Class ejbInterface;
+
+ public EJBHandler(NamingEndpoint namingEndpoint, Class ejbInterface) {
+ this(namingEndpoint, InterfaceInfo.getInstance(ejbInterface));
+ this.ejbInterface = ejbInterface;
+ }
+
+ // locates the stub
+ public EJBHandler(NamingEndpoint namingEndpoint, InterfaceInfo ejbInterface) {
+ try {
+ this.ejbStub = EJBStubHelper.lookup(namingEndpoint);
+ this.interfaceInfo = ejbInterface;
+ } catch (Exception e) {
+ Throwable b = e.getCause();
+ b.printStackTrace();
+ throw new ServiceRuntimeException(e);
+ }
+ }
+
+ private final static Map<String, Class> primitiveClasses = new HashMap<String, Class>();
+ static {
+ primitiveClasses.put("boolean", boolean.class);
+ primitiveClasses.put("byte", byte.class);
+ primitiveClasses.put("char", char.class);
+ primitiveClasses.put("short", short.class);
+ primitiveClasses.put("int", int.class);
+ primitiveClasses.put("long", long.class);
+ primitiveClasses.put("float", float.class);
+ primitiveClasses.put("double", double.class);
+ primitiveClasses.put("void", void.class);
+ }
+
+ private static Class loadClass(final String name) {
+ Class type = (Class)primitiveClasses.get(name);
+ if (type != null)
+ return type;
+ return (Class)AccessController.doPrivileged(new PrivilegedAction<Class>() {
+ public Class run() {
+ try {
+ ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
+ return Class.forName(name, true, classLoader);
+ } catch (ClassNotFoundException e) {
+ return null;
+ }
+ }
+ });
+ }
+
+ // invokes EJB method
+ public Object invoke(String methodName, Object[] args) {
+ Object response = null;
+ try {
+ if (ejbStub instanceof ObjectImpl) {
+ ObjectImpl objectImpl = (ObjectImpl)ejbStub;
+ // TODO: If the Java 2 security is turned on, then
+ // the ORB will try to create proxy
+ // from the interfaces defined on the stub
+ if (System.getSecurityManager() == null && objectImpl._is_local()) {
+ /*
+ * CORBA.Stub is what the object from JNDI will be for a
+ * remote EJB in the same JVM as the client, but with no
+ * stub classes available on the client
+ */
+ response = invokeLocalCORBACall(objectImpl, methodName, args);
+ } else {
+ /*
+ * _EJBObject_Stub is what the object from JNDI will be for
+ * a remote EJB with no stub classes available on the client
+ */
+ response = invokeRemoteCORBACall(objectImpl, methodName, args);
+ }
+ } else {
+ /*
+ * A generated ejb stub or it must be an EJB in the same ear as
+ * the client or an AppServer with a single classloader, so
+ * reflection can be used directly on the JNDI
+ */
+ JavaReflectionAdapter reflectionAdapter =
+ JavaReflectionAdapter.createJavaReflectionAdapter(ejbStub.getClass());
+ try {
+ Method method = reflectionAdapter.getMethod(methodName);
+ response = method.invoke(ejbStub, args);
+ } catch (InvocationTargetException e) {
+ Throwable t = e.getTargetException();
+ // FIXME need to throw really a business exception.
+ // ServiceBusinessException?
+ // Tuscany core doesn't have ServiceBusinessException
+ throw new ServiceRuntimeException(t);
+ }
+ }
+
+ return response;
+ } catch (Exception e) {
+ // FIXME this be business exception? Tuscany core doesn't have
+ // ServiceBusinessException
+ throw new ServiceRuntimeException(e);
+
+ } catch (Throwable e) {
+ throw new ServiceRuntimeException(e);
+ }
+ }
+
+ /**
+ * Get the IDL operation name for a java method
+ *
+ * @param methodName java method name
+ * @return The IDL operation name
+ */
+ private String getOperation(String methodName) {
+ if (interfaceInfo == null)
+ return methodName;
+ MethodInfo methodInfo = interfaceInfo.getMethod(methodName);
+ if (methodInfo != null)
+ return methodInfo.getIDLName();
+ else
+ return null;
+ }
+
+ /*
+ * Derive the EJB interface name from the Stub When loading a stub class
+ * corresponding to an interface or class <packagename>.<typename>, the
+ * class <packagename>._<typename>_Stub shall be used if it exists;
+ * otherwise, the class org.omg.stub.<packagename>._<typename>_Stub shall
+ * be used.
+ */
+ private static String getInterface(String stubName) {
+ int index = stubName.lastIndexOf('.');
+ String packageName = null;
+ String typeName = stubName;
+ if (index != -1) {
+ packageName = stubName.substring(0, index);
+ if (packageName.startsWith("org.omg.stub.")) {
+ packageName = packageName.substring("org.omg.stub.".length());
+ }
+ typeName = stubName.substring(index + 1);
+ }
+ if (typeName.startsWith("_") && typeName.endsWith("_Stub")) {
+ typeName = typeName.substring(1, typeName.length() - "_Stub".length());
+ }
+ if (packageName != null)
+ return packageName + "." + typeName;
+ else
+ return typeName;
+ }
+
+ /**
+ * Invoke a method on the local CORBA object
+ *
+ * @param stub
+ * @param methodName
+ * @param args
+ * @return
+ * @throws RemoteException
+ * @throws ServiceBusinessException
+ */
+ protected Object invokeLocalCORBACall(final ObjectImpl stub, String methodName, Object[] args)
+ throws RemoteException {
+
+ final String operation = getOperation(methodName);
+
+ Class type = loadClass(getInterface(stub.getClass().getName()));
+ if (type == null)
+ type = (ejbInterface != null) ? ejbInterface : EJBObject.class;
+
+ ServantObject so = stub._servant_preinvoke(operation, type);
+ if (so == null) {
+ // The Servant is not local any more
+ return invokeRemoteCORBACall(stub, methodName, args);
+ }
+ Object[] newArgs = null;
+ ORB orb = stub._orb();
+ try {
+ if (args != null)
+ newArgs = Util.copyObjects(args, orb);
+ JavaReflectionAdapter reflectionAdapter =
+ JavaReflectionAdapter.createJavaReflectionAdapter(so.servant.getClass());
+ Method method = reflectionAdapter.getMethod(methodName);
+ Object obj = reflectionAdapter.invoke(method, so.servant, newArgs);
+ Object result = Util.copyObject(obj, orb);
+ return result;
+
+ } catch (InvocationTargetException e) {
+ Throwable exCopy = (Throwable)Util.copyObject(e.getTargetException(), orb);
+ MethodInfo methodInfo = interfaceInfo.getMethod(methodName);
+ String[] exceptionTypes = methodInfo.getExceptionTypes();
+ for (int i = 0; i < exceptionTypes.length; i++) {
+ Class exceptionType = loadClass(exceptionTypes[i]);
+ if (exceptionType.isAssignableFrom(exCopy.getClass()))
+ throw new ServiceRuntimeException(exCopy); // FIXME should
+ // be business
+ // exception?
+ }
+ throw Util.wrapException(exCopy);
+ } catch (Throwable e) {
+ // Other exceptions thrown from "invoke"
+ throw new ServiceRuntimeException(e);
+ } finally {
+ stub._servant_postinvoke(so);
+ }
+ }
+
+ /**
+ * Invoke a method on a remote CORBA object
+ *
+ * @param stub The remote stub
+ * @param methodName The name of the method
+ * @param args Argument list
+ * @return
+ * @throws RemoteException
+ * @throws ServiceBusinessException
+ */
+ protected Object invokeRemoteCORBACall(ObjectImpl stub, String methodName, Object[] args) throws RemoteException {
+
+ try {
+ String operation = getOperation(methodName);
+
+ MethodInfo methodInfo = interfaceInfo.getMethod(methodName);
+ if (methodInfo == null) {
+ throw new ServiceRuntimeException("Invalid Method " + methodName);
+ }
+ String[] types = methodInfo.getParameterTypes();
+ if (args != null) {
+ if (types.length != args.length)
+ throw new ServiceRuntimeException(
+ "The argument list doesn't match the method signature of " + methodName);
+ }
+
+ Class[] parameterTypes = new Class[types.length];
+ for (int i = 0; i < types.length; i++) {
+ parameterTypes[i] = loadClass(types[i]);
+ }
+ Class returnType = loadClass(methodInfo.getReturnType());
+
+ InputStream in = null;
+ try {
+ OutputStream out = (OutputStream)stub._request(operation, true);
+
+ for (int i = 0; i < types.length; i++) {
+ // Object arg = (args.length < i) ? null : args[i];
+ writeValue(out, args[i], parameterTypes[i]);
+ }
+ if (returnType == void.class) {
+ // void return
+ stub._invoke(out);
+ return null;
+ } else {
+ // read the return value
+ in = (InputStream)stub._invoke(out);
+ Object response = readValue(in, returnType);
+ return response;
+ }
+
+ } catch (ApplicationException ex) {
+ in = (InputStream)ex.getInputStream();
+ String id = in.read_string();
+ // Check if the id matches to any declared exceptions for the
+ // method
+ String[] exceptionTypes = methodInfo.getExceptionTypes();
+ for (int i = 0; i < exceptionTypes.length; i++) {
+ Class exceptionType = loadClass(exceptionTypes[i]);
+ String exceptionId = ExceptionType.getExceptionType(exceptionType).getExceptionRepositoryId();
+ if (id.equals(exceptionId)) {
+ Throwable t = (Throwable)in.read_value(exceptionType);
+ throw new ServiceRuntimeException(t); // FIXME should
+ // be
+ // ServcieBusinessException?
+ // no support by
+ // Tuscany core
+ // for
+ // ServcieBusinessException.
+ }
+ }
+ throw new UnexpectedException(id);
+ } catch (RemarshalException ex) {
+ return invokeRemoteCORBACall(stub, methodName, args);
+ } finally {
+ stub._releaseReply(in);
+ }
+ } catch (SystemException ex) {
+ throw Util.mapSystemException(ex);
+ }
+ }
+
+ /**
+ * @param out
+ * @param value
+ * @param type
+ */
+ protected void writeValue(OutputStream out, Object value, Class type) {
+ if (type == null)
+ out.write_value((Serializable)value);
+ else if (type == Object.class || type == Serializable.class || type == Externalizable.class) {
+ // Any
+ Util.writeAny(out, value);
+ } else if (type == Integer.TYPE) {
+ // java int maps to CORBA long
+ out.write_long(((Integer)value).intValue());
+ } else if (type == Short.TYPE) {
+ out.write_short(((Short)value).shortValue());
+ } else if (type == Boolean.TYPE) {
+ out.write_boolean(((Boolean)value).booleanValue());
+ } else if (type == Byte.TYPE) {
+ out.write_octet(((Byte)value).byteValue());
+ } else if (type == Long.TYPE) {
+ out.write_longlong(((Long)value).longValue());
+ } else if (type == Double.TYPE) {
+ out.write_double(((Double)value).doubleValue());
+ } else if (type == Float.TYPE) {
+ out.write_float(((Float)value).floatValue());
+ } else if (type == Character.TYPE) {
+ out.write_wchar(((Character)value).charValue());
+ } else if (type.isArray()) {
+ out.write_value((Serializable)value, type);
+ } else if (Java2IDLUtil.isRemoteInterface(type)) {
+ // Remote interface
+ Util.writeRemoteObject(out, value);
+ } else if (Java2IDLUtil.isAbstractInterface(type)) {
+ // Non-remote Interface
+ Util.writeAbstractObject(out, value);
+ } else {
+ out.write_value((Serializable)value, type);
+ }
+ }
+
+ /**
+ * @param in
+ * @param type
+ * @return
+ */
+ protected Object readValue(InputStream in, Class type) {
+ Object value = null;
+ if (type == null)
+ value = in.read_value();
+ else if (type == Object.class || type == Serializable.class || type == Externalizable.class) {
+ value = Util.readAny(in);
+ } else if (type == Integer.TYPE) {
+ value = new Integer(in.read_long());
+ } else if (type == Short.TYPE) {
+ value = new Short(in.read_short());
+ } else if (type == Boolean.TYPE) {
+ value = new Boolean(in.read_boolean());
+ } else if (type == Byte.TYPE) {
+ value = new Byte(in.read_octet());
+ } else if (type == Long.TYPE) {
+ value = new Long(in.read_longlong());
+ } else if (type == Float.TYPE) {
+ value = new Float(in.read_float());
+ } else if (type == Double.TYPE) {
+ value = new Double(in.read_double());
+ } else if (type == Character.TYPE) {
+ value = new Character(in.read_wchar());
+ } else if (type.isArray()) {
+ // []
+ value = in.read_value(type);
+ } else if (Java2IDLUtil.isRemoteInterface(type)) {
+ // java.rmi.Remote
+ value = in.read_Object(type);
+ } else if (Java2IDLUtil.isAbstractInterface(type)) {
+ // Non-remote Interface
+ value = in.read_abstract_interface(type);
+ } else {
+ // java.io.Serializable
+ value = in.read_value(type);
+ }
+ return value;
+ }
+}
diff --git a/branches/sca-java-0.91/modules/binding-ejb/src/main/java/org/apache/tuscany/sca/binding/ejb/util/EJBLocator.java b/branches/sca-java-0.91/modules/binding-ejb/src/main/java/org/apache/tuscany/sca/binding/ejb/util/EJBLocator.java
new file mode 100644
index 0000000000..1369b92715
--- /dev/null
+++ b/branches/sca-java-0.91/modules/binding-ejb/src/main/java/org/apache/tuscany/sca/binding/ejb/util/EJBLocator.java
@@ -0,0 +1,511 @@
+/*
+ * 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.
+ */
+package org.apache.tuscany.sca.binding.ejb.util;
+
+import java.net.URL;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.Properties;
+import java.util.Set;
+
+import javax.naming.Context;
+import javax.naming.InitialContext;
+import javax.naming.InvalidNameException;
+import javax.naming.NamingException;
+
+import org.omg.CORBA.ORB;
+import org.omg.CORBA.ORBPackage.InvalidName;
+import org.omg.CosNaming.NamingContextExt;
+import org.omg.CosNaming.NamingContextExtHelper;
+
+/**
+ * CosNaming utility
+ */
+public class EJBLocator {
+
+ /*
+ * Root Context Initial Reference Key ------------
+ * ----------------------------------- Server Root NameServiceServerRoot
+ * Cell Persistent Root NameServiceCellPersistentRoot Cell Root
+ * NameServiceCellRoot, NameService Node Root NameServiceNodeRoot
+ */
+ public static final String SERVER_ROOT = "NameServiceServerRoot";
+ public static final String CELL_PERSISTENT_ROOT = "NameServiceCellPersistentRoot";
+ public static final String CELL_ROOT = "NameServiceCellRoot";
+ public static final String NODE_ROOT = "NameServiceNodeRoot";
+ public static final String DEFAULT_ROOT = "NameService"; // Same as
+ // CELL_ROOT
+
+ private static final Set ROOTS = new HashSet(Arrays.asList(new String[] {SERVER_ROOT, CELL_PERSISTENT_ROOT,
+ CELL_ROOT, DEFAULT_ROOT, NODE_ROOT}));
+
+ public static final String DEFAULT_HOST = "127.0.0.1"; // Default host name
+ // or IP address for
+ // Websphere
+ public static final int DEFAULT_NAMING_PORT = 2809; // Default port
+ public static final String NAMING_SERVICE = "NameService"; // The name of
+ // the naming
+ // service
+
+ // private static final String CHARS_TO_ESCAPE = "\\/.";
+ private static final String RFC2396 = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789;/:?@&=+$,-_.!~*'()";
+ private static final String HEX = "0123456789ABCDEF";
+
+ private String hostName = DEFAULT_HOST;
+ private int port = DEFAULT_NAMING_PORT;
+ private String root = SERVER_ROOT;
+
+ private ORB orb = null;
+ private ObjectLocator locator = null;
+ boolean managed = true;
+
+ public EJBLocator(boolean managed) {
+ this.managed = managed;
+ if (!managed) {
+ String url = (String)AccessController.doPrivileged(new PrivilegedAction() {
+ public Object run() {
+ return System.getProperty(Context.PROVIDER_URL);
+ }
+ });
+ processCorbaURL(url);
+ }
+ }
+
+ private void processCorbaURL(String url) {
+ if (url != null && (url.startsWith("corbaname:iiop:") || url.startsWith("corbaloc:iiop:"))) {
+ /**
+ * corbaname:iiop:<hostName>:<port>/<root>#name corbaloc:iiop:<hostname>:<port>/<root>
+ * For exmaple,
+ * "corbaname:iiop:localhost:2809/NameServiceServerRoot#ejb/MyEJBHome";
+ * or "corbaloc:iiop:myhost:2809/NameServiceServerRoot"
+ */
+ String[] parts = url.split("(:|/|#)");
+ if (parts.length > 2 && parts[2].length() > 0) {
+ hostName = parts[2]; // The host name
+ int index = hostName.lastIndexOf('@'); // version@hostname
+ if (index != -1)
+ hostName = hostName.substring(index + 1);
+ }
+ if (parts.length > 3 && parts[3].length() > 0)
+ port = Integer.parseInt(parts[3]); // The port number
+ if (parts.length > 4 && parts[4].length() > 0)
+ root = parts[4]; // The root of naming
+ }
+ }
+
+ public EJBLocator(String hostName, int port) {
+ this.hostName = (hostName == null) ? DEFAULT_HOST : hostName;
+ this.port = port > 0 ? port : DEFAULT_NAMING_PORT;
+ this.root = SERVER_ROOT;
+ }
+
+ public EJBLocator(String hostName, int port, String root) {
+ this(hostName, port);
+ if (ROOTS.contains(root))
+ this.root = root;
+ else
+ throw new IllegalArgumentException(root + " is not a legal root");
+ }
+
+ public EJBLocator(String corbaName, boolean managed) {
+ this.managed = managed;
+ if (corbaName.startsWith("corbaname:iiop:")) {
+ processCorbaURL(corbaName);
+ } else
+ throw new IllegalArgumentException(corbaName + " is not a legal corbaname");
+ }
+
+ /**
+ * The corbaloc and corbaname formats enable you to provide a URL to access
+ * CORBA objects. Use the corbaloc format for resolving to a particular
+ * CORBAservice without going through a naming service. Use the corbaname
+ * format to resolve a stringified name from a specific naming context.
+ */
+
+ /**
+ * Compose a corbaloc URI
+ *
+ * @param hostName
+ * @param port
+ * @param service
+ * @return
+ */
+ private static String getCorbaloc(String hostName, int port, String service) {
+ if (service == null)
+ return "corbaloc:iiop:" + hostName + ":" + port;
+ else
+ return "corbaloc:iiop:" + hostName + ":" + port + "/" + service;
+ }
+
+ private String getCorbaloc(String service) {
+ return getCorbaloc(hostName, port, service);
+ }
+
+ /**
+ * corbaname Syntax The full corbaname BNF is: &lt;corbaname&gt; =
+ * "corbaname:"&lt;corbaloc_obj&gt;["#"&lt;string_name&gt;]
+ * &lt;corbaloc_obj&gt; = &lt;obj_addr_list&gt; ["/"&lt;key_string&gt;]
+ * &lt;obj_addr_list&gt; = as defined in a corbaloc URL &lt;key_string&gt; =
+ * as defined in a corbaloc URL &lt;string_name&gt;= stringified Name
+ * empty_string Where:
+ * <ul>
+ * <li>corbaloc_obj: portion of a corbaname URL that identifies the naming
+ * context. The syntax is identical to its use in a corbaloc URL.
+ * <li>obj_addr_list: as defined in a corbaloc URL
+ * <li>key_string: as defined in a corbaloc URL.
+ * <li>string_name: a stringified Name with URL escapes as defined below.
+ * </ul>
+ *
+ * @param hostName The host name or IP address of the naming server
+ * @param port The port number of the naming service
+ * @param root The root of the namespace
+ * @param name The JNDI name
+ */
+ private static String getCorbaname(String hostName, int port, String root, String name) {
+ if (name == null)
+ return "corbaname:iiop:" + hostName + ":" + port + "/" + root;
+ else
+ return "corbaname:iiop:" + hostName + ":" + port + "/" + root + "#" + toCorbaname(name);
+ }
+
+ String getCorbaname(String name) {
+ return getCorbaname(hostName, port, root, name);
+ }
+
+ /**
+ * Connect to the ORB.
+ */
+
+ // FIXME. May need to change the IBM classes if this binding is contributed
+ // to Tuscany
+ public ORB connect() {
+ if (orb == null) {
+ Properties props = new Properties();
+ /* This code is for IBM JVM
+ props.put("org.omg.CORBA.ORBClass", "com.ibm.CORBA.iiop.ORB");
+ props.put("com.ibm.CORBA.ORBInitRef.NameService", getCorbaloc(NAMING_SERVICE));
+ props.put("com.ibm.CORBA.ORBInitRef.NameServiceServerRoot", getCorbaloc("NameServiceServerRoot")); */
+ orb = ORB.init((String[])null, props);
+ }
+ return orb;
+ }
+
+ /**
+ * Replace substrings
+ *
+ * @param source The source string.
+ * @param match The string to search for within the source string.
+ * @param replace The replacement for any matching components.
+ * @return
+ */
+ private static String replace(String source, String match, String replace) {
+ int index = source.indexOf(match, 0);
+ if (index >= 0) {
+
+ // We have at least one match, so gotta do the
+ // work...
+
+ StringBuffer result = new StringBuffer(source.length() + 16);
+ int matchLength = match.length();
+ int startIndex = 0;
+
+ while (index >= 0) {
+ result.append(source.substring(startIndex, index));
+ result.append(replace);
+ startIndex = index + matchLength;
+ index = source.indexOf(match, startIndex);
+ }
+
+ // Grab the last piece, if any...
+ if (startIndex < source.length()) {
+ result.append(source.substring(startIndex));
+ }
+
+ return result.toString();
+
+ } else {
+ // No matches, just return the source...
+ return source;
+ }
+ }
+
+ /**
+ * Resovled the JNDI name from the initial CosNaming context
+ *
+ * @param jndiName
+ * @return resovled CORBA ojbect
+ * @throws NamingException
+ */
+ private static org.omg.CORBA.Object resovleString(NamingContextExt initCtx, String jndiName) throws NamingException {
+ try {
+ String name = stringify(jndiName);
+ return initCtx.resolve_str(name);
+ } catch (Exception e) {
+ NamingException ne = new NamingException(e.getMessage());
+ ne.setRootCause(e);
+ throw ne;
+ }
+ }
+
+ private NamingContextExt getCosNamingContext(String namingRoot) throws NamingException {
+ /*
+ * Using an ORB reference to get an initial naming reference There are
+ * two basic ways to get an initial CosNaming context. Both ways involve
+ * an ORB method invocation. The first way is to invoke the
+ * resolve_initial_references method on the ORB with an initial
+ * reference key. For this call to work, the ORB must be initialized
+ * with an initial reference for that key. The other way is to invoke
+ * the string_to_object method on the ORB, passing in a CORBA object URL
+ * with the host and port of the bootstrap server. The following
+ * examples illustrate both approaches.
+ */
+
+ /*
+ * Invoking resolve_initial_references Once an ORB reference is
+ * obtained, invoke the resolve_initial_references method on the ORB to
+ * obtain a reference to the initial context. The following code example
+ * invokes resolve_initial_reference on an ORB reference
+ */
+ try {
+ connect();
+ org.omg.CORBA.Object rootCtx = orb.resolve_initial_references(namingRoot);
+ return NamingContextExtHelper.narrow(rootCtx);
+ } catch (InvalidName e) {
+ InvalidNameException ne = new InvalidNameException(e.getMessage());
+ ne.setRootCause(e);
+ throw ne;
+ }
+ }
+
+ /**
+ * Look up a CORBA object by its JNDI name
+ *
+ * @param jndiName
+ * @return
+ * @throws NamingException
+ */
+ org.omg.CORBA.Object stringToObject(String jndiName) throws NamingException {
+ /*
+ * Using an existing ORB and invoking string_to_object with a CORBA
+ * object URL with multiple name server addresses to get an initial
+ * context CORBA object URLs can contain more than one bootstrap server
+ * address. Use this feature when attempting to obtain an initial
+ * context from a server cluster. You can specify the bootstrap server
+ * addresses for all servers in the cluster in the URL. The operation
+ * will succeed if at least one of the servers is running, eliminating a
+ * single point of failure. There is no guarantee of any particular
+ * order in which the address list will be processed. For example, the
+ * second bootstrap server address may be used to obtain the initial
+ * context even though the first bootstrap server in the list is
+ * available. An example of a corbaloc URL with multiple addresses
+ * follows. obj =
+ * orb.string_to_object("corbaloc::myhost1:9810,:myhost1:9811,:myhost2:9810/NameService");
+ */
+ String corbaName = null;
+ if (jndiName.startsWith("corbaloc:") || jndiName.startsWith("corbaname:")) {
+ // Keep the qualified URL
+ corbaName = jndiName;
+ } else {
+ // Create a corbaname URL
+ corbaName = getCorbaname(jndiName);
+ }
+
+ connect();
+ org.omg.CORBA.Object obj = orb.string_to_object(corbaName);
+ return obj;
+ }
+
+ private boolean isJndiConfigured() {
+ if (managed)
+ return true;
+ Boolean provided = (Boolean)AccessController.doPrivileged(new PrivilegedAction() {
+ public Object run() {
+ String initCtxFactory = System.getProperty(Context.INITIAL_CONTEXT_FACTORY);
+ if (initCtxFactory == null) {
+ URL file = Thread.currentThread().getContextClassLoader().getResource("jndi.properties");
+ if (file != null)
+ return Boolean.TRUE;
+ else
+ return Boolean.FALSE;
+ } else
+ return Boolean.TRUE;
+ }
+ });
+ return provided.booleanValue();
+ }
+
+ /**
+ * The character escape rules for the stringified name portion of an
+ * corbaname are: US-ASCII alphanumeric characters are not escaped.
+ * Characters outside this range are escaped, except for the following: ; / : ? @ & = + $ , - _ . ! ~ * ' ( )
+ * corbaname Escape Mechanism The percent '%' character is used as an
+ * escape. If a character that requires escaping is present in a name
+ * component it is encoded as two hexadecimal digits following a "%"
+ * character to represent the octet. (The first hexadecimal character
+ * represent the highorder nibble of the octet, the second hexadecimal
+ * character represents the low-order nibble.) If a '%' is not followed by
+ * two hex digits, the stringified name is syntactically invalid.
+ * @param s
+ * @return RFC2396-encoded stringified name
+ */
+ static String encode2396(String s) {
+ if (s == null)
+ return null;
+ StringBuffer encoded = new StringBuffer(s);
+ for (int i = 0; i < encoded.length(); i++) {
+ char c = encoded.charAt(i);
+ if (RFC2396.indexOf(c) == -1) {
+ encoded.setCharAt(i, '%');
+ char ac[] = Integer.toHexString(c).toCharArray();
+ if (ac.length == 2)
+ encoded.insert(i + 1, ac);
+ else if (ac.length == 1) {
+ encoded.insert(i + 1, '0');
+ encoded.insert(i + 2, ac[0]);
+ } else {
+ throw new IllegalArgumentException("Invalid character '" + c + "' in \"" + s + "\"");
+ }
+ i += 2;
+ }
+ }
+ return encoded.toString();
+ }
+
+ /**
+ * Decode an RFC2396-encoded string
+ *
+ * @param s
+ * @return Plain string
+ */
+ static String decode2396(String s) {
+ if (s == null)
+ return null;
+ StringBuffer decoded = new StringBuffer(s);
+ for (int i = 0; i < decoded.length(); i++) {
+ char c = decoded.charAt(i);
+ if (c == '%') {
+ if (i + 2 >= decoded.length())
+ throw new IllegalArgumentException("Incomplete key_string escape sequence");
+ int j;
+ j = HEX.indexOf(decoded.charAt(i + 1)) * 16 + HEX.indexOf(decoded.charAt(i + 2));
+ decoded.setCharAt(i, (char)j);
+ decoded.delete(i + 1, i + 3);
+ } else if (RFC2396.indexOf(c) == -1)
+ throw new IllegalArgumentException("Invalid key_string character '" + c + "'");
+ }
+ return decoded.toString();
+ }
+
+ /**
+ * The backslash '\' character escapes the reserved meaning of '/', '.', and
+ * '\' in a stringified name.
+ *
+ * @param jndiName
+ * @return Escaped stringified name for CosNaming
+ */
+ private static String stringify(String jndiName) {
+ // Esacpe . into \. since it's an INS naming delimeter
+ return replace(encode2396(jndiName), ".", "\\.");
+ }
+
+ /**
+ * Escape the "." into "%5C%2E"
+ *
+ * @param jndiName
+ * @return corbaname treating "." as a literal
+ */
+ private static String toCorbaname(String jndiName) {
+ // Esacpe . into %5C%2E (\.) since it's an INS naming delimeter
+ // For example, sca.sample.StockQuote --->
+ // sca%5C%2Esample%5C%2EStockQuote/StockQuote
+ return replace(encode2396(jndiName), ".", "%5C%2E");
+ }
+
+ private ObjectLocator getObjectLocator() throws NamingException {
+ if (locator != null)
+ return locator;
+ /*
+ * For managed env, jndi is assumed to be configured by default For
+ * unmanaged environment, jndi could have configured through
+ * jndi.properties file
+ */
+ if (isJndiConfigured()) {
+ locator = new JndiLocator();
+ } else { // this is definitely JSE env without jndi configured. Use
+ // Corba.
+ locator = new CosNamingLocator();
+ }
+ return locator;
+ }
+
+ public Object locate(String jndiName) throws NamingException {
+
+ Object result = getObjectLocator().locate(jndiName);
+ return result;
+ }
+
+ private static interface ObjectLocator {
+ public Object locate(String name) throws NamingException;
+ }
+
+ private class JndiLocator implements ObjectLocator {
+ private Context context;
+
+ private JndiLocator() throws NamingException {
+ this.context = new InitialContext();
+ }
+
+ private JndiLocator(Context context) {
+ this.context = context;
+ }
+
+ public Object locate(String name) throws NamingException {
+ try {
+ return context.lookup(name);
+ } catch (Exception e) {
+ e.printStackTrace();
+ return null;
+ }
+ }
+ }
+
+ private class CosNamingLocator implements ObjectLocator {
+ private NamingContextExt context = null;
+
+ private CosNamingLocator() {
+ }
+
+ private CosNamingLocator(NamingContextExt context) {
+ this.context = context;
+ }
+
+ public Object locate(String name) throws NamingException {
+ if (context != null)
+ return resovleString(context, name);
+ else
+ return stringToObject(name);
+ }
+ }
+
+ public void setHostEnv(boolean managed) {
+ this.managed = managed;
+ }
+}
diff --git a/branches/sca-java-0.91/modules/binding-ejb/src/main/java/org/apache/tuscany/sca/binding/ejb/util/EJBObjectFactory.java b/branches/sca-java-0.91/modules/binding-ejb/src/main/java/org/apache/tuscany/sca/binding/ejb/util/EJBObjectFactory.java
new file mode 100644
index 0000000000..1538c27716
--- /dev/null
+++ b/branches/sca-java-0.91/modules/binding-ejb/src/main/java/org/apache/tuscany/sca/binding/ejb/util/EJBObjectFactory.java
@@ -0,0 +1,188 @@
+/*
+ * 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.
+ */
+package org.apache.tuscany.sca.binding.ejb.util;
+
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.rmi.RemoteException;
+import java.rmi.UnexpectedException;
+
+import javax.ejb.CreateException;
+import javax.ejb.EJBLocalHome;
+import javax.naming.NamingException;
+import javax.rmi.CORBA.Util;
+
+import org.omg.CORBA.SystemException;
+import org.omg.CORBA.portable.ApplicationException;
+import org.omg.CORBA.portable.ObjectImpl;
+import org.omg.CORBA.portable.RemarshalException;
+import org.osoa.sca.ServiceRuntimeException;
+
+public class EJBObjectFactory {
+
+ private EJBObjectFactory() {
+ }
+
+ /**
+ * Get either a generated of dynamic EJB stub using the specified JNDI
+ * properties.
+ * <p>
+ * The returned stub will implement the specified stubInterface Interface.
+ * If the underlying EJB stub is not assignable from the specified
+ * stubInterface then a proxy is used to convert between the two.
+ * <p>
+ * The returned EJB stub may be either the pregenerated EJB stub or a
+ * dynamic stub. This allows a client to invoke an EJB without requiring any
+ * of the pregenerated EJB stub classes be avaiable in the classpath.
+ * <p>
+ */
+ public static Object createStub(NamingEndpoint namingEndpoint) throws NamingException, RemoteException,
+ CreateException {
+
+ EJBLocator locator = namingEndpoint.getLocator();
+ Object homeObject = locator.locate(namingEndpoint.getJndiName());
+ /*
+ * The type of the object returned from the lookup is as follows: If the
+ * generated stub exists on the classpath, it's an instance of that
+ * type, otherwise, "org.omg.stub.java.rmi._Remote_Stub" or
+ * "org.omg.stub.javax.ejb._EJBHome_Stub"
+ */
+ Object stub = getEJBStub(homeObject);
+ // Cache dynamic stub only
+ return stub;
+ }
+
+ /**
+ * @param homeObject
+ * @param ejbHomeClass
+ * @return
+ * @throws RemoteException
+ */
+ protected static Object getEJBStub(Object homeObject) throws RemoteException, CreateException {
+
+ Object stub = null;
+ if (homeObject instanceof EJBLocalHome) {
+ // Local EJB
+ stub = createEJBLocalObject(homeObject);
+ } else {
+ // Handle dynamic stub
+ if (homeObject instanceof ObjectImpl) {
+ ObjectImpl objectImpl = (ObjectImpl)homeObject;
+ stub = createEJBObject(objectImpl);
+ } /**
+ * Above checks will be satisfied if Bean is running on servers like Websphere. With this
+ * logic, client (SCA composite with EJB ref binding) doesn't need to include home class or
+ * client stubs.
+ *
+ * Below check is needed SCA composite with EJB ref binding is accessing openEJB implementation.
+ * For e.g if the bean is running on Geronimo.
+ */
+ else if ((javax.rmi.PortableRemoteObject.narrow(homeObject, javax.ejb.EJBHome.class)) instanceof javax.ejb.EJBHome) {
+ stub = createEJBObjectFromHome(homeObject);
+ } else
+ throw new ServiceRuntimeException("Invalid stub type: " + homeObject.getClass());
+ }
+ return stub;
+ }
+
+ /**
+ * Create a pre-generated EJB stub
+ *
+ * @param homeObject
+ * @return
+ * @throws RemoteException
+ */
+ protected static Object createEJBLocalObject(Object homeObject) throws RemoteException {
+
+ Object stub = null;
+ try {
+ // Find the "create()" method
+ Method createMethod = homeObject.getClass().getMethod("create", null);
+ // Create an EJB object
+ stub = createMethod.invoke(homeObject, null);
+ } catch (NoSuchMethodException e) {
+ // "create()" method not found, it's still a dynamic stub
+ stub = null;
+ } catch (InvocationTargetException e) {
+ throw new RemoteException(e.getTargetException().toString());
+ } catch (Exception e) {
+ throw new RemoteException(e.toString());
+ }
+ return stub;
+ }
+
+ /**
+ * Here homeObject is instance of EJBHome
+ *
+ * @param homeObject
+ * @return
+ * @throws RemoteException
+ */
+ protected static Object createEJBObjectFromHome(Object homeObject) throws RemoteException {
+
+ Object stub = null;
+ try {
+ // Find the "create()" method
+ Method createMethod = homeObject.getClass().getMethod("create", null);
+ // Create an EJB object
+ stub = createMethod.invoke(homeObject, null);
+ } catch (NoSuchMethodException e) {
+ // "create()" method not found, it's still a dynamic stub
+ stub = null;
+ } catch (InvocationTargetException e) {
+ throw new RemoteException(e.getTargetException().toString());
+ } catch (Exception e) {
+ throw new RemoteException(e.toString());
+ }
+ return stub;
+ }
+
+ /**
+ * Create an EJBObject using RMI/IIOP APIs
+ *
+ * @param ejbHomeObject
+ * @return The EJBObject remote stub
+ * @throws CreateException
+ * @throws RemoteException
+ */
+ protected static Object createEJBObject(ObjectImpl ejbHomeObject) throws CreateException, RemoteException {
+
+ try {
+ org.omg.CORBA_2_3.portable.InputStream in = null;
+ try {
+ org.omg.CORBA.portable.OutputStream out = ejbHomeObject._request("create", true);
+ in = (org.omg.CORBA_2_3.portable.InputStream)ejbHomeObject._invoke(out);
+ return (Object)in.read_Object(Object.class);
+ } catch (ApplicationException ex) {
+ in = (org.omg.CORBA_2_3.portable.InputStream)ex.getInputStream();
+ String id = in.read_string();
+ if (id.equals("IDL:javax/ejb/CreateEx:1.0")) {
+ throw (CreateException)in.read_value(CreateException.class);
+ }
+ throw new UnexpectedException(id);
+ } catch (RemarshalException ex) {
+ return createEJBObject(ejbHomeObject);
+ } finally {
+ ejbHomeObject._releaseReply(in);
+ }
+ } catch (SystemException ex) {
+ throw Util.mapSystemException(ex);
+ }
+ }
+}
diff --git a/branches/sca-java-0.91/modules/binding-ejb/src/main/java/org/apache/tuscany/sca/binding/ejb/util/EJBStubHelper.java b/branches/sca-java-0.91/modules/binding-ejb/src/main/java/org/apache/tuscany/sca/binding/ejb/util/EJBStubHelper.java
new file mode 100644
index 0000000000..ee05420cd7
--- /dev/null
+++ b/branches/sca-java-0.91/modules/binding-ejb/src/main/java/org/apache/tuscany/sca/binding/ejb/util/EJBStubHelper.java
@@ -0,0 +1,69 @@
+/*
+ * 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.
+ */
+package org.apache.tuscany.sca.binding.ejb.util;
+
+import java.rmi.RemoteException;
+
+import javax.ejb.CreateException;
+import javax.naming.NamingException;
+
+import org.osoa.sca.ServiceRuntimeException;
+import org.osoa.sca.ServiceUnavailableException;
+
+public class EJBStubHelper {
+
+ private static Object stub;
+ private static ServiceRuntimeException exception;
+
+ private EJBStubHelper() {
+ }
+
+ /**
+ * @param owner
+ * @param jndiName
+ * @return
+ */
+
+ public static Object lookup(NamingEndpoint endpoint) {
+ return getStub(endpoint);
+ }
+
+ public static Object getStub(NamingEndpoint namingEndpoint) {
+ try {
+ stub = EJBObjectFactory.createStub(namingEndpoint);
+ } catch (NamingException e) {
+ exception = new ServiceUnavailableException(e);
+ e.printStackTrace();
+ throw (ServiceUnavailableException)exception;
+ } catch (CreateException e) {
+ exception = new ServiceUnavailableException(e);
+ throw (ServiceUnavailableException)exception;
+ } catch (RemoteException e) {
+ exception = new ServiceRuntimeException(e);
+ throw (ServiceRuntimeException)exception;
+ }
+
+ if (exception == null) {
+ return stub; // Normal result
+ } else {
+ throw exception; // Throw the exception
+ }
+ }
+
+}
diff --git a/branches/sca-java-0.91/modules/binding-ejb/src/main/java/org/apache/tuscany/sca/binding/ejb/util/InterfaceInfo.java b/branches/sca-java-0.91/modules/binding-ejb/src/main/java/org/apache/tuscany/sca/binding/ejb/util/InterfaceInfo.java
new file mode 100644
index 0000000000..19f4063a12
--- /dev/null
+++ b/branches/sca-java-0.91/modules/binding-ejb/src/main/java/org/apache/tuscany/sca/binding/ejb/util/InterfaceInfo.java
@@ -0,0 +1,125 @@
+/*
+ * 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.
+ */
+package org.apache.tuscany.sca.binding.ejb.util;
+
+import java.io.Serializable;
+import java.lang.reflect.Method;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.WeakHashMap;
+
+import org.apache.tuscany.sca.binding.ejb.java2idl.Java2IDL;
+import org.apache.tuscany.sca.binding.ejb.java2idl.OperationType;
+
+// import commonj.sdo.DataObject;
+
+/**
+ * The signature for a java interface
+ */
+public class InterfaceInfo implements Serializable {
+
+ private static final Map interfaces = Collections.synchronizedMap(new WeakHashMap());
+
+ private static final long serialVersionUID = 2314533906465094860L;
+ private String name;
+
+ private Map methods = new HashMap();
+
+ public synchronized final static InterfaceInfo getInstance(final Class iface) {
+ InterfaceInfo info = (InterfaceInfo)interfaces.get(iface);
+ if (info == null) {
+ info = new InterfaceInfo(iface);
+ interfaces.put(iface, info);
+ }
+ return info;
+ }
+
+ public InterfaceInfo(final Class iface) {
+ super();
+ if (iface == null)
+ throw new IllegalArgumentException("The interface cannot be null");
+ this.name = iface.getName();
+ // SECURITY
+ /*
+ * Permission: accessDeclaredMembers : Access denied
+ * (java.lang.RuntimePermission accessDeclaredMembers)
+ */
+ Map idlNames = (Map)AccessController.doPrivileged(new PrivilegedAction() {
+ public Object run() {
+ return Java2IDL.getIDLMapping(iface);
+ }
+ });
+ Iterator i = idlNames.entrySet().iterator();
+ while (i.hasNext()) {
+ Map.Entry entry = (Map.Entry)i.next();
+ Method method = (Method)entry.getKey();
+ OperationType operationType = (OperationType)entry.getValue();
+ MethodInfo methodInfo = new MethodInfo(method);
+ methodInfo.setIDLName(operationType.getIDLName());
+ methods.put(method.getName(), methodInfo);
+ }
+ }
+
+ /*
+ * public InterfaceInfo(String portType, String wsdlOperationName) {
+ * super(); this.name = portType; // <DataObject> operation(<DataObject>)
+ * throws RemoteException MethodInfo method = new
+ * MethodInfo(wsdlOperationName, DataObject.class.getName(), new
+ * String[]{DataObject.class.getName()}, new
+ * String[]{RemoteException.class.getName()}); methods.put(method.getName(),
+ * method); }
+ */
+
+ /**
+ * @return
+ */
+ public Map getMethods() {
+ return methods;
+ }
+
+ /**
+ * @return
+ */
+ public MethodInfo getMethod(String name) {
+ return (MethodInfo)methods.get(name);
+ }
+
+ /**
+ * @return
+ */
+ public String getName() {
+ return name;
+ }
+
+ public String toString() {
+ StringBuffer sb = new StringBuffer();
+ sb.append("interface ").append(name).append("{ \n");
+ Iterator i = methods.values().iterator();
+ while (i.hasNext()) {
+ MethodInfo methodInfo = (MethodInfo)i.next();
+ sb.append("\t").append(methodInfo).append("\n");
+ }
+ sb.append("};\n");
+ return sb.toString();
+ }
+}
diff --git a/branches/sca-java-0.91/modules/binding-ejb/src/main/java/org/apache/tuscany/sca/binding/ejb/util/JavaReflectionAdapter.java b/branches/sca-java-0.91/modules/binding-ejb/src/main/java/org/apache/tuscany/sca/binding/ejb/util/JavaReflectionAdapter.java
new file mode 100644
index 0000000000..db762aeb13
--- /dev/null
+++ b/branches/sca-java-0.91/modules/binding-ejb/src/main/java/org/apache/tuscany/sca/binding/ejb/util/JavaReflectionAdapter.java
@@ -0,0 +1,155 @@
+/*
+ * 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.
+ */
+package org.apache.tuscany.sca.binding.ejb.util;
+
+import java.beans.PropertyDescriptor;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.WeakHashMap;
+
+import org.osoa.sca.ServiceRuntimeException;
+
+/**
+ * An adapter for java classes, indexes the methods by name and provides an
+ * invoke method that takes a method name.
+ */
+public class JavaReflectionAdapter {
+
+ private static Map adapters = Collections.synchronizedMap(new WeakHashMap());
+
+ private Class clazz;
+ private Map methodMap = new HashMap();
+
+ /**
+ * Create a java reflection adapter
+ *
+ * @param clazz
+ */
+ public synchronized static JavaReflectionAdapter createJavaReflectionAdapter(Class clazz) {
+ JavaReflectionAdapter adapter = (JavaReflectionAdapter)adapters.get(clazz);
+ if (adapter == null) {
+ adapter = new JavaReflectionAdapter(clazz);
+ adapters.put(clazz, adapter);
+ }
+ return adapter;
+ }
+
+ /**
+ * Constructor
+ *
+ * @param clazz
+ */
+ private JavaReflectionAdapter(final Class clazz) {
+ this.clazz = clazz;
+
+ // Index the methods on the implementation class
+ Method[] methods = (Method[])AccessController.doPrivileged(new PrivilegedAction() {
+ public Object run() {
+ return clazz.getMethods();
+ }
+ });
+ for (int i = 0, n = methods.length; i < n; i++) {
+ methodMap.put(methods[i].getName(), methods[i]);
+ }
+ }
+
+ /**
+ * Returns a map containing the methods on the class, keyed by name
+ *
+ * @return
+ */
+ public Map getMethods() {
+ return methodMap;
+ }
+
+ /**
+ * Return the specified method
+ *
+ * @param methodName
+ * @return
+ * @throws NoSuchMethodException
+ */
+ public Method getMethod(String methodName) throws NoSuchMethodException {
+
+ Method method = (Method)methodMap.get(methodName);
+ if (method == null)
+ throw new NoSuchMethodException(methodName);
+ return method;
+ }
+
+ private final static Map DEFAULT_PRIMITIVE_VALUES = new HashMap();
+ static {
+ DEFAULT_PRIMITIVE_VALUES.put(boolean.class, Boolean.FALSE);
+ DEFAULT_PRIMITIVE_VALUES.put(byte.class, new Byte((byte)0));
+ DEFAULT_PRIMITIVE_VALUES.put(char.class, new Character((char)0));
+ DEFAULT_PRIMITIVE_VALUES.put(short.class, new Short((short)0));
+ DEFAULT_PRIMITIVE_VALUES.put(int.class, new Integer(0));
+ DEFAULT_PRIMITIVE_VALUES.put(long.class, new Long(0));
+ DEFAULT_PRIMITIVE_VALUES.put(float.class, new Float(0.0));
+ DEFAULT_PRIMITIVE_VALUES.put(double.class, new Double(0.0));
+ }
+
+ /**
+ * Invoke a method using Java reflection.
+ *
+ * @param method
+ * @param object
+ * @param args
+ * @return
+ * @throws InvocationTargetException
+ * @throws IllegalAccessException
+ */
+ public Object invoke(Method method, Object object, Object[] args) throws InvocationTargetException,
+ IllegalAccessException {
+ Class[] parameterTypes = method.getParameterTypes();
+ for (int i = 0; i < parameterTypes.length; i++) {
+ Class parameterType = parameterTypes[i];
+ if (args[i] == null && parameterType.isPrimitive()) {
+ args[i] = DEFAULT_PRIMITIVE_VALUES.get(parameterType);
+ }
+ }
+ return method.invoke(object, args);
+ }
+
+ /**
+ * Set the java bean property
+ *
+ * @param bean
+ * @param propertyName
+ * @param value
+ * @return
+ */
+ public boolean setProperty(Object bean, String propertyName, Object value) {
+ try {
+ PropertyDescriptor propertyDescriptor = new PropertyDescriptor(propertyName, bean.getClass());
+ Method writeMethod = propertyDescriptor.getWriteMethod();
+ writeMethod.invoke(bean, new Object[] {value});
+ return true;
+ } catch (InvocationTargetException e) {
+ throw new ServiceRuntimeException(e.getTargetException());
+ } catch (Exception e) {
+ return false;
+ }
+ }
+}
diff --git a/branches/sca-java-0.91/modules/binding-ejb/src/main/java/org/apache/tuscany/sca/binding/ejb/util/MethodInfo.java b/branches/sca-java-0.91/modules/binding-ejb/src/main/java/org/apache/tuscany/sca/binding/ejb/util/MethodInfo.java
new file mode 100644
index 0000000000..ac3ace2d6c
--- /dev/null
+++ b/branches/sca-java-0.91/modules/binding-ejb/src/main/java/org/apache/tuscany/sca/binding/ejb/util/MethodInfo.java
@@ -0,0 +1,176 @@
+/*
+ * 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.
+ */
+package org.apache.tuscany.sca.binding.ejb.util;
+
+import java.io.Serializable;
+import java.lang.reflect.Method;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * MetaData for a java method
+ */
+public class MethodInfo implements Serializable {
+
+ /** Automatically generated javadoc for: serialVersionUID */
+ private static final long serialVersionUID = -5557260979514687514L;
+ private String name;
+ private String returnType;
+ private String[] parameterTypes;
+ private String[] exceptionTypes;
+
+ private String IDLName;
+
+ /**
+ * Type Signature Java Type -------------- --------- Z boolean B byte C char
+ * S short I int J long F float D double L fully-qualified-class ;
+ * fully-qualified-class [ type type[] ( arg-types ) ret-type method type
+ */
+ private final static Map signatures = new HashMap();
+ static {
+ signatures.put("Z", boolean.class);
+ signatures.put("B", byte.class);
+ signatures.put("C", char.class);
+ signatures.put("S", short.class);
+ signatures.put("I", int.class);
+ signatures.put("J", long.class);
+ signatures.put("F", float.class);
+ signatures.put("D", double.class);
+ signatures.put("V", void.class);
+ }
+
+ public MethodInfo(Method method) {
+ this.name = method.getName();
+ // this.declaringClass = method.getDeclaringClass().getName();
+ this.returnType = method.getReturnType().getName();
+ Class[] types = method.getParameterTypes();
+ this.parameterTypes = new String[types.length];
+ for (int i = 0; i < types.length; i++) {
+ this.parameterTypes[i] = types[i].getName();
+ }
+ types = method.getExceptionTypes();
+ this.exceptionTypes = new String[types.length];
+ for (int i = 0; i < types.length; i++) {
+ this.exceptionTypes[i] = types[i].getName();
+ }
+ IDLName = this.name;
+ }
+
+ protected MethodInfo(String name, String returnType, String[] parameterTypes, String[] exceptionTypes) {
+ this.name = name;
+ this.returnType = returnType;
+ this.parameterTypes = parameterTypes;
+ this.exceptionTypes = exceptionTypes;
+ this.IDLName = name;
+ }
+
+ /**
+ * Parse the class name from the internal signature Sample signatures: int
+ * ---> I; int[] ---> [I Object ---> java/lang/Object Object[] --->
+ * [Ljava/lang/Object;
+ *
+ * @param value
+ * @return
+ */
+ private static String getName(String signature) {
+ String name = signature;
+ // Remove leading ARRAY ([) signatures
+ int index = name.lastIndexOf('[');
+ if (index != -1)
+ name = name.substring(index + 1);
+
+ // Remove L<...>;
+ if (name.charAt(0) == 'L' && name.charAt(name.length() - 1) == ';')
+ name = name.substring(1, name.length() - 1);
+
+ // Primitive types
+ Class primitiveClass = (Class)signatures.get(name);
+ if (primitiveClass != null) {
+ name = primitiveClass.getName();
+ }
+
+ for (int i = 0; i < index + 1; i++) {
+ name = name + "[]";
+ }
+ return name;
+ }
+
+ /**
+ * @return
+ */
+ public String getName() {
+ return name;
+ }
+
+ /**
+ * @return
+ */
+ public String[] getParameterTypes() {
+ return parameterTypes;
+ }
+
+ /**
+ * @return
+ */
+ public String getReturnType() {
+ return returnType;
+ }
+
+ /**
+ * @return
+ */
+ public String[] getExceptionTypes() {
+ return exceptionTypes;
+ }
+
+ public String toString() {
+ StringBuffer sb = new StringBuffer();
+ sb.append(getName(returnType)).append(" ").append(name).append("(");
+ for (int j = 0; j < parameterTypes.length; j++) {
+ sb.append(getName(parameterTypes[j])).append(" ").append("arg" + j);
+ if (j < (parameterTypes.length - 1))
+ sb.append(", ");
+ }
+ sb.append(")");
+ if (exceptionTypes.length > 0) {
+ sb.append(" throws ");
+ for (int k = 0; k < exceptionTypes.length; k++) {
+ sb.append(exceptionTypes[k]);
+ if (k < (exceptionTypes.length - 1))
+ sb.append(", ");
+ }
+ }
+ sb.append(";");
+ return sb.toString();
+ }
+
+ /**
+ * @return Returns the iDLName.
+ */
+ public String getIDLName() {
+ return IDLName;
+ }
+
+ /**
+ * @param name The iDLName to set.
+ */
+ public void setIDLName(String name) {
+ IDLName = name;
+ }
+}
diff --git a/branches/sca-java-0.91/modules/binding-ejb/src/main/java/org/apache/tuscany/sca/binding/ejb/util/NamingEndpoint.java b/branches/sca-java-0.91/modules/binding-ejb/src/main/java/org/apache/tuscany/sca/binding/ejb/util/NamingEndpoint.java
new file mode 100644
index 0000000000..5d4b91d0f9
--- /dev/null
+++ b/branches/sca-java-0.91/modules/binding-ejb/src/main/java/org/apache/tuscany/sca/binding/ejb/util/NamingEndpoint.java
@@ -0,0 +1,118 @@
+/*
+ * 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.
+ */
+package org.apache.tuscany.sca.binding.ejb.util;
+
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+
+public class NamingEndpoint {
+ private String jndiName;
+ private EJBLocator locator;
+ private boolean managed = true;
+
+ public NamingEndpoint(String hostName, int port, String jndiName) {
+ this.jndiName = jndiName;
+ this.locator = new EJBLocator(hostName, port);
+ }
+
+ public NamingEndpoint(String name) {
+
+ /**
+ * by default it's a managed environment means SCA composite with ref binding is running on
+ * an AppServer. If running on J2SE, pass -Dmanaged=false for the VM
+ */
+ String managedEnv = (String)AccessController.doPrivileged(new PrivilegedAction() {
+ public Object run() {
+ return System.getProperty("managed");
+ }
+ });
+
+ if (managedEnv != null)
+ managed = new Boolean(managedEnv);
+
+ if ((!managed) && name.startsWith("corbaname:iiop:")) {
+ /**
+ * if (name.startsWith("corbaname:iiop:")) { corbaname:iiop:<hostName>:<port>/<root>#name
+ * For exmaple,
+ * "corbaname:iiop:localhost:2809/NameServiceServerRoot#ejb/MyEJBHome";
+ */
+
+ String[] parts = split(name, '#');
+ if (parts.length != 2)
+ throw new IllegalArgumentException("Invalid corbaname: " + name);
+
+ this.jndiName = parts[1]; // The logical jndi name
+ this.locator = new EJBLocator(parts[0], managed);
+
+ } else {
+ this.jndiName = name;
+ this.locator = new EJBLocator(managed);
+ }
+
+ }
+
+ private static String[] split(String str, char ch) {
+ int index = str.lastIndexOf(ch);
+ if (index == -1) {
+ return new String[] {str, ""};
+ } else {
+ return new String[] {str.substring(0, index), str.substring(index + 1)};
+ }
+ }
+
+ /**
+ * @return Returns the jndiName.
+ */
+ public String getJndiName() {
+ return jndiName;
+ }
+
+ public EJBLocator getLocator() {
+ return locator;
+ }
+
+ public String getCorbaname() {
+ return locator.getCorbaname(jndiName);
+ }
+
+ /**
+ * @see java.lang.Object#equals(java.lang.Object)
+ */
+ public boolean equals(Object obj) {
+ if (obj instanceof NamingEndpoint) {
+ NamingEndpoint endpoint = (NamingEndpoint)obj;
+ return jndiName.equals(endpoint.jndiName);
+ }
+ return false;
+ }
+
+ /**
+ * @see java.lang.Object#hashCode()
+ */
+ public int hashCode() {
+ return jndiName.hashCode();
+ }
+
+ /**
+ * @see java.lang.Object#toString()
+ */
+ public String toString() {
+ return jndiName;
+ }
+}
diff --git a/branches/sca-java-0.91/modules/binding-ejb/src/main/resources/META-INF/services/org.apache.tuscany.sca.spi.BindingActivator b/branches/sca-java-0.91/modules/binding-ejb/src/main/resources/META-INF/services/org.apache.tuscany.sca.spi.BindingActivator
new file mode 100644
index 0000000000..1e69e1a07c
--- /dev/null
+++ b/branches/sca-java-0.91/modules/binding-ejb/src/main/resources/META-INF/services/org.apache.tuscany.sca.spi.BindingActivator
@@ -0,0 +1,19 @@
+# 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.
+# Implementation class for the ExtensionActivator
+org.apache.tuscany.sca.binding.ejb.EJBBindingActivator
+