001: ///////////////////////////////////////////////////////////////////////////////
002: //
003: // Copyright (C) 2003-@year@ by Thomas M. Hazel, MyOODB (www.myoodb.org)
004: //
005: // All Rights Reserved
006: //
007: // This program is free software; you can redistribute it and/or modify
008: // it under the terms of the GNU General Public License and GNU Library
009: // General Public License as published by the Free Software Foundation;
010: // either version 2, or (at your option) any later version.
011: //
012: // This program is distributed in the hope that it will be useful,
013: // but WITHOUT ANY WARRANTY; without even the implied warranty of
014: // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
015: // GNU General Public License and GNU Library General Public License
016: // for more details.
017: //
018: // You should have received a copy of the GNU General Public License
019: // and GNU Library General Public License along with this program; if
020: // not, write to the Free Software Foundation, 675 Mass Ave, Cambridge,
021: // MA 02139, USA.
022: //
023: ///////////////////////////////////////////////////////////////////////////////
024: package org.myoodb.core;
025:
026: import java.io.*;
027: import javax.servlet.*;
028: import javax.servlet.http.*;
029:
030: import org.myoodb.util.*;
031: import org.myoodb.core.command.*;
032:
033: public class MyOodbTunnelHttp extends BaseServlet {
034: private static final org.myoodb.util.Logger LOGGER = org.myoodb.util.Logger
035: .getLogger(MyOodbTunnelHttp.class);
036:
037: public MyOodbTunnelHttp() {
038: }
039:
040: protected ObjectInputStream getObjectInputStream(
041: InputStream inputStream) throws java.io.IOException {
042: return new org.myoodb.util.FastObjectInputStream(
043: new BufferedInputStream(inputStream, AbstractConnection
044: .getBufferSize()), m_db);
045: }
046:
047: protected ObjectOutputStream getObjectOutputStream(
048: OutputStream outputStream) throws java.io.IOException {
049: return new org.myoodb.util.FastObjectOutputStream(
050: new BufferedOutputStream(outputStream,
051: AbstractConnection.getBufferSize()), m_db);
052: }
053:
054: private void prepareResponse(ObjectOutputStream out,
055: long sessionIdentifier, Object result)
056: throws java.io.IOException {
057: //
058: // XXX: since this is outside the context of the database we need to check for concurrency
059: //
060: java.util.ConcurrentModificationException globalError = null;
061:
062: for (int i = 0; i < org.myoodb.core.storage.ClusterStore.CONCURRENCY_RETRY; i++) {
063: try {
064: out.writeLong(sessionIdentifier);
065: out.writeObject(result);
066: out.flush();
067: globalError = null;
068: break;
069: } catch (java.util.ConcurrentModificationException e) {
070: try {
071: Thread.sleep(100);
072: } catch (java.lang.InterruptedException ee) {
073: // nothing to do
074: }
075:
076: globalError = e;
077: }
078: }
079:
080: if (globalError != null) {
081: out.writeLong(sessionIdentifier);
082: out.writeObject(new org.myoodb.exception.InternalException(
083: "Concurrency error:", globalError));
084: out.flush();
085: }
086: }
087:
088: public void doPost(HttpServletRequest request,
089: HttpServletResponse response) throws IOException,
090: ServletException {
091: short gRequestVal = -1;
092:
093: try {
094: ObjectInputStream in = getObjectInputStream(request
095: .getInputStream());
096:
097: gRequestVal = in.readShort();
098: long sessionIdentifier = in.readLong();
099:
100: Object[] connectionTuple = null;
101: synchronized (TunnelManager.CONNECTIONS) {
102: connectionTuple = (Object[]) TunnelManager.CONNECTIONS
103: .get(sessionIdentifier);
104: }
105:
106: if (gRequestVal >= TunnelManager.Protocol.USER_DATA) {
107: AbstractCommand command = (AbstractCommand) in
108: .readObject();
109:
110: org.myoodb.core.DatabaseConnection connection = null;
111: if (connectionTuple == null) {
112: if (sessionIdentifier != -1) {
113: throw new org.myoodb.exception.TimeoutException(
114: "Connection timed out");
115: }
116:
117: if ((command instanceof LoginCommand) == false) {
118: throw new org.myoodb.exception.PermissionException(
119: "Permission denied");
120: }
121:
122: connection = new org.myoodb.core.DatabaseConnection(
123: m_db, null, m_db.getHost(), m_db.getPort(),
124: -1, false, null);
125:
126: sessionIdentifier = MyOodbManager.getTheManager()
127: .getIdentifierManager()
128: .getNextConnectionId();
129:
130: connectionTuple = new Object[3];
131: connectionTuple[0] = connection;
132: connectionTuple[1] = request.getRemoteAddr();
133: connectionTuple[2] = System.currentTimeMillis();
134:
135: synchronized (TunnelManager.CONNECTIONS) {
136: TunnelManager.CONNECTIONS.put(
137: sessionIdentifier, connectionTuple);
138: }
139: } else {
140: connection = (org.myoodb.core.DatabaseConnection) connectionTuple[0];
141: connectionTuple[2] = System.currentTimeMillis();
142: }
143:
144: Object result = null;
145: synchronized (connection) {
146: boolean tunnel = (gRequestVal == TunnelManager.Protocol.USER_DATA_TUNNEL);
147: if ((tunnel == false)
148: && (command instanceof InvokeMethodCommand)) {
149: tunnel = (((InvokeMethodCommand) command)
150: .getAccessLevel() == org.myoodb.MyOodbAccess.TUNNEL);
151: }
152:
153: if (tunnel == true) {
154: ((AbstractCommand) command)
155: .setTunnelIdentifier(sessionIdentifier);
156:
157: synchronized (TunnelManager.INVOKE_COMMANDS) {
158: TunnelManager.INVOKE_COMMANDS.put(
159: sessionIdentifier, command);
160: }
161: }
162:
163: try {
164: connection.send(command);
165: result = connection.receive(-1);
166: } finally {
167: if (tunnel == true) {
168: synchronized (TunnelManager.INVOKE_COMMANDS) {
169: result = TunnelManager.INVOKE_COMMANDS
170: .remove(sessionIdentifier);
171: }
172: }
173: }
174: }
175:
176: FastByteArrayOutputStream byteStream = new FastByteArrayOutputStream(
177: AbstractConnection.getBufferSize());
178: prepareResponse(getObjectOutputStream(byteStream),
179: sessionIdentifier, result);
180: response.setContentType("application/octet-stream");
181: response.setContentLength(byteStream.size());
182: response.getOutputStream().write(
183: byteStream.toByteArray(), 0, byteStream.size());
184: response.getOutputStream().flush();
185: } else if (connectionTuple != null) {
186: connectionTuple[2] = System.currentTimeMillis();
187: }
188: } catch (Exception e) {
189: if (LOGGER.isDebugEnabled() == true) {
190: LOGGER.debug(null, e);
191: }
192:
193: if (gRequestVal >= TunnelManager.Protocol.USER_DATA) {
194: if ((e instanceof org.myoodb.exception.RemoteException) == false) {
195: e = new org.myoodb.exception.InternalException(e);
196: }
197:
198: FastByteArrayOutputStream byteStream = new FastByteArrayOutputStream(
199: AbstractConnection.getBufferSize());
200: prepareResponse(getObjectOutputStream(byteStream), -1,
201: e);
202: response.setContentType("application/octet-stream");
203: response.setContentLength(byteStream.size());
204: response.getOutputStream().write(
205: byteStream.toByteArray(), 0, byteStream.size());
206: response.getOutputStream().flush();
207: }
208: }
209: }
210: }
|