001/* 002 * Copyright 2002-2013 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.caucho; 018 019import java.lang.reflect.InvocationTargetException; 020import java.lang.reflect.UndeclaredThrowableException; 021import java.net.ConnectException; 022import java.net.MalformedURLException; 023 024import com.caucho.burlap.client.BurlapProxyFactory; 025import com.caucho.burlap.client.BurlapRuntimeException; 026import org.aopalliance.intercept.MethodInterceptor; 027import org.aopalliance.intercept.MethodInvocation; 028 029import org.springframework.remoting.RemoteAccessException; 030import org.springframework.remoting.RemoteConnectFailureException; 031import org.springframework.remoting.RemoteLookupFailureException; 032import org.springframework.remoting.RemoteProxyFailureException; 033import org.springframework.remoting.support.UrlBasedRemoteAccessor; 034import org.springframework.util.Assert; 035 036/** 037 * {@link org.aopalliance.intercept.MethodInterceptor} for accessing a Burlap service. 038 * Supports authentication via username and password. 039 * The service URL must be an HTTP URL exposing a Burlap service. 040 * 041 * <p>Burlap is a slim, XML-based RPC protocol. 042 * For information on Burlap, see the 043 * <a href="https://www.caucho.com/burlap">Burlap website</a> 044 * 045 * <p>Note: There is no requirement for services accessed with this proxy factory 046 * to have been exported using Spring's {@link BurlapServiceExporter}, as there is 047 * no special handling involved. As a consequence, you can also access services that 048 * have been exported using Caucho's {@link com.caucho.burlap.server.BurlapServlet}. 049 * 050 * @author Juergen Hoeller 051 * @since 29.09.2003 052 * @see #setServiceInterface 053 * @see #setServiceUrl 054 * @see #setUsername 055 * @see #setPassword 056 * @see BurlapServiceExporter 057 * @see BurlapProxyFactoryBean 058 * @see com.caucho.burlap.client.BurlapProxyFactory 059 * @see com.caucho.burlap.server.BurlapServlet 060 * @deprecated as of Spring 4.0, since Burlap hasn't evolved in years 061 * and is effectively retired (in contrast to its sibling Hessian) 062 */ 063@Deprecated 064public class BurlapClientInterceptor extends UrlBasedRemoteAccessor implements MethodInterceptor { 065 066 private BurlapProxyFactory proxyFactory = new BurlapProxyFactory(); 067 068 private Object burlapProxy; 069 070 071 /** 072 * Set the BurlapProxyFactory instance to use. 073 * If not specified, a default BurlapProxyFactory will be created. 074 * <p>Allows to use an externally configured factory instance, 075 * in particular a custom BurlapProxyFactory subclass. 076 */ 077 public void setProxyFactory(BurlapProxyFactory proxyFactory) { 078 this.proxyFactory = (proxyFactory != null ? proxyFactory : new BurlapProxyFactory()); 079 } 080 081 /** 082 * Set the username that this factory should use to access the remote service. 083 * Default is none. 084 * <p>The username will be sent by Burlap via HTTP Basic Authentication. 085 * @see com.caucho.burlap.client.BurlapProxyFactory#setUser 086 */ 087 public void setUsername(String username) { 088 this.proxyFactory.setUser(username); 089 } 090 091 /** 092 * Set the password that this factory should use to access the remote service. 093 * Default is none. 094 * <p>The password will be sent by Burlap via HTTP Basic Authentication. 095 * @see com.caucho.burlap.client.BurlapProxyFactory#setPassword 096 */ 097 public void setPassword(String password) { 098 this.proxyFactory.setPassword(password); 099 } 100 101 /** 102 * Set whether overloaded methods should be enabled for remote invocations. 103 * Default is "false". 104 * @see com.caucho.burlap.client.BurlapProxyFactory#setOverloadEnabled 105 */ 106 public void setOverloadEnabled(boolean overloadEnabled) { 107 this.proxyFactory.setOverloadEnabled(overloadEnabled); 108 } 109 110 111 @Override 112 public void afterPropertiesSet() { 113 super.afterPropertiesSet(); 114 prepare(); 115 } 116 117 /** 118 * Initialize the Burlap proxy for this interceptor. 119 * @throws RemoteLookupFailureException if the service URL is invalid 120 */ 121 public void prepare() throws RemoteLookupFailureException { 122 try { 123 this.burlapProxy = createBurlapProxy(this.proxyFactory); 124 } 125 catch (MalformedURLException ex) { 126 throw new RemoteLookupFailureException("Service URL [" + getServiceUrl() + "] is invalid", ex); 127 } 128 } 129 130 /** 131 * Create the Burlap proxy that is wrapped by this interceptor. 132 * @param proxyFactory the proxy factory to use 133 * @return the Burlap proxy 134 * @throws MalformedURLException if thrown by the proxy factory 135 * @see com.caucho.burlap.client.BurlapProxyFactory#create 136 */ 137 protected Object createBurlapProxy(BurlapProxyFactory proxyFactory) throws MalformedURLException { 138 Assert.notNull(getServiceInterface(), "Property 'serviceInterface' is required"); 139 return proxyFactory.create(getServiceInterface(), getServiceUrl()); 140 } 141 142 143 @Override 144 public Object invoke(MethodInvocation invocation) throws Throwable { 145 if (this.burlapProxy == null) { 146 throw new IllegalStateException("BurlapClientInterceptor is not properly initialized - " + 147 "invoke 'prepare' before attempting any operations"); 148 } 149 150 ClassLoader originalClassLoader = overrideThreadContextClassLoader(); 151 try { 152 return invocation.getMethod().invoke(this.burlapProxy, invocation.getArguments()); 153 } 154 catch (InvocationTargetException ex) { 155 Throwable targetEx = ex.getTargetException(); 156 if (targetEx instanceof BurlapRuntimeException) { 157 Throwable cause = targetEx.getCause(); 158 throw convertBurlapAccessException(cause != null ? cause : targetEx); 159 } 160 else if (targetEx instanceof UndeclaredThrowableException) { 161 UndeclaredThrowableException utex = (UndeclaredThrowableException) targetEx; 162 throw convertBurlapAccessException(utex.getUndeclaredThrowable()); 163 } 164 else { 165 throw targetEx; 166 } 167 } 168 catch (Throwable ex) { 169 throw new RemoteProxyFailureException( 170 "Failed to invoke Burlap proxy for remote service [" + getServiceUrl() + "]", ex); 171 } 172 finally { 173 resetThreadContextClassLoader(originalClassLoader); 174 } 175 } 176 177 /** 178 * Convert the given Burlap access exception to an appropriate 179 * Spring RemoteAccessException. 180 * @param ex the exception to convert 181 * @return the RemoteAccessException to throw 182 */ 183 protected RemoteAccessException convertBurlapAccessException(Throwable ex) { 184 if (ex instanceof ConnectException) { 185 return new RemoteConnectFailureException( 186 "Cannot connect to Burlap remote service at [" + getServiceUrl() + "]", ex); 187 } 188 else { 189 return new RemoteAccessException( 190 "Cannot access Burlap remote service at [" + getServiceUrl() + "]", ex); 191 } 192 } 193 194}