Author: dblevins
Date: Tue Aug 14 18:25:15 2007
New Revision: 565996

URL: http://svn.apache.org/viewvc?view=rev&rev=565996
Log:
Improved proxy creation code so that for business interfaces it includes as 
many interfaces as possible

Added:
    
openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/ProxyInterfaceResolver.java
    
openejb/trunk/openejb3/container/openejb-core/src/test/java/org/apache/openejb/assembler/classic/ProxyInterfaceResolverTest.java
Modified:
    
openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/JndiBuilder.java

Modified: 
openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/JndiBuilder.java
URL: 
http://svn.apache.org/viewvc/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/JndiBuilder.java?view=diff&rev=565996&r1=565995&r2=565996
==============================================================================
--- 
openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/JndiBuilder.java
 (original)
+++ 
openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/JndiBuilder.java
 Tue Aug 14 18:25:15 2007
@@ -19,9 +19,11 @@
 import javax.naming.Context;
 import javax.naming.NamingException;
 import javax.naming.Reference;
+import javax.naming.NameAlreadyBoundException;
 import javax.jms.MessageListener;
 
 import org.apache.openejb.DeploymentInfo;
+import org.apache.openejb.InterfaceType;
 import org.apache.openejb.util.LogCategory;
 import org.apache.openejb.util.Logger;
 import org.apache.openejb.loader.SystemInstance;
@@ -36,6 +38,7 @@
 import java.util.ArrayList;
 import java.util.Map;
 import java.util.HashMap;
+import java.util.Comparator;
 
 
 /**
@@ -77,7 +80,58 @@
 
         public static enum Interface {
 
-            REMOTE_HOME, LOCAL_HOME, BUSINESS_LOCAL, BUSINESS_REMOTE, 
SERVICE_ENDPOINT
+            REMOTE_HOME(InterfaceType.EJB_HOME, "RemoteHome", "home", ""),
+            LOCAL_HOME(InterfaceType.EJB_LOCAL_HOME, "LocalHome", 
"local-home", "Local"),
+            BUSINESS_LOCAL(InterfaceType.BUSINESS_LOCAL, "Local", 
"business-local", "BusinessLocal"),
+            BUSINESS_REMOTE(InterfaceType.BUSINESS_REMOTE, "Remote", 
"business-remote", "BusinessRemote"),
+            SERVICE_ENDPOINT(InterfaceType.SERVICE_ENDPOINT, "Endpoint", 
"service-endpoint", "ServiceEndpoint");
+
+            private final InterfaceType type;
+            private final String annotatedName;
+            private final String xmlName;
+            private final String xmlNameCc;
+            private final String openejbLegacy;
+
+            Interface(InterfaceType type, String annotatedName, String 
xmlName, String openejbLegacy) {
+                this.type = type;
+                this.annotatedName = annotatedName;
+                this.xmlName = xmlName;
+                this.xmlNameCc = camelCase(xmlName);
+                this.openejbLegacy = openejbLegacy;
+            }
+
+            private String camelCase(String string){
+                StringBuilder sb = new StringBuilder();
+                String[] strings = string.split("-");
+                for (String s : strings) {
+                    int l = sb.length();
+                    sb.append(s);
+                    sb.setCharAt(l, Character.toUpperCase(sb.charAt(l)));
+                }
+                return sb.toString();
+            }
+
+
+            public InterfaceType getType() {
+                return type;
+            }
+
+            public String getAnnotatedName() {
+                return annotatedName;
+            }
+
+            public String getXmlName() {
+                return xmlName;
+            }
+
+            public String getXmlNameCc() {
+                return xmlNameCc;
+            }
+
+            public String getOpenejbLegacy() {
+                return openejbLegacy;
+            }
+
         }
 
         public String getName(DeploymentInfo deploymentInfo, Class interfce, 
Interface type);
@@ -101,7 +155,10 @@
             contextData.put("ejbClass.simpleName", 
deploymentInfo.getBeanClass().getSimpleName());
             contextData.put("ejbName", deploymentInfo.getEjbName());
             contextData.put("deploymentId", 
deploymentInfo.getDeploymentID().toString());
-            contextData.put("interfaceType", 
deploymentInfo.getInterfaceType(interfce).name());
+            contextData.put("interfaceType", type.annotatedName);
+            contextData.put("interfaceType.xmlName", type.getXmlName());
+            contextData.put("interfaceType.xmlNameCc", type.getXmlNameCc());
+            contextData.put("interfaceType.openejbLegacyName", 
type.getOpenejbLegacy());
             contextData.put("interfaceClass", interfce.getName());
             contextData.put("interfaceClass.simpleName", 
interfce.getSimpleName());
             return template.apply(contextData);
@@ -198,7 +255,7 @@
             Class homeInterface = deployment.getHomeInterface();
             if (homeInterface != null) {
 
-                String name = "openejb/ejb/" + strategy.getName(deployment, 
deploymentInfo.getRemoteInterface(), JndiNameStrategy.Interface.REMOTE_HOME);
+                String name = "openejb/ejb/" + strategy.getName(deployment, 
deploymentInfo.getHomeInterface(), JndiNameStrategy.Interface.REMOTE_HOME);
                 ObjectReference ref = new 
ObjectReference(deployment.getEJBHome());
                 bind(name, ref, bindings, beanInfo);
 
@@ -213,7 +270,7 @@
             Class localHomeInterface = deployment.getLocalHomeInterface();
             if (localHomeInterface != null) {
 
-                String name = "openejb/ejb/" + strategy.getName(deployment, 
deploymentInfo.getLocalInterface(), JndiNameStrategy.Interface.LOCAL_HOME);
+                String name = "openejb/ejb/" + strategy.getName(deployment, 
deploymentInfo.getLocalHomeInterface(), JndiNameStrategy.Interface.LOCAL_HOME);
                 ObjectReference ref = new 
ObjectReference(deployment.getEJBLocalHome());
                 bind(name, ref, bindings, beanInfo);
 
@@ -225,25 +282,22 @@
         }
 
         try {
-            Class businessLocalInterface = 
deployment.getBusinessLocalInterface();
-            if (businessLocalInterface != null) {
+            List<Class> localInterfaces = 
deployment.getBusinessLocalInterfaces();
+            Class beanClass = deployment.getBeanClass();
 
-                String name = "openejb/ejb/" + strategy.getName(deployment, 
businessLocalInterface, JndiNameStrategy.Interface.BUSINESS_LOCAL);
-                DeploymentInfo.BusinessLocalHome businessLocalHome = 
deployment.getBusinessLocalHome();
-                bind(name, new BusinessLocalReference(businessLocalHome), 
bindings, beanInfo);
-
-                for (Class interfce : deployment.getBusinessLocalInterfaces()) 
{
-                    DeploymentInfo.BusinessLocalHome home = 
deployment.getBusinessLocalHome(asList(interfce));
-                    BusinessLocalReference ref = new 
BusinessLocalReference(home);
-
-                    name = "openejb/Deployment/" + 
deployment.getDeploymentID() + "/" + interfce.getName();
-                    bind(name, ref, bindings, beanInfo);
-
-                    try {
-                        name = "openejb/ejb/" + strategy.getName(deployment, 
interfce, JndiNameStrategy.Interface.BUSINESS_LOCAL);
-                        bind(name, ref, bindings, beanInfo);
-                    } catch (NamingException dontCareJustYet) {
-                    }
+            for (Class interfce : deployment.getBusinessLocalInterfaces()) {
+
+                List<Class> interfaces = 
ProxyInterfaceResolver.getInterfaces(beanClass, interfce, localInterfaces);
+                DeploymentInfo.BusinessLocalHome home = 
deployment.getBusinessLocalHome(interfaces);
+                BusinessLocalReference ref = new BusinessLocalReference(home);
+
+                String internalName = "openejb/Deployment/" + 
deployment.getDeploymentID() + "/" + interfce.getName();
+                bind(internalName, ref, bindings, beanInfo);
+
+                try {
+                    String externalName = "openejb/ejb/" + 
strategy.getName(deployment, interfce, 
JndiNameStrategy.Interface.BUSINESS_LOCAL);
+                    bind(externalName, ref, bindings, beanInfo);
+                } catch (NamingException dontCareJustYet) {
                 }
             }
         } catch (NamingException e) {
@@ -251,27 +305,23 @@
         }
 
         try {
-            Class businessRemoteInterface = 
deployment.getBusinessRemoteInterface();
-            if (businessRemoteInterface != null) {
 
-                DeploymentInfo.BusinessRemoteHome businessRemoteHome = 
deployment.getBusinessRemoteHome();
-                BusinessRemoteReference ref = new 
BusinessRemoteReference(businessRemoteHome);
+            List<Class> remoteInterfaces = 
deployment.getBusinessRemoteInterfaces();
+            Class beanClass = deployment.getBeanClass();
 
-                String name = "openejb/ejb/" + strategy.getName(deployment, 
businessRemoteInterface, JndiNameStrategy.Interface.BUSINESS_REMOTE);
-                bind(name, ref, bindings, beanInfo);
+            for (Class interfce : deployment.getBusinessRemoteInterfaces()) {
 
-                for (Class interfce : 
deployment.getBusinessRemoteInterfaces()) {
-                    DeploymentInfo.BusinessRemoteHome home = 
deployment.getBusinessRemoteHome(asList(interfce));
-                    ref = new BusinessRemoteReference(home);
-
-                    name = "openejb/Deployment/" + 
deployment.getDeploymentID() + "/" + interfce.getName();
-                    bind(name, ref, bindings, beanInfo);
-
-                    try {
-                        name = "openejb/ejb/" + strategy.getName(deployment, 
interfce, JndiNameStrategy.Interface.BUSINESS_REMOTE);
-                        bind(name, ref, bindings, beanInfo);
-                    } catch (NamingException dontCareJustYet) {
-                    }
+                List<Class> interfaces = 
ProxyInterfaceResolver.getInterfaces(beanClass, interfce, remoteInterfaces);
+                DeploymentInfo.BusinessRemoteHome home = 
deployment.getBusinessRemoteHome(interfaces);
+                BusinessRemoteReference ref = new 
BusinessRemoteReference(home);
+
+                String internalName = "openejb/Deployment/" + 
deployment.getDeploymentID() + "/" + interfce.getName();
+                bind(internalName, ref, bindings, beanInfo);
+
+                try {
+                    String externalName = "openejb/ejb/" + 
strategy.getName(deployment, interfce, 
JndiNameStrategy.Interface.BUSINESS_REMOTE);
+                    bind(externalName, ref, bindings, beanInfo);
+                } catch (NamingException dontCareJustYet) {
                 }
             }
         } catch (NamingException e) {
@@ -295,14 +345,26 @@
 
 
     private void bind(String name, Reference ref, Bindings bindings, 
EnterpriseBeanInfo beanInfo) throws NamingException {
-        context.bind(name, ref);
-        bindings.add(name);
+
         if (name.startsWith("openejb/ejb/")) {
-            name = name.replaceFirst("openejb/ejb/", "");
-            logger.info("Jndi(name=" + name+")");
-            if (!beanInfo.jndiNames.contains(name)){
-                beanInfo.jndiNames.add(name);
+
+            String externalName = name.replaceFirst("openejb/ejb/", "");
+
+            if (beanInfo.jndiNames.contains(externalName)){
+                logger.debug("Duplicate: Jndi(name=" + externalName +")");
+                return;
             }
+
+            beanInfo.jndiNames.add(externalName);
+            logger.info("Jndi(name=" + externalName +")");
+        }
+
+        try {
+            context.bind(name, ref);
+            bindings.add(name);
+        } catch (NameAlreadyBoundException e) {
+            logger.error("Jndi name could not be bound; it may be taken by 
another ejb.  Jndi(name=" + name +")");
+            throw e;
         }
     }
 
@@ -321,6 +383,17 @@
 
         public boolean add(String o) {
             return bindings.add(o);
+        }
+    }
+
+    public static class RemoteInterfaceComparator implements Comparator<Class> 
{
+
+        public int compare(java.lang.Class a, java.lang.Class b) {
+            boolean aIsRmote = java.rmi.Remote.class.isAssignableFrom(a);
+            boolean bIsRmote = java.rmi.Remote.class.isAssignableFrom(b);
+
+            if (aIsRmote == bIsRmote) return 0;
+            return (aIsRmote)? 1: -1;
         }
     }
 }

Added: 
openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/ProxyInterfaceResolver.java
URL: 
http://svn.apache.org/viewvc/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/ProxyInterfaceResolver.java?view=auto&rev=565996
==============================================================================
--- 
openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/ProxyInterfaceResolver.java
 (added)
+++ 
openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/ProxyInterfaceResolver.java
 Tue Aug 14 18:25:15 2007
@@ -0,0 +1,205 @@
+/**
+ * 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.openejb.assembler.classic;
+
+import java.util.List;
+import java.util.ArrayList;
+import java.lang.reflect.Method;
+
+/**
+ * @version $Rev$ $Date$
+ */
+public class ProxyInterfaceResolver {
+
+    public static List<Class> getInterfaces(Class implementation, Class 
mainInterface, List<Class> interfaces){
+        List<Class> valid = new ArrayList<Class>();
+        // The intended interface is safe to add
+        valid.add(mainInterface);
+
+        // Any interface the bean implements is safe (potentially)
+        for (Class interfce : interfaces) {
+            if (interfce.isAssignableFrom(implementation)){
+                valid.add(interfce);
+            }
+        }
+
+
+        // Here comes the trick, if any of them implement java.rmi.Remote
+        // we have to check the "remote" methods against the other methods
+        // of the same name and params to see if there are any conflicts in
+        // the exception clauses.  If there are, then we need to remove the
+        // conflicting interface(s).
+        //
+        // DETAILS:
+        // The trick is that two nearly matching interface methods
+        //   -InterfaceA: void doIt() throws Foo;
+        //   -InterfaceB: void doIt() throws Bar;
+        //
+        // can be implemented in a class by leaving out exceptions from the
+        // throws clause that aren't declared in both interfaces methods.
+        //   -Implementation:  void doIt(){}
+        //
+        // This means the implementing class can not throw Foo or Bar.  The
+        // same rule applies to proxies created from these two interfaces as
+        // the proxy generating code will automatically remove exceptions
+        // not shared by the two matching interface methods; eliminating
+        // the proxy's and therefore container's ability to throw those
+        // exceptions.
+        //
+        // The specific issue with java.rmi.Remote interfaces is that per
+        // spec rules many runtime exceptions (container or connection issues)
+        // are thrown to clients as java.rmi.RemoteException which is not
+        // a runtime exception and must be throwable via the proxy.
+
+
+        List<Class> remotes = new ArrayList<Class>();
+        List<Class> nonremotes = new ArrayList<Class>();
+        for (Class interfce : valid) {
+            if (java.rmi.Remote.class.isAssignableFrom(interfce)){
+                remotes.add(interfce);
+            } else {
+                nonremotes.add(interfce);
+            }
+        }
+
+        // No remote interfaces, we're good to go
+        if (remotes.size() == 0) return valid;
+
+        // -----------------------------------------------------------
+        // If we got here, we have potentially clashing interfaces
+        // We sort of have to start over and go "slower" checking
+        // methods for conflicts and not including those interfaces
+        // -----------------------------------------------------------
+
+        valid.clear();
+        remotes.remove(mainInterface);
+        nonremotes.remove(mainInterface);
+
+        // Re-add the main interface
+        valid.add(mainInterface);
+
+        // Track the method signatures of the interfaces we add
+        List<Signature> proxySignatures = getSignatures(mainInterface);
+
+
+        // Show affinity for the remote interfaces if the main
+        // interface is a java.rmi.Remote
+        if (java.rmi.Remote.class.isAssignableFrom(mainInterface)){
+            for (Class interfce : remotes) {
+                addIfNotConflicting(interfce, valid, proxySignatures);
+            }
+            for (Class interfce : nonremotes) {
+                addIfNotConflicting(interfce, valid, proxySignatures);
+            }
+        } else {
+            for (Class interfce : nonremotes) {
+                addIfNotConflicting(interfce, valid, proxySignatures);
+            }
+            for (Class interfce : remotes) {
+                addIfNotConflicting(interfce, valid, proxySignatures);
+            }
+        }
+
+        return valid;
+    }
+
+    /**
+     * Adds the interface to the list of valid interfaces for the proxy
+     * if the signatures on the interface do not conflict with the method
+     * signatures already apart of the proxy's other interfaces.
+     *
+     * @param interfce
+     * @param valid
+     * @param proxySignatures
+     */
+    private static void addIfNotConflicting(Class interfce, List<Class> valid, 
List<Signature> proxySignatures) {
+
+        List<Signature> interfaceSigs = getSignatures(interfce);
+
+
+        for (Signature sig : interfaceSigs) {
+            // Contains will return true if the
+            // method signature exits *and* has
+            // a different throws clause
+            if (proxySignatures.contains(sig)){
+                 return;  // conflicts and cannot be added
+            }
+        }
+
+
+        // Does not conflict, add it and track the new signatures
+        valid.add(interfce);
+        proxySignatures.addAll(interfaceSigs);
+    }
+
+    private static List<Signature> getSignatures(Class mainInterface) {
+        List<Signature> sigs = new ArrayList<Signature>();
+        for (Method method : mainInterface.getMethods()) {
+            sigs.add(new Signature(mainInterface, method));
+        }
+        return sigs;
+    }
+
+    public static class Signature {
+        private final Class clazz;
+        private final Method method;
+        private final String sig;
+
+        public Signature(Class clazz, Method method) {
+            this.clazz = clazz;
+            this.method = method;
+            StringBuilder sb = new StringBuilder();
+            sb.append(method.getName());
+            sb.append('(');
+            for (Class<?> type : method.getParameterTypes()) {
+                sb.append(type.getName());
+                sb.append(',');
+            }
+            sb.append(')');
+            sig = sb.toString();
+        }
+
+        public Method getMethod() {
+            return method;
+        }
+
+        // This equals returns true only if the method signatures
+        // are the same *and* one is remote and one is not
+        public boolean equals(Object o) {
+            if (this == o) return true;
+            if (o == null || getClass() != o.getClass()) return false;
+
+            final Signature signature = (Signature) o;
+
+            if (!sig.equals(signature.sig)) return false;
+
+            boolean aIsRemote = java.rmi.Remote.class.isAssignableFrom(clazz);
+            boolean bIsRemote = 
java.rmi.Remote.class.isAssignableFrom(signature.clazz);
+
+            return !(aIsRemote == bIsRemote);
+        }
+
+        public int hashCode() {
+            return sig.hashCode();
+        }
+
+        public String toString() {
+            return method.toString();
+        }
+    }
+
+}

Added: 
openejb/trunk/openejb3/container/openejb-core/src/test/java/org/apache/openejb/assembler/classic/ProxyInterfaceResolverTest.java
URL: 
http://svn.apache.org/viewvc/openejb/trunk/openejb3/container/openejb-core/src/test/java/org/apache/openejb/assembler/classic/ProxyInterfaceResolverTest.java?view=auto&rev=565996
==============================================================================
--- 
openejb/trunk/openejb3/container/openejb-core/src/test/java/org/apache/openejb/assembler/classic/ProxyInterfaceResolverTest.java
 (added)
+++ 
openejb/trunk/openejb3/container/openejb-core/src/test/java/org/apache/openejb/assembler/classic/ProxyInterfaceResolverTest.java
 Tue Aug 14 18:25:15 2007
@@ -0,0 +1,144 @@
+/**
+ * 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.openejb.assembler.classic;
+
+import junit.framework.TestCase;
+
+import java.rmi.RemoteException;
+import java.util.Arrays;
+import java.util.List;
+
+/**
+ * @version $Rev$ $Date$
+ */
+public class ProxyInterfaceResolverTest extends TestCase {
+    public void test() throws Exception {
+        Class smoothie;
+        List<Class> ingredients;
+
+        // No remotes
+        smoothie = implement(Mango.class, Lime.class, Lemon.class);
+        ingredients = resolve(smoothie, Mango.class, Lime.class, Lemon.class);
+        assertEquals(3, ingredients.size());
+        assertTrue(ingredients.contains(Mango.class));
+        assertTrue(ingredients.contains(Lime.class));
+        assertTrue(ingredients.contains(Lemon.class));
+
+        // All remotes
+        smoothie = implement(Cherry.class, Honey.class, Grape.class);
+        ingredients = resolve(smoothie, Cherry.class, Honey.class, 
Grape.class);
+        assertEquals(3, ingredients.size());
+        assertTrue(ingredients.contains(Cherry.class));
+        assertTrue(ingredients.contains(Grape.class));
+        assertTrue(ingredients.contains(Honey.class));
+
+        // mixed remote and non-remote, no conflicts
+        smoothie = implement(Banana.class, Honey.class, Creme.class);
+        ingredients = resolve(smoothie, Banana.class, Honey.class, 
Creme.class);
+        assertEquals(3, ingredients.size());
+        assertTrue(ingredients.contains(Banana.class));
+        assertTrue(ingredients.contains(Honey.class));
+        assertTrue(ingredients.contains(Creme.class));
+
+        // mixed remote and non-remote, conflicts (cherry, grape)
+        smoothie = implement(Mango.class, Banana.class, Creme.class, 
Honey.class, Cherry.class, Grape.class);
+        ingredients = resolve(smoothie, Mango.class, Banana.class, 
Creme.class, Honey.class, Cherry.class, Grape.class);
+        assertEquals(4, ingredients.size());
+        assertTrue(ingredients.contains(Mango.class));
+        assertTrue(ingredients.contains(Banana.class));
+        assertTrue(ingredients.contains(Creme.class));
+        assertTrue(ingredients.contains(Honey.class));
+
+        // mixed remote and non-remote, conflicts (mango, banana)
+        smoothie = implement(Cherry.class, Mango.class, Banana.class, 
Creme.class, Honey.class, Grape.class);
+        ingredients = resolve(smoothie, Cherry.class, Mango.class, 
Banana.class, Creme.class, Honey.class, Grape.class);
+        assertEquals(4, ingredients.size());
+        assertTrue(ingredients.contains(Cherry.class));
+        assertTrue(ingredients.contains(Grape.class));
+        assertTrue(ingredients.contains(Creme.class));
+        assertTrue(ingredients.contains(Honey.class));
+    }
+
+    public List<Class> resolve(Class impl, Class mainInterface, Class... 
interfaces) {
+        return ProxyInterfaceResolver.getInterfaces(impl, mainInterface, 
Arrays.asList(interfaces));
+    }
+
+
+    public Class implement(Class<?>... interfaces) {
+        return 
java.lang.reflect.Proxy.getProxyClass(this.getClass().getClassLoader(), 
interfaces);
+    }
+
+    public interface Mango {
+        void exist() throws RoundException, GreenException;
+
+        void mango();
+    }
+
+    public interface Lime {
+        void exist() throws RoundException, GreenException;
+
+        void lime();
+    }
+
+    public interface Lemon {
+        void exist() throws RoundException, YellowException;
+
+        void lemon();
+    }
+
+    public interface Banana {
+        void exist() throws LongException, YellowException;
+
+        void banana();
+    }
+
+    public interface Creme {
+        void thiken();
+    }
+
+    public interface Cherry extends java.rmi.Remote {
+        void exist() throws RoundException, RemoteException;
+
+        void cherry() throws RemoteException;
+    }
+
+    public interface Grape extends java.rmi.Remote {
+        void exist() throws RoundException, RemoteException;
+
+        void grape() throws RemoteException;
+    }
+
+    public interface Honey extends java.rmi.Remote {
+        void sweeten() throws RemoteException;
+    }
+
+    //--------------//
+    public static class RoundException extends Exception {
+    }
+
+    public static class GreenException extends Exception {
+    }
+
+    public static class YellowException extends Exception {
+    }
+
+    public static class LongException extends Exception {
+    }
+
+
+}
+


Reply via email to