summaryrefslogtreecommitdiff
path: root/java/demo/Manual
diff options
context:
space:
mode:
authorJose <jose@zeroc.com>2014-11-07 21:28:00 +0100
committerJose <jose@zeroc.com>2014-11-07 21:28:00 +0100
commitf99742d525f519996a6d321afb323a67fd9be4f9 (patch)
treef7b4454611d64d1a28bf9609aa64234fe78d3f53 /java/demo/Manual
parentSome IceJS linting fixes (diff)
downloadice-f99742d525f519996a6d321afb323a67fd9be4f9.tar.bz2
ice-f99742d525f519996a6d321afb323a67fd9be4f9.tar.xz
ice-f99742d525f519996a6d321afb323a67fd9be4f9.zip
Fix for (ICE-5832) Versioning of Jar files
Renaming JAR files
Diffstat (limited to 'java/demo/Manual')
-rw-r--r--java/demo/Manual/README31
-rw-r--r--java/demo/Manual/build.gradle98
-rw-r--r--java/demo/Manual/evictor/EvictorBase.java124
-rw-r--r--java/demo/Manual/evictor/LinkedList.java225
-rw-r--r--java/demo/Manual/evictor/README15
-rw-r--r--java/demo/Manual/evictor_filesystem/.externalToolBuilders/book.demo.evictor_filesystem.slice.launch17
-rw-r--r--java/demo/Manual/evictor_filesystem/.gitignore1
-rw-r--r--java/demo/Manual/evictor_filesystem/Client.java50
-rw-r--r--java/demo/Manual/evictor_filesystem/DirectoryI.java170
-rw-r--r--java/demo/Manual/evictor_filesystem/FileI.java80
-rw-r--r--java/demo/Manual/evictor_filesystem/Filesystem.ice63
-rw-r--r--java/demo/Manual/evictor_filesystem/Grammar.java202
-rw-r--r--java/demo/Manual/evictor_filesystem/NodeFactory.java38
-rw-r--r--java/demo/Manual/evictor_filesystem/Parser.java349
-rw-r--r--java/demo/Manual/evictor_filesystem/PersistentFilesystem.ice38
-rw-r--r--java/demo/Manual/evictor_filesystem/README11
-rw-r--r--java/demo/Manual/evictor_filesystem/Scanner.java283
-rw-r--r--java/demo/Manual/evictor_filesystem/Server.java82
-rw-r--r--java/demo/Manual/evictor_filesystem/Token.java40
-rw-r--r--java/demo/Manual/evictor_filesystem/config.client28
-rw-r--r--java/demo/Manual/evictor_filesystem/config.server49
-rw-r--r--java/demo/Manual/evictor_filesystem/demo_manual_evictor_filesystem.iml24
-rwxr-xr-xjava/demo/Manual/evictor_filesystem/expect.py34
-rw-r--r--java/demo/Manual/lifecycle/.externalToolBuilders/demo.book.lifecycle.slice.launch17
-rw-r--r--java/demo/Manual/lifecycle/Client.java55
-rw-r--r--java/demo/Manual/lifecycle/Filesystem.ice54
-rw-r--r--java/demo/Manual/lifecycle/FilesystemI/DirectoryI.java189
-rw-r--r--java/demo/Manual/lifecycle/FilesystemI/FileI.java86
-rw-r--r--java/demo/Manual/lifecycle/FilesystemI/NodeI.java15
-rw-r--r--java/demo/Manual/lifecycle/Grammar.java202
-rw-r--r--java/demo/Manual/lifecycle/Parser.java349
-rw-r--r--java/demo/Manual/lifecycle/README11
-rw-r--r--java/demo/Manual/lifecycle/Scanner.java283
-rw-r--r--java/demo/Manual/lifecycle/Server.java60
-rw-r--r--java/demo/Manual/lifecycle/Token.java40
-rw-r--r--java/demo/Manual/lifecycle/demo_manual_lifecycle.iml23
-rwxr-xr-xjava/demo/Manual/lifecycle/expect.py29
-rw-r--r--java/demo/Manual/map_filesystem/.externalToolBuilders/demo.book.map_filesystem.launch17
-rw-r--r--java/demo/Manual/map_filesystem/.gitignore1
-rw-r--r--java/demo/Manual/map_filesystem/Client.java50
-rw-r--r--java/demo/Manual/map_filesystem/DirectoryI.java407
-rw-r--r--java/demo/Manual/map_filesystem/FileI.java221
-rw-r--r--java/demo/Manual/map_filesystem/Filesystem.ice54
-rw-r--r--java/demo/Manual/map_filesystem/FilesystemDB.ice31
-rw-r--r--java/demo/Manual/map_filesystem/Grammar.java202
-rw-r--r--java/demo/Manual/map_filesystem/Parser.java349
-rw-r--r--java/demo/Manual/map_filesystem/README11
-rw-r--r--java/demo/Manual/map_filesystem/Scanner.java283
-rw-r--r--java/demo/Manual/map_filesystem/Server.java80
-rw-r--r--java/demo/Manual/map_filesystem/Token.java40
-rw-r--r--java/demo/Manual/map_filesystem/build.gradle104
-rw-r--r--java/demo/Manual/map_filesystem/config.client28
-rw-r--r--java/demo/Manual/map_filesystem/config.server37
-rw-r--r--java/demo/Manual/map_filesystem/demo_manual_map_filesystem.iml24
-rwxr-xr-xjava/demo/Manual/map_filesystem/expect.py34
-rw-r--r--java/demo/Manual/printer/.externalToolBuilders/demo.book.printer.launch17
-rw-r--r--java/demo/Manual/printer/Client.java53
-rwxr-xr-xjava/demo/Manual/printer/Printer.ice20
-rw-r--r--java/demo/Manual/printer/PrinterI.java17
-rw-r--r--java/demo/Manual/printer/README8
-rw-r--r--java/demo/Manual/printer/Server.java45
-rw-r--r--java/demo/Manual/printer/demo_manual_printer.iml23
-rwxr-xr-xjava/demo/Manual/printer/expect.py34
-rw-r--r--java/demo/Manual/simple_filesystem/.externalToolBuilders/demo.book.simple_filesystem.launch17
-rw-r--r--java/demo/Manual/simple_filesystem/Client.java103
-rwxr-xr-xjava/demo/Manual/simple_filesystem/Filesystem.ice38
-rw-r--r--java/demo/Manual/simple_filesystem/Filesystem/DirectoryI.java72
-rw-r--r--java/demo/Manual/simple_filesystem/Filesystem/FileI.java67
-rw-r--r--java/demo/Manual/simple_filesystem/README10
-rw-r--r--java/demo/Manual/simple_filesystem/Server.java99
-rw-r--r--java/demo/Manual/simple_filesystem/demo_manual_simple_filesystem.iml23
-rwxr-xr-xjava/demo/Manual/simple_filesystem/expect.py34
72 files changed, 6118 insertions, 0 deletions
diff --git a/java/demo/Manual/README b/java/demo/Manual/README
new file mode 100644
index 00000000000..6dbc708834e
--- /dev/null
+++ b/java/demo/Manual/README
@@ -0,0 +1,31 @@
+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.
+
+- evictor_filesystem
+
+ An implementation of the persistent version of the file system
+ example described in the Freeze chapter using a Freeze evictor.
+
+- map_filesystem
+
+ An implementation of the persistent version of the file system
+ example described in the Freeze chapter using a Freeze map.
+
+- lifecycle
+
+ An implementation of the file system that supports life cycle operations.
+
+- printer
+
+ An implementation of the simple printer example at the beginning of
+ the manual.
+
+- simple_filesystem
+
+ An implementation of the simple (non-persistent, non-life-cycle)
+ version of the file system example.
diff --git a/java/demo/Manual/build.gradle b/java/demo/Manual/build.gradle
new file mode 100644
index 00000000000..32a101b37b9
--- /dev/null
+++ b/java/demo/Manual/build.gradle
@@ -0,0 +1,98 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2014 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.
+//
+// **********************************************************************
+
+['evictor_filesystem', 'lifecycle', 'printer', 'simple_filesystem'].each {
+ // abc_def -> AbcDef
+ def name = it.split('_').collect { it.capitalize() }.join()
+ project(":demoManual${name}") {
+ slice {
+ java {
+ include = ["${projectDir}", "${sliceDir}"]
+ srcDir = '.'
+ }
+ }
+
+ sourceSets {
+ main {
+ java {
+ srcDir '.'
+ output.classesDir "${buildDir}/classes"
+ }
+ }
+ }
+
+ if (useMavenJars) {
+ dependencies {
+ compile "com.zeroc:ice:${iceVersion}"
+ }
+ } else if (distJarDir != null) {
+ dependencies {
+ compile files("${distJarDir}/Ice${versionSuffix}.jar")
+ }
+ } else {
+ dependencies {
+ compile project(':Ice')
+ }
+ }
+
+ if(name == "EvictorFilesystem") {
+ if (distJarDir == null) {
+ dependencies {
+ compile project(':Freeze')
+ }
+ } else {
+ dependencies {
+ compile files("${distJarDir}/Freeze${versionSuffix}.jar")
+ compile 'com.sleepycat:db:5.3.28'
+ }
+ }
+ }
+
+ // Create a jar for the client & server which includes everything in the demo.
+ task clientJar(type: Jar) {
+ baseName = "client"
+ from(sourceSets.main.output) {
+ include "**"
+ }
+ }
+
+ task serverJar(type: Jar) {
+ baseName = "server"
+ from(sourceSets.main.output) {
+ include "**"
+ }
+ }
+
+ clientJar {
+ manifest {
+ attributes("Main-Class": "Client")
+ attributes("Class-Path": configurations.compile.resolve().collect { it.toURI() }.join(' '))
+ }
+ }
+
+ serverJar {
+ manifest {
+ attributes("Main-Class": "Server")
+ attributes("Class-Path": configurations.compile.resolve().collect { it.toURI() }.join(' '))
+ }
+ }
+
+ artifacts {
+ archives clientJar, serverJar;
+ }
+
+ // Don't create the default jar.
+ jar.enabled = false
+
+ idea.module {
+ excludeDirs -= file(buildDir)
+ buildDir.listFiles({d, f ->f != 'generated-src'} as FilenameFilter).each { excludeDirs += it }
+ }
+ }
+}
diff --git a/java/demo/Manual/evictor/EvictorBase.java b/java/demo/Manual/evictor/EvictorBase.java
new file mode 100644
index 00000000000..c309bd2866a
--- /dev/null
+++ b/java/demo/Manual/evictor/EvictorBase.java
@@ -0,0 +1,124 @@
+package Evictor;
+
+public abstract class EvictorBase implements Ice.ServantLocator
+{
+ public
+ EvictorBase()
+ {
+ _size = 1000;
+ }
+
+ public
+ EvictorBase(int size)
+ {
+ _size = size < 0 ? 1000 : size;
+ }
+
+ public abstract Ice.Object
+ add(Ice.Current c, Ice.LocalObjectHolder cookie);
+
+ public abstract void
+ evict(Ice.Object servant, java.lang.Object cookie);
+
+ synchronized public final Ice.Object
+ locate(Ice.Current c, Ice.LocalObjectHolder cookie)
+ {
+ //
+ // Check if we have a servant in the map already.
+ //
+ EvictorEntry entry = _map.get(c.id);
+ if(entry != null)
+ {
+ //
+ // Got an entry already, dequeue the entry from its current position.
+ //
+ entry.queuePos.remove();
+ }
+ else
+ {
+ //
+ // We do not have entry. Ask the derived class to
+ // instantiate a servant and add a new entry to the map.
+ //
+ entry = new EvictorEntry();
+ Ice.LocalObjectHolder cookieHolder = new Ice.LocalObjectHolder();
+ entry.servant = add(c, cookieHolder); // Down-call
+ if(entry.servant == null)
+ {
+ return null;
+ }
+ entry.userCookie = cookieHolder.value;
+ entry.useCount = 0;
+ _map.put(c.id, entry);
+ }
+
+ //
+ // Increment the use count of the servant and enqueue
+ // the entry at the front, so we get LRU order.
+ //
+ ++(entry.useCount);
+ _queue.addFirst(c.id);
+ entry.queuePos = _queue.iterator();
+ entry.queuePos.next(); // Position the iterator on the element.
+
+ cookie.value = entry;
+
+ return entry.servant;
+ }
+
+ synchronized public final void
+ finished(Ice.Current c, Ice.Object o, java.lang.Object cookie)
+ {
+ EvictorEntry entry = (EvictorEntry)cookie;
+
+ //
+ // Decrement use count and check if
+ // there is something to evict.
+ //
+ --(entry.useCount);
+ evictServants();
+ }
+
+ synchronized public final void
+ deactivate(String category)
+ {
+ _size = 0;
+ evictServants();
+ }
+
+ private class EvictorEntry
+ {
+ Ice.Object servant;
+ java.lang.Object userCookie;
+ java.util.Iterator<Ice.Identity> queuePos;
+ int useCount;
+ }
+
+ private void evictServants()
+ {
+ //
+ // If the evictor queue has grown larger than the limit,
+ // look at the excess elements to see whether any of them
+ // can be evicted.
+ //
+ java.util.Iterator<Ice.Identity> p = _queue.riterator();
+ int excessEntries = _map.size() - _size;
+ for(int i = 0; i < excessEntries; ++i)
+ {
+ Ice.Identity id = p.next();
+ EvictorEntry e = _map.get(id);
+ if(e.useCount == 0)
+ {
+ evict(e.servant, e.userCookie); // Down-call
+ e.queuePos.remove();
+ _map.remove(id);
+ }
+ }
+ }
+
+ private java.util.Map<Ice.Identity, EvictorEntry> _map =
+ new java.util.HashMap<Ice.Identity, EvictorEntry>();
+ private Evictor.LinkedList<Ice.Identity> _queue =
+ new Evictor.LinkedList<Ice.Identity>();
+ private int _size;
+}
diff --git a/java/demo/Manual/evictor/LinkedList.java b/java/demo/Manual/evictor/LinkedList.java
new file mode 100644
index 00000000000..5270142e6a9
--- /dev/null
+++ b/java/demo/Manual/evictor/LinkedList.java
@@ -0,0 +1,225 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2014 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 Evictor;
+
+//
+// Stripped down LinkedList implementation for use in the Evictor. The
+// API is similar to java.util.LinkedList.
+//
+// Major differences:
+// * listIterator() is not implemented.
+// * Operation riterator() returns a reverse iterator.
+// * This implementation also has the property that an Iterator can be
+// retained over structural changes to the list itself (similar to an
+// STL list).
+//
+public class LinkedList<T>
+{
+ public
+ LinkedList()
+ {
+ _header.next = _header.previous = _header;
+ }
+
+ public T
+ getFirst()
+ {
+ if(_size == 0)
+ {
+ throw new java.util.NoSuchElementException();
+ }
+
+ return _header.next.element;
+ }
+
+ public void
+ addFirst(T o)
+ {
+ addBefore(o, _header.next);
+ }
+
+ public boolean
+ isEmpty()
+ {
+ return _size == 0;
+ }
+
+ public int
+ size()
+ {
+ return _size;
+ }
+
+ public java.util.Iterator<T>
+ iterator()
+ {
+ return new ForwardIterator();
+ }
+
+ public java.util.Iterator<T>
+ riterator()
+ {
+ return new ReverseIterator();
+ }
+
+ private class ForwardIterator implements java.util.Iterator<T>
+ {
+ public boolean
+ hasNext()
+ {
+ return _next != null;
+ }
+
+ public T
+ next()
+ {
+ if(_next == null)
+ {
+ throw new java.util.NoSuchElementException();
+ }
+
+ _current = _next;
+
+ if(_next.next != _header)
+ {
+ _next = _next.next;
+ }
+ else
+ {
+ _next = null;
+ }
+ return _current.element;
+ }
+
+ public void
+ remove()
+ {
+ if(_current == null)
+ {
+ throw new IllegalStateException();
+ }
+ LinkedList.this.remove(_current);
+ _current = null;
+ }
+
+ ForwardIterator()
+ {
+ if(_header.next == _header)
+ {
+ _next = null;
+ }
+ else
+ {
+ _next = _header.next;
+ }
+ _current = null;
+ }
+
+ private Entry<T> _current;
+ private Entry<T> _next;
+ }
+
+ private class ReverseIterator implements java.util.Iterator<T>
+ {
+ public boolean
+ hasNext()
+ {
+ return _next != null;
+ }
+
+ public T
+ next()
+ {
+ if(_next == null)
+ {
+ throw new java.util.NoSuchElementException();
+ }
+
+ _current = _next;
+
+ if(_next.previous != _header)
+ {
+ _next = _next.previous;
+ }
+ else
+ {
+ _next = null;
+ }
+ return _current.element;
+ }
+
+ public void
+ remove()
+ {
+ if(_current == null)
+ {
+ throw new IllegalStateException();
+ }
+ LinkedList.this.remove(_current);
+ _current = null;
+ }
+
+ ReverseIterator()
+ {
+ if(_header.next == _header)
+ {
+ _next = null;
+ }
+ else
+ {
+ _next = _header.previous;
+ }
+ _current = null;
+ }
+
+ private Entry<T> _current;
+ private Entry<T> _next;
+ }
+
+ private static class Entry<T>
+ {
+ T element;
+ Entry<T> next;
+ Entry<T> previous;
+
+ Entry(T element, Entry<T> next, Entry<T> previous)
+ {
+ this.element = element;
+ this.next = next;
+ this.previous = previous;
+ }
+ }
+
+ private Entry<T>
+ addBefore(T o, Entry<T> e)
+ {
+ Entry<T> newEntry = new Entry<T>(o, e, e.previous);
+ newEntry.previous.next = newEntry;
+ newEntry.next.previous = newEntry;
+ _size++;
+ return newEntry;
+ }
+
+ private void
+ remove(Entry<T> e)
+ {
+ if(e == _header)
+ {
+ throw new java.util.NoSuchElementException();
+ }
+
+ e.previous.next = e.next;
+ e.next.previous = e.previous;
+ _size--;
+ }
+
+ private Entry<T> _header = new Entry<T>(null, null, null);
+ private int _size = 0;
+}
diff --git a/java/demo/Manual/evictor/README b/java/demo/Manual/evictor/README
new file mode 100644
index 00000000000..cc6b56f5d65
--- /dev/null
+++ b/java/demo/Manual/evictor/README
@@ -0,0 +1,15 @@
+The source code provided here implements a Java evictor base class. To
+use it, you must derive a class from EvictorBase and implement the
+abstract add() and evict() methods.
+
+add() is called when the evictor needs to instantiate a servant, and
+evict() is called when the evictor has decided to evict a servant.
+Note that you can pass information from add() to the corresponding
+call to evict() via the cookie argument.
+
+The evictor implementation relies on a linked list that allows items
+to be added and removed without invalidating iterators. Such an
+implementation is provided in LinkedList.java.
+
+For more details on this evictor, see the section "Server
+Implementation Techniques" in the Ice documentation.
diff --git a/java/demo/Manual/evictor_filesystem/.externalToolBuilders/book.demo.evictor_filesystem.slice.launch b/java/demo/Manual/evictor_filesystem/.externalToolBuilders/book.demo.evictor_filesystem.slice.launch
new file mode 100644
index 00000000000..0ce604434d2
--- /dev/null
+++ b/java/demo/Manual/evictor_filesystem/.externalToolBuilders/book.demo.evictor_filesystem.slice.launch
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<launchConfiguration type="org.eclipse.ant.AntBuilderLaunchConfigurationType">
+<stringAttribute key="org.eclipse.ant.ui.ATTR_ANT_AUTO_TARGETS" value="generate,"/>
+<stringAttribute key="org.eclipse.ant.ui.ATTR_ANT_CLEAN_TARGETS" value="clean,"/>
+<stringAttribute key="org.eclipse.ant.ui.ATTR_ANT_MANUAL_TARGETS" value="generate,"/>
+<booleanAttribute key="org.eclipse.ant.ui.ATTR_TARGETS_UPDATED" value="true"/>
+<booleanAttribute key="org.eclipse.ant.ui.DEFAULT_VM_INSTALL" value="false"/>
+<stringAttribute key="org.eclipse.debug.core.ATTR_REFRESH_SCOPE" value="${container}"/>
+<booleanAttribute key="org.eclipse.debug.ui.ATTR_LAUNCH_IN_BACKGROUND" value="false"/>
+<stringAttribute key="org.eclipse.jdt.launching.CLASSPATH_PROVIDER" value="org.eclipse.ant.ui.AntClasspathProvider"/>
+<booleanAttribute key="org.eclipse.jdt.launching.DEFAULT_CLASSPATH" value="true"/>
+<stringAttribute key="org.eclipse.jdt.launching.PROJECT_ATTR" value="demo.book.evictor_filesystem"/>
+<stringAttribute key="org.eclipse.ui.externaltools.ATTR_BUILD_SCOPE" value="${working_set:&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;&#10;&lt;resources&gt;&#10;&lt;item path=&quot;/demo.book.evictor_filesystem/Filesystem.ice&quot; type=&quot;1&quot;/&gt;&#10;&lt;item path=&quot;/demo.book.evictor_filesystem/PersistentFilesystem.ice&quot; type=&quot;1&quot;/&gt;&#10;&lt;/resources&gt;}"/>
+<stringAttribute key="org.eclipse.ui.externaltools.ATTR_LOCATION" value="${workspace_loc:/demo.book.evictor_filesystem/build.xml}"/>
+<stringAttribute key="org.eclipse.ui.externaltools.ATTR_RUN_BUILD_KINDS" value="incremental,auto,clean"/>
+<booleanAttribute key="org.eclipse.ui.externaltools.ATTR_TRIGGERS_CONFIGURED" value="true"/>
+</launchConfiguration>
diff --git a/java/demo/Manual/evictor_filesystem/.gitignore b/java/demo/Manual/evictor_filesystem/.gitignore
new file mode 100644
index 00000000000..9c39416c539
--- /dev/null
+++ b/java/demo/Manual/evictor_filesystem/.gitignore
@@ -0,0 +1 @@
+db/*
diff --git a/java/demo/Manual/evictor_filesystem/Client.java b/java/demo/Manual/evictor_filesystem/Client.java
new file mode 100644
index 00000000000..93a48deb2b5
--- /dev/null
+++ b/java/demo/Manual/evictor_filesystem/Client.java
@@ -0,0 +1,50 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2014 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
+{
+ @Override
+ public int
+ run(String[] args)
+ {
+ //
+ // Terminate cleanly on receipt of a signal.
+ //
+ shutdownOnInterrupt();
+
+ //
+ // Create a proxy for the root directory
+ //
+ DirectoryPrx rootDir = DirectoryPrxHelper.checkedCast(communicator().propertyToProxy("RootDir.Proxy"));
+ if(rootDir == null)
+ {
+ throw new Error("Client: invalid proxy");
+ }
+
+ Parser p = new Parser(rootDir);
+ return p.parse();
+ }
+
+ static public void
+ main(String[] args)
+ {
+ Client app = new Client();
+ app.main("demo.book.evictor_filesystem.Client", args, "config.client");
+ }
+
+ static private class Error extends RuntimeException
+ {
+ public Error(String msg)
+ {
+ super(msg);
+ }
+ }
+}
diff --git a/java/demo/Manual/evictor_filesystem/DirectoryI.java b/java/demo/Manual/evictor_filesystem/DirectoryI.java
new file mode 100644
index 00000000000..73074c8b5ec
--- /dev/null
+++ b/java/demo/Manual/evictor_filesystem/DirectoryI.java
@@ -0,0 +1,170 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2014 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 final class DirectoryI extends PersistentDirectory
+{
+ public
+ DirectoryI()
+ {
+ _destroyed = false;
+ nodes = new java.util.HashMap<java.lang.String, NodeDesc>();
+ }
+
+ @Override
+ public synchronized String
+ name(Ice.Current current)
+ {
+ if(_destroyed)
+ {
+ throw new Ice.ObjectNotExistException(current.id, current.facet, current.operation);
+ }
+
+ return nodeName;
+ }
+
+ @Override
+ public void
+ destroy(Ice.Current current)
+ throws PermissionDenied
+ {
+ if(parent == null)
+ {
+ throw new PermissionDenied("Cannot destroy root directory");
+ }
+
+ synchronized(this)
+ {
+ if(_destroyed)
+ {
+ throw new Ice.ObjectNotExistException(current.id, current.facet, current.operation);
+ }
+ if(!nodes.isEmpty())
+ {
+ throw new PermissionDenied("Cannot destroy non-empty directory");
+ }
+ _destroyed = true;
+ }
+
+ //
+ // Because we use a transactional evictor, these updates are guaranteed to be atomic.
+ //
+ parent.removeNode(nodeName);
+ _evictor.remove(current.id);
+ }
+
+ @Override
+ public synchronized NodeDesc[]
+ list(Ice.Current current)
+ {
+ if(_destroyed)
+ {
+ throw new Ice.ObjectNotExistException(current.id, current.facet, current.operation);
+ }
+
+ NodeDesc[] result = new NodeDesc[nodes.size()];
+ int i = 0;
+ java.util.Iterator<NodeDesc> p = nodes.values().iterator();
+ while(p.hasNext())
+ {
+ result[i++] = p.next();
+ }
+ return result;
+ }
+
+ @Override
+ public synchronized NodeDesc
+ find(String name, Ice.Current current)
+ throws NoSuchName
+ {
+ if(_destroyed)
+ {
+ throw new Ice.ObjectNotExistException(current.id, current.facet, current.operation);
+ }
+
+ if(!nodes.containsKey(name))
+ {
+ throw new NoSuchName(name);
+ }
+
+ return nodes.get(name);
+ }
+
+ @Override
+ public synchronized DirectoryPrx
+ createDirectory(String name, Ice.Current current)
+ throws NameInUse
+ {
+ if(_destroyed)
+ {
+ throw new Ice.ObjectNotExistException(current.id, current.facet, current.operation);
+ }
+
+ if(name.length() == 0 || nodes.containsKey(name))
+ {
+ throw new NameInUse(name);
+ }
+
+ Ice.Identity id = current.adapter.getCommunicator().stringToIdentity(java.util.UUID.randomUUID().toString());
+ PersistentDirectory dir = new DirectoryI();
+ dir.nodeName = name;
+ dir.parent = PersistentDirectoryPrxHelper.uncheckedCast(current.adapter.createProxy(current.id));
+ DirectoryPrx proxy = DirectoryPrxHelper.uncheckedCast(_evictor.add(dir, id));
+
+ NodeDesc nd = new NodeDesc();
+ nd.name = name;
+ nd.type = NodeType.DirType;
+ nd.proxy = proxy;
+ nodes.put(name, nd);
+
+ return proxy;
+ }
+
+ @Override
+ public synchronized FilePrx
+ createFile(String name, Ice.Current current)
+ throws NameInUse
+ {
+ if(_destroyed)
+ {
+ throw new Ice.ObjectNotExistException(current.id, current.facet, current.operation);
+ }
+
+ if(name.length() == 0 || nodes.containsKey(name))
+ {
+ throw new NameInUse(name);
+ }
+
+ Ice.Identity id = current.adapter.getCommunicator().stringToIdentity(java.util.UUID.randomUUID().toString());
+ PersistentFile file = new FileI();
+ file.nodeName = name;
+ file.parent = PersistentDirectoryPrxHelper.uncheckedCast(current.adapter.createProxy(current.id));
+ FilePrx proxy = FilePrxHelper.uncheckedCast(_evictor.add(file, id));
+
+ NodeDesc nd = new NodeDesc();
+ nd.name = name;
+ nd.type = NodeType.FileType;
+ nd.proxy = proxy;
+ nodes.put(name, nd);
+
+ return proxy;
+ }
+
+ @Override
+ public synchronized void
+ removeNode(String name, Ice.Current current)
+ {
+ assert(nodes.containsKey(name));
+ nodes.remove(name);
+ }
+
+ public static Freeze.Evictor _evictor;
+ private boolean _destroyed;
+}
diff --git a/java/demo/Manual/evictor_filesystem/FileI.java b/java/demo/Manual/evictor_filesystem/FileI.java
new file mode 100644
index 00000000000..f8904d52490
--- /dev/null
+++ b/java/demo/Manual/evictor_filesystem/FileI.java
@@ -0,0 +1,80 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2014 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 final class FileI extends PersistentFile
+{
+ public
+ FileI()
+ {
+ _destroyed = false;
+ }
+
+ @Override
+ public synchronized String
+ name(Ice.Current current)
+ {
+ if(_destroyed)
+ {
+ throw new Ice.ObjectNotExistException(current.id, current.facet, current.operation);
+ }
+
+ return nodeName;
+ }
+
+ @Override
+ public void
+ destroy(Ice.Current current)
+ throws PermissionDenied
+ {
+ synchronized(this)
+ {
+ if(_destroyed)
+ {
+ throw new Ice.ObjectNotExistException(current.id, current.facet, current.operation);
+ }
+ _destroyed = true;
+ }
+
+ //
+ // Because we use a transactional evictor, these updates are guaranteed to be atomic.
+ //
+ parent.removeNode(nodeName);
+ _evictor.remove(current.id);
+ }
+
+ @Override
+ public synchronized String[]
+ read(Ice.Current current)
+ {
+ if(_destroyed)
+ {
+ throw new Ice.ObjectNotExistException(current.id, current.facet, current.operation);
+ }
+
+ return text.clone();
+ }
+
+ @Override
+ public synchronized void
+ write(String[] text, Ice.Current current)
+ throws GenericError
+ {
+ if(_destroyed)
+ {
+ throw new Ice.ObjectNotExistException(current.id, current.facet, current.operation);
+ }
+
+ this.text = text;
+ }
+
+ public static Freeze.Evictor _evictor;
+ private boolean _destroyed;
+}
diff --git a/java/demo/Manual/evictor_filesystem/Filesystem.ice b/java/demo/Manual/evictor_filesystem/Filesystem.ice
new file mode 100644
index 00000000000..bb84720f462
--- /dev/null
+++ b/java/demo/Manual/evictor_filesystem/Filesystem.ice
@@ -0,0 +1,63 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2014 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.
+//
+// **********************************************************************
+
+#pragma once
+
+module Filesystem
+{
+ exception GenericError
+ {
+ string reason;
+ };
+ exception PermissionDenied extends GenericError {};
+ exception NameInUse extends GenericError {};
+ exception NoSuchName extends GenericError {};
+
+ interface Node
+ {
+ idempotent string name();
+
+ ["freeze:write"]
+ void destroy() throws PermissionDenied;
+ };
+
+ sequence<string> Lines;
+
+ interface File extends Node
+ {
+ idempotent Lines read();
+
+ ["freeze:write"]
+ 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;
+
+ ["freeze:write"]
+ File* createFile(string name) throws NameInUse;
+
+ ["freeze:write"]
+ Directory* createDirectory(string name) throws NameInUse;
+ };
+};
diff --git a/java/demo/Manual/evictor_filesystem/Grammar.java b/java/demo/Manual/evictor_filesystem/Grammar.java
new file mode 100644
index 00000000000..16234c61ea5
--- /dev/null
+++ b/java/demo/Manual/evictor_filesystem/Grammar.java
@@ -0,0 +1,202 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2014 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(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(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/Manual/evictor_filesystem/NodeFactory.java b/java/demo/Manual/evictor_filesystem/NodeFactory.java
new file mode 100644
index 00000000000..80669a9bde2
--- /dev/null
+++ b/java/demo/Manual/evictor_filesystem/NodeFactory.java
@@ -0,0 +1,38 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2014 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 NodeFactory implements Ice.ObjectFactory
+{
+ @Override
+ public Ice.Object
+ create(String type)
+ {
+ if(type.equals(PersistentFile.ice_staticId()))
+ {
+ return new FileI();
+ }
+ else if(type.equals(PersistentDirectory.ice_staticId()))
+ {
+ return new DirectoryI();
+ }
+ else
+ {
+ assert(false);
+ return null;
+ }
+ }
+
+ @Override
+ public void
+ destroy()
+ {
+ }
+}
diff --git a/java/demo/Manual/evictor_filesystem/Parser.java b/java/demo/Manual/evictor_filesystem/Parser.java
new file mode 100644
index 00000000000..8e89bed9a13
--- /dev/null
+++ b/java/demo/Manual/evictor_filesystem/Parser.java
@@ -0,0 +1,349 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2014 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)
+ {
+ StringBuilder b = new StringBuilder();
+ 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();
+
+ for(String name : names)
+ {
+ 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();
+
+ for(String name : names)
+ {
+ 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 = args.toArray(new String[0]);
+ 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();
+
+ for(String name : names)
+ {
+ if(name.equals("*"))
+ {
+ NodeDesc[] nodes = dir.list();
+ for(NodeDesc node : nodes)
+ {
+ try
+ {
+ node.proxy.destroy();
+ }
+ catch(PermissionDenied ex)
+ {
+ System.out.println("cannot remove `" + node.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/Manual/evictor_filesystem/PersistentFilesystem.ice b/java/demo/Manual/evictor_filesystem/PersistentFilesystem.ice
new file mode 100644
index 00000000000..07b7d43c382
--- /dev/null
+++ b/java/demo/Manual/evictor_filesystem/PersistentFilesystem.ice
@@ -0,0 +1,38 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2014 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.
+//
+// **********************************************************************
+
+#pragma once
+
+#include <Filesystem.ice>
+
+module Filesystem
+{
+ class PersistentDirectory;
+
+ class PersistentNode implements Node
+ {
+ string nodeName;
+ PersistentDirectory* parent;
+ };
+
+ class PersistentFile extends PersistentNode implements File
+ {
+ Lines text;
+ };
+
+ dictionary<string, NodeDesc> NodeDict;
+
+ class PersistentDirectory extends PersistentNode implements Directory
+ {
+ ["freeze:write"]
+ void removeNode(string name);
+
+ NodeDict nodes;
+ };
+};
diff --git a/java/demo/Manual/evictor_filesystem/README b/java/demo/Manual/evictor_filesystem/README
new file mode 100644
index 00000000000..73ff1f9f14d
--- /dev/null
+++ b/java/demo/Manual/evictor_filesystem/README
@@ -0,0 +1,11 @@
+This demo presents an alternate implementation of the filesystem
+application using a Freeze evictor, as discussed in the Freeze chapter
+of the Ice manual.
+
+To run it, start the server in a window:
+
+$ java -jar build/libs/server.jar
+
+Then run the client in a separate window:
+
+$ java -jar build/libs/client.jar
diff --git a/java/demo/Manual/evictor_filesystem/Scanner.java b/java/demo/Manual/evictor_filesystem/Scanner.java
new file mode 100644
index 00000000000..2b81fcfd450
--- /dev/null
+++ b/java/demo/Manual/evictor_filesystem/Scanner.java
@@ -0,0 +1,283 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2014 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;
+ }
+
+ StringBuilder buf = new StringBuilder(128);
+
+ 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/Manual/evictor_filesystem/Server.java b/java/demo/Manual/evictor_filesystem/Server.java
new file mode 100644
index 00000000000..93449bf215c
--- /dev/null
+++ b/java/demo/Manual/evictor_filesystem/Server.java
@@ -0,0 +1,82 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2014 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 Server extends Ice.Application
+{
+ public
+ Server(String envName)
+ {
+ _envName = envName;
+ }
+
+ @Override
+ public int
+ run(String[] args)
+ {
+ //
+ // Install object factories.
+ //
+ Ice.ObjectFactory factory = new NodeFactory();
+ communicator().addObjectFactory(factory, PersistentFile.ice_staticId());
+ communicator().addObjectFactory(factory, PersistentDirectory.ice_staticId());
+
+ //
+ // Create an object adapter.
+ //
+ Ice.ObjectAdapter adapter = communicator().createObjectAdapter("EvictorFilesystem");
+
+ //
+ // Create the Freeze evictor (stored in the _evictor
+ // static member).
+ //
+ Freeze.Evictor evictor = Freeze.Util.createTransactionalEvictor(adapter, _envName, "evictorfs",
+ null, null, null, true);
+ DirectoryI._evictor = evictor;
+ FileI._evictor = evictor;
+
+ adapter.addServantLocator(evictor, "");
+
+ //
+ // Create the root node if it doesn't exist.
+ //
+ Ice.Identity rootId = new Ice.Identity();
+ rootId.name = "RootDir";
+ if(!evictor.hasObject(rootId))
+ {
+ PersistentDirectory root = new DirectoryI();
+ root.nodeName = "/";
+ root.nodes = new java.util.HashMap<java.lang.String, NodeDesc>();
+ evictor.add(root, rootId);
+ }
+
+ //
+ // 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("demo.book.evictor_filesystem.Server", args, "config.server");
+ System.exit(status);
+ }
+
+ private String _envName;
+}
diff --git a/java/demo/Manual/evictor_filesystem/Token.java b/java/demo/Manual/evictor_filesystem/Token.java
new file mode 100644
index 00000000000..7a538343d6c
--- /dev/null
+++ b/java/demo/Manual/evictor_filesystem/Token.java
@@ -0,0 +1,40 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2014 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/Manual/evictor_filesystem/config.client b/java/demo/Manual/evictor_filesystem/config.client
new file mode 100644
index 00000000000..640cfade4f1
--- /dev/null
+++ b/java/demo/Manual/evictor_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 -h localhost -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/Manual/evictor_filesystem/config.server b/java/demo/Manual/evictor_filesystem/config.server
new file mode 100644
index 00000000000..69e536ab202
--- /dev/null
+++ b/java/demo/Manual/evictor_filesystem/config.server
@@ -0,0 +1,49 @@
+#
+# Configure the server endpoints.
+#
+EvictorFilesystem.Endpoints=default -h localhost -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/Manual/evictor_filesystem/demo_manual_evictor_filesystem.iml b/java/demo/Manual/evictor_filesystem/demo_manual_evictor_filesystem.iml
new file mode 100644
index 00000000000..e32f5e3b556
--- /dev/null
+++ b/java/demo/Manual/evictor_filesystem/demo_manual_evictor_filesystem.iml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<module external.linked.project.path="$MODULE_DIR$" external.root.project.path="$MODULE_DIR$/../../.." external.system.id="GRADLE" external.system.module.group="java" external.system.module.version="unspecified" type="JAVA_MODULE" version="4">
+ <component name="NewModuleRootManager" inherit-compiler-output="false">
+ <output url="file://$MODULE_DIR$/build/classes" />
+ <output-test url="file://$MODULE_DIR$/build/classes/test" />
+ <exclude-output />
+ <content url="file://$MODULE_DIR$">
+ <sourceFolder url="file://$MODULE_DIR$" isTestSource="false" />
+ <sourceFolder url="file://$MODULE_DIR$/src/main/java" isTestSource="false" />
+ <sourceFolder url="file://$MODULE_DIR$/build/generated-src" isTestSource="false" />
+ <sourceFolder url="file://$MODULE_DIR$/src/test/java" isTestSource="true" />
+ <sourceFolder url="file://$MODULE_DIR$/src/main/resources" type="java-resource" />
+ <sourceFolder url="file://$MODULE_DIR$/src/test/resources" type="java-test-resource" />
+ <excludeFolder url="file://$MODULE_DIR$/.gradle" />
+ <excludeFolder url="file://$MODULE_DIR$/build/dependency-cache" />
+ <excludeFolder url="file://$MODULE_DIR$/build/tmp" />
+ </content>
+ <orderEntry type="inheritedJdk" />
+ <orderEntry type="sourceFolder" forTests="false" />
+ <orderEntry type="module" module-name="Ice" exported="" />
+ <orderEntry type="module" module-name="Freeze" exported="" />
+ </component>
+</module>
+
diff --git a/java/demo/Manual/evictor_filesystem/expect.py b/java/demo/Manual/evictor_filesystem/expect.py
new file mode 100755
index 00000000000..bcd9eb26f47
--- /dev/null
+++ b/java/demo/Manual/evictor_filesystem/expect.py
@@ -0,0 +1,34 @@
+#!/usr/bin/env python
+# **********************************************************************
+#
+# Copyright (c) 2003-2014 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
+
+path = [ ".", "..", "../..", "../../..", "../../../.." ]
+head = os.path.dirname(sys.argv[0])
+if len(head) > 0:
+ path = [os.path.join(head, p) for p in path]
+path = [os.path.abspath(p) for p in path if os.path.exists(os.path.join(p, "demoscript")) ]
+if len(path) == 0:
+ raise RuntimeError("can't find toplevel directory!")
+sys.path.append(path[0])
+
+from demoscript import Util
+from demoscript.manual import evictor_filesystem
+
+sys.stdout.write("cleaning databases... ")
+sys.stdout.flush()
+Util.cleanDbDir("db")
+print("ok")
+
+server = Util.spawn('java -jar build/libs/server.jar --Ice.PrintAdapterReady')
+server.expect('.* ready')
+client = Util.spawn('java -jar build/libs/client.jar')
+
+evictor_filesystem.run(client, server)
diff --git a/java/demo/Manual/lifecycle/.externalToolBuilders/demo.book.lifecycle.slice.launch b/java/demo/Manual/lifecycle/.externalToolBuilders/demo.book.lifecycle.slice.launch
new file mode 100644
index 00000000000..f4da860e3df
--- /dev/null
+++ b/java/demo/Manual/lifecycle/.externalToolBuilders/demo.book.lifecycle.slice.launch
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<launchConfiguration type="org.eclipse.ant.AntBuilderLaunchConfigurationType">
+<stringAttribute key="org.eclipse.ant.ui.ATTR_ANT_AUTO_TARGETS" value="generate,"/>
+<stringAttribute key="org.eclipse.ant.ui.ATTR_ANT_CLEAN_TARGETS" value="clean,"/>
+<stringAttribute key="org.eclipse.ant.ui.ATTR_ANT_MANUAL_TARGETS" value="generate,"/>
+<booleanAttribute key="org.eclipse.ant.ui.ATTR_TARGETS_UPDATED" value="true"/>
+<booleanAttribute key="org.eclipse.ant.ui.DEFAULT_VM_INSTALL" value="false"/>
+<stringAttribute key="org.eclipse.debug.core.ATTR_REFRESH_SCOPE" value="${project}"/>
+<booleanAttribute key="org.eclipse.debug.ui.ATTR_LAUNCH_IN_BACKGROUND" value="false"/>
+<stringAttribute key="org.eclipse.jdt.launching.CLASSPATH_PROVIDER" value="org.eclipse.ant.ui.AntClasspathProvider"/>
+<booleanAttribute key="org.eclipse.jdt.launching.DEFAULT_CLASSPATH" value="true"/>
+<stringAttribute key="org.eclipse.jdt.launching.PROJECT_ATTR" value="demo.book.lifecycle"/>
+<stringAttribute key="org.eclipse.ui.externaltools.ATTR_BUILD_SCOPE" value="${working_set:&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;&#10;&lt;resources&gt;&#10;&lt;item path=&quot;/demo.book.lifecycle/Filesystem.ice&quot; type=&quot;1&quot;/&gt;&#10;&lt;/resources&gt;}"/>
+<stringAttribute key="org.eclipse.ui.externaltools.ATTR_LOCATION" value="${workspace_loc:/demo.book.lifecycle/build.xml}"/>
+<stringAttribute key="org.eclipse.ui.externaltools.ATTR_RUN_BUILD_KINDS" value="incremental,auto,clean"/>
+<booleanAttribute key="org.eclipse.ui.externaltools.ATTR_TRIGGERS_CONFIGURED" value="true"/>
+</launchConfiguration>
diff --git a/java/demo/Manual/lifecycle/Client.java b/java/demo/Manual/lifecycle/Client.java
new file mode 100644
index 00000000000..aac2733bc58
--- /dev/null
+++ b/java/demo/Manual/lifecycle/Client.java
@@ -0,0 +1,55 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2014 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
+{
+ @Override
+ 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 -h localhost -p 10000");
+
+ //
+ // 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/Manual/lifecycle/Filesystem.ice b/java/demo/Manual/lifecycle/Filesystem.ice
new file mode 100644
index 00000000000..a62086add45
--- /dev/null
+++ b/java/demo/Manual/lifecycle/Filesystem.ice
@@ -0,0 +1,54 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2014 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.
+//
+// **********************************************************************
+
+#pragma once
+
+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;
+ };
+};
diff --git a/java/demo/Manual/lifecycle/FilesystemI/DirectoryI.java b/java/demo/Manual/lifecycle/FilesystemI/DirectoryI.java
new file mode 100644
index 00000000000..005871ed897
--- /dev/null
+++ b/java/demo/Manual/lifecycle/FilesystemI/DirectoryI.java
@@ -0,0 +1,189 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2014 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
+{
+
+ // Slice name() operation.
+
+ public synchronized String
+ name(Current c)
+ {
+ if(_destroyed)
+ {
+ throw new ObjectNotExistException();
+ }
+ return _name;
+ }
+
+ // Return the object identity for this node.
+
+ public Identity
+ id()
+ {
+ return _id;
+ }
+
+ // Slice list() operation.
+
+ public synchronized NodeDesc[]
+ list(Current c)
+ {
+ if(_destroyed)
+ {
+ throw new ObjectNotExistException();
+ }
+
+ NodeDesc[] ret = new NodeDesc[_contents.size()];
+ java.util.Iterator<java.util.Map.Entry<String, NodeI> > pos = _contents.entrySet().iterator();
+ for(int i = 0; i < _contents.size(); ++i)
+ {
+ java.util.Map.Entry<String, NodeI> e = pos.next();
+ NodeI p = e.getValue();
+ ret[i] = new NodeDesc();
+ ret[i].name = e.getKey();
+ ret[i].type = p instanceof FileI ? NodeType.FileType : NodeType.DirType;
+ ret[i].proxy = NodePrxHelper.uncheckedCast(c.adapter.createProxy(p.id()));
+ }
+ return ret;
+ }
+
+ // Slice find() operation.
+
+ public synchronized NodeDesc
+ find(String name, Current c) throws NoSuchName
+ {
+ if(_destroyed)
+ {
+ throw new ObjectNotExistException();
+ }
+
+ NodeI p = _contents.get(name);
+ if(p == null)
+ {
+ throw new NoSuchName(name);
+ }
+
+ NodeDesc d = new NodeDesc();
+ d.name = name;
+ d.type = p instanceof FileI ? NodeType.FileType : NodeType.DirType;
+ d.proxy = NodePrxHelper.uncheckedCast(c.adapter.createProxy(p.id()));
+ return d;
+ }
+
+ // Slice createFile() operation.
+
+ public synchronized FilePrx
+ createFile(String name, Current c) throws NameInUse
+ {
+ if(_destroyed)
+ {
+ throw new ObjectNotExistException();
+ }
+
+ if(name.length() == 0 || _contents.containsKey(name))
+ {
+ throw new NameInUse(name);
+ }
+
+ FileI f = new FileI(name, this);
+ ObjectPrx node = c.adapter.add(f, f.id());
+ _contents.put(name, f);
+ return FilePrxHelper.uncheckedCast(node);
+ }
+
+ // Slice createDirectory() operation.
+
+ public synchronized DirectoryPrx
+ createDirectory(String name, Current c) throws NameInUse
+ {
+ if(_destroyed)
+ {
+ throw new ObjectNotExistException();
+ }
+
+ if(name.length() == 0 || _contents.containsKey(name))
+ {
+ throw new NameInUse(name);
+ }
+
+ DirectoryI d = new DirectoryI(name, this);
+ ObjectPrx node = c.adapter.add(d, d.id());
+ _contents.put(name, d);
+ return DirectoryPrxHelper.uncheckedCast(node);
+ }
+
+ // 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();
+ }
+
+ if(_contents.size() != 0)
+ {
+ throw new PermissionDenied("Cannot destroy non-empty directory");
+ }
+
+ c.adapter.remove(id());
+ _destroyed = true;
+ }
+
+ _parent.removeEntry(_name);
+ }
+
+ // DirectoryI constructor for root directory.
+
+ public DirectoryI()
+ {
+ this("/", null);
+ }
+
+ // DirectoryI constructor. parent == null indicates root directory.
+
+ public DirectoryI(String name, DirectoryI parent)
+ {
+ _name = name;
+ _parent = parent;
+ _id = new Identity();
+ _destroyed = false;
+ _contents = new java.util.HashMap<String, NodeI>();
+
+ _id.name = parent == null ? "RootDir" : java.util.UUID.randomUUID().toString();
+ }
+
+ // Remove the entry from the _contents map.
+
+ public synchronized void
+ removeEntry(String name)
+ {
+ _contents.remove(name);
+ }
+
+ private String _name; // Immutable
+ private DirectoryI _parent; // Immutable
+ private Identity _id; // Immutable
+ private boolean _destroyed;
+ private java.util.Map<String, NodeI> _contents;
+}
diff --git a/java/demo/Manual/lifecycle/FilesystemI/FileI.java b/java/demo/Manual/lifecycle/FilesystemI/FileI.java
new file mode 100644
index 00000000000..7912d4bc83e
--- /dev/null
+++ b/java/demo/Manual/lifecycle/FilesystemI/FileI.java
@@ -0,0 +1,86 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2014 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 FileI extends _FileDisp implements NodeI
+{
+ public synchronized String
+ name(Current c)
+ {
+ if(_destroyed)
+ {
+ throw new ObjectNotExistException();
+ }
+ return _name;
+ }
+
+ public Identity
+ id()
+ {
+ return _id;
+ }
+
+ public synchronized String[]
+ read(Current c)
+ {
+ if(_destroyed)
+ {
+ throw new ObjectNotExistException();
+ }
+
+ return _lines;
+ }
+
+ public synchronized void
+ write(String[] text, Current c)
+ {
+ if(_destroyed)
+ {
+ throw new ObjectNotExistException();
+ }
+
+ _lines = (String[])text.clone();
+ }
+
+ public void
+ destroy(Current c)
+ {
+ synchronized(this)
+ {
+ if(_destroyed)
+ {
+ throw new ObjectNotExistException();
+ }
+
+ c.adapter.remove(id());
+ _destroyed = true;
+ }
+
+ _parent.removeEntry(_name);
+ }
+
+ public FileI(String name, DirectoryI parent)
+ {
+ _name = name;
+ _parent = parent;
+ _destroyed = false;
+ _id = new Identity();
+ _id.name = java.util.UUID.randomUUID().toString();
+ }
+
+ private String _name;
+ private DirectoryI _parent;
+ private boolean _destroyed;
+ private Identity _id;
+ private String[] _lines;
+}
diff --git a/java/demo/Manual/lifecycle/FilesystemI/NodeI.java b/java/demo/Manual/lifecycle/FilesystemI/NodeI.java
new file mode 100644
index 00000000000..33786ce60f6
--- /dev/null
+++ b/java/demo/Manual/lifecycle/FilesystemI/NodeI.java
@@ -0,0 +1,15 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2014 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();
+}
diff --git a/java/demo/Manual/lifecycle/Grammar.java b/java/demo/Manual/lifecycle/Grammar.java
new file mode 100644
index 00000000000..16234c61ea5
--- /dev/null
+++ b/java/demo/Manual/lifecycle/Grammar.java
@@ -0,0 +1,202 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2014 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(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(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/Manual/lifecycle/Parser.java b/java/demo/Manual/lifecycle/Parser.java
new file mode 100644
index 00000000000..8e89bed9a13
--- /dev/null
+++ b/java/demo/Manual/lifecycle/Parser.java
@@ -0,0 +1,349 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2014 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)
+ {
+ StringBuilder b = new StringBuilder();
+ 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();
+
+ for(String name : names)
+ {
+ 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();
+
+ for(String name : names)
+ {
+ 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 = args.toArray(new String[0]);
+ 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();
+
+ for(String name : names)
+ {
+ if(name.equals("*"))
+ {
+ NodeDesc[] nodes = dir.list();
+ for(NodeDesc node : nodes)
+ {
+ try
+ {
+ node.proxy.destroy();
+ }
+ catch(PermissionDenied ex)
+ {
+ System.out.println("cannot remove `" + node.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/Manual/lifecycle/README b/java/demo/Manual/lifecycle/README
new file mode 100644
index 00000000000..ea985301bfd
--- /dev/null
+++ b/java/demo/Manual/lifecycle/README
@@ -0,0 +1,11 @@
+This demo implements the file system with life cycle support.
+
+To run it, start the server in a window:
+
+$ java -jar build/libs/server.jar
+
+Then run the client in a separate window:
+
+$ java -jar build/libs/client.jar
+
+Type "help" at the client prompt to see a list of commands.
diff --git a/java/demo/Manual/lifecycle/Scanner.java b/java/demo/Manual/lifecycle/Scanner.java
new file mode 100644
index 00000000000..2b81fcfd450
--- /dev/null
+++ b/java/demo/Manual/lifecycle/Scanner.java
@@ -0,0 +1,283 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2014 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;
+ }
+
+ StringBuilder buf = new StringBuilder(128);
+
+ 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/Manual/lifecycle/Server.java b/java/demo/Manual/lifecycle/Server.java
new file mode 100644
index 00000000000..2a5fe5d103a
--- /dev/null
+++ b/java/demo/Manual/lifecycle/Server.java
@@ -0,0 +1,60 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2014 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 FilesystemI.*;
+
+class Server extends Ice.Application
+{
+ @Override
+ public int
+ run(String[] args)
+ {
+ //
+ // Terminate cleanly on receipt of a signal.
+ //
+ shutdownOnInterrupt();
+
+ //
+ // Create an object adapter
+ //
+ Ice.ObjectAdapter adapter = communicator().createObjectAdapterWithEndpoints(
+ "LifecycleFilesystem", "default -h localhost -p 10000");
+
+ //
+ // Create the root directory.
+ //
+ DirectoryI root = new DirectoryI();
+ Ice.Identity id = new Ice.Identity();
+ id.name = "RootDir";
+ adapter.add(root, id);
+
+ //
+ // All objects are created, allow client requests now.
+ //
+ adapter.activate();
+
+ //
+ // Wait until we are done.
+ //
+ communicator().waitForShutdown();
+ if(interrupted())
+ {
+ System.err.println(appName() + ": received signal, shutting down");
+ }
+
+ return 0;
+ }
+
+ static public void
+ main(String[] args)
+ {
+ Server app = new Server();
+ app.main("demo.book.lifecycle.Server", args);
+ }
+}
diff --git a/java/demo/Manual/lifecycle/Token.java b/java/demo/Manual/lifecycle/Token.java
new file mode 100644
index 00000000000..7a538343d6c
--- /dev/null
+++ b/java/demo/Manual/lifecycle/Token.java
@@ -0,0 +1,40 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2014 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/Manual/lifecycle/demo_manual_lifecycle.iml b/java/demo/Manual/lifecycle/demo_manual_lifecycle.iml
new file mode 100644
index 00000000000..b6dce281ba2
--- /dev/null
+++ b/java/demo/Manual/lifecycle/demo_manual_lifecycle.iml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<module external.linked.project.path="$MODULE_DIR$" external.root.project.path="$MODULE_DIR$/../../.." external.system.id="GRADLE" external.system.module.group="java" external.system.module.version="unspecified" type="JAVA_MODULE" version="4">
+ <component name="NewModuleRootManager" inherit-compiler-output="false">
+ <output url="file://$MODULE_DIR$/build/classes" />
+ <output-test url="file://$MODULE_DIR$/build/classes/test" />
+ <exclude-output />
+ <content url="file://$MODULE_DIR$">
+ <sourceFolder url="file://$MODULE_DIR$/build/generated-src" isTestSource="false" />
+ <sourceFolder url="file://$MODULE_DIR$/src/main/java" isTestSource="false" />
+ <sourceFolder url="file://$MODULE_DIR$" isTestSource="false" />
+ <sourceFolder url="file://$MODULE_DIR$/src/test/java" isTestSource="true" />
+ <sourceFolder url="file://$MODULE_DIR$/src/main/resources" type="java-resource" />
+ <sourceFolder url="file://$MODULE_DIR$/src/test/resources" type="java-test-resource" />
+ <excludeFolder url="file://$MODULE_DIR$/.gradle" />
+ <excludeFolder url="file://$MODULE_DIR$/build/dependency-cache" />
+ <excludeFolder url="file://$MODULE_DIR$/build/tmp" />
+ </content>
+ <orderEntry type="inheritedJdk" />
+ <orderEntry type="sourceFolder" forTests="false" />
+ <orderEntry type="module" module-name="Ice" exported="" />
+ </component>
+</module>
+
diff --git a/java/demo/Manual/lifecycle/expect.py b/java/demo/Manual/lifecycle/expect.py
new file mode 100755
index 00000000000..ef248a53559
--- /dev/null
+++ b/java/demo/Manual/lifecycle/expect.py
@@ -0,0 +1,29 @@
+#!/usr/bin/env python
+# **********************************************************************
+#
+# Copyright (c) 2003-2014 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
+
+path = [ ".", "..", "../..", "../../..", "../../../.." ]
+head = os.path.dirname(sys.argv[0])
+if len(head) > 0:
+ path = [os.path.join(head, p) for p in path]
+path = [os.path.abspath(p) for p in path if os.path.exists(os.path.join(p, "demoscript")) ]
+if len(path) == 0:
+ raise RuntimeError("can't find toplevel directory!")
+sys.path.append(path[0])
+
+from demoscript import Util
+from demoscript.manual import lifecycle
+
+server = Util.spawn('java -jar build/libs/server.jar --Ice.PrintAdapterReady')
+server.expect('.* ready')
+client = Util.spawn('java -jar build/libs/client.jar')
+
+lifecycle.run(client, server)
diff --git a/java/demo/Manual/map_filesystem/.externalToolBuilders/demo.book.map_filesystem.launch b/java/demo/Manual/map_filesystem/.externalToolBuilders/demo.book.map_filesystem.launch
new file mode 100644
index 00000000000..abe7897ac17
--- /dev/null
+++ b/java/demo/Manual/map_filesystem/.externalToolBuilders/demo.book.map_filesystem.launch
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<launchConfiguration type="org.eclipse.ant.AntBuilderLaunchConfigurationType">
+<stringAttribute key="org.eclipse.ant.ui.ATTR_ANT_AUTO_TARGETS" value="generate,"/>
+<stringAttribute key="org.eclipse.ant.ui.ATTR_ANT_CLEAN_TARGETS" value="clean,"/>
+<stringAttribute key="org.eclipse.ant.ui.ATTR_ANT_MANUAL_TARGETS" value="generate,"/>
+<booleanAttribute key="org.eclipse.ant.ui.ATTR_TARGETS_UPDATED" value="true"/>
+<booleanAttribute key="org.eclipse.ant.ui.DEFAULT_VM_INSTALL" value="false"/>
+<stringAttribute key="org.eclipse.debug.core.ATTR_REFRESH_SCOPE" value="${project}"/>
+<booleanAttribute key="org.eclipse.debug.ui.ATTR_LAUNCH_IN_BACKGROUND" value="false"/>
+<stringAttribute key="org.eclipse.jdt.launching.CLASSPATH_PROVIDER" value="org.eclipse.ant.ui.AntClasspathProvider"/>
+<booleanAttribute key="org.eclipse.jdt.launching.DEFAULT_CLASSPATH" value="true"/>
+<stringAttribute key="org.eclipse.jdt.launching.PROJECT_ATTR" value="demo.book.map_filesystem"/>
+<stringAttribute key="org.eclipse.ui.externaltools.ATTR_BUILD_SCOPE" value="${working_set:&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;&#10;&lt;resources&gt;&#10;&lt;item path=&quot;/demo.book.map_filesystem/Filesystem.ice&quot; type=&quot;1&quot;/&gt;&#10;&lt;item path=&quot;/demo.book.map_filesystem/FilesystemDB.ice&quot; type=&quot;1&quot;/&gt;&#10;&lt;/resources&gt;}"/>
+<stringAttribute key="org.eclipse.ui.externaltools.ATTR_LOCATION" value="${workspace_loc:/demo.book.map_filesystem/build.xml}"/>
+<stringAttribute key="org.eclipse.ui.externaltools.ATTR_RUN_BUILD_KINDS" value="incremental,auto,clean"/>
+<booleanAttribute key="org.eclipse.ui.externaltools.ATTR_TRIGGERS_CONFIGURED" value="true"/>
+</launchConfiguration>
diff --git a/java/demo/Manual/map_filesystem/.gitignore b/java/demo/Manual/map_filesystem/.gitignore
new file mode 100644
index 00000000000..9c39416c539
--- /dev/null
+++ b/java/demo/Manual/map_filesystem/.gitignore
@@ -0,0 +1 @@
+db/*
diff --git a/java/demo/Manual/map_filesystem/Client.java b/java/demo/Manual/map_filesystem/Client.java
new file mode 100644
index 00000000000..2309f6a3b23
--- /dev/null
+++ b/java/demo/Manual/map_filesystem/Client.java
@@ -0,0 +1,50 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2014 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
+{
+ @Override
+ public int
+ run(String[] args)
+ {
+ //
+ // Terminate cleanly on receipt of a signal.
+ //
+ shutdownOnInterrupt();
+
+ //
+ // Create a proxy for the root directory
+ //
+ DirectoryPrx rootDir = DirectoryPrxHelper.checkedCast(communicator().propertyToProxy("RootDir.Proxy"));
+ if(rootDir == null)
+ {
+ throw new Error("Client: invalid proxy");
+ }
+
+ Parser p = new Parser(rootDir);
+ return p.parse();
+ }
+
+ static public void
+ main(String[] args)
+ {
+ Client app = new Client();
+ app.main("demo.book.map_filesystem.Client", args, "config.client");
+ }
+
+ static private class Error extends RuntimeException
+ {
+ public Error(String msg)
+ {
+ super(msg);
+ }
+ }
+}
diff --git a/java/demo/Manual/map_filesystem/DirectoryI.java b/java/demo/Manual/map_filesystem/DirectoryI.java
new file mode 100644
index 00000000000..226814d5981
--- /dev/null
+++ b/java/demo/Manual/map_filesystem/DirectoryI.java
@@ -0,0 +1,407 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2014 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 FilesystemDB.*;
+
+public class DirectoryI extends _DirectoryDisp
+{
+ public
+ DirectoryI(Ice.Communicator communicator, String envName)
+ {
+ _communicator = communicator;
+ _envName = envName;
+
+ Freeze.Connection connection = Freeze.Util.createConnection(_communicator, _envName);
+ try
+ {
+ IdentityDirectoryEntryMap dirDB = new IdentityDirectoryEntryMap(connection, directoriesDB());
+
+ //
+ // Create the record for the root directory if necessary.
+ //
+ for(;;)
+ {
+ try
+ {
+ Ice.Identity rootId = new Ice.Identity("RootDir", "");
+ DirectoryEntry entry = dirDB.get(rootId);
+ if(entry == null)
+ {
+ dirDB.put(rootId, new DirectoryEntry("/", new Ice.Identity("", ""), null));
+ }
+ break;
+ }
+ catch(Freeze.DeadlockException ex)
+ {
+ continue;
+ }
+ catch(Freeze.DatabaseException ex)
+ {
+ halt(ex);
+ }
+ }
+ }
+ finally
+ {
+ connection.close();
+ }
+ }
+
+ @Override
+ public String
+ name(Ice.Current c)
+ {
+ Freeze.Connection connection = Freeze.Util.createConnection(_communicator, _envName);
+ try
+ {
+ IdentityDirectoryEntryMap dirDB = new IdentityDirectoryEntryMap(connection, directoriesDB());
+
+ for(;;)
+ {
+ try
+ {
+ DirectoryEntry entry = dirDB.get(c.id);
+ if(entry == null)
+ {
+ throw new Ice.ObjectNotExistException();
+ }
+ return entry.name;
+ }
+ catch(Freeze.DeadlockException ex)
+ {
+ continue;
+ }
+ catch(Freeze.DatabaseException ex)
+ {
+ halt(ex);
+ }
+ }
+ }
+ finally
+ {
+ connection.close();
+ }
+ }
+
+ @Override
+ public NodeDesc[]
+ list(Ice.Current c)
+ {
+ Freeze.Connection connection = Freeze.Util.createConnection(_communicator, _envName);
+ try
+ {
+ IdentityDirectoryEntryMap dirDB = new IdentityDirectoryEntryMap(connection, directoriesDB());
+
+ for(;;)
+ {
+ try
+ {
+ DirectoryEntry entry = dirDB.get(c.id);
+ if(entry == null)
+ {
+ throw new Ice.ObjectNotExistException();
+ }
+ NodeDesc[] result = new NodeDesc[entry.nodes.size()];
+ java.util.Iterator<NodeDesc> p = entry.nodes.values().iterator();
+ for(int i = 0; i < entry.nodes.size(); ++i)
+ {
+ result[i] = p.next();
+ }
+ return result;
+ }
+ catch(Freeze.DeadlockException ex)
+ {
+ continue;
+ }
+ catch(Freeze.DatabaseException ex)
+ {
+ halt(ex);
+ }
+ }
+ }
+ finally
+ {
+ connection.close();
+ }
+ }
+
+ @Override
+ public NodeDesc
+ find(String name, Ice.Current c)
+ throws NoSuchName
+ {
+ Freeze.Connection connection = Freeze.Util.createConnection(_communicator, _envName);
+ try
+ {
+ IdentityDirectoryEntryMap dirDB = new IdentityDirectoryEntryMap(connection, directoriesDB());
+
+ for(;;)
+ {
+ try
+ {
+ DirectoryEntry entry = dirDB.get(c.id);
+ if(entry == null)
+ {
+ throw new Ice.ObjectNotExistException();
+ }
+ NodeDesc nd = entry.nodes.get(name);
+ if(nd == null)
+ {
+ throw new NoSuchName(name);
+ }
+ return nd;
+ }
+ catch(Freeze.DeadlockException ex)
+ {
+ continue;
+ }
+ catch(Freeze.DatabaseException ex)
+ {
+ halt(ex);
+ }
+ }
+ }
+ finally
+ {
+ connection.close();
+ }
+ }
+
+ @Override
+ public FilePrx
+ createFile(String name, Ice.Current c)
+ throws NameInUse
+ {
+ Freeze.Connection connection = Freeze.Util.createConnection(_communicator, _envName);
+ try
+ {
+ IdentityFileEntryMap fileDB = new IdentityFileEntryMap(connection, FileI.filesDB());
+ IdentityDirectoryEntryMap dirDB = new IdentityDirectoryEntryMap(connection, directoriesDB());
+
+ for(;;)
+ {
+ //
+ // The transaction is necessary since we are altering
+ // two records in one atomic action.
+ //
+ Freeze.Transaction txn = null;
+ try
+ {
+ txn = connection.beginTransaction();
+ DirectoryEntry entry = dirDB.get(c.id);
+ if(entry == null)
+ {
+ throw new Ice.ObjectNotExistException();
+ }
+ if(name.length() == 0 || entry.nodes.get(name) != null)
+ {
+ throw new NameInUse(name);
+ }
+
+ FileEntry newEntry = new FileEntry(name, c.id, null);
+ Ice.Identity id = new Ice.Identity(java.util.UUID.randomUUID().toString(), "file");
+ FilePrx proxy = FilePrxHelper.uncheckedCast(c.adapter.createProxy(id));
+
+ entry.nodes.put(name, new NodeDesc(name, NodeType.FileType, proxy));
+ dirDB.put(c.id, entry);
+
+ fileDB.put(id, newEntry);
+
+ txn.commit();
+ txn = null;
+
+ return proxy;
+ }
+ catch(Freeze.DeadlockException ex)
+ {
+ continue;
+ }
+ catch(Freeze.DatabaseException ex)
+ {
+ halt(ex);
+ }
+ finally
+ {
+ if(txn != null)
+ {
+ txn.rollback();
+ }
+ }
+ }
+ }
+ finally
+ {
+ connection.close();
+ }
+ }
+
+ @Override
+ public DirectoryPrx
+ createDirectory(String name, Ice.Current c)
+ throws NameInUse
+ {
+ Freeze.Connection connection = Freeze.Util.createConnection(_communicator, _envName);
+ try
+ {
+ IdentityDirectoryEntryMap dirDB = new IdentityDirectoryEntryMap(connection, directoriesDB());
+
+ for(;;)
+ {
+ //
+ // The transaction is necessary since we are altering
+ // two records in one atomic action.
+ //
+ Freeze.Transaction txn = null;
+ try
+ {
+ txn = connection.beginTransaction();
+ DirectoryEntry entry = dirDB.get(c.id);
+ if(entry == null)
+ {
+ throw new Ice.ObjectNotExistException();
+ }
+ if(name.length() == 0 || entry.nodes.get(name) != null)
+ {
+ throw new NameInUse(name);
+ }
+
+ DirectoryEntry newEntry = new DirectoryEntry(name, c.id, null);
+ Ice.Identity id = new Ice.Identity(java.util.UUID.randomUUID().toString(), "");
+ DirectoryPrx proxy = DirectoryPrxHelper.uncheckedCast(c.adapter.createProxy(id));
+
+ entry.nodes.put(name, new NodeDesc(name, NodeType.DirType, proxy));
+ dirDB.put(c.id, entry);
+
+ dirDB.put(id, newEntry);
+
+ txn.commit();
+ txn = null;
+
+ return proxy;
+ }
+ catch(Freeze.DeadlockException ex)
+ {
+ continue;
+ }
+ catch(Freeze.DatabaseException ex)
+ {
+ halt(ex);
+ }
+ finally
+ {
+ if(txn != null)
+ {
+ txn.rollback();
+ }
+ }
+ }
+ }
+ finally
+ {
+ connection.close();
+ }
+ }
+
+ @Override
+ public void
+ destroy(Ice.Current c)
+ throws PermissionDenied
+ {
+ Freeze.Connection connection = Freeze.Util.createConnection(_communicator, _envName);
+ try
+ {
+ IdentityDirectoryEntryMap dirDB = new IdentityDirectoryEntryMap(connection, directoriesDB());
+
+ for(;;)
+ {
+ //
+ // The transaction is necessary since we are altering
+ // two records in one atomic action.
+ //
+ Freeze.Transaction txn = null;
+ try
+ {
+ txn = connection.beginTransaction();
+ DirectoryEntry entry = dirDB.get(c.id);
+ if(entry == null)
+ {
+ throw new Ice.ObjectNotExistException();
+ }
+ if(entry.parent.name.length() == 0)
+ {
+ throw new PermissionDenied("Cannot destroy root directory");
+ }
+ if(!entry.nodes.isEmpty())
+ {
+ throw new PermissionDenied("Cannot destroy non-empty directory");
+ }
+
+ DirectoryEntry dirEntry = dirDB.get(entry.parent);
+ if(dirEntry == null)
+ {
+ halt(new Freeze.DatabaseException("consistency error: directory without parent"));
+ }
+
+ dirEntry.nodes.remove(entry.name);
+ dirDB.put(entry.parent, dirEntry);
+
+ dirDB.remove(c.id);
+
+ txn.commit();
+ txn = null;
+ break;
+ }
+ catch(Freeze.DeadlockException ex)
+ {
+ continue;
+ }
+ catch(Freeze.DatabaseException ex)
+ {
+ halt(ex);
+ }
+ finally
+ {
+ if(txn != null)
+ {
+ txn.rollback();
+ }
+ }
+ }
+ }
+ finally
+ {
+ connection.close();
+ }
+ }
+
+ private void
+ halt(Freeze.DatabaseException e)
+ {
+ //
+ // If this is called it's very bad news. We log the error and
+ // then kill the server.
+ //
+ java.io.StringWriter sw = new java.io.StringWriter();
+ java.io.PrintWriter pw = new java.io.PrintWriter(sw);
+ e.printStackTrace(pw);
+ pw.flush();
+ _communicator.getLogger().error("fatal database error\n" + sw.toString() + "\n*** Halting JVM ***");
+ Runtime.getRuntime().halt(1);
+ }
+
+ public static String
+ directoriesDB()
+ {
+ return "directories";
+ }
+
+ private Ice.Communicator _communicator;
+ private String _envName;
+}
diff --git a/java/demo/Manual/map_filesystem/FileI.java b/java/demo/Manual/map_filesystem/FileI.java
new file mode 100644
index 00000000000..33b8ece4e85
--- /dev/null
+++ b/java/demo/Manual/map_filesystem/FileI.java
@@ -0,0 +1,221 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2014 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 FilesystemDB.*;
+
+public class FileI extends _FileDisp
+{
+ public
+ FileI(Ice.Communicator communicator, String envName)
+ {
+ _communicator = communicator;
+ _envName = envName;
+ }
+
+ @Override
+ public String
+ name(Ice.Current c)
+ {
+ Freeze.Connection connection = Freeze.Util.createConnection(_communicator, _envName);
+ try
+ {
+ IdentityFileEntryMap fileDB = new IdentityFileEntryMap(connection, filesDB());
+
+ for(;;)
+ {
+ try
+ {
+ FileEntry entry = fileDB.get(c.id);
+ if(entry == null)
+ {
+ throw new Ice.ObjectNotExistException();
+ }
+ return entry.name;
+ }
+ catch(Freeze.DeadlockException ex)
+ {
+ continue;
+ }
+ catch(Freeze.DatabaseException ex)
+ {
+ halt(ex);
+ }
+ }
+ }
+ finally
+ {
+ connection.close();
+ }
+ }
+
+ @Override
+ public String[]
+ read(Ice.Current c)
+ {
+ Freeze.Connection connection = Freeze.Util.createConnection(_communicator, _envName);
+ try
+ {
+ IdentityFileEntryMap fileDB = new IdentityFileEntryMap(connection, filesDB());
+
+ for(;;)
+ {
+ try
+ {
+ FileEntry entry = fileDB.get(c.id);
+ if(entry == null)
+ {
+ throw new Ice.ObjectNotExistException();
+ }
+ return entry.text;
+ }
+ catch(Freeze.DeadlockException ex)
+ {
+ continue;
+ }
+ catch(Freeze.DatabaseException ex)
+ {
+ halt(ex);
+ }
+ }
+ }
+ finally
+ {
+ connection.close();
+ }
+ }
+
+ @Override
+ public void
+ write(String[] text, Ice.Current c)
+ throws GenericError
+ {
+ Freeze.Connection connection = Freeze.Util.createConnection(_communicator, _envName);
+ try
+ {
+ IdentityFileEntryMap fileDB = new IdentityFileEntryMap(connection, filesDB());
+
+ for(;;)
+ {
+ try
+ {
+ FileEntry entry = fileDB.get(c.id);
+ if(entry == null)
+ {
+ throw new Ice.ObjectNotExistException();
+ }
+ entry.text = text;
+ fileDB.put(c.id, entry);
+ break;
+ }
+ catch(Freeze.DeadlockException ex)
+ {
+ continue;
+ }
+ catch(Freeze.DatabaseException ex)
+ {
+ halt(ex);
+ }
+ }
+ }
+ finally
+ {
+ connection.close();
+ }
+ }
+
+ @Override
+ public void
+ destroy(Ice.Current c)
+ throws PermissionDenied
+ {
+ Freeze.Connection connection = Freeze.Util.createConnection(_communicator, _envName);
+ try
+ {
+ IdentityFileEntryMap fileDB = new IdentityFileEntryMap(connection, filesDB());
+ IdentityDirectoryEntryMap dirDB = new IdentityDirectoryEntryMap(connection, DirectoryI.directoriesDB());
+
+ for(;;)
+ {
+ Freeze.Transaction txn = null;
+ try
+ {
+ //
+ // The transaction is necessary since we are
+ // altering two records in one atomic action.
+ //
+ txn = connection.beginTransaction();
+ FileEntry entry = fileDB.get(c.id);
+ if(entry == null)
+ {
+ throw new Ice.ObjectNotExistException();
+ }
+
+ DirectoryEntry dirEntry = dirDB.get(entry.parent);
+ if(dirEntry == null)
+ {
+ halt(new Freeze.DatabaseException("consistency error: file without parent"));
+ }
+
+ dirEntry.nodes.remove(entry.name);
+ dirDB.put(entry.parent, dirEntry);
+
+ fileDB.remove(c.id);
+
+ txn.commit();
+ txn = null;
+ break;
+ }
+ catch(Freeze.DeadlockException ex)
+ {
+ continue;
+ }
+ catch(Freeze.DatabaseException ex)
+ {
+ halt(ex);
+ }
+ finally
+ {
+ if(txn != null)
+ {
+ txn.rollback();
+ }
+ }
+ }
+ }
+ finally
+ {
+ connection.close();
+ }
+ }
+
+ public static String
+ filesDB()
+ {
+ return "files";
+ }
+
+ private void
+ halt(Freeze.DatabaseException e)
+ {
+ //
+ // If this is called it's very bad news. We log the error and
+ // then kill the server.
+ //
+ java.io.StringWriter sw = new java.io.StringWriter();
+ java.io.PrintWriter pw = new java.io.PrintWriter(sw);
+ e.printStackTrace(pw);
+ pw.flush();
+ _communicator.getLogger().error("fatal database error\n" + sw.toString() + "\n*** Halting JVM ***");
+ Runtime.getRuntime().halt(1);
+ }
+
+ private Ice.Communicator _communicator;
+ private String _envName;
+}
diff --git a/java/demo/Manual/map_filesystem/Filesystem.ice b/java/demo/Manual/map_filesystem/Filesystem.ice
new file mode 100644
index 00000000000..a62086add45
--- /dev/null
+++ b/java/demo/Manual/map_filesystem/Filesystem.ice
@@ -0,0 +1,54 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2014 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.
+//
+// **********************************************************************
+
+#pragma once
+
+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;
+ };
+};
diff --git a/java/demo/Manual/map_filesystem/FilesystemDB.ice b/java/demo/Manual/map_filesystem/FilesystemDB.ice
new file mode 100644
index 00000000000..6e2eef6bcd1
--- /dev/null
+++ b/java/demo/Manual/map_filesystem/FilesystemDB.ice
@@ -0,0 +1,31 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2014 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.
+//
+// **********************************************************************
+
+#pragma once
+
+#include <Filesystem.ice>
+#include <Ice/Identity.ice>
+
+module FilesystemDB
+{
+ struct FileEntry
+ {
+ string name;
+ Ice::Identity parent;
+ Filesystem::Lines text;
+ };
+
+ dictionary<string, Filesystem::NodeDesc> StringNodeDescDict;
+ struct DirectoryEntry
+ {
+ string name;
+ Ice::Identity parent;
+ StringNodeDescDict nodes;
+ };
+};
diff --git a/java/demo/Manual/map_filesystem/Grammar.java b/java/demo/Manual/map_filesystem/Grammar.java
new file mode 100644
index 00000000000..16234c61ea5
--- /dev/null
+++ b/java/demo/Manual/map_filesystem/Grammar.java
@@ -0,0 +1,202 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2014 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(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(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/Manual/map_filesystem/Parser.java b/java/demo/Manual/map_filesystem/Parser.java
new file mode 100644
index 00000000000..8e89bed9a13
--- /dev/null
+++ b/java/demo/Manual/map_filesystem/Parser.java
@@ -0,0 +1,349 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2014 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)
+ {
+ StringBuilder b = new StringBuilder();
+ 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();
+
+ for(String name : names)
+ {
+ 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();
+
+ for(String name : names)
+ {
+ 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 = args.toArray(new String[0]);
+ 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();
+
+ for(String name : names)
+ {
+ if(name.equals("*"))
+ {
+ NodeDesc[] nodes = dir.list();
+ for(NodeDesc node : nodes)
+ {
+ try
+ {
+ node.proxy.destroy();
+ }
+ catch(PermissionDenied ex)
+ {
+ System.out.println("cannot remove `" + node.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/Manual/map_filesystem/README b/java/demo/Manual/map_filesystem/README
new file mode 100644
index 00000000000..f1b64f52ed4
--- /dev/null
+++ b/java/demo/Manual/map_filesystem/README
@@ -0,0 +1,11 @@
+This demo presents an alternate implementation of the filesystem
+application using a Freeze map, as discussed in the Freeze chapter of
+the Ice manual.
+
+To run it, start the server in a window:
+
+$ java -jar build/libs/server.jar
+
+Then run the client in a separate window:
+
+$ java -jar build/libs/client.jar
diff --git a/java/demo/Manual/map_filesystem/Scanner.java b/java/demo/Manual/map_filesystem/Scanner.java
new file mode 100644
index 00000000000..2b81fcfd450
--- /dev/null
+++ b/java/demo/Manual/map_filesystem/Scanner.java
@@ -0,0 +1,283 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2014 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;
+ }
+
+ StringBuilder buf = new StringBuilder(128);
+
+ 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/Manual/map_filesystem/Server.java b/java/demo/Manual/map_filesystem/Server.java
new file mode 100644
index 00000000000..8ce2d5f586a
--- /dev/null
+++ b/java/demo/Manual/map_filesystem/Server.java
@@ -0,0 +1,80 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2014 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 FilesystemDB.*;
+
+public class Server extends Ice.Application
+{
+ public
+ Server(String envName)
+ {
+ _envName = envName;
+ }
+
+ @Override
+ public int
+ run(String[] args)
+ {
+ //
+ // Create an object adapter
+ //
+ Ice.ObjectAdapter adapter = communicator().createObjectAdapter("MapFilesystem");
+
+ Freeze.Connection connection = null;
+ try
+ {
+ //
+ // Open a connection to the files and directories
+ // database. This should remain open for the duration of the
+ // application for performance reasons.
+ //
+ connection = Freeze.Util.createConnection(communicator(), _envName);
+ new IdentityFileEntryMap(connection, FileI.filesDB(), true);
+ new IdentityDirectoryEntryMap(connection, DirectoryI.directoriesDB(), true);
+
+ //
+ // Add default servants for the file and directory.
+ //
+ adapter.addDefaultServant(new FileI(communicator(), _envName), "file");
+ adapter.addDefaultServant(new DirectoryI(communicator(), _envName), "");
+
+ //
+ // Ready to accept requests now
+ //
+ adapter.activate();
+
+ //
+ // Wait until we are done
+ //
+ communicator().waitForShutdown();
+ }
+ finally
+ {
+ //
+ // Close the connection gracefully.
+ //
+ if(connection != null)
+ {
+ connection.close();
+ }
+ }
+
+ return 0;
+ }
+
+ public static void
+ main(String[] args)
+ {
+ Server app = new Server("db");
+ app.main("demo.book.map_filesystem.Server", args, "config.server");
+ System.exit(0);
+ }
+
+ private String _envName;
+}
diff --git a/java/demo/Manual/map_filesystem/Token.java b/java/demo/Manual/map_filesystem/Token.java
new file mode 100644
index 00000000000..7a538343d6c
--- /dev/null
+++ b/java/demo/Manual/map_filesystem/Token.java
@@ -0,0 +1,40 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2014 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/Manual/map_filesystem/build.gradle b/java/demo/Manual/map_filesystem/build.gradle
new file mode 100644
index 00000000000..9cfcbe348b2
--- /dev/null
+++ b/java/demo/Manual/map_filesystem/build.gradle
@@ -0,0 +1,104 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2014 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.
+//
+// **********************************************************************
+
+slice {
+ java {
+ include = ["${projectDir}", "${sliceDir}"]
+ srcDir = '.'
+ }
+ freezej {
+ files = [file("FilesystemDB.ice"),
+ file("${sliceDir}/Ice/Identity.ice")]
+ include = ["${projectDir}", "${sliceDir}"]
+ args = "--ice"
+ dict {
+ IdentityFileEntryMap {
+ javaType = "FilesystemDB.IdentityFileEntryMap"
+ key = "Ice::Identity"
+ value = "FilesystemDB::FileEntry"
+ }
+ }
+ dict {
+ IdentityDirectoryEntryMap {
+ javaType = "FilesystemDB.IdentityDirectoryEntryMap"
+ key="Ice::Identity"
+ value="FilesystemDB::DirectoryEntry"
+ }
+ }
+ }
+}
+
+sourceSets {
+ main {
+ java {
+ srcDir '.'
+ output.classesDir "${buildDir}/classes"
+ }
+ }
+}
+
+if (useMavenJars) {
+ dependencies {
+ compile "com.zeroc:ice:${iceVersion}"
+ compile "com.zeroc:freeze:${iceVersion}"
+ compile 'com.sleepycat:db:5.3.28'
+ }
+} else if (distJarDir != null) {
+ dependencies {
+ compile files("${distJarDir}/Ice${versionSuffix}.jar")
+ compile files("${distJarDir}/Freeze${versionSuffix}.jar")
+ compile 'com.sleepycat:db:5.3.28'
+ }
+} else {
+ dependencies {
+ compile project(':Ice')
+ compile project(':Freeze')
+ }
+}
+
+// Create a jar for the client & server which includes everything in the demo.
+task clientJar(type: Jar) {
+ baseName = "client"
+ from(sourceSets.main.output) {
+ include "**"
+ }
+}
+
+task serverJar(type: Jar) {
+ baseName = "server"
+ from(sourceSets.main.output) {
+ include "**"
+ }
+}
+
+clientJar {
+ manifest {
+ attributes("Main-Class": "Client")
+ attributes("Class-Path": configurations.compile.resolve().collect { it.toURI() }.join(' '))
+ }
+}
+
+serverJar {
+ manifest {
+ attributes("Main-Class": "Server")
+ attributes("Class-Path": configurations.compile.resolve().collect { it.toURI() }.join(' '))
+ }
+}
+
+artifacts {
+ archives clientJar, serverJar;
+}
+
+// Don't create the default jar.
+jar.enabled = false
+
+idea.module {
+ excludeDirs -= file(buildDir)
+ buildDir.listFiles({d, f ->f != 'generated-src'} as FilenameFilter).each { excludeDirs += it }
+}
diff --git a/java/demo/Manual/map_filesystem/config.client b/java/demo/Manual/map_filesystem/config.client
new file mode 100644
index 00000000000..640cfade4f1
--- /dev/null
+++ b/java/demo/Manual/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 -h localhost -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/Manual/map_filesystem/config.server b/java/demo/Manual/map_filesystem/config.server
new file mode 100644
index 00000000000..c8694039614
--- /dev/null
+++ b/java/demo/Manual/map_filesystem/config.server
@@ -0,0 +1,37 @@
+#
+# Configure the server endpoints.
+#
+MapFilesystem.Endpoints=default -h localhost -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
+
+#
+# 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/Manual/map_filesystem/demo_manual_map_filesystem.iml b/java/demo/Manual/map_filesystem/demo_manual_map_filesystem.iml
new file mode 100644
index 00000000000..93543e73196
--- /dev/null
+++ b/java/demo/Manual/map_filesystem/demo_manual_map_filesystem.iml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<module external.linked.project.path="$MODULE_DIR$" external.root.project.path="$MODULE_DIR$/../../.." external.system.id="GRADLE" external.system.module.group="java" external.system.module.version="unspecified" type="JAVA_MODULE" version="4">
+ <component name="NewModuleRootManager" inherit-compiler-output="false">
+ <output url="file://$MODULE_DIR$/build/classes" />
+ <output-test url="file://$MODULE_DIR$/build/classes/test" />
+ <exclude-output />
+ <content url="file://$MODULE_DIR$">
+ <sourceFolder url="file://$MODULE_DIR$/build/generated-src" isTestSource="false" />
+ <sourceFolder url="file://$MODULE_DIR$/src/main/java" isTestSource="false" />
+ <sourceFolder url="file://$MODULE_DIR$" isTestSource="false" />
+ <sourceFolder url="file://$MODULE_DIR$/src/test/java" isTestSource="true" />
+ <sourceFolder url="file://$MODULE_DIR$/src/main/resources" type="java-resource" />
+ <sourceFolder url="file://$MODULE_DIR$/src/test/resources" type="java-test-resource" />
+ <excludeFolder url="file://$MODULE_DIR$/.gradle" />
+ <excludeFolder url="file://$MODULE_DIR$/build/dependency-cache" />
+ <excludeFolder url="file://$MODULE_DIR$/build/tmp" />
+ </content>
+ <orderEntry type="inheritedJdk" />
+ <orderEntry type="sourceFolder" forTests="false" />
+ <orderEntry type="module" module-name="Ice" exported="" />
+ <orderEntry type="module" module-name="Freeze" exported="" />
+ </component>
+</module>
+
diff --git a/java/demo/Manual/map_filesystem/expect.py b/java/demo/Manual/map_filesystem/expect.py
new file mode 100755
index 00000000000..bb7ca5b8aa3
--- /dev/null
+++ b/java/demo/Manual/map_filesystem/expect.py
@@ -0,0 +1,34 @@
+#!/usr/bin/env python
+# **********************************************************************
+#
+# Copyright (c) 2003-2014 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
+
+path = [ ".", "..", "../..", "../../..", "../../../.." ]
+head = os.path.dirname(sys.argv[0])
+if len(head) > 0:
+ path = [os.path.join(head, p) for p in path]
+path = [os.path.abspath(p) for p in path if os.path.exists(os.path.join(p, "demoscript")) ]
+if len(path) == 0:
+ raise RuntimeError("can't find toplevel directory!")
+sys.path.append(path[0])
+
+from demoscript import Util
+from demoscript.manual import map_filesystem
+
+sys.stdout.write("cleaning databases... ")
+sys.stdout.flush()
+Util.cleanDbDir("db")
+print("ok")
+
+server = Util.spawn('java -jar build/libs/server.jar --Ice.PrintAdapterReady')
+server.expect('.* ready')
+client = Util.spawn('java -jar build/libs/client.jar')
+
+map_filesystem.run(client, server)
diff --git a/java/demo/Manual/printer/.externalToolBuilders/demo.book.printer.launch b/java/demo/Manual/printer/.externalToolBuilders/demo.book.printer.launch
new file mode 100644
index 00000000000..b8b0aefe5db
--- /dev/null
+++ b/java/demo/Manual/printer/.externalToolBuilders/demo.book.printer.launch
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<launchConfiguration type="org.eclipse.ant.AntBuilderLaunchConfigurationType">
+<stringAttribute key="org.eclipse.ant.ui.ATTR_ANT_AUTO_TARGETS" value="generate,"/>
+<stringAttribute key="org.eclipse.ant.ui.ATTR_ANT_CLEAN_TARGETS" value="clean,"/>
+<stringAttribute key="org.eclipse.ant.ui.ATTR_ANT_MANUAL_TARGETS" value="generate,"/>
+<booleanAttribute key="org.eclipse.ant.ui.ATTR_TARGETS_UPDATED" value="true"/>
+<booleanAttribute key="org.eclipse.ant.ui.DEFAULT_VM_INSTALL" value="false"/>
+<stringAttribute key="org.eclipse.debug.core.ATTR_REFRESH_SCOPE" value="${project}"/>
+<booleanAttribute key="org.eclipse.debug.ui.ATTR_LAUNCH_IN_BACKGROUND" value="false"/>
+<stringAttribute key="org.eclipse.jdt.launching.CLASSPATH_PROVIDER" value="org.eclipse.ant.ui.AntClasspathProvider"/>
+<booleanAttribute key="org.eclipse.jdt.launching.DEFAULT_CLASSPATH" value="true"/>
+<stringAttribute key="org.eclipse.jdt.launching.PROJECT_ATTR" value="demo.book.printer"/>
+<stringAttribute key="org.eclipse.ui.externaltools.ATTR_BUILD_SCOPE" value="${working_set:&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;&#10;&lt;resources&gt;&#10;&lt;item path=&quot;/demo.book.printer/Printer.ice&quot; type=&quot;1&quot;/&gt;&#10;&lt;/resources&gt;}"/>
+<stringAttribute key="org.eclipse.ui.externaltools.ATTR_LOCATION" value="${workspace_loc:/demo.book.printer/build.xml}"/>
+<stringAttribute key="org.eclipse.ui.externaltools.ATTR_RUN_BUILD_KINDS" value="incremental,auto,clean"/>
+<booleanAttribute key="org.eclipse.ui.externaltools.ATTR_TRIGGERS_CONFIGURED" value="true"/>
+</launchConfiguration>
diff --git a/java/demo/Manual/printer/Client.java b/java/demo/Manual/printer/Client.java
new file mode 100644
index 00000000000..458eaae3800
--- /dev/null
+++ b/java/demo/Manual/printer/Client.java
@@ -0,0 +1,53 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2014 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
+{
+ public static void
+ main(String[] args)
+ {
+ int status = 0;
+ Ice.Communicator ic = null;
+ try
+ {
+ ic = Ice.Util.initialize(args);
+ Ice.ObjectPrx base = ic.stringToProxy("SimplePrinter:default -h localhost -p 10000");
+ Demo.PrinterPrx printer = Demo.PrinterPrxHelper.checkedCast(base);
+ if(printer == null)
+ {
+ throw new Error("Invalid proxy");
+ }
+
+ printer.printString("Hello World!");
+ }
+ catch(Ice.LocalException e)
+ {
+ e.printStackTrace();
+ status = 1;
+ }
+ catch(Exception e)
+ {
+ System.err.println(e.getMessage());
+ status = 1;
+ }
+ if(ic != null)
+ {
+ try
+ {
+ ic.destroy();
+ }
+ catch(Exception e)
+ {
+ System.err.println(e.getMessage());
+ status = 1;
+ }
+ }
+ System.exit(status);
+ }
+}
diff --git a/java/demo/Manual/printer/Printer.ice b/java/demo/Manual/printer/Printer.ice
new file mode 100755
index 00000000000..343fd8e627b
--- /dev/null
+++ b/java/demo/Manual/printer/Printer.ice
@@ -0,0 +1,20 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2014 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.
+//
+// **********************************************************************
+
+#pragma once
+
+module Demo
+{
+
+ interface Printer
+ {
+ void printString(string s);
+ };
+
+};
diff --git a/java/demo/Manual/printer/PrinterI.java b/java/demo/Manual/printer/PrinterI.java
new file mode 100644
index 00000000000..6d17fbfd036
--- /dev/null
+++ b/java/demo/Manual/printer/PrinterI.java
@@ -0,0 +1,17 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2014 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 PrinterI extends Demo._PrinterDisp
+{
+ public void
+ printString(String s, Ice.Current current)
+ {
+ System.out.println(s);
+ }
+}
diff --git a/java/demo/Manual/printer/README b/java/demo/Manual/printer/README
new file mode 100644
index 00000000000..8a89f134050
--- /dev/null
+++ b/java/demo/Manual/printer/README
@@ -0,0 +1,8 @@
+This demo implements the printer example in chapter 3 of the
+documentation. To run it, start the server in a window:
+
+$ java -jar build/libs/server.jar
+
+In a separate window, run the client:
+
+$ java -jar build/libs/client.jar
diff --git a/java/demo/Manual/printer/Server.java b/java/demo/Manual/printer/Server.java
new file mode 100644
index 00000000000..cdb11fa5312
--- /dev/null
+++ b/java/demo/Manual/printer/Server.java
@@ -0,0 +1,45 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2014 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 Server
+{
+ public static void
+ main(String[] args)
+ {
+ int status = 0;
+ Ice.Communicator ic = null;
+ try
+ {
+ ic = Ice.Util.initialize(args);
+ Ice.ObjectAdapter adapter = ic.createObjectAdapterWithEndpoints("SimplePrinterAdapter", "default -h localhost -p 10000");
+ Ice.Object object = new PrinterI();
+ adapter.add(object, ic.stringToIdentity("SimplePrinter"));
+ adapter.activate();
+ ic.waitForShutdown();
+ }
+ catch(Exception e)
+ {
+ e.printStackTrace();
+ status = 1;
+ }
+ if(ic != null)
+ {
+ try
+ {
+ ic.destroy();
+ }
+ catch(Exception e)
+ {
+ System.err.println(e.getMessage());
+ status = 1;
+ }
+ }
+ System.exit(status);
+ }
+}
diff --git a/java/demo/Manual/printer/demo_manual_printer.iml b/java/demo/Manual/printer/demo_manual_printer.iml
new file mode 100644
index 00000000000..b6dce281ba2
--- /dev/null
+++ b/java/demo/Manual/printer/demo_manual_printer.iml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<module external.linked.project.path="$MODULE_DIR$" external.root.project.path="$MODULE_DIR$/../../.." external.system.id="GRADLE" external.system.module.group="java" external.system.module.version="unspecified" type="JAVA_MODULE" version="4">
+ <component name="NewModuleRootManager" inherit-compiler-output="false">
+ <output url="file://$MODULE_DIR$/build/classes" />
+ <output-test url="file://$MODULE_DIR$/build/classes/test" />
+ <exclude-output />
+ <content url="file://$MODULE_DIR$">
+ <sourceFolder url="file://$MODULE_DIR$/build/generated-src" isTestSource="false" />
+ <sourceFolder url="file://$MODULE_DIR$/src/main/java" isTestSource="false" />
+ <sourceFolder url="file://$MODULE_DIR$" isTestSource="false" />
+ <sourceFolder url="file://$MODULE_DIR$/src/test/java" isTestSource="true" />
+ <sourceFolder url="file://$MODULE_DIR$/src/main/resources" type="java-resource" />
+ <sourceFolder url="file://$MODULE_DIR$/src/test/resources" type="java-test-resource" />
+ <excludeFolder url="file://$MODULE_DIR$/.gradle" />
+ <excludeFolder url="file://$MODULE_DIR$/build/dependency-cache" />
+ <excludeFolder url="file://$MODULE_DIR$/build/tmp" />
+ </content>
+ <orderEntry type="inheritedJdk" />
+ <orderEntry type="sourceFolder" forTests="false" />
+ <orderEntry type="module" module-name="Ice" exported="" />
+ </component>
+</module>
+
diff --git a/java/demo/Manual/printer/expect.py b/java/demo/Manual/printer/expect.py
new file mode 100755
index 00000000000..e9a6a09932c
--- /dev/null
+++ b/java/demo/Manual/printer/expect.py
@@ -0,0 +1,34 @@
+#!/usr/bin/env python
+# **********************************************************************
+#
+# Copyright (c) 2003-2014 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, signal
+
+path = [ ".", "..", "../..", "../../..", "../../../.." ]
+head = os.path.dirname(sys.argv[0])
+if len(head) > 0:
+ path = [os.path.join(head, p) for p in path]
+path = [os.path.abspath(p) for p in path if os.path.exists(os.path.join(p, "demoscript")) ]
+if len(path) == 0:
+ raise RuntimeError("can't find toplevel directory!")
+sys.path.append(path[0])
+
+from demoscript import Util
+
+server = Util.spawn('java -jar build/libs/server.jar --Ice.PrintAdapterReady')
+server.expect('.* ready')
+
+sys.stdout.write("testing... ")
+sys.stdout.flush()
+client = Util.spawn('java -jar build/libs/client.jar')
+client.waitTestSuccess()
+server.expect('Hello World!')
+server.kill(signal.SIGINT)
+server.waitTestSuccess()
+print("ok")
diff --git a/java/demo/Manual/simple_filesystem/.externalToolBuilders/demo.book.simple_filesystem.launch b/java/demo/Manual/simple_filesystem/.externalToolBuilders/demo.book.simple_filesystem.launch
new file mode 100644
index 00000000000..2256b877bae
--- /dev/null
+++ b/java/demo/Manual/simple_filesystem/.externalToolBuilders/demo.book.simple_filesystem.launch
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<launchConfiguration type="org.eclipse.ant.AntBuilderLaunchConfigurationType">
+<stringAttribute key="org.eclipse.ant.ui.ATTR_ANT_AUTO_TARGETS" value="generate,"/>
+<stringAttribute key="org.eclipse.ant.ui.ATTR_ANT_CLEAN_TARGETS" value="clean,"/>
+<stringAttribute key="org.eclipse.ant.ui.ATTR_ANT_MANUAL_TARGETS" value="generate,"/>
+<booleanAttribute key="org.eclipse.ant.ui.ATTR_TARGETS_UPDATED" value="true"/>
+<booleanAttribute key="org.eclipse.ant.ui.DEFAULT_VM_INSTALL" value="false"/>
+<stringAttribute key="org.eclipse.debug.core.ATTR_REFRESH_SCOPE" value="${container}"/>
+<booleanAttribute key="org.eclipse.debug.ui.ATTR_LAUNCH_IN_BACKGROUND" value="false"/>
+<stringAttribute key="org.eclipse.jdt.launching.CLASSPATH_PROVIDER" value="org.eclipse.ant.ui.AntClasspathProvider"/>
+<booleanAttribute key="org.eclipse.jdt.launching.DEFAULT_CLASSPATH" value="true"/>
+<stringAttribute key="org.eclipse.jdt.launching.PROJECT_ATTR" value="demo.book.simple_filesystem"/>
+<stringAttribute key="org.eclipse.ui.externaltools.ATTR_BUILD_SCOPE" value="${working_set:&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;&#10;&lt;resources&gt;&#10;&lt;item path=&quot;/demo.book.simple_filesystem/Filesystem.ice&quot; type=&quot;1&quot;/&gt;&#10;&lt;/resources&gt;}"/>
+<stringAttribute key="org.eclipse.ui.externaltools.ATTR_LOCATION" value="${workspace_loc:/demo.book.simple_filesystem/build.xml}"/>
+<stringAttribute key="org.eclipse.ui.externaltools.ATTR_RUN_BUILD_KINDS" value="incremental,auto,clean"/>
+<booleanAttribute key="org.eclipse.ui.externaltools.ATTR_TRIGGERS_CONFIGURED" value="true"/>
+</launchConfiguration>
diff --git a/java/demo/Manual/simple_filesystem/Client.java b/java/demo/Manual/simple_filesystem/Client.java
new file mode 100644
index 00000000000..de1516eb010
--- /dev/null
+++ b/java/demo/Manual/simple_filesystem/Client.java
@@ -0,0 +1,103 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2014 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
+{
+ // 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);
+
+ NodePrx[] contents = dir.list();
+
+ for(int i = 0; i < contents.length; ++i)
+ {
+ DirectoryPrx subdir = DirectoryPrxHelper.checkedCast(contents[i]);
+ FilePrx file = FilePrxHelper.uncheckedCast(contents[i]);
+ 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]);
+ }
+ }
+ }
+ }
+
+ public static void
+ main(String[] args)
+ {
+ int status = 0;
+ Ice.Communicator ic = null;
+ try
+ {
+ //
+ // Create a communicator
+ //
+ ic = Ice.Util.initialize(args);
+
+ //
+ // Create a proxy for the root directory
+ //
+ Ice.ObjectPrx base = ic.stringToProxy("RootDir:default -h localhost -p 10000");
+
+ //
+ // Down-cast the proxy to a Directory proxy
+ //
+ DirectoryPrx rootDir = DirectoryPrxHelper.checkedCast(base);
+ if(rootDir == null)
+ {
+ throw new RuntimeException("Invalid proxy");
+ }
+
+ //
+ // Recursively list the contents of the root directory
+ //
+ System.out.println("Contents of root directory:");
+ listRecursive(rootDir, 0);
+ }
+ catch(Ice.LocalException e)
+ {
+ e.printStackTrace();
+ status = 1;
+ }
+ catch(Exception e)
+ {
+ System.err.println(e.getMessage());
+ status = 1;
+ }
+ if(ic != null)
+ {
+ try
+ {
+ ic.destroy();
+ }
+ catch(Exception e)
+ {
+ System.err.println(e.getMessage());
+ status = 1;
+ }
+ }
+ System.exit(status);
+ }
+}
diff --git a/java/demo/Manual/simple_filesystem/Filesystem.ice b/java/demo/Manual/simple_filesystem/Filesystem.ice
new file mode 100755
index 00000000000..21e8a435fcb
--- /dev/null
+++ b/java/demo/Manual/simple_filesystem/Filesystem.ice
@@ -0,0 +1,38 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2014 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.
+//
+// **********************************************************************
+
+#pragma once
+
+module Filesystem
+{
+ exception GenericError
+ {
+ string reason;
+ };
+
+ interface Node
+ {
+ idempotent string name();
+ };
+
+ sequence<string> Lines;
+
+ interface File extends Node
+ {
+ idempotent Lines read();
+ idempotent void write(Lines text) throws GenericError;
+ };
+
+ sequence<Node*> NodeSeq;
+
+ interface Directory extends Node
+ {
+ idempotent NodeSeq list();
+ };
+};
diff --git a/java/demo/Manual/simple_filesystem/Filesystem/DirectoryI.java b/java/demo/Manual/simple_filesystem/Filesystem/DirectoryI.java
new file mode 100644
index 00000000000..69f793bb89c
--- /dev/null
+++ b/java/demo/Manual/simple_filesystem/Filesystem/DirectoryI.java
@@ -0,0 +1,72 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2014 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 Filesystem;
+
+public final class DirectoryI extends _DirectoryDisp
+{
+ // DirectoryI constructor
+
+ public
+ DirectoryI(Ice.Communicator communicator, String name, DirectoryI parent)
+ {
+ _name = name;
+ _parent = parent;
+
+ // Create an identity. The root directory has the fixed identity "RootDir"
+ //
+ _id = new Ice.Identity();
+ _id.name = _parent != null ? java.util.UUID.randomUUID().toString() : "RootDir";
+ }
+
+ // Slice Node::name() operation
+
+ public String
+ name(Ice.Current current)
+ {
+ return _name;
+ }
+
+ // Slice Directory::list() operation
+
+ public NodePrx[]
+ list(Ice.Current current)
+ {
+ NodePrx[] result = new NodePrx[_contents.size()];
+ _contents.toArray(result);
+ return result;
+ }
+
+ // addChild is called by the child in order to add
+ // itself to the _contents member of the parent
+
+ void
+ addChild(NodePrx child)
+ {
+ _contents.add(child);
+ }
+
+ // activate adds the servant to the object adapter and
+ // adds child nodes ot the parent's _contents list.
+
+ public void
+ activate(Ice.ObjectAdapter a)
+ {
+ NodePrx thisNode = NodePrxHelper.uncheckedCast(a.add(this, _id));
+ if(_parent != null)
+ {
+ _parent.addChild(thisNode);
+ }
+ }
+
+ private String _name;
+ private DirectoryI _parent;
+ private Ice.Identity _id;
+ private java.util.List<NodePrx> _contents = new java.util.ArrayList<NodePrx>();
+}
diff --git a/java/demo/Manual/simple_filesystem/Filesystem/FileI.java b/java/demo/Manual/simple_filesystem/Filesystem/FileI.java
new file mode 100644
index 00000000000..3a4bff86431
--- /dev/null
+++ b/java/demo/Manual/simple_filesystem/Filesystem/FileI.java
@@ -0,0 +1,67 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2014 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 Filesystem;
+
+public class FileI extends _FileDisp
+{
+ // FileI constructor
+
+ public
+ FileI(Ice.Communicator communicator, String name, DirectoryI parent)
+ {
+ _name = name;
+ _parent = parent;
+
+ assert(_parent != null);
+
+ //
+ // Create an identity
+ //
+ _id = new Ice.Identity();
+ _id.name = java.util.UUID.randomUUID().toString();
+ }
+
+ // Slice Node::name() operation
+
+ public String
+ name(Ice.Current current)
+ {
+ return _name;
+ }
+
+ // Slice File::read() operation
+
+ public String[]
+ read(Ice.Current current)
+ {
+ return _lines;
+ }
+
+ // Slice File::write() operation
+
+ public void
+ write(String[] text, Ice.Current current)
+ throws GenericError
+ {
+ _lines = text;
+ }
+
+ public void
+ activate(Ice.ObjectAdapter a)
+ {
+ NodePrx thisNode = NodePrxHelper.uncheckedCast(a.add(this, _id));
+ _parent.addChild(thisNode);
+ }
+
+ private String _name;
+ private DirectoryI _parent;
+ private Ice.Identity _id;
+ private String[] _lines;
+}
diff --git a/java/demo/Manual/simple_filesystem/README b/java/demo/Manual/simple_filesystem/README
new file mode 100644
index 00000000000..f6ed81b1855
--- /dev/null
+++ b/java/demo/Manual/simple_filesystem/README
@@ -0,0 +1,10 @@
+This demo implements the simple filesystem application shown at
+the end of the client and server Java mapping chapters.
+
+To run it, start the server in a window:
+
+$ java -jar build/libs/server.jar
+
+Then run the client in a separate window:
+
+$ java -jar build/libs/client.jar
diff --git a/java/demo/Manual/simple_filesystem/Server.java b/java/demo/Manual/simple_filesystem/Server.java
new file mode 100644
index 00000000000..a5a97aa6140
--- /dev/null
+++ b/java/demo/Manual/simple_filesystem/Server.java
@@ -0,0 +1,99 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2014 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 Server extends Ice.Application
+{
+ public int
+ run(String[] args)
+ {
+ //
+ // Terminate cleanly on receipt of a signal
+ //
+ shutdownOnInterrupt();
+
+ //
+ // Create an object adapter.
+ //
+ Ice.ObjectAdapter adapter =
+ communicator().createObjectAdapterWithEndpoints("SimpleFilesystem", "default -h localhost -p 10000");
+
+ //
+ // Create the root directory (with name "/" and no parent)
+ //
+ DirectoryI root = new DirectoryI(communicator(), "/", null);
+ root.activate(adapter);
+
+ //
+ // Create a file called "README" in the root directory
+ //
+ FileI file = new FileI(communicator(), "README", root);
+ String[] text;
+ text = new String[]{ "This file system contains a collection of poetry." };
+ try
+ {
+ file.write(text, null);
+ }
+ catch(GenericError e)
+ {
+ System.err.println(e.reason);
+ }
+ file.activate(adapter);
+
+ //
+ // Create a directory called "Coleridge" in the root directory
+ //
+ DirectoryI coleridge = new DirectoryI(communicator(), "Coleridge", root);
+ coleridge.activate(adapter);
+
+ //
+ // Create a file called "Kubla_Khan" in the Coleridge directory
+ //
+ file = new FileI(communicator(), "Kubla_Khan", coleridge);
+ text = new String[]{ "In Xanadu did Kubla Khan",
+ "A stately pleasure-dome decree:",
+ "Where Alph, the sacred river, ran",
+ "Through caverns measureless to man",
+ "Down to a sunless sea." };
+ try
+ {
+ file.write(text, null);
+ }
+ catch(GenericError e)
+ {
+ System.err.println(e.reason);
+ }
+ file.activate(adapter);
+
+ //
+ // All objects are created, allow client requests now
+ //
+ adapter.activate();
+
+ //
+ // Wait until we are done
+ //
+ communicator().waitForShutdown();
+
+ if(interrupted())
+ {
+ System.err.println(appName() + ": terminating");
+ }
+
+ return 0;
+ }
+
+ public static void
+ main(String[] args)
+ {
+ Server app = new Server();
+ System.exit(app.main("Server", args));
+ }
+}
diff --git a/java/demo/Manual/simple_filesystem/demo_manual_simple_filesystem.iml b/java/demo/Manual/simple_filesystem/demo_manual_simple_filesystem.iml
new file mode 100644
index 00000000000..5e03c3e6c62
--- /dev/null
+++ b/java/demo/Manual/simple_filesystem/demo_manual_simple_filesystem.iml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<module external.linked.project.path="$MODULE_DIR$" external.root.project.path="$MODULE_DIR$/../../.." external.system.id="GRADLE" external.system.module.group="java" external.system.module.version="unspecified" type="JAVA_MODULE" version="4">
+ <component name="NewModuleRootManager" inherit-compiler-output="false">
+ <output url="file://$MODULE_DIR$/build/classes" />
+ <output-test url="file://$MODULE_DIR$/build/classes/test" />
+ <exclude-output />
+ <content url="file://$MODULE_DIR$">
+ <sourceFolder url="file://$MODULE_DIR$" isTestSource="false" />
+ <sourceFolder url="file://$MODULE_DIR$/src/main/java" isTestSource="false" />
+ <sourceFolder url="file://$MODULE_DIR$/build/generated-src" isTestSource="false" />
+ <sourceFolder url="file://$MODULE_DIR$/src/test/java" isTestSource="true" />
+ <sourceFolder url="file://$MODULE_DIR$/src/main/resources" type="java-resource" />
+ <sourceFolder url="file://$MODULE_DIR$/src/test/resources" type="java-test-resource" />
+ <excludeFolder url="file://$MODULE_DIR$/.gradle" />
+ <excludeFolder url="file://$MODULE_DIR$/build/dependency-cache" />
+ <excludeFolder url="file://$MODULE_DIR$/build/tmp" />
+ </content>
+ <orderEntry type="inheritedJdk" />
+ <orderEntry type="sourceFolder" forTests="false" />
+ <orderEntry type="module" module-name="Ice" exported="" />
+ </component>
+</module>
+
diff --git a/java/demo/Manual/simple_filesystem/expect.py b/java/demo/Manual/simple_filesystem/expect.py
new file mode 100755
index 00000000000..953113e2054
--- /dev/null
+++ b/java/demo/Manual/simple_filesystem/expect.py
@@ -0,0 +1,34 @@
+#!/usr/bin/env python
+# **********************************************************************
+#
+# Copyright (c) 2003-2014 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, signal
+
+path = [ ".", "..", "../..", "../../..", "../../../.." ]
+head = os.path.dirname(sys.argv[0])
+if len(head) > 0:
+ path = [os.path.join(head, p) for p in path]
+path = [os.path.abspath(p) for p in path if os.path.exists(os.path.join(p, "demoscript")) ]
+if len(path) == 0:
+ raise RuntimeError("can't find toplevel directory!")
+sys.path.append(path[0])
+
+from demoscript import Util
+
+server = Util.spawn('java -jar build/libs/server.jar --Ice.PrintAdapterReady')
+server.expect('.* ready')
+
+sys.stdout.write("testing... ")
+sys.stdout.flush()
+client = Util.spawn('java -jar build/libs/client.jar')
+client.expect('Contents of root directory:\n.*Down to a sunless sea.')
+client.waitTestSuccess()
+server.kill(signal.SIGINT)
+server.waitTestSuccess()
+print("ok")