⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 jaxrpcportclientinterceptor.java

📁 Spring API核心源代码 Spring API核心源代码 Spring API核心源代码
💻 JAVA
📖 第 1 页 / 共 2 页
字号:
/*
 * Copyright 2002-2007 the original author or authors.
 *
 * Licensed 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.springframework.remoting.jaxrpc;

import java.lang.reflect.InvocationTargetException;
import java.rmi.Remote;
import java.rmi.RemoteException;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Properties;

import javax.xml.namespace.QName;
import javax.xml.rpc.Call;
import javax.xml.rpc.JAXRPCException;
import javax.xml.rpc.Service;
import javax.xml.rpc.ServiceException;
import javax.xml.rpc.Stub;

import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;

import org.springframework.aop.support.AopUtils;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.remoting.RemoteLookupFailureException;
import org.springframework.remoting.RemoteProxyFailureException;
import org.springframework.remoting.rmi.RmiClientInterceptorUtils;
import org.springframework.util.CollectionUtils;

/**
 * Interceptor for accessing a specific port of a JAX-RPC service.
 * Uses either {@link LocalJaxRpcServiceFactory}'s facilities underneath,
 * or takes an explicit reference to an existing JAX-RPC Service instance
 * (e.g. obtained via {@link org.springframework.jndi.JndiObjectFactoryBean}).
 *
 * <p>Allows to set JAX-RPC's standard stub properties directly, via the
 * "username", "password", "endpointAddress" and "maintainSession" properties.
 * For typical usage, it is not necessary to specify those.
 *
 * <p>In standard JAX-RPC style, this invoker is used with an RMI service interface.
 * Alternatively, this invoker can also proxy a JAX-RPC service with a matching
 * non-RMI business interface, that is, an interface that declares the service methods
 * without RemoteExceptions. In the latter case, RemoteExceptions thrown by JAX-RPC
 * will automatically get converted to Spring's unchecked RemoteAccessException.
 *
 * <p>Setting "serviceInterface" is usually sufficient: The invoker will automatically
 * use JAX-RPC "dynamic invocations" via the Call API in this case, no matter whether
 * the specified interface is an RMI or non-RMI interface. Alternatively, a corresponding
 * JAX-RPC port interface can be specified as "portInterface", which will turn this
 * invoker into "static invocation" mode (operating on a standard JAX-RPC port stub).
 *
 * @author Juergen Hoeller
 * @since 15.12.2003
 * @see #setPortName
 * @see #setServiceInterface
 * @see #setPortInterface
 * @see javax.xml.rpc.Service#createCall
 * @see javax.xml.rpc.Service#getPort
 * @see org.springframework.remoting.RemoteAccessException
 * @see org.springframework.jndi.JndiObjectFactoryBean
 */
public class JaxRpcPortClientInterceptor extends LocalJaxRpcServiceFactory
		implements MethodInterceptor, InitializingBean {

	private Service jaxRpcService;

	private Service serviceToUse;

	private String portName;

	private String username;

	private String password;

	private String endpointAddress;

	private boolean maintainSession;

	/** Map of custom properties, keyed by property name (String) */
	private final Map	customPropertyMap = new HashMap();

	private Class serviceInterface;

	private Class portInterface;

	private boolean lookupServiceOnStartup = true;

	private boolean refreshServiceAfterConnectFailure = false;

	private QName portQName;

	private Remote portStub;

	private final Object preparationMonitor = new Object();


	/**
	 * Set a reference to an existing JAX-RPC Service instance,
	 * for example obtained via {@link org.springframework.jndi.JndiObjectFactoryBean}.
	 * If not set, LocalJaxRpcServiceFactory's properties have to be specified.
	 * @see #setServiceFactoryClass
	 * @see #setWsdlDocumentUrl
	 * @see #setNamespaceUri
	 * @see #setServiceName
	 * @see org.springframework.jndi.JndiObjectFactoryBean
	 */
	public void setJaxRpcService(Service jaxRpcService) {
		this.jaxRpcService = jaxRpcService;
	}

	/**
	 * Return a reference to an existing JAX-RPC Service instance, if any.
	 */
	public Service getJaxRpcService() {
		return this.jaxRpcService;
	}

	/**
	 * Set the name of the port.
	 * Corresponds to the "wsdl:port" name.
	 */
	public void setPortName(String portName) {
		this.portName = portName;
	}

	/**
	 * Return the name of the port.
	 */
	public String getPortName() {
		return this.portName;
	}

	/**
	 * Set the username to specify on the stub or call.
	 * @see javax.xml.rpc.Stub#USERNAME_PROPERTY
	 * @see javax.xml.rpc.Call#USERNAME_PROPERTY
	 */
	public void setUsername(String username) {
		this.username = username;
	}

	/**
	 * Return the username to specify on the stub or call.
	 */
	public String getUsername() {
		return this.username;
	}

	/**
	 * Set the password to specify on the stub or call.
	 * @see javax.xml.rpc.Stub#PASSWORD_PROPERTY
	 * @see javax.xml.rpc.Call#PASSWORD_PROPERTY
	 */
	public void setPassword(String password) {
		this.password = password;
	}

	/**
	 * Return the password to specify on the stub or call.
	 */
	public String getPassword() {
		return this.password;
	}

	/**
	 * Set the endpoint address to specify on the stub or call.
	 * @see javax.xml.rpc.Stub#ENDPOINT_ADDRESS_PROPERTY
	 * @see javax.xml.rpc.Call#setTargetEndpointAddress
	 */
	public void setEndpointAddress(String endpointAddress) {
		this.endpointAddress = endpointAddress;
	}

	/**
	 * Return the endpoint address to specify on the stub or call.
	 */
	public String getEndpointAddress() {
		return this.endpointAddress;
	}

	/**
	 * Set the maintain session flag to specify on the stub or call.
	 * @see javax.xml.rpc.Stub#SESSION_MAINTAIN_PROPERTY
	 * @see javax.xml.rpc.Call#SESSION_MAINTAIN_PROPERTY
	 */
	public void setMaintainSession(boolean maintainSession) {
		this.maintainSession = maintainSession;
	}

	/**
	 * Return the maintain session flag to specify on the stub or call.
	 */
	public boolean isMaintainSession() {
		return this.maintainSession;
	}

	/**
	 * Set custom properties to be set on the stub or call.
	 * <p>Can be populated with a String "value" (parsed via PropertiesEditor)
	 * or a "props" element in XML bean definitions.
	 * @see javax.xml.rpc.Stub#_setProperty
	 * @see javax.xml.rpc.Call#setProperty
	 */
	public void setCustomProperties(Properties customProperties) {
		CollectionUtils.mergePropertiesIntoMap(customProperties, this.customPropertyMap);
	}

	/**
	 * Set custom properties to be set on the stub or call.
	 * <p>Can be populated with a "map" or "props" element in XML bean definitions.
	 * @see javax.xml.rpc.Stub#_setProperty
	 * @see javax.xml.rpc.Call#setProperty
	 */
	public void setCustomPropertyMap(Map customProperties) {
		if (customProperties != null) {
			Iterator it = customProperties.entrySet().iterator();
			while (it.hasNext()) {
				Map.Entry entry = (Map.Entry) it.next();
				if (!(entry.getKey() instanceof String)) {
					throw new IllegalArgumentException(
							"Illegal property key [" + entry.getKey() + "]: only Strings allowed");
				}
				addCustomProperty((String) entry.getKey(), entry.getValue());
			}
		}
	}

	/**
	 * Allow Map access to the custom properties to be set on the stub
	 * or call, with the option to add or override specific entries.
	 * <p>Useful for specifying entries directly, for example via
	 * "customPropertyMap[myKey]". This is particularly useful for
	 * adding or overriding entries in child bean definitions.
	 */
	public Map getCustomPropertyMap() {
		return this.customPropertyMap;
	}

	/**
	 * Add a custom property to this JAX-RPC Stub/Call.
	 * @param name the name of the attribute to expose
	 * @param value the attribute value to expose
	 * @see javax.xml.rpc.Stub#_setProperty
	 * @see javax.xml.rpc.Call#setProperty
	 */
	public void addCustomProperty(String name, Object value) {
		this.customPropertyMap.put(name, value);
	}

	/**
	 * Set the interface of the service that this factory should create a proxy for.
	 * This will typically be a non-RMI business interface, although you can also
	 * use an RMI port interface as recommended by JAX-RPC here.
	 * <p>Calls on the specified service interface will either be translated to the
	 * underlying RMI port interface (in case of a "portInterface" being specified)
	 * or to dynamic calls (using the JAX-RPC Dynamic Invocation Interface).
	 * <p>The dynamic call mechanism has the advantage that you don't need to
	 * maintain an RMI port interface in addition to an existing non-RMI business
	 * interface. In terms of configuration, specifying the business interface
	 * as "serviceInterface" will be enough; this interceptor will automatically
	 * use dynamic calls in such a scenario.
	 * @see javax.xml.rpc.Service#createCall
	 * @see #setPortInterface
	 */
	public void setServiceInterface(Class serviceInterface) {
		if (serviceInterface != null && !serviceInterface.isInterface()) {
			throw new IllegalArgumentException("serviceInterface must be an interface");
		}
		this.serviceInterface = serviceInterface;
	}

	/**
	 * Return the interface of the service that this factory should create a proxy for.
	 */
	public Class getServiceInterface() {
		return this.serviceInterface;
	}

	/**
	 * Set the JAX-RPC port interface to use. Only needs to be set if a JAX-RPC
	 * port stub should be used instead of the dynamic call mechanism.
	 * See the javadoc of the "serviceInterface" property for more details.
	 * <p>The interface must be suitable for a JAX-RPC port, that is, it must be
	 * an RMI service interface (that extends <code>java.rmi.Remote</code>).
	 * <p><b>NOTE:</b> Check whether your JAX-RPC provider returns thread-safe
	 * port stubs. If not, use the dynamic call mechanism instead, which will
	 * always be thread-safe. In particular, do not use JAX-RPC port stubs
	 * with Apache Axis, whose port stubs are known to be non-thread-safe.
	 * @see javax.xml.rpc.Service#getPort
	 * @see java.rmi.Remote
	 * @see #setServiceInterface
	 */
	public void setPortInterface(Class portInterface) {
		if (portInterface != null &&
				(!portInterface.isInterface() || !Remote.class.isAssignableFrom(portInterface))) {
			throw new IllegalArgumentException(
					"portInterface must be an interface derived from [java.rmi.Remote]");
		}
		this.portInterface = portInterface;
	}

	/**
	 * Return the JAX-RPC port interface to use.
	 */
	public Class getPortInterface() {
		return this.portInterface;
	}

	/**
	 * Set whether to look up the JAX-RPC service on startup.
	 * <p>Default is "true". Turn this flag off to allow for late start
	 * of the target server. In this case, the JAX-RPC service will be
	 * lazily fetched on first access.
	 */
	public void setLookupServiceOnStartup(boolean lookupServiceOnStartup) {
		this.lookupServiceOnStartup = lookupServiceOnStartup;
	}

	/**
	 * Set whether to refresh the JAX-RPC service on connect failure,
	 * that is, whenever a JAX-RPC invocation throws a RemoteException.
	 * <p>Default is "false", keeping a reference to the JAX-RPC service
	 * in any case, retrying the next invocation on the same service
	 * even in case of failure. Turn this flag on to reinitialize the
	 * entire service in case of connect failures.
	 */
	public void setRefreshServiceAfterConnectFailure(boolean refreshServiceAfterConnectFailure) {
		this.refreshServiceAfterConnectFailure = refreshServiceAfterConnectFailure;
	}


	/**
	 * Prepares the JAX-RPC service and port if the "lookupServiceOnStartup"
	 * is turned on (which it is by default).
	 */
	public void afterPropertiesSet() throws ServiceException {
		if (this.lookupServiceOnStartup) {
			prepare();
		}
	}

	/**
	 * Create and initialize the JAX-RPC service for the specified port.
	 * <p>Prepares a JAX-RPC stub if possible (if an RMI interface is available);
	 * falls back to JAX-RPC dynamic calls else. Using dynamic calls can be
	 * enforced through overriding <code>alwaysUseJaxRpcCall</code> to return true.
	 * <p><code>postProcessJaxRpcService</code> and <code>postProcessPortStub</code>
	 * hooks are available for customization in subclasses. When using dynamic calls,
	 * each can be post-processed via <code>postProcessJaxRpcCall</code>.
	 * <p>Note: As of Spring 2.1, this method will always throw
	 * RemoteLookupFailureException and not declare ServiceException anymore.
	 * @throws ServiceException in case of service initialization failure
	 * @throws RemoteLookupFailureException if port stub creation failed
	 * @see #alwaysUseJaxRpcCall
	 * @see #postProcessJaxRpcService
	 * @see #postProcessPortStub
	 * @see #postProcessJaxRpcCall
	 */
	public void prepare() throws ServiceException, RemoteLookupFailureException {
		if (getPortName() == null) {
			throw new IllegalArgumentException("Property 'portName' is required");
		}

		synchronized (this.preparationMonitor) {
			this.serviceToUse = null;

			// Cache the QName for the port.
			this.portQName = getQName(getPortName());

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -