001/*
002 * Copyright 2002-2012 the original author or authors.
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 *      https://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016
017package org.springframework.remoting.rmi;
018
019import java.lang.reflect.InvocationTargetException;
020import java.rmi.Remote;
021
022import org.springframework.remoting.support.RemoteInvocation;
023import org.springframework.remoting.support.RemoteInvocationBasedExporter;
024
025/**
026 * Convenient superclass for RMI-based remote exporters. Provides a facility
027 * to automatically wrap a given plain Java service object with an
028 * RmiInvocationWrapper, exposing the {@link RmiInvocationHandler} remote interface.
029 *
030 * <p>Using the RMI invoker mechanism, RMI communication operates at the {@link RmiInvocationHandler}
031 * level, sharing a common invoker stub for any number of services. Service interfaces are <i>not</i>
032 * required to extend {@code java.rmi.Remote} or declare {@code java.rmi.RemoteException}
033 * on all service methods. However, in and out parameters still have to be serializable.
034 *
035 * @author Juergen Hoeller
036 * @since 1.2.5
037 * @see RmiServiceExporter
038 * @see JndiRmiServiceExporter
039 */
040public abstract class RmiBasedExporter extends RemoteInvocationBasedExporter {
041
042        /**
043         * Determine the object to export: either the service object itself
044         * or a RmiInvocationWrapper in case of a non-RMI service object.
045         * @return the RMI object to export
046         * @see #setService
047         * @see #setServiceInterface
048         */
049        protected Remote getObjectToExport() {
050                // determine remote object
051                if (getService() instanceof Remote &&
052                                (getServiceInterface() == null || Remote.class.isAssignableFrom(getServiceInterface()))) {
053                        // conventional RMI service
054                        return (Remote) getService();
055                }
056                else {
057                        // RMI invoker
058                        if (logger.isDebugEnabled()) {
059                                logger.debug("RMI service [" + getService() + "] is an RMI invoker");
060                        }
061                        return new RmiInvocationWrapper(getProxyForService(), this);
062                }
063        }
064
065        /**
066         * Redefined here to be visible to RmiInvocationWrapper.
067         * Simply delegates to the corresponding superclass method.
068         */
069        @Override
070        protected Object invoke(RemoteInvocation invocation, Object targetObject)
071                        throws NoSuchMethodException, IllegalAccessException, InvocationTargetException {
072
073                return super.invoke(invocation, targetObject);
074        }
075
076}