summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--cpp/demo/book/evictor_filesystem/PersistentFilesystemI.cpp2
-rw-r--r--cpp/demo/book/evictor_filesystem/README2
-rw-r--r--cpp/demo/book/map_filesystem/FilesystemI.cpp68
-rw-r--r--cpp/demo/book/map_filesystem/FilesystemI.h4
-rw-r--r--cpp/demo/book/map_filesystem/README2
-rw-r--r--cpp/demo/book/map_filesystem/Server.cpp4
-rwxr-xr-xjava/allDemos.py3
-rw-r--r--java/demo/book/README13
-rw-r--r--java/demo/book/build.xml7
-rw-r--r--java/demo/book/evictor_filesystem/.gitignore (renamed from java/demo/book/freeze_filesystem/.gitignore)0
-rw-r--r--java/demo/book/evictor_filesystem/Client.java56
-rw-r--r--java/demo/book/evictor_filesystem/DirectoryI.java (renamed from java/demo/book/freeze_filesystem/DirectoryI.java)7
-rw-r--r--java/demo/book/evictor_filesystem/FileI.java (renamed from java/demo/book/freeze_filesystem/FileI.java)0
-rw-r--r--java/demo/book/evictor_filesystem/Filesystem.ice (renamed from java/demo/book/freeze_filesystem/Filesystem.ice)0
-rw-r--r--java/demo/book/evictor_filesystem/Grammar.java202
-rw-r--r--java/demo/book/evictor_filesystem/NodeFactory.java (renamed from java/demo/book/freeze_filesystem/NodeFactory.java)0
-rw-r--r--java/demo/book/evictor_filesystem/NodeInitializer.java (renamed from java/demo/book/freeze_filesystem/NodeInitializer.java)0
-rw-r--r--java/demo/book/evictor_filesystem/Parser.java361
-rw-r--r--java/demo/book/evictor_filesystem/PersistentFilesystem.ice (renamed from java/demo/book/freeze_filesystem/PersistentFilesystem.ice)0
-rw-r--r--java/demo/book/evictor_filesystem/README13
-rw-r--r--java/demo/book/evictor_filesystem/Scanner.java283
-rw-r--r--java/demo/book/evictor_filesystem/Server.java (renamed from java/demo/book/freeze_filesystem/Server.java)0
-rw-r--r--java/demo/book/evictor_filesystem/Token.java40
-rw-r--r--java/demo/book/evictor_filesystem/build.xml (renamed from java/demo/book/freeze_filesystem/build.xml)2
-rw-r--r--java/demo/book/evictor_filesystem/config.client (renamed from java/demo/book/freeze_filesystem/config.client)0
-rw-r--r--java/demo/book/evictor_filesystem/config.server (renamed from java/demo/book/freeze_filesystem/config.server)0
-rw-r--r--java/demo/book/evictor_filesystem/db/.gitignore (renamed from java/demo/book/freeze_filesystem/db/.gitignore)0
-rwxr-xr-xjava/demo/book/evictor_filesystem/expect.py38
-rw-r--r--java/demo/book/freeze_filesystem/Client.java164
-rw-r--r--java/demo/book/freeze_filesystem/README10
-rw-r--r--java/demo/book/map_filesystem/.gitignore1
-rw-r--r--java/demo/book/map_filesystem/Client.java56
-rw-r--r--java/demo/book/map_filesystem/Filesystem.ice69
-rw-r--r--java/demo/book/map_filesystem/FilesystemI/DirectoryI.java332
-rw-r--r--java/demo/book/map_filesystem/FilesystemI/FileI.java102
-rw-r--r--java/demo/book/map_filesystem/FilesystemI/NodeI.java16
-rw-r--r--java/demo/book/map_filesystem/Grammar.java202
-rw-r--r--java/demo/book/map_filesystem/Parser.java361
-rw-r--r--java/demo/book/map_filesystem/README13
-rw-r--r--java/demo/book/map_filesystem/Scanner.java283
-rw-r--r--java/demo/book/map_filesystem/Server.java87
-rw-r--r--java/demo/book/map_filesystem/Token.java40
-rw-r--r--java/demo/book/map_filesystem/build.xml65
-rw-r--r--java/demo/book/map_filesystem/config.client28
-rw-r--r--java/demo/book/map_filesystem/config.server49
-rw-r--r--java/demo/book/map_filesystem/db/.gitignore1
-rwxr-xr-xjava/demo/book/map_filesystem/expect.py (renamed from java/demo/book/freeze_filesystem/expect.py)4
47 files changed, 2766 insertions, 224 deletions
diff --git a/cpp/demo/book/evictor_filesystem/PersistentFilesystemI.cpp b/cpp/demo/book/evictor_filesystem/PersistentFilesystemI.cpp
index 7dcda47a6b8..cc143cbb346 100644
--- a/cpp/demo/book/evictor_filesystem/PersistentFilesystemI.cpp
+++ b/cpp/demo/book/evictor_filesystem/PersistentFilesystemI.cpp
@@ -88,7 +88,7 @@ Filesystem::DirectoryI::destroy(const Ice::Current& c)
{
if(!parent)
{
- throw Filesystem::PermissionDenied("cannot destroy root directory");
+ throw Filesystem::PermissionDenied("Cannot destroy root directory");
}
NodeDict children;
diff --git a/cpp/demo/book/evictor_filesystem/README b/cpp/demo/book/evictor_filesystem/README
index 9f719fc6211..f6abb864764 100644
--- a/cpp/demo/book/evictor_filesystem/README
+++ b/cpp/demo/book/evictor_filesystem/README
@@ -9,3 +9,5 @@ $ server
Then run the client in a separate window:
$ client
+
+Type "help" at the client prompt to see a list of commands.
diff --git a/cpp/demo/book/map_filesystem/FilesystemI.cpp b/cpp/demo/book/map_filesystem/FilesystemI.cpp
index 77f46fe519e..6cf7f3dd386 100644
--- a/cpp/demo/book/map_filesystem/FilesystemI.cpp
+++ b/cpp/demo/book/map_filesystem/FilesystemI.cpp
@@ -140,9 +140,9 @@ FilesystemI::FileI::destroy(const Current& c)
// FileI constructor
-FilesystemI::FileI::FileI(const CommunicatorPtr& communicator, const Identity& id,
+FilesystemI::FileI::FileI(const ObjectAdapterPtr& adapter, const Identity& id,
const PersistentFilePtr& file, const DirectoryIPtr& parent) :
- NodeI(communicator, id, parent), _file(file)
+ NodeI(adapter->getCommunicator(), id, parent), _file(file)
{
}
@@ -204,10 +204,10 @@ FilesystemI::DirectoryI::find(const std::string& name, const Current& c)
return i->second;
}
-// Slice Directory::createDirectory() operation
+// Slice Directory::createFile() operation
-DirectoryPrx
-FilesystemI::DirectoryI::createDirectory(const std::string& name, const Current& c)
+FilePrx
+FilesystemI::DirectoryI::createFile(const std::string& name, const Current& c)
{
{
IceUtil::Mutex::Lock lock(_m);
@@ -227,32 +227,32 @@ FilesystemI::DirectoryI::createDirectory(const std::string& name, const Current&
throw NameInUse(name);
}
- PersistentDirectoryPtr persistentDir = new PersistentDirectory;
- persistentDir->name = name;
+ PersistentFilePtr persistentFile = new PersistentFile;
+ persistentFile->name = name;
CommunicatorPtr communicator = c.adapter->getCommunicator();
- DirectoryIPtr dir = new DirectoryI(communicator, communicator->stringToIdentity(IceUtil::generateUUID()),
- persistentDir, this);
- assert(findNode(dir->_id) == 0);
- _map.put(IdentityNodeMap::value_type(dir->_id, persistentDir));
+ FileIPtr file = new FileI(c.adapter, communicator->stringToIdentity(IceUtil::generateUUID()),
+ persistentFile, this);
+ assert(findNode(file->id()) == 0);
+ _map.put(IdentityNodeMap::value_type(file->id(), persistentFile));
- DirectoryPrx proxy = DirectoryPrx::uncheckedCast(c.adapter->createProxy(dir->_id));
+ FilePrx proxy = FilePrx::uncheckedCast(c.adapter->createProxy(file->id()));
NodeDesc nd;
nd.name = name;
- nd.type = DirType;
+ nd.type = FileType;
nd.proxy = proxy;
_dir->nodes[name] = nd;
_map.put(IdentityNodeMap::value_type(_id, _dir));
- dir->activate(c.adapter);
+ file->activate(c.adapter);
return proxy;
}
-// Slice Directory::createFile() operation
+// Slice Directory::createDirectory() operation
-FilePrx
-FilesystemI::DirectoryI::createFile(const std::string& name, const Current& c)
+DirectoryPrx
+FilesystemI::DirectoryI::createDirectory(const std::string& name, const Current& c)
{
{
IceUtil::Mutex::Lock lock(_m);
@@ -265,31 +265,31 @@ FilesystemI::DirectoryI::createFile(const std::string& name, const Current& c)
IceUtil::StaticMutex::Lock lock(_lcMutex);
+ reap();
+
if(name.empty() || _dir->nodes.find(name) != _dir->nodes.end())
{
throw NameInUse(name);
}
- reap();
-
- PersistentFilePtr persistentFile = new PersistentFile;
- persistentFile->name = name;
+ PersistentDirectoryPtr persistentDir = new PersistentDirectory;
+ persistentDir->name = name;
CommunicatorPtr communicator = c.adapter->getCommunicator();
- FileIPtr file = new FileI(communicator, communicator->stringToIdentity(IceUtil::generateUUID()),
- persistentFile, this);
- assert(findNode(file->id()) == 0);
- _map.put(IdentityNodeMap::value_type(file->id(), persistentFile));
+ DirectoryIPtr dir = new DirectoryI(c.adapter, communicator->stringToIdentity(IceUtil::generateUUID()),
+ persistentDir, this);
+ assert(findNode(dir->_id) == 0);
+ _map.put(IdentityNodeMap::value_type(dir->_id, persistentDir));
- FilePrx proxy = FilePrx::uncheckedCast(c.adapter->createProxy(file->id()));
+ DirectoryPrx proxy = DirectoryPrx::uncheckedCast(c.adapter->createProxy(dir->_id));
NodeDesc nd;
nd.name = name;
- nd.type = FileType;
+ nd.type = DirType;
nd.proxy = proxy;
_dir->nodes[name] = nd;
_map.put(IdentityNodeMap::value_type(_id, _dir));
- file->activate(c.adapter);
+ dir->activate(c.adapter);
return proxy;
}
@@ -301,7 +301,7 @@ FilesystemI::DirectoryI::destroy(const Current& c)
{
if(!_parent)
{
- throw Filesystem::PermissionDenied("cannot destroy root directory");
+ throw Filesystem::PermissionDenied("Cannot destroy root directory");
}
IceUtil::Mutex::Lock lock(_m);
@@ -328,9 +328,9 @@ FilesystemI::DirectoryI::destroy(const Current& c)
// DirectoryI constructor
-FilesystemI::DirectoryI::DirectoryI(const CommunicatorPtr& communicator, const Identity& id,
+FilesystemI::DirectoryI::DirectoryI(const ObjectAdapterPtr& adapter, const Identity& id,
const PersistentDirectoryPtr& dir, const DirectoryIPtr& parent)
- : NodeI(communicator, id, parent), _dir(dir)
+ : NodeI(adapter->getCommunicator(), id, parent), _dir(dir)
{
//
// Instantiate the child nodes
@@ -341,20 +341,22 @@ FilesystemI::DirectoryI::DirectoryI(const CommunicatorPtr& communicator, const I
{
Identity id = p->second.proxy->ice_getIdentity();
PersistentNodePtr node = findNode(id);
+ NodeIPtr servant;
if(node)
{
if(p->second.type == DirType)
{
PersistentDirectoryPtr pDir = PersistentDirectoryPtr::dynamicCast(node);
assert(pDir);
- DirectoryIPtr d = new DirectoryI(communicator, id, pDir, this);
+ servant = new DirectoryI(adapter, id, pDir, this);
}
else
{
PersistentFilePtr pFile = PersistentFilePtr::dynamicCast(node);
assert(pFile);
- FileIPtr f = new FileI(communicator, id, pFile, this);
+ servant = new FileI(adapter, id, pFile, this);
}
+ servant->activate(adapter);
}
else
{
diff --git a/cpp/demo/book/map_filesystem/FilesystemI.h b/cpp/demo/book/map_filesystem/FilesystemI.h
index 83a8a0c087e..afca6869313 100644
--- a/cpp/demo/book/map_filesystem/FilesystemI.h
+++ b/cpp/demo/book/map_filesystem/FilesystemI.h
@@ -56,7 +56,7 @@ public:
virtual void write(const Filesystem::Lines&, const Ice::Current&);
virtual void destroy(const Ice::Current&);
- FileI(const Ice::CommunicatorPtr&, const Ice::Identity&,
+ FileI(const Ice::ObjectAdapterPtr&, const Ice::Identity&,
const Filesystem::PersistentFilePtr&, const DirectoryIPtr&);
private:
@@ -78,7 +78,7 @@ public:
virtual Filesystem::DirectoryPrx createDirectory(const ::std::string&, const Ice::Current&);
virtual void destroy(const Ice::Current&);
- DirectoryI(const Ice::CommunicatorPtr&, const Ice::Identity&,
+ DirectoryI(const Ice::ObjectAdapterPtr&, const Ice::Identity&,
const Filesystem::PersistentDirectoryPtr&, const DirectoryIPtr&);
void addReapEntry(const std::string&);
diff --git a/cpp/demo/book/map_filesystem/README b/cpp/demo/book/map_filesystem/README
index 370331ef723..bb7408ec72e 100644
--- a/cpp/demo/book/map_filesystem/README
+++ b/cpp/demo/book/map_filesystem/README
@@ -9,3 +9,5 @@ $ server
Then run the client in a separate window:
$ client
+
+Type "help" at the client prompt to see a list of commands.
diff --git a/cpp/demo/book/map_filesystem/Server.cpp b/cpp/demo/book/map_filesystem/Server.cpp
index 03025e77d52..d2a35b13003 100644
--- a/cpp/demo/book/map_filesystem/Server.cpp
+++ b/cpp/demo/book/map_filesystem/Server.cpp
@@ -27,7 +27,7 @@ public:
virtual int run(int, char*[])
{
//
- // Terminate cleanly on receipt of a signal
+ // Terminate cleanly on receipt of a signal.
//
shutdownOnInterrupt();
@@ -70,7 +70,7 @@ public:
pRoot->name = "/";
persistentMap.insert(IdentityNodeMap::value_type(rootId, pRoot));
}
- DirectoryIPtr dir = new DirectoryI(communicator(), rootId, pRoot, 0);
+ DirectoryIPtr dir = new DirectoryI(adapter, rootId, pRoot, 0);
dir->activate(adapter);
}
diff --git a/java/allDemos.py b/java/allDemos.py
index fbe050a51c4..ff6722e2a41 100755
--- a/java/allDemos.py
+++ b/java/allDemos.py
@@ -46,7 +46,8 @@ demos = [
"Freeze/library",
"Freeze/transform",
"Freeze/casino",
- "book/freeze_filesystem",
+ "book/map_filesystem",
+ "book/evictor_filesystem",
"book/simple_filesystem",
"book/printer",
"book/lifecycle",
diff --git a/java/demo/book/README b/java/demo/book/README
index bbace203f6d..5876d2c345e 100644
--- a/java/demo/book/README
+++ b/java/demo/book/README
@@ -3,8 +3,8 @@ Demos in this directory:
- evictor
This is the source code for the evictor implementation described in
- the Ice Run Time chapter. You can copy and modify this code to
- suit your needs.
+ the Ice Run Time chapter. You can copy and modify this code to suit
+ your needs.
- printer
@@ -20,7 +20,12 @@ Demos in this directory:
An implementation of the file system that supports life cycle operations.
-- freeze_filesystem
+- map_filesystem
An implementation of the persistent version of the file system
- example described in the Freeze chapter.
+ based on Freeze maps as described in the Freeze chapter.
+
+- evictor_filesystem
+
+ An implementation of the persistent version of the file system
+ based on a background-save evictor as described in the Freeze chapter.
diff --git a/java/demo/book/build.xml b/java/demo/book/build.xml
index aa71c1ae517..e44df524923 100644
--- a/java/demo/book/build.xml
+++ b/java/demo/book/build.xml
@@ -14,7 +14,8 @@
<target name="all">
<ant dir="printer"/>
<ant dir="simple_filesystem"/>
- <ant dir="freeze_filesystem"/>
+ <ant dir="map_filesystem"/>
+ <ant dir="evictor_filesystem"/>
<ant dir="lifecycle"/>
</target>
@@ -22,8 +23,8 @@
<ant dir="printer" target="clean"/>
<ant dir="simple_filesystem" target="clean"/>
<ant dir="lifecycle" target="clean"/>
- <ant dir="freeze_filesystem" target="clean"/>
- <ant dir="lifecycle" target="clean"/>
+ <ant dir="map_filesystem" target="clean"/>
+ <ant dir="evictor_filesystem" target="clean"/>
</target>
</project>
diff --git a/java/demo/book/freeze_filesystem/.gitignore b/java/demo/book/evictor_filesystem/.gitignore
index 9c39416c539..9c39416c539 100644
--- a/java/demo/book/freeze_filesystem/.gitignore
+++ b/java/demo/book/evictor_filesystem/.gitignore
diff --git a/java/demo/book/evictor_filesystem/Client.java b/java/demo/book/evictor_filesystem/Client.java
new file mode 100644
index 00000000000..8599d43e81d
--- /dev/null
+++ b/java/demo/book/evictor_filesystem/Client.java
@@ -0,0 +1,56 @@
+// **********************************************************************
+//
+// 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 Filesystem.*;
+
+public class Client extends Ice.Application
+{
+ public int
+ run(String[] args)
+ {
+ // Terminate cleanly on receipt of a signal.
+ //
+ shutdownOnInterrupt();
+
+ // Create a proxy for the root directory
+ //
+ Ice.ObjectPrx base = communicator().stringToProxy("RootDir:default -p 10000");
+ if(base == null)
+ {
+ throw new Error("Could not create proxy");
+ }
+
+ // Down-cast the proxy to a Directory proxy.
+ //
+ DirectoryPrx rootDir = DirectoryPrxHelper.checkedCast(base);
+ if(rootDir == null)
+ {
+ throw new Error("Invalid proxy");
+ }
+
+ Parser p = new Parser(rootDir);
+ return p.parse();
+ }
+
+ static public void
+ main(String[] args)
+ {
+ Client app = new Client();
+ app.main("demo.book.lifecycle.Client", args);
+ }
+
+ static private class Error extends RuntimeException
+ {
+ public Error(String msg)
+ {
+ super(msg);
+ }
+ }
+
+}
diff --git a/java/demo/book/freeze_filesystem/DirectoryI.java b/java/demo/book/evictor_filesystem/DirectoryI.java
index d8fe5a312a9..5da25ce6b0c 100644
--- a/java/demo/book/freeze_filesystem/DirectoryI.java
+++ b/java/demo/book/evictor_filesystem/DirectoryI.java
@@ -42,7 +42,7 @@ public final class DirectoryI extends PersistentDirectory
{
if(parent == null)
{
- throw new PermissionDenied("cannot remove root directory");
+ throw new PermissionDenied("Cannot remove root directory");
}
java.util.Map children = null;
@@ -54,6 +54,11 @@ public final class DirectoryI extends PersistentDirectory
throw new Ice.ObjectNotExistException(current.id, current.facet, current.operation);
}
+ if(!nodes.isEmpty())
+ {
+ throw new PermissionDenied("Cannot destroy non-empty directory");
+ }
+
children = (java.util.Map)((java.util.HashMap)nodes).clone();
_destroyed = true;
}
diff --git a/java/demo/book/freeze_filesystem/FileI.java b/java/demo/book/evictor_filesystem/FileI.java
index 09db1e60320..09db1e60320 100644
--- a/java/demo/book/freeze_filesystem/FileI.java
+++ b/java/demo/book/evictor_filesystem/FileI.java
diff --git a/java/demo/book/freeze_filesystem/Filesystem.ice b/java/demo/book/evictor_filesystem/Filesystem.ice
index b8b5b38d351..b8b5b38d351 100644
--- a/java/demo/book/freeze_filesystem/Filesystem.ice
+++ b/java/demo/book/evictor_filesystem/Filesystem.ice
diff --git a/java/demo/book/evictor_filesystem/Grammar.java b/java/demo/book/evictor_filesystem/Grammar.java
new file mode 100644
index 00000000000..92da79a56d0
--- /dev/null
+++ b/java/demo/book/evictor_filesystem/Grammar.java
@@ -0,0 +1,202 @@
+// **********************************************************************
+//
+// 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_LIST)
+ {
+ _token = _scanner.nextToken();
+ if(_token.type != Token.TOK_SEMI)
+ {
+ throw new ParseError("Expected ';'");
+ }
+ _parser.list(false);
+ }
+ else if(_token.type == Token.TOK_LIST_RECURSIVE)
+ {
+ _token = _scanner.nextToken();
+ if(_token.type != Token.TOK_SEMI)
+ {
+ throw new ParseError("Expected ';'");
+ }
+ _parser.list(true);
+ }
+ else if(_token.type == Token.TOK_CREATE_FILE)
+ {
+ java.util.List<String> s = strings();
+ if(_token.type != Token.TOK_SEMI)
+ {
+ throw new ParseError("Expected ';'");
+ }
+ if(s.size() == 0)
+ {
+ throw new ParseError("usage: mkfile FILE [FILE...]");
+ }
+ _parser.createFile(s);
+ }
+ else if(_token.type == Token.TOK_CREATE_DIR)
+ {
+ java.util.List<String> s = strings();
+ if(_token.type != Token.TOK_SEMI)
+ {
+ throw new ParseError("Expected ';'");
+ }
+ if(s.size() == 0)
+ {
+ throw new ParseError("usage: mkdir DIR [DIR...]");
+ }
+ _parser.createDir(s);
+ }
+ else if(_token.type == Token.TOK_PWD)
+ {
+ _token = _scanner.nextToken();
+ if(_token.type != Token.TOK_SEMI)
+ {
+ throw new ParseError("Expected ';'");
+ }
+ _parser.pwd();
+ }
+ else if(_token.type == Token.TOK_CD)
+ {
+ java.util.List<String> s = strings();
+ if(_token.type != Token.TOK_SEMI)
+ {
+ throw new ParseError("Expected ';'");
+ }
+ if(s.size() > 1)
+ {
+ throw new ParseError("usage: cd [DIR]");
+ }
+ else if(s.size() == 0)
+ {
+ _parser.cd("/");
+ }
+ else
+ {
+ _parser.cd((String)s.get(0));
+ }
+ }
+ else if(_token.type == Token.TOK_CAT)
+ {
+ java.util.List<String> s = strings();
+ if(_token.type != Token.TOK_SEMI)
+ {
+ throw new ParseError("Expected ';'");
+ }
+ if(s.size() != 1)
+ {
+ throw new ParseError("usage: cat FILE");
+ }
+ _parser.cat((String)s.get(0));
+ }
+ else if(_token.type == Token.TOK_WRITE)
+ {
+ java.util.LinkedList<String> s = strings();
+ if(_token.type != Token.TOK_SEMI)
+ {
+ throw new ParseError("Expected ';'");
+ }
+ if(s.size() == 0)
+ {
+ throw new ParseError("usage: write FILE [STRING...]");
+ }
+ _parser.write(s);
+ }
+ else if(_token.type == Token.TOK_RM)
+ {
+ java.util.List<String> s = strings();
+ if(_token.type != Token.TOK_SEMI)
+ {
+ throw new ParseError("Expected ';'");
+ }
+ if(s.size() == 0)
+ {
+ throw new ParseError("usage: rm NAME [NAME...]");
+ }
+ _parser.destroy(s);
+ }
+ else
+ {
+ _parser.error("parse error");
+ }
+ }
+ catch(ParseError e)
+ {
+ _parser.error("Parse error: " + e.getMessage());
+ }
+ }
+ }
+
+ private java.util.LinkedList<String>
+ strings()
+ {
+ java.util.LinkedList<String> l = new java.util.LinkedList<String>();
+ 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/book/freeze_filesystem/NodeFactory.java b/java/demo/book/evictor_filesystem/NodeFactory.java
index 74982387cac..74982387cac 100644
--- a/java/demo/book/freeze_filesystem/NodeFactory.java
+++ b/java/demo/book/evictor_filesystem/NodeFactory.java
diff --git a/java/demo/book/freeze_filesystem/NodeInitializer.java b/java/demo/book/evictor_filesystem/NodeInitializer.java
index b1304afd16e..b1304afd16e 100644
--- a/java/demo/book/freeze_filesystem/NodeInitializer.java
+++ b/java/demo/book/evictor_filesystem/NodeInitializer.java
diff --git a/java/demo/book/evictor_filesystem/Parser.java b/java/demo/book/evictor_filesystem/Parser.java
new file mode 100644
index 00000000000..94e4af53654
--- /dev/null
+++ b/java/demo/book/evictor_filesystem/Parser.java
@@ -0,0 +1,361 @@
+// **********************************************************************
+//
+// 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 Filesystem.*;
+
+class Parser
+{
+ Parser(DirectoryPrx root)
+ {
+ _dirs = new java.util.LinkedList<DirectoryPrx>();
+ _dirs.addFirst(root);
+ }
+
+ void
+ usage()
+ {
+ System.err.print(
+ "help Print this message.\n" +
+ "pwd Print current directory (/ = root).\n" +
+ "cd [DIR] Change directory (/ or empty = root).\n" +
+ "ls List current directory.\n" +
+ "lr Recursively list current directory.\n" +
+ "mkdir DIR [DIR...] Create directories DIR in current directory.\n" +
+ "mkfile FILE [FILE...] Create files FILE in current directory.\n" +
+ "rm NAME [NAME...] Delete directory or file NAME (rm * to delete all).\n" +
+ "cat FILE List the contents of FILE.\n" +
+ "write FILE [STRING...] Write STRING to FILE.\n" +
+ "exit, quit Exit this program.\n");
+ }
+
+ void
+ list(boolean recursive)
+ {
+ try
+ {
+ list(_dirs.get(0), recursive, 0);
+ }
+ catch(Ice.LocalException ex)
+ {
+ error(ex.toString());
+ }
+ }
+
+ void
+ list(Filesystem.DirectoryPrx dir, boolean recursive, int depth)
+ {
+ StringBuffer b = new StringBuffer();
+ for(int i = 0; i < depth; ++i)
+ {
+ b.append('\t');
+ }
+ String indent = b.toString();
+
+ NodeDesc[] contents = dir.list();
+
+ for(int i = 0; i < contents.length; ++i)
+ {
+ DirectoryPrx d
+ = contents[i].type == NodeType.DirType
+ ? DirectoryPrxHelper.uncheckedCast(contents[i].proxy)
+ : null;
+ System.out.print(indent + contents[i].name + (d != null ? " (directory)" : " (file)"));
+ if(d != null && recursive)
+ {
+ System.out.println(":");
+ list(d, true, ++depth);
+ }
+ else
+ {
+ System.out.println();
+ }
+ }
+ }
+
+ void
+ createFile(java.util.List<String> names)
+ {
+ DirectoryPrx dir = _dirs.getFirst();
+
+ java.util.Iterator<String> i = names.iterator();
+ while(i.hasNext())
+ {
+ String name = i.next();
+ if(name.equals(".."))
+ {
+ System.out.println("Cannot create a file named `..'");
+ continue;
+ }
+
+ try
+ {
+ dir.createFile(name);
+ }
+ catch(NameInUse ex)
+ {
+ System.out.println("`" + name + "' exists already");
+ }
+ }
+ }
+
+ void
+ createDir(java.util.List<String> names)
+ {
+ DirectoryPrx dir = _dirs.getFirst();
+
+ java.util.Iterator<String> i = names.iterator();
+ while(i.hasNext())
+ {
+ String name = i.next();
+ if(name.equals(".."))
+ {
+ System.out.println("Cannot create a directory named `..'");
+ continue;
+ }
+
+ try
+ {
+ dir.createDirectory(name);
+ }
+ catch(NameInUse ex)
+ {
+ System.out.println("`" + name + "' exists already");
+ }
+ }
+ }
+
+ void
+ pwd()
+ {
+ if(_dirs.size() == 1)
+ {
+ System.out.print("/");
+ }
+ else
+ {
+ java.util.ListIterator<DirectoryPrx> i = _dirs.listIterator(_dirs.size());
+ i.previous();
+ while(i.hasPrevious())
+ {
+ System.out.print("/" + i.previous().name());
+ }
+ }
+ System.out.println();
+ }
+
+ void
+ cd(String name)
+ {
+ if(name.equals("/"))
+ {
+ while(_dirs.size() > 1)
+ {
+ _dirs.removeFirst();
+ }
+ return;
+ }
+
+ if(name.equals(".."))
+ {
+ if(_dirs.size() > 1)
+ {
+ _dirs.removeFirst();
+ }
+ return;
+ }
+
+ DirectoryPrx dir = _dirs.getFirst();
+ NodeDesc d;
+ try
+ {
+ d = dir.find(name);
+ }
+ catch(NoSuchName ex)
+ {
+ System.out.println("`" + name + "': no such directory");
+ return;
+ }
+ if(d.type == NodeType.FileType)
+ {
+ System.out.println("`" + name + "': not a directory");
+ return;
+ }
+ _dirs.addFirst(DirectoryPrxHelper.uncheckedCast(d.proxy));
+ }
+
+ void
+ cat(String name)
+ {
+ DirectoryPrx dir = _dirs.getFirst();
+ NodeDesc d;
+ try
+ {
+ d = dir.find(name);
+ }
+ catch(NoSuchName ex)
+ {
+ System.out.println("`" + name + "': no such file");
+ return;
+ }
+ if(d.type == NodeType.DirType)
+ {
+ System.out.println("`" + name + "': not a file");
+ return;
+ }
+ FilePrx f = FilePrxHelper.uncheckedCast(d.proxy);
+ String[] l = f.read();
+ for(int i = 0; i < l.length; ++i)
+ {
+ System.out.println(l[i]);
+ }
+ }
+
+ void
+ write(java.util.LinkedList<String> args)
+ {
+ DirectoryPrx dir = _dirs.getFirst();
+ String name = args.getFirst();
+ args.removeFirst();
+ NodeDesc d;
+ try
+ {
+ d = dir.find(name);
+ }
+ catch(NoSuchName ex)
+ {
+ System.out.println("`" + name + "': no such file");
+ return;
+ }
+ if(d.type == NodeType.DirType)
+ {
+ System.out.println("`" + name + "': not a file");
+ return;
+ }
+ FilePrx f = FilePrxHelper.uncheckedCast(d.proxy);
+
+ String[] l = new String[args.size()];
+ java.util.Iterator<String> i = args.iterator();
+ for(int j = 0; j < args.size(); ++j)
+ {
+ l[j] = i.next();
+ }
+ try
+ {
+ f.write(l);
+ }
+ catch(GenericError ex)
+ {
+ System.out.println("`" + name + "': cannot write to file: " + ex.reason);
+ }
+ }
+
+ void
+ destroy(java.util.List<String> names)
+ {
+ DirectoryPrx dir = _dirs.getFirst();
+
+ java.util.Iterator<String> i = names.iterator();
+ while(i.hasNext())
+ {
+ String name = i.next();
+ if(name.equals("*"))
+ {
+ NodeDesc[] nodes = dir.list();
+ for(int j = 0; j < nodes.length; ++j)
+ {
+ try
+ {
+ nodes[j].proxy.destroy();
+ }
+ catch(PermissionDenied ex)
+ {
+ System.out.println("cannot remove `" + nodes[j].name + "': " + ex.reason);
+ }
+ }
+ return;
+ }
+ else
+ {
+ NodeDesc d;
+ try
+ {
+ d = dir.find(name);
+ }
+ catch(NoSuchName ex)
+ {
+ System.out.println("`" + name + "': no such file or directory");
+ return;
+ }
+ try
+ {
+ d.proxy.destroy();
+ }
+ catch(PermissionDenied ex)
+ {
+ System.out.println("cannot remove `" + name + "': " + ex.reason);
+ }
+ }
+ }
+
+ }
+
+ 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()
+ {
+ _in = new java.io.BufferedReader(new java.io.InputStreamReader(System.in));
+
+ Grammar g = new Grammar(this);
+ g.parse();
+
+ return 0;
+ }
+
+ int
+ parse(java.io.BufferedReader in)
+ {
+ _in = in;
+
+ Grammar g = new Grammar(this);
+ g.parse();
+
+ return 0;
+ }
+
+ private java.util.LinkedList<DirectoryPrx> _dirs;
+
+ private java.io.BufferedReader _in;
+}
diff --git a/java/demo/book/freeze_filesystem/PersistentFilesystem.ice b/java/demo/book/evictor_filesystem/PersistentFilesystem.ice
index 2895d2f5d14..2895d2f5d14 100644
--- a/java/demo/book/freeze_filesystem/PersistentFilesystem.ice
+++ b/java/demo/book/evictor_filesystem/PersistentFilesystem.ice
diff --git a/java/demo/book/evictor_filesystem/README b/java/demo/book/evictor_filesystem/README
new file mode 100644
index 00000000000..7abae01bca6
--- /dev/null
+++ b/java/demo/book/evictor_filesystem/README
@@ -0,0 +1,13 @@
+This demo presents an implementation of the filesystem
+application based on a background-save evictor, as discussed in
+the Freeze chapter of the Ice manual.
+
+To run it, start the server in a window:
+
+$ java Server
+
+Then run the client in a separate window:
+
+$ java Client
+
+Type "help" at the client prompt to see a list of commands.
diff --git a/java/demo/book/evictor_filesystem/Scanner.java b/java/demo/book/evictor_filesystem/Scanner.java
new file mode 100644
index 00000000000..d318ed291f0
--- /dev/null
+++ b/java/demo/book/evictor_filesystem/Scanner.java
@@ -0,0 +1,283 @@
+// **********************************************************************
+//
+// 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("ls"))
+ {
+ return new Token(Token.TOK_LIST);
+ }
+ else if(s.equals("lr"))
+ {
+ return new Token(Token.TOK_LIST_RECURSIVE);
+ }
+ else if(s.equals("mkfile"))
+ {
+ return new Token(Token.TOK_CREATE_FILE);
+ }
+ else if(s.equals("mkdir"))
+ {
+ return new Token(Token.TOK_CREATE_DIR);
+ }
+ else if(s.equals("pwd"))
+ {
+ return new Token(Token.TOK_PWD);
+ }
+ else if(s.equals("cd"))
+ {
+ return new Token(Token.TOK_CD);
+ }
+ else if(s.equals("cat"))
+ {
+ return new Token(Token.TOK_CAT);
+ }
+ else if(s.equals("write"))
+ {
+ return new Token(Token.TOK_WRITE);
+ }
+ else if(s.equals("rm"))
+ {
+ return new Token(Token.TOK_RM);
+ }
+ 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/book/freeze_filesystem/Server.java b/java/demo/book/evictor_filesystem/Server.java
index 6e66f3ccb3f..6e66f3ccb3f 100644
--- a/java/demo/book/freeze_filesystem/Server.java
+++ b/java/demo/book/evictor_filesystem/Server.java
diff --git a/java/demo/book/evictor_filesystem/Token.java b/java/demo/book/evictor_filesystem/Token.java
new file mode 100644
index 00000000000..7fe92e242e0
--- /dev/null
+++ b/java/demo/book/evictor_filesystem/Token.java
@@ -0,0 +1,40 @@
+// **********************************************************************
+//
+// 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_SEMI = 2;
+ public static final int TOK_LIST = 3;
+ public static final int TOK_LIST_RECURSIVE = 4;
+ public static final int TOK_CREATE_FILE = 5;
+ public static final int TOK_CREATE_DIR = 6;
+ public static final int TOK_PWD = 7;
+ public static final int TOK_CD = 8;
+ public static final int TOK_CAT = 9;
+ public static final int TOK_WRITE = 10;
+ public static final int TOK_RM = 11;
+ public static final int TOK_STRING = 12;
+
+ 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/book/freeze_filesystem/build.xml b/java/demo/book/evictor_filesystem/build.xml
index b2c9993bb02..01d9c2a2a9e 100644
--- a/java/demo/book/freeze_filesystem/build.xml
+++ b/java/demo/book/evictor_filesystem/build.xml
@@ -9,7 +9,7 @@
**********************************************************************
-->
-<project name="demo_book_freeze_filesystem" default="all" basedir=".">
+<project name="demo_book_evictor_filesystem" default="all" basedir=".">
<!-- set global properties for this build -->
<property name="top.dir" value="../../.."/>
diff --git a/java/demo/book/freeze_filesystem/config.client b/java/demo/book/evictor_filesystem/config.client
index 6f0ba50b98f..6f0ba50b98f 100644
--- a/java/demo/book/freeze_filesystem/config.client
+++ b/java/demo/book/evictor_filesystem/config.client
diff --git a/java/demo/book/freeze_filesystem/config.server b/java/demo/book/evictor_filesystem/config.server
index 8ee5723e944..8ee5723e944 100644
--- a/java/demo/book/freeze_filesystem/config.server
+++ b/java/demo/book/evictor_filesystem/config.server
diff --git a/java/demo/book/freeze_filesystem/db/.gitignore b/java/demo/book/evictor_filesystem/db/.gitignore
index 39af5887579..39af5887579 100644
--- a/java/demo/book/freeze_filesystem/db/.gitignore
+++ b/java/demo/book/evictor_filesystem/db/.gitignore
diff --git a/java/demo/book/evictor_filesystem/expect.py b/java/demo/book/evictor_filesystem/expect.py
new file mode 100755
index 00000000000..60d3c0c8e9d
--- /dev/null
+++ b/java/demo/book/evictor_filesystem/expect.py
@@ -0,0 +1,38 @@
+#!/usr/bin/env python
+# **********************************************************************
+#
+# 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 sys, os
+
+try:
+ import demoscript
+except ImportError:
+ for toplevel in [".", "..", "../..", "../../..", "../../../.."]:
+ toplevel = os.path.normpath(toplevel)
+ if os.path.exists(os.path.join(toplevel, "demoscript")):
+ break
+ else:
+ raise "can't find toplevel directory!"
+ sys.path.append(os.path.join(toplevel))
+ import demoscript
+
+import demoscript.Util
+demoscript.Util.defaultLanguage = "Java"
+import demoscript.book.evictor_filesystem
+
+print "cleaning databases...",
+sys.stdout.flush()
+demoscript.Util.cleanDbDir("db")
+print "ok"
+
+server = demoscript.Util.spawn('java Server --Ice.PrintAdapterReady')
+server.expect('.* ready')
+client = demoscript.Util.spawn('java Client')
+
+demoscript.book.evictor_filesystem.run(client, server)
diff --git a/java/demo/book/freeze_filesystem/Client.java b/java/demo/book/freeze_filesystem/Client.java
deleted file mode 100644
index 01aac52f880..00000000000
--- a/java/demo/book/freeze_filesystem/Client.java
+++ /dev/null
@@ -1,164 +0,0 @@
-// **********************************************************************
-//
-// 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 Filesystem.*;
-
-public class Client extends Ice.Application
-{
- // Recursively print the contents of directory "dir" in tree fashion.
- // For files, show the contents of each file. The "depth"
- // parameter is the current nesting level (for indentation).
-
- static void
- listRecursive(DirectoryPrx dir, int depth)
- {
- char[] indentCh = new char[++depth];
- java.util.Arrays.fill(indentCh, '\t');
- String indent = new String(indentCh);
-
- NodeDesc[] contents = dir.list();
-
- for (int i = 0; i < contents.length; ++i) {
- DirectoryPrx subdir = DirectoryPrxHelper.checkedCast(contents[i].proxy);
- FilePrx file = FilePrxHelper.uncheckedCast(contents[i].proxy);
- System.out.println(indent + contents[i].name + (subdir != null ? " (directory):" : " (file):"));
- if (subdir != null) {
- listRecursive(subdir, depth);
- } else {
- String[] text = file.read();
- for (int j = 0; j < text.length; ++j)
- System.out.println(indent + "\t" + text[j]);
- }
- }
- }
-
- 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());
-
- //
- // Create a proxy for the root directory.
- //
- DirectoryPrx rootDir = DirectoryPrxHelper.checkedCast(communicator().propertyToProxy("RootDir.Proxy"));
- if(rootDir == null)
- {
- System.err.println("Client: invalid proxy");
- return 1;
- }
-
- try
- {
- //
- // Create a file called "README" in the root directory.
- //
- try
- {
- FilePrx readme = rootDir.createFile("README");
- String[] text = new String[1];
- text[0] = "This file system contains a collection of poetry.";
- readme.write(text);
- System.out.println("Created README.");
- }
- catch(NameInUse ex)
- {
- //
- // Ignore - file already exists.
- //
- }
-
- //
- // Create a directory called "Coleridge" in the root directory.
- //
- DirectoryPrx coleridge = null;
- try
- {
- coleridge = rootDir.createDirectory("Coleridge");
- System.out.println("Created Coleridge.");
- }
- catch(NameInUse ex)
- {
- NodeDesc desc = rootDir.find("Coleridge");
- coleridge = DirectoryPrxHelper.checkedCast(desc.proxy);
- assert(coleridge != null);
- }
-
- //
- // Create a file called "Kubla_Khan" in the Coleridge directory.
- //
- try
- {
- FilePrx file = coleridge.createFile("Kubla_Khan");
- String[] text = new String[5];
- text[0] = "In Xanadu did Kubla Khan";
- text[1] = "A stately pleasure-dome decree:";
- text[2] = "Where Alph, the sacred river, ran";
- text[3] = "Through caverns measureless to man";
- text[4] = "Down to a sunless sea.";
- file.write(text);
- System.out.println("Created Coleridge/Kubla_Khan.");
- }
- catch(NameInUse ex)
- {
- //
- // Ignore - file already exists.
- //
- }
-
- System.out.println("Contents of filesystem:");
- listRecursive(rootDir, 0);
-
- //
- // Destroy the filesystem.
- //
- NodeDesc[] contents = rootDir.list();
- for(int i = 0; i < contents.length; ++i)
- {
- NodeDesc d = contents[i];
- System.out.println("Destroying " + d.name);
- d.proxy.destroy();
- }
- }
- catch(Ice.UserException ex)
- {
- ex.printStackTrace();
- }
-
- return 0;
- }
-
- public static void
- main(String[] args)
- {
- Client app = new Client();
- int status = app.main("Client", args, "config.client");
- System.exit(status);
- }
-}
diff --git a/java/demo/book/freeze_filesystem/README b/java/demo/book/freeze_filesystem/README
deleted file mode 100644
index 32f3381a068..00000000000
--- a/java/demo/book/freeze_filesystem/README
+++ /dev/null
@@ -1,10 +0,0 @@
-This demo presents an alternate implementation of the filesystem
-application, as discussed in the Freeze chapter of the Ice manual.
-
-To run it, start the server in a window:
-
-$ java Server
-
-Then run the client in a separate window:
-
-$ java Client
diff --git a/java/demo/book/map_filesystem/.gitignore b/java/demo/book/map_filesystem/.gitignore
new file mode 100644
index 00000000000..9c39416c539
--- /dev/null
+++ b/java/demo/book/map_filesystem/.gitignore
@@ -0,0 +1 @@
+db/*
diff --git a/java/demo/book/map_filesystem/Client.java b/java/demo/book/map_filesystem/Client.java
new file mode 100644
index 00000000000..8599d43e81d
--- /dev/null
+++ b/java/demo/book/map_filesystem/Client.java
@@ -0,0 +1,56 @@
+// **********************************************************************
+//
+// 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 Filesystem.*;
+
+public class Client extends Ice.Application
+{
+ public int
+ run(String[] args)
+ {
+ // Terminate cleanly on receipt of a signal.
+ //
+ shutdownOnInterrupt();
+
+ // Create a proxy for the root directory
+ //
+ Ice.ObjectPrx base = communicator().stringToProxy("RootDir:default -p 10000");
+ if(base == null)
+ {
+ throw new Error("Could not create proxy");
+ }
+
+ // Down-cast the proxy to a Directory proxy.
+ //
+ DirectoryPrx rootDir = DirectoryPrxHelper.checkedCast(base);
+ if(rootDir == null)
+ {
+ throw new Error("Invalid proxy");
+ }
+
+ Parser p = new Parser(rootDir);
+ return p.parse();
+ }
+
+ static public void
+ main(String[] args)
+ {
+ Client app = new Client();
+ app.main("demo.book.lifecycle.Client", args);
+ }
+
+ static private class Error extends RuntimeException
+ {
+ public Error(String msg)
+ {
+ super(msg);
+ }
+ }
+
+}
diff --git a/java/demo/book/map_filesystem/Filesystem.ice b/java/demo/book/map_filesystem/Filesystem.ice
new file mode 100644
index 00000000000..fea080b38dd
--- /dev/null
+++ b/java/demo/book/map_filesystem/Filesystem.ice
@@ -0,0 +1,69 @@
+// **********************************************************************
+//
+// 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.
+//
+// **********************************************************************
+
+module Filesystem
+{
+ exception GenericError
+ {
+ string reason;
+ };
+ exception PermissionDenied extends GenericError {};
+ exception NameInUse extends GenericError {};
+ exception NoSuchName extends GenericError {};
+
+ interface Node
+ {
+ idempotent string name();
+ void destroy() throws PermissionDenied;
+ };
+
+ sequence<string> Lines;
+
+ interface File extends Node
+ {
+ idempotent Lines read();
+ idempotent void write(Lines text) throws GenericError;
+ };
+
+ enum NodeType { DirType, FileType };
+
+ struct NodeDesc
+ {
+ string name;
+ NodeType type;
+ Node* proxy;
+ };
+
+ sequence<NodeDesc> NodeDescSeq;
+
+ interface Directory extends Node
+ {
+ idempotent NodeDescSeq list();
+ idempotent NodeDesc find(string name) throws NoSuchName;
+ File* createFile(string name) throws NameInUse;
+ Directory* createDirectory(string name) throws NameInUse;
+ };
+
+ class PersistentNode
+ {
+ string name;
+ };
+
+ class PersistentFile extends PersistentNode
+ {
+ Lines text;
+ };
+
+ dictionary<string, NodeDesc> NodeDict;
+
+ class PersistentDirectory extends PersistentNode
+ {
+ NodeDict nodes;
+ };
+};
diff --git a/java/demo/book/map_filesystem/FilesystemI/DirectoryI.java b/java/demo/book/map_filesystem/FilesystemI/DirectoryI.java
new file mode 100644
index 00000000000..90b298d64cf
--- /dev/null
+++ b/java/demo/book/map_filesystem/FilesystemI/DirectoryI.java
@@ -0,0 +1,332 @@
+// **********************************************************************
+//
+// 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.
+//
+// **********************************************************************
+
+package FilesystemI;
+
+import Ice.*;
+import Filesystem.*;
+
+public class DirectoryI extends _DirectoryDisp implements NodeI, _DirectoryOperations
+{
+
+ // Slice name() operation.
+
+ public synchronized String
+ name(Current c)
+ {
+ if(_destroyed)
+ {
+ throw new ObjectNotExistException();
+ }
+ return _dir.name;
+ }
+
+ // Return the object identity for this node.
+
+ public Identity
+ id()
+ {
+ return _id;
+ }
+
+ // Slice list() operation.
+
+ public NodeDesc[]
+ list(Current c)
+ {
+ synchronized(this)
+ {
+ if(_destroyed)
+ {
+ throw new ObjectNotExistException();
+ }
+ }
+
+ synchronized(_lcMutex)
+ {
+ reap();
+
+ NodeDesc[] result = new NodeDesc[_dir.nodes.size()];
+ java.util.Iterator<java.util.Map.Entry<String, NodeDesc> > pos = _dir.nodes.entrySet().iterator();
+ for(int i = 0; i < _dir.nodes.size(); ++i)
+ {
+ java.util.Map.Entry<String, NodeDesc> e = pos.next();
+ result[i] = e.getValue();
+ }
+ return result;
+ }
+ }
+
+ // Slice find() operation.
+
+ public NodeDesc
+ find(String name, Current c) throws NoSuchName
+ {
+ synchronized(this)
+ {
+ if(_destroyed)
+ {
+ throw new ObjectNotExistException();
+ }
+ }
+
+ synchronized(_lcMutex)
+ {
+ reap();
+
+ NodeDesc nd = _dir.nodes.get(name);
+ if(nd == null)
+ {
+ throw new NoSuchName(name);
+ }
+ return nd;
+ }
+ }
+
+ // Slice createFile() operation.
+
+ public FilePrx
+ createFile(String name, Current c) throws NameInUse
+ {
+ synchronized(this)
+ {
+ if(_destroyed)
+ {
+ throw new ObjectNotExistException();
+ }
+ }
+
+ synchronized(_lcMutex)
+ {
+ reap();
+
+ if(name.length() == 0 || _dir.nodes.containsKey(name))
+ {
+ throw new NameInUse(name);
+ }
+
+ PersistentFile persistentFile = new PersistentFile();
+ persistentFile.name = name;
+ Communicator communicator = c.adapter.getCommunicator();
+ FileI file = new FileI(c.adapter, communicator.stringToIdentity(Util.generateUUID()),
+ persistentFile, this);
+ assert(_map.get(file.id()) == null);
+ _map.put(file.id(), persistentFile);
+
+ FilePrx proxy = FilePrxHelper.uncheckedCast(c.adapter.createProxy(file.id()));
+
+ NodeDesc nd = new NodeDesc();
+ nd.name = name;
+ nd.type = NodeType.FileType;
+ nd.proxy = proxy;
+ _dir.nodes.put(name, nd);
+ _map.put(_id, _dir);
+
+ file.activate(c.adapter);
+
+ return proxy;
+ }
+ }
+
+ // Slice createDirectory() operation.
+
+ public DirectoryPrx
+ createDirectory(String name, Current c) throws NameInUse
+ {
+ synchronized(this)
+ {
+ if(_destroyed)
+ {
+ throw new ObjectNotExistException();
+ }
+ }
+
+ synchronized(_lcMutex)
+ {
+ reap();
+
+ if(name.length() == 0 || _dir.nodes.containsKey(name))
+ {
+ throw new NameInUse(name);
+ }
+
+ PersistentDirectory persistentDir = new PersistentDirectory();
+ persistentDir.name = name;
+ persistentDir.nodes = new java.util.HashMap<String, NodeDesc>();
+ Communicator communicator = c.adapter.getCommunicator();
+ DirectoryI dir = new DirectoryI(c.adapter, communicator.stringToIdentity(Util.generateUUID()),
+ persistentDir, this);
+ assert(_map.get(dir.id()) == null);
+ _map.put(dir.id(), persistentDir);
+
+ DirectoryPrx proxy = DirectoryPrxHelper.uncheckedCast(c.adapter.createProxy(dir.id()));
+
+ NodeDesc nd = new NodeDesc();
+ nd.name = name;
+ nd.type = NodeType.DirType;
+ nd.proxy = proxy;
+ _dir.nodes.put(name, nd);
+ _map.put(_id, _dir);
+
+ dir.activate(c.adapter);
+
+ return proxy;
+ }
+ }
+
+ // Slice destroy() operation.
+
+ public void
+ destroy(Current c) throws PermissionDenied
+ {
+ if(_parent == null)
+ {
+ throw new PermissionDenied("Cannot destroy root directory");
+ }
+
+ synchronized(this)
+ {
+ if(_destroyed)
+ {
+ throw new ObjectNotExistException();
+ }
+
+ synchronized(_lcMutex)
+ {
+ reap();
+
+ if(_dir.nodes.size() != 0)
+ {
+ throw new PermissionDenied("Cannot destroy non-empty directory");
+ }
+
+ c.adapter.remove(id());
+ _parent.addReapEntry(_dir.name);
+ _destroyed = true;
+ }
+ }
+ }
+
+ // DirectoryI constructor. parent == null indicates root directory.
+
+ public DirectoryI(ObjectAdapter adapter, Identity id, PersistentDirectory dir, DirectoryI parent)
+ {
+ Communicator communicator = adapter.getCommunicator();
+ _connection = Freeze.Util.createConnection(communicator, _envName);
+ _map = new IdentityNodeMap(_connection, _dbName, false);
+ _id = id;
+ _dir = dir;
+ _parent = parent;
+ _destroyed = false;
+
+ java.util.Vector<String> staleEntries = new java.util.Vector<String>();
+
+ java.util.Iterator<java.util.Map.Entry<String, NodeDesc> > p = dir.nodes.entrySet().iterator();
+ while(p.hasNext())
+ {
+ java.util.Map.Entry<String, NodeDesc> e = (java.util.Map.Entry)p.next();
+ NodeDesc nd = e.getValue();
+ Identity ident = nd.proxy.ice_getIdentity();
+ PersistentNode node = (PersistentNode)_map.get(ident);
+ NodeI servant;
+ if(node != null)
+ {
+ if(nd.type == NodeType.DirType)
+ {
+ PersistentDirectory pDir = (PersistentDirectory)node;
+ servant = new DirectoryI(adapter, ident, pDir, this);
+ }
+ else
+ {
+ PersistentFile pFile = (PersistentFile)node;
+ servant = new FileI(adapter, ident, pFile, this);
+ }
+ servant.activate(adapter);
+ }
+ else
+ {
+ staleEntries.add(e.getKey());
+ }
+ }
+
+ java.util.Iterator<String> i = staleEntries.iterator();
+ while(i.hasNext())
+ {
+ dir.nodes.remove(i.next());
+ }
+ if(!staleEntries.isEmpty())
+ {
+ _map.put(id, dir);
+ }
+ }
+
+
+ // Add servant to ASM and to parent's _contents map.
+
+ public DirectoryPrx
+ activate(ObjectAdapter a)
+ {
+ return DirectoryPrxHelper.uncheckedCast(a.add(this, _id));
+ }
+
+ // Add this directory and the name of a deleted entry to the reap map.
+
+ public void
+ addReapEntry(String name)
+ {
+ java.util.List<String> l = _reapMap.get(this);
+ if(l != null)
+ {
+ l.add(name);
+ }
+ else
+ {
+ l = new java.util.ArrayList<String>();
+ l.add(name);
+ _reapMap.put(this, l);
+ }
+ }
+
+ // Remove all names in the reap map from the corresponding directory contents.
+
+ private static void
+ reap()
+ {
+ java.util.Iterator<java.util.Map.Entry<DirectoryI, java.util.List<String> > > i =
+ _reapMap.entrySet().iterator();
+ while(i.hasNext())
+ {
+ java.util.Map.Entry<DirectoryI, java.util.List<String> > e = i.next();
+ DirectoryI dir = e.getKey();
+ java.util.List<String> l = e.getValue();
+ java.util.Iterator<String> j = l.iterator();
+ while(j.hasNext())
+ {
+ dir._dir.nodes.remove(j.next());
+ }
+ }
+ _reapMap.clear();
+ }
+
+ public static java.lang.Object _lcMutex = new java.lang.Object();
+
+ public static String _envName;
+ public static String _dbName;
+
+ private DirectoryI _parent;
+ private boolean _destroyed;
+ private Identity _id;
+ private Freeze.Connection _connection;
+ private IdentityNodeMap _map;
+ private PersistentDirectory _dir;
+
+ private static java.util.Map<DirectoryI, java.util.List<String> > _reapMap =
+ new java.util.HashMap<DirectoryI, java.util.List<String> >();
+
+}
diff --git a/java/demo/book/map_filesystem/FilesystemI/FileI.java b/java/demo/book/map_filesystem/FilesystemI/FileI.java
new file mode 100644
index 00000000000..8014c9fa5cf
--- /dev/null
+++ b/java/demo/book/map_filesystem/FilesystemI/FileI.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.
+//
+// **********************************************************************
+
+package FilesystemI;
+
+import Ice.*;
+import Filesystem.*;
+import FilesystemI.*;
+
+public class FileI extends _FileDisp implements NodeI, _FileOperations
+{
+ public synchronized String
+ name(Current c)
+ {
+ if(_destroyed)
+ {
+ throw new ObjectNotExistException();
+ }
+ return _file.name;
+ }
+
+ public Identity
+ id()
+ {
+ return _id;
+ }
+
+ public synchronized String[]
+ read(Current c)
+ {
+ if(_destroyed)
+ {
+ throw new ObjectNotExistException();
+ }
+
+ return _file.text;
+ }
+
+ public synchronized void
+ write(String[] text, Current c)
+ {
+ if(_destroyed)
+ {
+ throw new ObjectNotExistException();
+ }
+
+ _file.text = (String[])text.clone();
+ _map.put(_id, _file);
+ }
+
+ public void
+ destroy(Current c)
+ {
+ synchronized(this)
+ {
+ if(_destroyed)
+ {
+ throw new ObjectNotExistException();
+ }
+ _destroyed = true;
+ }
+
+ synchronized(_parent._lcMutex)
+ {
+ c.adapter.remove(c.id);
+ _parent.addReapEntry(_file.name);
+ _map.remove(c.id);
+ }
+ }
+
+ public FileI(ObjectAdapter adapter, Ice.Identity id, PersistentFile file, DirectoryI parent)
+ {
+ _connection = Freeze.Util.createConnection(adapter.getCommunicator(), _envName);
+ _map = new IdentityNodeMap(_connection, _dbName, false);
+ _id = id;
+ _file = file;
+ _parent = parent;
+ _destroyed = false;
+ }
+
+ public FilePrx
+ activate(Ice.ObjectAdapter a)
+ {
+ return FilePrxHelper.uncheckedCast(a.add(this, _id));
+ }
+
+ public static String _envName;
+ public static String _dbName;
+
+ private DirectoryI _parent;
+ private boolean _destroyed;
+ private Identity _id;
+ private Freeze.Connection _connection;
+ private IdentityNodeMap _map;
+ private PersistentFile _file;
+}
diff --git a/java/demo/book/map_filesystem/FilesystemI/NodeI.java b/java/demo/book/map_filesystem/FilesystemI/NodeI.java
new file mode 100644
index 00000000000..52162b64b85
--- /dev/null
+++ b/java/demo/book/map_filesystem/FilesystemI/NodeI.java
@@ -0,0 +1,16 @@
+// **********************************************************************
+//
+// 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.
+//
+// **********************************************************************
+
+package FilesystemI;
+
+public interface NodeI
+{
+ Ice.Identity id();
+ Ice.ObjectPrx activate(Ice.ObjectAdapter a);
+}
diff --git a/java/demo/book/map_filesystem/Grammar.java b/java/demo/book/map_filesystem/Grammar.java
new file mode 100644
index 00000000000..92da79a56d0
--- /dev/null
+++ b/java/demo/book/map_filesystem/Grammar.java
@@ -0,0 +1,202 @@
+// **********************************************************************
+//
+// 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_LIST)
+ {
+ _token = _scanner.nextToken();
+ if(_token.type != Token.TOK_SEMI)
+ {
+ throw new ParseError("Expected ';'");
+ }
+ _parser.list(false);
+ }
+ else if(_token.type == Token.TOK_LIST_RECURSIVE)
+ {
+ _token = _scanner.nextToken();
+ if(_token.type != Token.TOK_SEMI)
+ {
+ throw new ParseError("Expected ';'");
+ }
+ _parser.list(true);
+ }
+ else if(_token.type == Token.TOK_CREATE_FILE)
+ {
+ java.util.List<String> s = strings();
+ if(_token.type != Token.TOK_SEMI)
+ {
+ throw new ParseError("Expected ';'");
+ }
+ if(s.size() == 0)
+ {
+ throw new ParseError("usage: mkfile FILE [FILE...]");
+ }
+ _parser.createFile(s);
+ }
+ else if(_token.type == Token.TOK_CREATE_DIR)
+ {
+ java.util.List<String> s = strings();
+ if(_token.type != Token.TOK_SEMI)
+ {
+ throw new ParseError("Expected ';'");
+ }
+ if(s.size() == 0)
+ {
+ throw new ParseError("usage: mkdir DIR [DIR...]");
+ }
+ _parser.createDir(s);
+ }
+ else if(_token.type == Token.TOK_PWD)
+ {
+ _token = _scanner.nextToken();
+ if(_token.type != Token.TOK_SEMI)
+ {
+ throw new ParseError("Expected ';'");
+ }
+ _parser.pwd();
+ }
+ else if(_token.type == Token.TOK_CD)
+ {
+ java.util.List<String> s = strings();
+ if(_token.type != Token.TOK_SEMI)
+ {
+ throw new ParseError("Expected ';'");
+ }
+ if(s.size() > 1)
+ {
+ throw new ParseError("usage: cd [DIR]");
+ }
+ else if(s.size() == 0)
+ {
+ _parser.cd("/");
+ }
+ else
+ {
+ _parser.cd((String)s.get(0));
+ }
+ }
+ else if(_token.type == Token.TOK_CAT)
+ {
+ java.util.List<String> s = strings();
+ if(_token.type != Token.TOK_SEMI)
+ {
+ throw new ParseError("Expected ';'");
+ }
+ if(s.size() != 1)
+ {
+ throw new ParseError("usage: cat FILE");
+ }
+ _parser.cat((String)s.get(0));
+ }
+ else if(_token.type == Token.TOK_WRITE)
+ {
+ java.util.LinkedList<String> s = strings();
+ if(_token.type != Token.TOK_SEMI)
+ {
+ throw new ParseError("Expected ';'");
+ }
+ if(s.size() == 0)
+ {
+ throw new ParseError("usage: write FILE [STRING...]");
+ }
+ _parser.write(s);
+ }
+ else if(_token.type == Token.TOK_RM)
+ {
+ java.util.List<String> s = strings();
+ if(_token.type != Token.TOK_SEMI)
+ {
+ throw new ParseError("Expected ';'");
+ }
+ if(s.size() == 0)
+ {
+ throw new ParseError("usage: rm NAME [NAME...]");
+ }
+ _parser.destroy(s);
+ }
+ else
+ {
+ _parser.error("parse error");
+ }
+ }
+ catch(ParseError e)
+ {
+ _parser.error("Parse error: " + e.getMessage());
+ }
+ }
+ }
+
+ private java.util.LinkedList<String>
+ strings()
+ {
+ java.util.LinkedList<String> l = new java.util.LinkedList<String>();
+ 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/book/map_filesystem/Parser.java b/java/demo/book/map_filesystem/Parser.java
new file mode 100644
index 00000000000..94e4af53654
--- /dev/null
+++ b/java/demo/book/map_filesystem/Parser.java
@@ -0,0 +1,361 @@
+// **********************************************************************
+//
+// 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 Filesystem.*;
+
+class Parser
+{
+ Parser(DirectoryPrx root)
+ {
+ _dirs = new java.util.LinkedList<DirectoryPrx>();
+ _dirs.addFirst(root);
+ }
+
+ void
+ usage()
+ {
+ System.err.print(
+ "help Print this message.\n" +
+ "pwd Print current directory (/ = root).\n" +
+ "cd [DIR] Change directory (/ or empty = root).\n" +
+ "ls List current directory.\n" +
+ "lr Recursively list current directory.\n" +
+ "mkdir DIR [DIR...] Create directories DIR in current directory.\n" +
+ "mkfile FILE [FILE...] Create files FILE in current directory.\n" +
+ "rm NAME [NAME...] Delete directory or file NAME (rm * to delete all).\n" +
+ "cat FILE List the contents of FILE.\n" +
+ "write FILE [STRING...] Write STRING to FILE.\n" +
+ "exit, quit Exit this program.\n");
+ }
+
+ void
+ list(boolean recursive)
+ {
+ try
+ {
+ list(_dirs.get(0), recursive, 0);
+ }
+ catch(Ice.LocalException ex)
+ {
+ error(ex.toString());
+ }
+ }
+
+ void
+ list(Filesystem.DirectoryPrx dir, boolean recursive, int depth)
+ {
+ StringBuffer b = new StringBuffer();
+ for(int i = 0; i < depth; ++i)
+ {
+ b.append('\t');
+ }
+ String indent = b.toString();
+
+ NodeDesc[] contents = dir.list();
+
+ for(int i = 0; i < contents.length; ++i)
+ {
+ DirectoryPrx d
+ = contents[i].type == NodeType.DirType
+ ? DirectoryPrxHelper.uncheckedCast(contents[i].proxy)
+ : null;
+ System.out.print(indent + contents[i].name + (d != null ? " (directory)" : " (file)"));
+ if(d != null && recursive)
+ {
+ System.out.println(":");
+ list(d, true, ++depth);
+ }
+ else
+ {
+ System.out.println();
+ }
+ }
+ }
+
+ void
+ createFile(java.util.List<String> names)
+ {
+ DirectoryPrx dir = _dirs.getFirst();
+
+ java.util.Iterator<String> i = names.iterator();
+ while(i.hasNext())
+ {
+ String name = i.next();
+ if(name.equals(".."))
+ {
+ System.out.println("Cannot create a file named `..'");
+ continue;
+ }
+
+ try
+ {
+ dir.createFile(name);
+ }
+ catch(NameInUse ex)
+ {
+ System.out.println("`" + name + "' exists already");
+ }
+ }
+ }
+
+ void
+ createDir(java.util.List<String> names)
+ {
+ DirectoryPrx dir = _dirs.getFirst();
+
+ java.util.Iterator<String> i = names.iterator();
+ while(i.hasNext())
+ {
+ String name = i.next();
+ if(name.equals(".."))
+ {
+ System.out.println("Cannot create a directory named `..'");
+ continue;
+ }
+
+ try
+ {
+ dir.createDirectory(name);
+ }
+ catch(NameInUse ex)
+ {
+ System.out.println("`" + name + "' exists already");
+ }
+ }
+ }
+
+ void
+ pwd()
+ {
+ if(_dirs.size() == 1)
+ {
+ System.out.print("/");
+ }
+ else
+ {
+ java.util.ListIterator<DirectoryPrx> i = _dirs.listIterator(_dirs.size());
+ i.previous();
+ while(i.hasPrevious())
+ {
+ System.out.print("/" + i.previous().name());
+ }
+ }
+ System.out.println();
+ }
+
+ void
+ cd(String name)
+ {
+ if(name.equals("/"))
+ {
+ while(_dirs.size() > 1)
+ {
+ _dirs.removeFirst();
+ }
+ return;
+ }
+
+ if(name.equals(".."))
+ {
+ if(_dirs.size() > 1)
+ {
+ _dirs.removeFirst();
+ }
+ return;
+ }
+
+ DirectoryPrx dir = _dirs.getFirst();
+ NodeDesc d;
+ try
+ {
+ d = dir.find(name);
+ }
+ catch(NoSuchName ex)
+ {
+ System.out.println("`" + name + "': no such directory");
+ return;
+ }
+ if(d.type == NodeType.FileType)
+ {
+ System.out.println("`" + name + "': not a directory");
+ return;
+ }
+ _dirs.addFirst(DirectoryPrxHelper.uncheckedCast(d.proxy));
+ }
+
+ void
+ cat(String name)
+ {
+ DirectoryPrx dir = _dirs.getFirst();
+ NodeDesc d;
+ try
+ {
+ d = dir.find(name);
+ }
+ catch(NoSuchName ex)
+ {
+ System.out.println("`" + name + "': no such file");
+ return;
+ }
+ if(d.type == NodeType.DirType)
+ {
+ System.out.println("`" + name + "': not a file");
+ return;
+ }
+ FilePrx f = FilePrxHelper.uncheckedCast(d.proxy);
+ String[] l = f.read();
+ for(int i = 0; i < l.length; ++i)
+ {
+ System.out.println(l[i]);
+ }
+ }
+
+ void
+ write(java.util.LinkedList<String> args)
+ {
+ DirectoryPrx dir = _dirs.getFirst();
+ String name = args.getFirst();
+ args.removeFirst();
+ NodeDesc d;
+ try
+ {
+ d = dir.find(name);
+ }
+ catch(NoSuchName ex)
+ {
+ System.out.println("`" + name + "': no such file");
+ return;
+ }
+ if(d.type == NodeType.DirType)
+ {
+ System.out.println("`" + name + "': not a file");
+ return;
+ }
+ FilePrx f = FilePrxHelper.uncheckedCast(d.proxy);
+
+ String[] l = new String[args.size()];
+ java.util.Iterator<String> i = args.iterator();
+ for(int j = 0; j < args.size(); ++j)
+ {
+ l[j] = i.next();
+ }
+ try
+ {
+ f.write(l);
+ }
+ catch(GenericError ex)
+ {
+ System.out.println("`" + name + "': cannot write to file: " + ex.reason);
+ }
+ }
+
+ void
+ destroy(java.util.List<String> names)
+ {
+ DirectoryPrx dir = _dirs.getFirst();
+
+ java.util.Iterator<String> i = names.iterator();
+ while(i.hasNext())
+ {
+ String name = i.next();
+ if(name.equals("*"))
+ {
+ NodeDesc[] nodes = dir.list();
+ for(int j = 0; j < nodes.length; ++j)
+ {
+ try
+ {
+ nodes[j].proxy.destroy();
+ }
+ catch(PermissionDenied ex)
+ {
+ System.out.println("cannot remove `" + nodes[j].name + "': " + ex.reason);
+ }
+ }
+ return;
+ }
+ else
+ {
+ NodeDesc d;
+ try
+ {
+ d = dir.find(name);
+ }
+ catch(NoSuchName ex)
+ {
+ System.out.println("`" + name + "': no such file or directory");
+ return;
+ }
+ try
+ {
+ d.proxy.destroy();
+ }
+ catch(PermissionDenied ex)
+ {
+ System.out.println("cannot remove `" + name + "': " + ex.reason);
+ }
+ }
+ }
+
+ }
+
+ 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()
+ {
+ _in = new java.io.BufferedReader(new java.io.InputStreamReader(System.in));
+
+ Grammar g = new Grammar(this);
+ g.parse();
+
+ return 0;
+ }
+
+ int
+ parse(java.io.BufferedReader in)
+ {
+ _in = in;
+
+ Grammar g = new Grammar(this);
+ g.parse();
+
+ return 0;
+ }
+
+ private java.util.LinkedList<DirectoryPrx> _dirs;
+
+ private java.io.BufferedReader _in;
+}
diff --git a/java/demo/book/map_filesystem/README b/java/demo/book/map_filesystem/README
new file mode 100644
index 00000000000..b0e8d943879
--- /dev/null
+++ b/java/demo/book/map_filesystem/README
@@ -0,0 +1,13 @@
+This demo presents an implementation of the filesystem
+application based on a Freeze map, as discussed in
+the Freeze chapter of the Ice manual.
+
+To run it, start the server in a window:
+
+$ java Server
+
+Then run the client in a separate window:
+
+$ java Client
+
+Type "help" at the client prompt to see a list of commands.
diff --git a/java/demo/book/map_filesystem/Scanner.java b/java/demo/book/map_filesystem/Scanner.java
new file mode 100644
index 00000000000..d318ed291f0
--- /dev/null
+++ b/java/demo/book/map_filesystem/Scanner.java
@@ -0,0 +1,283 @@
+// **********************************************************************
+//
+// 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("ls"))
+ {
+ return new Token(Token.TOK_LIST);
+ }
+ else if(s.equals("lr"))
+ {
+ return new Token(Token.TOK_LIST_RECURSIVE);
+ }
+ else if(s.equals("mkfile"))
+ {
+ return new Token(Token.TOK_CREATE_FILE);
+ }
+ else if(s.equals("mkdir"))
+ {
+ return new Token(Token.TOK_CREATE_DIR);
+ }
+ else if(s.equals("pwd"))
+ {
+ return new Token(Token.TOK_PWD);
+ }
+ else if(s.equals("cd"))
+ {
+ return new Token(Token.TOK_CD);
+ }
+ else if(s.equals("cat"))
+ {
+ return new Token(Token.TOK_CAT);
+ }
+ else if(s.equals("write"))
+ {
+ return new Token(Token.TOK_WRITE);
+ }
+ else if(s.equals("rm"))
+ {
+ return new Token(Token.TOK_RM);
+ }
+ 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/book/map_filesystem/Server.java b/java/demo/book/map_filesystem/Server.java
new file mode 100644
index 00000000000..b9666633b71
--- /dev/null
+++ b/java/demo/book/map_filesystem/Server.java
@@ -0,0 +1,87 @@
+// **********************************************************************
+//
+// 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 Filesystem.*;
+import FilesystemI.*;
+
+public class Server extends Ice.Application
+{
+ public
+ Server(String envName)
+ {
+ _envName = envName;
+ }
+
+ public int
+ run(String[] args)
+ {
+ //
+ // Terminate cleanly on receipt of a signal.
+ //
+ shutdownOnInterrupt();
+
+ //
+ // Install object factories.
+ //
+ communicator().addObjectFactory(PersistentFile.ice_factory(), PersistentFile.ice_staticId());
+ communicator().addObjectFactory(PersistentDirectory.ice_factory(), PersistentDirectory.ice_staticId());
+
+ //
+ // Create an object adapter.
+ //
+ Ice.ObjectAdapter adapter =
+ communicator().createObjectAdapterWithEndpoints("MapFilesystem", "default -p 10000");
+
+ DirectoryI._envName = _envName;
+ DirectoryI._dbName = "mapfs";
+ FileI._envName = _envName;
+ FileI._dbName = "mapfs";
+
+ //
+ // Find the persistent node for the root directory,
+ // or create it if not found.
+ //
+ Freeze.Connection connection = Freeze.Util.createConnection(communicator(), _envName);
+ IdentityNodeMap persistentMap = new IdentityNodeMap(connection, FileI._dbName, true);
+
+ Ice.Identity rootId = communicator().stringToIdentity("RootDir");
+ PersistentDirectory pRoot = (PersistentDirectory)persistentMap.get(rootId);
+ if(pRoot == null)
+ {
+ pRoot = new PersistentDirectory();
+ pRoot.name ="/";
+ pRoot.nodes = new java.util.HashMap<java.lang.String, NodeDesc>();
+ persistentMap.put(rootId, pRoot);
+ }
+ DirectoryI dir = new DirectoryI(adapter, rootId, pRoot, null);
+ dir.activate(adapter);
+
+ //
+ // Ready to accept requests now.
+ //
+ adapter.activate();
+
+ //
+ // Wait until we are done.
+ //
+ communicator().waitForShutdown();
+
+ return 0;
+ }
+
+ public static void
+ main(String[] args)
+ {
+ Server app = new Server("db");
+ int status = app.main("Server", args, "config.server");
+ System.exit(status);
+ }
+
+ private String _envName;
+}
diff --git a/java/demo/book/map_filesystem/Token.java b/java/demo/book/map_filesystem/Token.java
new file mode 100644
index 00000000000..7fe92e242e0
--- /dev/null
+++ b/java/demo/book/map_filesystem/Token.java
@@ -0,0 +1,40 @@
+// **********************************************************************
+//
+// 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_SEMI = 2;
+ public static final int TOK_LIST = 3;
+ public static final int TOK_LIST_RECURSIVE = 4;
+ public static final int TOK_CREATE_FILE = 5;
+ public static final int TOK_CREATE_DIR = 6;
+ public static final int TOK_PWD = 7;
+ public static final int TOK_CD = 8;
+ public static final int TOK_CAT = 9;
+ public static final int TOK_WRITE = 10;
+ public static final int TOK_RM = 11;
+ public static final int TOK_STRING = 12;
+
+ 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/book/map_filesystem/build.xml b/java/demo/book/map_filesystem/build.xml
new file mode 100644
index 00000000000..8799fe2a2e4
--- /dev/null
+++ b/java/demo/book/map_filesystem/build.xml
@@ -0,0 +1,65 @@
+<!--
+ **********************************************************************
+
+ 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_book_lifecycle" 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="Filesystem.ice"/>
+ </slice2java>
+ <slice2freezej ice="on" outputdir="${generated.dir}">
+ <includepath>
+ <pathelement path="${slice.dir}" />
+ </includepath>
+ <fileset dir=".">
+ <include name="Filesystem.ice"/>
+ </fileset>
+ <fileset dir="${slice.dir}/Ice">
+ <include name="Identity.ice"/>
+ </fileset>
+ <dict name="Filesystem.IdentityNodeMap" key="Ice::Identity" value="Filesystem::PersistentNode"/>
+ </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/book/map_filesystem/config.client b/java/demo/book/map_filesystem/config.client
new file mode 100644
index 00000000000..6f0ba50b98f
--- /dev/null
+++ b/java/demo/book/map_filesystem/config.client
@@ -0,0 +1,28 @@
+#
+# The client reads this property to create the reference to the root
+# "directory" object in the server.
+#
+RootDir.Proxy=RootDir: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/book/map_filesystem/config.server b/java/demo/book/map_filesystem/config.server
new file mode 100644
index 00000000000..8ee5723e944
--- /dev/null
+++ b/java/demo/book/map_filesystem/config.server
@@ -0,0 +1,49 @@
+#
+# Configure the server endpoints.
+#
+FreezeFilesystem.Endpoints=default -p 10000
+
+#
+# Freeze Map Tracing.
+#
+# 0 = No map activity trace (default).
+# 1 = Trace database open and close.
+# 2 = Also trace iterator and transaction operations, and reference
+# counting of the underlying database.
+#
+Freeze.Trace.Map=1
+
+#
+# Freeze Evictor Tracing.
+#
+# 0 = No evictor activity trace (default).
+# 1 = Trace Ice object and facet creation and destruction, facet
+# streaming time, facet saving time, object eviction (every 50
+# objects) and evictor deactivation.
+# 2 = Also trace object lookups, and all object evictions.
+# 3 = Also trace object retrieval from the database.
+#
+Freeze.Trace.Evictor=2
+
+#
+# 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/book/map_filesystem/db/.gitignore b/java/demo/book/map_filesystem/db/.gitignore
new file mode 100644
index 00000000000..39af5887579
--- /dev/null
+++ b/java/demo/book/map_filesystem/db/.gitignore
@@ -0,0 +1 @@
+# Dummy file, so that git retains this otherwise empty directory.
diff --git a/java/demo/book/freeze_filesystem/expect.py b/java/demo/book/map_filesystem/expect.py
index 555fc67854a..3504eff9099 100755
--- a/java/demo/book/freeze_filesystem/expect.py
+++ b/java/demo/book/map_filesystem/expect.py
@@ -24,7 +24,7 @@ except ImportError:
import demoscript.Util
demoscript.Util.defaultLanguage = "Java"
-import demoscript.book.freeze_filesystem
+import demoscript.book.map_filesystem
print "cleaning databases...",
sys.stdout.flush()
@@ -35,4 +35,4 @@ server = demoscript.Util.spawn('java Server --Ice.PrintAdapterReady')
server.expect('.* ready')
client = demoscript.Util.spawn('java Client')
-demoscript.book.freeze_filesystem.run(client, server)
+demoscript.book.map_filesystem.run(client, server)