001    /**
002     *
003     * Copyright 2005 LogicBlaze, Inc.
004     *
005     * Licensed under the Apache License, Version 2.0 (the "License");
006     * you may not use this file except in compliance with the License.
007     * You may obtain a copy of the License at
008     *
009     * http://www.apache.org/licenses/LICENSE-2.0
010     *
011     * Unless required by applicable law or agreed to in writing, software
012     * distributed under the License is distributed on an "AS IS" BASIS,
013     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014     * See the License for the specific language governing permissions and
015     * limitations under the License.
016     *
017     **/
018    package org.logicblaze.lingo;
019    
020    import java.lang.reflect.Method;
021    import java.rmi.Remote;
022    import java.util.EventListener;
023    import java.util.HashSet;
024    import java.util.Iterator;
025    import java.util.Set;
026    
027    /**
028     * A simple metadata strategy which uses POJO naming conventions.
029     *
030     * By default all method invocations are synchronous to avoid surprising users of Spring Remoting. However
031     * if you set the {@link #setOneWayForVoidMethods(boolean)} value to true then all void methods which do
032     * not throw checked exceptions become asynchronous one way methods.
033     *
034     * <p/>
035     * Also any object which implements the {@link Remote} interface or the {@link EventListener}
036     * are assumed to be remote and so a remote proxy is used to allow remote notifications and asynchronous
037     * messaging.
038     *
039     * @version $Revision: 1.2 $
040     */
041    public class SimpleMetadataStrategy implements MetadataStrategy {
042        private boolean oneWayForVoidMethods;
043        private Set remoteTypes;
044    
045        public SimpleMetadataStrategy() {
046        }
047    
048        public SimpleMetadataStrategy(boolean oneWayForVoidMethods) {
049            this.oneWayForVoidMethods = oneWayForVoidMethods;
050        }
051    
052        public MethodMetadata getMethodMetadata(Method method) {
053            boolean oneway = false;
054            if (oneWayForVoidMethods) {
055                oneway = method.getReturnType().equals(void.class) && method.getExceptionTypes().length == 0;
056            }
057            boolean[] remoteParams = null;
058            Class[] parameterTypes = method.getParameterTypes();
059            int size = parameterTypes.length;
060            if (size > 0) {
061                remoteParams = new boolean[size];
062                for (int i = 0; i < size; i++) {
063                    remoteParams[i] = isRemoteParameter(method, parameterTypes[i], i);
064                }
065            }
066            return new MethodMetadata(oneway, remoteParams);
067        }
068    
069        public boolean isOneWayForVoidMethods() {
070            return oneWayForVoidMethods;
071        }
072    
073        public void setOneWayForVoidMethods(boolean oneWayForVoidMethods) {
074            this.oneWayForVoidMethods = oneWayForVoidMethods;
075        }
076    
077        public Set getRemoteTypes() {
078            if (remoteTypes == null) {
079                remoteTypes = new HashSet();
080                populateDefaultRemoteTypes(remoteTypes);
081            }
082            return remoteTypes;
083        }
084    
085    
086        public void setRemoteTypes(Set remoteTypes) {
087            this.remoteTypes = remoteTypes;
088        }
089    
090        protected boolean isRemoteParameter(Method method, Class parameterType, int index) {
091            for (Iterator iter = getRemoteTypes().iterator(); iter.hasNext();) {
092                Class type = (Class) iter.next();
093                if (type.isAssignableFrom(parameterType)) {
094                    return true;
095                }
096            }
097            return false;
098        }
099    
100        protected void populateDefaultRemoteTypes(Set remoteTypes) {
101            remoteTypes.add(Remote.class);
102            remoteTypes.add(EventListener.class);
103        }
104    }