001 /*
002 * The Apache Software License, Version 1.1
003 *
004 * Copyright (c) 2001-2004 Caucho Technology, Inc. All rights reserved.
005 *
006 * Redistribution and use in source and binary forms, with or without
007 * modification, are permitted provided that the following conditions
008 * are met:
009 *
010 * 1. Redistributions of source code must retain the above copyright
011 * notice, this list of conditions and the following disclaimer.
012 *
013 * 2. Redistributions in binary form must reproduce the above copyright
014 * notice, this list of conditions and the following disclaimer in
015 * the documentation and/or other materials provided with the
016 * distribution.
017 *
018 * 3. The end-user documentation included with the redistribution, if
019 * any, must include the following acknowlegement:
020 * "This product includes software developed by the
021 * Caucho Technology (http://www.caucho.com/)."
022 * Alternately, this acknowlegement may appear in the software itself,
023 * if and wherever such third-party acknowlegements normally appear.
024 *
025 * 4. The names "Burlap", "Resin", and "Caucho" must not be used to
026 * endorse or promote products derived from this software without prior
027 * written permission. For written permission, please contact
028 * info@caucho.com.
029 *
030 * 5. Products derived from this software may not be called "Resin"
031 * nor may "Resin" appear in their names without prior written
032 * permission of Caucho Technology.
033 *
034 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
035 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
036 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
037 * DISCLAIMED. IN NO EVENT SHALL CAUCHO TECHNOLOGY OR ITS CONTRIBUTORS
038 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
039 * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
040 * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
041 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
042 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
043 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
044 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
045 *
046 * @author Scott Ferguson
047 */
048
049 package com.caucho.burlap.client;
050
051 import com.caucho.burlap.io.AbstractBurlapInput;
052 import com.caucho.burlap.io.BurlapOutput;
053
054 import java.io.FileNotFoundException;
055 import java.io.IOException;
056 import java.io.InputStream;
057 import java.io.OutputStream;
058 import java.lang.reflect.InvocationHandler;
059 import java.lang.reflect.Method;
060 import java.lang.reflect.Proxy;
061 import java.net.HttpURLConnection;
062 import java.net.URL;
063 import java.net.URLConnection;
064 import java.util.logging.*;
065
066 /**
067 * Proxy implementation for Burlap clients. Applications will generally
068 * use BurlapProxyFactory to create proxy clients.
069 */
070 public class BurlapProxy implements InvocationHandler {
071 private static final Logger log
072 = Logger.getLogger(BurlapProxy.class.getName());
073
074 private BurlapProxyFactory _factory;
075 private URL _url;
076
077 BurlapProxy(BurlapProxyFactory factory, URL url)
078 {
079 _factory = factory;
080 _url = url;
081 }
082
083 /**
084 * Returns the proxy's URL.
085 */
086 public URL getURL()
087 {
088 return _url;
089 }
090
091 /**
092 * Handles the object invocation.
093 *
094 * @param proxy the proxy object to invoke
095 * @param method the method to call
096 * @param args the arguments to the proxy object
097 */
098 public Object invoke(Object proxy, Method method, Object []args)
099 throws Throwable
100 {
101 String methodName = method.getName();
102 Class []params = method.getParameterTypes();
103
104 // equals and hashCode are special cased
105 if (methodName.equals("equals") &&
106 params.length == 1 && params[0].equals(Object.class)) {
107 Object value = args[0];
108 if (value == null || ! Proxy.isProxyClass(value.getClass()))
109 return new Boolean(false);
110
111 BurlapProxy handler = (BurlapProxy) Proxy.getInvocationHandler(value);
112
113 return new Boolean(_url.equals(handler.getURL()));
114 }
115 else if (methodName.equals("hashCode") && params.length == 0)
116 return new Integer(_url.hashCode());
117 else if (methodName.equals("getBurlapType"))
118 return proxy.getClass().getInterfaces()[0].getName();
119 else if (methodName.equals("getBurlapURL"))
120 return _url.toString();
121 else if (methodName.equals("toString") && params.length == 0)
122 return getClass().getSimpleName() + "[" + _url + "]";
123
124 InputStream is = null;
125
126 URLConnection conn = null;
127 HttpURLConnection httpConn = null;
128 try {
129 conn = _factory.openConnection(_url);
130
131 httpConn = (HttpURLConnection) conn;
132
133 httpConn.setRequestMethod("POST");
134 conn.setRequestProperty("Content-Type", "text/xml");
135
136 OutputStream os;
137
138 try {
139 os = conn.getOutputStream();
140 } catch (Exception e) {
141 throw new BurlapRuntimeException(e);
142 }
143
144 BurlapOutput out = _factory.getBurlapOutput(os);
145
146 if (! _factory.isOverloadEnabled()) {
147 }
148 else if (args != null)
149 methodName = methodName + "__" + args.length;
150 else
151 methodName = methodName + "__0";
152
153 if (log.isLoggable(Level.FINE))
154 log.fine(this + " calling " + methodName + " (" + method + ")");
155
156 out.call(methodName, args);
157
158 try {
159 os.flush();
160 } catch (Exception e) {
161 throw new BurlapRuntimeException(e);
162 }
163
164 if (conn instanceof HttpURLConnection) {
165 httpConn = (HttpURLConnection) conn;
166 int code = 500;
167
168 try {
169 code = httpConn.getResponseCode();
170 } catch (Exception e) {
171 }
172
173 if (code != 200) {
174 StringBuffer sb = new StringBuffer();
175 int ch;
176
177 try {
178 is = httpConn.getInputStream();
179
180 if (is != null) {
181 while ((ch = is.read()) >= 0)
182 sb.append((char) ch);
183
184 is.close();
185 }
186
187 is = httpConn.getErrorStream();
188 if (is != null) {
189 while ((ch = is.read()) >= 0)
190 sb.append((char) ch);
191 }
192 } catch (FileNotFoundException e) {
193 throw new BurlapRuntimeException(code + ": " + String.valueOf(e));
194 } catch (IOException e) {
195 }
196
197 if (is != null)
198 is.close();
199
200 throw new BurlapProtocolException(code + ": " + sb.toString());
201 }
202 }
203
204 is = conn.getInputStream();
205
206 AbstractBurlapInput in = _factory.getBurlapInput(is);
207
208 return in.readReply(method.getReturnType());
209 } catch (BurlapProtocolException e) {
210 throw new BurlapRuntimeException(e);
211 } finally {
212 try {
213 if (is != null)
214 is.close();
215 } catch (IOException e) {
216 }
217
218 if (httpConn != null)
219 httpConn.disconnect();
220 }
221 }
222
223 public String toString()
224 {
225 return getClass().getSimpleName() + "[" + _url + "]";
226 }
227 }