summaryrefslogtreecommitdiff
path: root/java
diff options
context:
space:
mode:
Diffstat (limited to 'java')
-rw-r--r--java/demo/Database/.DS_Storebin0 -> 6148 bytes
-rw-r--r--java/demo/Database/library/BookI.java435
-rw-r--r--java/demo/Database/library/Client.java47
-rw-r--r--java/demo/Database/library/ConnectionPool.java133
-rw-r--r--java/demo/Database/library/Grammar.java167
-rw-r--r--java/demo/Database/library/Library.ice300
-rw-r--r--java/demo/Database/library/LibraryI.java488
-rw-r--r--java/demo/Database/library/Parser.java354
-rw-r--r--java/demo/Database/library/README51
-rw-r--r--java/demo/Database/library/ReapThread.java102
-rw-r--r--java/demo/Database/library/RunParser.java100
-rw-r--r--java/demo/Database/library/Scanner.java279
-rw-r--r--java/demo/Database/library/Server.java130
-rw-r--r--java/demo/Database/library/SessionFactoryI.java34
-rw-r--r--java/demo/Database/library/SessionI.java97
-rw-r--r--java/demo/Database/library/Token.java39
-rw-r--r--java/demo/Database/library/books30
-rw-r--r--java/demo/Database/library/build.xml64
-rw-r--r--java/demo/Database/library/config.client28
-rw-r--r--java/demo/Database/library/config.server40
-rw-r--r--java/demo/Database/library/createTypes.sql43
21 files changed, 2961 insertions, 0 deletions
diff --git a/java/demo/Database/.DS_Store b/java/demo/Database/.DS_Store
new file mode 100644
index 00000000000..ca6143d6f15
--- /dev/null
+++ b/java/demo/Database/.DS_Store
Binary files differ
diff --git a/java/demo/Database/library/BookI.java b/java/demo/Database/library/BookI.java
new file mode 100644
index 00000000000..ef9df529608
--- /dev/null
+++ b/java/demo/Database/library/BookI.java
@@ -0,0 +1,435 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2008 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+import Demo.*;
+
+// This servant is a default servant. The book identity is retreived
+// from Ice.Current object.
+class BookI extends _BookDisp
+{
+ public void
+ ice_ping(Ice.Current current)
+ {
+ Integer id = new Integer(current.id.name);
+
+ java.sql.Connection conn = _pool.acquire();
+ try
+ {
+ java.sql.PreparedStatement stmt = null;
+ try
+ {
+ stmt = conn.prepareStatement("SELECT * FROM books WHERE id = ?");
+ stmt.setInt(1, id);
+ java.sql.ResultSet rs = stmt.executeQuery();
+ if(!rs.next())
+ {
+ throw new Ice.ObjectNotExistException();
+ }
+ }
+ finally
+ {
+ if(stmt != null)
+ {
+ stmt.close();
+ }
+ }
+ }
+ catch(java.sql.SQLException e)
+ {
+ // Log the error, and raise an UnknownException.
+ error(e);
+ Ice.UnknownException ex = new Ice.UnknownException();
+ ex.initCause(e);
+ throw ex;
+ }
+ finally
+ {
+ _pool.release(conn);
+ }
+ }
+
+ public BookDescription
+ describe(Ice.Current current)
+ {
+ Integer id = new Integer(current.id.name);
+
+ java.sql.Connection conn = _pool.acquire();
+ try
+ {
+ java.sql.PreparedStatement stmt = null;
+ try
+ {
+ stmt = conn.prepareStatement("SELECT * FROM books WHERE id = ?");
+ stmt.setInt(1, id);
+ java.sql.ResultSet rs = stmt.executeQuery();
+ if(!rs.next())
+ {
+ throw new Ice.ObjectNotExistException();
+ }
+ return extractDescription(conn, rs, current.adapter);
+ }
+ finally
+ {
+ if(stmt != null)
+ {
+ stmt.close();
+ }
+ }
+ }
+ catch(java.sql.SQLException e)
+ {
+ // Log the error, and raise an UnknownException.
+ error(e);
+ Ice.UnknownException ex = new Ice.UnknownException();
+ ex.initCause(e);
+ throw ex;
+ }
+ finally
+ {
+ _pool.release(conn);
+ }
+ }
+
+ public void
+ destroy(Ice.Current current)
+ {
+ Integer id = new Integer(current.id.name);
+ java.sql.Connection conn = _pool.acquire();
+ try
+ {
+ java.sql.PreparedStatement stmt = null;
+ try
+ {
+ stmt = conn.prepareStatement("DELETE FROM books WHERE id = ?");
+ stmt.setInt(1, id);
+ int count = stmt.executeUpdate();
+ if(count == 0)
+ {
+ throw new Ice.ObjectNotExistException();
+ }
+ }
+ finally
+ {
+ if(stmt != null)
+ {
+ stmt.close();
+ }
+ }
+ }
+ catch(java.sql.SQLException e)
+ {
+ // Log the error, and raise an UnknownException.
+ error(e);
+ Ice.UnknownException ex = new Ice.UnknownException();
+ ex.initCause(e);
+ throw ex;
+ }
+ finally
+ {
+ _pool.release(conn);
+ }
+ }
+
+ public String
+ getRenter(Ice.Current current)
+ throws BookNotRentedException
+ {
+ Integer id = new Integer(current.id.name);
+ java.sql.Connection conn = _pool.acquire();
+ try
+ {
+ java.sql.PreparedStatement stmt = null;
+ try
+ {
+ stmt = conn.prepareStatement("SELECT * FROM books WHERE id = ?");
+ stmt.setInt(1, id);
+ java.sql.ResultSet rs = stmt.executeQuery();
+ if(!rs.next())
+ {
+ throw new Ice.ObjectNotExistException();
+ }
+
+ int renterId = rs.getInt("renter_id");
+ if(rs.wasNull())
+ {
+ throw new BookNotRentedException();
+ }
+ stmt.close();
+ stmt = null;
+
+ stmt = conn.prepareStatement("SELECT * FROM customers WHERE id = ?");
+ stmt.setInt(1, renterId);
+ rs = stmt.executeQuery();
+ boolean next = rs.next();
+ assert next;
+ return rs.getString("name");
+ }
+ finally
+ {
+ if(stmt != null)
+ {
+ stmt.close();
+ }
+ }
+ }
+ catch(java.sql.SQLException e)
+ {
+ // Log the error, and raise an UnknownException.
+ error(e);
+ Ice.UnknownException ex = new Ice.UnknownException();
+ ex.initCause(e);
+ throw ex;
+ }
+ finally
+ {
+ _pool.release(conn);
+ }
+ }
+
+ public void
+ rentBook(String name, Ice.Current current)
+ throws BookRentedException
+ {
+ java.sql.Connection conn = _pool.acquire();
+ Integer id = new Integer(current.id.name);
+ try
+ {
+ conn.setAutoCommit(false);
+ java.sql.PreparedStatement stmt = null;
+ try
+ {
+ stmt = conn.prepareStatement("SELECT * FROM books WHERE id = ?");
+ stmt.setInt(1, id);
+ java.sql.ResultSet rs = stmt.executeQuery();
+ if(!rs.next())
+ {
+ throw new Ice.ObjectNotExistException();
+ }
+
+ rs.getInt("renter_id");
+ if(!rs.wasNull())
+ {
+ throw new BookRentedException();
+ }
+ stmt.close();
+ stmt = null;
+
+ stmt = conn.prepareStatement("SELECT * FROM customers WHERE name = ?");
+ stmt.setString(1, name);
+ rs = stmt.executeQuery();
+
+ Integer renterId = null;
+ if(rs.next())
+ {
+ renterId = rs.getInt("id");
+ assert !rs.next();
+ }
+ else
+ {
+ stmt.close();
+ stmt = null;
+
+ stmt = conn.prepareStatement("INSERT into customers (name) VALUES(?)",
+ java.sql.Statement.RETURN_GENERATED_KEYS);
+ stmt.setString(1, name);
+ int count = stmt.executeUpdate();
+ assert count == 1;
+ rs = stmt.getGeneratedKeys();
+ if(!rs.next())
+ {
+ // ERROR:
+ }
+ renterId = rs.getInt(1);
+ }
+ stmt.close();
+ stmt = null;
+
+ stmt = conn.prepareStatement("UPDATE books SET renter_id = ? WHERE id = ?");
+ stmt.setInt(1, renterId);
+ stmt.setInt(2, id);
+ int count = stmt.executeUpdate();
+ assert count == 1;
+
+ // Commit the transaction.
+ conn.commit();
+ }
+ catch(RuntimeException e)
+ {
+ // Rollback any updates.
+ conn.rollback();
+ throw e;
+ }
+ catch(java.sql.SQLException e)
+ {
+ // Rollback any updates.
+ conn.rollback();
+ throw e;
+ }
+ finally
+ {
+ if(stmt != null)
+ {
+ stmt.close();
+ }
+ }
+ }
+ catch(java.sql.SQLException e)
+ {
+ // Log the error, and raise an UnknownException.
+ error(e);
+ Ice.UnknownException ex = new Ice.UnknownException();
+ ex.initCause(e);
+ throw ex;
+ }
+ finally
+ {
+ try
+ {
+ conn.setAutoCommit(true);
+ }
+ catch(java.sql.SQLException e)
+ {
+ // Ignore
+ }
+ _pool.release(conn);
+ }
+ }
+
+ public void
+ returnBook(Ice.Current current)
+ throws BookNotRentedException
+ {
+ Integer id = new Integer(current.id.name);
+ java.sql.Connection conn = _pool.acquire();
+ try
+ {
+ java.sql.PreparedStatement stmt = null;
+ try
+ {
+ stmt = conn.prepareStatement("SELECT * FROM books WHERE id = ?");
+ stmt.setInt(1, id);
+ java.sql.ResultSet rs = stmt.executeQuery();
+ if(!rs.next())
+ {
+ throw new Ice.ObjectNotExistException();
+ }
+ Integer renterId = rs.getInt("renter_id");
+ if(rs.wasNull())
+ {
+ throw new BookNotRentedException();
+ }
+ stmt.close();
+ stmt = null;
+
+ stmt = conn.prepareStatement("UPDATE books SET renter_id = NULL WHERE id = ?");
+ stmt.setInt(1, id);
+ int count = stmt.executeUpdate();
+ assert count == 1;
+ }
+ finally
+ {
+ if(stmt != null)
+ {
+ stmt.close();
+ }
+ }
+ }
+ catch(java.sql.SQLException e)
+ {
+ // Log the error, and raise an UnknownException.
+ error(e);
+ Ice.UnknownException ex = new Ice.UnknownException();
+ ex.initCause(e);
+ throw ex;
+ }
+ finally
+ {
+ _pool.release(conn);
+ }
+ }
+
+ BookI(Ice.Logger logger, ConnectionPool pool)
+ {
+ _logger = logger;
+ _pool = pool;
+ }
+
+ static Ice.Identity
+ createIdentity(Integer bookId)
+ {
+ Ice.Identity id = new Ice.Identity();
+ id.category = "book";
+ id.name = bookId.toString();
+ return id;
+ }
+
+ static BookDescription
+ extractDescription(java.sql.Connection conn, java.sql.ResultSet rs, Ice.ObjectAdapter adapter)
+ throws java.sql.SQLException
+ {
+ Integer id = rs.getInt("id");
+
+ BookDescription desc = new BookDescription();
+ desc.isbn = rs.getString("isbn");
+ desc.title = rs.getString("title");
+ desc.authors = new java.util.LinkedList<String>();
+ desc.proxy = BookPrxHelper.uncheckedCast(adapter.createProxy(createIdentity(id)));
+
+ java.sql.PreparedStatement stmt = null;
+ try
+ {
+ // Query for the rentedBy.
+ Integer renterId = rs.getInt("renter_id");
+ if(!rs.wasNull())
+ {
+ stmt = conn.prepareStatement("SELECT * FROM customers WHERE id = ?");
+ stmt.setInt(1, renterId);
+ java.sql.ResultSet customerRS = stmt.executeQuery();
+ boolean next = customerRS.next();
+ assert next;
+ desc.rentedBy = customerRS.getString(2);
+
+ stmt.close();
+ stmt = null;
+ }
+
+ // Query for the authors.
+ stmt = conn.prepareStatement("SELECT * FROM authors INNER JOIN authors_books ON " +
+ "authors.id=authors_books.author_id AND authors_books.book_id = ?");
+ stmt.setInt(1, id);
+ java.sql.ResultSet authorRS = stmt.executeQuery();
+ while(authorRS.next())
+ {
+ desc.authors.add(authorRS.getString("name"));
+ }
+ }
+ finally
+ {
+ if(stmt != null)
+ {
+ stmt.close();
+ }
+ }
+
+ return desc;
+ }
+
+ private void
+ error(Exception ex)
+ {
+ java.io.StringWriter sw = new java.io.StringWriter();
+ java.io.PrintWriter pw = new java.io.PrintWriter(sw);
+ ex.printStackTrace(pw);
+ pw.flush();
+ _logger.error("BookI: error:\n" + sw.toString());
+ }
+
+ private Ice.Logger _logger;
+ private ConnectionPool _pool;
+}
diff --git a/java/demo/Database/library/Client.java b/java/demo/Database/library/Client.java
new file mode 100644
index 00000000000..8a181ef1519
--- /dev/null
+++ b/java/demo/Database/library/Client.java
@@ -0,0 +1,47 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2008 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+public class Client extends Ice.Application
+{
+ class ShutdownHook extends Thread
+ {
+ public void
+ run()
+ {
+ try
+ {
+ communicator().destroy();
+ }
+ catch(Ice.LocalException ex)
+ {
+ ex.printStackTrace();
+ }
+ }
+ }
+
+ public int
+ run(String[] args)
+ {
+ //
+ // Since this is an interactive demo we want to clear the
+ // Application installed interrupt callback and install our
+ // own shutdown hook.
+ //
+ setInterruptHook(new ShutdownHook());
+
+ return RunParser.runParser(appName(), args, communicator());
+ }
+
+ static public void
+ main(String[] args)
+ {
+ Client app = new Client();
+ app.main("demo.Freeze.library.Client", args, "config.client");
+ }
+}
diff --git a/java/demo/Database/library/ConnectionPool.java b/java/demo/Database/library/ConnectionPool.java
new file mode 100644
index 00000000000..38eed101095
--- /dev/null
+++ b/java/demo/Database/library/ConnectionPool.java
@@ -0,0 +1,133 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2008 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+class ConnectionPool
+{
+ public
+ ConnectionPool(Ice.Logger logger, String url, String username, String password, int numConnections)
+ throws java.sql.SQLException
+ {
+ _logger = logger;
+ _url = url;
+ _username = username;
+ _password = password;
+
+ _nconnections = numConnections;
+ while(numConnections-- > 0)
+ {
+ _connections.add(java.sql.DriverManager.getConnection (url, username, password));
+ }
+ }
+
+ public synchronized void
+ destroy()
+ {
+ _destroyed = true;
+ while(_connections.size() != _nconnections)
+ {
+ try
+ {
+ wait();
+ }
+ catch(InterruptedException e)
+ {
+ }
+ }
+
+ while(_connections.isEmpty())
+ {
+ java.sql.Connection conn = _connections.removeFirst();
+ try
+ {
+ conn.close();
+ }
+ catch(java.sql.SQLException e)
+ {
+ }
+ }
+ }
+
+ public synchronized java.sql.Connection
+ acquire()
+ {
+ while(_connections.isEmpty() && !_destroyed)
+ {
+ try
+ {
+ wait();
+ }
+ catch(InterruptedException e)
+ {
+ }
+ }
+ if(_destroyed)
+ {
+ return null;
+ }
+ java.sql.Connection conn = _connections.removeFirst();
+
+ try
+ {
+ boolean closed = conn.isClosed();
+ if(closed)
+ {
+ _logger.warning("ConnectionPool: lost connection to database");
+ conn = null;
+ }
+ }
+ catch(java.sql.SQLException e)
+ {
+ java.io.StringWriter sw = new java.io.StringWriter();
+ java.io.PrintWriter pw = new java.io.PrintWriter(sw);
+ e.printStackTrace(pw);
+ pw.flush();
+ _logger.warning("ConnectionPool: lost connection to database:\n" + sw.toString());
+
+ conn = null;
+ }
+
+ // If the connection has been closed, or is otherwise invalid
+ // re-establish the connection.
+ while(conn == null)
+ {
+ _logger.trace("ConnectionPool", "establishing new database connection");
+ try
+ {
+ conn = java.sql.DriverManager.getConnection (_url, _username, _password);
+ }
+ catch(java.sql.SQLException e)
+ {
+ java.io.StringWriter sw = new java.io.StringWriter();
+ java.io.PrintWriter pw = new java.io.PrintWriter(sw);
+ e.printStackTrace(pw);
+ pw.flush();
+ _logger.warning("ConnectionPool: database connection failed:\n" + sw.toString());
+ }
+ }
+ return conn;
+ }
+
+ public synchronized void
+ release(java.sql.Connection connection)
+ {
+ if(connection != null)
+ {
+ _connections.add(connection);
+ notifyAll();
+ }
+ }
+
+ Ice.Logger _logger;
+ private String _url;
+ private String _username;
+ private String _password;
+ private java.util.LinkedList<java.sql.Connection> _connections = new java.util.LinkedList<java.sql.Connection>();
+ private boolean _destroyed = false;
+ private int _nconnections;
+}
diff --git a/java/demo/Database/library/Grammar.java b/java/demo/Database/library/Grammar.java
new file mode 100644
index 00000000000..2b180cf139e
--- /dev/null
+++ b/java/demo/Database/library/Grammar.java
@@ -0,0 +1,167 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2008 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+class Grammar
+{
+ Grammar(Parser p)
+ {
+ _parser = p;
+ _scanner = new Scanner(_parser);
+ }
+
+ void
+ parse()
+ {
+ while(true)
+ {
+ try
+ {
+ _token = _scanner.nextToken();
+ if(_token == null)
+ {
+ return;
+ }
+ else if(_token.type == Token.TOK_SEMI)
+ {
+ // Continue
+ }
+ else if(_token.type == Token.TOK_HELP)
+ {
+ _token = _scanner.nextToken();
+ if(_token.type != Token.TOK_SEMI)
+ {
+ throw new ParseError("Expected ';'");
+ }
+
+ _parser.usage();
+ }
+ else if(_token.type == Token.TOK_EXIT)
+ {
+ _token = _scanner.nextToken();
+ if(_token.type != Token.TOK_SEMI)
+ {
+ throw new ParseError("Expected ';'");
+ }
+
+ return;
+ }
+ else if(_token.type == Token.TOK_ADD_BOOK)
+ {
+ java.util.List s = strings();
+ if(_token.type != Token.TOK_SEMI)
+ {
+ throw new ParseError("Expected ';'");
+ }
+ _parser.addBook(s);
+ }
+ else if(_token.type == Token.TOK_FIND_ISBN)
+ {
+ java.util.List s = strings();
+ if(_token.type != Token.TOK_SEMI)
+ {
+ throw new ParseError("Expected ';'");
+ }
+ _parser.findIsbn(s);
+ }
+ else if(_token.type == Token.TOK_FIND_AUTHORS)
+ {
+ java.util.List s = strings();
+ if(_token.type != Token.TOK_SEMI)
+ {
+ throw new ParseError("Expected ';'");
+ }
+ _parser.findAuthors(s);
+ }
+ else if(_token.type == Token.TOK_NEXT_FOUND_BOOK)
+ {
+ _token = _scanner.nextToken();
+ if(_token.type != Token.TOK_SEMI)
+ {
+ throw new ParseError("Expected ';'");
+ }
+
+ _parser.nextFoundBook();
+ }
+ else if(_token.type == Token.TOK_PRINT_CURRENT)
+ {
+ _token = _scanner.nextToken();
+ if(_token.type != Token.TOK_SEMI)
+ {
+ throw new ParseError("Expected ';'");
+ }
+
+ _parser.printCurrent();
+ }
+ else if(_token.type == Token.TOK_RENT_BOOK)
+ {
+ java.util.List s = strings();
+ if(_token.type != Token.TOK_SEMI)
+ {
+ throw new ParseError("Expected ';'");
+ }
+ _parser.rentCurrent(s);
+ }
+ else if(_token.type == Token.TOK_RETURN_BOOK)
+ {
+ _token = _scanner.nextToken();
+ if(_token.type != Token.TOK_SEMI)
+ {
+ throw new ParseError("Expected ';'");
+ }
+ _parser.returnCurrent();
+ }
+ else if(_token.type == Token.TOK_REMOVE_CURRENT)
+ {
+ _token = _scanner.nextToken();
+ if(_token.type != Token.TOK_SEMI)
+ {
+ throw new ParseError("Expected ';'");
+ }
+
+ _parser.removeCurrent();
+ }
+ else
+ {
+ _parser.error("parse error");
+ }
+ }
+ catch(ParseError e)
+ {
+ _parser.error("Parse error: " + e.getMessage());
+ }
+ }
+ }
+
+ private java.util.List
+ strings()
+ {
+ java.util.List l = new java.util.ArrayList();
+ while(true)
+ {
+ _token = _scanner.nextToken();
+ if(_token.type != Token.TOK_STRING)
+ {
+ return l;
+ }
+ l.add(_token.value);
+ }
+ }
+
+ static private class ParseError extends RuntimeException
+ {
+ ParseError(String msg)
+ {
+ super(msg);
+ }
+ }
+
+ private Parser _parser;
+ private Scanner _scanner;
+ private Token _token;
+}
diff --git a/java/demo/Database/library/Library.ice b/java/demo/Database/library/Library.ice
new file mode 100644
index 00000000000..ba4b5a9b7dc
--- /dev/null
+++ b/java/demo/Database/library/Library.ice
@@ -0,0 +1,300 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2008 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+#ifndef LIBRARY_ICE
+#define LIBRARY_ICE
+
+#include <Ice/BuiltinSequences.ice>
+
+module Demo
+{
+
+/**
+ *
+ * This exception is raised if the book already exists.
+ *
+ **/
+exception BookExistsException
+{
+};
+
+/**
+ *
+ * This exception is raised if a book has already been rented.
+ *
+ **/
+exception BookRentedException
+{
+};
+
+/**
+ *
+ * This exception is raised if the book has not been rented.
+ *
+ **/
+exception BookNotRentedException
+{
+};
+
+/**
+ *
+ * This exception is raised if a query has no results.
+ *
+ **/
+exception NoResultsException
+{
+};
+
+/**
+ *
+ * This exception is raised if a query is already active.
+ *
+ **/
+exception QueryActiveException
+{
+};
+
+/** Forward declaration for the interface Book. */
+interface Book;
+
+/**
+ *
+ * A description of a book.
+ *
+ **/
+struct BookDescription
+{
+ /** The ISBN number of the book. */
+ string isbn;
+
+ /** The title of the book. */
+ string title;
+
+ /** The authors of the book. */
+ ["java:type:java.util.LinkedList<String>:java.util.List<String>"] Ice::StringSeq authors;
+
+ /** The customer name of the renter. */
+ string rentedBy;
+
+ /** A proxy to the associated book. */
+ Book* proxy;
+};
+
+/** A sequence of book descriptions. */
+["java:type:java.util.LinkedList<BookDescription>:java.util.List<BookDescription>"]
+sequence<BookDescription> BookDescriptionSeq;
+
+/**
+ *
+ * This interface represents a book.
+ *
+ **/
+interface Book
+{
+ /**
+ *
+ * Get a description of the book.
+ *
+ * @return The book description.
+ *
+ **/
+ idempotent BookDescription describe();
+
+ /**
+ *
+ * Rent the book to the specified customer.
+ *
+ * @param customer The customer.
+ *
+ * @throws BookRentedException Raised if the book has already been
+ * rented.
+ *
+ **/
+ void rentBook(string name)
+ throws BookRentedException;
+
+ /**
+ *
+ * Get the renter.
+ *
+ * @return The current rental customer.
+ *
+ * @throws BookNotRentedException Raised if the book is not
+ * currently rented.
+ *
+ **/
+ idempotent string getRenter()
+ throws BookNotRentedException;
+
+ /**
+ *
+ * Return the book.
+ *
+ * @throws BookNotRentedException Raised if the book is not
+ * currently rented.
+ *
+ **/
+ void returnBook()
+ throws BookNotRentedException;
+
+ /**
+ *
+ * Destroy the book.
+ *
+ **/
+ void destroy();
+};
+
+/**
+ *
+ * Interface to get query results.
+ *
+ **/
+interface BookQueryResult
+{
+ /**
+ *
+ * Get more query results.
+ *
+ * @param n The maximum number of results to return.
+ *
+ * @param destroyed There are no more results, and the query has
+ * been destroyed.
+ *
+ * @returns A sequence of up to n results.
+ *
+ **/
+ BookDescriptionSeq next(int n, out bool destroyed);
+
+ /**
+ *
+ * Destroy the query result.
+ *
+ **/
+ void destroy();
+};
+
+/**
+ *
+ * An interface to the library.
+ *
+ **/
+interface Library
+{
+ /**
+ *
+ * Query based on isbn number. The query is a partial match of the
+ * isbn number.
+ *
+ * @param isbn The ISBN number.
+ *
+ * @param first The first book description.
+ *
+ * @param result The remainder of the results. If there are no
+ * further results, a null proxy is returned.
+
+ * @throws NoResultsException Raised if there are no results.
+ *
+ * @throws QueryActiveException Raised if an existing query is active.
+ *
+ **/
+ void queryByIsbn(string isbn, out BookDescription first, out BookQueryResult* result)
+ throws QueryActiveException, NoResultsException;
+
+ /**
+ *
+ * Query based on the author name. The query is a partial match of
+ * the authors name.
+ *
+ * @param author The authors name.
+ *
+ * @param first The first book description.
+ *
+ * @param result The remainder of the results. If there are no
+ * further results, a null proxy is returned.
+
+ * @throws NoResultsException Raised if there are no results.
+ *
+ * @throws QueryActiveException Raised if an existing query is active.
+ *
+ **/
+ void queryByAuthor(string author, out BookDescription first, out BookQueryResult* result)
+ throws QueryActiveException, NoResultsException;
+
+ /**
+ *
+ * Create a book with the given description.
+ *
+ * @param description The book description.
+ *
+ * @return A proxy for the new book.
+ *
+ * @throws BookExistsException Raised if a book with the same ISBN
+ * number already exists.
+ *
+ **/
+ Book* createBook(string isbn, string title,
+ ["java:type:java.util.LinkedList<String>:java.util.List<String>"] Ice::StringSeq authors)
+ throws BookExistsException;
+};
+
+/**
+ *
+ * The session object. This is used to retrieve a per-session library
+ * on behalf of the client. If the session is not refreshed on a
+ * periodic basis, it will be automatically destroyed.
+ *
+ */
+interface Session
+{
+ /**
+ *
+ * Get the library object.
+ *
+ * @return A proxy for the new library.
+ *
+ **/
+ Library* getLibrary();
+
+ /**
+ *
+ * Refresh a session. If a session is not refreshed on a regular
+ * basis by the client, it will be automatically destroyed.
+ *
+ **/
+ idempotent void refresh();
+
+ /**
+ *
+ * Destroy the session.
+ *
+ **/
+ void destroy();
+};
+
+/**
+ *
+ * Interface to create new sessions.
+ *
+ **/
+interface SessionFactory
+{
+ /**
+ *
+ * Create a session.
+ *
+ * @return A proxy to the session.
+ *
+ **/
+ Session* create();
+};
+
+};
+
+#endif
diff --git a/java/demo/Database/library/LibraryI.java b/java/demo/Database/library/LibraryI.java
new file mode 100644
index 00000000000..99c2f7fddc8
--- /dev/null
+++ b/java/demo/Database/library/LibraryI.java
@@ -0,0 +1,488 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2008 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+import Demo.*;
+
+// Per-session library object.
+class LibraryI extends _LibraryDisp
+{
+ class BookQueryResultI extends _BookQueryResultDisp
+ {
+ // The query result owns the java.sql.Connection object until
+ // destroyed.
+ BookQueryResultI(java.sql.Connection conn, java.sql.PreparedStatement stmt, java.sql.ResultSet rs)
+ {
+ _conn = conn;
+ _stmt = stmt;
+ _rs = rs;
+ }
+
+ synchronized public java.util.List<BookDescription>
+ next(int n, Ice.BooleanHolder destroyed, Ice.Current current)
+ {
+ if(_destroyed)
+ {
+ throw new Ice.ObjectNotExistException();
+ }
+ destroyed.value = false;
+ java.util.List<BookDescription> l = new java.util.LinkedList<BookDescription>();
+ if(n <= 0)
+ {
+ return l;
+ }
+ boolean next = true;
+ try
+ {
+ for(int i = 0; i < n && next; ++i)
+ {
+ l.add(BookI.extractDescription(_conn, _rs, current.adapter));
+ next = _rs.next();
+ }
+ }
+ catch(java.sql.SQLException e)
+ {
+ // Log the error, and raise an UnknownException.
+ error(e);
+ Ice.UnknownException ex = new Ice.UnknownException();
+ ex.initCause(e);
+ throw ex;
+ }
+
+ if(!next)
+ {
+ try
+ {
+ destroyed.value = true;
+ destroy(current);
+ }
+ catch(Exception e)
+ {
+ // Ignore.
+ }
+ }
+
+ return l;
+ }
+
+ synchronized public void
+ destroy(Ice.Current current)
+ {
+ if(_destroyed)
+ {
+ throw new Ice.ObjectNotExistException();
+ }
+ _destroyed = true;
+
+ try
+ {
+ // Closing a statement closes the associated
+ // java.sql.ResultSet.
+ _stmt.close();
+ }
+ catch(java.sql.SQLException e)
+ {
+ // Log the error, but otherwise ignore the exception.
+ error(e);
+ }
+ _pool.release(_conn);
+
+ current.adapter.remove(current.id);
+ }
+
+ // Called on application shutdown by the Library.
+ synchronized private void
+ shutdown()
+ {
+ if(!_destroyed)
+ {
+ _destroyed = true;
+
+ try
+ {
+ // Closing a statement closes the associated
+ // java.sql.ResultSet.
+ _stmt.close();
+ }
+ catch(java.sql.SQLException e)
+ {
+ // Log the error, but otherwise ignore the
+ // exception.
+ error(e);
+ }
+ _pool.release(_conn);
+ }
+ }
+
+ private java.sql.Connection _conn;
+ private java.sql.PreparedStatement _stmt;
+ private java.sql.ResultSet _rs;
+ private boolean _destroyed = false;
+ }
+
+ synchronized public void
+ queryByIsbn(String isbn, BookDescriptionHolder first, BookQueryResultPrxHolder result, Ice.Current current)
+ throws QueryActiveException, NoResultsException
+ {
+ reapQuery();
+
+ java.sql.Connection conn = _pool.acquire();
+ try
+ {
+ java.sql.PreparedStatement stmt = null;
+ try
+ {
+ stmt = conn.prepareStatement("SELECT * FROM books WHERE isbn LIKE ?");
+ stmt.setString(1, "%" + isbn + "%");
+ java.sql.ResultSet rs = stmt.executeQuery();
+ if(!rs.next())
+ {
+ throw new NoResultsException();
+ }
+
+ first.value = BookI.extractDescription(conn, rs, current.adapter);
+ if(rs.next())
+ {
+ _queryImpl = new BookQueryResultI(conn, stmt, rs);
+ result.value = BookQueryResultPrxHelper.uncheckedCast(current.adapter.addWithUUID(_queryImpl));
+ _query = result.value;
+ // The java.sql.Connection, result set and
+ // statement are now owned by the book query. Set
+ // to null so they are not prematurely released.
+ conn = null;
+ stmt = null;
+ }
+ }
+ finally
+ {
+ if(stmt != null)
+ {
+ // Closing a statement closes the associated
+ // java.sql.ResultSet.
+ stmt.close();
+ }
+ }
+ }
+ catch(java.sql.SQLException e)
+ {
+ // Log the error, and raise an UnknownException.
+ error(e);
+ Ice.UnknownException ex = new Ice.UnknownException();
+ ex.initCause(e);
+ throw ex;
+ }
+ finally
+ {
+ _pool.release(conn);
+ }
+ }
+
+ synchronized public void
+ queryByAuthor(String author, BookDescriptionHolder first, BookQueryResultPrxHolder result, Ice.Current current)
+ throws QueryActiveException, NoResultsException
+ {
+ reapQuery();
+
+ java.sql.Connection conn = _pool.acquire();
+ try
+ {
+ java.sql.PreparedStatement stmt = null;
+ try
+ {
+ // Find each of the authors.
+ stmt = conn.prepareStatement("SELECT * FROM authors WHERE name LIKE ?");
+ stmt.setString(1, "%" + author + "%");
+ java.sql.ResultSet rs = stmt.executeQuery();
+ if(!rs.next())
+ {
+ throw new NoResultsException();
+ }
+
+ // Build a query that finds all books by these set of
+ // authors.
+ StringBuffer sb = new StringBuffer("SELECT * FROM books INNER JOIN authors_books ON " +
+ "books.id=authors_books.book_id AND (");
+ boolean front = true;
+ do
+ {
+ if(!front)
+ {
+ sb.append(" OR ");
+ }
+ front = false;
+ sb.append("authors_books.author_id=");
+ sb.append(rs.getInt("id"));
+ }
+ while(rs.next());
+ sb.append(")");
+
+ stmt.close();
+ stmt = null;
+
+ // Execute the query.
+ stmt = conn.prepareStatement(sb.toString());
+ rs = stmt.executeQuery();
+ if(!rs.next())
+ {
+ throw new NoResultsException();
+ }
+
+ first.value = BookI.extractDescription(conn, rs, current.adapter);
+ if(rs.next())
+ {
+ _queryImpl = new BookQueryResultI(conn, stmt, rs);
+ result.value = BookQueryResultPrxHelper.uncheckedCast(current.adapter.addWithUUID(_queryImpl));
+ _query = result.value;
+ // The java.sql.Connection, result set and
+ // statement are now owned by the book query. Set
+ // to null so they are not prematurely released.
+ stmt = null;
+ conn = null;
+ }
+ }
+ finally
+ {
+ // Closing a statement closes the associated
+ // java.sql.ResultSet.
+ if(stmt != null)
+ {
+ stmt.close();
+ }
+ }
+ }
+ catch(java.sql.SQLException e)
+ {
+ // Log the error, and raise an UnknownException.
+ error(e);
+ Ice.UnknownException ex = new Ice.UnknownException();
+ ex.initCause(e);
+ throw ex;
+ }
+ finally
+ {
+ _pool.release(conn);
+ }
+ }
+
+ synchronized public BookPrx
+ createBook(String isbn, String title, java.util.List<String> authors, Ice.Current current)
+ throws BookExistsException
+ {
+ java.sql.Connection conn = _pool.acquire();
+ try
+ {
+ conn.setAutoCommit(false);
+ java.sql.PreparedStatement stmt = null;
+ try
+ {
+ stmt = conn.prepareStatement("SELECT * FROM books WHERE isbn = ?");
+ stmt.setString(1, isbn);
+ java.sql.ResultSet rs = stmt.executeQuery();
+ if(rs.next())
+ {
+ throw new BookExistsException();
+ }
+
+ stmt.close();
+ stmt = null;
+
+ //
+ // First convert the authors string to an id set.
+ //
+ java.util.List<Integer> authIds = new java.util.LinkedList<Integer>();
+ java.util.Iterator<String> p = authors.iterator();
+ while(p.hasNext())
+ {
+ String author = p.next();
+
+ Integer id;
+ stmt = conn.prepareStatement("SELECT * FROM authors WHERE name = ?");
+ stmt.setString(1, author);
+ rs = stmt.executeQuery();
+ if(rs.next())
+ {
+ // If there is a result, then the database
+ // already contains this author.
+ id = rs.getInt(1);
+ assert !rs.next();
+ }
+ else
+ {
+ stmt.close();
+ stmt = null;
+
+ // Otherwise, create a new author record.
+ stmt = conn.prepareStatement("INSERT INTO authors (name) VALUES(?)",
+ java.sql.Statement.RETURN_GENERATED_KEYS);
+ stmt.setString(1, author);
+ int count = stmt.executeUpdate();
+ assert count == 1;
+ rs = stmt.getGeneratedKeys();
+ boolean next = rs.next();
+ assert next;
+ id = rs.getInt(1);
+ }
+
+ stmt.close();
+ stmt = null;
+
+ // Add the new id to the list of ids.
+ authIds.add(id);
+ }
+
+ // Create the new book.
+ stmt = conn.prepareStatement("INSERT INTO books (isbn, title) VALUES(?, ?)",
+ java.sql.Statement.RETURN_GENERATED_KEYS);
+ stmt.setString(1, isbn);
+ stmt.setString(2, title);
+ int count = stmt.executeUpdate();
+ assert count == 1;
+
+ rs = stmt.getGeneratedKeys();
+ boolean next = rs.next();
+ assert next;
+ Integer bookId = rs.getInt(1);
+
+ stmt.close();
+ stmt = null;
+
+ // Create new authors_books records.
+ java.util.Iterator<Integer> q = authIds.iterator();
+ while(q.hasNext())
+ {
+ stmt = conn.prepareStatement("INSERT INTO authors_books (book_id, author_id) VALUES(?, ?)");
+ stmt.setInt(1, bookId);
+ stmt.setInt(2, q.next());
+ count = stmt.executeUpdate();
+ assert count == 1;
+
+ stmt.close();
+ stmt = null;
+ }
+
+ // Commit the transaction.
+ conn.commit();
+
+ return BookPrxHelper.uncheckedCast(current.adapter.createProxy(BookI.createIdentity(bookId)));
+ }
+ catch(RuntimeException e)
+ {
+ // Rollback any updates.
+ conn.rollback();
+ throw e;
+ }
+ catch(java.sql.SQLException e)
+ {
+ // Rollback any updates.
+ conn.rollback();
+ throw e;
+ }
+ finally
+ {
+ if(stmt != null)
+ {
+ stmt.close();
+ }
+ }
+ }
+ catch(java.sql.SQLException e)
+ {
+ // Log the error, and raise an UnknownException.
+ error(e);
+ Ice.UnknownException ex = new Ice.UnknownException();
+ ex.initCause(e);
+ throw ex;
+ }
+ finally
+ {
+ try
+ {
+ conn.setAutoCommit(true);
+ }
+ catch(java.sql.SQLException e)
+ {
+ // Ignore
+ }
+ _pool.release(conn);
+ }
+ }
+
+ LibraryI(Ice.Logger logger, ConnectionPool pool)
+ {
+ _logger = logger;
+ _pool = pool;
+ }
+
+ // Called when the session is destroyed.
+ synchronized void
+ destroy()
+ {
+ if(_query != null)
+ {
+ try
+ {
+ _query.destroy();
+ }
+ catch(Ice.ObjectNotExistException e)
+ {
+ }
+ _query = null;
+ _queryImpl = null;
+ }
+ }
+
+ // Called on application shutdown.
+ synchronized void
+ shutdown()
+ {
+ if(_queryImpl != null)
+ {
+ _queryImpl.shutdown();
+ _queryImpl = null;
+ _query = null;
+ }
+ }
+
+ private void
+ error(Exception ex)
+ {
+ java.io.StringWriter sw = new java.io.StringWriter();
+ java.io.PrintWriter pw = new java.io.PrintWriter(sw);
+ ex.printStackTrace(pw);
+ pw.flush();
+ _logger.error("LibraryI: error:\n" + sw.toString());
+ }
+
+ private void
+ reapQuery()
+ throws QueryActiveException
+ {
+ if(_query != null)
+ {
+ try
+ {
+ _query.ice_ping();
+ }
+ catch(Ice.ObjectNotExistException e)
+ {
+ _query = null;
+ _queryImpl = null;
+ }
+
+ if(_query != null)
+ {
+ throw new QueryActiveException();
+ }
+ }
+ }
+
+ private Ice.Logger _logger;
+ private ConnectionPool _pool;
+ private BookQueryResultPrx _query = null;
+ private BookQueryResultI _queryImpl = null;
+}
diff --git a/java/demo/Database/library/Parser.java b/java/demo/Database/library/Parser.java
new file mode 100644
index 00000000000..be4f19ec6fe
--- /dev/null
+++ b/java/demo/Database/library/Parser.java
@@ -0,0 +1,354 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2008 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+import Demo.*;
+
+class Parser
+{
+ Parser(Ice.Communicator communicator, LibraryPrx library)
+ {
+ _library = library;
+ }
+
+ void
+ usage()
+ {
+ System.err.print(
+ "help Print this message.\n" +
+ "exit, quit Exit this program.\n" +
+ "add isbn title authors Create new book.\n" +
+ "isbn NUMBER Find the book with given ISBN number.\n" +
+ "authors NAME Find all books by the given authors.\n" +
+ "next Set the current book to the next one that was found.\n" +
+ "current Display the current book.\n" +
+ "rent NAME Rent the current book for customer NAME.\n" +
+ "return Return the currently rented book.\n" +
+ "remove Permanently remove the current book from the library.\n");
+ }
+
+ void
+ addBook(java.util.List args)
+ {
+ if(args.size() != 3)
+ {
+ error("`add' requires at exactly three arguments (type `help' for more info)");
+ return;
+ }
+
+ try
+ {
+ String isbn = (String)args.get(0);
+ String title = (String)args.get(1);
+
+ java.util.List<String> authors = new java.util.LinkedList<String>();
+ java.util.StringTokenizer st = new java.util.StringTokenizer((String)args.get(2), ",");
+ while(st.hasMoreTokens())
+ {
+ authors.add(st.nextToken().trim());
+ }
+
+ BookPrx book = _library.createBook(isbn, title, authors);
+ System.out.println("added new book with isbn " + isbn);
+ }
+ catch(BookExistsException ex)
+ {
+ error("the book already exists.");
+ }
+ catch(Ice.LocalException ex)
+ {
+ error(ex.toString());
+ }
+ }
+
+ void
+ findIsbn(java.util.List args)
+ {
+ if(args.size() != 1)
+ {
+ error("`isbn' requires exactly one argument (type `help' for more info)");
+ return;
+ }
+
+ try
+ {
+ if(_query != null)
+ {
+ try
+ {
+ _query.destroy();
+ }
+ catch(Exception e)
+ {
+ // Ignore
+ }
+ }
+ _query = null;
+ _current = null;
+
+ BookDescriptionHolder first = new BookDescriptionHolder();
+ BookQueryResultPrxHolder result = new BookQueryResultPrxHolder();
+
+ _library.queryByIsbn((String)args.get(0), first, result);
+ _current = first.value;
+ _query = result.value;
+ printCurrent();
+ }
+ catch(QueryActiveException ex)
+ {
+ error(ex.toString());
+ }
+ catch(NoResultsException ex)
+ {
+ error(ex.toString());
+ }
+ catch(Ice.LocalException ex)
+ {
+ error(ex.toString());
+ }
+ }
+
+ void
+ findAuthors(java.util.List args)
+ {
+ if(args.size() != 1)
+ {
+ error("`authors' requires exactly one argument (type `help' for more info)");
+ return;
+ }
+
+ try
+ {
+ if(_query != null)
+ {
+ try
+ {
+ _query.destroy();
+ }
+ catch(Exception e)
+ {
+ // Ignore
+ }
+ }
+ _query = null;
+ _current = null;
+
+ BookDescriptionHolder first = new BookDescriptionHolder();
+ BookQueryResultPrxHolder result = new BookQueryResultPrxHolder();
+
+ _library.queryByAuthor((String)args.get(0), first, result);
+ _current = first.value;
+ _query = result.value;
+ printCurrent();
+ }
+ catch(QueryActiveException ex)
+ {
+ error(ex.toString());
+ }
+ catch(NoResultsException ex)
+ {
+ error(ex.toString());
+ }
+ catch(Ice.LocalException ex)
+ {
+ error(ex.toString());
+ }
+ }
+
+ void
+ nextFoundBook()
+ {
+ if(_query != null)
+ {
+ Ice.IntHolder remaining = new Ice.IntHolder();
+ Ice.BooleanHolder destroyed = new Ice.BooleanHolder();
+ java.util.List<BookDescription> next = _query.next(1, destroyed);
+ if(destroyed.value)
+ {
+ _query = null;
+ _current = null;
+ }
+ else
+ {
+ _current = next.get(0);
+ }
+ }
+ printCurrent();
+ }
+
+ void
+ printCurrent()
+ {
+ try
+ {
+ if(_current != null)
+ {
+ System.out.println("current book is:" );
+ System.out.println("isbn: " + _current.isbn);
+ System.out.println("title: " + _current.title);
+ System.out.println("authors: " + _current.authors);
+ if(_current.rentedBy.length() > 0)
+ {
+ System.out.println("rented: " + _current.rentedBy);
+ }
+ }
+ else
+ {
+ System.out.println("no current book");
+ }
+ }
+ catch(Ice.ObjectNotExistException ex)
+ {
+ System.out.println("current book no longer exists");
+ }
+ catch(Ice.LocalException ex)
+ {
+ error(ex.toString());
+ }
+ }
+
+ void
+ rentCurrent(java.util.List args)
+ {
+ if(args.size() != 1)
+ {
+ error("`rent' requires exactly one argument (type `help' for more info)");
+ return;
+ }
+
+ try
+ {
+ if(_current != null)
+ {
+ _current.proxy.rentBook((String)args.get(0));
+ System.out.println("the book is now rented by `" + (String)args.get(0) + "'");
+ }
+ else
+ {
+ System.out.println("no current book");
+ }
+ }
+ catch(BookRentedException ex)
+ {
+ System.out.println("the book has already been rented.");
+ }
+ catch(Ice.ObjectNotExistException ex)
+ {
+ System.out.println("current book no longer exists");
+ }
+ catch(Ice.LocalException ex)
+ {
+ error(ex.toString());
+ }
+ }
+
+ void
+ returnCurrent()
+ {
+ try
+ {
+ if(_current != null)
+ {
+ _current.proxy.returnBook();
+ System.out.println( "the book has been returned.");
+ }
+ else
+ {
+ System.out.println("no current book");
+ }
+ }
+ catch(BookNotRentedException ex)
+ {
+ System.out.println("the book is not currently rented.");
+ }
+ catch(Ice.ObjectNotExistException ex)
+ {
+ System.out.println("current book no longer exists");
+ }
+ catch(Ice.LocalException ex)
+ {
+ error(ex.toString());
+ }
+ }
+
+ void
+ removeCurrent()
+ {
+ try
+ {
+ if(_current != null)
+ {
+ _current.proxy.destroy();
+ _current = null;
+ System.out.println("removed current book" );
+ }
+ else
+ {
+ System.out.println("no current book" );
+ }
+ }
+ catch(Ice.ObjectNotExistException ex)
+ {
+ System.out.println("current book no longer exists");
+ }
+ catch(Ice.LocalException ex)
+ {
+ error(ex.toString());
+ }
+ }
+
+ void
+ error(String s)
+ {
+ System.err.println("error: " + s);
+ }
+
+ void
+ warning(String s)
+ {
+ System.err.println("warning: " + s);
+ }
+
+ String
+ getInput()
+ {
+ System.out.print(">>> ");
+ System.out.flush();
+
+ try
+ {
+ return _in.readLine();
+ }
+ catch(java.io.IOException e)
+ {
+ return null;
+ }
+ }
+
+ int
+ parse()
+ {
+ _query = null;
+ _current = null;
+
+ _in = new java.io.BufferedReader(new java.io.InputStreamReader(System.in));
+
+ Grammar g = new Grammar(this);
+ g.parse();
+
+ return 0;
+ }
+
+ private BookQueryResultPrx _query;
+ private BookDescription _current;
+
+ private LibraryPrx _library;
+
+ private java.io.BufferedReader _in;
+ private boolean _interactive;
+}
diff --git a/java/demo/Database/library/README b/java/demo/Database/library/README
new file mode 100644
index 00000000000..f7340d80620
--- /dev/null
+++ b/java/demo/Database/library/README
@@ -0,0 +1,51 @@
+MySQL JDBC Demo
+===============
+
+This demo shows how to implement an Ice server that uses mysql
+through a JDBC API.
+
+It is a fairly simple demo that illustrates how to:
+
+ - Map relational data to Ice objects, in particular convert between
+ Ice and JDBC types.
+ - Use an JDBC connection pool to provide JDBC connections to Ice
+ requests.
+ - Use an Ice servant locator.
+
+
+Building the demo
+-----------------
+
+- Install mysql.
+
+- Download version 5.0.8 of the mysql JDBC connector. Ensure that
+ mysql-connector-java-5.0.8-bin.jar is in your CLASSPATH.
+
+- Ensure that your user (by default, matthew) has appropriate
+ privileges.
+
+- Create the SQL tables using the provided createTypes.sql
+ script. For example:
+
+ $ mysql --user=matthew --pass=foo library < initialize.mysql
+
+Running the demo
+----------------
+
+Review the JDBC properties in the config.server file. You may need to
+change them to connect to your mysql server.
+
+To run the demo, first start the server:
+
+ $ java Server
+
+In another window, populate the server's database by starting the
+client and redirecting its input from the file "books":
+
+$ java Client < books
+
+Then start the client again to use the demo interactively:
+
+$ java Client
+
+Type "help" to get a list of valid commands.
diff --git a/java/demo/Database/library/ReapThread.java b/java/demo/Database/library/ReapThread.java
new file mode 100644
index 00000000000..5bef3cd3c50
--- /dev/null
+++ b/java/demo/Database/library/ReapThread.java
@@ -0,0 +1,102 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2008 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+import Demo.*;
+
+class ReapThread extends Thread
+{
+ static class SessionProxyPair
+ {
+ SessionProxyPair(Demo.SessionPrx p, SessionI s)
+ {
+ proxy = p;
+ session = s;
+ }
+
+ Demo.SessionPrx proxy;
+ SessionI session;
+ }
+
+ ReapThread(Ice.Logger logger)
+ {
+ _logger = logger;
+ }
+
+ synchronized public void
+ run()
+ {
+ while(!_terminated)
+ {
+ try
+ {
+ wait(1000);
+ }
+ catch(InterruptedException e)
+ {
+ }
+
+ if(!_terminated)
+ {
+ java.util.Iterator<SessionProxyPair> p = _sessions.iterator();
+ while(p.hasNext())
+ {
+ SessionProxyPair s = p.next();
+ try
+ {
+ //
+ // Session destruction may take time in a
+ // real-world example. Therefore the current time
+ // is computed for each iteration.
+ //
+ if((System.currentTimeMillis() - s.session.timestamp()) > _timeout)
+ {
+ _logger.trace("ReapThread", "The session " + s.proxy.ice_getIdentity() + " has timed out.");
+ s.proxy.destroy();
+ p.remove();
+ }
+ }
+ catch(Ice.ObjectNotExistException e)
+ {
+ p.remove();
+ }
+ }
+ }
+ }
+ }
+
+ synchronized public void
+ terminate()
+ {
+ _terminated = true;
+ notify();
+
+ // Destroy each of the sessions, releasing any resources they
+ // may hold. This calls directly on the session, not via the
+ // proxy since terminate() is called after the communicator is
+ // shutdown, which means calls on collocated objects is not
+ // permitted.
+ java.util.Iterator<SessionProxyPair> p = _sessions.iterator();
+ while(p.hasNext())
+ {
+ p.next().session.shutdown();
+ }
+ _sessions.clear();
+ }
+
+ synchronized public void
+ add(SessionPrx proxy, SessionI session)
+ {
+ _sessions.add(new SessionProxyPair(proxy, session));
+ }
+
+ private final long _timeout = 10 * 1000; // 10 seconds.
+ private Ice.Logger _logger;
+ private boolean _terminated = false;
+ private java.util.List<SessionProxyPair> _sessions = new java.util.LinkedList<SessionProxyPair>();
+}
diff --git a/java/demo/Database/library/RunParser.java b/java/demo/Database/library/RunParser.java
new file mode 100644
index 00000000000..42b10910861
--- /dev/null
+++ b/java/demo/Database/library/RunParser.java
@@ -0,0 +1,100 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2008 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+import Demo.*;
+
+class RunParser
+{
+ static private class SessionRefreshThread extends Thread
+ {
+ SessionRefreshThread(Ice.Logger logger, long timeout, SessionPrx session)
+ {
+ _logger = logger;
+ _session = session;
+ _timeout = timeout;
+ }
+
+ synchronized public void
+ run()
+ {
+ while(!_terminated)
+ {
+ try
+ {
+ wait(_timeout);
+ }
+ catch(InterruptedException e)
+ {
+ }
+ if(!_terminated)
+ {
+ try
+ {
+ _session.refresh();
+ }
+ catch(Ice.LocalException ex)
+ {
+ _logger.warning("SessionRefreshThread: " + ex);
+ _terminated = true;
+ }
+ }
+ }
+ }
+
+ synchronized private void
+ terminate()
+ {
+ _terminated = true;
+ notify();
+ }
+
+ final private Ice.Logger _logger;
+ final private SessionPrx _session;
+ final private long _timeout;
+ private boolean _terminated = false;
+ }
+
+ static int
+ runParser(String appName, String[] args, Ice.Communicator communicator)
+ {
+ SessionFactoryPrx factory = SessionFactoryPrxHelper.checkedCast(
+ communicator.propertyToProxy("SessionFactory.Proxy"));
+ if(factory == null)
+ {
+ System.err.println(appName + ": invalid object reference");
+ return 1;
+ }
+
+ SessionPrx session = factory.create();
+ SessionRefreshThread refresh = new SessionRefreshThread(communicator.getLogger(), 5000, session);
+ refresh.start();
+
+ LibraryPrx library = session.getLibrary();
+
+ Parser parser = new Parser(communicator, library);
+ int rc = parser.parse();
+
+ if(refresh != null)
+ {
+ refresh.terminate();
+ try
+ {
+ refresh.join();
+ }
+ catch(InterruptedException e)
+ {
+ }
+ refresh = null;
+ }
+
+ session.destroy();
+
+ return rc;
+ }
+}
diff --git a/java/demo/Database/library/Scanner.java b/java/demo/Database/library/Scanner.java
new file mode 100644
index 00000000000..f5ee752de84
--- /dev/null
+++ b/java/demo/Database/library/Scanner.java
@@ -0,0 +1,279 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2008 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+class Scanner
+{
+ Scanner(Parser p)
+ {
+ _parser = p;
+ }
+
+ Token
+ nextToken()
+ {
+ String s = next();
+ if(s == null)
+ {
+ return null;
+ }
+
+ if(s.equals(";"))
+ {
+ return new Token(Token.TOK_SEMI);
+ }
+ else if(s.equals("help"))
+ {
+ return new Token(Token.TOK_HELP);
+ }
+ else if(s.equals("exit") || s.equals("quit"))
+ {
+ return new Token(Token.TOK_EXIT);
+ }
+ else if(s.equals("add"))
+ {
+ return new Token(Token.TOK_ADD_BOOK);
+ }
+ else if(s.equals("isbn"))
+ {
+ return new Token(Token.TOK_FIND_ISBN);
+ }
+ else if(s.equals("authors"))
+ {
+ return new Token(Token.TOK_FIND_AUTHORS);
+ }
+ else if(s.equals("next"))
+ {
+ return new Token(Token.TOK_NEXT_FOUND_BOOK);
+ }
+ else if(s.equals("current"))
+ {
+ return new Token(Token.TOK_PRINT_CURRENT);
+ }
+ else if(s.equals("rent"))
+ {
+ return new Token(Token.TOK_RENT_BOOK);
+ }
+ else if(s.equals("return"))
+ {
+ return new Token(Token.TOK_RETURN_BOOK);
+ }
+ else if(s.equals("remove"))
+ {
+ return new Token(Token.TOK_REMOVE_CURRENT);
+ }
+ else
+ {
+ return new Token(Token.TOK_STRING, s);
+ }
+ }
+
+ static private class EndOfInput extends Exception
+ {
+ }
+
+ private char
+ get()
+ throws EndOfInput
+ {
+ //
+ // If there is an character in the unget buffer, return it.
+ //
+ if(_unget)
+ {
+ _unget = false;
+ return _ungetChar;
+ }
+
+ //
+ // No current buffer?
+ //
+ if(_buf == null)
+ {
+ _buf = _parser.getInput();
+ _pos = 0;
+ if(_buf == null)
+ {
+ throw new EndOfInput();
+ }
+ }
+
+ //
+ // At the end-of-buffer?
+ //
+ while(_pos >= _buf.length())
+ {
+ _buf = null;
+ _pos = 0;
+ return '\n';
+ }
+
+ return _buf.charAt(_pos++);
+ }
+
+ //
+ // unget only works with one character.
+ //
+ private void
+ unget(char c)
+ {
+ assert(!_unget);
+ _unget = true;
+ _ungetChar = c;
+ }
+
+ private String
+ next()
+ {
+ //
+ // Eat any whitespace.
+ //
+ char c;
+ try
+ {
+ do
+ {
+ c = get();
+ }
+ while(Character.isWhitespace(c) && c != '\n');
+ }
+ catch(EndOfInput ignore)
+ {
+ return null;
+ }
+
+ StringBuffer buf = new StringBuffer();
+
+ if(c == ';' || c == '\n')
+ {
+ buf.append(';');
+ }
+ else if(c == '\'')
+ {
+ try
+ {
+ while(true)
+ {
+ c = get();
+ if(c == '\'')
+ {
+ break;
+ }
+ else
+ {
+ buf.append(c);
+ }
+ }
+ }
+ catch(EndOfInput e)
+ {
+ _parser.warning("EOF in string");
+ }
+ }
+ else if(c == '\"')
+ {
+ try
+ {
+ while(true)
+ {
+ c = get();
+ if(c == '\"')
+ {
+ break;
+ }
+ else if(c == '\\')
+ {
+ try
+ {
+ char next = get();
+ switch(next)
+ {
+ case '\\':
+ case '"':
+ {
+ buf.append(next);
+ break;
+ }
+
+ case 'n':
+ {
+ buf.append('\n');
+ break;
+ }
+
+ case 'r':
+ {
+ buf.append('\r');
+ break;
+ }
+
+ case 't':
+ {
+ buf.append('\t');
+ break;
+ }
+
+ case 'f':
+ {
+ buf.append('\f');
+ break;
+ }
+
+ default:
+ {
+ buf.append(c);
+ unget(next);
+ }
+ }
+ }
+ catch(EndOfInput e)
+ {
+ buf.append(c);
+ }
+ }
+ else
+ {
+ buf.append(c);
+ }
+ }
+ }
+ catch(EndOfInput e)
+ {
+ _parser.warning("EOF in string");
+ }
+ }
+ else
+ {
+ //
+ // Otherwise it's a string.
+ //
+ try
+ {
+ do
+ {
+ buf.append(c);
+ c = get();
+ }
+ while(!Character.isWhitespace(c) && c != ';' && c != '\n');
+
+ unget(c);
+ }
+ catch(EndOfInput ignore)
+ {
+ }
+ }
+
+ return buf.toString();
+ }
+
+ private Parser _parser;
+ private boolean _unget = false;
+ private char _ungetChar;
+ private String _buf = null;
+ private int _pos;
+}
diff --git a/java/demo/Database/library/Server.java b/java/demo/Database/library/Server.java
new file mode 100644
index 00000000000..0ba4f08d036
--- /dev/null
+++ b/java/demo/Database/library/Server.java
@@ -0,0 +1,130 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2008 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+import Demo.*;
+
+class LibraryServer extends Ice.Application
+{
+ static class BookLocator implements Ice.ServantLocator
+ {
+ BookLocator(Ice.Object servant)
+ {
+ _servant = servant;
+ }
+
+ public Ice.Object locate(Ice.Current c, Ice.LocalObjectHolder cookie)
+ {
+ return _servant;
+ }
+
+ public void finished(Ice.Current c, Ice.Object servant, Object cookie)
+ {
+ }
+
+ public void deactivate(String category)
+ {
+ }
+
+ private Ice.Object _servant;
+ }
+
+ public int
+ run(String[] args)
+ {
+ if(args.length > 0)
+ {
+ System.err.println(appName() + ": too many arguments");
+ return 1;
+ }
+
+ Ice.Properties properties = communicator().getProperties();
+
+ String username = properties.getProperty("JDBC.Username");
+ String password = properties.getProperty("JDBC.Password");
+ String url = properties.getProperty("JDBC.Url");
+ int nConnections = properties.getPropertyAsIntWithDefault("JDBC.NumConnections", 5);
+ if(nConnections < 1)
+ {
+ nConnections = 1;
+ }
+ ConnectionPool pool = null;
+ Ice.Logger logger = communicator().getLogger();
+
+ try
+ {
+ Class.forName ("com.mysql.jdbc.Driver").newInstance ();
+ }
+ catch(Exception e)
+ {
+ java.io.StringWriter sw = new java.io.StringWriter();
+ java.io.PrintWriter pw = new java.io.PrintWriter(sw);
+ e.printStackTrace(pw);
+ pw.flush();
+ System.err.println("failed to initialize mysql driver:\n" + sw.toString());
+ return 1;
+ }
+
+ try
+ {
+ pool = new ConnectionPool(logger, url, username, password, nConnections);
+ }
+ catch(java.sql.SQLException e)
+ {
+ java.io.StringWriter sw = new java.io.StringWriter();
+ java.io.PrintWriter pw = new java.io.PrintWriter(sw);
+ e.printStackTrace(pw);
+ pw.flush();
+ System.err.println("failed to create connection pool: SQLException:\n" + sw.toString());
+ return 1;
+ }
+
+ ReapThread reaper = new ReapThread(logger);
+ reaper.start();
+
+ //
+ // Create an object adapter
+ //
+ Ice.ObjectAdapter adapter = communicator().createObjectAdapter("SessionFactory");
+ adapter.add(new SessionFactoryI(logger, pool, reaper), communicator().stringToIdentity("SessionFactory"));
+ BookI book = new BookI(logger, pool);
+ adapter.addServantLocator(new BookLocator(book), "book");
+
+ //
+ // Everything ok, let's go.
+ //
+ adapter.activate();
+
+ shutdownOnInterrupt();
+ communicator().waitForShutdown();
+ defaultInterrupt();
+
+ reaper.terminate();
+ try
+ {
+ reaper.join();
+ }
+ catch(InterruptedException e)
+ {
+ }
+
+ pool.destroy();
+
+ return 0;
+ }
+}
+
+public class Server
+{
+ static public void
+ main(String[] args)
+ {
+ LibraryServer app = new LibraryServer();
+ app.main("demo.Database.library.Server", args, "config.server");
+ }
+}
diff --git a/java/demo/Database/library/SessionFactoryI.java b/java/demo/Database/library/SessionFactoryI.java
new file mode 100644
index 00000000000..677a92078f2
--- /dev/null
+++ b/java/demo/Database/library/SessionFactoryI.java
@@ -0,0 +1,34 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2008 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+import Demo.*;
+
+class SessionFactoryI extends _SessionFactoryDisp
+{
+ SessionFactoryI(Ice.Logger logger, ConnectionPool pool, ReapThread reaper)
+ {
+ _logger = logger;
+ _pool = pool;
+ _reaper = reaper;
+ }
+
+ public synchronized SessionPrx
+ create(Ice.Current c)
+ {
+ SessionI session = new SessionI(_pool, _logger, c.adapter);
+ SessionPrx proxy = SessionPrxHelper.uncheckedCast(c.adapter.addWithUUID(session));
+ _logger.trace("SessionFactory", "create new session: " + proxy.ice_getIdentity());
+ _reaper.add(proxy, session);
+ return proxy;
+ }
+
+ private Ice.Logger _logger;
+ private ConnectionPool _pool;
+ private ReapThread _reaper;
+}
diff --git a/java/demo/Database/library/SessionI.java b/java/demo/Database/library/SessionI.java
new file mode 100644
index 00000000000..610cb8e4201
--- /dev/null
+++ b/java/demo/Database/library/SessionI.java
@@ -0,0 +1,97 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2008 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+import Demo.*;
+
+class SessionI extends _SessionDisp
+{
+ public
+ SessionI(ConnectionPool pool, Ice.Logger logger, Ice.ObjectAdapter adapter)
+ {
+ _pool = pool;
+ _logger = logger;
+ _timestamp = System.currentTimeMillis();
+ _libraryImpl = new LibraryI(_logger, _pool);
+ _library = LibraryPrxHelper.uncheckedCast(adapter.addWithUUID(_libraryImpl));
+ }
+
+ synchronized public LibraryPrx
+ getLibrary(Ice.Current c)
+ {
+ if(_destroyed)
+ {
+ throw new Ice.ObjectNotExistException();
+ }
+ return _library;
+ }
+
+ synchronized public void
+ refresh(Ice.Current c)
+ {
+ if(_destroyed)
+ {
+ throw new Ice.ObjectNotExistException();
+ }
+ _timestamp = System.currentTimeMillis();
+ }
+
+ synchronized public void
+ destroy(Ice.Current c)
+ {
+ if(_destroyed)
+ {
+ throw new Ice.ObjectNotExistException();
+ }
+
+ _destroyed = true;
+ _logger.trace("Session", "The session " + c.id + " is now destroyed.");
+ _libraryImpl.destroy();
+ try
+ {
+ if(c != null)
+ {
+ c.adapter.remove(c.id);
+ c.adapter.remove(_library.ice_getIdentity());
+ }
+ }
+ catch(Ice.ObjectAdapterDeactivatedException e)
+ {
+ // This method is called on shutdown of the server, in
+ // which case this exception is expected.
+ }
+ }
+
+ // Called on application shutdown.
+ synchronized public void
+ shutdown()
+ {
+ if(!_destroyed)
+ {
+ _destroyed = true;
+ _libraryImpl.shutdown();
+ }
+ }
+
+ synchronized public long
+ timestamp()
+ {
+ if(_destroyed)
+ {
+ throw new Ice.ObjectNotExistException();
+ }
+ return _timestamp;
+ }
+
+ private Ice.Logger _logger;
+ private ConnectionPool _pool;
+ private boolean _destroyed = false; // true if destroy() was called, false otherwise.
+ private long _timestamp; // The last time the session was refreshed.
+ private LibraryPrx _library;
+ private LibraryI _libraryImpl;
+}
diff --git a/java/demo/Database/library/Token.java b/java/demo/Database/library/Token.java
new file mode 100644
index 00000000000..656630f40c9
--- /dev/null
+++ b/java/demo/Database/library/Token.java
@@ -0,0 +1,39 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2008 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+class Token
+{
+ public static final int TOK_HELP = 0;
+ public static final int TOK_EXIT = 1;
+ public static final int TOK_ADD_BOOK = 2;
+ public static final int TOK_FIND_ISBN = 3;
+ public static final int TOK_FIND_AUTHORS = 4;
+ public static final int TOK_NEXT_FOUND_BOOK = 5;
+ public static final int TOK_PRINT_CURRENT = 6;
+ public static final int TOK_RENT_BOOK = 7;
+ public static final int TOK_RETURN_BOOK = 8;
+ public static final int TOK_REMOVE_CURRENT = 9;
+ public static final int TOK_STRING = 12;
+ public static final int TOK_SEMI = 13;
+
+ int type;
+ String value;
+
+ Token(int t)
+ {
+ type = t;
+ value = null;
+ }
+
+ Token(int t, String v)
+ {
+ type = t;
+ value = v;
+ }
+}
diff --git a/java/demo/Database/library/books b/java/demo/Database/library/books
new file mode 100644
index 00000000000..18836dbdba6
--- /dev/null
+++ b/java/demo/Database/library/books
@@ -0,0 +1,30 @@
+add '096447963X' 'The Dragon Style (Learn to Play Go, Volume III)' 'Janice Kim, Jeong Soo-Hyun' ;
+add '0964479613' "Learn to Play Go: A Master's Guide to the Ultimate Game (Volume I)" 'Janice Kim, Jeong Soo-Hyun' ;
+add '0964479621' 'The Way of the Moving Horse (Learn to Play Go, Volume II)' 'Janice Kim, Jeong Soo-Hyun' ;
+add '0964479648' 'Battle Strategies (Learn to Play Go Series)' 'Janice Kim, Jeong Soo-Hyun' ;
+add '0201889544' 'The C++ Programming Language' 'Bjarne Stroustrup' ;
+add '0201543303' 'The Design and Evolution of C++' 'Bjarne Stroustrup' ;
+add '0201700735' 'The C++ Programming Language Special Edition' 'Bjarne Stroustrup' ;
+add '0201379260' 'The C++ Standard Library : A Tutorial and Reference' 'Nicolai M. Josuttis' ;
+add '0201749629' 'Effective STL: 50 Specific Ways to Improve Your Use of the Standard Template Library' 'Scott Meyers' ;
+add '0201924889' 'Effective C++: 50 Specific Ways to Improve Your Programs and Design' 'Scott Meyers' ;
+add '020163371X' 'More Effective C++: 35 New Ways to Improve Your Programs and Designs' 'Scott Meyers' ;
+add '0201615622' 'Exceptional C++: 47 Engineering Puzzles, Programming Problems, and Solutions' 'Herb Sutter' ;
+add '020170434X' 'More Exceptional C++' 'Herb Sutter' ;
+add '0201704315' 'Modern C++ Design: Generic Programming and Design Patterns Applied' 'Andrei Alexandrescu' ;
+add '0735616353' 'Microsoft Visual C++ .NET Deluxe Learning Edition' 'Microsoft Corporation' ;
+add '0735615497' 'Programming with Microsoft Visual C++ .NET, Sixth Edition (Core Reference)' 'George Shepherd, David Kruglinski' ;
+add '0735614229' 'Applied Microsoft .NET Framework Programming' 'Jeffrey Richter' ;
+add '0201824701' 'C++ Primer' 'Stanley B. Lippman, Josee Lajoie' ;
+add '0201485184' 'Essential C++' 'Stanley B. Lippman' ;
+add '020170353X' 'Accelerated C++: Practical Programming by Example' 'Andrew Koenig, Barbara E. Moo' ;
+add '0201423391' 'Ruminations on C++ : A Decade of Programming Insight and Experience' 'Andrew Koenig, Barbara E. Moo' ;
+add '0201179288' 'C Traps and Pitfalls' 'Andrew Koenig' ;
+add '0131103628' 'The C Programming Language' 'Brian W. Kernighan, Dennis M. Ritchie' ;
+add '020161586X' 'The Practice of Programming' 'Brian W. Kernighan, Rob Pike' ;
+add '013937681X' 'UNIX Programming Environment, The' 'Brian W. Kernighan, Rob Pike' ;
+add '0201563177' 'Advanced Programming in the UNIX(R) Environment' 'W. Richard Stevens' ;
+add '0201633469' 'The Protocols (TCP/IP Illustrated, Volume 1)' 'W. Richard Stevens' ;
+add '0201634953' 'TCP for Transactions, HTTP, NNTP, and the UNIX(R) Domain Protocols (TCP/IP Illustrated, Volume 3)' 'W. Richard Stevens' ;
+add '013490012X' 'UNIX Network Programming, Volume 1: Networking APIs - Sockets and XTI' 'W. Richard Stevens' ;
+add '0130810819' 'UNIX Network Programming: Interprocess Communications' 'W. Richard Stevens' ;
diff --git a/java/demo/Database/library/build.xml b/java/demo/Database/library/build.xml
new file mode 100644
index 00000000000..cd874693901
--- /dev/null
+++ b/java/demo/Database/library/build.xml
@@ -0,0 +1,64 @@
+<!--
+ **********************************************************************
+
+ Copyright (c) 2003-2008 ZeroC, Inc. All rights reserved.
+
+ This copy of Ice is licensed to you under the terms described in the
+ ICE_LICENSE file included in this distribution.
+
+ **********************************************************************
+-->
+
+<project name="demo_Freeze_library" default="all" basedir=".">
+
+ <!-- set global properties for this build -->
+ <property name="top.dir" value="../../.."/>
+
+ <!-- import common definitions -->
+ <import file="${top.dir}/config/common.xml"/>
+
+ <target name="generate" depends="init">
+ <!-- Create the output directory for generated code -->
+ <mkdir dir="${generated.dir}"/>
+ <slice2java outputdir="${generated.dir}">
+ <meta value="${java2metadata}"/>
+ <includepath>
+ <pathelement path="${slice.dir}" />
+ </includepath>
+ <fileset dir="." includes="Library.ice"/>
+ </slice2java>
+ <slice2freezej ice="on" outputdir="${generated.dir}">
+ <meta value="${java2metadata}"/>
+ <includepath>
+ <pathelement path="${slice.dir}" />
+ </includepath>
+ <fileset dir="${slice.dir}/Ice">
+ <include name="BuiltinSequences.ice" />
+ </fileset>
+ <fileset dir="." includes="Library.ice"/>
+ <dict name="StringIsbnSeqDict" key="string" value="Ice::StringSeq"/>
+ </slice2freezej>
+ </target>
+
+ <target name="compile" depends="generate">
+ <mkdir dir="${class.dir}"/>
+ <javac srcdir="${generated.dir}" destdir="${class.dir}"
+ debug="${debug}">
+ <classpath refid="ice.classpath"/>
+ <compilerarg value="${javac.lint}"/>
+ </javac>
+ <javac srcdir="." destdir="${class.dir}"
+ excludes="generated/**" debug="${debug}">
+ <classpath refid="ice.classpath"/>
+ <compilerarg value="${javac.lint}"/>
+ </javac>
+ </target>
+
+ <target name="all" depends="compile"/>
+
+ <target name="clean">
+ <delete dir="${generated.dir}"/>
+ <delete dir="${class.dir}"/>
+ </target>
+
+</project>
diff --git a/java/demo/Database/library/config.client b/java/demo/Database/library/config.client
new file mode 100644
index 00000000000..93ae62d757e
--- /dev/null
+++ b/java/demo/Database/library/config.client
@@ -0,0 +1,28 @@
+#
+# The client reads this property to create the reference to the
+# "SessionFactory" object in the server.
+#
+SessionFactory.Proxy=SessionFactory:default -p 10000
+
+#
+# Warn about connection exceptions
+#
+Ice.Warn.Connections=1
+
+#
+# Network Tracing
+#
+# 0 = no network tracing
+# 1 = trace connection establishment and closure
+# 2 = like 1, but more detailed
+# 3 = like 2, but also trace data transfer
+#
+#Ice.Trace.Network=1
+
+#
+# Protocol Tracing
+#
+# 0 = no protocol tracing
+# 1 = trace protocol messages
+#
+#Ice.Trace.Protocol=1
diff --git a/java/demo/Database/library/config.server b/java/demo/Database/library/config.server
new file mode 100644
index 00000000000..4cbefb70ffc
--- /dev/null
+++ b/java/demo/Database/library/config.server
@@ -0,0 +1,40 @@
+#
+# Configure the server endpoints.
+#
+SessionFactory.Endpoints=default -p 10000
+
+# JDBC configuration.
+JDBC.Username=matthew
+JDBC.Password=foo
+JDBC.Url=jdbc:mysql://localhost/library
+
+# The number of connections in the JDBC connection pool. This number
+# should be at least as big as the number of the threads in the server
+# thread pool.
+JDBC.NumConnections=5
+
+# Number of threads in the server-side dispatch thread pool.
+Ice.ThreadPool.Server.Size=1
+
+#
+# Warn about connection exceptions
+#
+Ice.Warn.Connections=1
+
+#
+# Network Tracing
+#
+# 0 = no network tracing
+# 1 = trace connection establishment and closure
+# 2 = like 1, but more detailed
+# 3 = like 2, but also trace data transfer
+#
+#Ice.Trace.Network=1
+
+#
+# Protocol Tracing
+#
+# 0 = no protocol tracing
+# 1 = trace protocol messages
+#
+#Ice.Trace.Protocol=1
diff --git a/java/demo/Database/library/createTypes.sql b/java/demo/Database/library/createTypes.sql
new file mode 100644
index 00000000000..cd07546b83f
--- /dev/null
+++ b/java/demo/Database/library/createTypes.sql
@@ -0,0 +1,43 @@
+# **********************************************************************
+#
+# Copyright (c) 2003-2008 ZeroC, Inc. All rights reserved.
+#
+# This copy of Ice is licensed to you under the terms described in the
+# ICE_LICENSE file included in this distribution.
+#
+# **********************************************************************
+#
+# Initialize SQL tables.
+#
+DROP TABLE IF EXISTS books;
+CREATE TABLE books
+(
+ id INT UNSIGNED AUTO_INCREMENT NOT NULL,
+ PRIMARY KEY (id),
+ isbn CHAR(10),
+ title VARCHAR(255),
+ renter_id INT
+);
+
+DROP TABLE IF EXISTS authors_books;
+CREATE TABLE authors_books
+(
+ book_id INT,
+ author_id INT
+);
+
+DROP TABLE IF EXISTS authors;
+CREATE TABLE authors
+(
+ id INT UNSIGNED NOT NULL AUTO_INCREMENT,
+ PRIMARY KEY(id),
+ name VARCHAR(255)
+);
+
+DROP TABLE IF EXISTS customers;
+CREATE TABLE customers
+(
+ id INT UNSIGNED NOT NULL AUTO_INCREMENT,
+ PRIMARY KEY(id),
+ name VARCHAR(255)
+);