[Author Prev][Author Next][Thread Prev][Thread Next][Author Index][Thread Index]

[or-cvs] r16546: {puppetor} Something that doesn't do any tests yet, but creates a netwo (in puppetor/branches/gsoc2008/src/de/uniba/wiai/lspi/puppetor: . examples impl rmi rmi/execute rmi/impl rmi/tasks)



Author: sebastian
Date: 2008-08-14 10:04:37 -0400 (Thu, 14 Aug 2008)
New Revision: 16546

Modified:
   puppetor/branches/gsoc2008/src/de/uniba/wiai/lspi/puppetor/NetworkFactory.java
   puppetor/branches/gsoc2008/src/de/uniba/wiai/lspi/puppetor/examples/AccessingPublicWebServerOverTor.java
   puppetor/branches/gsoc2008/src/de/uniba/wiai/lspi/puppetor/impl/ClientApplicationImpl.java
   puppetor/branches/gsoc2008/src/de/uniba/wiai/lspi/puppetor/impl/DirectoryNodeImpl.java
   puppetor/branches/gsoc2008/src/de/uniba/wiai/lspi/puppetor/impl/EventImpl.java
   puppetor/branches/gsoc2008/src/de/uniba/wiai/lspi/puppetor/impl/EventManagerImpl.java
   puppetor/branches/gsoc2008/src/de/uniba/wiai/lspi/puppetor/impl/HiddenServiceImpl.java
   puppetor/branches/gsoc2008/src/de/uniba/wiai/lspi/puppetor/impl/NetworkImpl.java
   puppetor/branches/gsoc2008/src/de/uniba/wiai/lspi/puppetor/impl/ProxyNodeImpl.java
   puppetor/branches/gsoc2008/src/de/uniba/wiai/lspi/puppetor/impl/RouterNodeImpl.java
   puppetor/branches/gsoc2008/src/de/uniba/wiai/lspi/puppetor/impl/ServerApplicationImpl.java
   puppetor/branches/gsoc2008/src/de/uniba/wiai/lspi/puppetor/rmi/AbstractSlaveFactory.java
   puppetor/branches/gsoc2008/src/de/uniba/wiai/lspi/puppetor/rmi/LocalMaster.java
   puppetor/branches/gsoc2008/src/de/uniba/wiai/lspi/puppetor/rmi/Network.java
   puppetor/branches/gsoc2008/src/de/uniba/wiai/lspi/puppetor/rmi/NetworkDescription.java
   puppetor/branches/gsoc2008/src/de/uniba/wiai/lspi/puppetor/rmi/Task.java
   puppetor/branches/gsoc2008/src/de/uniba/wiai/lspi/puppetor/rmi/TorInstance.java
   puppetor/branches/gsoc2008/src/de/uniba/wiai/lspi/puppetor/rmi/execute/PuppeTorMasterProgram.java
   puppetor/branches/gsoc2008/src/de/uniba/wiai/lspi/puppetor/rmi/execute/PuppeTorSlaveProgram.java
   puppetor/branches/gsoc2008/src/de/uniba/wiai/lspi/puppetor/rmi/impl/AbstractTaskImpl.java
   puppetor/branches/gsoc2008/src/de/uniba/wiai/lspi/puppetor/rmi/impl/MasterImpl.java
   puppetor/branches/gsoc2008/src/de/uniba/wiai/lspi/puppetor/rmi/impl/NetworkDescriptionImpl.java
   puppetor/branches/gsoc2008/src/de/uniba/wiai/lspi/puppetor/rmi/impl/NetworkImpl.java
   puppetor/branches/gsoc2008/src/de/uniba/wiai/lspi/puppetor/rmi/impl/TestExecutorImpl.java
   puppetor/branches/gsoc2008/src/de/uniba/wiai/lspi/puppetor/rmi/impl/TorInstanceImpl.java
   puppetor/branches/gsoc2008/src/de/uniba/wiai/lspi/puppetor/rmi/tasks/CreateNetworkTask.java
   puppetor/branches/gsoc2008/src/de/uniba/wiai/lspi/puppetor/rmi/tasks/TerminateTask.java
Log:
Something that doesn't do any tests yet, but creates a network as it is supposed to do. Still a mess...

Modified: puppetor/branches/gsoc2008/src/de/uniba/wiai/lspi/puppetor/NetworkFactory.java
===================================================================
--- puppetor/branches/gsoc2008/src/de/uniba/wiai/lspi/puppetor/NetworkFactory.java	2008-08-14 12:43:35 UTC (rev 16545)
+++ puppetor/branches/gsoc2008/src/de/uniba/wiai/lspi/puppetor/NetworkFactory.java	2008-08-14 14:04:37 UTC (rev 16546)
@@ -87,7 +87,8 @@
 	 *            created nodes.
 	 * @return A new network instance.
 	 */
-	public static Network createNetwork(final String networkName, final int startPort) {
+	public static Network createNetwork(final String networkName,
+			final int startPort) {
 		final Network network = new NetworkImpl(networkName, startPort);
 		networks.put(networkName, network);
 		return network;

Modified: puppetor/branches/gsoc2008/src/de/uniba/wiai/lspi/puppetor/examples/AccessingPublicWebServerOverTor.java
===================================================================
--- puppetor/branches/gsoc2008/src/de/uniba/wiai/lspi/puppetor/examples/AccessingPublicWebServerOverTor.java	2008-08-14 12:43:35 UTC (rev 16545)
+++ puppetor/branches/gsoc2008/src/de/uniba/wiai/lspi/puppetor/examples/AccessingPublicWebServerOverTor.java	2008-08-14 14:04:37 UTC (rev 16546)
@@ -141,6 +141,5 @@
 
 		// Shut down the JVM
 		System.out.println("Goodbye.");
-		System.exit(0);
 	}
 }

Modified: puppetor/branches/gsoc2008/src/de/uniba/wiai/lspi/puppetor/impl/ClientApplicationImpl.java
===================================================================
--- puppetor/branches/gsoc2008/src/de/uniba/wiai/lspi/puppetor/impl/ClientApplicationImpl.java	2008-08-14 12:43:35 UTC (rev 16545)
+++ puppetor/branches/gsoc2008/src/de/uniba/wiai/lspi/puppetor/impl/ClientApplicationImpl.java	2008-08-14 14:04:37 UTC (rev 16546)
@@ -104,7 +104,8 @@
 
 			// check parameters
 			if (retries < 0 || timeoutForEachRetry < 0) {
-				final IllegalArgumentException e = new IllegalArgumentException();
+				final IllegalArgumentException e =
+						new IllegalArgumentException();
 				logger.throwing(this.getClass().getName(), "RequestThread", e);
 				throw e;
 			}
@@ -170,7 +171,8 @@
 						s.connect(hs, (int) timeoutForEachRetry);
 
 						// open output stream to write request
-						final PrintStream out = new PrintStream(s.getOutputStream());
+						final PrintStream out =
+								new PrintStream(s.getOutputStream());
 						out.print("GET / HTTP/1.0\r\n\r\n");
 
 						// open input stream to read reply
@@ -363,8 +365,9 @@
 	 *             If at least one of the parameters is <code>null</code> or
 	 *             has an invalid value.
 	 */
-	ClientApplicationImpl(final NetworkImpl network, final String clientApplicationName,
-			final String targetName, final int targetPort, final int socksPort) {
+	ClientApplicationImpl(final NetworkImpl network,
+			final String clientApplicationName, final String targetName,
+			final int targetPort, final int socksPort) {
 
 		// check if clientApplicationName can be used as logger name
 		if (clientApplicationName == null
@@ -377,18 +380,17 @@
 		logger = Logger.getLogger("client." + clientApplicationName);
 
 		// log entering
-		logger.entering(this.getClass().getName(),
-				"ClientApplicationImpl", new Object[] { network,
-						clientApplicationName, targetName, targetPort,
-						socksPort });
+		logger.entering(this.getClass().getName(), "ClientApplicationImpl",
+				new Object[] { network, clientApplicationName, targetName,
+						targetPort, socksPort });
 
 		// check parameters
 		if (network == null || targetName == null || targetName.length() == 0
 				|| targetPort < 0 || targetPort > 65535 || socksPort < 0
 				|| socksPort > 65535) {
 			final IllegalArgumentException e = new IllegalArgumentException();
-			logger.throwing(this.getClass().getName(),
-					"ClientApplicationImpl", e);
+			logger.throwing(this.getClass().getName(), "ClientApplicationImpl",
+					e);
 			throw e;
 		}
 
@@ -415,8 +417,7 @@
 		// check parameters
 		if (retries <= 0 || timeoutForEachRetry < 0) {
 			final IllegalArgumentException e = new IllegalArgumentException();
-			logger
-					.throwing(this.getClass().getName(), "performRequest", e);
+			logger.throwing(this.getClass().getName(), "performRequest", e);
 			throw e;
 		}
 
@@ -426,8 +427,7 @@
 			final IllegalStateException e =
 					new IllegalStateException(
 							"Another request has already been started!");
-			logger
-					.throwing(this.getClass().getName(), "performRequest", e);
+			logger.throwing(this.getClass().getName(), "performRequest", e);
 			throw e;
 		}
 
@@ -469,9 +469,8 @@
 	@Override
 	public String toString() {
 		return this.getClass().getSimpleName() + ": clientApplicationName=\""
-				+ clientApplicationName + "\", targetAddress=\""
-				+ targetName + "\", targetPort=" + targetPort
-				+ ", socksPort=" + socksPort;
+				+ clientApplicationName + "\", targetAddress=\"" + targetName
+				+ "\", targetPort=" + targetPort + ", socksPort=" + socksPort;
 	}
 
 	public String getClientApplicationName() {

Modified: puppetor/branches/gsoc2008/src/de/uniba/wiai/lspi/puppetor/impl/DirectoryNodeImpl.java
===================================================================
--- puppetor/branches/gsoc2008/src/de/uniba/wiai/lspi/puppetor/impl/DirectoryNodeImpl.java	2008-08-14 12:43:35 UTC (rev 16545)
+++ puppetor/branches/gsoc2008/src/de/uniba/wiai/lspi/puppetor/impl/DirectoryNodeImpl.java	2008-08-14 14:04:37 UTC (rev 16546)
@@ -83,9 +83,8 @@
 							"--create-identity-key"// );
 							, "--passphrase-fd", "0");
 			final File workingDirectory =
-					new File(workingDir
-							.getAbsolutePath()
-							+ File.separator + "keys" + File.separator);
+					new File(workingDir.getAbsolutePath() + File.separator
+							+ "keys" + File.separator);
 
 			// create working directory
 			workingDirectory.mkdirs();
@@ -242,8 +241,9 @@
 	 *             Thrown if an I/O problem occurs while writing the temporary
 	 *             <code>approved-routers</code> file.
 	 */
-	DirectoryNodeImpl(final NetworkImpl network, final String nodeName, final int controlPort,
-			final int socksPort, final int orPort, final int dirPort, final String serverIpAddress) {
+	DirectoryNodeImpl(final NetworkImpl network, final String nodeName,
+			final int controlPort, final int socksPort, final int orPort,
+			final int dirPort, final String serverIpAddress) {
 		// create superclass instance; parameter checking is done in super
 		// constructor
 		super(network, nodeName, controlPort, socksPort, orPort, dirPort,
@@ -273,8 +273,7 @@
 	 */
 	private synchronized void setV3Identity(final String v3Identity) {
 		// log entering
-		logger.entering(this.getClass().getName(), "setV3Identity",
-				v3Identity);
+		logger.entering(this.getClass().getName(), "setV3Identity", v3Identity);
 
 		// remember fingerprint and notify all waiting threads
 		this.v3Identity = v3Identity;
@@ -312,8 +311,7 @@
 		}
 
 		// log exiting
-		logger.exiting(this.getClass().getName(), "getV3Identity",
-				v3Identity);
+		logger.exiting(this.getClass().getName(), "getV3Identity", v3Identity);
 		return v3Identity;
 	}
 
@@ -333,10 +331,9 @@
 
 		// put everything together
 		final String dirServerString =
-				"DirServer " + nodeName + " v3ident="
-						+ determinedV3Identity + " orport=" + orPort + " "
-						+ serverIpAddress + ":" + dirPort + " "
-						+ fingerprint;
+				"DirServer " + nodeName + " v3ident=" + determinedV3Identity
+						+ " orport=" + orPort + " " + serverIpAddress + ":"
+						+ dirPort + " " + fingerprint;
 
 		// log exiting and return dir server string
 		logger.exiting(this.getClass().getName(), "getDirServerString",
@@ -353,8 +350,7 @@
 		// check parameter
 		if (routers == null) {
 			final IllegalArgumentException e = new IllegalArgumentException();
-			logger.throwing(this.getClass().getName(),
-					"addApprovedRouters", e);
+			logger.throwing(this.getClass().getName(), "addApprovedRouters", e);
 			throw e;
 		}
 
@@ -424,8 +420,9 @@
 			bw.close();
 		} catch (final IOException e) {
 			final PuppeTorException ex = new PuppeTorException(e);
-			logger.throwing(this.getClass().getName(),
-					"writeConfiguration", ex);
+			logger
+					.throwing(this.getClass().getName(), "writeConfiguration",
+							ex);
 			throw ex;
 		}
 

Modified: puppetor/branches/gsoc2008/src/de/uniba/wiai/lspi/puppetor/impl/EventImpl.java
===================================================================
--- puppetor/branches/gsoc2008/src/de/uniba/wiai/lspi/puppetor/impl/EventImpl.java	2008-08-14 12:43:35 UTC (rev 16545)
+++ puppetor/branches/gsoc2008/src/de/uniba/wiai/lspi/puppetor/impl/EventImpl.java	2008-08-14 14:04:37 UTC (rev 16546)
@@ -79,7 +79,8 @@
 	 *            Either the log message that led to firing this event, or an
 	 *            internal message.
 	 */
-	EventImpl(final long occurrenceTime, final String source, final EventType type, final String message) {
+	EventImpl(final long occurrenceTime, final String source,
+			final EventType type, final String message) {
 		this.occurrenceTime = occurrenceTime;
 		this.source = source;
 		this.type = type;
@@ -130,8 +131,8 @@
 	public String toString() {
 		return this.getClass().getSimpleName() + ": occurenceTime="
 				+ new Date(occurrenceTime) + ", source=\"" + source
-				+ "\", type=" + type.getTypeName() + ", message=\""
-				+ message + "\"";
+				+ "\", type=" + type.getTypeName() + ", message=\"" + message
+				+ "\"";
 	}
 
 	/**

Modified: puppetor/branches/gsoc2008/src/de/uniba/wiai/lspi/puppetor/impl/EventManagerImpl.java
===================================================================
--- puppetor/branches/gsoc2008/src/de/uniba/wiai/lspi/puppetor/impl/EventManagerImpl.java	2008-08-14 12:43:35 UTC (rev 16545)
+++ puppetor/branches/gsoc2008/src/de/uniba/wiai/lspi/puppetor/impl/EventManagerImpl.java	2008-08-14 14:04:37 UTC (rev 16546)
@@ -153,8 +153,7 @@
 		if (source == null || listener == null
 				|| !eventSources.contains(source)) {
 			final IllegalArgumentException e = new IllegalArgumentException();
-			logger.throwing(this.getClass().getName(), "addEventListener",
-					e);
+			logger.throwing(this.getClass().getName(), "addEventListener", e);
 			throw e;
 		}
 
@@ -167,13 +166,11 @@
 		eventHandlers.get(source).add(listener);
 
 		// log change
-		logger
-				.log(Level.FINE, "Added event listener for source " + source);
+		logger.log(Level.FINE, "Added event listener for source " + source);
 
 		// log exiting and return
 		final List<Event> result = getEventHistory(source);
-		logger.exiting(this.getClass().getName(), "addEventListener",
-				result);
+		logger.exiting(this.getClass().getName(), "addEventListener", result);
 		return result;
 	}
 
@@ -186,8 +183,7 @@
 		// check parameters
 		if (listener == null) {
 			final IllegalArgumentException e = new IllegalArgumentException();
-			logger.throwing(this.getClass().getName(), "addEventListener",
-					e);
+			logger.throwing(this.getClass().getName(), "addEventListener", e);
 			throw e;
 		}
 
@@ -205,14 +201,12 @@
 	public synchronized List<Event> getEventHistory(final String source) {
 
 		// log entering
-		logger.entering(this.getClass().getName(), "getEventHistory",
-				source);
+		logger.entering(this.getClass().getName(), "getEventHistory", source);
 
 		// check parameter
 		if (source == null || !eventSources.contains(source)) {
 			final IllegalArgumentException e = new IllegalArgumentException();
-			logger.throwing(this.getClass().getName(), "getEventHistory",
-					e);
+			logger.throwing(this.getClass().getName(), "getEventHistory", e);
 			throw e;
 		}
 
@@ -226,23 +220,21 @@
 		}
 
 		// log exiting and return result
-		logger.exiting(this.getClass().getName(), "getEventHistory",
-				result);
+		logger.exiting(this.getClass().getName(), "getEventHistory", result);
 		return result;
 	}
 
-	public synchronized boolean hasEventOccured(final String source, final EventType type) {
+	public synchronized boolean hasEventOccured(final String source,
+			final EventType type) {
 
 		// log entering
 		logger.entering(this.getClass().getName(), "hasEventOccured",
 				new Object[] { source, type });
 
 		// check parameters
-		if (source == null || type == null
-				|| !eventSources.contains(source)) {
+		if (source == null || type == null || !eventSources.contains(source)) {
 			final IllegalArgumentException e = new IllegalArgumentException();
-			logger.throwing(this.getClass().getName(), "hasEventOccured",
-					e);
+			logger.throwing(this.getClass().getName(), "hasEventOccured", e);
 			throw e;
 		}
 
@@ -258,15 +250,15 @@
 		}
 
 		// log exiting and return result
-		logger.exiting(this.getClass().getName(), "hasEventOccured",
-				result);
+		logger.exiting(this.getClass().getName(), "hasEventOccured", result);
 		return result;
 	}
 
 	/**
 	 * An ordered list of all log statements that are still unparsed.
 	 */
-	private final List<EventImpl> unparsedLogStatements = new LinkedList<EventImpl>();
+	private final List<EventImpl> unparsedLogStatements =
+			new LinkedList<EventImpl>();
 
 	/**
 	 * Stores the occurrence of an unparsed Tor log events that might result in
@@ -282,7 +274,8 @@
 	 * @throws IllegalArgumentException
 	 *             Thrown if the source is unknown.
 	 */
-	synchronized void observeUnparsedEvent(final String source, final String logMessage) {
+	synchronized void observeUnparsedEvent(final String source,
+			final String logMessage) {
 		unparsedLogStatements.add(new EventImpl(source, logMessage));
 		notifyAll();
 	}
@@ -301,18 +294,18 @@
 	 * @throws IllegalArgumentException
 	 *             Thrown if the source is unknown.
 	 */
-	synchronized void observeInternalEvent(final long occurrenceTime, final String source,
-			final EventType type, final String message) {
+	public synchronized void observeInternalEvent(final long occurrenceTime,
+			final String source, final EventType type, final String message) {
 
 		if (!eventSources.contains(source)) {
 			final IllegalArgumentException e = new IllegalArgumentException();
-			logger.throwing(this.getClass().getName(),
-					"observeInternalEvent", e);
+			logger.throwing(this.getClass().getName(), "observeInternalEvent",
+					e);
 			throw e;
 		}
 
-		unparsedLogStatements.add(new EventImpl(occurrenceTime, source,
-				type, message));
+		unparsedLogStatements.add(new EventImpl(occurrenceTime, source, type,
+				message));
 		notifyAll();
 	}
 
@@ -357,7 +350,8 @@
 			final int currentYear = c.get(Calendar.YEAR);
 
 			// try to apply one of the event type patterns
-			for (final Entry<Pattern, EventType> entry : eventTypePatterns.entrySet()) {
+			for (final Entry<Pattern, EventType> entry : eventTypePatterns
+					.entrySet()) {
 				final Matcher matcher = entry.getKey().matcher(line);
 				if (matcher.find()) {
 					final SimpleDateFormat sdf =
@@ -383,8 +377,8 @@
 	 */
 	Map<Pattern, EventType> eventTypePatterns;
 
-	public synchronized void registerEventTypePattern(final String patternString,
-			final EventType eventType) {
+	public synchronized void registerEventTypePattern(
+			final String patternString, final EventType eventType) {
 		eventTypePatterns.put(Pattern.compile(patternString), eventType);
 	}
 
@@ -510,8 +504,8 @@
 
 		for (final EventListener eventHandler : copyOfEventHandlersForAllSources) {
 
-			logger.log(Level.FINE, "Informing event listener "
-					+ eventHandler + " about recently observed event " + event
+			logger.log(Level.FINE, "Informing event listener " + eventHandler
+					+ " about recently observed event " + event
 					+ " from source " + source + "!");
 			eventHandler.handleEvent(event);
 		}
@@ -520,7 +514,8 @@
 		logger.exiting(this.getClass().getName(), "observeEvent");
 	}
 
-	public synchronized void removeEventListener(final EventListener eventListener) {
+	public synchronized void removeEventListener(
+			final EventListener eventListener) {
 
 		// log entering
 		logger.entering(this.getClass().getName(), "removeEventListener",
@@ -529,8 +524,9 @@
 		// check parameters
 		if (eventListener == null) {
 			final IllegalArgumentException e = new IllegalArgumentException();
-			logger.throwing(this.getClass().getName(),
-					"removeEventListener", e);
+			logger
+					.throwing(this.getClass().getName(), "removeEventListener",
+							e);
 			throw e;
 		}
 
@@ -551,18 +547,19 @@
 		logger.exiting(this.getClass().getName(), "removeEventListener");
 	}
 
-	public synchronized void waitForAnyOccurence(final String source, final EventType event) {
+	public synchronized void waitForAnyOccurence(final String source,
+			final EventType event) {
 
 		// log entering
 		logger.entering(this.getClass().getName(), "waitForAnyOccurence",
 				new Object[] { source, event });
 
 		// check parameters
-		if (source == null || event == null
-				|| !eventSources.contains(source)) {
+		if (source == null || event == null || !eventSources.contains(source)) {
 			final IllegalArgumentException e = new IllegalArgumentException();
-			logger.throwing(this.getClass().getName(),
-					"waitForAnyOccurence", e);
+			logger
+					.throwing(this.getClass().getName(), "waitForAnyOccurence",
+							e);
 			throw e;
 		}
 
@@ -583,11 +580,11 @@
 				new Object[] { source, event, maximumTimeToWaitInMillis });
 
 		// check parameters
-		if (source == null || event == null
-				|| !eventSources.contains(source)) {
+		if (source == null || event == null || !eventSources.contains(source)) {
 			final IllegalArgumentException e = new IllegalArgumentException();
-			logger.throwing(this.getClass().getName(),
-					"waitForAnyOccurence", e);
+			logger
+					.throwing(this.getClass().getName(), "waitForAnyOccurence",
+							e);
 			throw e;
 		}
 
@@ -595,8 +592,8 @@
 		if (hasEventOccured(source, event)) {
 			logger.log(Level.FINE, "Waiting for any occurence of event "
 					+ event + " returned immediately!");
-			logger.exiting(this.getClass().getName(),
-					"waitForAnyOccurence", true);
+			logger.exiting(this.getClass().getName(), "waitForAnyOccurence",
+					true);
 			return true;
 		}
 
@@ -605,23 +602,24 @@
 				waitForNextOccurence(source, event, maximumTimeToWaitInMillis);
 
 		// log exiting and return result
-		logger.exiting(this.getClass().getName(), "waitForAnyOccurence",
-				result);
+		logger
+				.exiting(this.getClass().getName(), "waitForAnyOccurence",
+						result);
 		return result;
 	}
 
-	public synchronized void waitForNextOccurence(final String source, final EventType event) {
+	public synchronized void waitForNextOccurence(final String source,
+			final EventType event) {
 
 		// log entering
 		logger.entering(this.getClass().getName(), "waitForNextOccurence",
 				new Object[] { source, event });
 
 		// check parameters
-		if (source == null || event == null
-				|| !eventSources.contains(source)) {
+		if (source == null || event == null || !eventSources.contains(source)) {
 			final IllegalArgumentException e = new IllegalArgumentException();
-			logger.throwing(this.getClass().getName(),
-					"waitForNextOccurence", e);
+			logger.throwing(this.getClass().getName(), "waitForNextOccurence",
+					e);
 			throw e;
 		}
 
@@ -641,11 +639,10 @@
 				new Object[] { source, type, maximumTimeToWaitInMillis });
 
 		// check parameters
-		if (source == null || type == null
-				|| !eventSources.contains(source)) {
+		if (source == null || type == null || !eventSources.contains(source)) {
 			final IllegalArgumentException e = new IllegalArgumentException();
-			logger.throwing(this.getClass().getName(),
-					"waitForNextOccurence", e);
+			logger.throwing(this.getClass().getName(), "waitForNextOccurence",
+					e);
 			throw e;
 		}
 
@@ -678,14 +675,15 @@
 					+ type + " succeeded!");
 
 			// log exiting and return result
-			logger.exiting(this.getClass().getName(),
-					"waitForNextOccurence", true);
+			logger.exiting(this.getClass().getName(), "waitForNextOccurence",
+					true);
 			return true;
 
 		}
 
 		// wait for the given time at most
-		final long endOfTime = System.currentTimeMillis() + maximumTimeToWaitInMillis;
+		final long endOfTime =
+				System.currentTimeMillis() + maximumTimeToWaitInMillis;
 		long timeLeft = 0;
 		while (!hasEventOccured(source, type)
 				&& (timeLeft = endOfTime - System.currentTimeMillis()) > 0) {
@@ -732,8 +730,7 @@
 	void addEventSource(final String source) {
 
 		// log entering
-		logger.entering(this.getClass().getName(), "addEventSource",
-				source);
+		logger.entering(this.getClass().getName(), "addEventSource", source);
 
 		// check if source name is unique in this network
 		if (eventSources.contains(source)) {
@@ -741,8 +738,7 @@
 					new IllegalArgumentException(
 							"There is already an event source with name "
 									+ source + " in this network!");
-			logger
-					.throwing(this.getClass().getName(), "addEventSource", e);
+			logger.throwing(this.getClass().getName(), "addEventSource", e);
 			throw e;
 		}
 

Modified: puppetor/branches/gsoc2008/src/de/uniba/wiai/lspi/puppetor/impl/HiddenServiceImpl.java
===================================================================
--- puppetor/branches/gsoc2008/src/de/uniba/wiai/lspi/puppetor/impl/HiddenServiceImpl.java	2008-08-14 12:43:35 UTC (rev 16545)
+++ puppetor/branches/gsoc2008/src/de/uniba/wiai/lspi/puppetor/impl/HiddenServiceImpl.java	2008-08-14 14:04:37 UTC (rev 16546)
@@ -70,8 +70,8 @@
 	 *             Thrown if an invalid value is given for either of the
 	 *             parameters.
 	 */
-	HiddenServiceImpl(final ProxyNodeImpl node, final String serviceName, final int servicePort,
-			final int virtualPort) {
+	HiddenServiceImpl(final ProxyNodeImpl node, final String serviceName,
+			final int servicePort, final int virtualPort) {
 
 		// check if networkName can be used as logger name
 		if (serviceName == null || serviceName.length() == 0) {
@@ -92,8 +92,7 @@
 			logger.log(Level.SEVERE,
 					"Illegal argument when adding hidden service!");
 			final IllegalArgumentException e = new IllegalArgumentException();
-			logger.throwing(this.getClass().getName(), "addHiddenService",
-					e);
+			logger.throwing(this.getClass().getName(), "addHiddenService", e);
 			throw e;
 		}
 
@@ -126,8 +125,7 @@
 					new PuppeTorException(
 							"Hidden service directory or hostname file does not exist: "
 									+ hiddenServiceFile.getAbsolutePath());
-			logger.throwing(this.getClass().getName(), "getOnionAddress",
-					e);
+			logger.throwing(this.getClass().getName(), "getOnionAddress", e);
 			throw e;
 		}
 
@@ -141,14 +139,12 @@
 		} catch (final IOException e) {
 			final PuppeTorException ex =
 					new PuppeTorException("Could not read hostname file!", e);
-			logger.throwing(this.getClass().getName(), "getOnionAddress",
-					ex);
+			logger.throwing(this.getClass().getName(), "getOnionAddress", ex);
 			throw ex;
 		}
 
 		// log exiting and return address
-		logger.exiting(this.getClass().getName(), "getOnionAddress",
-				address);
+		logger.exiting(this.getClass().getName(), "getOnionAddress", address);
 		return address;
 	}
 

Modified: puppetor/branches/gsoc2008/src/de/uniba/wiai/lspi/puppetor/impl/NetworkImpl.java
===================================================================
--- puppetor/branches/gsoc2008/src/de/uniba/wiai/lspi/puppetor/impl/NetworkImpl.java	2008-08-14 12:43:35 UTC (rev 16545)
+++ puppetor/branches/gsoc2008/src/de/uniba/wiai/lspi/puppetor/impl/NetworkImpl.java	2008-08-14 14:04:37 UTC (rev 16546)
@@ -38,6 +38,7 @@
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
 import java.util.logging.Level;
 import java.util.logging.Logger;
 
@@ -121,8 +122,7 @@
 
 			try {
 				// try to start node
-				success =
-						node.startNode(maximumTimeToWaitInMillis);
+				success = node.startNode(maximumTimeToWaitInMillis);
 			} catch (final PuppeTorException e) {
 				logger.log(Level.SEVERE,
 						"Caught an exception while starting node "
@@ -225,8 +225,7 @@
 		logger = Logger.getLogger("network." + networkName);
 
 		// log entering
-		logger.entering(this.getClass().getName(), "NetworkImpl",
-				networkName);
+		logger.entering(this.getClass().getName(), "NetworkImpl", networkName);
 
 		// TODO is this necessary?!
 		logger.setLevel(Level.ALL);
@@ -245,7 +244,7 @@
 		// + "\\events.log");
 
 		// initialize data structures
-		nodes = new HashMap<String, ProxyNode>();
+		nodes = new ConcurrentHashMap<String, ProxyNode>();
 
 		// create event manager
 		eventManager = new EventManagerImpl(this.networkName);
@@ -283,8 +282,7 @@
 
 	public void configureAsPrivateNetwork() throws PuppeTorException {
 		// log entering
-		logger.entering(this.getClass().getName(),
-				"configureAsPrivateNetwork");
+		logger.entering(this.getClass().getName(), "configureAsPrivateNetwork");
 
 		for (final ProxyNode node : nodes.values()) {
 			if (node.getNodeState() == NodeState.CONFIGURING) {
@@ -314,7 +312,8 @@
 		}
 
 		// read fingerprints for all directories and routers
-		final HashSet<String> approvedRoutersFingerprints = new HashSet<String>();
+		final HashSet<String> approvedRoutersFingerprints =
+				new HashSet<String>();
 		for (final ProxyNode node : nodes.values()) {
 			if (node instanceof RouterNode) {
 				final RouterNode routerOrDirNode = (RouterNode) node;
@@ -333,12 +332,12 @@
 		}
 
 		// log exiting
-		logger.exiting(this.getClass().getName(),
-				"configureAsPrivateNetwork");
+		logger.exiting(this.getClass().getName(), "configureAsPrivateNetwork");
 	}
 
 	public ClientApplication createClient(final String clientApplicationName,
-			final String targetAddress, final int targetPort, final int socksPort) {
+			final String targetAddress, final int targetPort,
+			final int socksPort) {
 		// log entering
 		logger.entering(this.getClass().getName(), "createClient",
 				new Object[] { clientApplicationName, targetAddress,
@@ -357,8 +356,9 @@
 		return client;
 	}
 
-	public DirectoryNode createDirectory(final String nodeName, final int controlPort,
-			final int socksPort, final int orPort, final int dirPort, final String serverIpAddress) {
+	public DirectoryNode createDirectory(final String nodeName,
+			final int controlPort, final int socksPort, final int orPort,
+			final int dirPort, final String serverIpAddress) {
 		// log entering
 		logger.entering(this.getClass().getName(), "createDirectory",
 				new Object[] { nodeName, controlPort, socksPort, orPort,
@@ -380,8 +380,9 @@
 		return dir;
 	}
 
-	public DirectoryNode createDirectory(final String nodeName, final int controlPort,
-			final int socksPort, final int orPort, final int dirPort) {
+	public DirectoryNode createDirectory(final String nodeName,
+			final int controlPort, final int socksPort, final int orPort,
+			final int dirPort) {
 
 		// log entering
 		logger.entering(this.getClass().getName(), "createDirectory",
@@ -398,7 +399,8 @@
 		return dir;
 	}
 
-	public DirectoryNode createDirectory(final String nodeName, final String serverIpAddress) {
+	public DirectoryNode createDirectory(final String nodeName,
+			final String serverIpAddress) {
 
 		// log entering
 		logger.entering(this.getClass().getName(), "createDirectory",
@@ -406,9 +408,8 @@
 
 		// invoke overloaded method
 		final DirectoryNode dir =
-				this.createDirectory(nodeName, portCounter++,
-						portCounter++, portCounter++,
-						portCounter++, serverIpAddress);
+				this.createDirectory(nodeName, portCounter++, portCounter++,
+						portCounter++, portCounter++, serverIpAddress);
 
 		// log exiting and return directory node
 		logger.exiting(this.getClass().getName(), "createDirectory", dir);
@@ -418,25 +419,24 @@
 	public DirectoryNode createDirectory(final String nodeName) {
 
 		// log entering
-		logger.entering(this.getClass().getName(), "createDirectory",
-				nodeName);
+		logger.entering(this.getClass().getName(), "createDirectory", nodeName);
 
 		// invoke overloaded method
 		final DirectoryNode dir =
-				this.createDirectory(nodeName, portCounter++,
-						portCounter++, portCounter++,
-						portCounter++, "127.0.0.1");
+				this.createDirectory(nodeName, portCounter++, portCounter++,
+						portCounter++, portCounter++, "127.0.0.1");
 
 		// log exiting and return directory node
 		logger.exiting(this.getClass().getName(), "createDirectory", dir);
 		return dir;
 	}
 
-	public ProxyNode createProxy(final String nodeName, final int controlPort, final int socksPort) {
+	public ProxyNode createProxy(final String nodeName, final int controlPort,
+			final int socksPort) {
 
 		// log entering
-		logger.entering(this.getClass().getName(), "createProxy",
-				new Object[] { nodeName, controlPort, socksPort });
+		logger.entering(this.getClass().getName(), "createProxy", new Object[] {
+				nodeName, controlPort, socksPort });
 
 		// create proxy node; parameter checking is done in constructor
 		final ProxyNode proxy =
@@ -456,21 +456,20 @@
 	public ProxyNode createProxy(final String nodeName) {
 
 		// log entering
-		logger
-				.entering(this.getClass().getName(), "createProxy", nodeName);
+		logger.entering(this.getClass().getName(), "createProxy", nodeName);
 
 		// invoke overloaded method
 		final ProxyNode proxy =
-				this.createProxy(nodeName, portCounter++,
-						portCounter++);
+				this.createProxy(nodeName, portCounter++, portCounter++);
 
 		// log exiting and return proxy node
 		logger.exiting(this.getClass().getName(), "createProxy", proxy);
 		return proxy;
 	}
 
-	public RouterNode createRouter(final String nodeName, final int controlPort,
-			final int socksPort, final int orPort, final int dirPort, final String serverIpAddress) {
+	public RouterNode createRouter(final String nodeName,
+			final int controlPort, final int socksPort, final int orPort,
+			final int dirPort, final String serverIpAddress) {
 
 		// log entering
 		logger.entering(this.getClass().getName(), "createRouter",
@@ -493,8 +492,9 @@
 		return router;
 	}
 
-	public RouterNode createRouter(final String nodeName, final int controlPort,
-			final int socksPort, final int orPort, final int dirPort) {
+	public RouterNode createRouter(final String nodeName,
+			final int controlPort, final int socksPort, final int orPort,
+			final int dirPort) {
 
 		// log entering
 		logger.entering(this.getClass().getName(), "createRouter",
@@ -511,7 +511,8 @@
 		return dir;
 	}
 
-	public RouterNode createRouter(final String nodeName, final String serverIpAddress) {
+	public RouterNode createRouter(final String nodeName,
+			final String serverIpAddress) {
 
 		// log entering
 		logger.entering(this.getClass().getName(), "createRouter",
@@ -519,9 +520,8 @@
 
 		// invoke overloaded method
 		final RouterNode dir =
-				this.createRouter(nodeName, portCounter++,
-						portCounter++, portCounter++,
-						portCounter++, serverIpAddress);
+				this.createRouter(nodeName, portCounter++, portCounter++,
+						portCounter++, portCounter++, serverIpAddress);
 
 		// log exiting and return directory node
 		logger.exiting(this.getClass().getName(), "createRouter", dir);
@@ -531,14 +531,12 @@
 	public RouterNode createRouter(final String nodeName) {
 
 		// log entering
-		logger.entering(this.getClass().getName(), "createRouter",
-				nodeName);
+		logger.entering(this.getClass().getName(), "createRouter", nodeName);
 
 		// invoke overloaded method
 		final RouterNode router =
-				this.createRouter(nodeName, portCounter++,
-						portCounter++, portCounter++,
-						portCounter++, "127.0.0.1");
+				this.createRouter(nodeName, portCounter++, portCounter++,
+						portCounter++, portCounter++, "127.0.0.1");
 
 		// log exiting and return router node
 		logger.exiting(this.getClass().getName(), "createRouter", router);
@@ -589,7 +587,7 @@
 	 *
 	 * @return The implementation instance of the event manager of this network.
 	 */
-	EventManagerImpl getEventManagerImpl() {
+	public EventManagerImpl getEventManagerImpl() {
 		return eventManager;
 	}
 
@@ -613,7 +611,8 @@
 	}
 
 	public Map<String, RouterNode> getAllRouterNodes() {
-		final Map<String, RouterNode> result = new HashMap<String, RouterNode>();
+		final Map<String, RouterNode> result =
+				new HashMap<String, RouterNode>();
 		for (final String nodeName : nodes.keySet()) {
 			final ProxyNode node = nodes.get(nodeName);
 			if (node instanceof RouterNode && !(node instanceof DirectoryNode)) {
@@ -643,8 +642,8 @@
 			throws PuppeTorException {
 
 		// log entering
-		logger.entering(this.getClass().getName(), "hupUntilUp",
-				new Object[] { tries, hupInterval });
+		logger.entering(this.getClass().getName(), "hupUntilUp", new Object[] {
+				tries, hupInterval });
 
 		// check if all nodes are running
 		for (final ProxyNode node : nodes.values()) {
@@ -653,8 +652,7 @@
 						new IllegalStateException(
 								"All nodes must be running before sending them HUP "
 										+ "commands!");
-				logger
-						.throwing(this.getClass().getName(), "hupUntilUp", e);
+				logger.throwing(this.getClass().getName(), "hupUntilUp", e);
 				throw e;
 			}
 		}
@@ -703,8 +701,8 @@
 				if (allNodesUp()) {
 
 					// log exiting and return true
-					logger.exiting(this.getClass().getName(),
-							"hupUntilUp", true);
+					logger.exiting(this.getClass().getName(), "hupUntilUp",
+							true);
 					return true;
 				}
 			}
@@ -712,8 +710,9 @@
 			logger.log(Level.FINE, "Sending HUP to nodes");
 			// send a HUP signal to all nodes
 			for (final ProxyNode node : nodes.values()) {
-				logger.log(Level.FINE, "Sending HUP to node "
-						+ node.toString());
+				logger
+						.log(Level.FINE, "Sending HUP to node "
+								+ node.toString());
 				node.hup();
 			}
 
@@ -738,16 +737,14 @@
 						new IllegalStateException(
 								"All nodes must be running before sending them HUP "
 										+ "commands!");
-				logger.throwing(this.getClass().getName(), "hupAllNodes",
-						e);
+				logger.throwing(this.getClass().getName(), "hupAllNodes", e);
 				throw e;
 			}
 		}
 
 		// send a HUP signal to all nodes
 		for (final ProxyNode node : nodes.values()) {
-			logger.log(Level.FINE, "Sending HUP to node "
-					+ node.toString());
+			logger.log(Level.FINE, "Sending HUP to node " + node.toString());
 			node.hup();
 		}
 
@@ -769,8 +766,8 @@
 						new IllegalStateException(
 								"All directory nodes must be running before sending "
 										+ "them HUP commands!");
-				logger.throwing(this.getClass().getName(),
-						"hupAllDirectories", e);
+				logger.throwing(this.getClass().getName(), "hupAllDirectories",
+						e);
 				throw e;
 			}
 		}
@@ -778,8 +775,9 @@
 		// send a HUP signal to all nodes
 		for (final ProxyNode node : nodes.values()) {
 			if (node instanceof DirectoryNode) {
-				logger.log(Level.FINE, "Sending HUP to node "
-						+ node.toString());
+				logger
+						.log(Level.FINE, "Sending HUP to node "
+								+ node.toString());
 				node.hup();
 			}
 		}
@@ -836,8 +834,7 @@
 						new IllegalStateException(
 								"All configurations must be written before starting "
 										+ "nodes!");
-				logger
-						.throwing(this.getClass().getName(), "startNodes", e);
+				logger.throwing(this.getClass().getName(), "startNodes", e);
 				throw e;
 			}
 		}
@@ -873,8 +870,7 @@
 						"Interrupt while joining node starter!");
 
 				// log exiting and return false
-				logger.exiting(this.getClass().getName(), "startNodes",
-						false);
+				logger.exiting(this.getClass().getName(), "startNodes", false);
 				return false;
 			}
 
@@ -885,8 +881,7 @@
 						new PuppeTorException("Exception while starting node "
 								+ nodeStarter.node.getNodeName(),
 								caughtException);
-				logger.throwing(this.getClass().getName(), "startNodes",
-						ex);
+				logger.throwing(this.getClass().getName(), "startNodes", ex);
 				throw ex;
 			}
 
@@ -898,8 +893,7 @@
 								+ " seconds.", networkName);
 
 				// log exiting and return false
-				logger.exiting(this.getClass().getName(), "startNodes",
-						false);
+				logger.exiting(this.getClass().getName(), "startNodes", false);
 				return false;
 			}
 		}
@@ -938,7 +932,8 @@
 		logger.exiting(this.getClass().getName(), "writeConfigurations");
 	}
 
-	public void addTemplateConfiguration(final Class<? extends ProxyNode> nodeClass,
+	public void addTemplateConfiguration(
+			final Class<? extends ProxyNode> nodeClass,
 			final String templateConfigurationString) {
 
 		// log entering
@@ -1050,7 +1045,8 @@
 
 		// iterate over existing template configuration strings and remove all
 		// configuration strings that have the given configuration key
-		final List<String> configurationStringsToRemove = new ArrayList<String>();
+		final List<String> configurationStringsToRemove =
+				new ArrayList<String>();
 		for (final String currentConfigurationString : templateConfig) {
 			final String currentConfigurationKey =
 					currentConfigurationString.substring(0,

Modified: puppetor/branches/gsoc2008/src/de/uniba/wiai/lspi/puppetor/impl/ProxyNodeImpl.java
===================================================================
--- puppetor/branches/gsoc2008/src/de/uniba/wiai/lspi/puppetor/impl/ProxyNodeImpl.java	2008-08-14 12:43:35 UTC (rev 16545)
+++ puppetor/branches/gsoc2008/src/de/uniba/wiai/lspi/puppetor/impl/ProxyNodeImpl.java	2008-08-14 14:04:37 UTC (rev 16546)
@@ -160,20 +160,21 @@
 	 *             If at least one of the parameters is <code>null</code> or
 	 *             has an invalid value.
 	 */
-	ProxyNodeImpl(final NetworkImpl network, final String nodeName, final int controlPort,
-			final int socksPort) {
+	ProxyNodeImpl(final NetworkImpl network, final String nodeName,
+			final int controlPort, final int socksPort) {
 
 		// make sure that nodeName is a valid logger name
 		if (nodeName == null || nodeName.length() < 1 || nodeName.length() > 19
 				|| !nodeName.matches("[a-zA-Z0-9]*")) {
-			final String reason = "\"" + nodeName + "\" is not a valid node name!";
-			final IllegalArgumentException e = new IllegalArgumentException(reason);
+			final String reason =
+					"\"" + nodeName + "\" is not a valid node name!";
+			final IllegalArgumentException e =
+					new IllegalArgumentException(reason);
 			throw e;
 		}
 
 		// create logger
-		logger =
-				Logger.getLogger(nodeName + "." + this.getClass().getName());
+		logger = Logger.getLogger(nodeName + "." + this.getClass().getName());
 
 		logger.setLevel(Level.ALL);
 
@@ -233,8 +234,7 @@
 		if (configurationString == null || configurationString.length() < 1
 				|| !configurationString.contains(" ")) {
 			final IllegalArgumentException e = new IllegalArgumentException();
-			logger.throwing(this.getClass().getName(), "addConfiguration",
-					e);
+			logger.throwing(this.getClass().getName(), "addConfiguration", e);
 			throw e;
 		}
 
@@ -254,8 +254,7 @@
 		// check parameter
 		if (configurationStrings == null) {
 			final IllegalArgumentException e = new IllegalArgumentException();
-			logger.throwing(this.getClass().getName(),
-					"addConfigurations", e);
+			logger.throwing(this.getClass().getName(), "addConfigurations", e);
 			throw e;
 		}
 
@@ -278,8 +277,8 @@
 		if (configurationString == null || configurationString.length() < 1
 				|| !configurationString.contains(" ")) {
 			final IllegalArgumentException e = new IllegalArgumentException();
-			logger.throwing(this.getClass().getName(),
-					"replaceConfiguration", e);
+			logger.throwing(this.getClass().getName(), "replaceConfiguration",
+					e);
 			throw e;
 		}
 
@@ -322,14 +321,16 @@
 		// check parameter
 		if (configurationKey == null || configurationKey.length() < 1) {
 			final IllegalArgumentException e = new IllegalArgumentException();
-			logger.throwing(this.getClass().getName(),
-					"deleteConfiguration", e);
+			logger
+					.throwing(this.getClass().getName(), "deleteConfiguration",
+							e);
 			throw e;
 		}
 
 		// iterate over existing configuration strings and remove all
 		// configuration strings that have the given configuration key
-		final List<String> configurationStringsToRemove = new ArrayList<String>();
+		final List<String> configurationStringsToRemove =
+				new ArrayList<String>();
 		for (final String currentConfigurationString : configuration) {
 			final String currentConfigurationKey =
 					currentConfigurationString.substring(0,
@@ -344,8 +345,9 @@
 		logger.exiting(this.getClass().getName(), "deleteConfiguration");
 	}
 
-	public synchronized HiddenService addHiddenService(final String serviceName,
-			final int servicePort, final int virtualPort) {
+	public synchronized HiddenService addHiddenService(
+			final String serviceName, final int servicePort,
+			final int virtualPort) {
 
 		// log entering
 		logger.entering(this.getClass().getName(), "addHiddenService",
@@ -358,19 +360,17 @@
 						virtualPort);
 
 		// add hidden service using Tor controller
-		configuration.add("HiddenServiceDir "
-				+ workingDir.getAbsolutePath() + File.separator + serviceName
-				+ "\nHiddenServicePort " + virtualPort + " 127.0.0.1:"
-				+ servicePort);
+		configuration.add("HiddenServiceDir " + workingDir.getAbsolutePath()
+				+ File.separator + serviceName + "\nHiddenServicePort "
+				+ virtualPort + " 127.0.0.1:" + servicePort);
 
 		// log exiting and return hidden service object
-		logger.exiting(this.getClass().getName(), "addHiddenService",
-				result);
+		logger.exiting(this.getClass().getName(), "addHiddenService", result);
 		return result;
 	}
 
-	public synchronized HiddenService addHiddenService(final String serviceName,
-			final int servicePort) {
+	public synchronized HiddenService addHiddenService(
+			final String serviceName, final int servicePort) {
 
 		// log entering
 		logger.entering(this.getClass().getName(), "addHiddenService",
@@ -381,8 +381,7 @@
 				this.addHiddenService(serviceName, servicePort, 80);
 
 		// log exiting and return hidden service
-		logger.exiting(this.getClass().getName(), "addHiddenService",
-				result);
+		logger.exiting(this.getClass().getName(), "addHiddenService", result);
 		return result;
 	}
 
@@ -394,12 +393,11 @@
 
 		// invoke overloaded method
 		final HiddenService result =
-				this.addHiddenService(serviceName, network
-						.getNextPortNumber(), 80);
+				this.addHiddenService(serviceName, network.getNextPortNumber(),
+						80);
 
 		// log exiting and return hidden service
-		logger.exiting(this.getClass().getName(), "addHiddenService",
-				result);
+		logger.exiting(this.getClass().getName(), "addHiddenService", result);
 		return result;
 	}
 
@@ -438,8 +436,7 @@
 			throw ex;
 		} catch (final NullPointerException e) {
 			// TODO sometimes, this throws a NullPointerException...
-			logger.log(Level.SEVERE, "is conn null? "
-					+ (conn == null));
+			logger.log(Level.SEVERE, "is conn null? " + (conn == null));
 			logger.log(Level.SEVERE,
 					"NullPointerException while sending HUP signal to node "
 							+ toString());
@@ -467,7 +464,6 @@
 		// failure and throw a RuntimeException
 		try {
 			conn.shutdownTor("SHUTDOWN");
-			conn.shutdownTor("SHUTDOWN");
 		} catch (final IOException e) {
 			final PuppeTorException ex =
 					new PuppeTorException(
@@ -481,7 +477,8 @@
 		nodeState = NodeState.SHUT_DOWN;
 
 		// fire event
-		eventManager.observeInternalEvent(System.currentTimeMillis(), getNodeName(), NodeEventType.NODE_STOPPED, "Node stopped.");
+		eventManager.observeInternalEvent(System.currentTimeMillis(),
+				getNodeName(), NodeEventType.NODE_STOPPED, "Node stopped.");
 
 		// log exiting
 		logger.exiting(this.getClass().getName(), "shutdown");
@@ -597,7 +594,7 @@
 
 					// only print out a warning for this exception if this node
 					// is running; otherwise, silently ignore it...
-					if (nodeState == NodeState.RUNNING) {
+					if (getNodeState() == NodeState.RUNNING) {
 						String reason =
 								"IOException when reading output from Tor "
 										+ "process "
@@ -646,8 +643,8 @@
 			// Tor did not manage to start correctly
 			logger.log(Level.WARNING, "Could not start Tor process! Tor "
 					+ "exited with exit value " + exitValue
-					+ "! Please go check the config options in "
-					+ configFile + " manually!");
+					+ "! Please go check the config options in " + configFile
+					+ " manually!");
 
 			// log exiting
 			logger.exiting(this.getClass().getName(), "startNode", false);
@@ -655,8 +652,7 @@
 		}
 
 		// wait for Tor to open the control port
-		logger.log(Level.FINER,
-				"Waiting for Tor to open its control port...");
+		logger.log(Level.FINER, "Waiting for Tor to open its control port...");
 		if (!eventManager.waitForAnyOccurence(nodeName,
 				NodeEventType.NODE_CONTROL_PORT_OPENED,
 				maximumTimeToWaitInMillis)) {
@@ -694,7 +690,8 @@
 		nodeState = NodeState.RUNNING;
 
 		// fire event
-		eventManager.observeInternalEvent(System.currentTimeMillis(), getNodeName(), NodeEventType.NODE_STARTED, "Node started.");
+		eventManager.observeInternalEvent(System.currentTimeMillis(),
+				getNodeName(), NodeEventType.NODE_STARTED, "Node started.");
 
 		// log exiting and return with success
 		logger.exiting(this.getClass().getName(), "startNode", true);
@@ -703,9 +700,8 @@
 
 	@Override
 	public String toString() {
-		return this.getClass().getSimpleName() + ": nodeName=\""
-				+ nodeName + "\", controlPort=" + controlPort
-				+ ", socksPort=" + socksPort;
+		return this.getClass().getSimpleName() + ": nodeName=\"" + nodeName
+				+ "\", controlPort=" + controlPort + ", socksPort=" + socksPort;
 	}
 
 	public synchronized void writeConfiguration() throws PuppeTorException {

Modified: puppetor/branches/gsoc2008/src/de/uniba/wiai/lspi/puppetor/impl/RouterNodeImpl.java
===================================================================
--- puppetor/branches/gsoc2008/src/de/uniba/wiai/lspi/puppetor/impl/RouterNodeImpl.java	2008-08-14 12:43:35 UTC (rev 16545)
+++ puppetor/branches/gsoc2008/src/de/uniba/wiai/lspi/puppetor/impl/RouterNodeImpl.java	2008-08-14 14:04:37 UTC (rev 16546)
@@ -67,8 +67,8 @@
 
 			// create file reference for temporary config file
 			final File tempConfigFile =
-					new File(workingDir.getAbsolutePath()
-							+ File.separator + "torrc.tmp");
+					new File(workingDir.getAbsolutePath() + File.separator
+							+ "torrc.tmp");
 
 			// compose a modified config file, including a DirServer option with
 			// false fingerprint; this is necessary, because otherwise Tor
@@ -151,8 +151,8 @@
 
 			// read fingerprint from file
 			final File fingerprintFile =
-					new File(workingDir.getAbsolutePath()
-							+ File.separator + "fingerprint");
+					new File(workingDir.getAbsolutePath() + File.separator
+							+ "fingerprint");
 			try {
 				final BufferedReader br2 =
 						new BufferedReader(new FileReader(fingerprintFile));
@@ -291,8 +291,9 @@
 	 *             If at least one of the parameters is <code>null</code> or
 	 *             has an invalid value.
 	 */
-	RouterNodeImpl(final NetworkImpl network, final String nodeName, final int controlPort,
-			final int socksPort, final int orPort, final int dirPort, final String serverIpAddress) {
+	RouterNodeImpl(final NetworkImpl network, final String nodeName,
+			final int controlPort, final int socksPort, final int orPort,
+			final int dirPort, final String serverIpAddress) {
 
 		// create superclass instance; parameter checking is done in super
 		// constructor
@@ -313,8 +314,7 @@
 							+ socksPort + ", orPort=" + orPort + ", dirPort="
 							+ dirPort + ", serverIpAddress='" + serverIpAddress
 							+ "'");
-			logger
-					.throwing(this.getClass().getName(), "RouterNodeImpl", e);
+			logger.throwing(this.getClass().getName(), "RouterNodeImpl", e);
 			throw e;
 		}
 
@@ -373,15 +373,15 @@
 		}
 
 		// log exiting
-		logger.exiting(this.getClass().getName(), "getFingerprint",
-				fingerprint);
+		logger
+				.exiting(this.getClass().getName(), "getFingerprint",
+						fingerprint);
 		return fingerprint;
 	}
 
 	@Override
 	public String toString() {
-		return super.toString() + ", orPort=" + orPort + ", dirPort="
-				+ dirPort;
+		return super.toString() + ", orPort=" + orPort + ", dirPort=" + dirPort;
 	}
 
 	public int getDirPort() {

Modified: puppetor/branches/gsoc2008/src/de/uniba/wiai/lspi/puppetor/impl/ServerApplicationImpl.java
===================================================================
--- puppetor/branches/gsoc2008/src/de/uniba/wiai/lspi/puppetor/impl/ServerApplicationImpl.java	2008-08-14 12:43:35 UTC (rev 16545)
+++ puppetor/branches/gsoc2008/src/de/uniba/wiai/lspi/puppetor/impl/ServerApplicationImpl.java	2008-08-14 14:04:37 UTC (rev 16546)
@@ -273,8 +273,8 @@
 	 *             If at least one of the parameters is <code>null</code> or
 	 *             has an invalid value.
 	 */
-	ServerApplicationImpl(final NetworkImpl network, final String serverApplicationName,
-			final int serverPort) {
+	ServerApplicationImpl(final NetworkImpl network,
+			final String serverApplicationName, final int serverPort) {
 
 		// check if serverApplicationName can be used as logger name
 		if (serverApplicationName == null
@@ -287,15 +287,14 @@
 		logger = Logger.getLogger("server." + serverApplicationName);
 
 		// log entering
-		logger.entering(this.getClass().getName(),
-				"ServerApplicationImpl", new Object[] { network,
-						serverApplicationName, serverPort });
+		logger.entering(this.getClass().getName(), "ServerApplicationImpl",
+				new Object[] { network, serverApplicationName, serverPort });
 
 		// check parameters
 		if (network == null || serverPort < 0 || serverPort > 65535) {
 			final IllegalArgumentException e = new IllegalArgumentException();
-			logger.throwing(this.getClass().getName(),
-					"ServerApplicationImpl", e);
+			logger.throwing(this.getClass().getName(), "ServerApplicationImpl",
+					e);
 			throw e;
 		}
 
@@ -366,8 +365,7 @@
 	@Override
 	public String toString() {
 		return this.getClass().getSimpleName() + ": serverApplicationName=\""
-				+ serverApplicationName + "\", serverPort="
-				+ serverPort;
+				+ serverApplicationName + "\", serverPort=" + serverPort;
 	}
 
 	public String getServerApplicationName() {

Modified: puppetor/branches/gsoc2008/src/de/uniba/wiai/lspi/puppetor/rmi/AbstractSlaveFactory.java
===================================================================
--- puppetor/branches/gsoc2008/src/de/uniba/wiai/lspi/puppetor/rmi/AbstractSlaveFactory.java	2008-08-14 12:43:35 UTC (rev 16545)
+++ puppetor/branches/gsoc2008/src/de/uniba/wiai/lspi/puppetor/rmi/AbstractSlaveFactory.java	2008-08-14 14:04:37 UTC (rev 16546)
@@ -82,18 +82,14 @@
 	/**
 	 * Register a new master. Note that calling this twice for different master
 	 * doesn't indicate an error, but trying to to set the same master again is
-	 * a bug.
+	 * a bug. Setting this to null means the connection to the master was
+	 * closed.
 	 *
 	 * @param master
 	 *            The master that should be used from now on.
 	 */
 	final public synchronized static void setMaster(final RemoteMaster master) {
-		if (AbstractSlaveFactory.master == null) {
-			AbstractSlaveFactory.master = master;
-		} else if (AbstractSlaveFactory.master.equals(master)) {
-			throw new IllegalStateException("This master was already "
-					+ "registered!");
-		}
+		AbstractSlaveFactory.master = master;
 	}
 
 	/**

Modified: puppetor/branches/gsoc2008/src/de/uniba/wiai/lspi/puppetor/rmi/LocalMaster.java
===================================================================
--- puppetor/branches/gsoc2008/src/de/uniba/wiai/lspi/puppetor/rmi/LocalMaster.java	2008-08-14 12:43:35 UTC (rev 16545)
+++ puppetor/branches/gsoc2008/src/de/uniba/wiai/lspi/puppetor/rmi/LocalMaster.java	2008-08-14 14:04:37 UTC (rev 16546)
@@ -31,8 +31,6 @@
  */
 package de.uniba.wiai.lspi.puppetor.rmi;
 
-import de.uniba.wiai.lspi.puppetor.rmi.impl.AbstractTaskImpl;
-
 /**
  * Represent a connection between the locally running PuppeTor network Master
  * and a slave. This is the master part of the <code>Master</code> interface.
@@ -46,22 +44,19 @@
 	public Slave getSlave();
 
 	/**
-	 * Register with the TestExecutor
-	 */
-	public void registerWithTestExecutor();
-
-	/**
 	 * Add a new AbstractTaskImpl for the connected slave.
 	 *
 	 * @param abstractTaskImpl
 	 */
-	public void addTask(AbstractTaskImpl abstractTaskImpl);
+	public void addTask(Task task);
 
 	/**
-	 * @return Get the latest TestResult for this slave.
+	 * @param taskId
+	 *            The task id that we want to get
+	 * @return Get the TaskResult for the Task with the specified taskId.
 	 * @throws InterruptedException
 	 *             if interrupted while waiting for the next TestResult
 	 */
-	public TaskResult getTaskResult() throws InterruptedException;
+	public TaskResult getTaskResult(int taskId) throws InterruptedException;
 
 }

Modified: puppetor/branches/gsoc2008/src/de/uniba/wiai/lspi/puppetor/rmi/Network.java
===================================================================
--- puppetor/branches/gsoc2008/src/de/uniba/wiai/lspi/puppetor/rmi/Network.java	2008-08-14 12:43:35 UTC (rev 16545)
+++ puppetor/branches/gsoc2008/src/de/uniba/wiai/lspi/puppetor/rmi/Network.java	2008-08-14 14:04:37 UTC (rev 16546)
@@ -32,16 +32,53 @@
 package de.uniba.wiai.lspi.puppetor.rmi;
 
 import java.io.Serializable;
+import java.util.Set;
 
 public interface Network extends Serializable {
 
 	// XXX Maybe we want to do this in the constructor-SH
-	public void addTorInstanceForMaster(TorInstance torInstance,
-			LocalMaster master);
+	public void addTorInstance(TorInstance torInstance);
 
+	/**
+	 * @return this network's name, mainly to identify it in logs.
+	 */
 	public String getName();
 
+	/**
+	 * @param test
+	 *            add this <code>test</code> to the network.
+	 */
 	public void addTest(Test test);
 
-	public int initializeSlaves(String networkName);
+	/**
+	 * @return a link for each slave that is part of this network.
+	 */
+	public Set<LocalMaster> getMasters();
+
+	/**
+	 * @return all Tor instances that are authorities
+	 */
+	public Set<TorInstance> getDirectoryAuthorities();
+
+	/**
+	 * @return all Tor instances that are routers, but not authorities
+	 */
+	public Set<TorInstance> getRoutersOnly();
+
+	/**
+	 * @return all Tor instances that are routers (including authorities)
+	 */
+	public Set<TorInstance> getRouters();
+
+	/**
+	 * @return all Tor instances that are proxis (but not authorities or
+	 *         routers)
+	 */
+	public Set<TorInstance> getProxiesOnly();
+
+	/**
+	 * @return all Tor instances that are proxies (including authorities and
+	 *         routers)
+	 */
+	public Set<TorInstance> getProxies();
 }

Modified: puppetor/branches/gsoc2008/src/de/uniba/wiai/lspi/puppetor/rmi/NetworkDescription.java
===================================================================
--- puppetor/branches/gsoc2008/src/de/uniba/wiai/lspi/puppetor/rmi/NetworkDescription.java	2008-08-14 12:43:35 UTC (rev 16545)
+++ puppetor/branches/gsoc2008/src/de/uniba/wiai/lspi/puppetor/rmi/NetworkDescription.java	2008-08-14 14:04:37 UTC (rev 16546)
@@ -31,10 +31,12 @@
  */
 package de.uniba.wiai.lspi.puppetor.rmi;
 
-public interface NetworkDescription {
-	public int necessaryRelays();
+import java.io.Serializable;
 
-	public int necessaryClients();
+public interface NetworkDescription extends Serializable {
+	public int necessaryProxies();
 
-	public int necessaryAuthorities();
+	public int necessaryRouters();
+
+	public int necessaryDirectoryAuthorities();
 }

Modified: puppetor/branches/gsoc2008/src/de/uniba/wiai/lspi/puppetor/rmi/Task.java
===================================================================
--- puppetor/branches/gsoc2008/src/de/uniba/wiai/lspi/puppetor/rmi/Task.java	2008-08-14 12:43:35 UTC (rev 16545)
+++ puppetor/branches/gsoc2008/src/de/uniba/wiai/lspi/puppetor/rmi/Task.java	2008-08-14 14:04:37 UTC (rev 16546)
@@ -35,6 +35,19 @@
 
 public interface Task {
 
-	public abstract void execute() throws InterruptedException, RemoteException;
+	/**
+	 * Execute the task. Must be called by the slave.
+	 *
+	 * @throws InterruptedException
+	 *             if interrupted while the task is running.
+	 * @throws RemoteException
+	 *             RMI
+	 */
+	public void execute() throws InterruptedException, RemoteException;
 
+	/**
+	 * Returns this tasks id. Task ids must be globally unique and larger than 0
+	 * or 0 to indicate a task that was sent out by the slave, not the master.
+	 */
+	public int getId();
 }

Modified: puppetor/branches/gsoc2008/src/de/uniba/wiai/lspi/puppetor/rmi/TorInstance.java
===================================================================
--- puppetor/branches/gsoc2008/src/de/uniba/wiai/lspi/puppetor/rmi/TorInstance.java	2008-08-14 12:43:35 UTC (rev 16545)
+++ puppetor/branches/gsoc2008/src/de/uniba/wiai/lspi/puppetor/rmi/TorInstance.java	2008-08-14 14:04:37 UTC (rev 16546)
@@ -50,6 +50,12 @@
 	public List<String> getConfiguration();
 
 	/**
+	 * @return the name by which this Tor instance will be identified at the
+	 *         slaves. See de.uniba.wiai.lspi.puppetor.Network.getNode().
+	 */
+	public String getName();
+
+	/**
 	 * Whether the caller should use the result of
 	 * <code>TorInstance.getExtraConfiguration()</code> to append tor's
 	 * default configuration or replace it.
@@ -63,7 +69,7 @@
 
 	public boolean isBridgeAuthority();
 
-	public boolean isRelay();
+	public boolean isRouter();
 
 	public boolean isExit();
 
@@ -73,5 +79,5 @@
 
 	public boolean isBridge();
 
-	public void linkToSlave(Slave slave);
+	public LocalMaster getMaster();
 }
\ No newline at end of file

Modified: puppetor/branches/gsoc2008/src/de/uniba/wiai/lspi/puppetor/rmi/execute/PuppeTorMasterProgram.java
===================================================================
--- puppetor/branches/gsoc2008/src/de/uniba/wiai/lspi/puppetor/rmi/execute/PuppeTorMasterProgram.java	2008-08-14 12:43:35 UTC (rev 16545)
+++ puppetor/branches/gsoc2008/src/de/uniba/wiai/lspi/puppetor/rmi/execute/PuppeTorMasterProgram.java	2008-08-14 14:04:37 UTC (rev 16546)
@@ -31,6 +31,9 @@
  */
 package de.uniba.wiai.lspi.puppetor.rmi.execute;
 
+import java.rmi.AccessException;
+import java.rmi.NoSuchObjectException;
+import java.rmi.NotBoundException;
 import java.rmi.RemoteException;
 import java.rmi.registry.LocateRegistry;
 import java.rmi.registry.Registry;
@@ -60,9 +63,9 @@
 public class PuppeTorMasterProgram {
 
 	/**
-	 * The login object for clients
+	 * The RMI registry.
 	 */
-	final private PuppeTorMasterProgram.InnerMasterConnector master;
+	private Registry registry;
 
 	/**
 	 * The port the server is supposed to listen on. This port must not be
@@ -81,30 +84,32 @@
 	 *
 	 * @param args
 	 *            Command-line arguments - ignored for now.
+	 * @throws NotBoundException
+	 * @throws RemoteException
+	 * @throws AccessException
 	 */
-	public static void main(final String[] args) {
+	public static void main(final String[] args) throws AccessException,
+			RemoteException, NotBoundException {
 		final PuppeTorMasterProgram server = new PuppeTorMasterProgram();
-		System.out.println("PuppeTorMasterProgram made");
-		server.exportObject();
-		System.out.println("exported objects. waiting for slaves.");
-		try {
-			Thread.sleep(1000 * 10);// XXX this should be two minutes-SH
-		} catch (final InterruptedException e) {
-			e.printStackTrace();
-			throw new RuntimeException("This is the main thread. We don't "
-					+ "want to be interrupted.");
-		}
+
 		final TestExecutor exec =
 				AbstractMasterFactory.getInstance().getTestExecutorInstance();
-		System.out.println("trying to start executor");
 		exec.startTesting();
+		server.unregisterRMIRegistry();
+		// Suggest a garbage collection, may increase shutdown.
+		System.gc();
 	}
 
 	/**
 	 * Private constructor to set up RMI-related Java-internal variables and
 	 * create a <code>RemotePuppeTorImpl</code>.
+	 *
+	 * @throws NotBoundException
+	 * @throws RemoteException
+	 * @throws AccessException
 	 */
-	private PuppeTorMasterProgram() {
+	private PuppeTorMasterProgram() throws AccessException, RemoteException,
+			NotBoundException {
 		// Set the location of the keystore where your private certificate is.
 		System.setProperty("javax.net.ssl.keyStore", "res/keystore");
 		// Set the password for your keystore.
@@ -117,33 +122,20 @@
 		System.setProperty("javax.net.ssl.trustStore", "res/truststore");
 		// Tell the RMI system the location of the master
 		System.setProperty("java.rmi.server.hostname", serveraddress);
+		// Use a timeout of 15 seconds to detect disconnected clients.
+		System.setProperty("java.rmi.dgc.leaseValue", "15000");
+
 		// Set up the factories we want to use
 		AbstractMasterFactory.initialize(new MasterImplFactory());
 
 		registerTests();
+		final InnerMasterConnector master = InnerMasterConnector.getInstance();
 
 		try {
-			master = new InnerMasterConnector();
-		} catch (final RemoteException e) {
-			// We cannot do much better here. This is supposed to just work.
-			e.printStackTrace();
-			throw new RuntimeException("Couldn't create remote object. Dying.");
-		}
-	}
-
-	/**
-	 * Create an RMI registry that uses SSL-secured Sockets for communication,
-	 * requires client authentication, and bind our <code>MasterConnector</code>
-	 * in the registry. If this doesn't work, most likely the user's system
-	 * configuration isn't correct.
-	 */
-	private void exportObject() {
-		try {
-			final Registry registry =
+			registry =
 					LocateRegistry.createRegistry(serverport,
 							new SslRMIClientSocketFactory(),
 							new SslRMIServerSocketFactory(null, null, true));
-
 			registry.bind("Master", master);
 		} catch (final Throwable th) {
 			th.printStackTrace();
@@ -151,8 +143,19 @@
 					"Could not create the registry or bind"
 							+ "an object in it. Please check your system's configuration. "
 							+ th);
+		}
 
+		System.out.println("waiting for slaves.");
+		try {
+			Thread.sleep(1000 * 10);// XXX this should be two minutes-SH
+		} catch (final InterruptedException e) {
+			e.printStackTrace();
+			throw new RuntimeException("This is the main thread. We don't "
+					+ "want to be interrupted.");
 		}
+		registry.unbind("Master");
+		// Only unbinding is not enough, the object will still be exported.
+		UnicastRemoteObject.unexportObject(master, true);
 	}
 
 	/**
@@ -166,6 +169,11 @@
 						.createPublicNetworkTestForClientsOnly("Access google over public Tor network."));
 	}
 
+	private void unregisterRMIRegistry() throws NoSuchObjectException {
+		UnicastRemoteObject.unexportObject(registry, true);
+		registry = null;
+	}
+
 	static class InnerMasterConnector extends UnicastRemoteObject implements
 			MasterConnector {
 		/**
@@ -174,20 +182,36 @@
 		 */
 		private static final long serialVersionUID = 1L;
 
+		private static InnerMasterConnector instance;
+
+		static {
+			try {
+				instance = new InnerMasterConnector();
+			} catch (final RemoteException e) {
+				e.printStackTrace();
+				throw new ExceptionInInitializerError(e);
+			}
+		}
+
 		/**
-		 * empty default constructor necessary for the Exception
+		 * private constructor, Singleton
 		 *
 		 * @throws RemoteException
 		 *             RMI
 		 */
-		public InnerMasterConnector() throws RemoteException {}
+		private InnerMasterConnector() throws RemoteException {}
 
+		public static InnerMasterConnector getInstance() {
+			return instance;
+		}
+
 		public RemoteMaster registerClient(final Slave slave)
 				throws RemoteException {
 			final AbstractMasterFactory fact =
 					AbstractMasterFactory.getInstance();
 			final Master master = fact.createMaster(slave);
-			((LocalMaster) master).registerWithTestExecutor();
+			AbstractMasterFactory.getInstance().getTestExecutorInstance()
+					.registerLocalMaster((LocalMaster) master);
 			return (RemoteMaster) master;
 		}
 	}

Modified: puppetor/branches/gsoc2008/src/de/uniba/wiai/lspi/puppetor/rmi/execute/PuppeTorSlaveProgram.java
===================================================================
--- puppetor/branches/gsoc2008/src/de/uniba/wiai/lspi/puppetor/rmi/execute/PuppeTorSlaveProgram.java	2008-08-14 12:43:35 UTC (rev 16545)
+++ puppetor/branches/gsoc2008/src/de/uniba/wiai/lspi/puppetor/rmi/execute/PuppeTorSlaveProgram.java	2008-08-14 14:04:37 UTC (rev 16546)
@@ -31,6 +31,7 @@
  */
 package de.uniba.wiai.lspi.puppetor.rmi.execute;
 
+import java.rmi.NoSuchObjectException;
 import java.rmi.NotBoundException;
 import java.rmi.RemoteException;
 import java.rmi.registry.LocateRegistry;
@@ -46,7 +47,6 @@
 import de.uniba.wiai.lspi.puppetor.rmi.AbstractSlaveFactory;
 import de.uniba.wiai.lspi.puppetor.rmi.MasterConnector;
 import de.uniba.wiai.lspi.puppetor.rmi.Slave;
-import de.uniba.wiai.lspi.puppetor.rmi.RemoteMaster;
 import de.uniba.wiai.lspi.puppetor.rmi.Task;
 import de.uniba.wiai.lspi.puppetor.rmi.impl.SlaveImplFactory;
 import de.uniba.wiai.lspi.puppetor.rmi.tasks.TerminateTask;
@@ -64,12 +64,6 @@
 public class PuppeTorSlaveProgram {
 
 	/**
-	 * The <code>RemotePuppeTor</code> object that is exported by the server.
-	 * This variable may be written to only from the main thread.
-	 */
-	volatile private RemoteMaster master;
-
-	/**
 	 * The port the master server is supposed to listen on. This port must not
 	 * be firewalled and must be forwarded to the machine if necessary. Use the
 	 * same value as you used for the master's configuration.
@@ -102,45 +96,60 @@
 	 *
 	 * @param args
 	 *            Command-line arguments
+	 * @throws NoSuchObjectException
 	 */
 	public static void main(final String[] args) {
 		final PuppeTorSlaveProgram slave = new PuppeTorSlaveProgram();
-		System.out.println("PuppeTorSlaveProgram made");
+		// XXX put this in a while(true) -SH
+		// while(true) {
 		while (slave.connectToMaster() == false) {
 			try {
-				Thread.sleep(60000); // wait one minute
+				Thread.sleep(5000); // wait one minute
 			} catch (final InterruptedException e) {
 				// and immediatly retry if we're interrupted.
 			}
 		}
-		System.out.println("Connected to master");
 
-		new Thread(new Runnable() {
+		final Thread taskGetter = new Thread(new Runnable() {
 			public void run() {
 				while (true) {
 					try {
 						try {
-							tasks.put(slave.master.getNewTask());
-							System.out.println("added task");
+							// XXX I dislike the following three lines, but
+							// interruption doesn't work while we wait for the
+							// master. Maybe there is a better solution that
+							// doesn't eat the poison pill twice. -SH
+							Task task =
+									AbstractSlaveFactory.getMaster()
+											.getNewTask();
+							tasks.put(task);
+							if (task instanceof TerminateTask) {
+								break;
+							}
 						} catch (final RemoteException e) {
-							// The connection to the master broke down. Stop
-							// this thread.
-							e.printStackTrace();
-							tasks.put(new TerminateTask("local termination"));
+							// Empty the task queue - we cannot send any results
+							// back, anyways.
+							// tasks.clear();
+							// A taskid of 0 indicates a local Task
+							tasks
+									.put(new TerminateTask(0,
+											"local termination"));
 							Thread.currentThread().interrupt();
 						}
 					} catch (final InterruptedException e) {
-						e.printStackTrace();
 						Thread.currentThread().interrupt();
 					}
 					if (Thread.interrupted()) {
-						System.out.println("interrupted.");
 						break;
 					}
 
 				}
 			}
-		}).start();
+		});
+
+		taskGetter.start();
+		// XXX We use just a single Thread here. That isn't the smartest move.
+		// -SH
 		try {
 			while (true) {
 				final Task newTask = tasks.take();
@@ -149,15 +158,13 @@
 					break;
 				}
 			}
-		} catch (final InterruptedException e) {
-			// XXX handle-SH
-			System.out.println("handle stuff here");
-		} catch (final RemoteException e) {
-			// XXX handle-SH
-			System.out.println("handle stuff here");
-		}
+		} catch (final InterruptedException ignored) {} catch (final RemoteException ignored) {}
+		taskGetter.interrupt();
+		AbstractSlaveFactory.setMaster(null);
 	}
 
+	// }
+
 	/**
 	 * Private constructor to set up RMI-related Java-internal variables.
 	 */
@@ -207,26 +214,19 @@
 			final Registry registry =
 					LocateRegistry.getRegistry(serveraddress, serverport,
 							new SslRMIClientSocketFactory());
-
-			master =
-					((MasterConnector) registry.lookup("Master"))
-							.registerClient(slave);
-			AbstractSlaveFactory.setMaster(master);
+			AbstractSlaveFactory.setMaster(((MasterConnector) registry
+					.lookup("Master")).registerClient(slave));
 		} catch (final NotBoundException e) {
 			e.printStackTrace();
 			System.out.println("We could connect, but the master has not "
 					+ "exported the Master Object yet." + e);
 			return false;
 		} catch (final RemoteException e) {
-			// XXX remove the next two lines once this stabilizes-SH
-			e.printStackTrace();
-			System.out.println("Server down " + e);
 			return false;
 		} catch (final IllegalArgumentException e) {
-			e.printStackTrace();
-			System.out.println("A slave with this name is already connected "
-					+ "to the server! " + e);
-			return false;
+			throw new RuntimeException(
+					"A slave with this name is already connected "
+							+ "to the server! " + e);
 		}
 		return true;
 	}

Modified: puppetor/branches/gsoc2008/src/de/uniba/wiai/lspi/puppetor/rmi/impl/AbstractTaskImpl.java
===================================================================
--- puppetor/branches/gsoc2008/src/de/uniba/wiai/lspi/puppetor/rmi/impl/AbstractTaskImpl.java	2008-08-14 12:43:35 UTC (rev 16545)
+++ puppetor/branches/gsoc2008/src/de/uniba/wiai/lspi/puppetor/rmi/impl/AbstractTaskImpl.java	2008-08-14 14:04:37 UTC (rev 16546)
@@ -35,25 +35,40 @@
 import java.rmi.RemoteException;
 
 import de.uniba.wiai.lspi.puppetor.rmi.AbstractSlaveFactory;
-import de.uniba.wiai.lspi.puppetor.rmi.RemoteMaster;
 import de.uniba.wiai.lspi.puppetor.rmi.Task;
+import de.uniba.wiai.lspi.puppetor.rmi.TaskResult;
 
 public abstract class AbstractTaskImpl implements Serializable, Task {
 
 	/**
-	 * The name that will be shared across all slaves to identify this network.
+	 * A human-readable name for the task (to be included in log-messages, etc).
 	 */
 	final protected String name;
 
-	public AbstractTaskImpl(final String name) {
+	/**
+	 * The globally unique id for this task.
+	 */
+	final protected int id;
+
+	public AbstractTaskImpl(final int id, final String name) {
 		this.name = name;
+		this.id = id;
 	}
 
+	public int getId() {
+		return id;
+	}
+
 	public abstract void execute() throws InterruptedException, RemoteException;
 
-	protected void reportResult(final boolean success) throws InterruptedException,
+	protected void reportResult(final boolean success)
+			throws InterruptedException, RemoteException {
+		reportResult(success, new TaskResultImpl(success, this));
+	}
+
+	protected void reportResult(final boolean success,
+			final TaskResult taskResult) throws InterruptedException,
 			RemoteException {
-		final RemoteMaster master = AbstractSlaveFactory.getMaster();
-		master.reportTaskResult(new TaskResultImpl(success, this));
+		AbstractSlaveFactory.getMaster().reportTaskResult(taskResult);
 	}
 }

Modified: puppetor/branches/gsoc2008/src/de/uniba/wiai/lspi/puppetor/rmi/impl/MasterImpl.java
===================================================================
--- puppetor/branches/gsoc2008/src/de/uniba/wiai/lspi/puppetor/rmi/impl/MasterImpl.java	2008-08-14 12:43:35 UTC (rev 16545)
+++ puppetor/branches/gsoc2008/src/de/uniba/wiai/lspi/puppetor/rmi/impl/MasterImpl.java	2008-08-14 14:04:37 UTC (rev 16546)
@@ -68,15 +68,12 @@
 
 	private final BlockingQueue<TaskResult> completedTasks;
 
+	private final Object completedTasksLock = new Object();
+
 	public Slave getSlave() {
 		return slave;
 	}
 
-	public void registerWithTestExecutor() {
-		AbstractMasterFactory.getInstance().getTestExecutorInstance()
-				.registerLocalMaster(this);
-	}
-
 	/**
 	 * Check the slave object for validity and save it for further reference
 	 *
@@ -98,11 +95,23 @@
 
 	public void reportTaskResult(final TaskResult task) throws RemoteException,
 			InterruptedException {
-		completedTasks.put(task);
+		synchronized (completedTasksLock) {
+			completedTasks.put(task);
+			completedTasksLock.notifyAll();
+		}
 	}
 
-	public TaskResult getTaskResult() throws InterruptedException {
-		return completedTasks.take();
+	public TaskResult getTaskResult(final int taskId)
+			throws InterruptedException {
+
+		synchronized (completedTasksLock) {
+			TaskResult res;
+			while ((res = completedTasks.peek()) == null
+					|| res.getTask().getId() != taskId) {
+				completedTasksLock.wait();
+			}
+			return completedTasks.take();
+		}
 	}
 
 	/**
@@ -112,11 +121,12 @@
 	 * do that when there are the queues that I mentioned.-SH
 	 */
 	public void unreferenced() {
+		System.out.println("unreferenced called");
 		AbstractMasterFactory.getInstance().getTestExecutorInstance()
 				.unregisterLocalMaster(this);
 	}
 
-	public void addTask(final AbstractTaskImpl abstractTaskImpl) {
-		tasks.add(abstractTaskImpl);
+	public void addTask(final Task task) {
+		tasks.add(task);
 	}
 }

Modified: puppetor/branches/gsoc2008/src/de/uniba/wiai/lspi/puppetor/rmi/impl/NetworkDescriptionImpl.java
===================================================================
--- puppetor/branches/gsoc2008/src/de/uniba/wiai/lspi/puppetor/rmi/impl/NetworkDescriptionImpl.java	2008-08-14 12:43:35 UTC (rev 16545)
+++ puppetor/branches/gsoc2008/src/de/uniba/wiai/lspi/puppetor/rmi/impl/NetworkDescriptionImpl.java	2008-08-14 14:04:37 UTC (rev 16546)
@@ -42,27 +42,28 @@
 	 */
 	private static final long serialVersionUID = 1L;
 
-	private final AtomicInteger numClients;
-	private final AtomicInteger numRelays;
-	private final AtomicInteger numAuthorities;
+	private final AtomicInteger numProxies;
+	private final AtomicInteger numRouters;
+	private final AtomicInteger numDirectoryAuthorities;
 
-	public int necessaryClients() {
-		return numClients.get();
+	public int necessaryProxies() {
+		return numProxies.get();
 	}
 
-	public int necessaryRelays() {
-		return numRelays.get();
+	public int necessaryRouters() {
+		return numRouters.get();
 	}
 
-	public int necessaryAuthorities() {
-		return numAuthorities.get();
+	public int necessaryDirectoryAuthorities() {
+		return numDirectoryAuthorities.get();
 	}
 
-	public NetworkDescriptionImpl(final int numClients, final int numRelays,
-			final int numAuthorities) {
-		this.numClients = new AtomicInteger(numClients);
-		this.numRelays = new AtomicInteger(numRelays);
-		this.numAuthorities = new AtomicInteger(numAuthorities);
+	public NetworkDescriptionImpl(final int numProxies, final int numRouters,
+			final int numDirectoryAuthorities) {
+		this.numProxies = new AtomicInteger(numProxies);
+		this.numRouters = new AtomicInteger(numRouters);
+		this.numDirectoryAuthorities =
+				new AtomicInteger(numDirectoryAuthorities);
 	}
 
 }

Modified: puppetor/branches/gsoc2008/src/de/uniba/wiai/lspi/puppetor/rmi/impl/NetworkImpl.java
===================================================================
--- puppetor/branches/gsoc2008/src/de/uniba/wiai/lspi/puppetor/rmi/impl/NetworkImpl.java	2008-08-14 12:43:35 UTC (rev 16545)
+++ puppetor/branches/gsoc2008/src/de/uniba/wiai/lspi/puppetor/rmi/impl/NetworkImpl.java	2008-08-14 14:04:37 UTC (rev 16546)
@@ -31,10 +31,10 @@
  */
 package de.uniba.wiai.lspi.puppetor.rmi.impl;
 
+import java.util.Collections;
+import java.util.HashSet;
 import java.util.List;
 import java.util.Set;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.ConcurrentMap;
 import java.util.concurrent.CopyOnWriteArrayList;
 import java.util.concurrent.CopyOnWriteArraySet;
 
@@ -42,7 +42,6 @@
 import de.uniba.wiai.lspi.puppetor.rmi.Network;
 import de.uniba.wiai.lspi.puppetor.rmi.Test;
 import de.uniba.wiai.lspi.puppetor.rmi.TorInstance;
-import de.uniba.wiai.lspi.puppetor.rmi.tasks.CreateNetworkTask;
 
 public class NetworkImpl implements Network {
 
@@ -62,21 +61,16 @@
 	 */
 	private final List<Test> tests;
 
-	private final ConcurrentMap<LocalMaster, Set<TorInstance>> torInstances;
+	private final Set<TorInstance> torInstances;
 
 	public NetworkImpl(final String name) {
 		this.name = name;
 		tests = new CopyOnWriteArrayList<Test>();
-		torInstances =
-				new ConcurrentHashMap<LocalMaster, Set<TorInstance>>();
+		torInstances = new CopyOnWriteArraySet<TorInstance>();
 	}
 
-	public void addTorInstanceForMaster(final TorInstance torInstance,
-			final LocalMaster master) {
-		torInstance.linkToSlave(master.getSlave());
-		torInstances
-				.putIfAbsent(master, new CopyOnWriteArraySet<TorInstance>());
-		torInstances.get(master).add(torInstance);
+	public void addTorInstance(final TorInstance torInstance) {
+		torInstances.add(torInstance);
 	}
 
 	public String getName() {
@@ -87,13 +81,56 @@
 		tests.add(test);
 	}
 
-	public int initializeSlaves(final String networkName) {
-		int i = 0;
-		for (final LocalMaster master : torInstances.keySet()) {
-			master.addTask(new CreateNetworkTask(networkName));
-			i++;
+	public Set<LocalMaster> getMasters() {
+		final Set<LocalMaster> masters = new HashSet<LocalMaster>();
+		for (final TorInstance torInstance : torInstances) {
+			masters.add(torInstance.getMaster());
 		}
-		return i;
+		return Collections.unmodifiableSet(masters);
 	}
 
+	public Set<TorInstance> getDirectoryAuthorities() {
+		final Set<TorInstance> authorities = new HashSet<TorInstance>();
+		for (final TorInstance torInstance : torInstances) {
+			if (torInstance.isDirectoryAuthority()) {
+				authorities.add(torInstance);
+			}
+		}
+		return Collections.unmodifiableSet(authorities);
+	}
+
+	public Set<TorInstance> getProxies() {
+		return Collections.unmodifiableSet(torInstances);
+	}
+
+	public Set<TorInstance> getProxiesOnly() {
+		final Set<TorInstance> proxies = new HashSet<TorInstance>();
+		for (final TorInstance torInstance : torInstances) {
+			if (!torInstance.isRouter()) {
+				proxies.add(torInstance);
+			}
+		}
+		return Collections.unmodifiableSet(proxies);
+	}
+
+	public Set<TorInstance> getRouters() {
+		final Set<TorInstance> routers = new HashSet<TorInstance>();
+		for (final TorInstance torInstance : torInstances) {
+			if (!torInstance.isRouter()) {
+				routers.add(torInstance);
+			}
+		}
+		return Collections.unmodifiableSet(routers);
+	}
+
+	public Set<TorInstance> getRoutersOnly() {
+		final Set<TorInstance> routers = new HashSet<TorInstance>();
+		for (final TorInstance torInstance : torInstances) {
+			if (torInstance.isRouter() && !torInstance.isDirectoryAuthority()) {
+				routers.add(torInstance);
+			}
+		}
+		return Collections.unmodifiableSet(routers);
+	}
+
 }

Modified: puppetor/branches/gsoc2008/src/de/uniba/wiai/lspi/puppetor/rmi/impl/TestExecutorImpl.java
===================================================================
--- puppetor/branches/gsoc2008/src/de/uniba/wiai/lspi/puppetor/rmi/impl/TestExecutorImpl.java	2008-08-14 12:43:35 UTC (rev 16545)
+++ puppetor/branches/gsoc2008/src/de/uniba/wiai/lspi/puppetor/rmi/impl/TestExecutorImpl.java	2008-08-14 14:04:37 UTC (rev 16546)
@@ -31,22 +31,46 @@
  */
 package de.uniba.wiai.lspi.puppetor.rmi.impl;
 
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
+import java.rmi.NoSuchObjectException;
+import java.rmi.server.UnicastRemoteObject;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.LinkedList;
 import java.util.List;
 import java.util.Map;
+import java.util.Queue;
 import java.util.Set;
 import java.util.Vector;
+import java.util.concurrent.Callable;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.ConcurrentMap;
 import java.util.concurrent.CopyOnWriteArraySet;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.FutureTask;
 import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.atomic.AtomicInteger;
 
 import de.uniba.wiai.lspi.puppetor.rmi.Network;
 import de.uniba.wiai.lspi.puppetor.rmi.LocalMaster;
 import de.uniba.wiai.lspi.puppetor.rmi.NetworkDescription;
+import de.uniba.wiai.lspi.puppetor.rmi.RemoteMaster;
+import de.uniba.wiai.lspi.puppetor.rmi.Task;
 import de.uniba.wiai.lspi.puppetor.rmi.TaskResult;
 import de.uniba.wiai.lspi.puppetor.rmi.Test;
 import de.uniba.wiai.lspi.puppetor.rmi.TestResult;
 import de.uniba.wiai.lspi.puppetor.rmi.TestExecutor;
+import de.uniba.wiai.lspi.puppetor.rmi.TorInstance;
+import de.uniba.wiai.lspi.puppetor.rmi.tasks.BuildCircuitsTask;
+import de.uniba.wiai.lspi.puppetor.rmi.tasks.CreateDirectoryAuthorityTask;
+import de.uniba.wiai.lspi.puppetor.rmi.tasks.CreateNetworkTask;
+import de.uniba.wiai.lspi.puppetor.rmi.tasks.CreateProxyTask;
+import de.uniba.wiai.lspi.puppetor.rmi.tasks.CreateRouterTask;
+import de.uniba.wiai.lspi.puppetor.rmi.tasks.ShutdownNodesTask;
+import de.uniba.wiai.lspi.puppetor.rmi.tasks.StartNodesTask;
+import de.uniba.wiai.lspi.puppetor.rmi.tasks.TerminateTask;
 
 /**
  * @author Sebastian Hahn
@@ -104,11 +128,13 @@
 	 */
 	private static AtomicBoolean startedTesting = new AtomicBoolean(false);
 
-	private static Set<TaskResult> taskResults =
-			new CopyOnWriteArraySet<TaskResult>();
+	/**
+	 * Store the id for the next task. Every task gets its own unique id > 0. A
+	 * task id equal to 0 indicates that the task was created by the slave to
+	 * stop execution.
+	 */
+	private static AtomicInteger nextTaskId = new AtomicInteger(1);
 
-	protected static Object taskResultsLock = new Object();
-
 	/**
 	 * Singleton
 	 */
@@ -133,6 +159,12 @@
 		// XXX Don't forget to mark all tests as failed that depended on this
 		// slave if we have already started with testing-SH
 		System.out.println("unregister slave " + master.getSlave().getName());
+		try {
+			UnicastRemoteObject.unexportObject((RemoteMaster) master, true);
+		} catch (final NoSuchObjectException e) {
+			throw new RuntimeException(
+					"This is a bug. The master should have been exported.");
+		}
 		if (masters.remove(master.getSlave().getName()) == null) {
 			throw new RuntimeException(
 					"This is a bug. unregisterLocalMaster must never be called twice for the same master.");
@@ -149,7 +181,7 @@
 	protected void evaluateNetwork() {
 		if (startedTesting.get() == false) {
 			throw new RuntimeException("Bug: Testing has not been started.");
-		// XXX We need to actually check the network.-SH
+			// XXX We need to actually check the network.-SH
 		}
 	}
 
@@ -166,44 +198,179 @@
 		for (final Test test : newTests) {
 			makeNetworks(test);
 		}
-		final int networkCount = 0;
-		for (final LocalMaster master : masters.values()) {
-			new Thread(new TaskCollector(master)).start();
-		}
+		// final int networkCount = 0;
 		// XXX cancelled networks will still appear here...=SH
 		for (final Network nw : networks) {
-			final int slaveCount = nw.initializeSlaves("Network #: " + networkCount);
+
 			try {
-				synchronized (taskResultsLock) {
-					while (taskResults.size() < slaveCount) {
-						taskResultsLock.wait();
-					}
+				executeTaskForMaster(nw.getMasters(), CreateNetworkTask.class,
+						nw.getName(), nw.getName());
+				// The network has been created at the slaves. Set up
+				// authorities, routers and proxies.
 
+				final Queue<LocalMaster> masters =
+						new LinkedList<LocalMaster>();
+
+				for (final TorInstance authority : nw.getDirectoryAuthorities()) {
+					masters.add(authority.getMaster());
 				}
-			} catch (final InterruptedException e) {
-				System.out.println("Interrupted");
-				// XXX Mark all the tests for this network failed.-SH
+				executeTaskForMaster(masters,
+						CreateDirectoryAuthorityTask.class, nw.getName(),
+						"authority");
+				masters.clear();
+				System.out.println("after authoritycreation");
+				for (final TorInstance router : nw.getRoutersOnly()) {
+					masters.add(router.getMaster());
+				}
+				executeTaskForMaster(masters, CreateRouterTask.class, nw
+						.getName(), "router");
+				masters.clear();
+				for (final TorInstance proxy : nw.getProxiesOnly()) {
+					masters.add(proxy.getMaster());
+				}
+				executeTaskForMaster(masters, CreateProxyTask.class, nw
+						.getName(), "proxy");
+
+				// Start the nodes ...
+				executeTaskForMaster(nw.getMasters(), StartNodesTask.class, nw
+						.getName(), "");
+				// ... and build circuits. This may take some time.
+				System.out.println("Build circuits");
+				executeTaskForMaster(nw.getMasters(), BuildCircuitsTask.class,
+						nw.getName(), "");
+
+				// Put the tests here.
+
+				System.out.println("Shutdown the nodes");
+				// We don't need the network anymore, make sure it's shut down
+				// properly.
+				executeTaskForMaster(nw.getMasters(), ShutdownNodesTask.class,
+						nw.getName(), "");
+				System.out.println("Sending the terminate task");
+				executeTaskForMaster(nw.getMasters(), TerminateTask.class, nw
+						.getName(), "");
+
+			} catch (final TaskExecutionNotSuccessfulException e) {
+				e.printStackTrace();
+				// XXX Log this properly -SH
 			}
-			// XXXBlock here or cancel when interrupted.... -SH
 
 		}
+		System.out.println("done testing");
+		networks.clear();
 	}
 
+	// protected void executeTaskForTorInstance(final List<TorInstance>
+	// instances,
+	// final Task task) {}
+
+	/**
+	 * Execute the passed <code>Task</code> once per passed
+	 * <code>LocalMaster</code>. If a <code>LocalMaster</code> is passed
+	 * more than once, the task will be executed multiple times.
+	 *
+	 * @param masters
+	 *            execute the task for those masters.
+	 * @param task
+	 *            execute this task.
+	 * @throws TaskExecutionNotSuccessfulException
+	 *             Indicates a failure during task execution
+	 */
+	protected void executeTaskForMaster(final Collection<LocalMaster> masters,
+			final Class<? extends Task> taskClass, final String networkName,
+			final String taskName) throws TaskExecutionNotSuccessfulException {
+
+		if (masters.isEmpty()) {
+			return;
+		}
+		int i = 1;
+		final Set<MasterTask> mTasks = new HashSet<MasterTask>();
+		Constructor<? extends Task> ctor = null;
+		try {
+			try {
+				ctor =
+						taskClass.getConstructor(int.class, String.class,
+								String.class);
+				for (final LocalMaster master : masters) {
+					mTasks.add(new MasterTask(master, ctor.newInstance(
+							nextTaskId.getAndIncrement(), networkName, taskName
+									+ i++)));
+				}
+			} catch (final NoSuchMethodException e) {
+				ctor = taskClass.getConstructor(int.class, String.class);
+				for (final LocalMaster master : masters) {
+					mTasks.add(new MasterTask(master, ctor.newInstance(
+							nextTaskId.getAndIncrement(), networkName)));
+				}
+			}
+
+			final TaskManager man = new TaskManager(mTasks);
+			final FutureTask<Boolean> futureTask = new FutureTask<Boolean>(man);
+			new Thread(futureTask).start();
+			try {
+				if (futureTask.get() == false) {
+					throw new TaskExecutionNotSuccessfulException(man
+							.getTaskResults());
+				}
+			} catch (final InterruptedException e) {
+				throw new TaskExecutionNotSuccessfulException(null);
+			} catch (final ExecutionException e) {
+				// XXX Log this with the cause. Should not happen. -SH
+				e.printStackTrace();
+				throw new TaskExecutionNotSuccessfulException(null);
+			}
+		} catch (final SecurityException e) {
+			throw new RuntimeException(
+					"BUG: We're not using a security manager, so where does this exception come from?");
+		} catch (final NoSuchMethodException e) {
+			e.printStackTrace();
+			throw new RuntimeException("BUG: Expected constructor undefined1!");
+		} catch (final IllegalArgumentException e) {
+			e.printStackTrace();
+			throw new RuntimeException("BUG: Expected constructor undefined2!");
+		} catch (final InstantiationException e) {
+			e.printStackTrace();
+			throw new RuntimeException("BUG: InstantiationException.");
+		} catch (final IllegalAccessException e) {
+			e.printStackTrace();
+			throw new RuntimeException("BUG: Expected constructor undefined3!");
+		} catch (final InvocationTargetException e) {
+			e.printStackTrace();
+			throw new RuntimeException("BUG: Constructor threw an exception.");
+		}
+	}
+
 	protected void makeNetworks(final Test test) {
 		final NetworkDescription nd = test.getNetworkDescription();
 		// XXX we want to do something much smarter here.-SH
 
 		for (final LocalMaster master : masters.values()) {
-			// XXX the name choosing doesn't make sense-SH
+			// XXX the name choosing doesn't make sense. -SH
 			final Network nw =
 					new NetworkImpl(test.getDescription() + " slavename:"
 							+ master.getSlave().getName());
-			int necessaryClients = nd.necessaryClients();
-			while (necessaryClients >= 1) {
-				System.out.println("adding master");
-				nw.addTorInstanceForMaster(new TorInstanceImpl(), master);
-				necessaryClients--;
+			int necessaryDirectoryAuthorities =
+					nd.necessaryDirectoryAuthorities();
+			while (necessaryDirectoryAuthorities >= 1) {
+				System.out.println("adding authority");
+				// XXX add an actual authority, not a regular instance -SH
+				nw.addTorInstance(new TorInstanceImpl(master));
+				necessaryDirectoryAuthorities--;
 			}
+			int necessaryRouters = nd.necessaryRouters();
+			while (necessaryRouters >= 1) {
+				System.out.println("adding router");
+				// XXX add an actual router, not a regular instance -SH
+				nw.addTorInstance(new TorInstanceImpl(master));
+				necessaryRouters--;
+			}
+			int necessaryProxies = nd.necessaryProxies();
+			while (necessaryProxies >= 1) {
+				System.out.println("adding proxy");
+				// XXX add an actual proxy, not a regular instance -SH
+				nw.addTorInstance(new TorInstanceImpl(master));
+				necessaryProxies--;
+			}
 			nw.addTest(test);
 			networks.add(nw);
 		}
@@ -231,31 +398,111 @@
 		newTests.add(test);
 	}
 
-	private class TaskCollector implements Runnable {
-		private final LocalMaster master;
+	private static class TaskExecutionNotSuccessfulException extends Exception {
 
-		public void run() {
-			while (true) {
+		private static final long serialVersionUID = 1L;
+		final private Set<TaskResult> taskResults;
+
+		TaskExecutionNotSuccessfulException(final Set<TaskResult> taskResults) {
+			this.taskResults = taskResults;
+		}
+
+		public Set<TaskResult> getTaskResults() {
+			return taskResults;
+		}
+
+		// XXX Add some logging capabilities -SH
+	}
+
+	private static class TaskManager implements Callable<Boolean> {
+
+		final private Set<TaskResult> taskResults =
+				new CopyOnWriteArraySet<TaskResult>();
+
+		final private Object taskResultsLock = new Object();
+
+		final private Set<MasterTask> tasks;
+
+		TaskManager(final Set<MasterTask> tasks) {
+			if (tasks.isEmpty()) {
+				throw new IllegalArgumentException("No tasks passed!");
+			}
+			this.tasks =
+					Collections.synchronizedSet(new HashSet<MasterTask>(tasks));
+		}
+
+		public Boolean call() {
+			for (final MasterTask task : tasks) {
+				task.getMaster().addTask(task.getTask());
+				// XXX Asking for trouble here. task could throw an exception!
+				// -SH
+				new Thread(new TaskCollector(task)).start();
+			}
+			try {
+				synchronized (taskResultsLock) {
+					// XXX See above. This needs more thinking -SH
+					while (tasks.size() != taskResults.size()) {
+						taskResultsLock.wait();
+					}
+					// XXX We want some logic here.-SH
+					for (final TaskResult taskResult : taskResults) {
+						if (!taskResult.wasSuccessful()) {
+							return false;
+						}
+					}
+					return true;
+				}
+			} catch (final InterruptedException e) {
+				// figure out a better solution here -SH
+				e.printStackTrace();
+			}
+			return false;
+		}
+
+		public Set<TaskResult> getTaskResults() {
+			return taskResults;
+		}
+
+		private class TaskCollector implements Runnable {
+			private final MasterTask task;
+
+			public void run() {
 				try {
+					final TaskResult taskResult =
+							task.getMaster().getTaskResult(
+									task.getTask().getId());
 					synchronized (taskResultsLock) {
-						taskResults.add(master.getTaskResult());
+						taskResults.add(taskResult);
 						taskResultsLock.notifyAll();
 					}
-					System.out.println("received completed task");
 				} catch (final InterruptedException e) {
 					e.printStackTrace();
 					Thread.currentThread().interrupt();
 				}
-				if (Thread.interrupted()) {
-					break;
-				}
+
 			}
+
+			protected TaskCollector(final MasterTask task) {
+				this.task = task;
+			}
 		}
+	}
 
-		protected TaskCollector(final LocalMaster master) {
+	private static class MasterTask {
+		final private LocalMaster master;
+		final private Task task;
+
+		MasterTask(final LocalMaster master, final Task task) {
 			this.master = master;
+			this.task = task;
 		}
 
+		public LocalMaster getMaster() {
+			return master;
+		}
+
+		public Task getTask() {
+			return task;
+		}
 	}
-
 }

Modified: puppetor/branches/gsoc2008/src/de/uniba/wiai/lspi/puppetor/rmi/impl/TorInstanceImpl.java
===================================================================
--- puppetor/branches/gsoc2008/src/de/uniba/wiai/lspi/puppetor/rmi/impl/TorInstanceImpl.java	2008-08-14 12:43:35 UTC (rev 16545)
+++ puppetor/branches/gsoc2008/src/de/uniba/wiai/lspi/puppetor/rmi/impl/TorInstanceImpl.java	2008-08-14 14:04:37 UTC (rev 16546)
@@ -36,7 +36,7 @@
 import java.util.concurrent.atomic.AtomicBoolean;
 import java.util.concurrent.atomic.AtomicInteger;
 
-import de.uniba.wiai.lspi.puppetor.rmi.Slave;
+import de.uniba.wiai.lspi.puppetor.rmi.LocalMaster;
 import de.uniba.wiai.lspi.puppetor.rmi.TorInstance;
 
 /**
@@ -47,44 +47,47 @@
 public class TorInstanceImpl implements TorInstance {
 
 	/**
-	 * Saves configuration options in an "option value" format. Synchronized
-	 * with <code>this</code>.
+	 * Saves configuration options in an "option value" format.
 	 */
 	private List<String> configuration;
 
 	/**
+	 * The name of this node.
+	 */
+	private String name;
+
+	/**
 	 * The svn revision of the Tor build. 0 means no specified revision.
-	 * Synchronized with <code>this</code>.
 	 */
-	private AtomicInteger revision;
+	private final AtomicInteger revision = new AtomicInteger(0);
 
 	/**
-	 * Whether we are a bridge authority. Synchronized with <code>this</code>.
+	 * Whether we are a bridge authority.
 	 */
-	private AtomicBoolean bridgeAuthority;
+	private final AtomicBoolean bridgeAuthority = new AtomicBoolean(false);
 
 	/**
-	 * Whether we are a directory authority. Synchronized with <code>this</code>.
+	 * Whether we are a directory authority.
 	 */
-	private AtomicBoolean directoryAuthority;
+	final private AtomicBoolean directoryAuthority = new AtomicBoolean(false);
 
 	/**
-	 * Whether we are an exit. Synchronized with <code>this</code>.
+	 * Whether we are an exit.
 	 */
-	private AtomicBoolean exit;
+	private final AtomicBoolean exit = new AtomicBoolean(false);
 
 	/**
-	 * Whether we are a relay. Synchronized with <code>this</code>.
+	 * Whether we are a relay.
 	 */
-	private AtomicBoolean relay;
+	private final AtomicBoolean relay = new AtomicBoolean(false);
 
 	/**
-	 * Whether we are a bridge. Synchronized with <code>this</code>.
+	 * Whether we are a bridge.
 	 */
-	private AtomicBoolean bridge;
+	private final AtomicBoolean bridge = new AtomicBoolean(false);
 
 	/**
-	 * Whether we are on a private network. Synchronized with <code>this</code>.
+	 * Whether we are on a private network.
 	 */
 	private AtomicBoolean privateNetwork;
 
@@ -94,8 +97,15 @@
 	 */
 	private AtomicBoolean replaceConfiguration;
 
-	private Slave slave;
+	/**
+	 * Provide a link to the slave where this torInstance will run.
+	 */
+	private final LocalMaster master;
 
+	TorInstanceImpl(final LocalMaster master) {
+		this.master = master;
+	}
+
 	public synchronized List<String> getConfiguration() {
 		return Collections.unmodifiableList(configuration);
 	}
@@ -116,7 +126,7 @@
 		return exit.get();
 	}
 
-	public boolean isRelay() {
+	public boolean isRouter() {
 		return relay.get();
 	}
 
@@ -132,12 +142,12 @@
 		return bridge.get();
 	}
 
-	public synchronized void linkToSlave(final Slave slave) {
-		if (this.slave != null) {
-			throw new IllegalStateException("A TorInstance cannot be "
-					+ "reassigend to a new Slave!");
-		}
-		this.slave = slave;
+	public LocalMaster getMaster() {
+		return master;
 	}
 
+	public synchronized String getName() {
+		return name;
+	}
+
 }

Modified: puppetor/branches/gsoc2008/src/de/uniba/wiai/lspi/puppetor/rmi/tasks/CreateNetworkTask.java
===================================================================
--- puppetor/branches/gsoc2008/src/de/uniba/wiai/lspi/puppetor/rmi/tasks/CreateNetworkTask.java	2008-08-14 12:43:35 UTC (rev 16545)
+++ puppetor/branches/gsoc2008/src/de/uniba/wiai/lspi/puppetor/rmi/tasks/CreateNetworkTask.java	2008-08-14 14:04:37 UTC (rev 16546)
@@ -43,8 +43,8 @@
 	 */
 	private static final long serialVersionUID = 1L;
 
-	public CreateNetworkTask(final String name) {
-		super(name);
+	public CreateNetworkTask(final int id, final String name) {
+		super(id, name);
 	}
 
 	@Override

Modified: puppetor/branches/gsoc2008/src/de/uniba/wiai/lspi/puppetor/rmi/tasks/TerminateTask.java
===================================================================
--- puppetor/branches/gsoc2008/src/de/uniba/wiai/lspi/puppetor/rmi/tasks/TerminateTask.java	2008-08-14 12:43:35 UTC (rev 16545)
+++ puppetor/branches/gsoc2008/src/de/uniba/wiai/lspi/puppetor/rmi/tasks/TerminateTask.java	2008-08-14 14:04:37 UTC (rev 16546)
@@ -42,13 +42,14 @@
 	 */
 	private static final long serialVersionUID = 1L;
 
-	public TerminateTask(final String name) {
-		super(name);
+	public TerminateTask(final int id, final String name) {
+		super(id, name);
 	}
 
 	@Override
 	public void execute() throws InterruptedException, RemoteException {
 		Thread.currentThread().interrupt();
+		reportResult(true);
 	}
 
 }