/*
* Copyright (c) 1998-2011 Caucho Technology -- all rights reserved
*
* This file is part of Resin(R) Open Source
*
* Each copy or derived work must preserve the copyright notice and this
* notice unmodified.
*
* Resin Open Source is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* Resin Open Source is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, or any warranty
* of NON-INFRINGEMENT. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License
* along with Resin Open Source; if not, write to the
*
* Free Software Foundation, Inc.
* 59 Temple Place, Suite 330
* Boston, MA 02111-1307 USA
*
* @author Scott Ferguson
*/
package com.caucho.server.admin;
import com.caucho.hessian.io.AbstractHessianInput;
import com.caucho.hessian.io.AbstractHessianOutput;
import com.caucho.hessian.io.Hessian2Input;
import com.caucho.hessian.io.Hessian2Output;
import com.caucho.hessian.io.HessianProtocolException;
import com.caucho.util.CharBuffer;
import com.caucho.util.L10N;
import com.caucho.vfs.Path;
import com.caucho.vfs.ReadStream;
import com.caucho.vfs.ReadWritePair;
import com.caucho.vfs.WriteStream;
import java.io.IOException;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
/**
* Proxy implementation for Hessian clients. Applications will generally
* use HessianProxyFactory to create proxy clients.
*/
public class HessianHmuxProxy implements InvocationHandler {
private static final L10N L = new L10N(HessianHmuxProxy.class);
private Path _path;
private HessianHmuxProxy(Path url)
{
_path = url;
}
public static <X> X create(Path url, Class<X> api)
{
Thread thread = Thread.currentThread();
ClassLoader loader = thread.getContextClassLoader();
if (loader == null)
loader = ClassLoader.getSystemClassLoader();
return (X) Proxy.newProxyInstance(loader,
new Class[] { api },
new HessianHmuxProxy(url));
}
/**
* Handles the object invocation.
*
* @param proxy the proxy object to invoke
* @param method the method to call
* @param args the arguments to the proxy object
*/
public Object invoke(Object proxy, Method method, Object []args)
throws Throwable
{
String methodName = method.getName();
Class []params = method.getParameterTypes();
// equals and hashCode are special cased
if (methodName.equals("equals") &&
params.length == 1 && params[0].equals(Object.class)) {
Object value = args[0];
if (value == null || ! Proxy.isProxyClass(value.getClass()))
return new Boolean(false);
HessianHmuxProxy handler = (HessianHmuxProxy) Proxy.getInvocationHandler(value);
return new Boolean(_path.equals(handler._path));
}
else if (methodName.equals("hashCode") && params.length == 0)
return new Integer(_path.hashCode());
else if (methodName.equals("getHessianType"))
return proxy.getClass().getInterfaces()[0].getName();
else if (methodName.equals("getHessianURL"))
return _path.toString();
else if (methodName.equals("toString") && params.length == 0)
return "HessianHmuxProxy[" + _path + "]";
ReadStream is = null;
try {
if (args != null)
methodName = methodName + "__" + args.length;
else
methodName = methodName + "__0";
is = sendRequest(methodName, args);
String code = (String) is.getAttribute("status");
if (! "200".equals(code)) {
CharBuffer sb = new CharBuffer();
int count = 1024;
while (is.readLine(sb, false) && count-- >= 0) {
}
throw new HessianProtocolException(code + ": " + sb);
}
int ch = is.read();
if (ch != 'H')
throw new HessianProtocolException(L.l("expected 'H' at '{0}'", ch));
int major = is.read();
int minor = is.read();
AbstractHessianInput in = new Hessian2Input(is);
return in.readReply(method.getReturnType());
} catch (HessianProtocolException e) {
throw new RuntimeException(e);
} finally {
try {
if (is != null)
is.close();
} catch (Throwable e) {
}
}
}
private ReadStream sendRequest(String methodName, Object []args)
throws IOException
{
ReadWritePair pair = _path.openReadWrite();
ReadStream is = pair.getReadStream();
WriteStream os = pair.getWriteStream();
try {
Hessian2Output out = new Hessian2Output(os);
out.writeVersion();
out.call(methodName, args);
out.flush();
return is;
} catch (IOException e) {
try {
os.close();
} catch (Exception e1) {
}
try {
is.close();
} catch (Exception e1) {
}
throw e;
} catch (RuntimeException e) {
try {
os.close();
} catch (Exception e1) {
}
try {
is.close();
} catch (Exception e1) {
}
throw e;
}
}
}