001: /*
002: * Copyright (c) 1998-2008 Caucho Technology -- all rights reserved
003: *
004: * This file is part of Resin(R) Open Source
005: *
006: * Each copy or derived work must preserve the copyright notice and this
007: * notice unmodified.
008: *
009: * Resin Open Source is free software; you can redistribute it and/or modify
010: * it under the terms of the GNU General Public License as published by
011: * the Free Software Foundation; either version 2 of the License, or
012: * (at your option) any later version.
013: *
014: * Resin Open Source is distributed in the hope that it will be useful,
015: * but WITHOUT ANY WARRANTY; without even the implied warranty of
016: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, or any warranty
017: * of NON-INFRINGEMENT. See the GNU General Public License for more
018: * details.
019: *
020: * You should have received a copy of the GNU General Public License
021: * along with Resin Open Source; if not, write to the
022: *
023: * Free Software Foundation, Inc.
024: * 59 Temple Place, Suite 330
025: * Boston, MA 02111-1307 USA
026: *
027: * @author Scott Ferguson
028: */
029:
030: package com.caucho.server.admin;
031:
032: import com.caucho.hessian.io.AbstractHessianInput;
033: import com.caucho.hessian.io.AbstractHessianOutput;
034: import com.caucho.hessian.io.Hessian2Input;
035: import com.caucho.hessian.io.HessianOutput;
036: import com.caucho.hessian.io.HessianProtocolException;
037: import com.caucho.util.CharBuffer;
038: import com.caucho.vfs.Path;
039: import com.caucho.vfs.ReadStream;
040: import com.caucho.vfs.ReadWritePair;
041: import com.caucho.vfs.WriteStream;
042:
043: import java.io.IOException;
044: import java.lang.reflect.InvocationHandler;
045: import java.lang.reflect.Method;
046: import java.lang.reflect.Proxy;
047:
048: /**
049: * Proxy implementation for Hessian clients. Applications will generally
050: * use HessianProxyFactory to create proxy clients.
051: */
052: public class HessianHmuxProxy implements InvocationHandler {
053: private Path _path;
054:
055: private HessianHmuxProxy(Path url) {
056: _path = url;
057: }
058:
059: public static <X> X create(Path url, Class<X> api) {
060: Thread thread = Thread.currentThread();
061:
062: return (X) Proxy.newProxyInstance(thread
063: .getContextClassLoader(), new Class[] { api },
064: new HessianHmuxProxy(url));
065: }
066:
067: /**
068: * Handles the object invocation.
069: *
070: * @param proxy the proxy object to invoke
071: * @param method the method to call
072: * @param args the arguments to the proxy object
073: */
074: public Object invoke(Object proxy, Method method, Object[] args)
075: throws Throwable {
076: String methodName = method.getName();
077: Class[] params = method.getParameterTypes();
078:
079: // equals and hashCode are special cased
080: if (methodName.equals("equals") && params.length == 1
081: && params[0].equals(Object.class)) {
082: Object value = args[0];
083: if (value == null || !Proxy.isProxyClass(value.getClass()))
084: return new Boolean(false);
085:
086: HessianHmuxProxy handler = (HessianHmuxProxy) Proxy
087: .getInvocationHandler(value);
088:
089: return new Boolean(_path.equals(handler._path));
090: } else if (methodName.equals("hashCode") && params.length == 0)
091: return new Integer(_path.hashCode());
092: else if (methodName.equals("getHessianType"))
093: return proxy.getClass().getInterfaces()[0].getName();
094: else if (methodName.equals("getHessianURL"))
095: return _path.toString();
096: else if (methodName.equals("toString") && params.length == 0)
097: return "HessianHmuxProxy[" + _path + "]";
098:
099: ReadStream is = null;
100:
101: try {
102: if (args != null)
103: methodName = methodName + "__" + args.length;
104: else
105: methodName = methodName + "__0";
106:
107: is = sendRequest(methodName, args);
108:
109: String code = (String) is.getAttribute("status");
110:
111: if (!"200".equals(code)) {
112: CharBuffer sb = new CharBuffer();
113:
114: while (is.readLine(sb)) {
115: }
116:
117: throw new HessianProtocolException(code + ": " + sb);
118: }
119:
120: AbstractHessianInput in = new Hessian2Input(is);
121:
122: return in.readReply(method.getReturnType());
123: } catch (HessianProtocolException e) {
124: throw new RuntimeException(e);
125: } finally {
126: try {
127: if (is != null)
128: is.close();
129: } catch (Throwable e) {
130: }
131: }
132: }
133:
134: private ReadStream sendRequest(String methodName, Object[] args)
135: throws IOException {
136: ReadWritePair pair = _path.openReadWrite();
137:
138: ReadStream is = pair.getReadStream();
139: WriteStream os = pair.getWriteStream();
140:
141: try {
142: AbstractHessianOutput out = new HessianOutput(os);
143:
144: out.call(methodName, args);
145: out.flush();
146:
147: return is;
148: } catch (IOException e) {
149: try {
150: os.close();
151: } catch (Exception e1) {
152: }
153:
154: try {
155: is.close();
156: } catch (Exception e1) {
157: }
158:
159: throw e;
160: } catch (RuntimeException e) {
161: try {
162: os.close();
163: } catch (Exception e1) {
164: }
165:
166: try {
167: is.close();
168: } catch (Exception e1) {
169: }
170:
171: throw e;
172: }
173: }
174: }
|