001: /*
002: * Copyright (C) The MX4J Contributors.
003: * All rights reserved.
004: *
005: * This software is distributed under the terms of the MX4J License version 1.0.
006: * See the terms of the MX4J License in the documentation provided with this software.
007: */
008:
009: package mx4j.tools.remote.caucho;
010:
011: import java.io.BufferedInputStream;
012: import java.io.BufferedOutputStream;
013: import java.io.IOException;
014: import java.io.InputStream;
015: import java.io.OutputStream;
016: import java.lang.reflect.InvocationTargetException;
017: import java.lang.reflect.Method;
018: import java.util.HashMap;
019: import java.util.Map;
020:
021: import javax.servlet.ServletException;
022: import javax.servlet.http.HttpServlet;
023: import javax.servlet.http.HttpServletRequest;
024: import javax.servlet.http.HttpServletResponse;
025:
026: import mx4j.tools.remote.http.HTTPConnection;
027:
028: /**
029: * @version $Revision: 1.4 $
030: */
031: public abstract class CauchoServlet extends HttpServlet {
032: private Map methods;
033:
034: public void init() throws ServletException {
035: methods = new HashMap();
036: mapMethods(HTTPConnection.class, methods);
037: }
038:
039: protected void mapMethods(Class cls, Map methods) {
040: Method[] mthds = cls.getMethods();
041: for (int i = 0; i < mthds.length; ++i) {
042: Method mthd = mthds[i];
043: String key = mangleMethodName(mthd);
044: methods.put(key, mthd);
045: }
046: }
047:
048: protected Method findMethod(String methodName) {
049: return (Method) methods.get(methodName);
050: }
051:
052: protected String mangleMethodName(Method method) {
053: return CauchoService.mangleMethodName(method);
054: }
055:
056: protected void service(HttpServletRequest request,
057: HttpServletResponse response) throws ServletException,
058: IOException {
059: if (!"POST".equalsIgnoreCase(request.getMethod()))
060: throw new ServletException("Caucho protocol requires POST");
061:
062: BufferedInputStream is = new BufferedInputStream(request
063: .getInputStream(), 48);
064: CauchoInput input = createCauchoInput(is);
065: BufferedOutputStream bos = new BufferedOutputStream(response
066: .getOutputStream(), 48);
067: CauchoOutput output = createCauchoOutput(bos);
068:
069: invoke(request, input, output);
070:
071: bos.flush();
072: }
073:
074: protected abstract CauchoInput createCauchoInput(InputStream stream);
075:
076: protected abstract CauchoOutput createCauchoOutput(
077: OutputStream stream);
078:
079: protected abstract Object getService();
080:
081: protected void invoke(HttpServletRequest request,
082: CauchoInput input, CauchoOutput output) throws IOException {
083: input.startCall();
084: Map headers = readHeaders(input);
085: String methodName = input.readMethod();
086: Method method = findMethod(methodName);
087: if (method == null) {
088: output.startReply();
089: NoSuchMethodException x = new NoSuchMethodException(
090: methodName);
091: output.writeFault(x);
092: output.completeReply();
093: } else {
094: Object[] values = readArguments(input, method);
095: input.completeCall();
096:
097: Object result = null;
098: try {
099: result = invoke(request.getRequestURL().toString(),
100: getService(), method, headers, values);
101: } catch (Throwable x) {
102: output.startReply();
103: output.writeFault(x);
104: output.completeReply();
105: return;
106: }
107: output.startReply();
108: output.writeObject(result);
109: output.completeReply();
110: }
111: }
112:
113: protected Map readHeaders(CauchoInput input) throws IOException {
114: Map headers = new HashMap();
115: String header = null;
116: while ((header = input.readHeader()) != null)
117: headers.put(header, input.readObject(null));
118: return headers;
119: }
120:
121: protected Object[] readArguments(CauchoInput input, Method method)
122: throws IOException {
123: Class[] types = method.getParameterTypes();
124: Object[] values = new Object[types.length];
125: for (int i = 0; i < types.length; ++i)
126: values[i] = input.readObject(types[i]);
127: return values;
128: }
129:
130: protected Object invoke(String url, Object target, Method method,
131: Map headers, Object[] values) throws Exception {
132: if (target == null)
133: throw new IOException("Service is not available");
134: String connectionId = (String) headers
135: .get(CauchoService.CONNECTION_ID_HEADER_NAME);
136: CauchoService.setConnectionContext(url, connectionId);
137: try {
138: return method.invoke(target, values);
139: } catch (InvocationTargetException x) {
140: Throwable t = x.getTargetException();
141: if (t instanceof Exception)
142: throw (Exception) t;
143: throw (Error) t;
144: } finally {
145: CauchoService.resetConnectionContext();
146: }
147: }
148: }
|