| /* |
| * For work developed by the HSQL Development Group: |
| * |
| * Copyright (c) 2001-2010, The HSQL Development Group |
| * All rights reserved. |
| * |
| * Redistribution and use in source and binary forms, with or without |
| * modification, are permitted provided that the following conditions are met: |
| * |
| * Redistributions of source code must retain the above copyright notice, this |
| * list of conditions and the following disclaimer. |
| * |
| * Redistributions in binary form must reproduce the above copyright notice, |
| * this list of conditions and the following disclaimer in the documentation |
| * and/or other materials provided with the distribution. |
| * |
| * Neither the name of the HSQL Development Group nor the names of its |
| * contributors may be used to endorse or promote products derived from this |
| * software without specific prior written permission. |
| * |
| * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
| * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
| * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
| * ARE DISCLAIMED. IN NO EVENT SHALL HSQL DEVELOPMENT GROUP, HSQLDB.ORG, |
| * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, |
| * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, |
| * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |
| * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND |
| * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
| * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| * |
| * |
| * |
| * For work originally developed by the Hypersonic SQL Group: |
| * |
| * Copyright (c) 1995-2000, The Hypersonic SQL Group. |
| * All rights reserved. |
| * |
| * Redistribution and use in source and binary forms, with or without |
| * modification, are permitted provided that the following conditions are met: |
| * |
| * Redistributions of source code must retain the above copyright notice, this |
| * list of conditions and the following disclaimer. |
| * |
| * Redistributions in binary form must reproduce the above copyright notice, |
| * this list of conditions and the following disclaimer in the documentation |
| * and/or other materials provided with the distribution. |
| * |
| * Neither the name of the Hypersonic SQL Group nor the names of its |
| * contributors may be used to endorse or promote products derived from this |
| * software without specific prior written permission. |
| * |
| * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
| * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
| * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
| * ARE DISCLAIMED. IN NO EVENT SHALL THE HYPERSONIC SQL GROUP, |
| * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, |
| * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, |
| * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |
| * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND |
| * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
| * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| * |
| * This software consists of voluntary contributions made by many individuals |
| * on behalf of the Hypersonic SQL Group. |
| */ |
| |
| |
| package org.hsqldb.server; |
| |
| import java.io.DataInputStream; |
| import java.io.IOException; |
| import java.io.PrintWriter; |
| |
| import javax.servlet.ServletConfig; |
| import javax.servlet.ServletException; |
| import javax.servlet.http.HttpServletRequest; |
| import javax.servlet.http.HttpServletResponse; |
| |
| import org.hsqldb.DatabaseManager; |
| import org.hsqldb.DatabaseURL; |
| import org.hsqldb.HsqlException; |
| import org.hsqldb.Session; |
| import org.hsqldb.lib.DataOutputStream; |
| import org.hsqldb.persist.HsqlProperties; |
| import org.hsqldb.result.Result; |
| import org.hsqldb.result.ResultConstants; |
| import org.hsqldb.rowio.RowInputBinary; |
| import org.hsqldb.rowio.RowOutputBinary; |
| |
| // fredt@users 20020130 - patch 475586 by wreissen@users |
| // fredt@users 20020328 - patch 1.7.0 by fredt - error trapping |
| // fredt@users 20030630 - patch 1.7.2 - new protocol, persistent sessions |
| // fredt@users 20041112 - patch by Willian Crick - use web_inf directory |
| |
| /** |
| * Servlet can act as an interface between the client and the database for the |
| * the client / server mode of HSQL Database Engine. It uses the HTTP protocol |
| * for communication. This class is not required if the included HSQLDB |
| * Weberver is used on the server host. But if the host is running a J2EE |
| * application server or a servlet container such as Tomcat, the Servlet class |
| * can be hosted on this server / container to serve external requests from |
| * external hosts.<p> |
| * The remote applet / application should |
| * use the normal JDBC interfaces to connect to the URL of this servlet. An |
| * example URL is: |
| * <pre> |
| * jdbc:hsqldb:http://myhost.com:8080/servlet/org.hsqldb.server.Servlet |
| * </pre> |
| * The database path/name is taken from the servlet engine property: |
| * <pre> |
| * hsqldb.server.database |
| * </pre> |
| * <p> |
| * If the database is deployed in the WEB-INF directory of the servlet container, |
| * the property: |
| * <pre> |
| * hsqldb.server.use_web-inf_path |
| * </pre> |
| * should be set "true" in the web.xml file of the servlet container. |
| * In this case, the database path should begin with a "/". |
| * |
| * JDBC connections via the HTTP protocol are persistent |
| * in the JDBC sense. The JDBC Connection that is established can support |
| * transactions spanning several Statement calls and real PreparedStatement |
| * calls are supported. This class has been rewritten to support the new |
| * features.<p> |
| * (fredt@users)<p> |
| * |
| * Extensively rewritten for HSQLDB. |
| * |
| * @author Thomas Mueller (Hypersonic SQL Group) |
| * @author Fred Toussi (fredt@users dot sourceforge.net) |
| * @version 1.9.0 |
| * @since Hypersonic SQL |
| */ |
| public class Servlet extends javax.servlet.http.HttpServlet { |
| |
| private static final int BUFFER_SIZE = 256; |
| private String dbType; |
| private String dbPath; |
| private String errorStr; |
| private RowOutputBinary rowOut; |
| private RowInputBinary rowIn; |
| private int iQueries; |
| |
| public void init(ServletConfig config) { |
| |
| try { |
| super.init(config); |
| |
| rowOut = new RowOutputBinary(BUFFER_SIZE, 1); |
| rowIn = new RowInputBinary(rowOut); |
| } catch (ServletException e) { |
| log(e.toString()); |
| } |
| |
| String dbStr = getInitParameter("hsqldb.server.database"); |
| |
| if (dbStr == null) { |
| dbStr = "."; |
| } |
| |
| // begin WEB-INF patch */ |
| String useWebInfStr = |
| getInitParameter("hsqldb.server.use_web-inf_path"); |
| |
| if (!dbStr.equals(".") && "true".equalsIgnoreCase(useWebInfStr)) { |
| dbStr = getServletContext().getRealPath("/") + "WEB-INF/" + dbStr; |
| } |
| |
| // end WEB-INF patch |
| HsqlProperties dbURL = DatabaseURL.parseURL(dbStr, false, false); |
| |
| log("Database filename = " + dbStr); |
| |
| if (dbURL == null) { |
| errorStr = "Bad Database name"; |
| } else { |
| dbPath = dbURL.getProperty("database"); |
| dbType = dbURL.getProperty("connection_type"); |
| |
| try { |
| |
| // loosecannon1@users 1.7.2 patch properties on the JDBC URL |
| DatabaseManager.getDatabase(dbType, dbPath, dbURL); |
| } catch (HsqlException e) { |
| errorStr = e.getMessage(); |
| } |
| } |
| |
| log(errorStr); |
| log("Initialization completed."); |
| } |
| |
| private static long lModified = 0; |
| |
| protected long getLastModified(HttpServletRequest req) { |
| |
| // this is made so that the cache of the http server is not used |
| // maybe there is some other way |
| return lModified++; |
| } |
| |
| public void doGet(HttpServletRequest request, |
| HttpServletResponse response) |
| throws IOException, ServletException { |
| |
| String query = request.getQueryString(); |
| |
| if ((query == null) || (query.length() == 0)) { |
| response.setContentType("text/html"); |
| |
| // fredt@users 20020130 - patch 1.7.0 by fredt |
| // to avoid caching on the browser |
| response.setHeader("Pragma", "no-cache"); |
| |
| PrintWriter out = response.getWriter(); |
| |
| out.println( |
| "<html><head><title>HSQL Database Engine Servlet</title>"); |
| out.println("</head><body><h1>HSQL Database Engine Servlet</h1>"); |
| out.println("The servlet is running.<p>"); |
| |
| if (errorStr == null) { |
| out.println("The database is also running.<p>"); |
| out.println("Database name: " + dbType + dbPath + "<p>"); |
| out.println("Queries processed: " + iQueries + "<p>"); |
| } else { |
| out.println("<h2>The database is not running!</h2>"); |
| out.println("The error message is:<p>"); |
| out.println(errorStr); |
| } |
| |
| out.println("</body></html>"); |
| } |
| } |
| |
| public void doPost(HttpServletRequest request, |
| HttpServletResponse response) |
| throws IOException, ServletException { |
| |
| synchronized (this) { |
| DataInputStream inStream = null; |
| DataOutputStream dataOut = null; |
| |
| try { |
| |
| // fredt@users - the servlet container, Resin does not return all |
| // the bytes with one call to input.read(b,0,len) when len > 8192 |
| // bytes, the loop in the Result.read() method handles this |
| inStream = new DataInputStream(request.getInputStream()); |
| |
| int databaseID = inStream.readInt(); |
| long sessionID = inStream.readLong(); |
| int mode = inStream.readByte(); |
| Session session = DatabaseManager.getSession(databaseID, |
| sessionID); |
| Result resultIn = Result.newResult(session, mode, inStream, |
| rowIn); |
| |
| resultIn.setDatabaseId(databaseID); |
| resultIn.setSessionId(sessionID); |
| |
| Result resultOut; |
| |
| if (resultIn.getType() == ResultConstants.CONNECT) { |
| try { |
| session = DatabaseManager.newSession( |
| dbType, dbPath, resultIn.getMainString(), |
| resultIn.getSubString(), new HsqlProperties(), |
| resultIn.getZoneString(), |
| resultIn.getUpdateCount()); |
| |
| resultIn.readAdditionalResults(null, inStream, rowIn); |
| |
| resultOut = Result.newConnectionAcknowledgeResponse( |
| session.getDatabase(), session.getId(), |
| session.getDatabase().getDatabaseID()); |
| } catch (HsqlException e) { |
| resultOut = Result.newErrorResult(e); |
| } |
| } else { |
| int dbId = resultIn.getDatabaseId(); |
| long sessionId = resultIn.getSessionId(); |
| |
| session = DatabaseManager.getSession(dbId, sessionId); |
| |
| resultIn.readAdditionalResults(session, inStream, rowIn); |
| |
| resultOut = session.execute(resultIn); |
| } |
| |
| // |
| response.setContentType("application/octet-stream"); |
| response.setContentLength(rowOut.size()); |
| |
| // |
| dataOut = new DataOutputStream(response.getOutputStream()); |
| |
| resultOut.write(dataOut, rowOut); |
| |
| iQueries++; |
| } catch (HsqlException e) {} |
| finally { |
| if (dataOut != null) { |
| dataOut.close(); |
| } |
| |
| if (inStream != null) { |
| inStream.close(); |
| } |
| } |
| } |
| |
| // Trace.printSystemOut("Queries processed: "+iQueries+" \n"); |
| } |
| } |