001/*
002 * Copyright 2002-2017 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 javax.naming.NamingException;
020
021import org.springframework.aop.framework.ProxyFactory;
022import org.springframework.beans.factory.BeanClassLoaderAware;
023import org.springframework.beans.factory.FactoryBean;
024import org.springframework.util.Assert;
025import org.springframework.util.ClassUtils;
026
027/**
028 * {@link FactoryBean} for RMI proxies from JNDI.
029 *
030 * <p>Typically used for RMI-IIOP (CORBA), but can also be used for EJB home objects
031 * (for example, a Stateful Session Bean home). In contrast to a plain JNDI lookup,
032 * this accessor also performs narrowing through {@link javax.rmi.PortableRemoteObject}.
033 *
034 * <p>With conventional RMI services, this invoker is typically used with the RMI
035 * service interface. Alternatively, this invoker can also proxy a remote RMI service
036 * with a matching non-RMI business interface, i.e. an interface that mirrors the RMI
037 * service methods but does not declare RemoteExceptions. In the latter case,
038 * RemoteExceptions thrown by the RMI stub will automatically get converted to
039 * Spring's unchecked RemoteAccessException.
040 *
041 * <p>The JNDI environment can be specified as "jndiEnvironment" property,
042 * or be configured in a {@code jndi.properties} file or as system properties.
043 * For example:
044 *
045 * <pre class="code">&lt;property name="jndiEnvironment"&gt;
046 *       &lt;props>
047 *               &lt;prop key="java.naming.factory.initial"&gt;com.sun.jndi.cosnaming.CNCtxFactory&lt;/prop&gt;
048 *               &lt;prop key="java.naming.provider.url"&gt;iiop://localhost:1050&lt;/prop&gt;
049 *       &lt;/props&gt;
050 * &lt;/property&gt;</pre>
051 *
052 * @author Juergen Hoeller
053 * @since 1.1
054 * @see #setServiceInterface
055 * @see #setJndiName
056 * @see #setJndiTemplate
057 * @see #setJndiEnvironment
058 * @see #setJndiName
059 * @see JndiRmiServiceExporter
060 * @see org.springframework.remoting.RemoteAccessException
061 * @see java.rmi.RemoteException
062 * @see java.rmi.Remote
063 * @see javax.rmi.PortableRemoteObject#narrow
064 */
065public class JndiRmiProxyFactoryBean extends JndiRmiClientInterceptor
066                implements FactoryBean<Object>, BeanClassLoaderAware {
067
068        private ClassLoader beanClassLoader = ClassUtils.getDefaultClassLoader();
069
070        private Object serviceProxy;
071
072
073        @Override
074        public void setBeanClassLoader(ClassLoader classLoader) {
075                this.beanClassLoader = classLoader;
076        }
077
078        @Override
079        public void afterPropertiesSet() throws NamingException {
080                super.afterPropertiesSet();
081                Class<?> ifc = getServiceInterface();
082                Assert.notNull(ifc, "Property 'serviceInterface' is required");
083                this.serviceProxy = new ProxyFactory(ifc, this).getProxy(this.beanClassLoader);
084        }
085
086
087        @Override
088        public Object getObject() {
089                return this.serviceProxy;
090        }
091
092        @Override
093        public Class<?> getObjectType() {
094                return getServiceInterface();
095        }
096
097        @Override
098        public boolean isSingleton() {
099                return true;
100        }
101
102}