[Arakhnę-Dev] [117] Release 2.0.

[ Thread Index | Date Index | More arakhne.org/dev Archives ]


Revision: 117
Author:   galland
Date:     2010-01-21 09:29:52 +0100 (Thu, 21 Jan 2010)
Log Message:
-----------
Release 2.0.

Added Paths:
-----------
    tags/afc-2.0/
    tags/afc-2.0/arakhneLog4J/
    tags/afc-2.0/arakhneLog4J/pom.xml
    tags/afc-2.0/arakhneLog4J/src/
    tags/afc-2.0/arakhneLog4J/src/main/
    tags/afc-2.0/arakhneLog4J/src/main/java/
    tags/afc-2.0/arakhneLog4J/src/main/java/org/
    tags/afc-2.0/arakhneLog4J/src/main/java/org/arakhne/
    tags/afc-2.0/arakhneLog4J/src/main/java/org/arakhne/logging/
    tags/afc-2.0/arakhneLog4J/src/main/java/org/arakhne/logging/ApacheLogger.java
    tags/afc-2.0/arakhneLogger/
    tags/afc-2.0/arakhneLogger/pom.xml
    tags/afc-2.0/arakhneLogger/src/
    tags/afc-2.0/arakhneLogger/src/main/
    tags/afc-2.0/arakhneLogger/src/main/java/
    tags/afc-2.0/arakhneLogger/src/main/java/org/
    tags/afc-2.0/arakhneLogger/src/main/java/org/arakhne/
    tags/afc-2.0/arakhneLogger/src/main/java/org/arakhne/logging/
    tags/afc-2.0/arakhneLogger/src/main/java/org/arakhne/logging/AbstractLogger.java
    tags/afc-2.0/arakhneLogger/src/main/java/org/arakhne/logging/AbstractPrintStreamLogger.java
    tags/afc-2.0/arakhneLogger/src/main/java/org/arakhne/logging/AbstractStandAloneLogger.java
    tags/afc-2.0/arakhneLogger/src/main/java/org/arakhne/logging/ConsoleLogger.java
    tags/afc-2.0/arakhneLogger/src/main/java/org/arakhne/logging/FileLogger.java
    tags/afc-2.0/arakhneLogger/src/main/java/org/arakhne/logging/LogLevel.java
    tags/afc-2.0/arakhneLogger/src/main/java/org/arakhne/logging/Logger.java
    tags/afc-2.0/arakhneLogger/src/main/java/org/arakhne/logging/LoggerEvent.java
    tags/afc-2.0/arakhneLogger/src/main/java/org/arakhne/logging/LoggerEventListener.java
    tags/afc-2.0/arakhneLogger/src/main/java/org/arakhne/logging/LoggingSystem.java
    tags/afc-2.0/arakhneLogger/src/main/java/org/arakhne/logging/SunLogger.java
    tags/afc-2.0/arakhneLogger/src/main/resources/
    tags/afc-2.0/arakhneLogger/src/main/resources/org/
    tags/afc-2.0/arakhneLogger/src/main/resources/org/arakhne/
    tags/afc-2.0/arakhneLogger/src/main/resources/org/arakhne/logging/
    tags/afc-2.0/arakhneLogger/src/main/resources/org/arakhne/logging/AbstractStandAloneLogger.properties
    tags/afc-2.0/arakhneLogger/src/main/resources/org/arakhne/logging/AbstractStandAloneLogger_de.properties
    tags/afc-2.0/arakhneLogger/src/main/resources/org/arakhne/logging/AbstractStandAloneLogger_es.properties
    tags/afc-2.0/arakhneLogger/src/main/resources/org/arakhne/logging/AbstractStandAloneLogger_fr.properties
    tags/afc-2.0/arakhneLogger/src/main/resources/org/arakhne/logging/AbstractStandAloneLogger_it.properties
    tags/afc-2.0/arakhneLogger/src/main/resources/org/arakhne/logging/AbstractStandAloneLogger_nl.properties
    tags/afc-2.0/arakhneLogger/src/main/resources/org/arakhne/logging/AbstractStandAloneLogger_pt.properties
    tags/afc-2.0/arakhneRefs/
    tags/afc-2.0/arakhneRefs/pom.xml
    tags/afc-2.0/arakhneRefs/src/
    tags/afc-2.0/arakhneRefs/src/main/
    tags/afc-2.0/arakhneRefs/src/main/java/
    tags/afc-2.0/arakhneRefs/src/main/java/org/
    tags/afc-2.0/arakhneRefs/src/main/java/org/arakhne/
    tags/afc-2.0/arakhneRefs/src/main/java/org/arakhne/util/
    tags/afc-2.0/arakhneRefs/src/main/java/org/arakhne/util/ref/
    tags/afc-2.0/arakhneRefs/src/main/java/org/arakhne/util/ref/AbstractWeakSoftValueMap.java
    tags/afc-2.0/arakhneRefs/src/main/java/org/arakhne/util/ref/ComparableSoftReference.java
    tags/afc-2.0/arakhneRefs/src/main/java/org/arakhne/util/ref/ComparableWeakReference.java
    tags/afc-2.0/arakhneRefs/src/main/java/org/arakhne/util/ref/ReferenceListener.java
    tags/afc-2.0/arakhneRefs/src/main/java/org/arakhne/util/ref/SoftValueMap.java
    tags/afc-2.0/arakhneRefs/src/main/java/org/arakhne/util/ref/WeakArrayList.java
    tags/afc-2.0/arakhneRefs/src/main/java/org/arakhne/util/ref/WeakValueMap.java
    tags/afc-2.0/arakhneRefs/src/main/resources/
    tags/afc-2.0/arakhneRefs/src/main/resources/AUTHORS
    tags/afc-2.0/arakhneRefs/src/main/resources/COPYING
    tags/afc-2.0/arakhneRefs/src/main/resources/Changelog
    tags/afc-2.0/arakhneRefs/src/main/resources/VERSION
    tags/afc-2.0/arakhneRefs/src/test/
    tags/afc-2.0/arakhneRefs/src/test/java/
    tags/afc-2.0/arakhneRefs/src/test/java/org/
    tags/afc-2.0/arakhneRefs/src/test/java/org/arakhne/
    tags/afc-2.0/arakhneRefs/src/test/java/org/arakhne/junit/
    tags/afc-2.0/arakhneRefs/src/test/java/org/arakhne/junit/AbstractRepeatedTest.java
    tags/afc-2.0/arakhneRefs/src/test/java/org/arakhne/junit/AbstractTestCase.java
    tags/afc-2.0/arakhneRefs/src/test/java/org/arakhne/junit/RepeatableTest.java
    tags/afc-2.0/arakhneRefs/src/test/java/org/arakhne/util/
    tags/afc-2.0/arakhneRefs/src/test/java/org/arakhne/util/ref/
    tags/afc-2.0/arakhneRefs/src/test/java/org/arakhne/util/ref/SoftValueMapTest.java
    tags/afc-2.0/arakhneRefs/src/test/java/org/arakhne/util/ref/WeakArrayListTest.java
    tags/afc-2.0/arakhneRefs/src/test/java/org/arakhne/util/ref/WeakValueMapTest.java
    tags/afc-2.0/arakhneVmutils/
    tags/afc-2.0/arakhneVmutils/bin.xml
    tags/afc-2.0/arakhneVmutils/java/
    tags/afc-2.0/arakhneVmutils/java/pom.xml
    tags/afc-2.0/arakhneVmutils/java/src/
    tags/afc-2.0/arakhneVmutils/java/src/main/
    tags/afc-2.0/arakhneVmutils/java/src/main/java/
    tags/afc-2.0/arakhneVmutils/java/src/main/java/org/
    tags/afc-2.0/arakhneVmutils/java/src/main/java/org/arakhne/
    tags/afc-2.0/arakhneVmutils/java/src/main/java/org/arakhne/vmutil/
    tags/afc-2.0/arakhneVmutils/java/src/main/java/org/arakhne/vmutil/AutoboxingUtil.java
    tags/afc-2.0/arakhneVmutils/java/src/main/java/org/arakhne/vmutil/Caller.java
    tags/afc-2.0/arakhneVmutils/java/src/main/java/org/arakhne/vmutil/ClassLoaderFinder.java
    tags/afc-2.0/arakhneVmutils/java/src/main/java/org/arakhne/vmutil/DynamicURLClassLoader.java
    tags/afc-2.0/arakhneVmutils/java/src/main/java/org/arakhne/vmutil/DynamicURLStreamHandlerFactory.java
    tags/afc-2.0/arakhneVmutils/java/src/main/java/org/arakhne/vmutil/ExternalizableResource.java
    tags/afc-2.0/arakhneVmutils/java/src/main/java/org/arakhne/vmutil/FileSystem.java
    tags/afc-2.0/arakhneVmutils/java/src/main/java/org/arakhne/vmutil/FileURLConnection.java
    tags/afc-2.0/arakhneVmutils/java/src/main/java/org/arakhne/vmutil/FileURLStreamHandler.java
    tags/afc-2.0/arakhneVmutils/java/src/main/java/org/arakhne/vmutil/FileURLStreamHandlerFactory.java
    tags/afc-2.0/arakhneVmutils/java/src/main/java/org/arakhne/vmutil/LibraryLoader.java
    tags/afc-2.0/arakhneVmutils/java/src/main/java/org/arakhne/vmutil/MACNumber.java
    tags/afc-2.0/arakhneVmutils/java/src/main/java/org/arakhne/vmutil/OperatingSystem.java
    tags/afc-2.0/arakhneVmutils/java/src/main/java/org/arakhne/vmutil/OperatingSystemInfo.java
    tags/afc-2.0/arakhneVmutils/java/src/main/java/org/arakhne/vmutil/ReflectionUtil.java
    tags/afc-2.0/arakhneVmutils/java/src/main/java/org/arakhne/vmutil/ResourceNotFoundException.java
    tags/afc-2.0/arakhneVmutils/java/src/main/java/org/arakhne/vmutil/ResourceURLConnection.java
    tags/afc-2.0/arakhneVmutils/java/src/main/java/org/arakhne/vmutil/ResourceURLStreamHandler.java
    tags/afc-2.0/arakhneVmutils/java/src/main/java/org/arakhne/vmutil/ResourceURLStreamHandlerFactory.java
    tags/afc-2.0/arakhneVmutils/java/src/main/java/org/arakhne/vmutil/Resources.java
    tags/afc-2.0/arakhneVmutils/java/src/main/java/org/arakhne/vmutil/ThreadServiceFinder.java
    tags/afc-2.0/arakhneVmutils/java/src/main/java/org/arakhne/vmutil/ThreadServiceProvider.java
    tags/afc-2.0/arakhneVmutils/java/src/main/java/org/arakhne/vmutil/VMCommandLine.java
    tags/afc-2.0/arakhneVmutils/java/src/main/resources/
    tags/afc-2.0/arakhneVmutils/java/src/main/resources/AUTHORS
    tags/afc-2.0/arakhneVmutils/java/src/main/resources/COPYING
    tags/afc-2.0/arakhneVmutils/java/src/main/resources/Changelog
    tags/afc-2.0/arakhneVmutils/java/src/main/resources/VERSION
    tags/afc-2.0/arakhneVmutils/java/src/test/
    tags/afc-2.0/arakhneVmutils/java/src/test/java/
    tags/afc-2.0/arakhneVmutils/java/src/test/java/org/
    tags/afc-2.0/arakhneVmutils/java/src/test/java/org/arakhne/
    tags/afc-2.0/arakhneVmutils/java/src/test/java/org/arakhne/vmutil/
    tags/afc-2.0/arakhneVmutils/java/src/test/java/org/arakhne/vmutil/FileSystemTest.java
    tags/afc-2.0/arakhneVmutils/java/src/test/java/org/arakhne/vmutil/FileURLConnectionTest.java
    tags/afc-2.0/arakhneVmutils/java/src/test/java/org/arakhne/vmutil/ResourceURLConnectionTest.java
    tags/afc-2.0/arakhneVmutils/java/src/test/java/org/arakhne/vmutil/ResourcesTest.java
    tags/afc-2.0/arakhneVmutils/java/src/test/java/org/arakhne/vmutil/VMCommandLineTest.java
    tags/afc-2.0/arakhneVmutils/java/src/test/resources/
    tags/afc-2.0/arakhneVmutils/java/src/test/resources/org/
    tags/afc-2.0/arakhneVmutils/java/src/test/resources/org/arakhne/
    tags/afc-2.0/arakhneVmutils/java/src/test/resources/org/arakhne/vmutil/
    tags/afc-2.0/arakhneVmutils/java/src/test/resources/org/arakhne/vmutil/test.txt
    tags/afc-2.0/arakhneVmutils/native/
    tags/afc-2.0/arakhneVmutils/native/josuuid/
    tags/afc-2.0/arakhneVmutils/native/josuuid/linux32/
    tags/afc-2.0/arakhneVmutils/native/josuuid/linux32/pom.xml
    tags/afc-2.0/arakhneVmutils/native/josuuid/linux64/
    tags/afc-2.0/arakhneVmutils/native/josuuid/linux64/pom.xml
    tags/afc-2.0/arakhneVmutils/native/josuuid/mingw/
    tags/afc-2.0/arakhneVmutils/native/josuuid/mingw/pom.xml
    tags/afc-2.0/arakhneVmutils/native/josuuid/pom.xml
    tags/afc-2.0/arakhneVmutils/native/josuuid/src/
    tags/afc-2.0/arakhneVmutils/native/josuuid/src/main/
    tags/afc-2.0/arakhneVmutils/native/josuuid/src/main/native/
    tags/afc-2.0/arakhneVmutils/native/josuuid/src/main/native/OperatingSystemJNI.cpp
    tags/afc-2.0/arakhneVmutils/native/josuuid/src/main/native/josuuid.cpp
    tags/afc-2.0/arakhneVmutils/native/josuuid/src/main/native/josuuid.h
    tags/afc-2.0/arakhneVmutils/native/josuuid/src/main/native/osmacro.h
    tags/afc-2.0/arakhneVmutils/native/josuuid/src/main/native/winos.cpp
    tags/afc-2.0/arakhneVmutils/native/josuuid/src/main/native/winos.h
    tags/afc-2.0/arakhneVmutils/native/josuuid/src/test/
    tags/afc-2.0/arakhneVmutils/native/pom.xml
    tags/afc-2.0/arakhneVmutils/pom.xml
    tags/afc-2.0/pom.xml

Added: tags/afc-2.0/arakhneLog4J/pom.xml
===================================================================
--- tags/afc-2.0/arakhneLog4J/pom.xml	                        (rev 0)
+++ tags/afc-2.0/arakhneLog4J/pom.xml	2010-01-21 08:29:52 UTC (rev 117)
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"; xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"; xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd";>
+  <modelVersion>4.0.0</modelVersion>
+
+  <parent>
+	<artifactId>afc</artifactId>
+	<groupId>org.arakhne.afc</groupId>
+	<version>2.0</version>
+  </parent>
+
+  <groupId>org.arakhne.afc</groupId>
+  <artifactId>arakhneLog4J</artifactId>
+  <packaging>jar</packaging>
+  <version>1.0</version>
+  <name>${pom.artifactId}</name>
+  <url>http://www.arakhne.org/arakhneLogger/</url>
+
+	<!-- ======================================= -->
+	<!-- ====       Project Information      === -->
+	<!-- ======================================= -->
+		
+	<dependencies>
+		<dependency>
+			<groupId>org.arakhne.afc</groupId>
+			<artifactId>arakhneLogger</artifactId>
+			<version>1.2</version>
+		</dependency>
+		<dependency>
+			<groupId>log4j</groupId>
+			<artifactId>log4j</artifactId>
+			<version>1.2.14</version>
+		</dependency>
+	</dependencies>
+		
+</project>

Added: tags/afc-2.0/arakhneLog4J/src/main/java/org/arakhne/logging/ApacheLogger.java
===================================================================
--- tags/afc-2.0/arakhneLog4J/src/main/java/org/arakhne/logging/ApacheLogger.java	                        (rev 0)
+++ tags/afc-2.0/arakhneLog4J/src/main/java/org/arakhne/logging/ApacheLogger.java	2010-01-21 08:29:52 UTC (rev 117)
@@ -0,0 +1,115 @@
+/* 
+ * $Id$
+ * 
+ * Copyright (C) 2004-2009 St&eacute;phane GALLAND and Nicolas GAUD
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * This program is free software; you can redistribute it and/or modify
+ */
+package org.arakhne.logging;
+
+import org.apache.log4j.Level;
+
+/**
+ * This class provides the concrete implementation of the <code>Logger</code>
+ * interface. This impl is based on the Apache's Logging Facade for Java, aka.
+ * Log4J.
+ * 
+ * @author St&eacute;phane GALLAND &lt;galland@xxxxxxxxxxx&gt;
+ * @version $Name$ $Revision$ $Date$
+ * @see Logger
+ */
+public class ApacheLogger extends AbstractLogger {
+
+	private final org.apache.log4j.Logger bindedLogger;
+
+	/**
+	 * Create an unamed logger based of Apache's logging system.
+	 */
+	public ApacheLogger() {
+		this.bindedLogger = org.apache.log4j.Logger.getRootLogger();
+		this.bindedLogger.setLevel(Level.ALL);
+	}
+
+	/**
+	 * Create a named logger based of Apache's logging system.
+	 * 
+	 * @param name is the name of the logger.
+	 */
+	public ApacheLogger(String name) {
+		this.bindedLogger = org.apache.log4j.Logger.getLogger(name);
+		this.bindedLogger.setLevel(toApacheLevel(getLogLevel()));
+	}
+
+//	**************************************************************************************//
+
+	/** Translate a logging level into the same thing for Apache's logging system.
+	 * 
+	 * @param level is the level to translate
+	 * @return the Sun's level
+	 */
+	protected Level toApacheLevel(LogLevel level) {
+		switch(level) {
+		case NONE:
+			return Level.OFF;
+		case ERROR:
+			return Level.ERROR;
+		case WARNING:
+			return Level.WARN;
+		case INFO:
+			return Level.INFO;
+		case DEBUG:
+			return Level.DEBUG;
+		}
+		return Level.OFF;
+	}
+	
+	/** {@InheritDoc}
+	 */
+	@Override
+	public void log(Object source, LogLevel level, String msg) {
+		this.bindedLogger.log(toApacheLevel(level),msg);
+		fireLoggerEvent(source, level, msg);
+	}
+
+	/** {@InheritDoc}
+	 */
+	public void log(Object source, LogLevel level, String msg, Throwable exception) {
+		this.bindedLogger.log(toApacheLevel(level),msg,exception);
+		fireLoggerEvent(source, level, msg);
+	}
+
+	
+//	**************************************************************************************//	
+
+	/** {@InheritDoc}
+	 * 
+	 * @return {@InheritDoc}
+	 */
+	public String getName() {
+		return this.bindedLogger.getName();
+	}
+
+	/** Set the minimum log level.
+	 * 
+	 * @param level
+	 */
+	@Override
+	public void setLogLevel(LogLevel level) {
+		super.setLogLevel(level);
+		this.bindedLogger.setLevel(toApacheLevel(level));
+	}
+
+}

Added: tags/afc-2.0/arakhneLogger/pom.xml
===================================================================
--- tags/afc-2.0/arakhneLogger/pom.xml	                        (rev 0)
+++ tags/afc-2.0/arakhneLogger/pom.xml	2010-01-21 08:29:52 UTC (rev 117)
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"; xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"; xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd";>
+  <modelVersion>4.0.0</modelVersion>
+
+  <parent>
+	<artifactId>afc</artifactId>
+	<groupId>org.arakhne.afc</groupId>
+	<version>2.0</version>
+  </parent>
+
+  <groupId>org.arakhne.afc</groupId>
+  <artifactId>arakhneLogger</artifactId>
+  <packaging>jar</packaging>
+  <version>1.2</version>
+  <name>${pom.artifactId}</name>
+  <url>http://www.arakhne.org/arakhneLogger/</url>
+
+	<!-- ======================================= -->
+	<!-- ====       Project Information      === -->
+	<!-- ======================================= -->
+		
+</project>

Added: tags/afc-2.0/arakhneLogger/src/main/java/org/arakhne/logging/AbstractLogger.java
===================================================================
--- tags/afc-2.0/arakhneLogger/src/main/java/org/arakhne/logging/AbstractLogger.java	                        (rev 0)
+++ tags/afc-2.0/arakhneLogger/src/main/java/org/arakhne/logging/AbstractLogger.java	2010-01-21 08:29:52 UTC (rev 117)
@@ -0,0 +1,295 @@
+/* 
+ * $Id$
+ * 
+ * Copyright (C) 2004-2009 St&eacute;phane GALLAND and Nicolas GAUD
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * This program is free software; you can redistribute it and/or modify
+ */
+package org.arakhne.logging;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * This class provides the base for a concrete implementation of the <code>Logger</code>
+ * interface.
+ * 
+ * @author St&eacute;phane GALLAND &lt;galland@xxxxxxxxxxx&gt;
+ * @version $Name$ $Revision$ $Date$
+ * @see Logger
+ */
+public abstract class AbstractLogger implements Logger {
+
+	private LogLevel minLevel;
+	private transient List<LoggerEventListener> listeners = null;
+	
+	/**
+	 */
+	public AbstractLogger() {
+		this.minLevel = null;
+	}
+	
+	/** Check if logging is allowed.
+	 * 
+	 * @param requestedLevel is the level to check.
+	 * @return <code>true</code> if logging is allowed, <code>false</code> otherwise
+	 */
+	protected final boolean isLoggableFor(LogLevel requestedLevel) {
+		return requestedLevel.hasHigherPriority(getLogLevel());
+	}	
+
+	/** 
+	 * {@inheritDoc}
+	 */
+	public void setLogLevel(LogLevel level) {
+		this.minLevel = level;
+	}
+
+	/** 
+	 * {@inheritDoc}
+	 */
+	public final LogLevel getLogLevel() {
+		if (this.minLevel==null) return LoggingSystem.getLoggingSystem().getDefaultLogLevel(); 
+		return this.minLevel;
+	}
+
+	/** {@InheritDoc}
+	 * 
+	 * @param arg0 {@InheritDoc}
+	 * @param arg1 {@InheritDoc}
+	 */
+	@Deprecated
+	public final void debug(String arg0, Throwable arg1) {
+		log(this,LogLevel.DEBUG,arg0,arg1);
+	}
+
+	/** 
+	 * {@inheritDoc}
+	 */
+	@Deprecated
+	public final void debug(String arg0) {
+		log(LogLevel.DEBUG,arg0);
+	}
+
+	/** 
+	 * {@inheritDoc}
+	 */
+	@Deprecated
+	public final void error(String arg0, Throwable arg1) {
+		log(this,LogLevel.ERROR,arg0,arg1);
+	}
+
+	/** 
+	 * {@inheritDoc}
+	 */
+	@Deprecated
+	public final void error(String arg0) {
+		log(this,LogLevel.ERROR,arg0);
+	}
+
+	/** 
+	 * {@inheritDoc}
+	 */
+	@Deprecated
+	public final void info(String arg0, Throwable arg1) {
+		log(this,LogLevel.INFO,arg0,arg1);
+	}
+
+	/** 
+	 * {@inheritDoc}
+	 */
+	@Deprecated
+	public final void info(String arg0) {
+		log(this,LogLevel.INFO,arg0);
+	}
+
+	/** 
+	 * {@inheritDoc}
+	 */
+	@Deprecated
+	public final void warn(String arg0, Throwable arg1) {
+		log(this,LogLevel.WARNING,arg0,arg1);
+	}
+
+	/** 
+	 * {@inheritDoc}
+	 */
+	@Deprecated
+	public final void warn(String arg0) {
+		log(this,LogLevel.WARNING,arg0);
+	}
+
+	/** {@InheritDoc}
+	 * 
+	 * @param level {@InheritDoc}
+	 * @param msg {@InheritDoc}
+	 */
+	@Deprecated
+	public final void log(LogLevel level, String msg) {
+		log(this, level, msg, null);
+	}
+
+	/** {@InheritDoc}
+	 */
+	@Deprecated
+	public final void log(LogLevel level, String msg, Throwable exception) {
+		log(this,level,msg,exception);
+	}
+
+	/** {@InheritDoc}
+	 */
+	public final void debug(Object source, String arg0, Throwable arg1) {
+		log(source,LogLevel.DEBUG,arg0,arg1);
+	}
+
+	/** 
+	 * {@inheritDoc}
+	 */
+	public final void debug(Object source, String arg0) {
+		log(source, LogLevel.DEBUG,arg0);
+	}
+
+	/** 
+	 * {@inheritDoc}
+	 */
+	public final void error(Object source, String arg0, Throwable arg1) {
+		log(source,LogLevel.ERROR,arg0,arg1);
+	}
+
+	/** 
+	 * {@inheritDoc}
+	 */
+	public final void error(Object source, String arg0) {
+		log(source,LogLevel.ERROR,arg0);
+	}
+
+	/** 
+	 * {@inheritDoc}
+	 */
+	public final void info(Object source, String arg0, Throwable arg1) {
+		log(source,LogLevel.INFO,arg0,arg1);
+	}
+
+	/** 
+	 * {@inheritDoc}
+	 */
+	public final void info(Object source, String arg0) {
+		log(source,LogLevel.INFO,arg0);
+	}
+
+	/** 
+	 * {@inheritDoc}
+	 */
+	public final void warn(Object source, String arg0, Throwable arg1) {
+		log(source,LogLevel.WARNING,arg0,arg1);
+	}
+
+	/** 
+	 * {@inheritDoc}
+	 */
+	public final void warn(Object source, String arg0) {
+		log(source,LogLevel.WARNING,arg0);
+	}
+
+	/** {@InheritDoc}
+	 */
+	public void log(Object source, LogLevel level, String msg) {
+		log(source, level, msg, null);
+	}
+
+	/** {@InheritDoc}
+	 * 
+	 * @return {@InheritDoc}
+	 */
+	public boolean isDebugEnabled() {
+		return isLoggableFor(LogLevel.DEBUG);
+	}
+
+	/** {@InheritDoc}
+	 * 
+	 * @return {@InheritDoc}
+	 */
+	public boolean isErrorEnabled() {
+		return isLoggableFor(LogLevel.ERROR);
+	}
+
+	/** {@InheritDoc}
+	 * 
+	 * @return {@InheritDoc}
+	 */
+	public boolean isInfoEnabled() {
+		return isLoggableFor(LogLevel.INFO);
+	}
+
+	/** {@InheritDoc}
+	 * 
+	 * @return {@InheritDoc}
+	 */
+	public boolean isWarnEnabled() {
+		return isLoggableFor(LogLevel.WARNING);
+	}
+
+	/** Add listener on logger events.
+	 * 
+	 * @param listener
+	 */
+	public final void addLoggerEventListener(LoggerEventListener listener) {
+		if (this.listeners==null) {
+			this.listeners = new ArrayList<LoggerEventListener>();
+		}
+		this.listeners.add(listener);
+	}
+
+	/** Remove listener on logger events.
+	 * 
+	 * @param listener
+	 */
+	public void removeLoggerEventListener(LoggerEventListener listener) {
+		if (this.listeners!=null) {
+			this.listeners.remove(listener);
+			if (this.listeners.isEmpty())
+				this.listeners = null;
+		}
+	}
+	
+	/** Notify the logger event listeners.
+	 * 
+	 * @param source is the object which has log the message.
+	 * @param level is the level of the message
+	 * @param message is the text of the message.
+	 */
+	protected final void fireLoggerEvent(Object source, LogLevel level, String message) {
+		fireLoggerEvent(source, level, message, null);
+	}
+	
+	/** Notify the logger event listeners.
+	 * 
+	 * @param source is the object which has log the message.
+	 * @param level is the level of the message
+	 * @param message is the text of the message.
+	 * @param exception is the exception associated to the message.
+	 */
+	protected final void fireLoggerEvent(Object source, LogLevel level, String message, Throwable exception) {
+		LoggerEvent event = new LoggerEvent(source, this, level, message, exception);
+		if (this.listeners!=null) {
+			for(LoggerEventListener listener : this.listeners) {
+				listener.onLoggedEvent(event);
+			}
+		}
+		LoggingSystem.getLoggingSystem().fireLoggerEvent(event);
+	}
+
+}

Added: tags/afc-2.0/arakhneLogger/src/main/java/org/arakhne/logging/AbstractPrintStreamLogger.java
===================================================================
--- tags/afc-2.0/arakhneLogger/src/main/java/org/arakhne/logging/AbstractPrintStreamLogger.java	                        (rev 0)
+++ tags/afc-2.0/arakhneLogger/src/main/java/org/arakhne/logging/AbstractPrintStreamLogger.java	2010-01-21 08:29:52 UTC (rev 117)
@@ -0,0 +1,96 @@
+/* 
+ * $Id$
+ * 
+ * Copyright (C) 2009 St&eacute;phane GALLAND and Nicolas GAUD
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * This program is free software; you can redistribute it and/or modify
+ */
+package org.arakhne.logging;
+
+import java.io.PrintStream;
+
+/**
+ * This class provides the base for a concrete implementation of the <code>Logger</code>
+ * interface. This logger impl contains the minimal knowledge required to implement
+ * loggers which are writing inside a print stream.
+ * 
+ * @author St&eacute;phane GALLAND &lt;galland@xxxxxxxxxxx&gt;
+ * @version $Name$ $Revision$ $Date$
+ * @see Logger
+ */
+public abstract class AbstractPrintStreamLogger extends AbstractStandAloneLogger {
+
+	/** Output print stream for anomalies.
+	 */
+	protected final PrintStream anomalyStream;
+	
+	/** Output print stream for messages.
+	 */
+	protected final PrintStream noticeStream;
+
+	/**
+	 * Unamed Logger on system console.
+	 * 
+	 * @param anomalyStream is the output stream inside which anomaly logs will be put.
+	 * @param noticeStream is the output stream inside which notice logs will be put.
+	 */
+	public AbstractPrintStreamLogger(PrintStream anomalyStream, PrintStream noticeStream) {
+		this.anomalyStream = anomalyStream;
+		this.noticeStream = noticeStream;
+	}
+
+	/**
+	 * Named Logger on system console.
+	 * 
+	 * @param anomalyStream is the output stream inside which anomaly logs will be put.
+	 * @param noticeStream is the output stream inside which notice logs will be put.
+	 * @param name is the name of the logger.
+	 */
+	public AbstractPrintStreamLogger(PrintStream anomalyStream, PrintStream noticeStream, String name) {
+		super(name);
+		this.anomalyStream = anomalyStream;
+		this.noticeStream = noticeStream;
+	}
+
+	/** {@InheritDoc}
+	 */
+	public void log(Object source, LogLevel level, String msg, Throwable exception) {
+		if (isLoggableFor(level)) {
+			
+			StringBuffer buffer = new StringBuffer();
+			
+			if (this.name!=null) {
+				buffer.append("["); //$NON-NLS-1$
+				buffer.append(this.name);
+				buffer.append("] - "); //$NON-NLS-1$
+			}
+			buffer.append(getLocalizedString(level));
+			buffer.append(": "); //$NON-NLS-1$
+			buffer.append(msg);
+			
+			PrintStream ps = level.isAnomalyLevel() ? this.anomalyStream : this.noticeStream;
+
+			ps.println(buffer.toString());
+			
+			if (exception!=null) {
+				exception.printStackTrace(ps);
+			}
+
+			fireLoggerEvent(source, level, msg);
+		}
+	}
+
+}

Added: tags/afc-2.0/arakhneLogger/src/main/java/org/arakhne/logging/AbstractStandAloneLogger.java
===================================================================
--- tags/afc-2.0/arakhneLogger/src/main/java/org/arakhne/logging/AbstractStandAloneLogger.java	                        (rev 0)
+++ tags/afc-2.0/arakhneLogger/src/main/java/org/arakhne/logging/AbstractStandAloneLogger.java	2010-01-21 08:29:52 UTC (rev 117)
@@ -0,0 +1,124 @@
+/* 
+ * $Id$
+ * 
+ * Copyright (C) 2009 St&eacute;phane GALLAND and Nicolas GAUD
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * This program is free software; you can redistribute it and/or modify
+ */
+package org.arakhne.logging;
+
+import java.util.MissingResourceException;
+import java.util.ResourceBundle;
+
+/**
+ * This class provides the base for a concrete implementation of the <code>Logger</code>
+ * interface. This logger impl is not wrapped to a third-party logger (Sun nor Apache
+ * for example). It contains the minimal knowledge required to implement
+ * not-wrapped loggers.
+ * 
+ * @author St&eacute;phane GALLAND &lt;galland@xxxxxxxxxxx&gt;
+ * @version $Name$ $Revision$ $Date$
+ * @see Logger
+ */
+public abstract class AbstractStandAloneLogger extends AbstractLogger {
+
+	private static String errorLabel = null;
+	private static String warningLabel = null;
+	private static String infoLabel = null;
+	private static String debugLabel = null;
+	
+	/** Replies the label which is corresponding to the given log level.
+	 * 
+	 * @param level
+	 * @return the localized label which is corresponding to the given log level.
+	 */
+	protected static String getLocalizedString(LogLevel level) {
+		switch (level) {
+		case NONE:
+			return null;
+		case DEBUG:
+			if (debugLabel!=null) return debugLabel;
+			break;
+		case WARNING:
+			if (warningLabel!=null) return warningLabel;
+			break;
+		case ERROR:
+			if (errorLabel!=null) return errorLabel;
+			break;
+		case INFO:
+			if (infoLabel!=null) return infoLabel;
+			break;
+		}
+
+		String name = level.name().toUpperCase();
+		
+        try {
+        	ResourceBundle resource = ResourceBundle.getBundle(AbstractStandAloneLogger.class.getCanonicalName());
+        	String str = resource.getString(name);
+        	if ((str!=null)&&(!"".equals(str))) //$NON-NLS-1$
+        		name = str;
+        }
+        catch (MissingResourceException exep) {
+            //
+        }
+		
+		switch (level) {
+		case NONE:
+			return null;
+		case DEBUG:
+			debugLabel = name;
+			break;
+		case WARNING:
+			warningLabel = name;
+			break;
+		case ERROR:
+			errorLabel = name;
+			break;
+		case INFO:
+			infoLabel = name;
+			break;
+		}
+		
+		return name;
+	}
+
+	/** Name of this logger.
+	 */
+	protected final String name;
+	
+	/**
+	 * Unamed Logger on system console.
+	 */
+	public AbstractStandAloneLogger() {
+		this.name = null;
+	}
+
+	/**
+	 * Named Logger on system console.
+	 * 
+	 * @param name is the name of the logger.
+	 */
+	public AbstractStandAloneLogger(String name) {
+		this.name = name;
+	}
+
+	/** {@InheritDoc}
+	 */
+	public String getName() {
+		return this.name;
+	}
+
+}

Added: tags/afc-2.0/arakhneLogger/src/main/java/org/arakhne/logging/ConsoleLogger.java
===================================================================
--- tags/afc-2.0/arakhneLogger/src/main/java/org/arakhne/logging/ConsoleLogger.java	                        (rev 0)
+++ tags/afc-2.0/arakhneLogger/src/main/java/org/arakhne/logging/ConsoleLogger.java	2010-01-21 08:29:52 UTC (rev 117)
@@ -0,0 +1,49 @@
+/* 
+ * $Id$
+ * 
+ * Copyright (C) 2004-2009 St&eacute;phane GALLAND and Nicolas GAUD
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * This program is free software; you can redistribute it and/or modify
+ */
+package org.arakhne.logging;
+
+/**
+ * This class provides the concrete implementation of the <code>Logger</code>
+ * interface. This impl is displaying on the standard output.
+ * 
+ * @author St&eacute;phane GALLAND &lt;galland@xxxxxxxxxxx&gt;
+ * @version $Name$ $Revision$ $Date$
+ * @see Logger
+ */
+public class ConsoleLogger extends AbstractPrintStreamLogger {
+
+	/**
+	 * Unamed Logger on system console.
+	 */
+	public ConsoleLogger() {
+		super(System.err, System.out);
+	}
+
+	/**
+	 * Named Logger on system console.
+	 * 
+	 * @param name is the name of the logger.
+	 */
+	public ConsoleLogger(String name) {
+		super(System.err, System.out, name);
+	}
+
+}

Added: tags/afc-2.0/arakhneLogger/src/main/java/org/arakhne/logging/FileLogger.java
===================================================================
--- tags/afc-2.0/arakhneLogger/src/main/java/org/arakhne/logging/FileLogger.java	                        (rev 0)
+++ tags/afc-2.0/arakhneLogger/src/main/java/org/arakhne/logging/FileLogger.java	2010-01-21 08:29:52 UTC (rev 117)
@@ -0,0 +1,79 @@
+/* 
+ * $Id$
+ * 
+ * Copyright (C) 2009 St&eacute;phane GALLAND and Nicolas GAUD
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * This program is free software; you can redistribute it and/or modify
+ */
+package org.arakhne.logging;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.PrintStream;
+
+/**
+ * This class provides the concrete implementation of the <code>Logger</code>
+ * interface. This impl is writting inside a file.
+ * 
+ * @author St&eacute;phane GALLAND &lt;galland@xxxxxxxxxxx&gt;
+ * @version $Name$ $Revision$ $Date$
+ * @see Logger
+ */
+public class FileLogger extends AbstractPrintStreamLogger {
+
+	private final File logFile;
+	
+	/**
+	 * Unamed Logger on system console.
+	 * 
+	 * @param logFile is the log file to write inside.
+	 * @throws IOException when error on log file opening. 
+	 */
+	public FileLogger(File logFile) throws IOException {
+		this(logFile, new PrintStream(new FileOutputStream(logFile)));
+	}
+
+	/**
+	 * Named Logger on system console.
+	 * 
+	 * @param logFile is the log file to write inside.
+	 * @param name is the name of the logger.
+	 * @throws IOException when error on log file opening. 
+	 */
+	public FileLogger(File logFile, String name) throws IOException {
+		this(logFile, new PrintStream(new FileOutputStream(logFile)), name);
+	}
+
+	private FileLogger(File logFile, PrintStream logStream) {
+		super(logStream, logStream);
+		this.logFile = logFile;
+	}
+
+	private FileLogger(File logFile, PrintStream logStream, String name) {
+		super(logStream, logStream, name);
+		this.logFile = logFile;
+	}
+
+	/** Replies the log file which is written by this logger.
+	 * 
+	 * @return the log file, never <code>null</code>
+	 */
+	public File getLogFile() {
+		return this.logFile;
+	}
+
+}

Added: tags/afc-2.0/arakhneLogger/src/main/java/org/arakhne/logging/LogLevel.java
===================================================================
--- tags/afc-2.0/arakhneLogger/src/main/java/org/arakhne/logging/LogLevel.java	                        (rev 0)
+++ tags/afc-2.0/arakhneLogger/src/main/java/org/arakhne/logging/LogLevel.java	2010-01-21 08:29:52 UTC (rev 117)
@@ -0,0 +1,72 @@
+/* 
+ * $Id$
+ * 
+ * Copyright (C) 2004-2009 St&eacute;phane GALLAND and Nicolas GAUD
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * This program is free software; you can redistribute it and/or modify
+ */
+package org.arakhne.logging;
+
+/**
+ * The enum describing the various available log levels.
+ * 
+ * @author Nicolas GAUD &lt;gaud@xxxxxxxxxxx&gt;
+ * @author St&eacute;phane GALLAND &lt;galland@xxxxxxxxxxx&gt;
+ * @version $Name$ $Revision$ $Date$
+ */	
+public enum LogLevel {
+	/**
+	 * No logging.
+	 */
+	NONE,
+	/**
+	 * Error message Level.
+	 */
+	ERROR,
+	/**
+	 * Warning message Level.
+	 */
+	WARNING,
+	/**
+	 * Information message Level.
+	 */
+	INFO,
+	/**
+	 * Debug message Level.
+	 */
+	DEBUG;
+
+	/** Check if logging is allowed.
+	 * This function check if the current log level has a priority
+	 * greater or equals to the given log level.
+	 * 
+	 * @param referenceLogLevel is the level to check.
+	 * @return <code>true</code> if logging is allowed, <code>false</code> otherwise
+	 */
+	public boolean hasHigherPriority(LogLevel referenceLogLevel) {
+		return ordinal()>0 && ordinal()<=referenceLogLevel.ordinal();
+	}	
+	
+	/** Replies if this log level is for anomalies.
+	 * 
+	 * @return <code>true</code> if this log level is an error or a warning,
+	 * otherwise <code>false</code>.
+	 */
+	public boolean isAnomalyLevel() {
+		return this==ERROR || this==WARNING;
+	}
+
+}

Added: tags/afc-2.0/arakhneLogger/src/main/java/org/arakhne/logging/Logger.java
===================================================================
--- tags/afc-2.0/arakhneLogger/src/main/java/org/arakhne/logging/Logger.java	                        (rev 0)
+++ tags/afc-2.0/arakhneLogger/src/main/java/org/arakhne/logging/Logger.java	2010-01-21 08:29:52 UTC (rev 117)
@@ -0,0 +1,302 @@
+/* 
+ * $Id$
+ * 
+ * Copyright (C) 2004-2009 St&eacute;phane GALLAND and Nicolas GAUD
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * This program is free software; you can redistribute it and/or modify
+ */
+package org.arakhne.logging;
+
+/**
+ * The main user interface to logging.
+ * This interface provides classic method use to log 
+ * string or status at various level.
+ * These level are described in the <code>LogLevel</code> Enum;
+ * 
+ * @author Nicolas GAUD &lt;gaud@xxxxxxxxxxx&gt;
+ * @author St&eacute;phane GALLAND &lt;galland@xxxxxxxxxxx&gt;
+ * @version $Name$ $Revision$ $Date$
+ * @see LogLevel
+ */
+public interface Logger {
+
+	/**
+	 * Return the name of this <code>Logger</code> instance.
+	 * 
+	 * @return the name of this <code>Logger</code> instance.
+	 */
+	public String getName();
+
+	/**
+	 * Is the logger instance enabled for the DEBUG level?
+	 * 
+	 * @return <code>true</code> if this Logger is enabled for the DEBUG level,
+	 * <code>false</code> otherwise.
+	 */
+	public boolean isDebugEnabled();
+
+	/**
+	 * Log the specified message at the specified level
+	 * 
+	 * @param level - the log level
+	 * @param msg - the message to log
+	 * @deprecated see {@link #log(Object, LogLevel, String)}
+	 */
+	@Deprecated
+	public void log(LogLevel level, String msg);
+
+	/**
+	 * Log the specified message at the specified level
+	 * 
+	 * @param source - the object which send this log
+	 * @param level - the log level
+	 * @param msg - the message to log
+	 * @since 1.2
+	 */
+	public void log(Object source, LogLevel level, String msg);
+
+	/**
+	 * Log the specified message at the specified level
+	 * 
+	 * @param level - the log level
+	 * @param msg - the message to log
+	 * @param exception - the exception cause of the log message
+	 * @deprecated see {@link #log(Object, LogLevel, String, Throwable)}
+	 */
+	@Deprecated
+	public void log(LogLevel level, String msg, Throwable exception);
+
+	/**
+	 * Log the specified message at the specified level
+	 * 
+	 * @param source - the object which send this log
+	 * @param level - the log level
+	 * @param msg - the message to log
+	 * @param exception - the exception cause of the log message
+	 * @since 1.2
+	 */
+	public void log(Object source, LogLevel level, String msg, Throwable exception);
+
+	/**
+	 * Log a message at the DEBUG level.
+	 *
+	 * @param msg the message string to be logged
+	 * @deprecated see {@link #debug(Object, String)}
+	 */
+	@Deprecated
+	public void debug(String msg);
+
+	/**
+	 * Log a message at the DEBUG level.
+	 *
+	 * @param source - the object which send this log
+	 * @param msg the message string to be logged
+	 * @since 1.2
+	 */
+	public void debug(Object source, String msg);
+
+	/**
+	 * Log an exception (throwable) at the DEBUG level with an
+	 * accompanying message. 
+	 * 
+	 * @param msg the message accompanying the exception
+	 * @param t the exception (throwable) to log
+	 * @deprecated see {@link #debug(Object, String, Throwable)}
+	 */ 
+	@Deprecated
+	public void debug(String msg, Throwable t);
+
+	/**
+	 * Log an exception (throwable) at the DEBUG level with an
+	 * accompanying message. 
+	 * 
+	 * @param source - the object which send this log
+	 * @param msg the message accompanying the exception
+	 * @param t the exception (throwable) to log
+	 * @since 1.2
+	 */ 
+	public void debug(Object source, String msg, Throwable t);
+
+	/**
+	 * Is the logger instance enabled for the INFO level?
+	 * 
+	 * @return <code>true</code> if this Logger is enabled for the INFO level,
+	 * <code>false</code> otherwise.
+	 */
+	public boolean isInfoEnabled();
+
+
+	/**
+	 * Log a message at the INFO level.
+	 *
+	 * @param msg the message string to be logged
+	 * @deprecated see {@link #info(Object, String)}
+	 */
+	@Deprecated
+	public void info(String msg);
+
+	/**
+	 * Log a message at the INFO level.
+	 *
+	 * @param source - the object which send this log
+	 * @param msg the message string to be logged
+	 * @since 1.2
+	 */
+	public void info(Object source, String msg);
+
+	/**
+	 * Log an exception (throwable) at the INFO level with an
+	 * accompanying message. 
+	 * 
+	 * @param msg the message accompanying the exception
+	 * @param t the exception (throwable) to log 
+	 * @deprecated see {@link #info(Object, String, Throwable)}
+	 */
+	@Deprecated
+	public void info(String msg, Throwable t);
+
+	/**
+	 * Log an exception (throwable) at the INFO level with an
+	 * accompanying message. 
+	 * 
+	 * @param source - the object which send this log
+	 * @param msg the message accompanying the exception
+	 * @param t the exception (throwable) to log
+	 * @since 1.2 
+	 */
+	public void info(Object source, String msg, Throwable t);
+
+	/**
+	 * Is the logger instance enabled for the WARN level?
+	 * 
+	 * @return <code>true</code> if this Logger is enabled for the WARN level,
+	 * <code>false</code> otherwise.
+	 */
+	public boolean isWarnEnabled();
+
+	/**
+	 * Log a message at the WARN level.
+	 *
+	 * @param msg the message string to be logged
+	 * @deprecated see {@link #warn(Object, String)}
+	 */
+	@Deprecated
+	public void warn(String msg);
+
+	/**
+	 * Log a message at the WARN level.
+	 *
+	 * @param source - the object which send this log
+	 * @param msg the message string to be logged
+	 * @since 1.2
+	 */
+	public void warn(Object source, String msg);
+
+	/**
+	 * Log an exception (throwable) at the WARN level with an
+	 * accompanying message. 
+	 * 
+	 * @param msg the message accompanying the exception
+	 * @param t the exception (throwable) to log 
+	 * @deprecated see {@link #warn(Object, String, Throwable)}
+	 */
+	@Deprecated
+	public void warn(String msg, Throwable t);
+
+	/**
+	 * Log an exception (throwable) at the WARN level with an
+	 * accompanying message. 
+	 * 
+	 * @param source - the object which send this log
+	 * @param msg the message accompanying the exception
+	 * @param t the exception (throwable) to log
+	 * @since 1.2 
+	 */
+	public void warn(Object source, String msg, Throwable t);
+
+	/**
+	 * Is the logger instance enabled for the ERROR level?
+	 * 
+	 * @return <code>true</code> if this Logger is enabled for the ERROR level,
+	 * <code>false</code> otherwise.
+	 */
+	public boolean isErrorEnabled();
+
+	/**
+	 * Log a message at the ERROR level.
+	 *
+	 * @param msg the message string to be logged
+	 * @deprecated see {@link #error(Object, String)}
+	 */
+	@Deprecated
+	public void error(String msg);
+
+	/**
+	 * Log a message at the ERROR level.
+	 *
+	 * @param source - the object which send this log
+	 * @param msg the message string to be logged
+	 * @since 1.2
+	 */
+	public void error(Object source, String msg);
+
+	/**
+	 * Log an exception (throwable) at the ERROR level with an
+	 * accompanying message. 
+	 * 
+	 * @param msg the message accompanying the exception
+	 * @param t the exception (throwable) to log
+	 * @deprecated see {@link #error(Object, String, Throwable)}
+	 */
+	@Deprecated
+	public void error(String msg, Throwable t);
+	
+	/**
+	 * Log an exception (throwable) at the ERROR level with an
+	 * accompanying message. 
+	 * 
+	 * @param source - the object which send this log
+	 * @param msg the message accompanying the exception
+	 * @param t the exception (throwable) to log
+	 * @since 1.2
+	 */
+	public void error(Object source, String msg, Throwable t);
+
+	/** Set the minimum log level.
+	 * 
+	 * @param level
+	 */
+	public void setLogLevel(LogLevel level);
+
+	/** Replies the minimum log level.
+	 * 
+	 * @return the minimal log level
+	 */
+	public LogLevel getLogLevel();
+
+	/** Add listener on logger events.
+	 * 
+	 * @param listener
+	 */
+	public void addLoggerEventListener(LoggerEventListener listener);
+
+	/** Remove listener on logger events.
+	 * 
+	 * @param listener
+	 */
+	public void removeLoggerEventListener(LoggerEventListener listener);
+
+}

Added: tags/afc-2.0/arakhneLogger/src/main/java/org/arakhne/logging/LoggerEvent.java
===================================================================
--- tags/afc-2.0/arakhneLogger/src/main/java/org/arakhne/logging/LoggerEvent.java	                        (rev 0)
+++ tags/afc-2.0/arakhneLogger/src/main/java/org/arakhne/logging/LoggerEvent.java	2010-01-21 08:29:52 UTC (rev 117)
@@ -0,0 +1,103 @@
+/* 
+ * $Id$
+ * 
+ * Copyright (C) 2004-2009 St&eacute;phane GALLAND and Nicolas GAUD
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * This program is free software; you can redistribute it and/or modify
+ */
+package org.arakhne.logging;
+
+import java.util.EventObject;
+
+/**
+ * This class provides a description of a logging event.
+ * 
+ * @author St&eacute;phane GALLAND &lt;galland@xxxxxxxxxxx&gt;
+ * @version $Name$ $Revision$ $Date$
+ * @see Logger
+ */
+public class LoggerEvent extends EventObject {
+
+	private static final long serialVersionUID = -272287628530037390L;
+	
+	private final Logger logger;
+	private final LogLevel level;
+	private final String message;
+	private final Throwable exception;
+	
+	/**
+	 * @param source is the source of the event.
+	 * @param logger is the logger which has received the message.
+	 * @param level is the level of the message.
+	 * @param message is the text of the message.
+	 */
+	public LoggerEvent(Object source, Logger logger, LogLevel level, String message) {
+		super(source);
+		this.logger = logger;
+		this.level = level;
+		this.message = message;
+		this.exception = null;
+	}
+	
+	/**
+	 * @param source is the source of the event.
+	 * @param logger is the logger which has received the message.
+	 * @param level is the level of the message
+	 * @param message is the text of the message.
+	 * @param exception is the exception associated to the message.
+	 */
+	public LoggerEvent(Object source, Logger logger, LogLevel level, String message, Throwable exception) {
+		super(source);
+		this.logger = logger;
+		this.level = level;
+		this.message = message;
+		this.exception = exception;
+	}
+	
+	/** Replies the logger which has received the event.
+	 * 
+	 * @return the logger which as receivd the log.
+	 * @since 1.2
+	 */
+	public Logger getLogger() {
+		return this.logger;
+	}
+
+	/** Replies the log level of the event.
+	 * 
+	 * @return the log level of the event.
+	 */
+	public LogLevel getLogLevel() {
+		return this.level;
+	}
+	
+	/** Replies the message in the event.
+	 * 
+	 * @return the message in the event.
+	 */
+	public String getMessage() {
+		return this.message;
+	}
+	
+	/** Replies the exception associated to this event.
+	 * 
+	 * @return the associated exception or <code>null</code>
+	 */
+	public Throwable getException() {
+		return this.exception;
+	}
+
+}

Added: tags/afc-2.0/arakhneLogger/src/main/java/org/arakhne/logging/LoggerEventListener.java
===================================================================
--- tags/afc-2.0/arakhneLogger/src/main/java/org/arakhne/logging/LoggerEventListener.java	                        (rev 0)
+++ tags/afc-2.0/arakhneLogger/src/main/java/org/arakhne/logging/LoggerEventListener.java	2010-01-21 08:29:52 UTC (rev 117)
@@ -0,0 +1,40 @@
+/* 
+ * $Id$
+ * 
+ * Copyright (C) 2004-2008 St&eacute;phane GALLAND and Nicolas GAUD
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * This program is free software; you can redistribute it and/or modify
+ */
+package org.arakhne.logging;
+
+import java.util.EventListener;
+
+/**
+ * Listener on logger events.
+ * 
+ * @author St&eacute;phane GALLAND &lt;galland@xxxxxxxxxxx&gt;
+ * @version $Name$ $Revision$ $Date$
+ * @see Logger
+ */
+public interface LoggerEventListener extends EventListener {
+
+	/** Invoked when an event was logged in.
+	 * 
+	 * @param event
+	 */
+	public void onLoggedEvent(LoggerEvent event);
+
+}

Added: tags/afc-2.0/arakhneLogger/src/main/java/org/arakhne/logging/LoggingSystem.java
===================================================================
--- tags/afc-2.0/arakhneLogger/src/main/java/org/arakhne/logging/LoggingSystem.java	                        (rev 0)
+++ tags/afc-2.0/arakhneLogger/src/main/java/org/arakhne/logging/LoggingSystem.java	2010-01-21 08:29:52 UTC (rev 117)
@@ -0,0 +1,272 @@
+/* 
+ * $Id$
+ * 
+ * Copyright (C) 2004-2008 St&eacute;phane GALLAND and Nicolas GAUD
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * This program is free software; you can redistribute it and/or modify
+ */
+package org.arakhne.logging;
+
+import java.lang.reflect.Constructor;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.TreeMap;
+
+/** This interface describes the body of an situated agent.
+ * The body is the only available interaction mean between
+ * an agent and the environment.
+ * 
+ * @author Nicolas GAUD &lt;gaud@xxxxxxxxxxx&gt;
+ * @author St&eacute;phane GALLAND &lt;galland@xxxxxxxxxxx&gt;
+ * @version $Name$ $Revision$ $Date$
+ */
+public class LoggingSystem {
+
+	private static final String[] PREFERED_LOGGERS = new String[] {
+		"org.arakhne.logging.ApacheLogger", //$NON-NLS-1$
+		"org.arakhne.logging.SunLogger", //$NON-NLS-1$
+		"org.arakhne.logging.ConsoleLogger" //$NON-NLS-1$
+	};
+	
+	private static final LoggingSystem singleton = new LoggingSystem();
+	
+	/**
+	 * Return an anonymous logger.
+	 * 
+	 * @return logger
+	 */
+	public static Logger getLogger() {
+		return singleton.getAnonymousLogger();
+	}
+
+	/**
+	 * Return a logger named according to the name parameter.
+	 * 
+	 * @param name - The name of the logger.
+	 * @return logger
+	 */
+	public static Logger getLogger(String name) {
+		return singleton.getPreferedLogger(name);
+	}
+
+	/**
+	 * Return a logger named corresponding to the class passed as parameter.
+	 * 
+	 * @param clazz - the returned logger will be named after clazz
+	 * @return logger
+	 */
+	public static Logger getLogger(Class<?> clazz) {
+		return singleton.getPreferedLogger(clazz.getCanonicalName());
+	}
+
+	/**
+	 * Returns the instance of <code>LoggingSystem</code> in use
+	 * @return the instance of <code>LoggingSystem</code> in use
+	 */
+	public static LoggingSystem getLoggingSystem() {
+		return singleton;
+	}	
+	
+	private final Map<String,Logger> preferedLoggers = new TreeMap<String,Logger>();
+	private Logger anonymousLogger = null;
+	
+	private Class<? extends Logger> preferedLoggerType = null;
+	
+	private LogLevel defaultLevel = LogLevel.WARNING;
+	
+	private List<LoggerEventListener> listeners = null;
+	
+	/**
+	 */
+	protected LoggingSystem() {
+		//
+	}
+	
+	/** Set the default log level for new loggers.
+	 * 
+	 * @param logLevel
+	 */
+	public void setDefaultLogLevel(LogLevel logLevel) {
+		assert(logLevel!=null);
+		this.defaultLevel = logLevel;
+	}
+	
+	/** Replies the default log level for new loggers.
+	 * 
+	 * @return the default log level, never <code>null</code>
+	 */
+	public LogLevel getDefaultLogLevel() {
+		return this.defaultLevel;
+	}
+
+	/** Set the prefered type for the loggers.
+	 * 
+	 * @param type is the prefered type or <code>null</code> to use the system default.
+	 */
+	public void setPreferedLoggerType(Class<? extends Logger> type) {
+		this.preferedLoggerType = type;
+	}
+	
+	/** Replies the prefered type for the loggers.
+	 * 
+	 * @return the type of <code>null</code> to use the system default.
+	 */
+	public Class<? extends Logger> getPreferedLoggerType() {
+		return this.preferedLoggerType;
+	}
+	/** Set the prefered logger.
+	 * 
+	 * @param scopeName is the name of the scope for the new prefered logger.
+	 * @param logger msut be a reference to the new prefered logger
+	 * or <code>null</code> to use the default logger.
+	 */
+	public void setPreferedLogger(String scopeName, Logger logger) {
+		if (logger==null)
+			this.preferedLoggers.remove(scopeName);
+		else
+			this.preferedLoggers.put(scopeName, logger);
+	}
+	
+	/** Replies the prefered logger for the specified scope.
+	 * 
+	 * @param scopeName is the name of the logger scope.
+	 * @return the logger.
+	 */
+	public Logger getPreferedLogger(String scopeName) {
+		Logger refLogger = this.preferedLoggers.get(scopeName);
+		if (refLogger!=null) return refLogger;
+		// Create default logger
+		Logger logger = createLoggerInstance(scopeName, this.defaultLevel);
+		this.preferedLoggers.put(scopeName, logger);
+		return logger;
+	}	
+	
+	/** Replies the logger to use when the scope is unknown.
+	 * 
+	 * @return the anonymous logger.
+	 */
+	public Logger getAnonymousLogger() {
+		Logger anonLogger = this.anonymousLogger;
+		if (anonLogger==null) {
+			anonLogger = createLoggerInstance(null, this.defaultLevel);
+			this.anonymousLogger = anonLogger;
+		}
+		return anonLogger;
+	}
+	
+	/** 
+	 * @param name is the scope of the logger to create.
+	 * @param minLogLevel is the minimal log level of the new logger.
+	 * @return the created logged.
+	 */
+	protected Logger createLoggerInstance(String name, LogLevel minLogLevel) {
+		Class<? extends Logger> type = findLoggerClass();
+		Logger logger = createLoggerInstance(type, name);
+		if (logger!=null) {
+			logger.setLogLevel(this.defaultLevel);
+			return logger;
+		}
+		type = findDefaultLoggerClass();
+		logger = createLoggerInstance(type, name);
+		if (logger!=null) {
+			logger.setLogLevel(this.defaultLevel);
+			return logger;
+		}
+		throw new Error("unable to create an instance of Logger"); //$NON-NLS-1$
+	}
+	
+	private Logger createLoggerInstance(Class<? extends Logger> type, String name) {
+		if (type==null) return null;
+		if ((name!=null)&&(!"".equals(name))) { //$NON-NLS-1$
+			try {
+				Constructor<? extends Logger> cons = type.getConstructor(String.class);
+				return cons.newInstance(name);
+			}
+			catch(Exception _) {
+				//
+			}
+		}
+		try {
+			return type.newInstance();
+		}
+		catch(Exception _) {
+			//
+		}
+		return null;
+	}
+
+	/**
+	 * @return the type of the the preferred logging system.
+	 */
+	protected final Class<? extends Logger> findLoggerClass() {
+		if (this.preferedLoggerType!=null) return this.preferedLoggerType;
+		return findDefaultLoggerClass();
+	}
+
+	/**
+	 * @return the type of the the preferred logging system.
+	 */
+	@SuppressWarnings("unchecked")
+	protected Class<? extends Logger> findDefaultLoggerClass() {
+		for(String className : PREFERED_LOGGERS) {
+			try {
+				Class<?> type = Class.forName(className);
+				if (type!=null && Logger.class.isAssignableFrom(type)) return (Class<? extends Logger>)type;
+			}
+			catch(Exception _) {
+				//
+			}
+		}
+		return null;
+	}
+
+	/** Add listener on logger events.
+	 * 
+	 * @param listener
+	 */
+	public final void addLoggerEventListener(LoggerEventListener listener) {
+		if (this.listeners==null) {
+			this.listeners = new ArrayList<LoggerEventListener>();
+		}
+		this.listeners.add(listener);
+	}
+
+	/** Remove listener on logger events.
+	 * 
+	 * @param listener
+	 */
+	public void removeLoggerEventListener(LoggerEventListener listener) {
+		if (this.listeners!=null) {
+			this.listeners.remove(listener);
+			if (this.listeners.isEmpty())
+				this.listeners = null;
+		}
+	}
+
+	/** Notify the logger event listeners.
+	 * 
+	 * @param event
+	 */
+	final void fireLoggerEvent(LoggerEvent event) {
+		if (this.listeners!=null) {
+			for(LoggerEventListener listener : this.listeners) {
+				listener.onLoggedEvent(event);
+			}
+		}
+	}
+
+}

Added: tags/afc-2.0/arakhneLogger/src/main/java/org/arakhne/logging/SunLogger.java
===================================================================
--- tags/afc-2.0/arakhneLogger/src/main/java/org/arakhne/logging/SunLogger.java	                        (rev 0)
+++ tags/afc-2.0/arakhneLogger/src/main/java/org/arakhne/logging/SunLogger.java	2010-01-21 08:29:52 UTC (rev 117)
@@ -0,0 +1,114 @@
+/* 
+ * $Id$
+ * 
+ * Copyright (C) 2004-2009 St&eacute;phane GALLAND and Nicolas GAUD
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * This program is free software; you can redistribute it and/or modify
+ */
+package org.arakhne.logging;
+
+import java.util.logging.Level;
+
+/**
+ * This class provides the concrete implementation of the <code>Logger</code>
+ * interface. This impl is based on the Sun's Logging Facade for Java
+ * 
+ * @author St&eacute;phane GALLAND &lt;galland@xxxxxxxxxxx&gt;
+ * @version $Name$ $Revision$ $Date$
+ * @see Logger
+ */
+public class SunLogger extends AbstractLogger {
+
+	private final java.util.logging.Logger bindedLogger;
+
+	/**
+	 * Create an unamed logger based of Sun's logging system.
+	 */
+	public SunLogger() {
+		this.bindedLogger = java.util.logging.Logger.getAnonymousLogger();
+		this.bindedLogger.setLevel(Level.ALL);
+	}
+
+	/**
+	 * Create a named logger based of Sun's logging system.
+	 * 
+	 * @param name is the name of the logger.
+	 */
+	public SunLogger(String name) {
+		this.bindedLogger = java.util.logging.Logger.getLogger(name);
+		this.bindedLogger.setLevel(toSunLevel(getLogLevel()));
+	}
+
+//	**************************************************************************************//
+
+	/** Translate a logging level into the same thing for Sun's logging system.
+	 * 
+	 * @param level is the level to translate
+	 * @return the Sun's level
+	 */
+	protected Level toSunLevel(LogLevel level) {
+		switch(level) {
+		case NONE:
+			return Level.OFF;
+		case ERROR:
+			return Level.SEVERE;
+		case WARNING:
+			return Level.WARNING;
+		case INFO:
+			return Level.INFO;
+		case DEBUG:
+			return Level.CONFIG;
+		}
+		return Level.OFF;
+	}
+	
+	/** {@InheritDoc}
+	 */
+	@Override
+	public void log(Object source, LogLevel level, String msg) {
+		this.bindedLogger.log(toSunLevel(level),msg);
+		fireLoggerEvent(source, level, msg);
+	}
+
+	/** {@InheritDoc}
+	 */
+	public void log(Object source, LogLevel level, String msg, Throwable exception) {
+		this.bindedLogger.log(toSunLevel(level),msg,exception);
+		fireLoggerEvent(source, level, msg);
+	}
+
+	
+//	**************************************************************************************//	
+
+	/** {@InheritDoc}
+	 * 
+	 * @return {@InheritDoc}
+	 */
+	public String getName() {
+		return this.bindedLogger.getName();
+	}
+
+	/** Set the minimum log level.
+	 * 
+	 * @param level
+	 */
+	@Override
+	public void setLogLevel(LogLevel level) {
+		super.setLogLevel(level);
+		this.bindedLogger.setLevel(toSunLevel(level));
+	}
+
+}

Added: tags/afc-2.0/arakhneLogger/src/main/resources/org/arakhne/logging/AbstractStandAloneLogger.properties
===================================================================
--- tags/afc-2.0/arakhneLogger/src/main/resources/org/arakhne/logging/AbstractStandAloneLogger.properties	                        (rev 0)
+++ tags/afc-2.0/arakhneLogger/src/main/resources/org/arakhne/logging/AbstractStandAloneLogger.properties	2010-01-21 08:29:52 UTC (rev 117)
@@ -0,0 +1,23 @@
+# $Id$
+# 
+# Copyright (C) 2009 St&eacute;phane GALLAND and Nicolas GAUD
+# 
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+# 
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+# Lesser General Public License for more details.
+# 
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+# This program is free software; you can redistribute it and/or modify
+
+ERROR = Error
+WARNING = Warning
+INFO = Information
+DEBUG = Debug

Added: tags/afc-2.0/arakhneLogger/src/main/resources/org/arakhne/logging/AbstractStandAloneLogger_de.properties
===================================================================
--- tags/afc-2.0/arakhneLogger/src/main/resources/org/arakhne/logging/AbstractStandAloneLogger_de.properties	                        (rev 0)
+++ tags/afc-2.0/arakhneLogger/src/main/resources/org/arakhne/logging/AbstractStandAloneLogger_de.properties	2010-01-21 08:29:52 UTC (rev 117)
@@ -0,0 +1,23 @@
+# $Id$
+# 
+# Copyright (C) 2009 St&eacute;phane GALLAND and Nicolas GAUD
+# 
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+# 
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+# Lesser General Public License for more details.
+# 
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+# This program is free software; you can redistribute it and/or modify
+
+ERROR = St\xF6rung
+WARNING = Warnen
+INFO = Informationen
+DEBUG = Auspr\xFCfen mitteilung en

Added: tags/afc-2.0/arakhneLogger/src/main/resources/org/arakhne/logging/AbstractStandAloneLogger_es.properties
===================================================================
--- tags/afc-2.0/arakhneLogger/src/main/resources/org/arakhne/logging/AbstractStandAloneLogger_es.properties	                        (rev 0)
+++ tags/afc-2.0/arakhneLogger/src/main/resources/org/arakhne/logging/AbstractStandAloneLogger_es.properties	2010-01-21 08:29:52 UTC (rev 117)
@@ -0,0 +1,23 @@
+# $Id$
+# 
+# Copyright (C) 2009 St&eacute;phane GALLAND and Nicolas GAUD
+# 
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+# 
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+# Lesser General Public License for more details.
+# 
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+# This program is free software; you can redistribute it and/or modify
+
+ERROR = Error
+WARNING = Cuidado
+INFO = Informaci\xF3n
+DEBUG = Eliminan errores del mensaje

Added: tags/afc-2.0/arakhneLogger/src/main/resources/org/arakhne/logging/AbstractStandAloneLogger_fr.properties
===================================================================
--- tags/afc-2.0/arakhneLogger/src/main/resources/org/arakhne/logging/AbstractStandAloneLogger_fr.properties	                        (rev 0)
+++ tags/afc-2.0/arakhneLogger/src/main/resources/org/arakhne/logging/AbstractStandAloneLogger_fr.properties	2010-01-21 08:29:52 UTC (rev 117)
@@ -0,0 +1,23 @@
+# $Id$
+# 
+# Copyright (C) 2009 St&eacute;phane GALLAND and Nicolas GAUD
+# 
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+# 
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+# Lesser General Public License for more details.
+# 
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+# This program is free software; you can redistribute it and/or modify
+
+ERROR = Erreur
+WARNING = Avertissement
+INFO = Information
+DEBUG = D\xE9veloppement

Added: tags/afc-2.0/arakhneLogger/src/main/resources/org/arakhne/logging/AbstractStandAloneLogger_it.properties
===================================================================
--- tags/afc-2.0/arakhneLogger/src/main/resources/org/arakhne/logging/AbstractStandAloneLogger_it.properties	                        (rev 0)
+++ tags/afc-2.0/arakhneLogger/src/main/resources/org/arakhne/logging/AbstractStandAloneLogger_it.properties	2010-01-21 08:29:52 UTC (rev 117)
@@ -0,0 +1,23 @@
+# $Id$
+# 
+# Copyright (C) 2009 St&eacute;phane GALLAND and Nicolas GAUD
+# 
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+# 
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+# Lesser General Public License for more details.
+# 
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+# This program is free software; you can redistribute it and/or modify
+
+ERROR = Errore
+WARNING = Avvertire
+INFO = Informazioni
+DEBUG = Mettono a punto il messaggio

Added: tags/afc-2.0/arakhneLogger/src/main/resources/org/arakhne/logging/AbstractStandAloneLogger_nl.properties
===================================================================
--- tags/afc-2.0/arakhneLogger/src/main/resources/org/arakhne/logging/AbstractStandAloneLogger_nl.properties	                        (rev 0)
+++ tags/afc-2.0/arakhneLogger/src/main/resources/org/arakhne/logging/AbstractStandAloneLogger_nl.properties	2010-01-21 08:29:52 UTC (rev 117)
@@ -0,0 +1,23 @@
+# $Id$
+# 
+# Copyright (C) 2009 St&eacute;phane GALLAND and Nicolas GAUD
+# 
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+# 
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+# Lesser General Public License for more details.
+# 
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+# This program is free software; you can redistribute it and/or modify
+
+ERROR = Fout
+WARNING = Waarschuwing
+INFO = Informatie
+DEBUG = Zuivert bericht

Added: tags/afc-2.0/arakhneLogger/src/main/resources/org/arakhne/logging/AbstractStandAloneLogger_pt.properties
===================================================================
--- tags/afc-2.0/arakhneLogger/src/main/resources/org/arakhne/logging/AbstractStandAloneLogger_pt.properties	                        (rev 0)
+++ tags/afc-2.0/arakhneLogger/src/main/resources/org/arakhne/logging/AbstractStandAloneLogger_pt.properties	2010-01-21 08:29:52 UTC (rev 117)
@@ -0,0 +1,25 @@
+# $Id$
+# 
+# Copyright (C) 2009 St&eacute;phane GALLAND and Nicolas GAUD
+# 
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+# 
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+# Lesser General Public License for more details.
+# 
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+# This program is free software; you can redistribute it and/or modify
+
+ERRO =  ADVERT\xCANCIA =  A informa\xE7\xE3o = a  ELIMINAM ERROS =  
+
+ERROR = Erro
+WARNING = Advert\xEAncia
+INFO = Informa\xE7\xE3o
+DEBUG = Eliminam erros

Added: tags/afc-2.0/arakhneRefs/pom.xml
===================================================================
--- tags/afc-2.0/arakhneRefs/pom.xml	                        (rev 0)
+++ tags/afc-2.0/arakhneRefs/pom.xml	2010-01-21 08:29:52 UTC (rev 117)
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"; xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"; xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd";>
+  <modelVersion>4.0.0</modelVersion>
+
+  <parent>
+	<artifactId>afc</artifactId>
+	<groupId>org.arakhne.afc</groupId>
+	<version>2.0</version>
+  </parent>
+
+  <groupId>org.arakhne.afc</groupId>
+  <artifactId>arakhneRefs</artifactId>
+  <packaging>jar</packaging>
+  <version>5.2</version>
+  <name>${pom.artifactId}</name>
+  <url>http://www.arakhne.org/arakhneRefs/</url>
+
+	<!-- ======================================= -->
+	<!-- ====       Project Information      === -->
+	<!-- ======================================= -->
+		
+	<dependencies>
+		<dependency>
+			<groupId>junit</groupId>
+			<artifactId>junit</artifactId>
+			<scope>test</scope>
+		</dependency>
+	</dependencies>
+
+</project>

Added: tags/afc-2.0/arakhneRefs/src/main/java/org/arakhne/util/ref/AbstractWeakSoftValueMap.java
===================================================================
--- tags/afc-2.0/arakhneRefs/src/main/java/org/arakhne/util/ref/AbstractWeakSoftValueMap.java	                        (rev 0)
+++ tags/afc-2.0/arakhneRefs/src/main/java/org/arakhne/util/ref/AbstractWeakSoftValueMap.java	2010-01-21 08:29:52 UTC (rev 117)
@@ -0,0 +1,534 @@
+/* 
+ * $Id: WeakValueMap.java,v 1.1 2007-02-20 08:52:37 sgalland Exp $
+ * 
+ * Copyright (C) 2005-2009 St&eacute;phane GALLAND
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * This program is free software; you can redistribute it and/or modify
+ */
+
+package org.arakhne.util.ref;
+
+import java.lang.ref.Reference;
+import java.lang.ref.ReferenceQueue;
+import java.util.AbstractMap;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * A <tt>Map</tt> implementation with <em>weak/soft values</em>. An entry in a
+ * <tt>AbstractWeakSoftValueMap</tt> will automatically be removed when its value is no
+ * longer in ordinary use or null.
+ *
+ * @param <K> is the type of the keys.
+ * @param <V> is the type of the values.
+ * @author St&eacute;phane GALLAND &lt;galland@xxxxxxxxxxx&gt;
+ * @version $Name:  $ $Revision: 1.1 $ $Date: 2007-02-20 08:52:37 $
+ */
+public abstract class AbstractWeakSoftValueMap<K,V> extends AbstractMap<K,V> {
+	
+	/** Defines the NULL object inside a WeakValueMap.
+	 * 
+	 * @see #maskNull(Object)
+	 */
+	protected static final Object NULL_VALUE = new Object();
+
+	/** Mask the null values given by the used of this map.
+	 * <p>
+	 * This method replaces the <code>null</code> value by
+	 * the internal representation {@link #NULL_VALUE}.
+	 *
+	 * @param <V> is the type of the value.
+	 * @param value is the value given by the user of this map.
+	 * @return the internal representation of the value.
+	 * @see #unmaskNull(Object)
+	 */
+	@SuppressWarnings("unchecked")
+	protected static <V> V maskNull(V value) {
+		return (value==null) ? (V)NULL_VALUE : value;
+	}
+
+	/** Unmask the null values given by the used of this map.
+	 * <p>
+	 * This method replaces the internal representation
+	 * {@link #NULL_VALUE} of null values by its user representation
+	 * <code>null</code>.
+	 * 
+	 * @param <V> is the type of the value.
+	 * @param value is the value given by the user of this map.
+	 * @return the internal representation of the value.
+	 * @see #maskNull(Object)
+	 */
+	protected static <V> V unmaskNull(V value) {
+		return (value==NULL_VALUE) ? null : value;
+	}
+
+	private boolean autoExpurge = false;
+	private final HashMap<K,WeakSoftValue<K,V>> map;
+	private final ReferenceQueue<V> queue = new ReferenceQueue<V>();
+
+    /**
+     * Constructs an empty <tt>HashMap</tt> with the specified initial
+     * capacity and load factor.
+     *
+     * @param  initialCapacity the initial capacity
+     * @param  loadFactor      the load factor
+     * @throws IllegalArgumentException if the initial capacity is negative
+     *         or the load factor is nonpositive
+     */
+    public AbstractWeakSoftValueMap(int initialCapacity, float loadFactor) {
+        this.map = new HashMap<K,WeakSoftValue<K,V>>(initialCapacity, loadFactor);
+    }
+
+    /**
+     * Constructs an empty <tt>HashMap</tt> with the specified initial
+     * capacity and the default load factor (0.75).
+     *
+     * @param  initialCapacity the initial capacity.
+     * @throws IllegalArgumentException if the initial capacity is negative.
+     */
+    public AbstractWeakSoftValueMap(int initialCapacity) {
+        this.map = new HashMap<K,WeakSoftValue<K,V>>(initialCapacity);
+    }
+
+    /**
+     * Constructs an empty <tt>HashMap</tt> with the default initial capacity
+     * (16) and the default load factor (0.75).
+     */
+    public AbstractWeakSoftValueMap() {
+        this.map = new HashMap<K,WeakSoftValue<K,V>>();
+    }
+
+    /**
+     * Constructs a new <tt>HashMap</tt> with the same mappings as the
+     * specified <tt>Map</tt>.  The <tt>HashMap</tt> is created with
+     * default load factor (0.75) and an initial capacity sufficient to
+     * hold the mappings in the specified <tt>Map</tt>.
+     *
+     * @param   m the map whose mappings are to be placed in this map
+     * @throws  NullPointerException if the specified map is null
+     */
+    public AbstractWeakSoftValueMap(Map<? extends K, ? extends V> m) {
+        this.map = new HashMap<K,WeakSoftValue<K,V>>();
+        putAll(m);
+    }	
+
+    /** Clean the references that was marked as released inside
+     * the queue.
+     */
+	protected final void expurgeNow() {
+		if (this.autoExpurge)
+			expurge();
+		else
+			expurgeQueuedReferences();
+	}
+	
+	/** Replies if this map expurge all the released references
+	 * even if they are not enqueued by the virtual machine
+	 * 
+	 * @return <code>true</code> is the values are deeply expurged when they
+	 * are released from the moemory, otherwise <code>false</code>
+	 */
+	public final boolean isDeeplyExpurge() {
+		return this.autoExpurge;
+	}
+	
+	/** Set if this map expurge all the released references
+	 * even if they are not enqueued by the virtual machine
+	 * 
+	 * @param deeplyExpurge must be <code>true</code> to
+	 * expurge all the released values, otherwise <code>false</code>
+	 * to expurge only the enqueued values.
+	 * @return the old value of this flag
+	 */
+	public final boolean setDeeplyExpurge(boolean deeplyExpurge) {
+		boolean old = this.autoExpurge;
+		this.autoExpurge = deeplyExpurge;
+		return old;
+	}
+	
+    /** Clean the references that was marked as released inside
+     * the queue.
+     */
+	public final void expurgeQueuedReferences() {
+		Reference<? extends V> o;
+		while((o = this.queue.poll()) != null) {
+			if (o instanceof WeakSoftValue<?,?>) {
+				this.map.remove(((WeakSoftValue<?,?>)o).getKey());
+			}
+			o.clear();
+		}
+	}
+
+	/** Clean the references that was released.
+     */
+	public final void expurge() {
+		Reference<? extends V> o;
+		
+		Iterator<Entry<K,WeakSoftValue<K,V>>> iter = this.map.entrySet().iterator();
+		Entry<K,WeakSoftValue<K,V>> entry;
+		WeakSoftValue<K,V> value;
+		while (iter.hasNext()) {
+			entry = iter.next();
+			if (entry!=null) {
+				value = entry.getValue();
+				if ((value!=null)&&
+					((value.isEnqueued())||(value.get()==null))) {
+					value.enqueue();
+					value.clear();
+				}
+			}
+		}
+		entry = null;
+		value = null;
+
+		while((o = this.queue.poll()) != null) {
+			if (o instanceof WeakSoftValue<?,?>) {
+				this.map.remove(((WeakSoftValue<?,?>)o).getKey());
+			}
+			o.clear();
+		}
+	}
+
+	/** Create a storage object that permits to put the specified
+	 * elements inside this map.
+	 * 
+	 * @param k is the key associated to the value
+	 * @param v is the value
+	 * @param refQueue is the reference queue to use
+	 * @return the new storage object
+	 */
+	protected abstract WeakSoftValue<K,V> makeValue(K k, V v, ReferenceQueue<V> refQueue);
+
+	/** Create a storage object that permits to put the specified
+	 * elements inside this map.
+	 * 
+	 * @param k is the key associated to the value
+	 * @param v is the value
+	 * @return the new storage object
+	 */
+	protected final WeakSoftValue<K,V> makeValue(K k, V v) {
+		return makeValue(k, v, this.queue);
+	}
+
+	/**
+     * {@inheritDoc}
+     */
+	@Override
+	public final V put(K key, V value) {
+		expurgeNow();
+		WeakSoftValue<K,V> ret = this.map.put(key, makeValue(key, value, this.queue));
+		if(ret == null) return null;
+		return ret.getValue();
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	@Override
+	public final Set<Entry<K,V>> entrySet() {
+		expurgeNow();
+		return new InnerEntrySet();
+	}	
+		
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+	public final boolean equals(Object o) {
+    	expurgeNow();
+    	return super.equals(o);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+	public final int hashCode() {
+    	expurgeNow();
+    	return hashCode();
+    }
+        
+	/**
+	 * This interface provides information about the pairs inside
+	 * a map with weak/soft reference values.
+	 * 
+	 * @param <K> is the type of the map keys.
+	 * @param <V> is the type of the map values.
+	 * @author St&eacute;phane GALLAND &lt;galland@xxxxxxxxxxx&gt;
+	 * @version $Name:  $ $Revision: 1.1 $ $Date: 2007-02-20 08:52:37 $
+	 */
+	protected interface WeakSoftValue<K,V> extends Entry<K,V> {
+		
+		/**
+		 * @return if the value is enqueued into a reference queue.
+		 */
+		public boolean isEnqueued();
+		
+		/**
+		 * @return the weak/soft reference.
+		 */
+		public V get();
+
+		/**
+		 * @return if the value was enqueued
+		 */
+		public boolean enqueue();
+
+		/**
+		 */
+		public void clear();
+
+	}
+
+	/**
+	 * @author St&eacute;phane GALLAND &lt;galland@xxxxxxxxxxx&gt;
+	 * @version $Name:  $ $Revision: 1.1 $ $Date: 2007-02-20 08:52:37 $
+	 */
+	@SuppressWarnings("synthetic-access")
+	private class InnerEntrySet implements Set<Entry<K,V>> {
+
+		public InnerEntrySet() {
+			//
+		}
+
+		@Override
+		public final boolean add(java.util.Map.Entry<K, V> e) {
+			K key = e.getKey();
+			V value = e.getValue();
+			return AbstractWeakSoftValueMap.this.map.put(key,
+					makeValue(key, value)) == null;
+		}
+
+		@Override
+		public final boolean addAll(Collection<? extends java.util.Map.Entry<K, V>> c) {
+			boolean ok = true;
+			for(java.util.Map.Entry<K, V> entry : c) {
+				ok = add(entry) && ok;
+			}
+			return ok;
+		}
+
+		@Override
+		public final void clear() {
+			AbstractWeakSoftValueMap.this.map.clear();
+		}
+
+		@Override
+		public final boolean contains(Object o) {
+			if (o instanceof Entry<?,?>) {
+				try {
+					expurgeNow();
+					return AbstractWeakSoftValueMap.this.map.containsKey(((Entry<?,?>)o).getKey());
+				}
+				catch(Throwable _) {
+					//
+				}
+			}
+			return false;
+		}
+
+		@Override
+		public final boolean containsAll(Collection<?> c) {
+			boolean ok;
+			expurgeNow();
+			for(Object o : c) {
+				ok = false;
+				if (o instanceof Entry<?,?>) {
+					try {
+						ok = AbstractWeakSoftValueMap.this.map.containsKey(((Entry<?,?>)o).getKey());
+					}
+					catch(Throwable _) {
+						//
+					}
+				}
+				if (!ok) return false;
+			}
+			return true;
+		}
+
+		@Override
+		public final boolean isEmpty() {
+			expurgeNow();
+			return AbstractWeakSoftValueMap.this.map.isEmpty();
+		}
+
+		@Override
+		public final Iterator<java.util.Map.Entry<K, V>> iterator() {
+			return new InnerIterator();
+		}
+
+		@Override
+		public final boolean remove(Object o) {
+			if (o instanceof Entry<?,?>) {
+				try {
+					return AbstractWeakSoftValueMap.this.map.remove(((Entry<?,?>)o).getKey())!=null;
+				}
+				catch(Throwable _) {
+					//
+				}
+			}
+			return false;
+		}
+
+		@Override
+		public final boolean removeAll(Collection<?> c) {
+			boolean ok = true;
+			for(Object o : c) {
+				ok = remove(o) && ok;
+			}
+			return ok;
+		}
+
+		@Override
+		public final boolean retainAll(Collection<?> c) {
+			expurgeNow();
+			Collection<K> keys = AbstractWeakSoftValueMap.this.map.keySet();
+			Iterator<K> iterator = keys.iterator();
+			K key;
+			boolean changed = false;
+			while (iterator.hasNext()) {
+				key = iterator.next();
+				if (!c.contains(key)) {
+					iterator.remove();
+					changed = true;
+				}
+			}
+			return changed;
+		}
+
+		@Override
+		public final int size() {
+			expurgeNow();
+			return AbstractWeakSoftValueMap.this.map.size();
+		}
+
+		@Override
+		public final Object[] toArray() {
+			expurgeNow();
+			Object[] tab = new Object[AbstractWeakSoftValueMap.this.map.size()];
+			return toArray(tab);
+		}
+
+		@SuppressWarnings("unchecked")
+		@Override
+		public final <T> T[] toArray(T[] a) {
+			Entry[] tab;
+			expurgeNow();
+			int count = AbstractWeakSoftValueMap.this.map.size();
+			if (a==null || a.length<count) {
+				tab = new Entry[count];
+			}
+			else {
+				tab = (Entry[])a;
+			}
+
+			Iterator<java.util.Map.Entry<K, V>> iterator = iterator();
+			int i = 0;
+			while (i<tab.length && iterator.hasNext()) {
+				tab[i] = iterator.next();
+			}
+			
+			return (T[])tab;
+		}
+		
+	}
+	
+	/**
+	 * @author St&eacute;phane GALLAND &lt;galland@xxxxxxxxxxx&gt;
+	 * @version $Name:  $ $Revision: 1.1 $ $Date: 2007-02-20 08:52:37 $
+	 */
+	private class InnerIterator implements Iterator<Entry<K,V>> {
+
+		private final Iterator<Entry<K,WeakSoftValue<K,V>>> originalIterator;
+		private Entry<K,V> next;
+		
+		@SuppressWarnings("synthetic-access")
+		public InnerIterator() {
+			this.originalIterator = AbstractWeakSoftValueMap.this.map.entrySet().iterator();
+			this.next = searchNext();
+		}
+		
+		private Entry<K,V> searchNext() {
+			Entry<K,WeakSoftValue<K,V>> originalNext;
+			WeakSoftValue<K,V> wValue;
+			Entry<K,V> cnext = null;
+			while (cnext==null && this.originalIterator.hasNext()) {
+				originalNext = this.originalIterator.next();
+				if (originalNext!=null) {
+					wValue = originalNext.getValue();
+					if (wValue!=null) {
+						cnext = new InnerEntry(wValue.getValue(), originalNext);
+					}
+				}
+			}
+			return cnext;
+		}
+		
+		@Override
+		public boolean hasNext() {
+			return this.next!=null;
+		}
+
+		@Override
+		public java.util.Map.Entry<K, V> next() {
+			Entry<K,V> cnext = this.next;
+			this.next = searchNext();
+			return cnext;
+		}
+
+		@Override
+		public void remove() {
+			this.originalIterator.remove();
+		}
+		
+	}
+
+	/**
+	 * @author St&eacute;phane GALLAND &lt;galland@xxxxxxxxxxx&gt;
+	 * @version $Name:  $ $Revision: 1.1 $ $Date: 2007-02-20 08:52:37 $
+	 */
+	private class InnerEntry implements Entry<K,V> {
+
+		private final Entry<K,WeakSoftValue<K,V>> original;
+		private V value;
+		
+		public InnerEntry(V v, Entry<K,WeakSoftValue<K,V>> o) {
+			this.original = o;
+			this.value = v;
+		}
+		
+		@Override
+		public K getKey() {
+			return this.original.getKey();
+		}
+
+		@Override
+		public V getValue() {
+			return this.value;
+		}
+
+		@Override
+		public V setValue(V value) {
+			this.value = value;
+			return this.original.getValue().setValue(value);
+		}
+
+	}
+	
+}

Added: tags/afc-2.0/arakhneRefs/src/main/java/org/arakhne/util/ref/ComparableSoftReference.java
===================================================================
--- tags/afc-2.0/arakhneRefs/src/main/java/org/arakhne/util/ref/ComparableSoftReference.java	                        (rev 0)
+++ tags/afc-2.0/arakhneRefs/src/main/java/org/arakhne/util/ref/ComparableSoftReference.java	2010-01-21 08:29:52 UTC (rev 117)
@@ -0,0 +1,148 @@
+/* 
+ * $Id: ComparableSoftReference.java,v 1.1 2007-02-20 08:52:37 sgalland Exp $
+ * 
+ * Copyright (C) 2005-2009 St&eacute;phane GALLAND
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * This program is free software; you can redistribute it and/or modify
+ */
+
+package org.arakhne.util.ref;
+
+import java.lang.ref.Reference;
+import java.lang.ref.ReferenceQueue;
+import java.lang.ref.SoftReference;
+
+/**
+ * This class is a WeakReference that allows to be
+ * compared on its pointed value.
+ * 
+ * @param <T> is the type of the referenced object. 
+ * @author St&eacute;phane GALLAND &lt;galland@xxxxxxxxxxx&gt;
+ * @version $Name:  $ $Revision: 1.1 $ $Date: 2007-02-20 08:52:37 $
+ */
+public class ComparableSoftReference<T> extends SoftReference<T> implements Comparable<Object> {
+
+	/**
+	 * @param referent is the referenced object.
+	 */
+	public ComparableSoftReference(T referent) {
+		super(referent);
+	}
+	
+	/**
+	 * @param referent is the referenced object.
+	 * @param queue is the object that will be notified of the memory released for the referenced object.
+	 */
+	public ComparableSoftReference(T referent, ReferenceQueue<? super T> queue) {
+		super(referent,queue);
+	}
+
+	/** {@inheritDoc}
+	 */
+	@Override
+	public boolean equals(Object o) {
+		return compareTo(o)==0;
+	}
+
+	/** {@inheritDoc}
+	 */
+	@Override
+	public int hashCode() {
+		T cur = get();
+		return cur==null ? 0 : cur.hashCode();
+	}
+
+	/** Compare this reference to the specified object
+	 * based on the {@link Object#hashCode()} if the
+	 * references are not equals.
+	 * 
+	 * @param o {@inheritDoc}
+	 * @return {@inheritDoc}
+	 */
+	@SuppressWarnings("unchecked")
+	public int compareTo(Object o) {
+		Object oth = (o instanceof Reference) ? ((Reference<?>)o).get() : o;
+		T cur = get();
+		
+		if (oth==null && cur==null) return 0;
+		if (cur==null) return 1;
+		if (oth==null) return -1;
+			
+		if (cur instanceof Comparable) {
+			try {
+				return ((Comparable<Object>)cur).compareTo(oth);
+			}
+			catch(Throwable _) {
+				//
+			}
+		}
+
+		if (oth instanceof Comparable) {
+			try {
+				return -((Comparable<Object>)oth).compareTo(cur);
+			}
+			catch(Throwable _) {
+				//
+			}
+		}
+
+		return oth.hashCode() - cur.hashCode();			
+	}
+
+	/** Compare this reference to the specified object
+	 * based on the {@link Object#hashCode()} if the
+	 * references are not equals.
+	 * 
+     * @param   o the object to be compared.
+     * @return  a negative integer, zero, or a positive integer as this object
+     *		is less than, equal to, or greater than the specified object.
+     * @deprecated call {@link #compareTo(Object)} insteed
+	 */
+	@Deprecated
+	public int compareToObject(T o) {
+		return compareTo(o);
+	}
+
+	/** Compare this reference to the specified object
+	 * based on the {@link Object#hashCode()} if the
+	 * references are not equals.
+	 * 
+     * @param   o the object to be compared.
+     * @return  a negative integer, zero, or a positive integer as this object
+     *		is less than, equal to, or greater than the specified object.
+     * @deprecated call {@link #compareTo(Object)} insteed
+	 */
+	@Deprecated
+	public int compareToRef(Reference<T> o) {
+		return compareTo(o);
+	}
+
+	/** {@inheritDoc}
+	 * 
+	 * @return {@inheritDoc}
+	 */
+	@Override
+	public String toString() {
+		StringBuffer buffer = new StringBuffer();
+		buffer.append('{');
+		T obj = get();
+		if (obj==null) buffer.append("#null#"); //$NON-NLS-1$
+		else buffer.append(obj.toString());
+		buffer.append('}');
+		return buffer.toString();
+	}
+
+}

Added: tags/afc-2.0/arakhneRefs/src/main/java/org/arakhne/util/ref/ComparableWeakReference.java
===================================================================
--- tags/afc-2.0/arakhneRefs/src/main/java/org/arakhne/util/ref/ComparableWeakReference.java	                        (rev 0)
+++ tags/afc-2.0/arakhneRefs/src/main/java/org/arakhne/util/ref/ComparableWeakReference.java	2010-01-21 08:29:52 UTC (rev 117)
@@ -0,0 +1,148 @@
+/* 
+ * $Id: ComparableWeakReference.java,v 1.1 2007-02-20 08:52:37 sgalland Exp $
+ * 
+ * Copyright (C) 2005-2009 St&eacute;phane GALLAND
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * This program is free software; you can redistribute it and/or modify
+ */
+
+package org.arakhne.util.ref;
+
+import java.lang.ref.Reference;
+import java.lang.ref.ReferenceQueue;
+import java.lang.ref.WeakReference;
+
+/**
+ * This class is a WeakReference that allows to be
+ * compared on its pointed value.
+ * 
+ * @param <T> is the type of the referenced object.
+ * @author St&eacute;phane GALLAND &lt;galland@xxxxxxxxxxx&gt;
+ * @version $Name:  $ $Revision: 1.1 $ $Date: 2007-02-20 08:52:37 $
+ */
+public class ComparableWeakReference<T> extends WeakReference<T> implements Comparable<Object> {
+
+	/**
+	 * @param referent is the referenced object.
+	 */
+	public ComparableWeakReference(T referent) {
+		super(referent);
+	}
+	
+	/**
+	 * @param referent is the referenced object.
+	 * @param queue is the object that will be notified of the memory released for the referenced object.
+	 */
+	public ComparableWeakReference(T referent, ReferenceQueue<? super T> queue) {
+		super(referent,queue);
+	}
+
+	/** {@inheritDoc}
+	 */
+	@Override
+	public boolean equals(Object o) {
+		return compareTo(o)==0;
+	}
+
+	/** {@inheritDoc}
+	 */
+	@Override
+	public int hashCode() {
+		T cur = get();
+		return cur==null ? 0 : cur.hashCode();
+	}
+
+	/** Compare this reference to the specified object
+	 * based on the {@link Object#hashCode()} if the
+	 * references are not equals.
+	 * 
+	 * @param o {@inheritDoc}
+	 * @return {@inheritDoc}
+	 */
+	@SuppressWarnings("unchecked")
+	public int compareTo(Object o) {
+		Object oth = (o instanceof Reference) ? ((Reference<?>)o).get() : o;
+		T cur = get();
+		
+		if (oth==null && cur==null) return 0;
+		if (cur==null) return 1;
+		if (oth==null) return -1;
+			
+		if (cur instanceof Comparable) {
+			try {
+				return ((Comparable<Object>)cur).compareTo(oth);
+			}
+			catch(Throwable _) {
+				//
+			}
+		}
+
+		if (oth instanceof Comparable) {
+			try {
+				return -((Comparable<Object>)oth).compareTo(cur);
+			}
+			catch(Throwable _) {
+				//
+			}
+		}
+
+		return oth.hashCode() - cur.hashCode();			
+	}
+
+	/** Compare this reference to the specified object
+	 * based on the {@link Object#hashCode()} if the
+	 * references are not equals.
+	 * 
+     * @param   o the object to be compared.
+     * @return  a negative integer, zero, or a positive integer as this object
+     *		is less than, equal to, or greater than the specified object.
+     * @deprecated call {@link #compareTo(Object)} insteed
+	 */
+	@Deprecated
+	public int compareToObject(T o) {
+		return compareTo(o);
+	}
+
+	/** Compare this reference to the specified object
+	 * based on the {@link Object#hashCode()} if the
+	 * references are not equals.
+	 * 
+     * @param   o the object to be compared.
+     * @return  a negative integer, zero, or a positive integer as this object
+     *		is less than, equal to, or greater than the specified object.
+     * @deprecated call {@link #compareTo(Object)} insteed
+	 */
+	@Deprecated
+	public int compareToRef(Reference<T> o) {
+		return compareTo(o);
+	}
+
+	/** {@inheritDoc}
+	 * 
+	 * @return {@inheritDoc}
+	 */
+	@Override
+	public String toString() {
+		StringBuffer buffer = new StringBuffer();
+		buffer.append('{');
+		T obj = get();
+		if (obj==null) buffer.append("#null#"); //$NON-NLS-1$
+		else buffer.append(obj.toString());
+		buffer.append('}');
+		return buffer.toString();
+	}
+
+}

Added: tags/afc-2.0/arakhneRefs/src/main/java/org/arakhne/util/ref/ReferenceListener.java
===================================================================
--- tags/afc-2.0/arakhneRefs/src/main/java/org/arakhne/util/ref/ReferenceListener.java	                        (rev 0)
+++ tags/afc-2.0/arakhneRefs/src/main/java/org/arakhne/util/ref/ReferenceListener.java	2010-01-21 08:29:52 UTC (rev 117)
@@ -0,0 +1,43 @@
+/* 
+ * $Id$
+ * 
+ * Copyright (C) 2009 St&eacute;phane GALLAND
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * This program is free software; you can redistribute it and/or modify
+ */
+
+package org.arakhne.util.ref;
+
+import java.util.EventListener;
+
+/**
+ * Listener on the release of a reference.
+ *
+ * @author St&eacute;phane GALLAND &lt;galland@xxxxxxxxxxx&gt;
+ * @version $Name$ $Revision$ $Date$ 
+ */
+public interface ReferenceListener extends EventListener {
+
+	/** Invoked when at least one reference was released.
+	 * <p>
+	 * No reference is given to avoid strong referencing of the released objects
+	 * inside the listener's source code.
+	 * 
+	 * @param released is the count of released objects.
+	 */
+	public void referenceReleased(int released);
+	
+}

Added: tags/afc-2.0/arakhneRefs/src/main/java/org/arakhne/util/ref/SoftValueMap.java
===================================================================
--- tags/afc-2.0/arakhneRefs/src/main/java/org/arakhne/util/ref/SoftValueMap.java	                        (rev 0)
+++ tags/afc-2.0/arakhneRefs/src/main/java/org/arakhne/util/ref/SoftValueMap.java	2010-01-21 08:29:52 UTC (rev 117)
@@ -0,0 +1,226 @@
+/* 
+ * $Id: SoftValueMap.java,v 1.1 2007-02-20 08:52:37 sgalland Exp $
+ * 
+ * Copyright (C) 2005-2007 St&eacute;phane GALLAND
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * This program is free software; you can redistribute it and/or modify
+ */
+
+package org.arakhne.util.ref;
+
+import java.lang.ref.ReferenceQueue;
+import java.lang.ref.SoftReference;
+import java.util.Map;
+
+/**
+ * A <tt>Map</tt> implementation with <em>soft values</em>. An entry in a
+ * <tt>SoftValueMap</tt> will automatically be removed when its value is no
+ * longer in ordinary use or null.
+ * <p>
+ * This class was inspirated from <code>WeakHashMap</code>
+ * <p>
+ * This class has a special flag which permits to control the
+ * way how the released references are expurged: {@link #isDeeplyExpurge()},
+ * {@link #setDeeplyExpurge(boolean)}. If this flag is <code>true</code>,
+ * all the released references will be immediately removed from the map even
+ * if they are not enqueued by the virtual machine (see {@link #expurge()}.
+ * If this flag is <code>false</code>,
+ * only the enqueued references will be removed from the map
+ * (see {@link #expurgeQueuedReferences()}.
+ * <p>
+ * If this map does not use a "deep expurge" of the released references,
+ * it could contains <code>null</code> values that corresponds to
+ * values that are released by the garbage collector. If a "deep expurge"
+ * is used, all the values released by the garbage collector will be
+ * removed from the map.
+ * <p>
+ * "Deep expurge" consumes much more time that "No deep expurge". This is the
+ * reason why this feature is not activated by default.
+ * <p>
+ * The "deep expurge" feature was added to fix the uncoherent behavior
+ * of the garbage collector which seems to not always enqueued the 
+ * released values (sometimes the queue is empty even if a value was released).
+ *
+ * @param <K> is the type of the keys.
+ * @param <V> is the type of the values.
+ * @author St&eacute;phane GALLAND &lt;galland@xxxxxxxxxxx&gt;
+ * @version $Name:  $ $Revision: 1.1 $ $Date: 2007-02-20 08:52:37 $
+ */
+public class SoftValueMap<K,V> extends AbstractWeakSoftValueMap<K,V> {
+	
+    /**
+     * Constructs an empty <tt>HashMap</tt> with the specified initial
+     * capacity and load factor.
+     *
+     * @param  initialCapacity the initial capacity
+     * @param  loadFactor      the load factor
+     * @throws IllegalArgumentException if the initial capacity is negative
+     *         or the load factor is nonpositive
+     */
+    public SoftValueMap(int initialCapacity, float loadFactor) {
+        super(initialCapacity, loadFactor);
+    }
+
+    /**
+     * Constructs an empty <tt>HashMap</tt> with the specified initial
+     * capacity and the default load factor (0.75).
+     *
+     * @param  initialCapacity the initial capacity.
+     * @throws IllegalArgumentException if the initial capacity is negative.
+     */
+    public SoftValueMap(int initialCapacity) {
+    	super(initialCapacity);
+    }
+
+    /**
+     * Constructs an empty <tt>HashMap</tt> with the default initial capacity
+     * (16) and the default load factor (0.75).
+     */
+    public SoftValueMap() {
+    	super();
+    }
+
+    /**
+     * Constructs a new <tt>HashMap</tt> with the same mappings as the
+     * specified <tt>Map</tt>.  The <tt>HashMap</tt> is created with
+     * default load factor (0.75) and an initial capacity sufficient to
+     * hold the mappings in the specified <tt>Map</tt>.
+     *
+     * @param   m the map whose mappings are to be placed in this map
+     * @throws  NullPointerException if the specified map is null
+     */
+    public SoftValueMap(Map<? extends K, ? extends V> m) {
+        super(m);
+    }	
+
+	/** Create a storage object that permits to put the specified
+	 * elements inside this map.
+	 * 
+	 * @param k is the key associated to the value
+	 * @param v is the value
+	 * @param queue is the reference queue to use
+	 * @return the new storage object
+	 */
+	@Override
+	protected WeakSoftValue<K,V> makeValue(K k, V v, ReferenceQueue<V> queue) {
+		return new Value<K,V>(k, v, queue);
+	}
+
+	/**
+	 * @author St&eacute;phane GALLAND &lt;galland@xxxxxxxxxxx&gt;
+	 * @version $Name:  $ $Revision: 1.1 $ $Date: 2007-02-20 08:52:37 $
+	 */
+	private static class Value<K,V> extends SoftReference<V> implements WeakSoftValue<K,V> {
+		
+		private final K k;
+
+		/**
+		 * @param k is the key.
+		 * @param v is the value.
+		 * @param queue is the memory-release listener.
+		 */
+		Value(K k, V v, ReferenceQueue<V> queue) {
+			super(maskNull(v), queue);
+			this.k = k;
+		}
+		
+		/**
+		 * {@inheritDoc}
+		 * 
+		 * @return {@inheritDoc}
+		 */
+		@Override
+		public String toString() {
+			StringBuffer buffer = new StringBuffer();
+			buffer.append('{');
+			K key = getKey();
+			buffer.append(key==null ? null : key.toString());
+			buffer.append('=');
+			if (isEnqueued()) {
+				buffer.append("Q#"); //$NON-NLS-1$
+			}
+			else {
+				buffer.append("P#"); //$NON-NLS-1$
+			}
+			V v = getValue();
+			buffer.append((v==null ? null : v.toString()));
+			buffer.append('}');
+			return buffer.toString();
+		}
+		
+		/**
+		 * {@inheritDoc}
+		 * 
+		 * @return {@inheritDoc}
+		 */
+		public K getKey() {
+			return this.k;
+		}
+		
+		/**
+		 * {@inheritDoc}
+		 * 
+		 * @return {@inheritDoc}
+		 */
+		public V getValue() {
+			return unmaskNull(get());
+		}
+		
+		/**
+		 * {@inheritDoc}
+		 *
+		 * @param o {@inheritDoc}
+		 * @return {@inheritDoc}
+		 */
+		public V setValue(V o) {
+			throw new UnsupportedOperationException();
+		}
+
+		/**
+		 * {@inheritDoc}
+		 * 
+		 * @return {@inheritDoc}
+		 */
+		@Override
+		public int hashCode() { 
+			Object val = getValue();
+			return (getKey()==null   ? 0 : getKey().hashCode()) ^
+				   (val==null ? 0 : val.hashCode()); 
+		}
+		
+		/**
+		 * {@inheritDoc}
+		 *
+		 * @param o {@inheritDoc}
+		 * @return {@inheritDoc}
+		 */
+		@SuppressWarnings("unchecked")
+		@Override
+		public boolean equals(Object o) {
+			if (o instanceof Entry) {
+				Entry<K,V> e = (Entry<K,V>)o;
+				Object e1val = getValue();
+				Object e2val = e.getValue();
+				return  (getKey()==null ?
+						e.getKey()==null : getKey().equals(e.getKey()))  &&
+						(e1val==null ? e2val==null : e1val.equals(e2val));
+			}
+			return false;
+		}
+
+	}
+        
+}

Added: tags/afc-2.0/arakhneRefs/src/main/java/org/arakhne/util/ref/WeakArrayList.java
===================================================================
--- tags/afc-2.0/arakhneRefs/src/main/java/org/arakhne/util/ref/WeakArrayList.java	                        (rev 0)
+++ tags/afc-2.0/arakhneRefs/src/main/java/org/arakhne/util/ref/WeakArrayList.java	2010-01-21 08:29:52 UTC (rev 117)
@@ -0,0 +1,439 @@
+/* 
+ * $Id: WeakArrayList.java,v 1.1 2007-02-20 08:52:37 sgalland Exp $
+ * 
+ * Copyright (C) 2005-2009 St&eacute;phane GALLAND
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * This program is free software; you can redistribute it and/or modify
+ */
+
+package org.arakhne.util.ref;
+
+import java.lang.ref.Reference;
+import java.lang.ref.ReferenceQueue;
+import java.lang.ref.WeakReference;
+import java.util.AbstractList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.LinkedList;
+import java.util.List;
+
+/**
+ * A array-based <tt>List</tt> implementation with <em>weak keys</em>.
+ * An entry in a <tt>WeakArrayList</tt> will automatically be removed when
+ * it is no longer in ordinary use.
+ *
+ * <p> The behavior of the <tt>WeakArrayList</tt> class depends in part upon
+ * the actions of the garbage collector, so several familiar (though not
+ * required) <tt>List</tt> invariants do not hold for this class.  Because
+ * the garbage collector may discard values at any time, a
+ * <tt>WeakArrayList</tt> may behave as though an unknown thread is silently
+ * removing entries.  In particular, even if you synchronize on a
+ * <tt>WeakArrayList</tt> instance and invoke none of its mutator methods, it
+ * is possible for the <tt>size</tt> method to return smaller values over
+ * time, for the <tt>isEmpty</tt> method to return <tt>false</tt> and
+ * then <tt>true</tt>, for the <tt>contains</tt> method to return
+ * <tt>true</tt> and later <tt>false</tt> for a given value, for the
+ * <tt>get</tt> method to return a value for a given key but later return
+ * <tt>null</tt>, for the <tt>add</tt> method to return
+ * <tt>null</tt> and the <tt>remove</tt> method to return
+ * <tt>false</tt> for a value that previously appeared to be in the list.
+ * <p>
+ * This class has a special flag which permits to control the
+ * way how the released references are expurged: {@link #isDeeplyExpurge()},
+ * {@link #setDeeplyExpurge(boolean)}. If this flag is <code>true</code>,
+ * all the released references will be immediately removed from the map even
+ * if they are not enqueued by the virtual machine (see {@link #expurge()}.
+ * If this flag is <code>false</code>,
+ * only the enqueued references will be removed from the map
+ * (see {@link #expurgeQueuedReferences()}.
+ * <p>
+ * If this map does not use a "deep expurge" of the released references,
+ * it could contains <code>null</code> values that corresponds to
+ * values that are released by the garbage collector. If a "deep expurge"
+ * is used, all the values released by the garbage collector will be
+ * removed from the map.
+ * <p>
+ * "Deep expurge" consumes much more time that "No deep expurge". This is the
+ * reason why this feature is not activated by default.
+ * <p>
+ * The "deep expurge" feature was added to fix the uncoherent behavior
+ * of the garbage collector which seems to not always enqueued the 
+ * released values (sometimes the queue is empty even if a value was released).
+ *
+ * @param <T> is the type of the array's elements.
+ * @author St&eacute;phane GALLAND &lt;galland@xxxxxxxxxxx&gt;
+ * @version $Name:  $ $Revision: 1.1 $ $Date: 2007-02-20 08:52:37 $ 
+ */
+public class WeakArrayList<T> extends AbstractList<T> {
+
+	private static final long serialVersionUID = 2601162363164961860L;
+	
+	/** This value represents a null value given by the user.
+	 */
+	private static final Object NULL_VALUE = new Object();
+	
+	/** Replies the null value given by the user by the corresponding null object.
+	 */
+	@SuppressWarnings("unchecked")
+	private static <T> T maskNull(T value) {
+		return (value==null) ? (T)NULL_VALUE : value;
+	}
+
+	/** Replies the value given by the user.
+	 */
+	private static <T> T unmaskNull(T value) {
+		return (value==NULL_VALUE) ? null : value;
+	}
+
+	private final transient ReferenceQueue<T> queue = new ReferenceQueue<T>();
+	
+	private Object[] data;
+	
+	private int size;
+	
+	private boolean enquedElement = false;
+	
+	private List<ReferenceListener> listeners = null;
+	
+    /**
+     * Constructs an empty list with the specified initial capacity.
+     *
+     * @param   initialCapacity   the initial capacity of the list
+     * @exception IllegalArgumentException if the specified initial capacity
+     *            is negative
+     */
+    public WeakArrayList(int initialCapacity) {
+        if (initialCapacity < 0)
+            throw new IllegalArgumentException("Illegal Capacity: "+initialCapacity); //$NON-NLS-1$
+        this.data = new Object[initialCapacity];
+        this.size = 0;
+    }
+
+    /**
+     * Constructs an empty list with an initial capacity of ten.
+     */
+    public WeakArrayList() {
+    	this(10);
+    }
+    
+    /**
+     * Constructs a list containing the elements of the specified
+     * collection, in the order they are returned by the collection's
+     * iterator.
+     *
+     * @param c the collection whose elements are to be placed into this list
+     * @throws NullPointerException if the specified collection is null
+     */
+    public WeakArrayList(Collection<? extends T> c) {
+    	this.data = new Object[c.size()];
+    	this.size = this.data.length;
+    	int i=0;
+    	for (T t : c) {
+			this.data[i] = createRef(t);
+			i++;
+		}
+    }
+    
+	/**
+	 * {@inheritDoc}
+	 * 
+	 * @return {@inheritDoc}
+	 */
+    @Override
+	@SuppressWarnings("unchecked")
+	public String toString() {
+    	StringBuffer buffer = new StringBuffer();
+    	Reference<T> ref;
+    	T obj;
+    	for(int i=0; i<this.size; i++) {
+    		ref = (Reference<T>)this.data[i];
+    		if (this.data[i]==null) obj = null;
+    		else obj = ref.get();
+    		buffer.append('{');
+    		buffer.append(obj==null ? null : obj.toString());
+    		buffer.append('}');
+    	}
+    	return buffer.toString();
+    }
+	
+    /** Create and replies the reference for the specified object.
+     * 
+     * @param obj is the object on which a weak reference must be attached.
+     * @return the weak reference. 
+     */
+    private Reference<T> createRef(T obj) {
+    	return new WeakReference<T>(maskNull(obj), this.queue);
+    }
+    
+    /**
+     * Increases the capacity of this <tt>WeakArrayList</tt> instance, if
+     * necessary, to ensure that it can hold at least the number of elements
+     * specified by the minimum capacity argument.
+     *
+     * @param   minCapacity   the desired minimum capacity
+     */
+    public void ensureCapacity(int minCapacity) {
+		this.modCount++;
+		int oldCapacity = this.data.length;
+		if (minCapacity > oldCapacity) {
+			Object[] oldData = this.data;
+			int newCapacity = (oldCapacity * 3)/2 + 1;
+			if (newCapacity < minCapacity)
+				newCapacity = minCapacity;
+			// minCapacity is usually close to size, so this is a win:
+			this.data = Arrays.copyOf(oldData, newCapacity);
+		}
+    }
+
+    /**
+     * Trims the capacity of this <tt>WeakArrayList</tt> instance to be the
+     * list's current size.  An application can use this operation to minimize
+     * the storage of an <tt>WeakArrayList</tt> instance.
+     */
+    public void trimToSize() {
+    	this.modCount++;
+    	int oldCapacity = this.data.length;
+    	if (this.size < oldCapacity) {
+    		this.data = Arrays.copyOf(this.data, this.size);
+    	}
+    }
+    
+	/** Clean the references that was released.
+	 * <p>
+	 * Notifies the listeners if a reference was released.
+	 * 
+	 * @return the size
+     */
+	@SuppressWarnings("unchecked")
+	public int expurge() {
+        // clear out ref queue.
+		while (this.queue.poll()!=null) {
+			this.enquedElement = true;
+		}
+			
+		int j;
+
+		if (this.enquedElement) {
+			// Clear the table
+			Reference<? extends T> ref;
+			j=0;
+			for(int i=0; i<this.size; i++) {
+				ref = (Reference<T>)this.data[i];
+				if ((ref==null)||(ref.isEnqueued())||(ref.get()==null)) {
+					if (ref!=null) ref.clear();
+					this.data[i] = null;
+				}
+				else {
+					if (i!=j) {
+						this.data[j] = this.data[i];
+						this.data[i] = null;
+					}
+					j++;
+				}
+			}
+			this.enquedElement = false;
+		}
+		else {
+			j = this.size;
+		}
+				
+        // Allocation of array may have caused GC, which may have caused
+        // additional entries to go stale.  Removing these entries from the
+        // reference queue will make them eligible for reclamation.
+		while (this.queue.poll()!=null) {
+			this.enquedElement = true;
+		}
+
+		int oldSize = this.size;
+		this.size = j;
+		
+		if (j<oldSize) {
+			fireReferenceRelease(oldSize - j);
+		}
+
+		return this.size;
+	}
+    
+    /** Verify if the specified index is inside the array.
+     * 
+     * @param index is the index totest
+     * @param allowLast indicates if the last elements is assumed to be valid or not.
+     */
+    protected void assertRange(int index, boolean allowLast) {
+    	int csize = expurge();
+    	if (index<0)
+    		throw new IndexOutOfBoundsException("invalid negative value: "+Integer.toString(index)); //$NON-NLS-1$
+    	if ((allowLast)&&(index>csize))
+    		throw new IndexOutOfBoundsException("index>"+csize+": "+Integer.toString(index)); //$NON-NLS-1$ //$NON-NLS-2$
+    	if ((!allowLast)&&(index>=csize))
+    		throw new IndexOutOfBoundsException("index>="+csize+": "+Integer.toString(index)); //$NON-NLS-1$ //$NON-NLS-2$
+    }
+
+	/** {@inheritDoc}
+	 */
+	@Override
+	public int size() {
+		return expurge();
+	}
+
+	/** {@inheritDoc}
+	 */
+	@SuppressWarnings("unchecked")
+	@Override
+	public T get(int index) {
+		T value;
+		do {
+			assertRange(index,false);
+			value = ((Reference<T>)this.data[index]).get();
+		}
+		while (value==null);
+		return unmaskNull(value);
+	}
+
+    /**
+     * {@inheritDoc}
+     */
+    @SuppressWarnings("unchecked")
+	@Override
+	public T set(int index, T element) {
+		T oldValue;
+		Reference<T> ref;
+		do {
+			assertRange(index, false);
+			ref = (Reference<T>)this.data[index];
+			oldValue = ref.get();
+		}
+		while (oldValue==null);
+		ref.clear();
+		this.data[index] = createRef(element);
+		this.modCount++;
+		return unmaskNull(oldValue);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+	public void add(int index, T element) {
+		assertRange(index,true);
+		ensureCapacity(this.size+1);
+		System.arraycopy(this.data, index, this.data, index+1, this.size-index);
+		this.data[index] = createRef(element);
+		this.size++;
+		this.modCount++;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @SuppressWarnings("unchecked")
+	@Override
+	public T remove(int index) {
+		T oldValue;
+		Reference<T> ref;
+		do {
+			assertRange(index, false);
+			ref = (Reference<T>)this.data[index];
+			oldValue = ref.get();
+		}
+		while (oldValue==null);
+		ref.clear();
+		System.arraycopy(this.data, index+1, this.data, index, this.size-index-1);
+		this.data[this.size-1] = null;
+		this.size--;
+		this.modCount++;
+		return unmaskNull(oldValue);
+    }
+    
+    /** Add listener on reference's release.
+     * 
+     * @param listener
+     */
+    public void addReferenceListener(ReferenceListener listener) {
+    	if (this.listeners==null) {
+    		this.listeners = new LinkedList<ReferenceListener>();
+    	}
+		List<ReferenceListener> list = this.listeners;
+    	synchronized(list) {
+    		list.add(listener);
+    	}
+    }
+
+    /** Remove listener on reference's release.
+     * 
+     * @param listener
+     */
+    public void removeReferenceListener(ReferenceListener listener) {
+		List<ReferenceListener> list = this.listeners;
+    	if (list!=null) {
+        	synchronized(list) {
+        		list.remove(listener);
+            	if (list.isEmpty()) this.listeners = null;
+        	}
+    	}
+    }
+    
+    /**
+     * Fire the reference release event.
+     * 
+     * @param released is the count of released objects.
+     */
+    protected void fireReferenceRelease(int released) {
+		List<ReferenceListener> list = this.listeners;
+    	if (list!=null && !list.isEmpty()) {
+    		for(ReferenceListener listener : list) {
+    			listener.referenceReleased(released);
+    		}
+    	}
+    }
+    
+	/** Replies if this map expurge all the released references
+	 * even if they are not enqueued by the virtual machine
+	 * 
+	 * @return <code>true</code>
+	 * @deprecated Always returns <code>true</code>, do not use!
+	 */
+    @Deprecated
+	public boolean isDeeplyExpurge() {
+		return true;
+	}
+	
+	/** Set if this map expurge all the released references
+	 * even if they are not enqueued by the virtual machine
+	 * 
+	 * @param deeplyExpurge must be <code>true</code> to
+	 * expurge all the released values, otherwise <code>false</code>
+	 * to expurge only the enqueued values.
+	 * @return the old value of this flag
+	 * @deprecated Do nothing, do not use!
+	 */
+    @Deprecated
+	public boolean setDeeplyExpurge(boolean deeplyExpurge) {
+		throw new UnsupportedOperationException();
+	}
+
+    /** Clean the references that was marked as released inside
+     * the queue.
+     * 
+     * @return the size 
+	 * @deprecated Do nothing, do not use!
+     */
+    @Deprecated
+	public int expurgeQueuedReferences() {
+		throw new UnsupportedOperationException();
+	}
+	
+}

Added: tags/afc-2.0/arakhneRefs/src/main/java/org/arakhne/util/ref/WeakValueMap.java
===================================================================
--- tags/afc-2.0/arakhneRefs/src/main/java/org/arakhne/util/ref/WeakValueMap.java	                        (rev 0)
+++ tags/afc-2.0/arakhneRefs/src/main/java/org/arakhne/util/ref/WeakValueMap.java	2010-01-21 08:29:52 UTC (rev 117)
@@ -0,0 +1,227 @@
+/* 
+ * $Id: WeakValueMap.java,v 1.1 2007-02-20 08:52:37 sgalland Exp $
+ * 
+ * Copyright (C) 2005-2007 St&eacute;phane GALLAND
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * This program is free software; you can redistribute it and/or modify
+ */
+
+package org.arakhne.util.ref;
+
+import java.lang.ref.ReferenceQueue;
+import java.lang.ref.WeakReference;
+import java.util.Map;
+import java.util.WeakHashMap;
+
+/**
+ * A <tt>Map</tt> implementation with <em>weak values</em>. An entry in a
+ * <tt>WeakValueMap</tt> will automatically be removed when its value is no
+ * longer in ordinary use or null.
+ * <p>
+ * This class was inspirated from {@link WeakHashMap}
+ * <p>
+ * This class has a special flag which permits to control the
+ * way how the released references are expurged: {@link #isDeeplyExpurge()},
+ * {@link #setDeeplyExpurge(boolean)}. If this flag is <code>true</code>,
+ * all the released references will be immediately removed from the map even
+ * if they are not enqueued by the virtual machine (see {@link #expurge()}.
+ * If this flag is <code>false</code>,
+ * only the enqueued references will be removed from the map
+ * (see {@link #expurgeQueuedReferences()}.
+ * <p>
+ * If this map does not use a "deep expurge" of the released references,
+ * it could contains <code>null</code> values that corresponds to
+ * values that are released by the garbage collector. If a "deep expurge"
+ * is used, all the values released by the garbage collector will be
+ * removed from the map.
+ * <p>
+ * "Deep expurge" consumes much more time that "No deep expurge". This is the
+ * reason why this feature is not activated by default.
+ * <p>
+ * The "deep expurge" feature was added to fix the uncoherent behavior
+ * of the garbage collector which seems to not always enqueued the 
+ * released values (sometimes the queue is empty even if a value was released).
+ *
+ * @param <K> is the type of the keys.
+ * @param <V> is the type of the values.
+ * @author St&eacute;phane GALLAND &lt;galland@xxxxxxxxxxx&gt;
+ * @version $Name:  $ $Revision: 1.1 $ $Date: 2007-02-20 08:52:37 $
+ */
+public class WeakValueMap<K,V> extends AbstractWeakSoftValueMap<K,V> {
+	
+    /**
+     * Constructs an empty <tt>HashMap</tt> with the specified initial
+     * capacity and load factor.
+     *
+     * @param  initialCapacity the initial capacity
+     * @param  loadFactor      the load factor
+     * @throws IllegalArgumentException if the initial capacity is negative
+     *         or the load factor is nonpositive
+     */
+    public WeakValueMap(int initialCapacity, float loadFactor) {
+        super(initialCapacity, loadFactor);
+    }
+
+    /**
+     * Constructs an empty <tt>HashMap</tt> with the specified initial
+     * capacity and the default load factor (0.75).
+     *
+     * @param  initialCapacity the initial capacity.
+     * @throws IllegalArgumentException if the initial capacity is negative.
+     */
+    public WeakValueMap(int initialCapacity) {
+    	super(initialCapacity);
+    }
+
+    /**
+     * Constructs an empty <tt>HashMap</tt> with the default initial capacity
+     * (16) and the default load factor (0.75).
+     */
+    public WeakValueMap() {
+    	super();
+    }
+
+    /**
+     * Constructs a new <tt>HashMap</tt> with the same mappings as the
+     * specified <tt>Map</tt>.  The <tt>HashMap</tt> is created with
+     * default load factor (0.75) and an initial capacity sufficient to
+     * hold the mappings in the specified <tt>Map</tt>.
+     *
+     * @param   m the map whose mappings are to be placed in this map
+     * @throws  NullPointerException if the specified map is null
+     */
+    public WeakValueMap(Map<? extends K, ? extends V> m) {
+        super(m);
+    }	
+
+	/** Create a storage object that permits to put the specified
+	 * elements inside this map.
+	 * 
+	 * @param k is the key associated to the value
+	 * @param v is the value
+	 * @param queue is the reference queue to use
+	 * @return the new storage object
+	 */
+	@Override
+	protected WeakSoftValue<K,V> makeValue(K k, V v, ReferenceQueue<V> queue) {
+		return new Value<K,V>(k, v, queue);
+	}
+
+	/**
+	 * @author St&eacute;phane GALLAND &lt;galland@xxxxxxxxxxx&gt;
+	 * @version $Name:  $ $Revision: 1.1 $ $Date: 2007-02-20 08:52:37 $
+	 */
+	private static class Value<K,V> extends WeakReference<V> implements WeakSoftValue<K,V> {
+		
+		private final K k;
+
+		/**
+		 * @param k is the key.
+		 * @param v is the value.
+		 * @param queue is the memory-release listener.
+		 */
+		Value(K k, V v, ReferenceQueue<V> queue) {
+			super(maskNull(v), queue);
+			this.k = k;
+		}
+		
+		/**
+		 * {@inheritDoc}
+		 * 
+		 * @return {@inheritDoc}
+		 */
+		@Override
+		public String toString() {
+			StringBuffer buffer = new StringBuffer();
+			buffer.append('{');
+			K key = getKey();
+			buffer.append(key==null ? null : key.toString());
+			buffer.append('=');
+			if (isEnqueued()) {
+				buffer.append("Q#"); //$NON-NLS-1$
+			}
+			else {
+				buffer.append("P#"); //$NON-NLS-1$
+			}
+			V v = getValue();
+			buffer.append((v==null ? null : v.toString()));
+			buffer.append('}');
+			return buffer.toString();
+		}
+		
+		/**
+		 * {@inheritDoc}
+		 * 
+		 * @return {@inheritDoc}
+		 */
+		public K getKey() {
+			return this.k;
+		}
+		
+		/**
+		 * {@inheritDoc}
+		 * 
+		 * @return {@inheritDoc}
+		 */
+		public V getValue() {
+			return unmaskNull(get());
+		}
+		
+		/**
+		 * {@inheritDoc}
+		 *
+		 * @param o {@inheritDoc}
+		 * @return {@inheritDoc}
+		 */
+		public V setValue(V o) {
+			throw new UnsupportedOperationException();
+		}
+
+		/**
+		 * {@inheritDoc}
+		 * 
+		 * @return {@inheritDoc}
+		 */
+		@Override
+		public int hashCode() { 
+			Object val = getValue();
+			return (getKey()==null   ? 0 : getKey().hashCode()) ^
+				   (val==null ? 0 : val.hashCode()); 
+		}
+		
+		/**
+		 * {@inheritDoc}
+		 *
+		 * @param o {@inheritDoc}
+		 * @return {@inheritDoc}
+		 */
+		@SuppressWarnings("unchecked")
+		@Override
+		public boolean equals(Object o) {
+			if (o instanceof Entry) {
+				Entry<K,V> e = (Entry<K,V>)o;
+				Object e1val = getValue();
+				Object e2val = e.getValue();
+				return  (getKey()==null ?
+						e.getKey()==null : getKey().equals(e.getKey()))  &&
+						(e1val==null ? e2val==null : e1val.equals(e2val));
+			}
+			return false;
+		}
+
+	}
+        
+}

Added: tags/afc-2.0/arakhneRefs/src/main/resources/AUTHORS
===================================================================
--- tags/afc-2.0/arakhneRefs/src/main/resources/AUTHORS	                        (rev 0)
+++ tags/afc-2.0/arakhneRefs/src/main/resources/AUTHORS	2010-01-21 08:29:52 UTC (rev 117)
@@ -0,0 +1,2 @@
+Stephane GALLAND <galland@xxxxxxxxxxx>
+Nicolas GAUD <gaud@xxxxxxxxxxx>

Added: tags/afc-2.0/arakhneRefs/src/main/resources/COPYING
===================================================================
--- tags/afc-2.0/arakhneRefs/src/main/resources/COPYING	                        (rev 0)
+++ tags/afc-2.0/arakhneRefs/src/main/resources/COPYING	2010-01-21 08:29:52 UTC (rev 117)
@@ -0,0 +1,165 @@
+		   GNU LESSER GENERAL PUBLIC LICENSE
+                       Version 3, 29 June 2007
+
+ Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+
+  This version of the GNU Lesser General Public License incorporates
+the terms and conditions of version 3 of the GNU General Public
+License, supplemented by the additional permissions listed below.
+
+  0. Additional Definitions. 
+
+  As used herein, "this License" refers to version 3 of the GNU Lesser
+General Public License, and the "GNU GPL" refers to version 3 of the GNU
+General Public License.
+
+  "The Library" refers to a covered work governed by this License,
+other than an Application or a Combined Work as defined below.
+
+  An "Application" is any work that makes use of an interface provided
+by the Library, but which is not otherwise based on the Library.
+Defining a subclass of a class defined by the Library is deemed a mode
+of using an interface provided by the Library.
+
+  A "Combined Work" is a work produced by combining or linking an
+Application with the Library.  The particular version of the Library
+with which the Combined Work was made is also called the "Linked
+Version".
+
+  The "Minimal Corresponding Source" for a Combined Work means the
+Corresponding Source for the Combined Work, excluding any source code
+for portions of the Combined Work that, considered in isolation, are
+based on the Application, and not on the Linked Version.
+
+  The "Corresponding Application Code" for a Combined Work means the
+object code and/or source code for the Application, including any data
+and utility programs needed for reproducing the Combined Work from the
+Application, but excluding the System Libraries of the Combined Work.
+
+  1. Exception to Section 3 of the GNU GPL.
+
+  You may convey a covered work under sections 3 and 4 of this License
+without being bound by section 3 of the GNU GPL.
+
+  2. Conveying Modified Versions.
+
+  If you modify a copy of the Library, and, in your modifications, a
+facility refers to a function or data to be supplied by an Application
+that uses the facility (other than as an argument passed when the
+facility is invoked), then you may convey a copy of the modified
+version:
+
+   a) under this License, provided that you make a good faith effort to
+   ensure that, in the event an Application does not supply the
+   function or data, the facility still operates, and performs
+   whatever part of its purpose remains meaningful, or
+
+   b) under the GNU GPL, with none of the additional permissions of
+   this License applicable to that copy.
+
+  3. Object Code Incorporating Material from Library Header Files.
+
+  The object code form of an Application may incorporate material from
+a header file that is part of the Library.  You may convey such object
+code under terms of your choice, provided that, if the incorporated
+material is not limited to numerical parameters, data structure
+layouts and accessors, or small macros, inline functions and templates
+(ten or fewer lines in length), you do both of the following:
+
+   a) Give prominent notice with each copy of the object code that the
+   Library is used in it and that the Library and its use are
+   covered by this License.
+
+   b) Accompany the object code with a copy of the GNU GPL and this license
+   document.
+
+  4. Combined Works.
+
+  You may convey a Combined Work under terms of your choice that,
+taken together, effectively do not restrict modification of the
+portions of the Library contained in the Combined Work and reverse
+engineering for debugging such modifications, if you also do each of
+the following:
+
+   a) Give prominent notice with each copy of the Combined Work that
+   the Library is used in it and that the Library and its use are
+   covered by this License.
+
+   b) Accompany the Combined Work with a copy of the GNU GPL and this license
+   document.
+
+   c) For a Combined Work that displays copyright notices during
+   execution, include the copyright notice for the Library among
+   these notices, as well as a reference directing the user to the
+   copies of the GNU GPL and this license document.
+
+   d) Do one of the following:
+
+       0) Convey the Minimal Corresponding Source under the terms of this
+       License, and the Corresponding Application Code in a form
+       suitable for, and under terms that permit, the user to
+       recombine or relink the Application with a modified version of
+       the Linked Version to produce a modified Combined Work, in the
+       manner specified by section 6 of the GNU GPL for conveying
+       Corresponding Source.
+
+       1) Use a suitable shared library mechanism for linking with the
+       Library.  A suitable mechanism is one that (a) uses at run time
+       a copy of the Library already present on the user's computer
+       system, and (b) will operate properly with a modified version
+       of the Library that is interface-compatible with the Linked
+       Version. 
+
+   e) Provide Installation Information, but only if you would otherwise
+   be required to provide such information under section 6 of the
+   GNU GPL, and only to the extent that such information is
+   necessary to install and execute a modified version of the
+   Combined Work produced by recombining or relinking the
+   Application with a modified version of the Linked Version. (If
+   you use option 4d0, the Installation Information must accompany
+   the Minimal Corresponding Source and Corresponding Application
+   Code. If you use option 4d1, you must provide the Installation
+   Information in the manner specified by section 6 of the GNU GPL
+   for conveying Corresponding Source.)
+
+  5. Combined Libraries.
+
+  You may place library facilities that are a work based on the
+Library side by side in a single library together with other library
+facilities that are not Applications and are not covered by this
+License, and convey such a combined library under terms of your
+choice, if you do both of the following:
+
+   a) Accompany the combined library with a copy of the same work based
+   on the Library, uncombined with any other library facilities,
+   conveyed under the terms of this License.
+
+   b) Give prominent notice with the combined library that part of it
+   is a work based on the Library, and explaining where to find the
+   accompanying uncombined form of the same work.
+
+  6. Revised Versions of the GNU Lesser General Public License.
+
+  The Free Software Foundation may publish revised and/or new versions
+of the GNU Lesser General Public License from time to time. Such new
+versions will be similar in spirit to the present version, but may
+differ in detail to address new problems or concerns.
+
+  Each version is given a distinguishing version number. If the
+Library as you received it specifies that a certain numbered version
+of the GNU Lesser General Public License "or any later version"
+applies to it, you have the option of following the terms and
+conditions either of that published version or of any later version
+published by the Free Software Foundation. If the Library as you
+received it does not specify a version number of the GNU Lesser
+General Public License, you may choose any version of the GNU Lesser
+General Public License ever published by the Free Software Foundation.
+
+  If the Library as you received it specifies that a proxy can decide
+whether future versions of the GNU Lesser General Public License shall
+apply, that proxy's public statement of acceptance of any version is
+permanent authorization for you to choose that version for the
+Library.

Added: tags/afc-2.0/arakhneRefs/src/main/resources/Changelog
===================================================================
--- tags/afc-2.0/arakhneRefs/src/main/resources/Changelog	                        (rev 0)
+++ tags/afc-2.0/arakhneRefs/src/main/resources/Changelog	2010-01-21 08:29:52 UTC (rev 117)
@@ -0,0 +1,49 @@
+arakhneRefs-5.1
+
+  * Bug fix: the Comparable weak/soft references throw ClassCastException when the 
+    object passed to compareTo() is not castable to the generic T.
+
+ -- Stephane GALLAND <galland@xxxxxxxxxxx> 2009-02-20
+
+
+arakhneRefs-5.0
+
+  * Reimplement the AbstractWeakSoftValueMap to avoid execeptions.
+
+ -- Stephane GALLAND <galland@xxxxxxxxxxx> 2009-02-03
+
+
+arakhneRefs-4.1
+
+  * Bug fix: avoid IllegalStateException from internal HashMap.
+
+ -- Stephane GALLAND <galland@xxxxxxxxxxx> 2009-02-03
+
+
+arakhneRefs-4.0
+
+  * Bug fix: avoid ConcurrentModificationException on SoftValueMap and WeakValueMap.
+  * Put the common code from SoftValueMap and WeakValueMap into a shared abstract class.
+
+ -- Stephane GALLAND <galland@xxxxxxxxxxx> 2009-02-02
+
+
+arakhneRefs-3.0
+
+  * Add the class SoftValueMap.
+
+ -- Stephane GALLAND <galland@xxxxxxxxxxx> 2008-02-18
+
+
+arakhneRefs-2.0
+
+  * Bug fixes inside the weak data structures.
+
+ -- Stephane GALLAND <galland@xxxxxxxxxxx> 2007-12-31
+
+
+arakhneLogger-1.0
+
+  * First public release.
+
+ -- Stephane GALLAND <galland@xxxxxxxxxxx> 2007-01-01

Added: tags/afc-2.0/arakhneRefs/src/main/resources/VERSION
===================================================================
--- tags/afc-2.0/arakhneRefs/src/main/resources/VERSION	                        (rev 0)
+++ tags/afc-2.0/arakhneRefs/src/main/resources/VERSION	2010-01-21 08:29:52 UTC (rev 117)
@@ -0,0 +1 @@
+arakhneRefs 5.1

Added: tags/afc-2.0/arakhneRefs/src/test/java/org/arakhne/junit/AbstractRepeatedTest.java
===================================================================
--- tags/afc-2.0/arakhneRefs/src/test/java/org/arakhne/junit/AbstractRepeatedTest.java	                        (rev 0)
+++ tags/afc-2.0/arakhneRefs/src/test/java/org/arakhne/junit/AbstractRepeatedTest.java	2010-01-21 08:29:52 UTC (rev 117)
@@ -0,0 +1,158 @@
+/* $Id$
+ * 
+ * Copyright (C) 2007-09 St&eacute;phane GALLAND
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * This program is free software; you can redistribute it and/or modify
+ */
+package org.arakhne.junit;
+
+import java.lang.ref.WeakReference;
+import java.util.Enumeration;
+
+import junit.extensions.TestDecorator;
+import junit.framework.AssertionFailedError;
+import junit.framework.Test;
+import junit.framework.TestListener;
+import junit.framework.TestResult;
+import junit.framework.TestSuite;
+
+/** Test case that repeat another test.
+ *
+ * @author St&eacute;phane GALLAND &lt;galland@xxxxxxxxxxx&gt;
+ * @version $Name$ $Revision$ $Date$
+ */
+public abstract class AbstractRepeatedTest extends TestDecorator {
+	
+	private final int fTimesRepeat;
+
+	/**
+	 * @param clazz
+	 * @param repeat
+	 */
+	public AbstractRepeatedTest(Class<? extends RepeatableTest> clazz, int repeat) {
+		this(new RepeatableTestSuite(clazz),repeat);
+	}
+
+	/**
+	 * @param test
+	 * @param repeat
+	 */
+	public AbstractRepeatedTest(Test test, int repeat) {
+		super(test);
+		if (repeat < 0)
+			throw new IllegalArgumentException("Repetition count must be > 0"); //$NON-NLS-1$
+		this.fTimesRepeat= repeat;
+	}
+	
+	@Override
+	public int countTestCases() {
+		return super.countTestCases()*this.fTimesRepeat;
+	}
+	
+	@Override
+	public void run(TestResult result) {
+		
+		final TestResultHandler handler = new TestResultHandler(result);
+		result.addListener(handler);
+
+		try {
+			for (int i= 0; i < this.fTimesRepeat; i++) {
+				if (result.shouldStop())
+					break;
+				((RepeatableTest)this.fTest).setLoopIndex(i);
+				try {
+					super.run(result);
+				}
+				finally {
+					((RepeatableTest)this.fTest).setLoopIndex(-1);
+				}
+			}
+		}
+		finally {
+			result.removeListener(handler);
+		}
+	}
+	
+	@Override
+	public String toString() {
+		int idx = ((RepeatableTest)this.fTest).getLoopIndex();
+		if (idx>0)
+			return super.toString()+"(repeated "+idx+"/"+this.fTimesRepeat+")"; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+		return super.toString()+"(repeated)"; //$NON-NLS-1$
+	}
+	
+	/** Handler on test result errors for a repeated test.
+	 *
+	 * @author St&eacute;phane GALLAND &lt;galland@xxxxxxxxxxx&gt;
+	 * @version $Name$ $Revision$ $Date$
+	 */
+	private class TestResultHandler implements TestListener {
+
+		private WeakReference<TestResult> result;
+		
+		public TestResultHandler(TestResult result) {
+			this.result = new WeakReference<TestResult>(result);
+		}
+		
+		public void addError(Test test, Throwable t) {
+			TestResult r = this.result.get();
+			if (r!=null) r.stop();
+		}
+
+		public void addFailure(Test test, AssertionFailedError t) {
+			TestResult r = this.result.get();
+			if (r!=null) r.stop();
+		}
+
+		public void endTest(Test test) {
+			//
+		}
+
+		public void startTest(Test test) {
+			//
+		}
+		
+	} /* class TestResultHandler */
+	
+	/** Test suite that could be repeated.
+	 *
+	 * @author St&eacute;phane GALLAND &lt;galland@xxxxxxxxxxx&gt;
+	 * @version $Name$ $Revision$ $Date$
+	 */
+	private static class RepeatableTestSuite extends TestSuite implements RepeatableTest {
+		
+		private int loopIndex = -1;
+		
+		public RepeatableTestSuite(Class<? extends RepeatableTest> clazz) {
+			super(clazz);
+		}
+
+		public void setLoopIndex(int index) {
+			this.loopIndex = index;
+			Enumeration<?> e = tests();
+			while (e.hasMoreElements()) {
+				RepeatableTest t = (RepeatableTest)e.nextElement();
+				t.setLoopIndex(index);
+			}
+		}
+		
+		public int getLoopIndex() {
+			return this.loopIndex;
+		}
+		
+	}
+
+}

Added: tags/afc-2.0/arakhneRefs/src/test/java/org/arakhne/junit/AbstractTestCase.java
===================================================================
--- tags/afc-2.0/arakhneRefs/src/test/java/org/arakhne/junit/AbstractTestCase.java	                        (rev 0)
+++ tags/afc-2.0/arakhneRefs/src/test/java/org/arakhne/junit/AbstractTestCase.java	2010-01-21 08:29:52 UTC (rev 117)
@@ -0,0 +1,761 @@
+/* $Id$
+ * 
+ * Copyright (C) 2007-09 St&eacute;phane GALLAND
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * This program is free software; you can redistribute it and/or modify
+ */
+package org.arakhne.junit;
+
+import java.awt.geom.Point2D;
+import java.lang.reflect.Array;
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Date;
+import java.util.List;
+import java.util.Map;
+import java.util.Random;
+import java.util.Map.Entry;
+
+import org.arakhne.junit.RepeatableTest;
+
+import junit.framework.AssertionFailedError;
+import junit.framework.TestCase;
+
+/** Test case with utility functions.
+*
+* @author St&eacute;phane GALLAND &lt;galland@xxxxxxxxxxx&gt;
+* @version $Name$ $Revision$ $Date$
+*/
+public abstract class AbstractTestCase extends TestCase implements RepeatableTest {
+	
+	private static String arrayToString(Object o) {
+		if (o==null) return null;
+		if (o instanceof boolean[])
+			return Arrays.toString((boolean[])o);
+		if (o instanceof byte[])
+			return Arrays.toString((byte[])o);
+		if (o instanceof char[])
+			return Arrays.toString((char[])o);
+		if (o instanceof short[])
+			return Arrays.toString((short[])o);
+		if (o instanceof int[])
+			return Arrays.toString((int[])o);
+		if (o instanceof long[])
+			return Arrays.toString((long[])o);
+		if (o instanceof float[])
+			return Arrays.toString((float[])o);
+		if (o instanceof double[])
+			return Arrays.toString((double[])o);
+		if (o instanceof Object[])
+			return Arrays.toString((Object[])o);
+		return o.toString();
+	}
+
+	/** Replies if the given elements is in the array.
+	 * <p>
+	 * This function is based on {@link Object#equals(java.lang.Object)}.
+	 */
+	private static <T> boolean arrayContainsAll(T[] elts, T[] array) {
+		boolean found;
+		for (T elt : elts) {
+			found = false;
+			for (T t : array) {
+				if ((t==elt)||
+					((t!=null)&&(t.equals(elt)))) {
+					found = true;
+					break;
+				}
+			}
+			if (!found) return false;
+		}
+		return true;
+	}
+
+	private int loopIndex = -1;
+
+	public int getLoopIndex() {
+		return this.loopIndex;
+	}
+
+	public void setLoopIndex(int index) {
+		this.loopIndex = index;
+	}
+
+	/**
+	 * Format a failure message for invalid value.
+	 * 
+	 * @param message is the message to reply.
+	 * @param expected is the expected object.
+	 * @param actual is the actual value of the object.
+	 * @return the message
+	 */
+	protected  String formatFailMessage(String message, Object expected, Object actual) {
+		StringBuffer formatted = new StringBuffer();
+		if (message!=null) {
+			formatted.append(message);
+			formatted.append(' ');
+		}
+		formatted.append("expected:<"); //$NON-NLS-1$
+		formatted.append(arrayToString(expected));
+		formatted.append("> but was:<"); //$NON-NLS-1$
+		formatted.append(arrayToString(actual));
+		formatted.append(">"); //$NON-NLS-1$
+		return formatted.toString();
+	}
+
+	/**
+	 * Format a failure message for invalid value.
+	 * 
+	 * @param message is the first part of the message (optional).
+	 * @param msg is the second part of the message (mandatory).
+	 * @param actual is the actual value of the object.
+	 * @return the message
+	 */
+	protected  String formatFailMessage(String message, String msg, Object actual) {
+		StringBuffer formatted = new StringBuffer();
+		if (message!=null) {
+			formatted.append(message);
+			formatted.append(' ');
+		}
+		formatted.append(msg);
+		formatted.append(" but was:<"); //$NON-NLS-1$
+		formatted.append(arrayToString(actual));
+		formatted.append(">"); //$NON-NLS-1$
+		return formatted.toString();
+	}
+
+	/**
+	 * Format a failure message for not-expected values.
+	 * 
+	 * @param message is the message to reply.
+	 * @param notexpected is the not-expected object.
+	 * @return the message
+	 */
+	protected String formatFailNegMessage(String message, Object notexpected) {
+		StringBuffer formatted = new StringBuffer();
+		if (message!=null) {
+			formatted.append(message);
+			formatted.append(' ');
+		}
+		formatted.append("not expected:<"); //$NON-NLS-1$
+		formatted.append(arrayToString(notexpected));
+		formatted.append("> but the same"); //$NON-NLS-1$
+		return formatted.toString();
+	}
+
+	/** Asserts that two objects are not equal. If they are
+	 * an AssertionFailedError is thrown with the given message.
+	 * 
+	 * @param message is the error message to put inside the assertion.
+	 * @param notexpected is the value which is not expected by the unit test.
+	 * @param actual is the actual value of the object in the unit test.
+	 */
+	protected void assertNotEquals(String message, Object notexpected, Object actual) {
+		if ((notexpected!=actual)&&
+			((notexpected==null)
+			 ||
+			 (!notexpected.equals(actual)))) return;
+		fail(formatFailNegMessage(message, notexpected));
+	}
+
+	/** Asserts that two objects are not equal. If they are
+	 * an AssertionFailedError is thrown with the given message.
+	 * 
+	 * @param notexpected is the value which is not expected by the unit test.
+	 * @param actual is the actual value of the object in the unit test.
+	 */
+	protected void assertNotEquals(Object notexpected, Object actual) {
+	    assertNotEquals(null, notexpected, actual);
+	}
+	
+	/** Asserts that the actuel object is equal to one of the expected objects. If not
+	 * an AssertionFailedError is thrown with the given message.
+	 * 
+	 * @param message is the error message to put inside the assertion.
+	 * @param expectedObjects are the set of expected values during the unit test.
+	 * @param actual is the actual value of the object in the unit test.
+	 */
+	protected void assertEquals(String message, Object[] expectedObjects, Object actual) {
+		if ((expectedObjects!=null)&&(expectedObjects.length>0)) {
+			for (Object object : expectedObjects) {
+				if ((object==null)&&(actual==null)) return;
+				if ((object!=null)&&(object.equals(actual))) return;
+			}
+		}
+		fail(formatFailMessage(message, expectedObjects, actual));
+	}
+
+	/** Asserts that the actuel object is equal to one of the expected objects. If not
+	 * an AssertionFailedError is thrown.
+	 * 
+	 * @param expectedObjects are the set of expected values during the unit test.
+	 * @param actual is the actual value of the object in the unit test.
+	 */
+	protected void assertEquals(Object[] expectedObjects, Object actual) {
+	    assertEquals(null, expectedObjects, actual);
+	}
+
+	/** Asserts that the actuel object is equal to one of the expected objects. If not
+	 * an AssertionFailedError is thrown with the given message.
+	 *
+	 * @param <T> is the type of the array.
+	 * @param message is the error message to put inside the assertion.
+	 * @param expectedObjects are the set of expected values during the unit test.
+	 * @param actual is the actual value of the objects in the unit test.
+	 */
+	protected <T> void assertEquals(String message, T[] expectedObjects, T[] actual) {
+		if (expectedObjects==actual) return;
+		if ((expectedObjects!=null)&&(actual!=null)&&
+			(expectedObjects.length==actual.length)) {
+			boolean ok = true;
+			for(int i=0; i<expectedObjects.length; i++) {
+				if ((expectedObjects[i]!=null)||(actual[i]!=null)) {
+					if ((expectedObjects[i]==null)||(!expectedObjects[i].equals(actual[i]))) {
+						ok = false;
+						break;
+					}
+				}
+			}
+			if (ok) return;
+		}
+		fail(formatFailMessage(message, expectedObjects, actual));
+	}
+
+	/** Asserts that the actuel object is equal to one of the expected objects. If not
+	 * an AssertionFailedError is thrown.
+	 *
+	 * @param <T> is the type of the array.
+	 * @param expectedObjects are the set of expected values during the unit test.
+	 * @param actual is the actual value of the objects in the unit test.
+	 */
+	protected <T> void assertEquals(T[] expectedObjects, T[] actual) {
+	    assertEquals(null, expectedObjects, actual);
+	}
+
+	/** Asserts that the actuel object is not equal to one of the expected objects. If not
+	 * an AssertionFailedError is thrown with the given message.
+	 *
+	 * @param <T> is the type of the array.
+	 * @param message is the error message to put inside the assertion.
+	 * @param expectedObjects are the set of expected values during the unit test.
+	 * @param actual is the actual value of the objects in the unit test.
+	 */
+	protected <T> void assertNotEquals(String message, T[] expectedObjects, T[] actual) {
+		if (expectedObjects!=actual) {			
+			if ((expectedObjects!=null)&&(actual!=null)) {
+				if (expectedObjects.length!=actual.length) return;
+				boolean ok = true;
+				for(int i=0; i<expectedObjects.length; i++) {
+					if ((expectedObjects[i]!=null)||(actual[i]!=null)) {
+						if ((expectedObjects[i]==null)||(!expectedObjects[i].equals(actual[i]))) {
+							ok = false;
+							break;
+						}
+					}
+				}
+				if (!ok) return;
+			}
+			else return;
+		}
+		fail(formatFailMessage(message, expectedObjects, actual));
+	}
+
+	/** Asserts that the actuel object is not equal to one of the expected objects. If not
+	 * an AssertionFailedError is thrown.
+	 *
+	 * @param <T> is the type of the array.
+	 * @param expectedObjects are the set of expected values during the unit test.
+	 * @param actual is the actual value of the objects in the unit test.
+	 */
+	protected <T> void assertNotEquals(T[] expectedObjects, T[] actual) {
+	    assertNotEquals(null, expectedObjects, actual);
+	}
+
+	/** Asserts that the actuel object is equal to one of the expected objects. If not
+	 * an AssertionFailedError is thrown.
+	 * This assertion function tests the types of its parameters to call the best
+	 * {@code assertEquals} function.
+	 * 
+	 * @param expected is the expected value during the unit test.
+	 * @param actual is the actual value of the object during the unit test.
+	 * @see #assertEquals(Object, Object)
+	 * @see #assertEquals(Object[], Object)
+	 * @see #assertEquals(Object[], Object[])
+	 */
+	protected void assertEqualsGeneric(Object expected, Object actual) {
+		assertEqualsGeneric(null, expected, actual);
+	}
+
+	/** Asserts that the actuel object is equal to one of the expected objects. If not
+	 * an AssertionFailedError is thrown.
+	 * This assertion function tests the types of its parameters to call the best
+	 * {@code assertEquals} function.
+	 * 
+	 * @param message is the error message to put inside the assertion.
+	 * @param expected is the expected value during the unit test.
+	 * @param actual is the actual value of the object during the unit test.
+	 * @see #assertEquals(Object, Object)
+	 * @see #assertEquals(Object[], Object)
+	 * @see #assertEquals(Object[], Object[])
+	 */
+	protected void assertEqualsGeneric(String message, Object expected, Object actual) {
+		if ((expected!=null)&&(actual!=null)&&(expected.getClass().isArray())) {
+			if (actual.getClass().isArray())
+				assertEquals(message, (Object[])expected, (Object[])actual);
+			else
+				assertEquals(message, (Object[])expected, actual);
+		}
+		else assertEquals(message, expected, actual);
+	}
+
+	/** Asserts that the actuel similar is equal to one of the expected objects. If not
+	 * an AssertionFailedError is thrown.
+	 * 
+	 * @param <T> is the type of the values
+	 * @param expectedObjects are the expected values during the unit test.
+	 * @param actual are the actual values of the objects during the unit test.
+	 */
+	protected <T> void assertSimilars(T[] expectedObjects, T[] actual) {
+	    assertSimilars(null, expectedObjects, actual);
+	}
+
+	/** Asserts that the actuel similar is equal to one of the expected objects. If not
+	 * an AssertionFailedError is thrown.
+	 * 
+	 * @param <T> is the type of the values
+	 * @param message is the error message to put inside the assertion.
+	 * @param expectedObjects are the expected values during the unit test.
+	 * @param actual are the actual values of the objects during the unit test.
+	 */
+	protected <T> void assertSimilars(String message, T[] expectedObjects, T[] actual) {
+		if (expectedObjects==actual) return;
+		if ((arrayContainsAll(expectedObjects, actual))&&(arrayContainsAll(actual, expectedObjects)))
+			return;
+		fail(formatFailMessage(message, expectedObjects, actual));
+	}
+
+	/** Asserts that the actuel similar is equal to one of the expected objects. If not
+	 * an AssertionFailedError is thrown.
+	 * 
+	 * @param <T> is the type of the values
+	 * @param expectedObjects are the expected values during the unit test.
+	 * @param actual are the actual values of the objects during the unit test.
+	 */
+	protected <T> void assertSimilars(Collection<T> expectedObjects, Collection<T> actual) {
+	    assertSimilars(null, expectedObjects, actual);
+	}
+	
+	/** Asserts that the actuel similar is equal to one of the expected objects. If not
+	 * an AssertionFailedError is thrown.
+	 * 
+	 * @param <T> is the type of the values
+	 * @param message is the error message to put inside the assertion.
+	 * @param expectedObjects are the expected values during the unit test.
+	 * @param actual are the actual values of the objects during the unit test.
+	 */
+	protected <T> void assertSimilars(String message, Collection<T> expectedObjects, Collection<T> actual) {
+		if (expectedObjects==actual) return;
+		if (similars(expectedObjects,actual)) return;
+		fail(formatFailMessage(message, expectedObjects, actual));
+	}
+	
+	private <T> boolean similars(Collection<T> c1, Collection<T> c2) {
+		ArrayList<T> a = new ArrayList<T>();
+		a.addAll(c2);
+		for(T elt : c1) {
+			if (!a.remove(elt)) {
+				return false;
+			}
+		}
+		return a.isEmpty();
+	}
+
+	/** Asserts that the actuel similar is equal to one of the expected objects. If not
+	 * an AssertionFailedError is thrown.
+	 * 
+	 * @param <T> is the type of the values
+	 * @param expectedObjects are the expected values during the unit test.
+	 * @param actual are the actual values of the objects during the unit test.
+	 */
+	protected <T> void assertEquals(List<T> expectedObjects, List<T> actual) {
+	    assertEquals(null, expectedObjects, actual);
+	}
+	
+	/** Asserts that the actuel similar is equal to one of the expected objects. If not
+	 * an AssertionFailedError is thrown.
+	 * 
+	 * @param <T> is the type of the values.
+	 * @param message is the error message to put inside the assertion.
+	 * @param expectedObjects are the expected values during the unit test.
+	 * @param actual are the actual values of the objects during the unit test.
+	 */
+	protected <T> void assertEquals(String message, List<T> expectedObjects, List<T> actual) {
+		if (expectedObjects==actual) return;
+		if (equals(expectedObjects,actual)) return;
+		fail(formatFailMessage(message, expectedObjects, actual));
+	}
+
+	private <T> boolean equals(List<T> c1, List<T> c2) {
+		if (c1.size()!=c2.size()) return false;
+		int count = c1.size();
+		T e1, e2;
+		for(int i=0; i<count; i++) {
+			e1 = c1.get(i);
+			e2 = c2.get(i);
+			if ((e1!=e2)&&(!e1.equals(e2))) {
+				return false;
+			}
+		}
+		return true;
+	}
+	
+	/** Asserts that the actuel similar is not equal to one of the expected objects. If not
+	 * an AssertionFailedError is thrown.
+	 * 
+	 * @param <T> is the type of the values
+	 * @param expectedObjects are the expected values during the unit test.
+	 * @param actual are the actual values of the objects during the unit test.
+	 */
+	protected <T> void assertNotEquals(List<T> expectedObjects, List<T> actual) {
+	    assertNotEquals(null, expectedObjects, actual);
+	}
+	
+	/** Asserts that the actuel object is not equal to one of the expected objects. If not
+	 * an AssertionFailedError is thrown.
+	 * 
+	 * @param <T> is the type of the values
+	 * @param message is the error message to put inside the assertion.
+	 * @param expectedObjects are the expected values during the unit test.
+	 * @param actual are the actual values of the objects during the unit test.
+	 */
+	protected <T> void assertNotEquals(String message, List<T> expectedObjects, List<T> actual) {
+		if ((expectedObjects!=actual)&&(!equals(expectedObjects,actual))) return;
+		fail(formatFailMessage(message, expectedObjects, actual));
+	}
+
+	/** Asserts that the actual object is equal to one of the expected objects. If not
+	 * an AssertionFailedError is thrown.
+	 * 
+	 * @param <T> is the type of the values
+	 * @param <X> is the element's type of the values if they are arrays.
+	 * @param message is the error message to put inside the assertion.
+	 * @param expected is the expected value during the unit test.
+	 * @param actual are the actual value of the object during the unit test.
+	 */
+	@SuppressWarnings("unchecked")
+	protected <T, X> void assertSimilars(String message, T expected, T actual) {
+		if (expected==actual) return;
+		if (expected instanceof Collection)
+			assertSimilars(message, (Collection)expected, (Collection)actual);
+		else if (expected instanceof Point2D)
+			assertSimilars(message, (Point2D)expected, (Point2D)actual);
+		else if (expected instanceof Date)
+			assertSimilars(message, (Date)expected, (Date)actual);
+		else if (expected.getClass().isArray())
+			assertSimilars(message, (X[])expected, (X[])actual);
+		else
+			assertEquals(message, expected, actual);
+	}
+
+	/** Asserts that the actual object is equal to one of the expected objects. If not
+	 * an AssertionFailedError is thrown.
+	 * 
+	 * @param <T> is the type of the values.
+	 * @param <X> is the element's type of the values if they are arrays.
+	 * @param message is the error message to put inside the assertion.
+	 * @param expected is the expected value.
+	 * @param actual is the current value.
+	 */
+	protected <T, X> void assertNotSimilars(String message, T expected, T actual) {
+		if (expected!=actual) {
+			try {
+				assertSimilars(message,expected, actual);
+			}
+			catch(AssertionError _) {
+				// ok
+				return;
+			}
+			catch(AssertionFailedError _) {
+				// ok
+				return;
+			}
+		}		
+		fail(formatFailMessage(message, expected, actual));
+	}
+
+	/** Replies if the two objects are similars.
+	 * 
+	 * @param <T> is the type of the values
+	 * @param <X> is the element's type of the values if they are arrays.
+	 * @param obj1
+	 * @param obj2
+	 * @return <code>true</code> if the objects are similar, otherwise <code>false</code>
+	 */
+	protected <T, X> boolean isSimilarObjects(T obj1, T obj2) {
+		if (obj1==obj2) return true;
+		try {
+			assertSimilars(null,obj1, obj2);
+			return true;
+		}
+		catch(AssertionError _) {
+			return false;
+		}
+		catch(AssertionFailedError _) {
+			return false;
+		}
+	}
+
+	/** Asserts that the actuel similar is equal to one of the expected objects. If not
+	 * an AssertionFailedError is thrown.
+	 * 
+	 * @param <K> is the type of the map keys.
+	 * @param <V> is the type of the map values.
+	 * @param expectedObjects is the expected map.
+	 * @param actual is the current map.
+	 */
+	protected <K,V> void assertDeepSimilars(Map<K,V> expectedObjects, Map<K,V> actual) {
+	    assertDeepSimilars(null, expectedObjects, actual);
+	}
+	
+	/** Asserts that the actuel similar is equal to one of the expected objects. If not
+	 * an AssertionFailedError is thrown.
+	 * 
+	 * @param <K> is the type of the map keys.
+	 * @param <V> is the type of the map values.
+	 * @param message is the error message to put inside the assertion.
+	 * @param expectedObjects is the expected map.
+	 * @param actual is the current map.
+	 */
+	protected <K,V> void assertDeepSimilars(String message, Map<K,V> expectedObjects, Map<K,V> actual) {
+		if (expectedObjects==actual) return;
+		if (similars(expectedObjects.keySet(), actual.keySet())) {
+			for(Entry<K,V> entry : expectedObjects.entrySet()) {
+				V v1 = entry.getValue();
+				V v2 = actual.get(entry.getKey());
+				assertSimilars(message, v1, v2);
+			}
+			// all values are correct
+			return;
+		}
+		fail(formatFailMessage(message, expectedObjects, actual));
+	}
+
+	/** Asserts that the actuel similar is equal to one of the expected objects. If not
+	 * an AssertionFailedError is thrown.
+	 * 
+	 * @param <K> is the type of the map keys.
+	 * @param <V> is the type of the map values.
+	 * @param expectedObjects is the expected map.
+	 * @param actual is the current map.
+	 */
+	protected <K,V> void assertNotDeepSimilars(Map<K,V> expectedObjects, Map<K,V> actual) {
+	    assertNotDeepSimilars(null, expectedObjects, actual);
+	}
+	
+	/** Asserts that the actuel similar is equal to one of the expected objects. If not
+	 * an AssertionFailedError is thrown.
+	 * 
+	 * @param <K> is the type of the map keys.
+	 * @param <V> is the type of the map values.
+	 * @param message is the error message to put inside the assertion.
+	 * @param expectedObjects is the expected map.
+	 * @param actual is the current map.
+	 */
+	protected <K,V> void assertNotDeepSimilars(String message, Map<K,V> expectedObjects, Map<K,V> actual) {
+		if (expectedObjects!=actual) {
+			if (!similars(expectedObjects.keySet(), actual.keySet())) return;
+			
+			for(Entry<K,V> entry : expectedObjects.entrySet()) {
+				V v1 = entry.getValue();
+				V v2 = actual.get(entry.getKey());
+				if (!isSimilarObjects(v1, v2)) return;
+			}
+		}
+		fail(formatFailMessage(message, expectedObjects, actual));
+	}
+
+	/** Asserts that the specified value is stricly negative.
+	 * 
+	 * @param number
+	 */
+	protected void assertStrictlyNegative(Number number) {
+		assertStrictlyNegative(null,number);
+	}
+
+	/** Asserts that the specified value is stricly negative.
+	 * 
+	 * @param message is the error message to put inside the assertion.
+	 * @param number
+	 */
+	protected void assertStrictlyNegative(String message, Number number) {
+		if (number.doubleValue()<0.) return;
+		fail(formatFailMessage(message, "expected negative value", number)); //$NON-NLS-1$
+	}
+
+	/** Asserts that the specified value is stricly positive.
+	 * 
+	 * @param number
+	 */
+	protected void assertStrictlyPositive(Number number) {
+		assertStrictlyPositive(null,number);
+	}
+
+	/** Asserts that the specified value is stricly positive.
+	 * 
+	 * @param message is the error message to put inside the assertion.
+	 * @param number
+	 */
+	protected void assertStrictlyPositive(String message, Number number) {
+		if (number.doubleValue()>0.) return;
+		fail(formatFailMessage(message, "expected positive value", number)); //$NON-NLS-1$
+	}
+
+	/** Asserts that the specified value is negative.
+	 * 
+	 * @param number
+	 */
+	protected void assertNegative(Number number) {
+		assertNegative(null,number);
+	}
+
+	/** Asserts that the specified value is negative.
+	 * 
+	 * @param message is the error message to put inside the assertion.
+	 * @param number
+	 */
+	protected void assertNegative(String message, Number number) {
+		if (number.doubleValue()<=0.) return;
+		fail(formatFailMessage(message, "expected negative value", number)); //$NON-NLS-1$
+	}
+
+	/** Asserts that the specified value is positive.
+	 * 
+	 * @param number
+	 */
+	protected void assertPositive(Number number) {
+		assertPositive(null,number);
+	}
+
+	/** Asserts that the specified value is positive.
+	 * 
+	 * @param message is the error message to put inside the assertion.
+	 * @param number
+	 */
+	protected void assertPositive(String message, Number number) {
+		if (number.doubleValue()>=0.) return;
+		fail(formatFailMessage(message, "expected positive value", number)); //$NON-NLS-1$
+	}
+
+	/**
+	 * Replies an array which is containing values randomly selected from the parameter.
+	 * Duplicate values are allowed.
+	 * 
+	 * @param <T> is the type of the values.
+	 * @param availableValues is the collection of available values.
+	 * @return the selected values (possible duplicated)
+	 */
+	@SuppressWarnings("unchecked")
+	protected <T> T[] extractRandomValues(T[] availableValues) {
+		Random rnd = new Random();
+		int count = rnd.nextInt(500);
+		ArrayList<T> tab = new ArrayList<T>(count);
+		for(int i=0; i<count; i++) {
+			tab.add(availableValues[rnd.nextInt(availableValues.length)]);
+		}
+		Class<?> clazz = availableValues.getClass().getComponentType();
+		T[] array = (T[])Array.newInstance(clazz, tab.size());
+		tab.toArray(array);
+		tab.clear();
+		return array;
+	}
+	
+	/** Replies a randomized string.
+	 * 
+	 * @return a random string.
+	 */
+	protected String randomString() {
+		return randomString(-1);
+	}
+
+	/** Replies a randomized string with a max length.
+	 *
+	 * @param maxSize is the max length of the string.
+	 * @return a random string with a max length.
+	 */
+	protected String randomString(int maxSize) {
+		Random rnd = new Random();
+		StringBuffer b = new StringBuffer();
+		int count = rnd.nextInt(maxSize<=0 ? 255 : maxSize-1)+1;
+		for(int i=0; i<count; i++) {
+			char c = (char)('A' + rnd.nextInt(26));
+			b.append(c);
+		}
+		return b.toString();
+	}
+
+	/** Assert the the specified method thrown an exception
+	 * 
+	 * @param self is the calling object
+	 * @param method is the name of the method to invoke
+	 * @param types is the parameter types of the method
+	 * @param parameters is the parameter values to pass at invocation.
+	 */
+	protected void assertException(Object self, String method, Class<?>[] types, Object[] parameters) {
+		assertException(null, self, method, types, parameters);
+	}
+
+	/** Assert the the specified method thrown an exception
+	 * 
+	 * @param message is the error message to put in the assertion.
+	 * @param self is the calling object
+	 * @param method is the name of the method to invoke
+	 * @param types is the parameter types of the method
+	 * @param parameters is the parameter values to pass at invocation.
+	 */
+	protected void assertException(String message, Object self, String method, Class<?>[] types, Object[] parameters) {
+		try {
+			Class<?> clazz = self.getClass();
+			Method methodFunc = clazz.getMethod(method, types);
+			methodFunc.invoke(self, parameters);
+			fail((message==null ? "" : message)+"An exception was attempted but never thrown."); //$NON-NLS-1$ //$NON-NLS-2$
+		}
+		catch(Exception _) {
+			// Expected behavior
+		}
+	}
+
+	/** Assert the the specified method thrown an exception
+	 * 
+	 * @param self is the calling object
+	 * @param method is the name of the method to invoke
+	 */
+	protected void assertException(Object self, String method) {
+		assertException(null, self, method, new Class<?>[0], new Object[0]);
+	}
+
+	/** Assert the the specified method thrown an exception
+	 * 
+	 * @param message is the error message to put in the assertion.
+	 * @param self is the calling object
+	 * @param method is the name of the method to invoke
+	 */
+	protected void assertException(String message, Object self, String method) {
+		assertException(message, self, method, new Class<?>[0], new Object[0]);
+	}
+
+}

Added: tags/afc-2.0/arakhneRefs/src/test/java/org/arakhne/junit/RepeatableTest.java
===================================================================
--- tags/afc-2.0/arakhneRefs/src/test/java/org/arakhne/junit/RepeatableTest.java	                        (rev 0)
+++ tags/afc-2.0/arakhneRefs/src/test/java/org/arakhne/junit/RepeatableTest.java	2010-01-21 08:29:52 UTC (rev 117)
@@ -0,0 +1,57 @@
+/* $Id$
+ * 
+ * Copyright (C) 2007-09 St&eacute;phane GALLAND
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * This program is free software; you can redistribute it and/or modify
+ */
+package org.arakhne.junit;
+
+import junit.framework.Test;
+
+/** Test case that could be repeated.
+ *
+ * @author St&eacute;phane GALLAND &lt;galland@xxxxxxxxxxx&gt;
+ * @version $Name$ $Revision$ $Date$
+ */
+public interface RepeatableTest extends Test {
+	
+	/**
+	 * Set the index of the current test.
+	 *  
+	 * @param index 
+	 */
+	public void setLoopIndex(int index);
+	
+	/**
+	 * Replies the index of the current test.
+	 *  
+	 * @return the index of the current test.
+	 */
+	public int getLoopIndex();
+
+	/** Set the name of the unit test.
+	 * 
+	 * @param name is the name of the unit test.
+	 */
+	public void setName(String name);
+	
+	/** Replies the name of the unit test.
+	 * 
+	 * @return the name of the unit test.
+	 */
+	public String getName();
+
+}

Added: tags/afc-2.0/arakhneRefs/src/test/java/org/arakhne/util/ref/SoftValueMapTest.java
===================================================================
--- tags/afc-2.0/arakhneRefs/src/test/java/org/arakhne/util/ref/SoftValueMapTest.java	                        (rev 0)
+++ tags/afc-2.0/arakhneRefs/src/test/java/org/arakhne/util/ref/SoftValueMapTest.java	2010-01-21 08:29:52 UTC (rev 117)
@@ -0,0 +1,382 @@
+/* $Id$
+ * 
+ * Copyright (C) 2007-09 St&eacute;phane GALLAND
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * This program is free software; you can redistribute it and/or modify
+ */
+package org.arakhne.util.ref;
+
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Random;
+import java.util.Map.Entry;
+
+import org.arakhne.junit.AbstractTestCase;
+
+/**
+* @author St&eacute;phane GALLAND &lt;galland@xxxxxxxxxxx&gt;
+* @version $Name$ $Revision$ $Date$
+*/
+public class SoftValueMapTest extends AbstractTestCase {
+
+	private static final int REFERENCE_SIZE = 0; 
+	
+	private final HashMap<String,String> reference = new HashMap<String,String>();
+	
+	private static void collect() {
+		System.gc();System.gc();System.gc();
+	}
+	
+	private void spawnReference() {
+		this.reference.clear();
+		Random rnd = new Random();
+		int count = rnd.nextInt(REFERENCE_SIZE+1)+5;
+		String str;
+		for(int i=0; i<count; i++) {
+			str = randomString(10);
+			this.reference.put(
+					Integer.toString(i)+str,
+					str);
+		}
+		str = null;
+	}
+	
+	private String getReferenceObject(int index) {
+		Object[] tab = this.reference.keySet().toArray();
+		return (String)tab[index];
+	}
+	
+	private Map<String,String> removeElementsFromReference() {
+		HashMap<String,String> removed = new HashMap<String,String>();
+		Random rnd = new Random();
+		int index;
+		int count = rnd.nextInt(this.reference.size()/4)+1;
+		String key, value;
+		for(int i=0; i<count; i++) {
+			index = rnd.nextInt(this.reference.size());
+			key = getReferenceObject(index);
+			value = this.reference.remove(key);
+			removed.put(key,value);
+		}
+		key = null;
+		value =  null;
+		return removed;
+	}
+	
+	@Override
+	public void setUp() {
+		spawnReference();
+	}
+	
+	@Override
+	public void tearDown() {
+		this.reference.clear();
+	}
+	
+	/**
+	 */
+	public void testSoftValueMapMap() {
+        SoftValueMap<String,String> test = new SoftValueMap<String,String>(this.reference);
+        assertDeepSimilars(this.reference, test);
+    }
+
+	/**
+	 */
+    public void testSize() {
+    	SoftValueMap<String,String> test = new SoftValueMap<String,String>();
+        assertEquals(0, test.size());
+        
+        test = new SoftValueMap<String,String>(this.reference);
+        test.setDeeplyExpurge(true);
+        assertEquals(this.reference.size(), test.size());
+
+        Map<String,String> removed = removeElementsFromReference();
+        assertNotNull(removed);
+        int count = removed.size();
+        removed = null;
+		
+		collect();
+		
+        assertTrue(((this.reference.size()-count)<=test.size())||(this.reference.size()>test.size()));		
+    }
+
+	/**
+	 */
+    public void testIsEmpty() {
+    	SoftValueMap<String,String> test = new SoftValueMap<String,String>();
+        assertTrue(test.isEmpty());
+        
+        test = new SoftValueMap<String,String>(this.reference);
+        test.setDeeplyExpurge(true);
+        assertFalse(test.isEmpty());
+        
+        removeElementsFromReference();
+
+		collect();
+		
+        assertFalse(test.isEmpty());
+        
+        this.reference.clear();
+
+		collect();
+		
+        assertFalse(test.isEmpty());
+    }
+	
+	/**
+	 */
+    public void testContainsKey() {
+    	SoftValueMap<String,String> test = new SoftValueMap<String,String>(this.reference);
+        test.setDeeplyExpurge(true);
+        assertDeepSimilars(this.reference, test);
+
+        // Test the content
+		{
+			String elt;
+			Iterator<String> iter = this.reference.keySet().iterator(); 
+			while (iter.hasNext()) {
+				elt = iter.next();
+				assertTrue(test.containsKey(elt));
+			}
+			elt = null;
+		}
+		assertDeepSimilars(this.reference, test);
+
+        Map<String,String> removedElements = removeElementsFromReference();
+        int originalSize = removedElements.size() + this.reference.size();
+
+		// Collects the objects
+		collect();
+
+        // Test the content
+		assertEquals(originalSize, test.size());
+		assertNotDeepSimilars(this.reference, test);
+		
+		// Clear the list of removed elements, which will cause collecting
+		removedElements.clear();
+		removedElements = null;
+
+		// Collects the objects
+		collect();
+		
+        // Test the content
+		assertNotEquals(this.reference.size(), test.size());
+		for(String elt : this.reference.keySet()) {
+			assertTrue(test.containsKey(elt));
+		}
+    }
+
+	/**
+	 */
+    public void testContainsValue() {
+    	SoftValueMap<String,String> test = new SoftValueMap<String,String>(this.reference);
+        test.setDeeplyExpurge(true);
+        assertDeepSimilars(this.reference, test);
+
+        // Test the content
+		{
+			String elt;
+			Iterator<String> iter = this.reference.values().iterator(); 
+			while (iter.hasNext()) {
+				elt = iter.next();
+				assertTrue(test.containsValue(elt));
+			}
+			elt = null;
+		}
+		assertDeepSimilars(this.reference, test);
+
+        Map<String,String> removedElements = removeElementsFromReference();
+        int originalSize = removedElements.size() + this.reference.size();
+
+		// Collects the objects
+		collect();
+
+        // Test the content
+		assertEquals(originalSize, test.size());
+		assertNotDeepSimilars(this.reference, test);
+		
+		// Clear the list of removed elements, which will cause collecting
+		removedElements.clear();
+		removedElements = null;
+
+		// Collects the objects
+		collect();
+		
+        // Test the content
+		assertNotEquals(this.reference.size(), test.size());
+		for(String elt : this.reference.values()) {
+			assertTrue(test.containsValue(elt));
+		}
+    }
+
+	/**
+	 */
+    public void testEntryIterator() {
+    	SoftValueMap<String,String> test = new SoftValueMap<String,String>(this.reference);
+        test.setDeeplyExpurge(true);
+	
+        // Test the content
+    	{
+        	assertDeepSimilars(this.reference, test);
+    		Entry<String,String> e;
+        	Iterator<Entry<String,String>> iter = test.entrySet().iterator();
+        	while (iter.hasNext()) {
+        		e = iter.next();
+        		assertTrue(this.reference.containsKey(e.getKey()));
+        		assertEquals(this.reference.get(e.getKey()),this.reference.get(e.getKey()));
+        	}
+    	}
+
+        // Remove elements
+    	Map<String,String> baseElements = new HashMap<String,String>(this.reference);
+        removeElementsFromReference();
+
+		// Collects the objects
+		collect();
+
+        // Test the content
+    	{
+    		assertNotDeepSimilars(this.reference, test);
+    		Entry<String,String> e;
+        	Iterator<Entry<String,String>> iter = test.entrySet().iterator();
+        	while (iter.hasNext()) {
+        		e = iter.next();
+        		assertTrue(baseElements.containsKey(e.getKey()));
+        		assertEquals(baseElements.get(e.getKey()),baseElements.get(e.getKey()));
+        	}
+    	}
+
+		// Clear the list of removed elements, which will cause collecting
+		baseElements.clear();
+		baseElements = null;
+
+		// Collects the objects
+		collect();
+
+        // Test the content
+    	{
+        	assertNotDeepSimilars(this.reference, test);
+    		Entry<String,String> e;
+        	Iterator<Entry<String,String>> iter = test.entrySet().iterator();
+        	while (iter.hasNext()) {
+        		e = iter.next();
+        		assertEquals(this.reference.get(e.getKey()),this.reference.get(e.getKey()));
+        	}
+    	}
+    }
+
+	/**
+	 */
+    public void testKeyIterator() {
+    	SoftValueMap<String,String> test = new SoftValueMap<String,String>(this.reference);
+        test.setDeeplyExpurge(true);
+	
+        // Test the content
+    	{
+        	assertDeepSimilars(this.reference, test);
+    		String k;
+        	Iterator<String> iter = test.keySet().iterator();
+        	while (iter.hasNext()) {
+        		k = iter.next();
+        		assertTrue(this.reference.containsKey(k));
+        	}
+    	}
+
+        // Remove elements
+    	Map<String,String> baseElements = new HashMap<String,String>(this.reference);
+        removeElementsFromReference();
+
+		// Collects the objects
+		collect();
+
+        // Test the content
+    	{
+        	assertNotDeepSimilars(this.reference, test);
+    		String k;
+        	Iterator<String> iter = test.keySet().iterator();
+        	while (iter.hasNext()) {
+        		k = iter.next();
+        		assertTrue(baseElements.containsKey(k));
+        	}
+    	}
+
+		// Clear the list of removed elements, which will cause collecting
+		baseElements.clear();
+		baseElements = null;
+
+		// Collects the objects
+		collect();
+
+        // Test the content
+    	{
+        	assertNotDeepSimilars(this.reference, test);
+    	}
+    }
+
+	/**
+	 */
+    public void testValueIterator() {
+    	SoftValueMap<String,String> test = new SoftValueMap<String,String>(this.reference);
+        test.setDeeplyExpurge(true);
+	
+        // Test the content
+    	{
+        	assertDeepSimilars(this.reference, test);
+    		String v;
+        	Iterator<String> iter = test.values().iterator();
+        	while (iter.hasNext()) {
+        		v = iter.next();
+        		assertTrue(this.reference.containsValue(v));
+        	}
+        	v = null;
+        	iter = null;
+    	}
+
+        // Remove elements
+    	Map<String,String> baseElements = new HashMap<String,String>(this.reference);
+        removeElementsFromReference();
+
+		// Collects the objects
+		collect();
+
+        // Test the content
+    	{
+        	assertNotDeepSimilars(this.reference, test);
+    		String v;
+        	Iterator<String> iter = test.values().iterator();
+        	while (iter.hasNext()) {
+        		v = iter.next();
+        		assertTrue(baseElements.containsValue(v));
+        	}
+        	v = null;
+        	iter = null;
+    	}
+
+		// Clear the list of removed elements, which will cause collecting
+		baseElements.clear();
+		baseElements = null;
+
+		// Collects the objects
+		collect();
+
+        // Test the content
+    	{
+        	assertNotDeepSimilars(this.reference, test);
+    	}
+    }
+
+}

Added: tags/afc-2.0/arakhneRefs/src/test/java/org/arakhne/util/ref/WeakArrayListTest.java
===================================================================
--- tags/afc-2.0/arakhneRefs/src/test/java/org/arakhne/util/ref/WeakArrayListTest.java	                        (rev 0)
+++ tags/afc-2.0/arakhneRefs/src/test/java/org/arakhne/util/ref/WeakArrayListTest.java	2010-01-21 08:29:52 UTC (rev 117)
@@ -0,0 +1,931 @@
+/* $Id$
+ * 
+ * Copyright (C) 2007-09 St&eacute;phane GALLAND
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * This program is free software; you can redistribute it and/or modify
+ */
+package org.arakhne.util.ref;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Random;
+
+import org.arakhne.junit.AbstractTestCase;
+
+/**
+* @author St&eacute;phane GALLAND &lt;galland@xxxxxxxxxxx&gt;
+* @version $Name$ $Revision$ $Date$
+*/
+public class WeakArrayListTest extends AbstractTestCase {
+
+	private static final int REFERENCE_SIZE = 0; 
+	
+	private static void collect(WeakArrayList<String> list) {
+		for(int i=0; i<3; i++) {
+			System.gc();
+		}
+		list.expurge();
+	}
+	
+	private List<String> spawnReference() {
+		Random rnd = new Random();
+		int count = rnd.nextInt(REFERENCE_SIZE+1)+5;
+		List<String> reference = new ArrayList<String>(count);
+		for(int i=0; i<count; i++) {
+			reference.add(Integer.toString(i)+randomString(10));
+		}
+		Collections.sort(reference);
+		return reference;
+	}
+		
+	/**
+	 */
+	public void testWeakArrayListCollection() {
+		List<String> reference = spawnReference();
+        WeakArrayList<String> test = new WeakArrayList<String>(reference);
+        assertEquals(reference, test);
+    }
+
+	/**
+	 */
+    public void testSize() {
+		List<String> reference = spawnReference();
+
+		WeakArrayList<String> test = new WeakArrayList<String>();
+        assertEquals(0, test.size());
+        
+        test = new WeakArrayList<String>(reference);
+        assertEquals(reference.size(), test.size());
+        
+        reference.clear();
+        reference = null;
+		collect(test);
+		
+        assertEquals(0, test.size());		
+    }
+
+	/**
+	 */
+    public void testIsEmpty() {
+		List<String> reference = spawnReference();
+
+		WeakArrayList<String> test = new WeakArrayList<String>();
+        assertEquals(0, test.size());
+        
+        test = new WeakArrayList<String>(reference);
+        assertFalse(test.isEmpty());
+        
+        reference.clear();
+        reference = null;
+		collect(test);
+		
+        assertTrue(test.isEmpty());		
+    }
+
+//    public void testContains() {
+//        WeakArrayList<String> test = new WeakArrayList<String>(this.reference);
+//        assertEquals(this.reference, test);
+//
+//        // Test the content
+//		for(String elt : this.reference) {
+//			assertTrue(test.contains(elt));
+//		}
+//        assertEquals(this.reference, test);
+//
+//        // Remove elements
+//		ArrayList<String> removedElements = new ArrayList<String>();
+//		int originalSize = this.reference.size();
+//		Random rnd = new Random();
+//		int count = rnd.nextInt(this.reference.size()/4)+1;
+//		for(int i=0; i<count; i++) {
+//			int index = rnd.nextInt(this.reference.size());
+//			removedElements.add(this.reference.remove(index));			
+//		}
+//
+//		// Collects the objects
+//		collect(test);
+//
+//        // Test the content
+//		assertEquals(originalSize, test.size());
+//        assertNotEquals(this.reference, test);
+//		for(String elt : this.reference) {
+//			assertTrue(test.contains(elt));
+//		}
+//
+//        // Test the removed elements
+//		for(String elt : removedElements) {
+//			assertTrue(test.contains(elt));
+//		}
+//		
+//		// Clear the list of removed elements, which will cause collecting
+//		removedElements.clear();
+//
+//		// Collects the objects
+//		collect(test);
+//
+//        // Test the content
+//		assertEquals(this.reference.size(), test.size());
+//        assertEquals(this.reference, test);
+//		for(String elt : this.reference) {
+//			assertTrue(test.contains(elt));
+//		}
+//    }
+//
+//    public void testEquals() {
+//        WeakArrayList<String> test = new WeakArrayList<String>(this.reference);
+//        assertEquals(this.reference, test);
+//
+//        assertTrue(test.equals(this.reference));
+//        assertTrue(this.reference.equals(test));
+//
+//        // Remove elements
+//		ArrayList<String> removedElements = new ArrayList<String>();
+//		int originalSize = this.reference.size();
+//		Random rnd = new Random();
+//		int count = rnd.nextInt(this.reference.size()/4)+1;
+//		for(int i=0; i<count; i++) {
+//			int index = rnd.nextInt(this.reference.size());
+//			removedElements.add(this.reference.remove(index));			
+//		}
+//
+//		// Collects the objects
+//		collect(test);
+//
+//        // Test the content
+//		assertEquals(originalSize, test.size());
+//        assertNotEquals(this.reference, test);
+//        assertFalse(test.equals(this.reference));
+//        assertFalse(this.reference.equals(test));
+//
+//		// Clear the list of removed elements, which will cause collecting
+//		removedElements.clear();
+//
+//		// Collects the objects
+//		collect(test);
+//
+//        // Test the content
+//		assertEquals(this.reference.size(), test.size());
+//        assertEquals(this.reference, test);
+//        assertTrue(test.equals(this.reference));
+//        assertTrue(this.reference.equals(test));
+//    }
+//
+//    public void testIterator() {
+//    	WeakArrayList<String> test = new WeakArrayList<String>(this.reference);
+//    	assertEquals(this.reference, test);
+//	
+//        // Test the content
+//    	String s;
+//    	int idx=0;
+//    	Iterator<String> iter = test.iterator();
+//    	while (iter.hasNext()) {
+//    		s = iter.next();
+//    		assertEquals(this.reference.get(idx), s);
+//    		idx++;
+//    	}
+//
+//        // Remove elements
+//		ArrayList<String> baseElements = new ArrayList<String>(this.reference);
+//		Random rnd = new Random();
+//		int count = rnd.nextInt(this.reference.size()/4)+1;
+//		for(int i=0; i<count; i++) {
+//			int index = rnd.nextInt(this.reference.size());
+//			this.reference.remove(index);			
+//		}
+//
+//		// Collects the objects
+//		collect(test);
+//
+//        // Test the content
+//    	idx=0;
+//    	iter = test.iterator();
+//    	while (iter.hasNext()) {
+//    		s = iter.next();
+//    		assertEquals(baseElements.get(idx), s);
+//    		idx++;
+//    	}
+//
+//		// Clear the list of removed elements, which will cause collecting
+//		baseElements.clear();
+//
+//		// Collects the objects
+//		collect(test);
+//
+//        // Test the content
+//    	idx=0;
+//    	iter = test.iterator();
+//    	while (iter.hasNext()) {
+//    		s = iter.next();
+//    		assertEquals(this.reference.get(idx), s);
+//    		idx++;
+//    	}
+//    }
+//
+//	public void testContainsAll() {
+//    	WeakArrayList<String> test = new WeakArrayList<String>(this.reference);
+//    	assertEquals(this.reference, test);
+//	
+//        // Test the content
+//    	assertTrue(this.reference.containsAll(test));
+//    	assertTrue(test.containsAll(this.reference));
+//
+//        // Remove elements
+//		ArrayList<String> baseElements = new ArrayList<String>(this.reference);
+//		Random rnd = new Random();
+//		int count = rnd.nextInt(this.reference.size()/4)+1;
+//		for(int i=0; i<count; i++) {
+//			int index = rnd.nextInt(this.reference.size());
+//			this.reference.remove(index);			
+//		}
+//
+//		// Collects the objects
+//		collect(test);
+//
+//        // Test the content
+//    	assertFalse(this.reference.containsAll(test));
+//    	assertTrue(test.containsAll(this.reference));
+//
+//		// Clear the list of removed elements, which will cause collecting
+//		baseElements.clear();
+//
+//		// Collects the objects
+//		collect(test);
+//
+//        // Test the content
+//    	assertTrue(this.reference.containsAll(test));
+//    	assertTrue(test.containsAll(this.reference));
+//	}
+//    
+//	public void testToArray() {
+//    	WeakArrayList<String> test = new WeakArrayList<String>(this.reference);
+//    	assertEquals(this.reference, test);
+//	
+//        // Test the content
+//    	assertEquals(this.reference.toArray(),test.toArray());
+//
+//        // Remove elements
+//		ArrayList<String> baseElements = new ArrayList<String>(this.reference);
+//		Random rnd = new Random();
+//		int count = rnd.nextInt(this.reference.size()/4)+1;
+//		for(int i=0; i<count; i++) {
+//			int index = rnd.nextInt(this.reference.size());
+//			this.reference.remove(index);			
+//		}
+//
+//		// Collects the objects
+//		collect(test);
+//
+//        // Test the content
+//    	assertNotEquals(this.reference.toArray(),test.toArray());
+//
+//		// Clear the list of removed elements, which will cause collecting
+//		baseElements.clear();
+//
+//		// Collects the objects
+//		collect(test);
+//
+//        // Test the content
+//    	assertEquals(this.reference.toArray(),test.toArray());
+//	}
+//	public void testToArrayArray() {
+//    	WeakArrayList<String> test = new WeakArrayList<String>(this.reference);
+//    	assertEquals(this.reference, test);
+//    	
+//    	String[] tab1, tab2;
+//	
+//        // Test the content
+//    	tab1 = new String[this.reference.size()];
+//    	this.reference.toArray(tab1);
+//    	tab2 = new String[test.size()];
+//    	test.toArray(tab2);
+//    	assertEquals(tab1,tab2);
+//    	Arrays.fill(tab1, null);
+//    	Arrays.fill(tab2, null);
+//
+//        // Remove elements
+//		ArrayList<String> baseElements = new ArrayList<String>(this.reference);
+//		Collections.sort(baseElements);
+//		Random rnd = new Random();
+//		int count = rnd.nextInt(this.reference.size()/4)+1;
+//		for(int i=0; i<count; i++) {
+//			int index = rnd.nextInt(this.reference.size());
+//			this.reference.remove(index);			
+//		}
+//
+//		// Collects the objects
+//		collect(test);
+//
+//        // Test the content
+//    	tab1 = new String[this.reference.size()];
+//    	this.reference.toArray(tab1);
+//    	tab2 = new String[test.size()];
+//    	test.toArray(tab2);
+//    	assertNotEquals(tab1,tab2);
+//    	Arrays.fill(tab1, null);
+//    	Arrays.fill(tab2, null);
+//
+//		// Clear the list of removed elements, which will cause collecting
+//		baseElements.clear();
+//
+//		// Collects the objects
+//		collect(test);
+//
+//        // Test the content
+//    	tab1 = new String[this.reference.size()];
+//    	this.reference.toArray(tab1);
+//    	tab2 = new String[test.size()];
+//    	test.toArray(tab2);
+//    	assertEquals(tab1,tab2);
+//    	Arrays.fill(tab1, null);
+//    	Arrays.fill(tab2, null);
+//	}
+//
+//	public void testClear() {
+//    	WeakArrayList<String> test = new WeakArrayList<String>(this.reference);
+//        assertEquals(this.reference, test);
+//    	
+//        // Remove elements
+//    	test.clear();
+//
+//		// Collects the objects
+//		collect(test);
+//
+//    	assertTrue(test.isEmpty());
+//	}
+//
+//	public void testIndexOf() {
+//        WeakArrayList<String> test = new WeakArrayList<String>(this.reference);
+//        assertEquals(this.reference, test);
+//
+//        // Test the content
+//		Random rnd = new Random();
+//		int index;
+//		int count = rnd.nextInt(this.reference.size())+1;
+//		for(int i=0; i<count; i++) {
+//			index = rnd.nextInt(this.reference.size());
+//			assertEquals(index, test.indexOf(this.reference.get(index)));
+//		}
+//
+//        // Remove elements
+//		ArrayList<String> removedElements = new ArrayList<String>();
+//		count = rnd.nextInt(this.reference.size()/4)+1;
+//		int minIndex = Integer.MAX_VALUE;
+//		for(int i=0; i<count; i++) {
+//			index = rnd.nextInt(this.reference.size());
+//			if (index<minIndex) minIndex = index;
+//			removedElements.add(this.reference.remove(index));			
+//		}
+//
+//		// Collects the objects
+//		collect(test);
+//
+//        // Test the content
+//		count = rnd.nextInt(this.reference.size())+1;
+//		for(int i=0; i<count; i++) {
+//			index = rnd.nextInt(this.reference.size());
+//			if (index<minIndex)
+//				assertEquals(index, test.indexOf(this.reference.get(index)));
+//			else
+//				assertFalse(index==test.indexOf(this.reference.get(index)));
+//		}
+//
+//		// Clear the list of removed elements, which will cause collecting
+//		removedElements.clear();
+//
+//		// Collects the objects
+//		collect(test);
+//
+//        // Test the content
+//		count = rnd.nextInt(this.reference.size());
+//		for(int i=0; i<count; i++) {
+//			index = rnd.nextInt(this.reference.size());
+//			assertEquals(index, test.indexOf(this.reference.get(index)));
+//		}
+//	}
+//	
+//	public void testLastIndexOf() {
+//        WeakArrayList<String> test = new WeakArrayList<String>(this.reference);
+//        assertEquals(this.reference, test);
+//
+//        // Test the content
+//		Random rnd = new Random();
+//		int index;
+//		int count = rnd.nextInt(this.reference.size())+1;
+//		for(int i=0; i<count; i++) {
+//			index = rnd.nextInt(this.reference.size());
+//			assertEquals(index, test.lastIndexOf(this.reference.get(index)));
+//		}
+//
+//        // Remove elements
+//		ArrayList<String> removedElements = new ArrayList<String>();
+//		count = rnd.nextInt(this.reference.size()/4)+1;
+//		int minIndex = Integer.MAX_VALUE;
+//		for(int i=0; i<count; i++) {
+//			index = rnd.nextInt(this.reference.size());
+//			if (index<minIndex) minIndex = index;
+//			removedElements.add(this.reference.remove(index));			
+//		}
+//
+//		// Collects the objects
+//		collect(test);
+//
+//        // Test the content
+//		count = rnd.nextInt(this.reference.size())+1;
+//		for(int i=0; i<count; i++) {
+//			index = rnd.nextInt(this.reference.size());
+//			if (index<minIndex)
+//				assertEquals(index, test.lastIndexOf(this.reference.get(index)));
+//			else
+//				assertFalse(index==test.lastIndexOf(this.reference.get(index)));
+//		}
+//
+//		// Clear the list of removed elements, which will cause collecting
+//		removedElements.clear();
+//
+//		// Collects the objects
+//		collect(test);
+//
+//        // Test the content
+//		count = rnd.nextInt(this.reference.size());
+//		for(int i=0; i<count; i++) {
+//			index = rnd.nextInt(this.reference.size());
+//			assertEquals(index, test.lastIndexOf(this.reference.get(index)));
+//		}
+//	}
+//
+//	public void testGetInt() {
+//        WeakArrayList<String> test = new WeakArrayList<String>(this.reference);
+//        assertEquals(this.reference, test);
+//
+//        // Test the content
+//		Random rnd = new Random();
+//		int index;
+//		int count = rnd.nextInt(this.reference.size())+1;
+//		for(int i=0; i<count; i++) {
+//			index = rnd.nextInt(this.reference.size());
+//			assertEquals(this.reference.get(index), test.get(index));
+//		}
+//
+//        // Remove elements
+//		ArrayList<String> removedElements = new ArrayList<String>();
+//		count = rnd.nextInt(this.reference.size()/4)+1;
+//		int minIndex = Integer.MAX_VALUE;
+//		for(int i=0; i<count; i++) {
+//			index = rnd.nextInt(this.reference.size());
+//			if (index<minIndex) minIndex = index;
+//			removedElements.add(this.reference.remove(index));			
+//		}
+//
+//		// Collects the objects
+//		collect(test);
+//
+//        // Test the content
+//		count = rnd.nextInt(this.reference.size())+1;
+//		for(int i=0; i<count; i++) {
+//			index = rnd.nextInt(this.reference.size());
+//			if (index<minIndex)
+//				assertEquals(this.reference.get(index), test.get(index));
+//			else
+//				assertFalse(this.reference.get(index)==test.get(index));
+//		}
+//
+//		// Clear the list of removed elements, which will cause collecting
+//		removedElements.clear();
+//
+//		// Collects the objects
+//		collect(test);
+//
+//        // Test the content
+//		count = rnd.nextInt(this.reference.size());
+//		for(int i=0; i<count; i++) {
+//			index = rnd.nextInt(this.reference.size());
+//			assertEquals(this.reference.get(index), test.get(index));
+//		}
+//		
+//		assertException(test, "get", new Class<?>[] {int.class}, new Object[] {test.size()}); //$NON-NLS-1$
+//	}
+//	
+//	public void testAddE() {
+//        WeakArrayList<String> test = new WeakArrayList<String>(this.reference);
+//        assertEquals(this.reference, test);
+//        
+//        // Add an element
+//        String newElement = randomString();
+//        this.reference.add(newElement);
+//        test.add(newElement);
+//        assertEquals(this.reference, test);
+//        newElement = null;
+//
+//
+//        // Remove elements
+//		ArrayList<String> removedElements = new ArrayList<String>();
+//		Random rnd = new Random();
+//		int index, count = rnd.nextInt(this.reference.size()/4)+1;
+//		for(int i=0; i<count; i++) {
+//			index = rnd.nextInt(this.reference.size());
+//			removedElements.add(this.reference.remove(index));			
+//		}
+//
+//		// Collects the objects
+//		collect(test);
+//
+//		// Test content
+//        assertNotEquals(this.reference, test);
+//
+//		// Clear the list of removed elements, which will cause collecting
+//		removedElements.clear();
+//
+//		// Collects the objects
+//		collect(test);
+//
+//		// Test content
+//        assertEquals(this.reference, test);
+//        
+//        // Add a string without reference
+//        newElement = randomString();
+//        test.add(newElement);
+//        newElement = null;
+//        
+//		// Collects the objects
+//		collect(test);
+//		
+//		// Test content
+//        assertEquals(this.reference, test);        
+//	}
+//
+//	public void testAddIntE() {
+//        WeakArrayList<String> test = new WeakArrayList<String>(this.reference);
+//        assertEquals(this.reference, test);
+//        
+//        Random rnd = new Random();
+//        int index, testCount, count;
+//        String newElement, msg;
+//        
+//        testCount = rnd.nextInt(20)+5;
+//        
+//        for(int i=0; i<testCount; i++) {
+//        	msg = "test "+(i+1)+"/"+testCount; //$NON-NLS-1$ //$NON-NLS-2$
+//        	
+//	        // Add an element
+//	        newElement = randomString(10);
+//	        index = rnd.nextInt(this.reference.size());
+//	        this.reference.add(index, newElement);
+//	        test.add(index, newElement);
+//	        newElement = null;
+//
+//	        // Test elements
+//	        assertEquals(msg,this.reference, test);	
+//	
+//	        // Remove elements
+//			ArrayList<String> removedElements = new ArrayList<String>();
+//			count = rnd.nextInt(this.reference.size()/4)+1;
+//			for(int j=0; j<count; j++) {
+//				index = rnd.nextInt(this.reference.size());
+//				removedElements.add(this.reference.remove(index));			
+//			}
+//	
+//			// Collects the objects
+//			collect(test);
+//	
+//			// Test content
+//	        assertNotEquals(msg,this.reference, test);
+//	
+//			// Clear the list of removed elements, which will cause collecting
+//			removedElements.clear();
+//	
+//			// Collects the objects
+//			collect(test);
+//	
+//			// Test content
+//	        assertEquals(msg,this.reference, test);
+//	        
+//	        // Add a string without reference
+//	        newElement = randomString(10);
+//	        index = rnd.nextInt(test.size());
+//	        test.add(index, newElement);
+//	        newElement = null;
+//	        
+//			// Collects the objects
+//			collect(test);
+//			
+//			// Test content
+//	        assertEquals(msg,this.reference, test);
+//	        
+//        }
+//	}
+//
+//	public void testAddAllCollection() {
+//        WeakArrayList<String> test = new WeakArrayList<String>(this.reference);
+//        assertEquals(this.reference, test);
+//        
+//        // Add a set of elements
+//        ArrayList<String> newElements = new ArrayList<String>();
+//		Random rnd = new Random();
+//        int count =  rnd.nextInt(20)+5;
+//        for(int i=0; i<count; i++)
+//        	newElements.add(randomString(10));
+//        this.reference.addAll(newElements);
+//        test.addAll(newElements);
+//        assertEquals(this.reference, test);
+//        newElements.clear();
+//        newElements = null;
+//
+//        // Remove elements
+//		ArrayList<String> removedElements = new ArrayList<String>();
+//		int index;
+//		count = rnd.nextInt(this.reference.size()/4)+1;
+//		for(int i=0; i<count; i++) {
+//			index = rnd.nextInt(this.reference.size());
+//			removedElements.add(this.reference.remove(index));			
+//		}
+//
+//		// Collects the objects
+//		collect(test);
+//
+//		// Test content
+//        assertNotEquals(this.reference, test);
+//
+//		// Clear the list of removed elements, which will cause collecting
+//		removedElements.clear();
+//
+//		// Collects the objects
+//		collect(test);
+//
+//		// Test content
+//        assertEquals(this.reference, test);
+//        
+//        // Add a string without reference
+//        count =  rnd.nextInt(20)+5;
+//        for(int i=0; i<count; i++)
+//        	test.add(randomString(10));
+//        
+//		// Collects the objects
+//		collect(test);
+//		
+//		// Test content
+//        assertEquals(this.reference, test);        
+//	}
+//
+//	public void testAddAllIntCollection() {
+//        WeakArrayList<String> test = new WeakArrayList<String>(this.reference);
+//        assertEquals(this.reference, test);
+//
+//        String msg;
+//		Random rnd = new Random();
+//        int testCount = rnd.nextInt(20)+5;
+//        int index, count, insertionIndex;
+//        ArrayList<String> newElements;
+//        
+//        for(int i=0; i<testCount; i++) {
+//        	msg = "test "+(i+1)+"/"+testCount; //$NON-NLS-1$ //$NON-NLS-2$
+//	        insertionIndex = rnd.nextInt(this.reference.size());
+//
+//	        // Add a set of elements
+//	        newElements = new ArrayList<String>();
+//	        count =  rnd.nextInt(20)+5;
+//	        for(int j=0; j<count; j++) {
+//	        	newElements.add(randomString(10));
+//	        }
+//	        this.reference.addAll(insertionIndex,newElements);
+//	        test.addAll(insertionIndex,newElements);
+//	        newElements.clear();
+//	        newElements = null;
+//	        assertEquals(msg,this.reference, test);
+//	
+//	        // Remove elements
+//			ArrayList<String> removedElements = new ArrayList<String>();
+//			count = rnd.nextInt(this.reference.size()/4)+1;
+//			for(int j=0; j<count; j++) {
+//				index = rnd.nextInt(this.reference.size());
+//				removedElements.add(this.reference.remove(index));			
+//			}
+//	
+//			// Collects the objects
+//			collect(test);
+//	
+//			// Test content
+//	        assertNotEquals(msg,this.reference, test);
+//	
+//			// Clear the list of removed elements, which will cause collecting
+//			removedElements.clear();
+//	
+//			// Collects the objects
+//			collect(test);
+//	
+//			// Test content
+//	        assertEquals(msg,this.reference, test);
+//	        
+//	        // Add a string without reference
+//	        count =  rnd.nextInt(20)+5;
+//	        for(int j=0; j<count; j++)
+//	        	test.add(randomString(10));
+//	        
+//			// Collects the objects
+//			collect(test);
+//			
+//			// Test content
+//	        assertEquals(msg,this.reference, test);
+//        }
+//	}
+//
+//	public void testSetIntE() {
+//        String msg;
+//		Random rnd = new Random();
+//        int testCount = rnd.nextInt(20)+5;
+//        int index, count, insertionIndex;
+//        
+//        for(int i=0; i<testCount; i++) {
+//        	msg = "test "+(i+1)+"/"+testCount; //$NON-NLS-1$ //$NON-NLS-2$
+//        	spawnReference();
+//        	insertionIndex = rnd.nextInt(this.reference.size());
+//
+//	        WeakArrayList<String> test = new WeakArrayList<String>(this.reference);
+//	        assertEquals(this.reference, test);
+//        	
+//	        // Add an element
+//	        String newElement = randomString();
+//	        this.reference.set(insertionIndex,newElement);
+//	        test.set(insertionIndex,newElement);
+//	        newElement = null;
+//	        assertEquals(msg,this.reference, test);
+//	
+//	
+//	        // Remove elements
+//			ArrayList<String> removedElements = new ArrayList<String>();
+//			rnd = new Random();
+//			count = rnd.nextInt(this.reference.size()/4+1)+1;
+//			for(int j=0; j<count; j++) {
+//				index = rnd.nextInt(this.reference.size());
+//				removedElements.add(this.reference.remove(index));			
+//			}
+//	
+//			// Collects the objects
+//			collect(test);
+//	
+//			// Test content
+//	        assertNotEquals(msg,this.reference, test);
+//	
+//			// Clear the list of removed elements, which will cause collecting
+//			removedElements.clear();
+//	
+//			// Collects the objects
+//			collect(test);
+//	
+//			// Test content
+//	        assertEquals(msg,this.reference, test);
+//	        
+//	        // Add a string without reference
+//	        if (!test.isEmpty()) {
+//		        newElement = randomString();
+//		        insertionIndex = rnd.nextInt(test.size());
+//		        test.set(insertionIndex,newElement);
+//		        newElement = null;
+//	        }
+//	        
+//			// Collects the objects
+//			collect(test);
+//			
+//			// Test content
+//	        assertNotEquals(msg,this.reference, test);
+//        }
+//	}
+//
+//	public void testRemoveObject() {
+//        String msg;
+//		Random rnd = new Random();
+//        int testCount = rnd.nextInt(20)+5;
+//        int removalIndex;
+//        
+//        for(int i=0; i<testCount; i++) {
+//        	msg = "test "+(i+1)+"/"+testCount; //$NON-NLS-1$ //$NON-NLS-2$
+//        	spawnReference();
+//        	removalIndex = rnd.nextInt(this.reference.size());
+//
+//	        WeakArrayList<String> test = new WeakArrayList<String>(this.reference);
+//	        assertEquals(this.reference, test);
+//        	
+//	        // Remove elements
+//	        test.remove(this.reference.get(removalIndex));
+//	
+//			// Collects the objects
+//			collect(test);
+//	
+//			// Test content
+//	        assertNotEquals(msg,this.reference, test);
+//	
+//			// Clear the list of removed elements, which will cause collecting
+//			this.reference.remove(removalIndex);
+//	
+//			// Collects the objects
+//			collect(test);
+//	
+//			// Test content
+//	        assertEquals(msg,this.reference, test);
+//        }
+//	}
+//
+//	public void testRemoveInt() {
+//        String msg;
+//		Random rnd = new Random();
+//        int testCount = rnd.nextInt(20)+5;
+//        int removalIndex;
+//        
+//        for(int i=0; i<testCount; i++) {
+//        	msg = "test "+(i+1)+"/"+testCount; //$NON-NLS-1$ //$NON-NLS-2$
+//        	spawnReference();
+//        	removalIndex = rnd.nextInt(this.reference.size());
+//
+//	        WeakArrayList<String> test = new WeakArrayList<String>(this.reference);
+//	        assertEquals(this.reference, test);
+//        	
+//	        // Remove elements
+//	        test.remove(removalIndex);
+//	
+//			// Collects the objects
+//			collect(test);
+//	
+//			// Test content
+//	        assertNotEquals(msg,this.reference, test);
+//	
+//			// Clear the list of removed elements, which will cause collecting
+//			this.reference.remove(removalIndex);
+//	
+//			// Collects the objects
+//			collect(test);
+//	
+//			// Test content
+//	        assertEquals(msg,this.reference, test);
+//        }
+//	}
+//
+	/**
+	 */
+	public void testHashCode() {
+		List<String> reference = spawnReference();
+        WeakArrayList<String> test = new WeakArrayList<String>(reference);
+        assertEquals(reference, test);
+
+        assertEquals(reference.hashCode(),test.hashCode());
+
+        // Remove elements
+		reference.clear();
+
+		// Collects the objects
+		collect(test);
+
+        // Test the content
+        assertNotEquals(hashCode(), test.hashCode());
+    }
+	
+	/**
+	 */
+	public void testListener() {
+		Listener listener = new Listener();
+		WeakArrayList<String> list = new WeakArrayList<String>();
+		list.addReferenceListener(listener);
+		
+		Random rnd = new Random();
+		int count = rnd.nextInt(REFERENCE_SIZE+1)+5;
+		for(int i=0; i<count; i++) {
+			list.add(randomString());
+		}
+		
+		assertFalse(list.isEmpty());
+
+		collect(list);
+		
+		assertTrue(list.isEmpty());
+		assertEquals(count, listener.count);
+		
+	}
+	
+	private class Listener implements ReferenceListener {
+		
+		public int count = 0;
+		
+		public Listener() {
+			//
+		}
+
+		@Override
+		public void referenceReleased(int released) {
+			this.count += released;
+		}
+		
+	}
+    
+}

Added: tags/afc-2.0/arakhneRefs/src/test/java/org/arakhne/util/ref/WeakValueMapTest.java
===================================================================
--- tags/afc-2.0/arakhneRefs/src/test/java/org/arakhne/util/ref/WeakValueMapTest.java	                        (rev 0)
+++ tags/afc-2.0/arakhneRefs/src/test/java/org/arakhne/util/ref/WeakValueMapTest.java	2010-01-21 08:29:52 UTC (rev 117)
@@ -0,0 +1,399 @@
+/* $Id$
+ * 
+ * Copyright (C) 2007-09 St&eacute;phane GALLAND
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * This program is free software; you can redistribute it and/or modify
+ */
+package org.arakhne.util.ref;
+
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Random;
+import java.util.Map.Entry;
+
+import org.arakhne.junit.AbstractTestCase;
+
+/**
+* @author St&eacute;phane GALLAND &lt;galland@xxxxxxxxxxx&gt;
+* @version $Name$ $Revision$ $Date$
+*/
+public class WeakValueMapTest extends AbstractTestCase {
+
+	private static final int REFERENCE_SIZE = 0; 
+	
+	private final HashMap<String,String> reference = new HashMap<String,String>();
+	
+	private static void collect() {
+		System.gc();System.gc();System.gc();
+	}
+	
+	private void spawnReference() {
+		this.reference.clear();
+		Random rnd = new Random();
+		int count = rnd.nextInt(REFERENCE_SIZE+1)+5;
+		String str;
+		for(int i=0; i<count; i++) {
+			str = randomString(10);
+			this.reference.put(
+					Integer.toString(i)+str,
+					str);
+		}
+		str = null;
+	}
+	
+	private String getReferenceObject(int index) {
+		Object[] tab = this.reference.keySet().toArray();
+		return (String)tab[index];
+	}
+	
+	private Map<String,String> removeElementsFromReference() {
+		HashMap<String,String> removed = new HashMap<String,String>();
+		Random rnd = new Random();
+		int index;
+		int count = rnd.nextInt(this.reference.size()/4)+1;
+		String key, value;
+		for(int i=0; i<count; i++) {
+			index = rnd.nextInt(this.reference.size());
+			key = getReferenceObject(index);
+			value = this.reference.remove(key);
+			removed.put(key,value);
+		}
+		key = null;
+		value =  null;
+		return removed;
+	}
+	
+	@Override
+	public void setUp() {
+		spawnReference();
+	}
+	
+	@Override
+	public void tearDown() {
+		this.reference.clear();
+	}
+	
+	/**
+	 */
+    public void testEntryIterator() {
+    	WeakValueMap<String,String> test = new WeakValueMap<String,String>(this.reference);
+        test.setDeeplyExpurge(true);
+	
+        // Test the content
+    	{
+        	assertDeepSimilars(this.reference, test);
+    		Entry<String,String> e;
+        	Iterator<Entry<String,String>> iter = test.entrySet().iterator();
+        	while (iter.hasNext()) {
+        		e = iter.next();
+        		assertTrue(this.reference.containsKey(e.getKey()));
+        		assertEquals(this.reference.get(e.getKey()),this.reference.get(e.getKey()));
+        	}
+    	}
+
+    	{
+	        // Remove elements
+	    	Map<String,String> baseElements = new HashMap<String,String>(this.reference);
+	        removeElementsFromReference();
+	
+			// Collects the objects
+			collect();
+	
+	        // Test the content
+	    	{
+	    		assertNotDeepSimilars(this.reference, test);
+	    		Entry<String,String> e;
+	        	Iterator<Entry<String,String>> iter = test.entrySet().iterator();
+	        	while (iter.hasNext()) {
+	        		e = iter.next();
+	        		assertTrue(baseElements.containsKey(e.getKey()));
+	        		assertEquals(baseElements.get(e.getKey()),baseElements.get(e.getKey()));
+	        	}
+	    	}
+	
+			// Clear the list of removed elements, which will cause collecting
+			baseElements.clear();
+			baseElements = null;
+	
+			// Collects the objects
+			collect();
+			collect();
+    	}
+
+        // Test the content
+    	/*{
+        	assertDeepSimilars(this.reference, test);
+    		Entry<String,String> e;
+        	Iterator<Entry<String,String>> iter = test.entrySet().iterator();
+        	while (iter.hasNext()) {
+        		e = iter.next();
+        		assertTrue(this.reference.containsKey(e.getKey()));
+        		assertEquals(this.reference.get(e.getKey()),this.reference.get(e.getKey()));
+        	}
+    	}*/
+    }
+
+	/**
+	 */
+    public void testWeakValueMapMap() {
+        WeakValueMap<String,String> test = new WeakValueMap<String,String>(this.reference);
+        assertDeepSimilars(this.reference, test);
+    }
+
+	/**
+	 */
+    public void testSize() {
+        WeakValueMap<String,String> test = new WeakValueMap<String,String>();
+        assertEquals(0, test.size());
+        
+        test = new WeakValueMap<String,String>(this.reference);
+        test.setDeeplyExpurge(true);
+        assertEquals(this.reference.size(), test.size());
+
+        removeElementsFromReference();
+		
+		collect();
+		
+        assertEquals(this.reference.size(), test.size());		
+    }
+
+	/**
+	 */
+    public void testIsEmpty() {
+    	WeakValueMap<String,String> test = new WeakValueMap<String,String>();
+        assertTrue(test.isEmpty());
+        
+        test = new WeakValueMap<String,String>(this.reference);
+        test.setDeeplyExpurge(true);
+        assertFalse(test.isEmpty());
+        
+        removeElementsFromReference();
+
+		collect();
+		
+        assertFalse(test.isEmpty());
+        
+        this.reference.clear();
+
+		collect();
+		
+        assertTrue(test.isEmpty());
+    }
+	
+	/**
+	 */
+    public void testContainsKey() {
+    	WeakValueMap<String,String> test = new WeakValueMap<String,String>(this.reference);
+        test.setDeeplyExpurge(true);
+        assertDeepSimilars(this.reference, test);
+
+        // Test the content
+		{
+			String elt;
+			Iterator<String> iter = this.reference.keySet().iterator(); 
+			while (iter.hasNext()) {
+				elt = iter.next();
+				assertTrue(test.containsKey(elt));
+			}
+			elt = null;
+		}
+		assertDeepSimilars(this.reference, test);
+
+        Map<String,String> removedElements = removeElementsFromReference();
+        int originalSize = removedElements.size() + this.reference.size();
+
+		// Collects the objects
+		collect();
+
+        // Test the content
+		assertEquals(originalSize, test.size());
+		assertNotDeepSimilars(this.reference, test);
+		
+		// Clear the list of removed elements, which will cause collecting
+		removedElements.clear();
+		removedElements = null;
+
+		// Collects the objects
+		collect();
+		
+        // Test the content
+		assertEquals(this.reference.size(), test.size());
+		assertDeepSimilars(this.reference, test);
+		for(String elt : this.reference.keySet()) {
+			assertTrue(test.containsKey(elt));
+		}
+    }
+
+	/**
+	 */
+    public void testContainsValue() {
+    	WeakValueMap<String,String> test = new WeakValueMap<String,String>(this.reference);
+        test.setDeeplyExpurge(true);
+        assertDeepSimilars(this.reference, test);
+
+        // Test the content
+		{
+			String elt;
+			Iterator<String> iter = this.reference.values().iterator(); 
+			while (iter.hasNext()) {
+				elt = iter.next();
+				assertTrue(test.containsValue(elt));
+			}
+			elt = null;
+		}
+		assertDeepSimilars(this.reference, test);
+
+        Map<String,String> removedElements = removeElementsFromReference();
+        int originalSize = removedElements.size() + this.reference.size();
+
+		// Collects the objects
+		collect();
+
+        // Test the content
+		assertEquals(originalSize, test.size());
+		assertNotDeepSimilars(this.reference, test);
+		
+		// Clear the list of removed elements, which will cause collecting
+		removedElements.clear();
+		removedElements = null;
+
+		// Collects the objects
+		collect();
+		
+        // Test the content
+		assertEquals(this.reference.size(), test.size());
+		assertDeepSimilars(this.reference, test);
+		for(String elt : this.reference.values()) {
+			assertTrue(test.containsValue(elt));
+		}
+    }
+
+	/**
+	 */
+    public void testKeyIterator() {
+    	WeakValueMap<String,String> test = new WeakValueMap<String,String>(this.reference);
+        test.setDeeplyExpurge(true);
+	
+        // Test the content
+    	{
+        	assertDeepSimilars(this.reference, test);
+    		String k;
+        	Iterator<String> iter = test.keySet().iterator();
+        	while (iter.hasNext()) {
+        		k = iter.next();
+        		assertTrue(this.reference.containsKey(k));
+        	}
+    	}
+
+        // Remove elements
+    	Map<String,String> baseElements = new HashMap<String,String>(this.reference);
+        removeElementsFromReference();
+
+		// Collects the objects
+		collect();
+
+        // Test the content
+    	{
+        	assertNotDeepSimilars(this.reference, test);
+    		String k;
+        	Iterator<String> iter = test.keySet().iterator();
+        	while (iter.hasNext()) {
+        		k = iter.next();
+        		assertTrue(baseElements.containsKey(k));
+        	}
+    	}
+
+		// Clear the list of removed elements, which will cause collecting
+		baseElements.clear();
+		baseElements = null;
+
+		// Collects the objects
+		collect();
+
+        // Test the content
+    	{
+        	assertDeepSimilars(this.reference, test);
+    		String k;
+        	Iterator<String> iter = test.keySet().iterator();
+        	while (iter.hasNext()) {
+        		k = iter.next();
+        		assertTrue(this.reference.containsKey(k));
+        	}
+    	}
+    }
+
+	/**
+	 */
+    public void testValueIterator() {
+    	WeakValueMap<String,String> test = new WeakValueMap<String,String>(this.reference);
+        test.setDeeplyExpurge(true);
+	
+        // Test the content
+    	{
+        	assertDeepSimilars(this.reference, test);
+    		String v;
+        	Iterator<String> iter = test.values().iterator();
+        	while (iter.hasNext()) {
+        		v = iter.next();
+        		assertTrue(this.reference.containsValue(v));
+        	}
+        	v = null;
+        	iter = null;
+    	}
+
+        // Remove elements
+    	Map<String,String> baseElements = new HashMap<String,String>(this.reference);
+        removeElementsFromReference();
+
+		// Collects the objects
+		collect();
+
+        // Test the content
+    	{
+        	assertNotDeepSimilars(this.reference, test);
+    		String v;
+        	Iterator<String> iter = test.values().iterator();
+        	while (iter.hasNext()) {
+        		v = iter.next();
+        		assertTrue(baseElements.containsValue(v));
+        	}
+        	v = null;
+        	iter = null;
+    	}
+
+		// Clear the list of removed elements, which will cause collecting
+		baseElements.clear();
+		baseElements = null;
+
+		// Collects the objects
+		collect();
+
+        // Test the content
+    	{
+        	assertDeepSimilars(this.reference, test);
+    		String v;
+        	Iterator<String> iter = test.values().iterator();
+        	while (iter.hasNext()) {
+        		v = iter.next();
+        		assertTrue(this.reference.containsValue(v));
+        	}
+        	v = null;
+        	iter = null;
+    	}
+    }
+
+}

Added: tags/afc-2.0/arakhneVmutils/bin.xml
===================================================================
--- tags/afc-2.0/arakhneVmutils/bin.xml	                        (rev 0)
+++ tags/afc-2.0/arakhneVmutils/bin.xml	2010-01-21 08:29:52 UTC (rev 117)
@@ -0,0 +1,36 @@
+<assembly>
+  <formats>
+    <format>jar</format>
+  </formats>
+  <includeBaseDirectory>false</includeBaseDirectory>
+  <moduleSets>
+    <moduleSet>
+      <includeSubModules>false</includeSubModules>
+      <includes>
+        <include>org.arakhne.afc:arakhneVmutils-java</include>
+      </includes>
+      <binaries>
+        <outputDirectory></outputDirectory>
+        <unpack>true</unpack>
+	<includeDependencies>false</includeDependencies>
+      </binaries>
+    </moduleSet>
+  </moduleSets>
+  <files>
+    <file>
+      <source>native/josuuid/linux32/target/josuuid-linux32.so</source>
+      <outputDirectory>org/arakhne/vmutil</outputDirectory>
+      <destName>libjosuuid32.so</destName>
+    </file>
+    <file>
+      <source>native/josuuid/linux64/target/josuuid-linux64.so</source>
+      <outputDirectory>org/arakhne/vmutil</outputDirectory>
+      <destName>libjosuuid64.so</destName>
+    </file>
+    <file>
+      <source>native/josuuid/mingw/target/josuuid-mingw.dll</source>
+      <outputDirectory>org/arakhne/vmutil</outputDirectory>
+      <destName>josuuid32.dll</destName>
+    </file>
+  </files>
+</assembly>

Added: tags/afc-2.0/arakhneVmutils/java/pom.xml
===================================================================
--- tags/afc-2.0/arakhneVmutils/java/pom.xml	                        (rev 0)
+++ tags/afc-2.0/arakhneVmutils/java/pom.xml	2010-01-21 08:29:52 UTC (rev 117)
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"; xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"; xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd";>
+
+  <modelVersion>4.0.0</modelVersion>
+
+  <parent>
+	<artifactId>afc</artifactId>
+	<groupId>org.arakhne.afc</groupId>
+	<version>2.0</version>
+  </parent>
+
+  <artifactId>arakhneVmutils-java</artifactId>
+  <packaging>jar</packaging>
+  <groupId>org.arakhne.afc</groupId>
+  <version>4.2</version>
+  <name>${pom.artifactId}</name>
+
+	<!-- ======================================= -->
+	<!-- ====       Project Information      === -->
+	<!-- ======================================= -->
+		
+	<dependencies>
+		<dependency>
+			<groupId>junit</groupId>
+			<artifactId>junit</artifactId>
+			<scope>test</scope>
+		</dependency>
+	</dependencies>
+
+</project>

Added: tags/afc-2.0/arakhneVmutils/java/src/main/java/org/arakhne/vmutil/AutoboxingUtil.java
===================================================================
--- tags/afc-2.0/arakhneVmutils/java/src/main/java/org/arakhne/vmutil/AutoboxingUtil.java	                        (rev 0)
+++ tags/afc-2.0/arakhneVmutils/java/src/main/java/org/arakhne/vmutil/AutoboxingUtil.java	2010-01-21 08:29:52 UTC (rev 117)
@@ -0,0 +1,226 @@
+/* 
+ * $Id$
+ * 
+ * Copyright (C) 2004-2008 St&eacute;phane GALLAND
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * This program is free software; you can redistribute it and/or modify
+ */
+
+package org.arakhne.vmutil;
+
+/**
+ * This utility class provides a way to extend the Class class
+ * with autoboxing-compliant functions.
+ * 
+ * @author St&eacute;phane GALLAND &lt;galland@xxxxxxxxxxx&gt;
+ * @version $Name$ $Revision$ $Date$
+ * @since since JDK 1.5
+ * @deprecated see {@link ReflectionUtil}
+ */
+@Deprecated
+public class AutoboxingUtil {
+
+    /**
+     * Determines if the specified <code>Object</code> is assignment-compatible
+     * with the object represented by the <code>Class</code>.  This method extends
+     * {@link Class#isInstance(Object)} with autoboxing support.
+     *
+     * @param type is the class against which the object must be test
+     * @param obj is the object to check
+     * @return <code>true</code> if <code>obj</code> is an instance of the type
+     * @see Class#isInstance(Object)
+     */
+    public static boolean isInstance(Class<?> type, Object obj) {
+    	assert(type!=null);
+    	if (obj==null) return false;
+
+    	// Test according to the Class's behaviour
+    	if (type.isInstance(obj)) return true;
+    	
+    	// Test according to autoboxing
+    	if (type.isPrimitive()
+    			&&
+    			type!=Void.class && type!=void.class) {
+    		
+    		if (type==Boolean.class) return boolean.class.isInstance(obj);
+    		if (type==boolean.class) return Boolean.class.isInstance(obj);
+    		
+    		if (type==Character.class) return char.class.isInstance(obj);
+    		if (type==char.class) return Character.class.isInstance(obj);
+
+    		if (type==Byte.class) return byte.class.isInstance(obj);
+    		if (type==byte.class) return Byte.class.isInstance(obj);
+
+    		if (type==Short.class) return short.class.isInstance(obj);
+    		if (type==short.class) return Short.class.isInstance(obj);
+
+    		if (type==Integer.class) return int.class.isInstance(obj);
+    		if (type==int.class) return Integer.class.isInstance(obj);
+
+    		if (type==Long.class) return long.class.isInstance(obj);
+    		if (type==long.class) return Long.class.isInstance(obj);
+
+    		if (type==Float.class) return float.class.isInstance(obj);
+    		if (type==float.class) return Float.class.isInstance(obj);
+    		
+    		if (type==Double.class) return double.class.isInstance(obj);
+    		if (type==double.class) return Double.class.isInstance(obj);
+
+    		if (type==Void.class) return void.class.isInstance(obj);
+    		if (type==void.class) return Void.class.isInstance(obj);
+    		
+    		assert false: "Unsupported primitive type"; //$NON-NLS-1$
+    	}
+    	
+    	return false;
+    }
+
+
+    /**
+     * Determines if the <code>assignmentTarget</code> object is either the same as,
+     * or is a superclass or superinterface of, the class or interface 
+     * represented by the specified
+     * <code>assignementSource</code> parameter. This method extends
+     * {@link Class#isAssignableFrom(Class)} with autoboxing support.
+     * 
+     * @param assignementTarget is the class that is tested to be a super class.
+     * @param assignementSource is the class that is tested to be a sub class.
+     * @return <code>true</code> if an object of the <var>assignementSource</var> type
+     * could be assigned to a variable of <var>assignementTarget</var> type,
+     * otherwise <code>false</code>.
+     */
+    public static boolean isAssignableFrom(Class<?> assignementTarget, Class<?> assignementSource) {
+    	assert(assignementSource!=null);
+    	assert(assignementTarget!=null);
+    	
+    	// Test according to the Class's behaviour
+    	if (assignementTarget.isAssignableFrom(assignementSource)) return true;
+    	
+    	// Test according to autoboxing
+    	if (assignementTarget.isPrimitive() && assignementSource.isPrimitive()
+    			&&
+    			assignementTarget!=Void.class && assignementTarget!=void.class
+    			&&
+    			assignementSource!=Void.class && assignementSource!=void.class) {
+    		return true;
+    	}
+    	
+    	return false;
+    }
+
+	/** Replies the type that corresponds to the specified class.
+	 * If the name corresponds to a primitive type, the low-level type
+	 * will be replied.
+	 * This method extends
+     * {@link Class#forName(String)} with autoboxing support.
+	 * 
+	 * @param name is the name of the class to load.
+	 * @return the loaded class
+	 * @throws ClassNotFoundException  if name names an
+	 * unknown class or primitive
+	 */
+	public static Class<?> forName(String name) throws ClassNotFoundException {
+		if (name == null || "".equals(name) || "null".equals(name) || "void".equals(name)) { //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+			return void.class;
+		}
+		if ("boolean".equals(name)) { //$NON-NLS-1$
+			return boolean.class;
+		}
+		if ("byte".equals(name)) { //$NON-NLS-1$
+			return byte.class;
+		}
+		if ("char".equals(name)) { //$NON-NLS-1$
+			return char.class;
+		}
+		if ("double".equals(name)) { //$NON-NLS-1$
+			return double.class;
+		}
+		if ("float".equals(name)) { //$NON-NLS-1$
+			return float.class;
+		}
+		if ("int".equals(name)) { //$NON-NLS-1$
+			return int.class;
+		}
+		if ("long".equals(name)) { //$NON-NLS-1$
+			return long.class;
+		}
+		if ("short".equals(name)) { //$NON-NLS-1$
+			return short.class;
+		}
+		return Class.forName(name);
+	}
+
+	/** Replies the type that corresponds to the specified class.
+	 * If the name corresponds to a primitive type, the low-level type
+	 * will be replied.
+	 * This method extends
+     * {@link Class#forName(String)} with autoboxing support.
+	 * 
+	 * @param name is the name of the class to load.
+	 * @param loader is the class loader to use.
+	 * @return the loaded class
+	 * @throws ClassNotFoundException  if name names an
+	 * unknown class or primitive
+	 */
+	public static Class<?> forName(String name, ClassLoader loader) throws ClassNotFoundException {
+		return forName(name, true, loader);
+	}
+
+	/** Replies the type that corresponds to the specified class.
+	 * If the name corresponds to a primitive type, the low-level type
+	 * will be replied.
+	 * This method extends
+     * {@link Class#forName(String)} with autoboxing support.
+	 * 
+	 * @param name is the name of the class to load.
+	 * @param typeInitialization must be <code>true</code> to initialize the type, <code>false</code> otherwise.
+	 * @param loader is the class loader to use.
+	 * @return the loaded class
+	 * @throws ClassNotFoundException  if name names an
+	 * unknown class or primitive
+	 */
+	public static Class<?> forName(String name, boolean typeInitialization, ClassLoader loader) throws ClassNotFoundException {
+		if (name == null || "".equals(name) || "null".equals(name) || "void".equals(name)) { //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+			return void.class;
+		}
+		if ("boolean".equals(name)) { //$NON-NLS-1$
+			return boolean.class;
+		}
+		if ("byte".equals(name)) { //$NON-NLS-1$
+			return byte.class;
+		}
+		if ("char".equals(name)) { //$NON-NLS-1$
+			return char.class;
+		}
+		if ("double".equals(name)) { //$NON-NLS-1$
+			return double.class;
+		}
+		if ("float".equals(name)) { //$NON-NLS-1$
+			return float.class;
+		}
+		if ("int".equals(name)) { //$NON-NLS-1$
+			return int.class;
+		}
+		if ("long".equals(name)) { //$NON-NLS-1$
+			return long.class;
+		}
+		if ("short".equals(name)) { //$NON-NLS-1$
+			return short.class;
+		}
+		return Class.forName(name, typeInitialization, loader);
+	}
+
+}

Added: tags/afc-2.0/arakhneVmutils/java/src/main/java/org/arakhne/vmutil/Caller.java
===================================================================
--- tags/afc-2.0/arakhneVmutils/java/src/main/java/org/arakhne/vmutil/Caller.java	                        (rev 0)
+++ tags/afc-2.0/arakhneVmutils/java/src/main/java/org/arakhne/vmutil/Caller.java	2010-01-21 08:29:52 UTC (rev 117)
@@ -0,0 +1,79 @@
+/* 
+ * $Id$
+ * 
+ * Copyright (C) 2004-2008 St&eacute;phane GALLAND
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * This program is free software; you can redistribute it and/or modify
+ */
+
+package org.arakhne.vmutil;
+
+import sun.reflect.Reflection;
+
+/**
+ * This utility class provides a way to determine which class
+ * call a function.
+ * <p>
+ * It inspirated from the Sun's <code>sun.reflect.Reflection</code> class
+ * 
+ * @author St&eacute;phane GALLAND &lt;galland@xxxxxxxxxxx&gt;
+ * @version $Name:  $ $Revision: 1.1 $ $Date: 2007-04-25 13:08:07 $
+ */
+@SuppressWarnings("restriction")
+public class Caller {
+
+	/** Replies the class of the caller that invoked the function
+	 * from which <code>GetCallerClass()</code> was invoked.
+	 * 
+	 * @return the class of the caller that invoked the function
+	 * from which <code>GetCallerClass()</code> was invoked.
+	 */
+	public static Class<?> getCallerClass() {
+    	// Parameter value:
+    	// 0: is the top from the trace stack (Reflection.class)
+    	// 1: is the second top from the trace stack (Caller.class)
+    	// 2: is the third top of the trace stack ie, the caller of this function
+    	// 3: is the fourth top of the trace stack ie, the caller of invoked function in step 2
+		return Reflection.getCallerClass(3);
+	}
+	
+	/** Replies the class from the stack according to its level.
+	 * <p>
+	 * The given <var>level</var> permits to specify which class to reply:
+	 * <ul>
+	 * <li><code>0</code>: the class where is defined the function (<code>f<sub>0</sub></code>) 
+	 * that has called <code>getCallerClass()</code></li>
+	 * <li><code>1</code>: the class where is defined the function (<code>f<sub>1</sub></code>) 
+	 * that has called <code>f<sub>0</sub></code></li>
+	 * <li><code>1</code>: the class where is defined the function (<code>f<sub>2</sub></code>) 
+	 * that has called <code>f<sub>1</sub></code></li>
+	 * <li>etc.</li>
+	 * </ul>
+	 * 
+	 * @param level is the desired level of the class
+	 * @return the class from the call stack according to the given level.
+	 */
+	public static Class<?> getCallerClass(int level) {
+		if (level<0) throw new IllegalArgumentException();
+    	// Parameter value:
+    	// 0: is the top from the trace stack (Reflection.class)
+    	// 1: is the second top from the trace stack (Caller.class)
+    	// 2: is the third top of the trace stack ie, the caller of this function
+    	// 3: is the fourth top of the trace stack ie, the caller of invoked function in step 2
+		return Reflection.getCallerClass(level+2);
+	}
+
+}

Added: tags/afc-2.0/arakhneVmutils/java/src/main/java/org/arakhne/vmutil/ClassLoaderFinder.java
===================================================================
--- tags/afc-2.0/arakhneVmutils/java/src/main/java/org/arakhne/vmutil/ClassLoaderFinder.java	                        (rev 0)
+++ tags/afc-2.0/arakhneVmutils/java/src/main/java/org/arakhne/vmutil/ClassLoaderFinder.java	2010-01-21 08:29:52 UTC (rev 117)
@@ -0,0 +1,101 @@
+/* 
+ * $Id$
+ * 
+ * Copyright (C) 2004-2008 St&eacute;phane GALLAND
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * This program is free software; you can redistribute it and/or modify
+ */
+
+package org.arakhne.vmutil;
+
+/**
+ * This utility class permits to find the better class loader
+ * for your application.
+ * <p>
+ * It tries to find the preferred class loader registered with
+ * {@link #setPreferredClassLoader(ClassLoader)}.
+ * If none was found, the default class loader will be replied.
+ * 
+ * @author St&eacute;phane GALLAND &lt;galland@xxxxxxxxxxx&gt;
+ * @version $Name:  $ $Revision: 1.1 $ $Date: 2007-02-20 08:43:41 $
+ */
+public final class ClassLoaderFinder {
+
+	private static volatile ClassLoader __dyn_loader = null;
+	
+    /**
+     * Replies the better class loader.
+	 * <p>
+	 * It tries to find the preferred class loader.
+	 * If none was found, the default class loader will be replied.
+	 * 
+     * @return the class loader, never <code>null</code>
+     */
+    public static ClassLoader findClassLoader() {
+
+    	if (__dyn_loader==null)
+    		return ClassLoaderFinder.class.getClassLoader();
+    	return __dyn_loader;
+    }
+
+    /**
+     * Set the preferred class loader.
+	 * 
+     * @param class_loader is the preferred class loader
+     */
+    public static void setPreferredClassLoader(ClassLoader class_loader) {
+    	if (class_loader!=__dyn_loader) {
+	    	__dyn_loader = class_loader;
+	    	Thread[] threads = new Thread[Thread.activeCount()];
+	    	Thread.enumerate(threads);
+	    	for(Thread t : threads) {
+	    		if (t!=null)
+	    			t.setContextClassLoader(class_loader);
+	    	}
+    	}
+    }
+    
+    /**
+     * Pop the preferred class loader.
+     */
+    public static void popPreferredClassLoader() {
+    	ClassLoader sysLoader = ClassLoaderFinder.class.getClassLoader();
+    	
+    	if ((__dyn_loader==null)||
+    		(__dyn_loader==sysLoader)) {
+    		__dyn_loader = null;
+	    	Thread[] threads = new Thread[Thread.activeCount()];
+	    	Thread.enumerate(threads);
+	    	for(Thread t : threads) {
+	    		if (t!=null)
+	    			t.setContextClassLoader(sysLoader);
+	    	}
+    		return;
+    	}
+    	
+    	ClassLoader parent = __dyn_loader.getParent();
+    	
+    	__dyn_loader = (parent==sysLoader) ? null : parent;    	
+
+    	Thread[] threads = new Thread[Thread.activeCount()];
+    	Thread.enumerate(threads);
+    	for(Thread t : threads) {
+    		if (t!=null)
+    			t.setContextClassLoader(parent);
+    	}
+    }
+
+}

Added: tags/afc-2.0/arakhneVmutils/java/src/main/java/org/arakhne/vmutil/DynamicURLClassLoader.java
===================================================================
--- tags/afc-2.0/arakhneVmutils/java/src/main/java/org/arakhne/vmutil/DynamicURLClassLoader.java	                        (rev 0)
+++ tags/afc-2.0/arakhneVmutils/java/src/main/java/org/arakhne/vmutil/DynamicURLClassLoader.java	2010-01-21 08:29:52 UTC (rev 117)
@@ -0,0 +1,583 @@
+/* 
+ * $Id$
+ * 
+ * Copyright (C) 2004-2008 St&eacute;phane GALLAND
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * This program is free software; you can redistribute it and/or modify
+ */
+
+package org.arakhne.vmutil;
+
+import java.io.File;
+import java.io.FilePermission;
+import java.io.IOException;
+import java.net.JarURLConnection;
+import java.net.MalformedURLException;
+import java.net.SocketPermission;
+import java.net.URL;
+import java.net.URLConnection;
+import java.security.AccessControlContext;
+import java.security.AccessController;
+import java.security.CodeSigner;
+import java.security.CodeSource;
+import java.security.Permission;
+import java.security.PermissionCollection;
+import java.security.PrivilegedAction;
+import java.security.PrivilegedExceptionAction;
+import java.security.SecureClassLoader;
+import java.util.Arrays;
+import java.util.Enumeration;
+import java.util.HashSet;
+import java.util.NoSuchElementException;
+import java.util.jar.Attributes;
+import java.util.jar.Manifest;
+import java.util.jar.Attributes.Name;
+
+import sun.misc.Resource;
+import sun.misc.URLClassPath;
+import sun.net.www.ParseUtil;
+import sun.security.util.SecurityConstants;
+
+/** This class loader permits to load classes from
+ * a set of classpaths.
+ * 
+ * @author St&eacute;phane GALLAND &lt;galland@xxxxxxxxxxx&gt;
+ * @version $Name:  $ $Revision: 1.2 $ $Date: 2007-04-10 08:35:33 $
+ */
+@SuppressWarnings("restriction")
+public class DynamicURLClassLoader extends SecureClassLoader {
+
+	/**
+	 * The search path for classes and resources.
+	 */
+	protected URLClassPath _ucp;
+	
+	/**
+	 * The context to be used when loading classes and resources
+	 */
+	protected AccessControlContext _acc;
+	
+	/**
+	 * Constructs a new ClassPathClassLoader for the given URLs. The URLs will be
+	 * searched in the order specified for classes and resources after first
+	 * searching in the specified parent class loader. Any URL that ends with
+	 * a '/' is assumed to refer to a directory. Otherwise, the URL is assumed
+	 * to refer to a JAR file which will be downloaded and opened as needed.
+	 *
+	 * <p>If there is a security manager, this method first
+	 * calls the security manager's <code>checkCreateClassLoader</code> method
+	 * to ensure creation of a class loader is allowed.
+	 * 
+	 * @param parent the parent class loader for delegation
+	 * @param acc is the current access context
+	 * @param urls the URLs from which to load classes and resources
+	 * @exception  SecurityException  if a security manager exists and its  
+	 *             <code>checkCreateClassLoader</code> method doesn't allow 
+	 *             creation of a class loader.
+	 * @see SecurityManager#checkCreateClassLoader
+	 */
+	protected DynamicURLClassLoader(ClassLoader parent, AccessControlContext acc, URL... urls) {
+		super(parent);
+		// this is to make the stack depth consistent with 1.1
+		SecurityManager security = System.getSecurityManager();
+		if (security != null) {
+			security.checkCreateClassLoader();
+		}
+		this._ucp = new URLClassPath(mergeClassPath(urls));
+		this._acc = acc;
+	}
+	
+	/**
+	 * Appends the specified URL to the list of URLs to search for
+	 * classes and resources.
+	 *
+	 * @param url the URL to be added to the search path of URLs
+	 */
+	public void addURL(final URL url) {
+		AccessController.doPrivileged(new PrivilegedAction<Object>() {
+			public Object run() {
+				DynamicURLClassLoader.this._ucp.addURL(url);
+				return null;
+			}
+		}, this._acc);
+	}
+	
+	/**
+	 * Appends the specified URL to the list of URLs to search for
+	 * classes and resources.
+	 *
+	 * @param urls the URLs to be added to the search path of URLs
+	 */
+	public void addURLs(URL... urls) {
+		for (URL url : urls) {
+			addURL(url);
+		}
+	}
+
+	/**
+	 * Appends the specified URL to the list of URLs to search for
+	 * classes and resources.
+	 *
+	 * @param urls the URL to be added to the search path of URLs
+	 */
+	public void removeURLs(URL... urls) {
+		HashSet<URL> set = new HashSet<URL>();
+		set.addAll(Arrays.asList(this._ucp.getURLs()));
+		set.removeAll(Arrays.asList(urls));
+		URL[] tab = new URL[set.size()];
+		set.toArray(tab);
+		this._ucp = new URLClassPath(tab);
+		tab = null;
+	}
+
+	/**
+	 * Appends the specified URL to the list of URLs to search for
+	 * classes and resources.
+	 *
+	 * @param url the URL to be added to the search path of URLs
+	 */
+	public void removeURL(URL url) {
+		removeURLs(url);
+	}
+
+	/**
+	 * Returns the search path of URLs for loading classes and resources.
+	 * This includes the original list of URLs specified to the constructor,
+	 * along with any URLs subsequently appended by the addURL() method.
+	 * @return the search path of URLs for loading classes and resources.
+	 */
+	public URL[] getURLs() {
+		return this._ucp.getURLs();
+	}
+	
+	/**
+	 * Finds and loads the class with the specified name from the URL search
+	 * path. Any URLs referring to JAR files are loaded and opened as needed
+	 * until the class is found.
+	 *
+	 * @param name the name of the class
+	 * @return the resulting class
+	 * @exception ClassNotFoundException if the class could not be found
+	 */
+	@Override
+	protected Class<?> findClass(final String name) throws ClassNotFoundException {
+		try {
+			return AccessController.doPrivileged(new PrivilegedExceptionAction<Class<?>>() {
+				public Class<?> run() throws ClassNotFoundException {
+					String path = name.replace('.', '/').concat(".class"); //$NON-NLS-1$
+					Resource res = DynamicURLClassLoader.this._ucp.getResource(path, false);
+					if (res != null) {
+						try {
+							return defineClass(name, res);
+						}
+						catch (IOException e) {
+							throw new ClassNotFoundException(name, e);
+						}
+					}
+					throw new ClassNotFoundException(name);
+				}
+			}, this._acc);
+		}
+		catch (java.security.PrivilegedActionException pae) {
+			throw (ClassNotFoundException) pae.getException();
+		}
+	}
+	
+	/**
+	 * Defines a Class using the class bytes obtained from the specified
+	 * Resource. The resulting Class must be resolved before it can be
+	 * used.
+	 * 
+	 * @param name is the name of the class to define
+	 * @param res is the resource from which the class byte-code could be obtained
+	 * @return the loaded class.
+	 * @throws IOException in case the byte-code was unavailable.
+	 */
+	protected Class<?> defineClass(String name, Resource res) throws IOException {
+		int i = name.lastIndexOf('.');
+		URL url = res.getCodeSourceURL();
+		if (i != -1) {
+			String pkgname = name.substring(0, i);
+			// Check if package already loaded.
+			Package pkg = getPackage(pkgname);
+			Manifest man = res.getManifest();
+			if (pkg != null) {
+				// Package found, so check package sealing.
+				if (pkg.isSealed()) {
+					// Verify that code source URL is the same.
+					if (!pkg.isSealed(url)) {
+						throw new SecurityException(
+								"sealing violation: package " + pkgname + " is sealed"); //$NON-NLS-1$ //$NON-NLS-2$
+					}
+					
+				} else {
+					// Make sure we are not attempting to seal the package
+					// at this code source URL.
+					if ((man != null) && isSealed(pkgname, man)) {
+						throw new SecurityException(
+								"sealing violation: can't seal package " + pkgname +  //$NON-NLS-1$
+						": already loaded"); //$NON-NLS-1$
+					}
+				}
+			} else {
+				if (man != null) {
+					definePackage(pkgname, man, url);
+				} else {
+					definePackage(pkgname, null, null, null, null, null, null, null);
+				}
+			}
+		}
+		// Now read the class bytes and define the class
+		java.nio.ByteBuffer bb = res.getByteBuffer();
+		if (bb != null) {
+			// Use (direct) ByteBuffer:
+			CodeSigner[] signers = res.getCodeSigners();
+			CodeSource cs = new CodeSource(url, signers);
+			return defineClass(name, bb, cs);
+		}
+
+		byte[] b = res.getBytes();
+		// must read certificates AFTER reading bytes.
+		CodeSigner[] signers = res.getCodeSigners();
+		CodeSource cs = new CodeSource(url, signers);
+		return defineClass(name, b, 0, b.length, cs);
+
+	}
+	
+	/**
+	 * Defines a new package by name in this ClassLoader. The attributes
+	 * contained in the specified Manifest will be used to obtain package
+	 * version and sealing information. For sealed packages, the additional
+	 * URL specifies the code source URL from which the package was loaded.
+	 *
+	 * @param name  the package name
+	 * @param man   the Manifest containing package version and sealing
+	 *              information
+	 * @param url   the code source url for the package, or null if none
+	 * @exception   IllegalArgumentException if the package name duplicates
+	 *              an existing package either in this class loader or one
+	 *              of its ancestors
+	 * @return the newly defined Package object
+	 */
+	protected Package definePackage(String name, Manifest man, URL url)
+	throws IllegalArgumentException
+	{
+		String path = name.replace('.', '/').concat("/"); //$NON-NLS-1$
+		String specTitle = null, specVersion = null, specVendor = null;
+		String implTitle = null, implVersion = null, implVendor = null;
+		String sealed = null;
+		URL sealBase = null;
+		
+		Attributes attr = man.getAttributes(path);
+		if (attr != null) {
+			specTitle   = attr.getValue(Name.SPECIFICATION_TITLE);
+			specVersion = attr.getValue(Name.SPECIFICATION_VERSION);
+			specVendor  = attr.getValue(Name.SPECIFICATION_VENDOR);
+			implTitle   = attr.getValue(Name.IMPLEMENTATION_TITLE);
+			implVersion = attr.getValue(Name.IMPLEMENTATION_VERSION);
+			implVendor  = attr.getValue(Name.IMPLEMENTATION_VENDOR);
+			sealed      = attr.getValue(Name.SEALED);
+		}
+		attr = man.getMainAttributes();
+		if (attr != null) {
+			if (specTitle == null) {
+				specTitle = attr.getValue(Name.SPECIFICATION_TITLE);
+			}
+			if (specVersion == null) {
+				specVersion = attr.getValue(Name.SPECIFICATION_VERSION);
+			}
+			if (specVendor == null) {
+				specVendor = attr.getValue(Name.SPECIFICATION_VENDOR);
+			}
+			if (implTitle == null) {
+				implTitle = attr.getValue(Name.IMPLEMENTATION_TITLE);
+			}
+			if (implVersion == null) {
+				implVersion = attr.getValue(Name.IMPLEMENTATION_VERSION);
+			}
+			if (implVendor == null) {
+				implVendor = attr.getValue(Name.IMPLEMENTATION_VENDOR);
+			}
+			if (sealed == null) {
+				sealed = attr.getValue(Name.SEALED);
+			}
+		}
+		if ("true".equalsIgnoreCase(sealed)) { //$NON-NLS-1$
+			sealBase = url;
+		}
+		return definePackage(name, specTitle, specVersion, specVendor,
+				implTitle, implVersion, implVendor, sealBase);
+	}
+	
+	/*
+	 * Returns true if the specified package name is sealed according to the
+	 * given manifest.
+	 */
+	private boolean isSealed(String name, Manifest man) {
+		String path = name.replace('.', '/').concat("/"); //$NON-NLS-1$
+		Attributes attr = man.getAttributes(path);
+		String sealed = null;
+		if (attr != null) {
+			sealed = attr.getValue(Name.SEALED);
+		}
+		if (sealed == null) {
+			if ((attr = man.getMainAttributes()) != null) {
+				sealed = attr.getValue(Name.SEALED);
+			}
+		}
+		return "true".equalsIgnoreCase(sealed); //$NON-NLS-1$
+	}
+	
+	/**
+	 * Finds the resource with the specified name on the URL search path.
+	 *
+	 * @param name the name of the resource
+	 * @return a <code>URL</code> for the resource, or <code>null</code> 
+	 * if the resource could not be found.
+	 */
+	@Override
+	public URL findResource(final String name) {
+		/*
+		 * The same restriction to finding classes applies to resources
+		 */
+		URL url = 
+			AccessController.doPrivileged(new PrivilegedAction<URL>() {
+				public URL run() {
+					return DynamicURLClassLoader.this._ucp.findResource(name, true);
+				}
+			}, this._acc);
+		
+		return url != null ? this._ucp.checkURL(url) : null;
+	}
+	
+	/**
+	 * Returns an Enumeration of URLs representing all of the resources
+	 * on the URL search path having the specified name.
+	 *
+	 * @param name the resource name
+	 * @exception IOException if an I/O exception occurs
+	 * @return an <code>Enumeration</code> of <code>URL</code>s
+	 */
+	@Override
+	public Enumeration<URL> findResources(final String name) throws IOException {
+		final Enumeration<?> e = this._ucp.findResources(name, true);
+		
+		return new Enumeration<URL>() {
+			private URL url = null;
+			
+			private boolean next() {
+				if (this.url != null) {
+					return true;
+				}
+				do {
+					URL u = AccessController.doPrivileged(new PrivilegedAction<URL>() {
+						public URL run() {
+							if (!e.hasMoreElements())
+								return null;
+							return (URL)e.nextElement();
+						}
+					}, DynamicURLClassLoader.this._acc);
+					if (u == null) break;
+					this.url = DynamicURLClassLoader.this._ucp.checkURL(u);
+				}
+				while (this.url == null);
+				
+				return (this.url != null);
+			}
+			
+			public URL nextElement() {
+				if (!next()) {
+					throw new NoSuchElementException();
+				}
+				URL u = this.url;
+				this.url = null;
+				return u;
+			}
+			
+			public boolean hasMoreElements() {
+				return next();
+			}
+		};
+	}
+	
+	/**
+	 * Returns the permissions for the given codesource object.
+	 * The implementation of this method first calls super.getPermissions
+	 * and then adds permissions based on the URL of the codesource.
+	 * <p>
+	 * If the protocol is "file"
+	 * and the path specifies a file, then permission to read that
+	 * file is granted. If protocol is "file" and the path is
+	 * a directory, permission is granted to read all files
+	 * and (recursively) all files and subdirectories contained in
+	 * that directory.
+	 * <p>
+	 * If the protocol is not "file", then
+	 * to connect to and accept connections from the URL's host is granted.
+	 * @param codesource the codesource
+	 * @return the permissions granted to the codesource
+	 */
+	@Override
+	protected PermissionCollection getPermissions(CodeSource codesource) {
+		PermissionCollection perms = super.getPermissions(codesource);
+		
+		URL url = codesource.getLocation();
+		
+		Permission p;
+		URLConnection urlConnection;
+		
+		try {
+			urlConnection = url.openConnection();
+			p = urlConnection.getPermission();
+		}
+		catch (java.io.IOException ioe) {
+			p = null;
+			urlConnection = null;
+		}
+		
+		if ((p!=null)&&(p instanceof FilePermission)) {
+			// if the permission has a separator char on the end,
+			// it means the codebase is a directory, and we need
+			// to add an additional permission to read recursively
+			String path = p.getName();
+			if (path.endsWith(File.separator)) {
+				path += "-"; //$NON-NLS-1$
+				p = new FilePermission(path, SecurityConstants.FILE_READ_ACTION);
+			}
+		}
+		else if ((p == null) && (url.getProtocol().equals("file"))) { //$NON-NLS-1$
+			String path = url.getFile().replace('/', File.separatorChar);
+			path = ParseUtil.decode(path);
+			if (path.endsWith(File.separator))
+				path += "-"; //$NON-NLS-1$
+			p =  new FilePermission(path, SecurityConstants.FILE_READ_ACTION);
+		}
+		else {
+			URL locUrl = url;
+			if (urlConnection instanceof JarURLConnection) {
+				locUrl = ((JarURLConnection)urlConnection).getJarFileURL();
+			}
+			String host = locUrl.getHost();
+			if (host == null)
+				host = "localhost"; //$NON-NLS-1$
+			p = new SocketPermission(host,
+					SecurityConstants.SOCKET_CONNECT_ACCEPT_ACTION);
+		}
+		
+		// make sure the person that created this class loader
+		// would have this permission
+		
+		final SecurityManager sm = System.getSecurityManager();
+		if (sm != null) {
+			final Permission fp = p;
+			AccessController.doPrivileged(new PrivilegedAction<Object>() {
+				public Object run() throws SecurityException {
+					sm.checkPermission(fp);
+					return null;
+				}
+			}, this._acc);
+		}
+		perms.add(p);
+
+		return perms;
+	}
+	
+	/**
+	 * Creates a new instance of DynamicURLClassLoader for the specified
+	 * URLs and parent class loader. If a security manager is
+	 * installed, the <code>loadClass</code> method of the URLClassLoader
+	 * returned by this method will invoke the
+	 * <code>SecurityManager.checkPackageAccess</code> method before
+	 * loading the class.
+	 *
+	 * @param parent the parent class loader for delegation
+	 * @param urls the URLs to search for classes and resources
+	 * @return the resulting class loader
+	 */
+	public static DynamicURLClassLoader newInstance(final ClassLoader parent, final URL... urls) {
+		// Save the caller's context
+		final AccessControlContext acc = AccessController.getContext();
+		// Need a privileged block to create the class loader
+		DynamicURLClassLoader ucl =
+			AccessController.doPrivileged(new PrivilegedAction<DynamicURLClassLoader>() {
+				public DynamicURLClassLoader run() {
+					// Now set the context on the loader using the one we saved,
+					// not the one inside the privileged block...
+					return new FactoryDynamicURLClassLoader(parent, acc, urls);
+				}
+			});
+		return ucl;
+	}
+	
+    /**
+     * Merge the specified URLs to the current classpath.
+     */
+    private static URL[] mergeClassPath(URL... urls) {
+    	String path = System.getProperty("java.class.path"); //$NON-NLS-1$
+    	String separator = System.getProperty("path.separator"); //$NON-NLS-1$
+    	String[] parts = path.split(separator);
+    	URL[] u = new URL[parts.length+urls.length];
+    	for(int i=0; i<parts.length; i++) {
+    		try {
+				u[i] = new File(parts[i]).toURI().toURL();
+			}
+    		catch (MalformedURLException _) {
+				// ignore exception
+			}
+    	}
+    	System.arraycopy(urls,0,u,parts.length,urls.length);
+    	return u;
+    }
+
+    /** 
+     * @author St&eacute;phane GALLAND &lt;galland@xxxxxxxxxxx&gt;
+     * @version $Name:  $ $Revision: 1.2 $ $Date: 2007-04-10 08:35:33 $
+     */
+    protected final static class FactoryDynamicURLClassLoader extends DynamicURLClassLoader {
+
+    	/**
+    	 * @param parent is the parent class loader.
+    	 * @param acc is the accessible context.
+    	 * @param urls is the list of urls to insert inside the class loading path.
+    	 */
+    	protected FactoryDynamicURLClassLoader(ClassLoader parent, AccessControlContext acc, URL... urls) {
+    		super(parent,acc,urls);
+    	}
+    	
+    	/** {@inheritDoc}
+    	 * 
+    	 * @param name {@inheritDoc}
+    	 * @param resolve {@inheritDoc}
+    	 * @return {@inheritDoc}
+    	 * @throws ClassNotFoundException {@inheritDoc}
+    	 */
+    	@Override
+    	public final synchronized Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException {
+    		// First check if we have permission to access the package. This
+    		// should go away once we've added support for exported packages.
+    		SecurityManager sm = System.getSecurityManager();
+    		if (sm != null) {
+    			int i = name.lastIndexOf('.');
+    			if (i != -1) {
+    				sm.checkPackageAccess(name.substring(0, i));
+    			}
+    		}
+    		return super.loadClass(name, resolve);
+    	}
+    	
+    }
+
+}

Added: tags/afc-2.0/arakhneVmutils/java/src/main/java/org/arakhne/vmutil/DynamicURLStreamHandlerFactory.java
===================================================================
--- tags/afc-2.0/arakhneVmutils/java/src/main/java/org/arakhne/vmutil/DynamicURLStreamHandlerFactory.java	                        (rev 0)
+++ tags/afc-2.0/arakhneVmutils/java/src/main/java/org/arakhne/vmutil/DynamicURLStreamHandlerFactory.java	2010-01-21 08:29:52 UTC (rev 117)
@@ -0,0 +1,130 @@
+/* 
+ * $Id$
+ * 
+ * Copyright (C) 2010 St&eacute;phane GALLAND
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * This program is free software; you can redistribute it and/or modify
+ */
+package org.arakhne.vmutil;
+
+import java.net.URL;
+import java.net.URLStreamHandler;
+import java.net.URLStreamHandlerFactory;
+import java.util.Collections;
+import java.util.Map;
+import java.util.Set;
+import java.util.TreeMap;
+
+/**
+ * This class defines a factory for <code>URL</code> stream protocol handlers
+ * which is generic and extendable.
+ * <p>
+ * It is used by the <code>URL</code> class to create a
+ * <code>URLStreamHandler</code> for protocols.
+ * <p>
+ * To use this factory, invoke the following code only ONCE time:
+ * <code>URL.setURLStreamHandlerFactory(new GenericURLStreamHandlerFactory());</code>.
+ * <p>
+ * By default this factory known the following protocols:
+ * <ul>
+ * <li><code>file</code>: {@link FileURLStreamHandler}</li>
+ * <li><code>resource</code>: {@link ResourceURLStreamHandler}</li>
+ * </ul>
+ * 
+ * @author St&eacute;phane GALLAND &lt;galland@xxxxxxxxxxx&gt;
+ * @version $Name$ $Revision$ $Date$
+ * @see URLStreamHandlerFactory
+ * @see URL#setURLStreamHandlerFactory(URLStreamHandlerFactory)
+ */
+public class DynamicURLStreamHandlerFactory
+implements URLStreamHandlerFactory {
+
+	private final Map<String, Class<? extends URLStreamHandler>> handlers
+		= new TreeMap<String, Class<? extends URLStreamHandler>>();
+	
+	/**
+	 * Create an URLStreamHandler factory with default protocols.
+	 */
+	public DynamicURLStreamHandlerFactory() {
+		addHandler("file", FileURLStreamHandler.class); //$NON-NLS-1$
+		addHandler("resource", ResourceURLStreamHandler.class); //$NON-NLS-1$
+	}
+	
+	/**
+	 * {@inheritDoc}
+	 */
+	@Override
+	public URLStreamHandler createURLStreamHandler(String protocol) {
+		Class<? extends URLStreamHandler> handler = this.handlers.get(protocol.toLowerCase());
+		if (handler!=null) {
+			try {
+				return handler.newInstance();
+			}
+			catch (Throwable _) {
+				// Ignore errors.
+			}
+		}
+		// Force the default factory to retreive stream handler.
+		return null;
+	}
+	
+	/** Add an handler for the given protocol.
+	 * 
+	 * @param protocol is the protocol to register.
+	 * @param handler is the type of handler to instance when treating an URL with given protocol.
+	 * @return the handler previously binded to the given protocol, or <code>null</code>.
+	 */
+	public Class<? extends URLStreamHandler> addHandler(String protocol, Class<? extends URLStreamHandler> handler) {
+		return this.handlers.put(protocol.toLowerCase(), handler);
+	}
+
+	/** Remove handler for the given protocol.
+	 * 
+	 * @param protocol is the protocol to remove.
+	 * @return the handler previously binded to the given protocol, or <code>null</code>.
+	 */
+	public Class<? extends URLStreamHandler> removeHandler(String protocol) {
+		return this.handlers.remove(protocol.toLowerCase());
+	}
+
+	/** Replies handler for the given protocol.
+	 * 
+	 * @param protocol is the protocol to search for.
+	 * @return the handler binded to the given protocol, or <code>null</code>.
+	 */
+	public Class<? extends URLStreamHandler> getHandler(String protocol) {
+		return this.handlers.get(protocol.toLowerCase());
+	}
+
+	/** Replies if the given protocol is supported.
+	 * 
+	 * @param protocol is the protocol.
+	 * @return <code>true</code> if the given protocol is known, otherwise
+	 * <code>false</code>
+	 */
+	public boolean contains(String protocol) {
+		return this.handlers.containsKey(protocol.toLowerCase());
+	}
+	
+	/** Replies an unmodifiable set of the known protocols.
+	 * 
+	 * @return the known protocols
+	 */
+	public Set<String> getProtocols() {
+		return Collections.unmodifiableSet(this.handlers.keySet());
+	}
+
+}

Added: tags/afc-2.0/arakhneVmutils/java/src/main/java/org/arakhne/vmutil/ExternalizableResource.java
===================================================================
--- tags/afc-2.0/arakhneVmutils/java/src/main/java/org/arakhne/vmutil/ExternalizableResource.java	                        (rev 0)
+++ tags/afc-2.0/arakhneVmutils/java/src/main/java/org/arakhne/vmutil/ExternalizableResource.java	2010-01-21 08:29:52 UTC (rev 117)
@@ -0,0 +1,46 @@
+/* 
+ * $Id$
+ * 
+ * Copyright (C) 2005-2010 St&eacute;phane GALLAND
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * This program is free software; you can redistribute it and/or modify
+ */
+package org.arakhne.vmutil;
+
+import java.net.URL;
+
+/**
+ * Indicates that the object implementing this interface
+ * owns a external resource.
+ * 
+ * @author St&eacute;phane GALLAND &lt;galland@xxxxxxxxxxx&gt;
+ * @version $Name$ $Revision$ $Date$
+ */
+public interface ExternalizableResource {
+
+	/** Replies the URL where the resource data could be find.
+	 * 
+	 * @return the URL to the external resource.
+	 */
+	public URL getExternalizableResourceLocation();
+
+	/** Replies the MIME type of the external resource.
+	 * 
+	 * @return the MIME of the external resource.
+	 */
+	public String getExternalizableResourceType();
+
+}
\ No newline at end of file

Added: tags/afc-2.0/arakhneVmutils/java/src/main/java/org/arakhne/vmutil/FileSystem.java
===================================================================
--- tags/afc-2.0/arakhneVmutils/java/src/main/java/org/arakhne/vmutil/FileSystem.java	                        (rev 0)
+++ tags/afc-2.0/arakhneVmutils/java/src/main/java/org/arakhne/vmutil/FileSystem.java	2010-01-21 08:29:52 UTC (rev 117)
@@ -0,0 +1,1508 @@
+/* 
+ * $Id$
+ * 
+ * Copyright (C) 2004-2009 St&eacute;phane GALLAND
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * This program is free software; you can redistribute it and/or modify
+ */
+
+package org.arakhne.vmutil;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.net.MalformedURLException;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.net.URL;
+import java.net.URLConnection;
+import java.nio.channels.Channels;
+import java.nio.channels.FileChannel;
+import java.nio.channels.ReadableByteChannel;
+
+
+/** An utility class that permits to deal with filenames.
+ * 
+ * @author St&eacute;phane GALLAND &lt;galland@xxxxxxxxxxx&gt;
+ * @version $Name$ $Revision$ $Date$
+ */
+public class FileSystem {
+
+	/** Character used to specify a file extension.
+	 */
+	public static final char EXTENSION_SEPARATOR_CHAR = '.';
+	
+	/** String which is representing the current directory in a relative path.
+	 */
+	public static final String CURRENT_DIRECTORY = "."; //$NON-NLS-1$
+
+	/** String which is representing the parent directory in a relative path.
+	 */
+	public static final String PARENT_DIRECTORY = ".."; //$NON-NLS-1$
+
+	/** Character used to separate paths on an URL.
+	 */
+	public static final char URL_PATH_SEPARATOR_CHAR = '/';
+
+	/** Character used to separate paths on an URL.
+	 */
+	public static final String URL_PATH_SEPARATOR = "/"; //$NON-NLS-1$
+
+	/** String used to specify a file extension.
+	 */
+	public static final String EXTENSION_SEPARATOR = "."; //$NON-NLS-1$
+	
+	/** Prefix used to join in a Jar URL the jar filename and the inside-jar filename.
+	 */
+	public static final String JAR_URL_FILE_ROOT = "!/"; //$NON-NLS-1$
+
+	/** Replies if the given URL has a jar scheme.
+	 * 
+	 * @param url
+	 * @return <code>true</code> if the given URL uses a jar scheme.
+	 */
+	public static boolean isJarURL(URL url) {
+		return url!=null && "jar".equalsIgnoreCase(url.getProtocol()); //$NON-NLS-1$
+	}
+	
+	/** Replies the jar part of the jar-scheme URL.
+	 * 
+	 * @param url
+	 * @return the URL of the jar file in the given URL, or <code>null</code>
+	 * if the given URL does not use jar scheme.
+	 */
+	public static URL getJarURL(URL url) {
+		if (!isJarURL(url)) return null;
+		String path = url.getPath();
+		int idx = path.lastIndexOf(JAR_URL_FILE_ROOT);
+		if (idx>=0) path = path.substring(0, idx);
+		try {
+			return new URL(path);
+		}
+		catch(MalformedURLException _) {
+			return null;
+		}
+	}
+
+	/** Replies the file part of the jar-scheme URL.
+	 * 
+	 * @param url
+	 * @return the file in the given URL, or <code>null</code>
+	 * if the given URL does not use jar scheme.
+	 */
+	public static File getJarFile(URL url) {
+		if (isJarURL(url)) {
+			String path = url.getPath();
+			int idx = path.lastIndexOf(JAR_URL_FILE_ROOT);
+			if (idx>=0) return new File(path.substring(idx+1));
+		}
+		return null;
+	}
+
+	/** Replies the jar-schemed URL composed of the two given components.
+	 * 
+	 * @param jarFile is the URL to the jar file.
+	 * @param insideFile is the name of the file inside the jar.
+	 * @return the jar-schemed URL.
+	 * @throws MalformedURLException when the URL is malformed.
+	 */
+	public static URL toJarURL(File jarFile, File insideFile) throws MalformedURLException {
+		if (jarFile==null || insideFile==null) return null;
+		return toJarURL(jarFile, insideFile.getPath());
+	}
+
+	/** Replies the jar-schemed URL composed of the two given components.
+	 * 
+	 * @param jarFile is the URL to the jar file.
+	 * @param insideFile is the name of the file inside the jar.
+	 * @return the jar-schemed URL.
+	 * @throws MalformedURLException when the URL is malformed.
+	 */
+	public static URL toJarURL(File jarFile, String insideFile) throws MalformedURLException {
+		if (jarFile==null || insideFile==null) return null;
+		StringBuffer buf = new StringBuffer("jar:"); //$NON-NLS-1$
+		buf.append(jarFile.toURI().toURL().toExternalForm());
+		buf.append(JAR_URL_FILE_ROOT);
+		String path = insideFile.replace(File.separatorChar, URL_PATH_SEPARATOR_CHAR);
+		if (path.startsWith(URL_PATH_SEPARATOR)) {
+			buf.append(path.substring(URL_PATH_SEPARATOR.length()));
+		}
+		else {
+			buf.append(path);
+		}
+		return new URL(buf.toString());
+	}
+
+	/** Replies the jar-schemed URL composed of the two given components.
+	 * 
+	 * @param jarFile is the URL to the jar file.
+	 * @param insideFile is the name of the file inside the jar.
+	 * @return the jar-schemed URL.
+	 * @throws MalformedURLException when the URL is malformed.
+	 */
+	public static URL toJarURL(URL jarFile, File insideFile) throws MalformedURLException {
+		if (jarFile==null || insideFile==null) return null;
+		return toJarURL(jarFile, insideFile.getPath());
+	}
+
+	/** Replies the jar-schemed URL composed of the two given components.
+	 * 
+	 * @param jarFile is the URL to the jar file.
+	 * @param insideFile is the name of the file inside the jar.
+	 * @return the jar-schemed URL.
+	 * @throws MalformedURLException when the URL is malformed.
+	 */
+	public static URL toJarURL(URL jarFile, String insideFile) throws MalformedURLException {
+		if (jarFile==null || insideFile==null) return null;
+		StringBuffer buf = new StringBuffer("jar:"); //$NON-NLS-1$
+		buf.append(jarFile.toExternalForm());
+		buf.append(JAR_URL_FILE_ROOT);
+		String path = insideFile.replace(File.separatorChar, URL_PATH_SEPARATOR_CHAR);
+		if (path.startsWith(URL_PATH_SEPARATOR)) {
+			buf.append(path.substring(URL_PATH_SEPARATOR.length()));
+		}
+		else {
+			buf.append(path);
+		}
+		return new URL(buf.toString());
+	}
+	
+	/** Replies if the current operating system uses case-sensitive filename.
+	 * 
+	 * @return <code>true</code> if the filenames on the current file system are case sensitive,
+	 * otherwise <code>false</code>
+	 */
+	public static boolean isCaseSensitiveFilenameSystem() {
+		switch(OperatingSystem.getCurrentOS()) {
+		case AIX:
+		case BSD:
+		case FREEBSD:
+		case NETBSD:
+		case OPENBSD:
+		case LINUX:
+		case SOLARIS:
+		case HPUX:
+			return true;
+		case MACOSX:
+		case WIN:
+		case OTHER:
+		default:
+			return false;
+		}
+	}
+	
+	/** Replies the character used to separate the basename and the file extension.
+	 * 
+	 * @return the character used to separate the basename and the file extension.
+	 */
+	public static char getFileExtensionCharacter() {
+		return EXTENSION_SEPARATOR_CHAR;
+	}
+
+	/** Replies the dirname of the specified file.
+	 *
+	 * @param filename is the name to parse.
+	 * @return the dirname of the specified file.
+	 * @see #shortBasename(String)
+	 * @see #largeBasename(String)
+	 * @see #basename(String)
+	 * @see #extension(String)
+	 * @deprecated use {@link #extension(File)} or {@link #extension(URL)}
+	 */
+	@Deprecated
+	public static String dirname(String filename) {
+		if (filename==null) return null;
+		int idx = filename.lastIndexOf(File.separatorChar);
+		if (idx<0) return CURRENT_DIRECTORY;
+		if (idx==0) return File.separator;
+		return filename.substring(0,idx);
+	}
+
+	/** Replies the dirname of the specified file.
+	 *
+	 * @param filename is the name to parse.
+	 * @return the dirname of the specified file.
+	 * @see #shortBasename(File)
+	 * @see #largeBasename(File)
+	 * @see #basename(File)
+	 * @see #extension(File)
+	 */
+	public static File dirname(File filename) {
+		if (filename==null) return null;
+		return filename.getParentFile();
+	}
+
+	/** Replies the dirname of the specified file.
+	 *
+	 * @param filename is the name to parse.
+	 * @return the dirname of the specified file.
+	 * @see #shortBasename(URL)
+	 * @see #largeBasename(URL)
+	 * @see #basename(URL)
+	 * @see #extension(URL)
+	 */
+	public static URL dirname(URL filename) {
+		if (filename==null) return null;
+		
+		URL prefix = null;
+		String path;
+		if (isJarURL(filename)) {
+			prefix = getJarURL(filename);
+			path = getJarFile(filename).getPath();
+		}
+		else
+			path = filename.getPath();
+		
+		int idx = path.lastIndexOf(URL_PATH_SEPARATOR_CHAR);
+		if (idx==path.length()-1)
+			idx = path.lastIndexOf(URL_PATH_SEPARATOR_CHAR, path.length()-2);
+
+		path = (idx<0) ? URL_PATH_SEPARATOR : path.substring(0, idx+1);
+				
+		try {
+			if (prefix!=null) {
+				return toJarURL(prefix, path);
+			}
+			URI uri = new URI(
+					filename.getProtocol(), 
+					filename.getUserInfo(), 
+					filename.getHost(), 
+					filename.getPort(), 
+					path,
+					null,
+					null);
+			return uri.toURL();
+		}
+		catch (Throwable _) {
+			return null;
+		}
+	}
+
+	/** Replies the basename of the specified file with the extension.
+	 *
+	 * @param filename is the name to parse.
+	 * @return the basename of the specified file with the extension.
+	 */
+	public static String largeBasename(String filename) {
+		if (filename==null) return null;
+		int idx = filename.lastIndexOf(File.separatorChar);
+		return (idx<0) ? filename : filename.substring(idx+1);
+	}
+
+	/** Replies the basename of the specified file with the extension.
+	 *
+	 * @param filename is the name to parse.
+	 * @return the basename of the specified file with the extension.
+	 */
+	public static String largeBasename(File filename) {
+		if (filename==null) return null;
+		return filename.getName();
+	}
+
+	/** Replies the basename of the specified file with the extension.
+	 *
+	 * @param filename is the name to parse.
+	 * @return the basename of the specified file with the extension.
+	 */
+	public static String largeBasename(URL filename) {
+		if (filename==null) return null;
+		String fullPath = filename.getPath();
+		int idx = fullPath.lastIndexOf(URL_PATH_SEPARATOR_CHAR);
+		int end = fullPath.length();
+		if (idx==end-1) {
+			end --;
+			idx = fullPath.lastIndexOf(URL_PATH_SEPARATOR_CHAR, end-1);
+		}
+		if (idx<0) idx = -1;
+		return fullPath.substring(idx+1, end);
+	}
+
+	/** Reply the basename of the specified file without the last extension.
+	 *
+	 * @param filename is the name to parse.
+	 * @return the basename of the specified file without the last extension.
+	 * @see #shortBasename(String)
+	 * @see #largeBasename(String)
+	 * @see #dirname(String)
+	 * @see #extension(String)
+	 */
+	public static String basename(String filename) {
+		if (filename==null) return null;
+		int idx = filename.lastIndexOf(File.separatorChar);
+		String basename = (idx<0) ? filename : filename.substring(idx+1);
+		idx = basename.lastIndexOf(getFileExtensionCharacter());
+		if (idx<0) return basename;
+		return basename.substring(0,idx);
+	}
+
+	/** Reply the basename of the specified file without the last extension.
+	 *
+	 * @param filename is the name to parse.
+	 * @return the basename of the specified file without the last extension.
+	 * @see #shortBasename(File)
+	 * @see #largeBasename(File)
+	 * @see #dirname(File)
+	 * @see #extension(File)
+	 */
+	public static String basename(File filename) {
+		if (filename==null) return null;
+		String largeBasename = filename.getName();
+		int idx = largeBasename.lastIndexOf(getFileExtensionCharacter());
+		if (idx<=0) return largeBasename;
+		return largeBasename.substring(0,idx);
+	}
+
+	/** Reply the basename of the specified file without the last extension.
+	 *
+	 * @param filename is the name to parse.
+	 * @return the basename of the specified file without the last extension.
+	 * @see #shortBasename(URL)
+	 * @see #largeBasename(URL)
+	 * @see #dirname(URL)
+	 * @see #extension(URL)
+	 */
+	public static String basename(URL filename) {
+		if (filename==null) return null;
+		String largeBasename = filename.getPath();
+		int idx = largeBasename.lastIndexOf(URL_PATH_SEPARATOR_CHAR);
+		int end = largeBasename.length();
+		if (idx==end-1) {
+			end --;
+			idx = largeBasename.lastIndexOf(URL_PATH_SEPARATOR_CHAR, end-1);
+		}
+		if (idx<0) idx = -1;
+		largeBasename = largeBasename.substring(idx+1, end);
+		idx = largeBasename.lastIndexOf(getFileExtensionCharacter());
+		if (idx<0) return largeBasename;
+		return largeBasename.substring(0,idx);
+	}
+
+	/** Reply the basename of the specified file without all the extensions.
+	 *
+	 * @param filename is the name to parse.
+	 * @return the basename of the specified file without all the extensions.
+	 */
+	public static String shortBasename(String filename) {
+		if (filename==null) return null;
+		int idx = filename.lastIndexOf(File.separatorChar);
+		String basename = (idx<0) ? filename : filename.substring(idx+1);
+		idx = basename.indexOf(getFileExtensionCharacter());
+		if (idx<0) return basename;
+		return basename.substring(0,idx);
+	}
+
+	/** Reply the basename of the specified file without all the extensions.
+	 *
+	 * @param filename is the name to parse.
+	 * @return the basename of the specified file without all the extensions.
+	 */
+	public static String shortBasename(File filename) {
+		if (filename==null) return null;
+		String largeBasename = filename.getName();
+		int idx = largeBasename.indexOf(getFileExtensionCharacter());
+		if (idx<0) return largeBasename;
+		return largeBasename.substring(0,idx);
+	}
+
+	/** Reply the basename of the specified file without all the extensions.
+	 *
+	 * @param filename is the name to parse.
+	 * @return the basename of the specified file without all the extensions.
+	 */
+	public static String shortBasename(URL filename) {
+		if (filename==null) return null;
+		String largeBasename = filename.getPath();
+		int idx = largeBasename.lastIndexOf(URL_PATH_SEPARATOR_CHAR);
+		int end = largeBasename.length();
+		if (idx==end-1) {
+			end --;
+			idx = largeBasename.lastIndexOf(URL_PATH_SEPARATOR_CHAR, end-1);
+		}
+		if (idx<0) idx = -1;
+		largeBasename = largeBasename.substring(idx+1, end);
+		idx = largeBasename.indexOf(getFileExtensionCharacter());
+		if (idx<0) return largeBasename;
+		return largeBasename.substring(0,idx);
+	}
+
+	/** Reply the extension of the specified file.
+	 *
+	 * @param filename is the name to parse.
+	 * @return the extension of the specified file
+	 * @deprecated use {@link #extension(File)} or {@link #extension(URL)}
+	 * @see #shortBasename(String)
+	 * @see #largeBasename(String)
+	 * @see #basename(String)
+	 * @see #dirname(String)
+	 * @see #extensions(String)
+	 */
+	@Deprecated
+	public static String extension(String filename) {
+		try {
+			return extension(new URL(filename));
+		}
+		catch(MalformedURLException _) {
+			return extension(new File(filename));
+		}
+	}
+	
+	/** Reply the extension of the specified file.
+	 *
+	 * @param filename is the name to parse.
+	 * @return the extension of the specified file
+	 * @see #shortBasename(File)
+	 * @see #largeBasename(File)
+	 * @see #basename(File)
+	 * @see #dirname(File)
+	 * @see #extensions(File)
+	 */
+	public static String extension(File filename) {
+		if (filename==null) return null;
+		String largeBasename = largeBasename(filename);
+		int idx = largeBasename.lastIndexOf(getFileExtensionCharacter());
+		if (idx<=0) return ""; //$NON-NLS-1$
+		return largeBasename.substring(idx);
+	}
+
+	/** Reply the extension of the specified file.
+	 *
+	 * @param filename is the name to parse.
+	 * @return the extension of the specified file
+	 * @see #shortBasename(URL)
+	 * @see #largeBasename(URL)
+	 * @see #basename(URL)
+	 * @see #dirname(URL)
+	 * @see #extensions(URL)
+	 */
+	public static String extension(URL filename) {
+		if (filename==null) return null;
+		String largeBasename = largeBasename(filename);
+		int idx = largeBasename.lastIndexOf(getFileExtensionCharacter());
+		if (idx<=0) return ""; //$NON-NLS-1$
+		return largeBasename.substring(idx);
+	}
+
+	/** Reply all the extensions of the specified file.
+	 *
+	 * @param filename is the name to parse.
+	 * @return the extensions of the specified file
+	 * @deprecated use {@link #extensions(File)} or {@link #extensions(URL)}
+	 */
+	@Deprecated
+	public static String[] extensions(String filename) {
+		try {
+			return extensions(new URL(filename));
+		}
+		catch(MalformedURLException _) {
+			return extensions(new File(filename));
+		}
+	}
+
+	/** Reply all the extensions of the specified file.
+	 *
+	 * @param filename is the name to parse.
+	 * @return the extensions of the specified file
+	 */
+	public static String[] extensions(File filename) {
+		if (filename==null) return new String[0];
+		String largeBasename = largeBasename(filename);
+		String[] parts = largeBasename.split("["+getFileExtensionCharacter()+"]"); //$NON-NLS-1$ //$NON-NLS-2$
+		if (parts.length<=1) return new String[0];
+		String[] r = new String[parts.length-1];
+		System.arraycopy(parts, 1, r, 0, r.length);
+		return r;
+	}
+
+	/** Reply all the extensions of the specified file.
+	 *
+	 * @param filename is the name to parse.
+	 * @return the extensions of the specified file
+	 */
+	public static String[] extensions(URL filename) {
+		if (filename==null) return new String[0];
+		String largeBasename = largeBasename(filename);
+		String[] parts = largeBasename.split("["+getFileExtensionCharacter()+"]"); //$NON-NLS-1$ //$NON-NLS-2$
+		if (parts.length<=1) return new String[0];
+		String[] r = new String[parts.length-1];
+		System.arraycopy(parts, 1, r, 0, r.length);
+		return r;
+	}
+
+	/** Replies the parts of a path.
+	 *
+	 * @param filename is the name to parse.
+	 * @return the parts of a path.
+	 * @deprecated use {@link #split(File)} or {@link #split(URL)}
+	 */
+	@Deprecated
+	public static String[] split(String filename) {
+		try {
+			return split(new URL(filename));
+		}
+		catch(MalformedURLException _) {
+			return split(new File(filename));
+		}
+	}
+
+	/** Replies the parts of a path.
+	 *
+	 * @param filename is the name to parse.
+	 * @return the parts of a path.
+	 */
+	public static String[] split(File filename) {
+		if (filename==null) return new String[0];
+		return filename.getPath().split("["+File.separatorChar+"]"); //$NON-NLS-1$ //$NON-NLS-2$
+	}
+
+	/** Replies the parts of a path.
+	 *
+	 * @param filename is the name to parse.
+	 * @return the parts of a path.
+	 */
+	public static String[] split(URL filename) {
+		if (filename==null) return new String[0];
+		String path;
+		if (isJarURL(filename))
+			path = getJarFile(filename).getPath();
+		else
+			path = filename.getPath();
+		return path.split("["+URL_PATH_SEPARATOR_CHAR+"]"); //$NON-NLS-1$ //$NON-NLS-2$
+	}
+
+	/** Join the parts of a path with the current OS directory separator.
+	 *
+	 * @param elements are the path's elements to join.
+	 * @return the result of the join of the path's elements.
+	 * @deprecated use {@link #split(File)} or {@link #split(URL)}
+	 */
+	@Deprecated
+	public static String join(String... elements) {
+		StringBuffer buf = new StringBuffer();
+		boolean first = true;
+		boolean empty;
+		for(String elt : elements) {
+			empty = (elt==null || elt.length()==0);
+			if (first && empty) {
+				buf.append(File.separatorChar);
+			}
+			else if (!empty) {
+				if (buf.length()>0 && buf.charAt(buf.length()-1)!=File.separatorChar)
+					buf.append(File.separatorChar);
+				buf.append(elt);
+			}
+			first = false;
+		}
+		return buf.toString();
+	}
+	
+	/** Join the parts of a path and append them to the given File.
+	 *
+	 * @param fileBase is the file to put as prefix.
+	 * @param elements are the path's elements to join.
+	 * @return the result of the join of the path's elements.
+	 */
+	public static File join(File fileBase, String... elements) {
+		if (fileBase==null) return null;
+		StringBuffer buf = new StringBuffer(fileBase.getPath());
+		boolean empty;
+		for(String elt : elements) {
+			empty = (elt==null || elt.length()==0);
+			if (!empty) {
+				assert(elt!=null);
+				if (!elt.startsWith(File.separator) 
+					&& buf.length()>=0
+					&& buf.charAt(buf.length()-1)!=File.separatorChar) {
+					buf.append(File.separatorChar);
+				}
+				buf.append(elt);
+			}
+		}
+		return new File(buf.toString());
+	}
+
+	/** Join the parts of a path and append them to the given File.
+	 *
+	 * @param fileBase is the file to put as prefix.
+	 * @param elements are the path's elements to join.
+	 * @return the result of the join of the path's elements.
+	 */
+	public static File join(File fileBase, File... elements) {
+		if (fileBase==null) return null;
+		StringBuffer buf = new StringBuffer(fileBase.getPath());
+		for(File elt : elements) {
+			if (!elt.isAbsolute()) {
+				if (buf.length()>=0 && buf.charAt(buf.length()-1)!=File.separatorChar) {
+					buf.append(File.separatorChar);
+				}
+			}
+			buf.append(elt.getPath());
+		}
+		return new File(buf.toString());
+	}
+
+	/** Join the parts of a path and append them to the given URL.
+	 *
+	 * @param urlBase is the url to put as prefix.
+	 * @param elements are the path's elements to join.
+	 * @return the result of the join of the path's elements.
+	 */
+	public static URL join(URL urlBase, String... elements) {
+		if (urlBase==null) return null;
+		StringBuffer buf = new StringBuffer(urlBase.getPath());
+		boolean empty;
+		for(String elt : elements) {
+			empty = (elt==null || elt.length()==0);
+			if (!empty) {
+				assert(elt!=null);
+				if (!elt.startsWith(File.separator) 
+					&& (buf.length()==0
+						|| buf.charAt(buf.length()-1)!=URL_PATH_SEPARATOR_CHAR)) {
+					buf.append(URL_PATH_SEPARATOR_CHAR);
+				}
+				buf.append(elt);
+			}
+		}
+		try {
+			if (isJarURL(urlBase)) {
+				return new URL(
+						urlBase.getProtocol(), 
+						urlBase.getHost(), 
+						urlBase.getPort(),
+						buf.toString());
+			}
+			URI uri = new URI(
+					urlBase.getProtocol(), 
+					urlBase.getUserInfo(), 
+					urlBase.getHost(), 
+					urlBase.getPort(), 
+					buf.toString(),
+					urlBase.getQuery(),
+					urlBase.getRef());
+			return uri.toURL();
+		}
+		catch (Throwable _) {
+			return null;
+		}
+	}
+
+	/** Join the parts of a path and append them to the given URL.
+	 *
+	 * @param urlBase is the url to put as prefix.
+	 * @param elements are the path's elements to join.
+	 * @return the result of the join of the path's elements.
+	 */
+	public static URL join(URL urlBase, File... elements) {
+		if (urlBase==null) return null;
+		StringBuffer buf = new StringBuffer(urlBase.getPath());
+		for(File elt : elements) {
+			if (!elt.isAbsolute()) {
+				if (buf.length()==0 || buf.charAt(buf.length()-1)!=URL_PATH_SEPARATOR_CHAR) {
+					buf.append(URL_PATH_SEPARATOR_CHAR);
+				}
+			}
+			buf.append(elt.getPath());
+		}
+		try {
+			if (isJarURL(urlBase)) {
+				return new URL(
+						urlBase.getProtocol(), 
+						urlBase.getHost(), 
+						urlBase.getPort(),
+						buf.toString());
+			}
+			URI uri = new URI(
+					urlBase.getProtocol(), 
+					urlBase.getUserInfo(), 
+					urlBase.getHost(), 
+					urlBase.getPort(), 
+					buf.toString(),
+					urlBase.getQuery(),
+					urlBase.getRef());
+			return uri.toURL();
+		}
+		catch (Throwable _) {
+			return null;
+		}
+	}
+
+	/** Replies if the specified file has the specified extension.
+	 * <p>
+	 * The test is dependent of the case-sensitive attribute of operating system.
+	 * 
+	 * @param filename is the filename to parse
+	 * @param extension is the extension to test.
+	 * @return <code>true</code> if the given filename has the given extension,
+	 * otherwise <code>false</code>
+	 * @deprecated use {@link #hasExtension(File,String)} or {@link #hasExtension(URL,String)}
+	 */
+	@Deprecated
+	public static boolean hasExtension(String filename, String extension) {
+		try {
+			return hasExtension(new URL(filename), extension);
+		}
+		catch(MalformedURLException _) {
+			return hasExtension(new File(filename), extension);
+		}
+	}
+
+	/** Replies if the specified file has the specified extension.
+	 * <p>
+	 * The test is dependent of the case-sensitive attribute of operating system.
+	 * 
+	 * @param filename is the filename to parse
+	 * @param extension is the extension to test.
+	 * @return <code>true</code> if the given filename has the given extension,
+	 * otherwise <code>false</code>
+	 */
+	public static boolean hasExtension(File filename, String extension) {
+		if (filename==null) return false;
+		String extent = extension;
+		if (!"".equals(extent) && !extent.startsWith(EXTENSION_SEPARATOR)) //$NON-NLS-1$
+			extent = EXTENSION_SEPARATOR+extent;
+		String ext = extension(filename);
+		if (ext==null) return false;
+		if (isCaseSensitiveFilenameSystem())
+			return ext.equals(extent);
+		return ext.equalsIgnoreCase(extent);
+	}
+
+	/** Replies if the specified file has the specified extension.
+	 * <p>
+	 * The test is dependent of the case-sensitive attribute of operating system.
+	 * 
+	 * @param filename is the filename to parse
+	 * @param extension is the extension to test.
+	 * @return <code>true</code> if the given filename has the given extension,
+	 * otherwise <code>false</code>
+	 */
+	public static boolean hasExtension(URL filename, String extension) {
+		if (filename==null) return false;
+		String extent = extension;
+		if (!"".equals(extent) && !extent.startsWith(EXTENSION_SEPARATOR)) //$NON-NLS-1$
+			extent = EXTENSION_SEPARATOR+extent;
+		String ext = extension(filename);
+		if (ext==null) return false;
+		if (isCaseSensitiveFilenameSystem())
+			return ext.equals(extent);
+		return ext.equalsIgnoreCase(extent);
+	}
+
+	/** Remove the extension from the specified filename.
+	 * 
+	 * @param filename is the filename to parse.
+	 * @return the filename without the extension.
+	 * @deprecated use {@link #removeExtension(File)} or {@link #removeExtension(URL)}
+	 */
+	@Deprecated
+	public static String removeExtension(String filename) {
+		try {
+			return removeExtension(new URL(filename)).toExternalForm();
+		}
+		catch(MalformedURLException _) {
+			return removeExtension(new File(filename)).getPath();
+		}
+	}
+
+	/** Remove the extension from the specified filename.
+	 * 
+	 * @param filename is the filename to parse.
+	 * @return the filename without the extension.
+	 */
+	public static File removeExtension(File filename) {
+		if (filename==null) return null;
+		File dir = filename.getParentFile();
+		String name = filename.getName();
+		int idx = name.lastIndexOf(getFileExtensionCharacter());
+		if (idx<0) return filename;
+		return new File(dir, name.substring(0,idx));
+	}
+
+	/** Remove the extension from the specified filename.
+	 * 
+	 * @param filename is the filename to parse.
+	 * @return the filename without the extension.
+	 */
+	public static URL removeExtension(URL filename) {
+		if (filename==null) return null;
+		String path = filename.getPath();
+		int idx = path.lastIndexOf(URL_PATH_SEPARATOR);
+		StringBuffer buf = new StringBuffer((idx<0) ? "" : path.substring(0, idx+1)); //$NON-NLS-1$
+		String largeBasename = path.substring(idx+1);
+		idx = largeBasename.lastIndexOf(getFileExtensionCharacter());
+		if (idx<0) return filename;
+		buf.append(largeBasename.substring(0, idx));
+		try {
+			if (isJarURL(filename)) {
+				return new URL(
+						filename.getProtocol(), 
+						filename.getHost(), 
+						filename.getPort(),
+						buf.toString());
+			}
+			URI uri = new URI(
+					filename.getProtocol(), 
+					filename.getUserInfo(), 
+					filename.getHost(), 
+					filename.getPort(), 
+					buf.toString(),
+					filename.getQuery(),
+					filename.getRef());
+			return uri.toURL();
+		}
+		catch(Throwable _) {
+			return null;
+		}
+	}
+
+	/** Replace the extension of the specified filename by the given extension.
+	 * If the filename has no extension, the specifiedone will be added.
+	 * 
+	 * @param filename is the filename to parse.
+	 * @param extension is the extension to remove if it is existing.
+	 * @return the filename without the extension.
+	 * @deprecated use {@link #replaceExtension(File,String)} or {@link #replaceExtension(URL,String)}
+	 */
+	@Deprecated
+	public static String replaceExtension(String filename, String extension) {
+		try {
+			return replaceExtension(new URL(filename), extension).toExternalForm();
+		}
+		catch(MalformedURLException _) {
+			return replaceExtension(new File(filename), extension).getPath();
+		}
+	}
+
+	/** Replace the extension of the specified filename by the given extension.
+	 * If the filename has no extension, the specified one will be added.
+	 * 
+	 * @param filename is the filename to parse.
+	 * @param extension is the extension to remove if it is existing.
+	 * @return the filename without the extension.
+	 */
+	public static File replaceExtension(File filename, String extension) {
+		if (filename==null) return null;
+		File dir = filename.getParentFile();
+		String name = filename.getName();
+		int idx = name.lastIndexOf(getFileExtensionCharacter());
+		if (idx<0) return new File(dir, name+extension);
+		return new File(dir, name.substring(0,idx)+extension);
+	}
+
+	/** Replace the extension of the specified filename by the given extension.
+	 * If the filename has no extension, the specified one will be added.
+	 * 
+	 * @param filename is the filename to parse.
+	 * @param extension is the extension to remove if it is existing.
+	 * @return the filename without the extension.
+	 */
+	public static URL replaceExtension(URL filename, String extension) {
+		if (filename==null) return null;
+		String path = filename.getPath();
+		int idx = path.lastIndexOf(URL_PATH_SEPARATOR);
+		int end = path.length();
+		if (idx==end-1) {
+			end --;
+			idx = path.lastIndexOf(URL_PATH_SEPARATOR, end-1);
+		}
+		StringBuffer buf = new StringBuffer((idx<0) ? "" : path.substring(0, idx+1)); //$NON-NLS-1$
+		String largeBasename = path.substring(idx+1, end);
+		idx = largeBasename.lastIndexOf(getFileExtensionCharacter());
+		if (idx<0) {
+			buf.append(largeBasename);
+		}
+		else {
+			buf.append(largeBasename.substring(0, idx));
+		}
+		buf.append(extension);
+		try {
+			if (isJarURL(filename)) {
+				return new URL(
+						filename.getProtocol(), 
+						filename.getHost(), 
+						filename.getPort(),
+						buf.toString());
+			}
+			URI uri = new URI(
+					filename.getProtocol(), 
+					filename.getUserInfo(), 
+					filename.getHost(), 
+					filename.getPort(), 
+					buf.toString(),
+					filename.getQuery(),
+					filename.getRef());
+			return uri.toURL();
+		}
+		catch(Throwable _) {
+			return null;
+		}
+	}
+
+	/** Copy the first file into the second file.
+	 * <p>
+	 * The content of the second file will be lost.
+	 * This copy function allows to do a copy between two different
+	 * partitions.
+	 * 
+	 * @param in is the file to copy.
+	 * @param out is the target file
+	 * @throws IOException in case of error.
+	 * @see #fileCopy(URL, File)
+	 */
+	public static void fileCopy(File in, File out) throws IOException {
+		FileChannel inChannel = new FileInputStream(in).getChannel();
+		FileChannel outChannel = new FileOutputStream(out).getChannel();
+		try {
+			// apparently has trouble copying large files on Windows
+			if (OperatingSystem.WIN.isCurrentOS()) {
+				// magic number for Windows, 64Mb - 32Kb
+				int maxCount = (64 * 1024 * 1024) - (32 * 1024);
+				long size = inChannel.size();
+				long position = 0;
+				while ( position < size ) {
+					position += inChannel.transferTo( position, maxCount, outChannel );
+				}
+			}
+			else {
+				inChannel.transferTo(0, inChannel.size(), outChannel);
+			}
+		}
+		finally {
+			if (inChannel!=null) inChannel.close();
+			if (outChannel!=null) outChannel.close();
+		}
+	}
+	
+	/** Copy the first file into the second file.
+	 * <p>
+	 * The content of the second file will be lost.
+	 * This copy function allows to do a copy between two different
+	 * partitions.
+	 * 
+	 * @param in is the file to copy.
+	 * @param out is the target file
+	 * @throws IOException in case of error.
+	 * @see #fileCopy(File, File)
+	 */
+	public static void fileCopy(URL in, File out) throws IOException {
+		URLConnection connection = in.openConnection();
+		ReadableByteChannel inChannel = Channels.newChannel(connection.getInputStream());
+		FileChannel outChannel = new FileOutputStream(out).getChannel();
+		int size = connection.getContentLength();
+		try {
+			// apparently has trouble copying large files on Windows
+			if (size<0 || OperatingSystem.WIN.isCurrentOS()) {
+				// magic number for Windows, 64Mb - 32Kb
+				int maxCount = (64 * 1024 * 1024) - (32 * 1024);
+				long position = 0;
+				long copied = 1;
+				while ( (size>=0 && position<size) || (size<0 && copied>0)) {
+					copied = outChannel.transferFrom(inChannel, position, maxCount);
+					position += copied;
+				}
+			}
+			else {
+				outChannel.transferFrom(inChannel, 0, size);
+			}
+		}
+		finally {
+			if (inChannel!=null) inChannel.close();
+			if (outChannel!=null) outChannel.close();
+		}
+	}
+
+	/** Replies the user home directory.
+	 *
+	 * @return the home directory of the current user.
+	 * @throws FileNotFoundException
+	 */
+	public static File getUserHomeDirectory() throws FileNotFoundException {
+		String userHome = System.getProperty("user.home"); //$NON-NLS-1$
+		if (userHome!=null) {
+			File file = new File(userHome);
+			if (file.isDirectory()) return file;
+		}
+		throw new FileNotFoundException();
+	}
+
+	/** Replies the user home directory.
+	 * 
+	 * @return the home directory of the current user.
+	 */
+	public static String getUserHomeDirectoryName() {
+		return System.getProperty("user.home"); //$NON-NLS-1$
+	}
+
+	/** Replies the user configuration directory for the specified software.
+	 * <p>
+	 * On Unix operating systems, the user directory for a
+	 * software is by default {@code $HOME/.software} where {@code software}
+	 * is the given parameter (case-sensitive). On Windows&reg; operating systems, the user
+	 * directory for a software is by default
+	 * {@code C:<span>\</span>Documents and Settings<span>\</span>userName<span>\</span>Local Settings<span>\</span>Application Data<span>\</span>software}
+	 * where {@code userName} is the login of the current user and {@code software}
+	 * is the given parameter (case-insensitive). 
+	 *
+	 * @param software is the name of the concerned software.
+	 * @return the configuration directory of the software for the current user.
+	 */
+	public static File getUserConfigurationDirectoryFor(String software) {
+		try {
+			File userHome = getUserHomeDirectory();
+			OperatingSystem os = OperatingSystem.getCurrentOS();
+			if (os.isUnixCompliant()) {
+				return new File(userHome, "."+software); //$NON-NLS-1$
+			}
+			else if (os==OperatingSystem.WIN) {
+				String userName = System.getProperty("user.name"); //$NON-NLS-1$
+				if (userName!=null && !"".equals(userName)) { //$NON-NLS-1$
+					return join(
+							new File("C:"),  //$NON-NLS-1$
+							"Documents and Settings", //$NON-NLS-1$
+							userName,
+							"Local Settings","Application Data",  //$NON-NLS-1$//$NON-NLS-2$
+							software);
+				}
+			}
+			return new File(userHome,software);
+		}
+		catch(FileNotFoundException _) {
+			//
+		}
+		return null;
+	}
+	
+	/** Replies the user configuration directory for the specified software.
+	 * <p>
+	 * On Unix operating systems, the user directory for a
+	 * software is by default {@code $HOME/.software} where {@code software}
+	 * is the given parameter (case-sensitive). On Windows&reg; operating systems, the user
+	 * directory for a software is by default
+	 * {@code C:<span>\</span>Documents and Settings<span>\</span>userName<span>\</span>Local Settings<span>\</span>Application Data<span>\</span>software}
+	 * where {@code userName} is the login of the current user and {@code software}
+	 * is the given parameter (case-insensitive). 
+	 * 
+	 * @param software is the name of the concerned software.
+	 * @return the configuration directory of the software for the current user.
+	 */
+	public static String getUserConfigurationDirectoryNameFor(String software) {
+		File directory = getUserConfigurationDirectoryFor(software);
+		if (directory!=null) return directory.getAbsolutePath();
+		return null;
+	}
+
+	/** Replies the system configuration directory for the specified software.
+	 * <p>
+	 * On Unix operating systems, the system directory for a
+	 * software is by default {@code /etc/software} where {@code software}
+	 * is the given parameter (case-sensitive). On Windows&reg; operating systems, the user
+	 * directory for a software is by default
+	 * {@code C:<span>\</span>Program Files<span>\</span>software}
+	 * where {@code software} is the given parameter (case-insensitive). 
+	 *
+	 * @param software is the name of the concerned software.
+	 * @return the configuration directory of the software for the current user.
+	 */
+	public static File getSystemConfigurationDirectoryFor(String software) {
+		OperatingSystem os = OperatingSystem.getCurrentOS();
+		if (os.isUnixCompliant()) {
+			File[] roots = File.listRoots();
+			return join(roots[0],"etc", software); //$NON-NLS-1$
+		}
+		else if (os==OperatingSystem.WIN) {
+			File pfDirectory;
+			for(File root : File.listRoots()) {
+				pfDirectory = new File(root, "Program Files"); //$NON-NLS-1$
+				if (pfDirectory.isDirectory()) {
+					return new File(root, software);
+				}
+			}
+		}
+		return null;
+	}
+	
+	/** Replies the user configuration directory for the specified software.
+	 * <p>
+	 * On Unix operating systems, the system directory for a
+	 * software is by default {@code /etc/software} where {@code software}
+	 * is the given parameter (case-sensitive). On Windows&reg; operating systems, the user
+	 * directory for a software is by default
+	 * {@code C:<span>\</span>Program Files<span>\</span>software}
+	 * where {@code software} is the given parameter (case-insensitive). 
+	 * 
+	 * @param software is the name of the concerned software.
+	 * @return the configuration directory of the software for the current user.
+	 */
+	public static String getSystemConfigurationDirectoryNameFor(String software) {
+		File directory = getSystemConfigurationDirectoryFor(software);
+		if (directory!=null) return directory.getAbsolutePath();
+		return null;
+	}
+
+	/** Replies the system shared library directory for the specified software.
+	 * <p>
+	 * On Unix operating systems, the system directory for a
+	 * software is by default {@code /usr/lib/software} where {@code software}
+	 * is the given parameter (case-sensitive). On Windows&reg; operating systems, the user
+	 * directory for a software is by default
+	 * {@code C:<span>\</span>Program Files<span>\</span>software}
+	 * where {@code software} is the given parameter (case-insensitive). 
+	 *
+	 * @param software is the name of the concerned software.
+	 * @return the configuration directory of the software for the current user.
+	 */
+	public static File getSystemSharedLibraryDirectoryFor(String software) {
+		OperatingSystem os = OperatingSystem.getCurrentOS();
+		if (os.isUnixCompliant()) {
+			File[] roots = File.listRoots();
+			return join(roots[0],"usr","lib", software); //$NON-NLS-1$ //$NON-NLS-2$
+		}
+		else if (os==OperatingSystem.WIN) {
+			File pfDirectory;
+			for(File root : File.listRoots()) {
+				pfDirectory = new File(root, "Program Files"); //$NON-NLS-1$
+				if (pfDirectory.isDirectory()) {
+					return new File(root, software);
+				}
+			}
+		}
+		return null;
+	}
+
+	/** Replies the system shared library directory for the specified software.
+	 * <p>
+	 * On Unix operating systems, the system directory for a
+	 * software is by default {@code /usr/lib/software} where {@code software}
+	 * is the given parameter (case-sensitive). On Windows&reg; operating systems, the user
+	 * directory for a software is by default
+	 * {@code C:<span>\</span>Program Files<span>\</span>software}
+	 * where {@code software} is the given parameter (case-insensitive). 
+	 *
+	 * @param software is the name of the concerned software.
+	 * @return the configuration directory of the software for the current user.
+	 */
+	public static String getSystemSharedLibraryDirectoryNameFor(String software) {
+		File f = getSystemSharedLibraryDirectoryFor(software);
+		if (f==null) return null;
+		return f.getAbsolutePath();
+	}
+
+	/** Convert an URL which represents a local file into a File.
+	 * 
+	 * @param url is the URL to convert.
+	 * @return the file.
+	 * @throws IllegalArgumentException is the URL was malformed.
+	 * @deprecated see {@link #convertUrlToFile(URL)}
+	 * @see #convertUrlToFile(URL)
+	 */
+	@Deprecated
+	public static File UrlToFile(URL url) {
+		return convertUrlToFile(url);
+	}
+
+	/** Convert an URL which represents a local file into a File.
+	 * 
+	 * @param url is the URL to convert.
+	 * @return the file.
+	 * @throws IllegalArgumentException is the URL was malformed.
+	 */
+	public static File convertUrlToFile(URL url) {
+		URI uri;
+		try {
+			// this is the step that can fail, and so
+			// it should be this step that should be fixed
+			uri = url.toURI();
+		}
+		catch (URISyntaxException e) {
+			// OK if we are here, then obviously the URL did
+			// not comply with RFC 2396. This can only
+			// happen if we have illegal unescaped characters.
+			// If we have one unescaped character, then
+			// the only automated fix we can apply, is to assume
+			// all characters are unescaped.
+			// If we want to construct a URI from unescaped
+			// characters, then we have to use the component
+			// constructors:
+			try {
+				uri = new URI(url.getProtocol(), url.getUserInfo(), url
+						.getHost(), url.getPort(), url.getPath(), url
+						.getQuery(), url.getRef());
+			}
+			catch (URISyntaxException e1) {
+				// The URL is broken beyond automatic repair
+				throw new IllegalArgumentException("broken URL: " + url); //$NON-NLS-1$
+			}
+
+		}
+		if ("file".equalsIgnoreCase(uri.getScheme())) { //$NON-NLS-1$
+			String auth = uri.getAuthority();
+			String path = uri.getPath();
+			if (path==null) path = uri.getRawPath();
+			if (path==null) path = uri.getSchemeSpecificPart();
+			if (path==null) path = uri.getRawSchemeSpecificPart();
+			if (path!=null) {
+				if (auth==null || "".equals(auth)) { //$NON-NLS-1$
+					// absolute filename in URI
+					return new File(path);
+				}
+				// relative filename in URI, extract it directly
+				return new File(auth+path);
+			}
+		}
+		throw new IllegalArgumentException("not a file URL: "+url); //$NON-NLS-1$
+	}
+	
+	/** Convert a string to an URL according to several rules.
+	 * <p>
+	 * The rules are (the first succeeded is replied):
+	 * <ul>
+	 * <li>if <var>urlDescription</var> is <code>null</code> or empty, return <code>null</code>;</li>
+	 * <li>try to build an {@link URL} with <var>urlDescription</var> as parameter;</li>
+	 * <li>if <var>allowResourceSearch</var> is <code>true</code> and 
+	 * <var>urlDescription</var> starts with {@code "resource:"}, call
+	 * {@link Resources#getResource(String)} with the rest of the string as parameter;</li>
+	 * <li>if <var>allowResourceSearch</var> is <code>true</code>, call
+	 * {@link Resources#getResource(String)} with the <var>urlDescription</var> as
+	 * parameter;</li>
+	 * <li>assuming that the <var>urlDescription</var> is
+	 * a filename, call {@link File#toURI()} to retreive an URI and then
+	 * {@link URI#toURL()};</li>
+	 * <li>If everything else failed, return <code>null</code>.</li>
+	 * </ul>
+	 * 
+	 * @param urlDescription is a string which is describing an URL.
+	 * @param allowResourceSearch indicates if the convertion must take into account the Java resources.
+	 * @return the URL.
+	 * @throws IllegalArgumentException is the string could not be formatted to URL.
+	 * @see Resources#getResource(String)
+	 */
+	public static URL convertStringToUrl(String urlDescription, boolean allowResourceSearch) {
+		return convertStringToUrl(urlDescription, allowResourceSearch, true);
+	}
+
+	/** Convert a string to an URL according to several rules.
+	 * <p>
+	 * The rules are (the first succeeded is replied):
+	 * <ul>
+	 * <li>if <var>urlDescription</var> is <code>null</code> or empty, return <code>null</code>;</li>
+	 * <li>try to build an {@link URL} with <var>urlDescription</var> as parameter;</li>
+	 * <li>if <var>allowResourceSearch</var> is <code>true</code> and 
+	 * <var>urlDescription</var> starts with {@code "resource:"}, call
+	 * {@link Resources#getResource(String)} with the rest of the string as parameter;</li>
+	 * <li>if <var>allowResourceSearch</var> is <code>true</code>, call
+	 * {@link Resources#getResource(String)} with the <var>urlDescription</var> as
+	 * parameter;</li>
+	 * <li>if <var>repliesFileURL</var> is <code>true</code> and 
+	 * assuming that the <var>urlDescription</var> is
+	 * a filename, call {@link File#toURI()} to retreive an URI and then
+	 * {@link URI#toURL()};</li>
+	 * <li>If everything else failed, return <code>null</code>.</li>
+	 * </ul>
+	 * 
+	 * @param urlDescription is a string which is describing an URL.
+	 * @param allowResourceSearch indicates if the convertion must take into account the Java resources.
+	 * @param repliesFileURL indicates if urlDescription is allowed to be a filename.
+	 * @return the URL.
+	 * @throws IllegalArgumentException is the string could not be formatted to URL.
+	 * @see Resources#getResource(String)
+	 */
+	public static URL convertStringToUrl(String urlDescription, boolean allowResourceSearch, boolean repliesFileURL) {
+		if (urlDescription==null || urlDescription.length()==0) return null;
+		
+		try {
+			return new URL(urlDescription);
+		}
+		catch (MalformedURLException _) {
+			// ignore error
+		}
+		
+		URL url;
+		
+		if (allowResourceSearch) {
+			
+			String resourceName;
+			
+			if (urlDescription.toLowerCase().startsWith("resource:")) { //$NON-NLS-1$
+				resourceName = urlDescription.substring(9);
+				return Resources.getResource(resourceName);
+			}
+			
+			resourceName = urlDescription;
+			url = Resources.getResource(resourceName);
+			if (url!=null) return url;
+		}
+		else if (urlDescription.toLowerCase().startsWith("resource:")) { //$NON-NLS-1$
+			return null;
+		}
+
+		if (repliesFileURL) {
+			try {
+				File file = new File(urlDescription);
+				URI uri = file.toURI();
+				return uri.toURL();
+			}
+			catch (MalformedURLException e) {
+				// ignore error
+			}
+		}
+		
+		return null;
+	}
+
+	/**
+	 * Make the given filename absolute from the given root if it is not already absolute. 
+	 *
+	 * @param filename is the name to make absolute.
+	 * @param current is the current directory which permits to make absolute.
+	 * @return an absolute filename.
+	 */
+	public static File makeAbsolute(File filename, File current) {
+		if (filename==null) return null;
+		if (current!=null && !filename.isAbsolute()) {
+			try {
+				return new File(current.getCanonicalFile(), filename.getPath());
+			}
+			catch(IOException _) {
+				return new File(current.getAbsoluteFile(), filename.getPath());
+			}
+		}
+		return filename;
+	}
+	
+	/** Replies if the given URL is using a protocol which could be map to files.
+	 * 
+	 * @param url
+	 * @return <code>true</code> if the given url is a "file", "http", 
+	 * "https", "ftp", "ssh", "jar" or "resource", otherwise <code>false</code>.
+	 */
+	public static boolean isFileBasedURL(URL url) {
+		if (url!=null) {
+			String scheme = url.getProtocol();
+			if ("file".equalsIgnoreCase(scheme)) return true; //$NON-NLS-1$
+			if ("http".equalsIgnoreCase(scheme)) return true; //$NON-NLS-1$
+			if ("https".equalsIgnoreCase(scheme)) return true; //$NON-NLS-1$
+			if ("ftp".equalsIgnoreCase(scheme)) return true; //$NON-NLS-1$
+			if ("ssh".equalsIgnoreCase(scheme)) return true; //$NON-NLS-1$
+			if ("jar".equalsIgnoreCase(scheme)) return true; //$NON-NLS-1$
+			if ("resource".equalsIgnoreCase(scheme)) return true; //$NON-NLS-1$
+		}
+		return false;
+	}
+
+	/**
+	 * Make the given filename absolute from the given root if it is not already absolute. 
+	 *
+	 * @param filename is the name to make absolute.
+	 * @param current is the current directory which permits to make absolute.
+	 * @return an absolute filename.
+	 */
+	public static URL makeAbsolute(URL filename, File current) {
+		if (filename==null) return null;
+		if (current!=null && isFileBasedURL(filename)) {
+			String scheme = filename.getProtocol();
+			if ("jar".equalsIgnoreCase(scheme)) { //$NON-NLS-1$
+				try {
+					String[] parts = filename.getPath().split(JAR_URL_FILE_ROOT);
+					URL u = makeAbsolute(new URL(parts[0]), current);
+					StringBuffer adr = new StringBuffer("jar:"); //$NON-NLS-1$
+					adr.append(u.toExternalForm());
+					for(int i=1; i<parts.length; i++) {
+						adr.append(JAR_URL_FILE_ROOT);
+						adr.append(parts[i]);
+					}
+					return new URL(adr.toString());
+				}
+				catch(MalformedURLException _) {
+					// Ignore error
+				}
+			}
+			else {
+				int port = filename.getPort();
+				try {
+					String absPath = filename.getPath();
+					if (!absPath.startsWith(URL_PATH_SEPARATOR)) {
+						URL rootUrl = current.toURI().toURL();
+						absPath = rootUrl.getPath()+URL_PATH_SEPARATOR+absPath;
+						return new URL(filename.getProtocol(), filename.getHost(), port, absPath);
+					}
+				}
+				catch (MalformedURLException e) {
+					//
+				}
+			}
+		}
+		return filename;
+	}
+
+	/**
+	 * Make the given filename absolute from the given root if it is not already absolute. 
+	 *
+	 * @param filename is the name to make absolute.
+	 * @param current is the current directory which permits to make absolute.
+	 * @return an absolute filename.
+	 */
+	public static URL makeAbsolute(URL filename, URL current) {
+		if (current!=null && "file".equalsIgnoreCase(current.getProtocol())) { //$NON-NLS-1$
+			File cur = convertUrlToFile(current);
+			if (cur!=null) return makeAbsolute(filename, cur);
+		}
+		return filename;
+	}
+
+	/** Replies the parent URL for the given URL.
+	 * 
+	 * @param url
+	 * @return the parent URL
+	 * @throws MalformedURLException 
+	 */
+	public static URL getParentURL(URL url) throws MalformedURLException {
+		String path = url.getPath();
+		String prefix, parentStr;
+
+		if ("jar".equalsIgnoreCase(url.getProtocol())) { //$NON-NLS-1$
+			int index = path.indexOf(JAR_URL_FILE_ROOT);
+			assert(index>0);
+			prefix = path.substring(0,index+1);
+			path = path.substring(index+1);
+			parentStr = URL_PATH_SEPARATOR;
+		}
+		else if ("file".equalsIgnoreCase(url.getProtocol())) { //$NON-NLS-1$
+			prefix = null;
+			parentStr = ".."+URL_PATH_SEPARATOR; //$NON-NLS-1$
+		}
+		else {
+			prefix = null;
+			parentStr = URL_PATH_SEPARATOR;
+		}
+		
+		if (path==null || "".equals(path)) path = parentStr; //$NON-NLS-1$
+		int index = path.lastIndexOf(URL_PATH_SEPARATOR_CHAR);
+		if (index==-1) path = parentStr;
+		else if (index==path.length()-1) {
+			index = path.lastIndexOf(URL_PATH_SEPARATOR_CHAR, index-1);
+			if (index==-1) path = parentStr;
+			else path = path.substring(0, index+1);
+		}
+		else path = path.substring(0, index+1);
+		
+		if (prefix!=null)  path = prefix + path;
+		
+		return new URL(url.getProtocol(), url.getHost(), url.getPort(), path);
+	}
+	
+}
+

Added: tags/afc-2.0/arakhneVmutils/java/src/main/java/org/arakhne/vmutil/FileURLConnection.java
===================================================================
--- tags/afc-2.0/arakhneVmutils/java/src/main/java/org/arakhne/vmutil/FileURLConnection.java	                        (rev 0)
+++ tags/afc-2.0/arakhneVmutils/java/src/main/java/org/arakhne/vmutil/FileURLConnection.java	2010-01-21 08:29:52 UTC (rev 117)
@@ -0,0 +1,203 @@
+/* 
+ * $Id$
+ * 
+ * Copyright (C) 2010 Alexandre WILLAUME, St&eacute;phane GALLAND
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * This program is free software; you can redistribute it and/or modify
+ */
+package org.arakhne.vmutil;
+
+import java.io.BufferedInputStream;
+import java.io.BufferedOutputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.net.URL;
+import java.net.URLConnection;
+import java.net.UnknownServiceException;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import javax.activation.MimetypesFileTypeMap;
+
+/**
+ * The class <code>FileURLConnection</code> is implementing
+ * connection between an URL and a local file.
+ * Instances of this class can be used both to
+ * read from and to write to the resource referenced by the file URL.
+ * <p>
+ * Supported header fields are:
+ * <ul>
+ * <li><code>content-type</code></li>
+ * <li><code>content-length</code></li>
+ * <li><code>last-modified</code></li>
+ * </ul>
+ * 
+ * @author Alexandre WILLAUME &lt;willaume@xxxxxxxxxxx&gt;
+ * @author St&eacute;phane GALLAND &lt;galland@xxxxxxxxxxx&gt;
+ * @version $Name$ $Revision$ $Date$
+ * @see URLConnection
+ */
+class FileURLConnection extends URLConnection {
+
+	private File file = null;
+	
+	private String contentType = null;
+	
+	/**
+	 * @param url is the "file"-protocol url to use.
+	 */
+	protected FileURLConnection(URL url) {
+		super(url);
+	}
+	
+	/**
+     * {@inheritDoc}
+     */
+	@Override
+    public String getHeaderField(int n) {
+		try {
+			connect();
+		}
+		catch(IOException e) {
+			throw new IllegalStateException(e);
+		}
+    	switch(n) {
+    	case 0: // content-type
+    		return this.contentType;
+    	case 1: // content-length
+    		return Long.toString(this.file.length());
+    	case 2: // last-modified
+    		return Long.toString(this.file.lastModified());
+    	}
+    	return null;
+    }
+	
+    /**
+     * {@inheritDoc}
+     */
+	@Override
+    public String getHeaderField(String name) {
+		try {
+			connect();
+		}
+		catch(IOException e) {
+			throw new IllegalStateException(e);
+		}
+    	if ("content-type".equals(name)) { //$NON-NLS-1$
+    		return this.contentType;
+    	}
+    	if ("content-length".equals(name)) { //$NON-NLS-1$
+    		return Long.toString(this.file.length());
+    	}
+    	if ("last-modified".equals(name)) { //$NON-NLS-1$
+    		return Long.toString(this.file.lastModified());
+    	}
+    	return null;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+	@Override
+    public String getHeaderFieldKey(int n) {
+    	switch(n) {
+    	case 0:
+    		return "content-type"; //$NON-NLS-1$
+    	case 1:
+    		return "content-length"; //$NON-NLS-1$
+    	case 2:
+    		return "last-modified"; //$NON-NLS-1$
+    	}
+    	return null;
+    }
+		
+    /**
+     * {@inheritDoc}
+     */
+	@Override
+    public Map<String,List<String>> getHeaderFields() {
+		try {
+			connect();
+		}
+		catch(IOException e) {
+			throw new IllegalStateException(e);
+		}
+		Map<String, List<String>> flds = new HashMap<String, List<String>>();
+    	flds.put("content-type", singletonList(this.contentType)); //$NON-NLS-1$
+    	flds.put("content-length", singletonList(Long.toString(this.file.length()))); //$NON-NLS-1$
+    	flds.put("last-modified", singletonList(Long.toString(this.file.lastModified()))); //$NON-NLS-1$
+        return flds;
+    }
+	
+	private List<String> singletonList(String value) {
+		if (value==null) return null;
+		return Collections.singletonList(value);
+	}
+
+    /**
+	 * {@inheritDoc}
+	 */
+	@Override
+	public void connect() throws IOException {
+		if (!this.connected) {
+			this.file = FileSystem.convertUrlToFile(this.url);
+			if (this.file==null)
+				throw new FileNotFoundException(this.url.toExternalForm());
+			this.contentType = new MimetypesFileTypeMap().getContentType(this.file);
+			this.connected = true;
+		}
+	}
+	
+	/**
+	 * {@inheritDoc}
+	 */
+	@Override
+	public OutputStream getOutputStream() throws IOException {
+        connect();
+		if (getDoOutput()) {
+			OutputStream os = new FileOutputStream(this.file);
+			if (getUseCaches()) {
+				os = new BufferedOutputStream(os);
+			}
+			return os;
+		}
+		throw new UnknownServiceException("URL connection cannot do output"); //$NON-NLS-1$
+    }
+	
+	/**
+	 * {@inheritDoc}
+	 */
+	@Override
+	public InputStream getInputStream() throws IOException {
+        connect();
+		if (getDoInput()) {
+			InputStream is = new FileInputStream(this.file);
+			if (getUseCaches()) {
+				is = new BufferedInputStream(is);
+			}
+			return is;
+		}
+		throw new UnknownServiceException("URL connection cannot do input"); //$NON-NLS-1$
+    }
+	
+}

Added: tags/afc-2.0/arakhneVmutils/java/src/main/java/org/arakhne/vmutil/FileURLStreamHandler.java
===================================================================
--- tags/afc-2.0/arakhneVmutils/java/src/main/java/org/arakhne/vmutil/FileURLStreamHandler.java	                        (rev 0)
+++ tags/afc-2.0/arakhneVmutils/java/src/main/java/org/arakhne/vmutil/FileURLStreamHandler.java	2010-01-21 08:29:52 UTC (rev 117)
@@ -0,0 +1,61 @@
+/* 
+ * $Id$
+ * 
+ * Copyright (C) 2010 Alexandre WILLAUME, St&eacute;phane GALLAND
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * This program is free software; you can redistribute it and/or modify
+ */
+package org.arakhne.vmutil;
+
+import java.io.IOException;
+import java.net.URL;
+import java.net.URLConnection;
+import java.net.URLStreamHandler;
+
+/**
+ * The class <code>FileURLStreamHandler</code> is supporting file protocol
+ * for URL streams. This stream protocol
+ * handler knows how to make a connection for "file" protocol.
+ * <p>
+ * In most cases, an instance of a <code>URLStreamHandler</code>
+ * subclass is not created directly by an application. Rather, the
+ * first time a protocol name is encountered when constructing a
+ * <code>URL</code>, the appropriate stream protocol handler is
+ * automatically loaded.
+ * <p>
+ * To use this factory, invoke the following code only ONCE time:
+ * <code>URL.setURLStreamHandlerFactory(new FileURLStreamHandlerFactory());</code>.
+ * 
+ * @author Alexandre WILLAUME &lt;willaume@xxxxxxxxxxx&gt;
+ * @author St&eacute;phane GALLAND &lt;galland@xxxxxxxxxxx&gt;
+ * @version $Name$ $Revision$ $Date$
+ * @see URLStreamHandler
+ * @see FileURLStreamHandlerFactory
+ */
+class FileURLStreamHandler extends URLStreamHandler {
+
+	/**
+	 * {@inheritDoc}
+	 */
+	@Override
+	protected URLConnection openConnection(URL url) throws IOException {
+		if ("file".equalsIgnoreCase(url.getProtocol())) { //$NON-NLS-1$
+			return new FileURLConnection(url);
+		}
+		throw new UnsupportedOperationException("Unsupported protocol: "+url); //$NON-NLS-1$
+	}
+
+}

Added: tags/afc-2.0/arakhneVmutils/java/src/main/java/org/arakhne/vmutil/FileURLStreamHandlerFactory.java
===================================================================
--- tags/afc-2.0/arakhneVmutils/java/src/main/java/org/arakhne/vmutil/FileURLStreamHandlerFactory.java	                        (rev 0)
+++ tags/afc-2.0/arakhneVmutils/java/src/main/java/org/arakhne/vmutil/FileURLStreamHandlerFactory.java	2010-01-21 08:29:52 UTC (rev 117)
@@ -0,0 +1,57 @@
+/* 
+ * $Id$
+ * 
+ * Copyright (C) 2010 Alexandre WILLAUME, St&eacute;phane GALLAND
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * This program is free software; you can redistribute it and/or modify
+ */
+package org.arakhne.vmutil;
+
+import java.net.URL;
+import java.net.URLStreamHandler;
+import java.net.URLStreamHandlerFactory;
+
+/**
+ * This class defines a factory for <code>URL</code> stream
+ * "file" protocol handlers.
+ * <p>
+ * It is used by the <code>URL</code> class to create a
+ * <code>URLStreamHandler</code> for a "file" protocol.
+ * <p>
+ * To use this factory, invoke the following code only ONCE time:
+ * <code>URL.setURLStreamHandlerFactory(new FileURLStreamHandlerFactory());</code>.
+ * 
+ * @author Alexandre WILLAUME &lt;willaume@xxxxxxxxxxx&gt;
+ * @author St&eacute;phane GALLAND &lt;galland@xxxxxxxxxxx&gt;
+ * @version $Name$ $Revision$ $Date$
+ * @see URLStreamHandlerFactory
+ * @see URL#setURLStreamHandlerFactory(URLStreamHandlerFactory)
+ */
+public class FileURLStreamHandlerFactory
+implements URLStreamHandlerFactory {
+
+	/**
+	 * {@inheritDoc}
+	 */
+	@Override
+	public URLStreamHandler createURLStreamHandler(String protocol) {
+		if ("file".equalsIgnoreCase(protocol)) //$NON-NLS-1$
+            return new FileURLStreamHandler();
+		// Force the default factory to retreive stream handler.
+		return null;
+	}
+
+}

Added: tags/afc-2.0/arakhneVmutils/java/src/main/java/org/arakhne/vmutil/LibraryLoader.java
===================================================================
--- tags/afc-2.0/arakhneVmutils/java/src/main/java/org/arakhne/vmutil/LibraryLoader.java	                        (rev 0)
+++ tags/afc-2.0/arakhneVmutils/java/src/main/java/org/arakhne/vmutil/LibraryLoader.java	2010-01-21 08:29:52 UTC (rev 117)
@@ -0,0 +1,370 @@
+/* 
+ * $Id$
+ * 
+ * Copyright (C) 2004-2009 St&eacute;phane GALLAND
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * This program is free software; you can redistribute it and/or modify
+ */
+
+package org.arakhne.vmutil;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URISyntaxException;
+import java.net.URL;
+
+/**
+ * This class provides more generic means for loading
+ * dynamical libraries. 
+ *
+ * @author St&eacute;phane GALLAND &lt;galland@xxxxxxxxxxx&gt;
+ * @version $Name:  $ $Revision: 1.1 $ $Date: 2007-02-20 08:43:41 $
+ */
+public class LibraryLoader {
+
+    /**
+     * Loads a code file with the specified filename from the local file
+     * system as a dynamic library. The filename
+     * argument must be a complete path name.
+     * <p>
+     * The call <code>LibraryLoader.load(name)</code> is effectively equivalent
+     * to the call:
+     * <blockquote><pre>
+     * System.load(name)
+     * </pre></blockquote>
+     *
+     * @param filename is the file to load.
+     * @throws  SecurityException if a security manager exists and its
+     *             <code>checkLink</code> method doesn't allow
+     *             loading of the specified dynamic library
+     * @throws  UnsatisfiedLinkError if the file does not exist.
+     * @throws  NullPointerException if <code>filename</code> is
+     *             <code>null</code>
+     * @see        java.lang.System#load(java.lang.String)
+     */
+    public static void load(String filename) {
+    	Runtime.getRuntime().load(filename);
+    }
+
+    /**
+     * Loads the system library specified by the <code>libname</code>
+     * argument. The manner in which a library name is mapped to the
+     * actual system library is system dependent.
+     * <p>
+     * The call <code>LibraryLoader.loadLibrary(name)</code> is effectively
+     * equivalent to the call
+     * <blockquote><pre>
+     * System.loadLibrary(name)
+     * </pre></blockquote>
+     *
+     * @param      libname   the name of the library.
+     * @throws  SecurityException  if a security manager exists and its
+     *             <code>checkLink</code> method doesn't allow
+     *             loading of the specified dynamic library
+     * @throws  UnsatisfiedLinkError  if the library does not exist.
+     * @throws  NullPointerException if <code>libname</code> is
+     *             <code>null</code>
+     * @see        java.lang.System#loadLibrary(java.lang.String)
+     */
+    public static void loadLibrary(String libname) {
+    	Runtime.getRuntime().loadLibrary(libname);
+    }
+
+    /**
+     * Loads a code file with the specified filename from the local file
+     * system as a dynamic library. The filename
+     * argument must be a complete path name.
+     * <p>
+     * The call <code>LibraryLoader.load(name)</code> is effectively equivalent
+     * to the call:
+     * <blockquote><pre>
+     * System.load(name.getAbsolutePath())
+     * </pre></blockquote>
+     *
+     * @param filename is the file to load.
+     * @throws  SecurityException if a security manager exists and its
+     *             <code>checkLink</code> method doesn't allow
+     *             loading of the specified dynamic library
+     * @throws  UnsatisfiedLinkError if the file does not exist.
+     * @throws  NullPointerException if <code>filename</code> is
+     *             <code>null</code>
+     * @see        java.lang.System#load(java.lang.String)
+     */
+    public static void load(File filename) {
+    	Runtime.getRuntime().load(filename.getAbsolutePath());
+    }
+
+    /** Replies the URL for the specified library.
+     * 
+     * @param libName is the name of the library
+     * @return the URL where the specified library was located. 
+     */
+    public static URL findLibraryURL(String libName) {
+        return findLibraryURL(null,libName,null,null);
+    }
+    
+    /** Replies the URL for the specified library.
+     * <p>
+     * The call <code>LibraryLoader.findLibraryURL(path,name)</code> is effectively equivalent
+     * to the call:
+     * <blockquote><pre>
+     * getClassLoader().getResource(path+System.mapLibraryName(name))
+     * </pre></blockquote>
+     * 
+     * @param path is the resource's path where the library was located.
+     * @param libName is the name of the library
+     * @return the URL where the specified library was located. 
+     */
+    public static URL findLibraryURL(String path, String libName) {
+    	return findLibraryURL(path, libName, null, null);
+    }
+    
+    private static URL findLibraryURL(String path, String libName, String platform, String arch) {
+        ClassLoader cl = ClassLoaderFinder.findClassLoader();
+        assert(cl!=null);
+        String resourcePath = path;
+        if (resourcePath==null) resourcePath = ""; //$NON-NLS-1$
+        else if ((resourcePath.length()>0)&&(!resourcePath.endsWith("/"))) { //$NON-NLS-1$
+        	resourcePath += "/"; //$NON-NLS-1$
+        }
+        // Find the 64bits version of the DLL
+        String realLibName;
+        if (platform!=null) {
+        	StringBuffer buf = new StringBuffer(libName);
+        	buf.append("-"); //$NON-NLS-1$
+        	buf.append(platform);
+        	if (arch!=null) buf.append(arch);
+        	realLibName = System.mapLibraryName(buf.toString());
+        	int idx = realLibName.indexOf(libName);
+        	if (idx>0) realLibName = realLibName.substring(idx);
+        }
+        else {
+        	StringBuffer buf = new StringBuffer(libName);
+        	if (arch!=null) buf.append(arch);
+        	realLibName = System.mapLibraryName(buf.toString());
+        }
+        URL libRes = Resources.getResource(cl, resourcePath+realLibName);
+        if (libRes!=null) return libRes;
+        return Resources.getResource(cl,realLibName);
+    }
+
+    /**
+     * Loads a code file with the specified filename from the local file
+     * system as a dynamic library. The filename
+     * argument must be a complete path name.
+     *
+     * @param filename is the file to load.
+     * @throws IOException 
+     * @throws  SecurityException if a security manager exists and its
+     *             <code>checkLink</code> method doesn't allow
+     *             loading of the specified dynamic library
+     * @throws  UnsatisfiedLinkError if the file does not exist.
+     * @throws  NullPointerException if <code>filename</code> is
+     *             <code>null</code>
+     * @see        java.lang.System#load(java.lang.String)
+     */
+    public static void load(URL filename) throws IOException {
+        if (filename.getProtocol().equalsIgnoreCase("file")) { //$NON-NLS-1$
+        	try {
+        		load(new File(filename.toURI()));
+        	} 
+        	catch (URISyntaxException e) {
+        		throw new FileNotFoundException(filename.toExternalForm());
+        	}
+        }
+        else {
+    	  // Create a tmp file to receive the library code.
+    	  String libName = System.mapLibraryName("javaDynLib"); //$NON-NLS-1$
+    	  String suffix = ".dll"; //$NON-NLS-1$
+    	  String prefix = "javaDynLib"; //$NON-NLS-1$
+    	  int pos = libName.lastIndexOf('.');
+    	  if (pos>=0) {
+    		  suffix = libName.substring(pos);
+    		  prefix = libName.substring(0,pos);
+    	  }
+    	  File f = File.createTempFile(prefix,suffix);
+    	  
+    	  // Copy the library code into the local file  	    	  
+    	  FileOutputStream outs = new FileOutputStream(f);
+    	  InputStream ins = filename.openStream();
+    	  byte[] buffer = new byte[2048];
+    	  int lu;
+    	  while ((lu=ins.read(buffer))>0) {
+    		  outs.write(buffer,0,lu);
+    	  }
+    	  ins.close();
+    	  outs.close();
+
+    	  // Load the library from the local file
+    	  load(f);
+    	  
+    	  // Delete local file
+    	  f.deleteOnExit();
+        }
+    }
+    
+    /**
+     * Search and load the dynamic library which is fitting the
+     * current operating system (32 or 64bits operating system...).
+     * A 64 bits library is assumed to be named <code>libname64.dll</code>
+     * on Windows&reg; and <code>liblibname64.so</code> on Unix.
+     * A 32 bits library is assumed to be named <code>libname32.dll</code>
+     * on Windows&reg; and <code>liblibname32.so</code> on Unix.
+     * A library which could be ran either on 32 and 64 platforms is assumed
+     * to be named <code>libname.dll</code> on Windows&reg; and
+     * <code>liblibname.so</code> on Unix.
+     *
+     * @param libname is the name of the library.
+     * @throws IOException 
+     * @throws  SecurityException if a security manager exists and its
+     *             <code>checkLink</code> method doesn't allow
+     *             loading of the specified dynamic library
+     * @throws  UnsatisfiedLinkError if the file does not exist.
+     * @throws  NullPointerException if <code>filename</code> is
+     *             <code>null</code>
+     * @see        java.lang.System#load(java.lang.String)
+     */
+    public static void loadPlatformDependentLibrary(String libname) throws IOException {
+    	loadPlatformDependentLibrary(null,libname);
+    }
+
+	/** Replies the data model of the current operating system: 32 or 64 bits.
+	 * 
+	 * @return the integer which is corresponding to the data model, or <code>0</code> if
+	 * it could not be determined.
+	 */
+	static int getOperatingSystemArchitectureDataModel() {
+		String arch = System.getProperty("sun.arch.data.model"); //$NON-NLS-1$
+		if (arch!=null) {
+			try {
+				return Integer.parseInt(arch); 
+			}
+			catch(Throwable _) {
+				//
+			}
+		}
+		return 0;
+	}
+
+    /**
+     * Search and load the dynamic library which is fitting the
+     * current operating system (32 or 64bits operating system...).
+     * A 64 bits library is assumed to be named <code>libname64.dll</code>
+     * on Windows&reg; and <code>liblibname64.so</code> on Unix.
+     * A 32 bits library is assumed to be named <code>libname32.dll</code>
+     * on Windows&reg; and <code>liblibname32.so</code> on Unix.
+     * A library which could be ran either on 32 and 64 platforms is assumed
+     * to be named <code>libname.dll</code> on Windows&reg; and
+     * <code>liblibname.so</code> on Unix.
+     *
+     * @param path is the resource's path where the library was located.
+     * @param libname is the name of the library.
+     * @throws IOException 
+     * @throws  SecurityException if a security manager exists and its
+     *             <code>checkLink</code> method doesn't allow
+     *             loading of the specified dynamic library
+     * @throws  UnsatisfiedLinkError if the file does not exist.
+     * @throws  NullPointerException if <code>filename</code> is
+     *             <code>null</code>
+     * @see        java.lang.System#load(java.lang.String)
+     */
+    public static void loadPlatformDependentLibrary(String path, String libname) throws IOException {
+    	loadPlatformDependentLibrary(libname, null, path);
+    }
+    
+    private static URL getPlatformDependentLibrary(String[] paths, String libname, String platform) {
+    	URL url;
+    	int dataModel = getOperatingSystemArchitectureDataModel();
+    	for(String path : paths) {
+	    	// Load the 64 library
+	    	if (dataModel==64) {
+	    		url = findLibraryURL(path, libname, platform, "64"); //$NON-NLS-1$
+	    		if (url!=null) return url;
+	    	}
+	    	// Load the 32 library
+	    	else if (dataModel==32) {
+	    		url = findLibraryURL(path, libname, platform, "32"); //$NON-NLS-1$
+	    		if (url!=null) return url;
+	    	}
+	    	// Load the multi-platform library
+			url = findLibraryURL(path, libname, platform, null);
+			if (url!=null) return url;
+    	}
+    	return null;
+    }
+
+    /**
+     * Search and load the dynamic library which is fitting the
+     * current operating system (32 or 64bits operating system...).
+     * A 64 bits library is assumed to be named <code>libname64.dll</code>
+     * on Windows&reg; and <code>liblibname64.so</code> on Unix.
+     * A 32 bits library is assumed to be named <code>libname32.dll</code>
+     * on Windows&reg; and <code>liblibname32.so</code> on Unix.
+     * A library which could be ran either on 32 and 64 platforms is assumed
+     * to be named <code>libname.dll</code> on Windows&reg; and
+     * <code>liblibname.so</code> on Unix.
+     *
+     * @param libname is the name of the library.
+     * @param platform is the name of the current OS platform.
+     * @param paths are the resource's paths where the library was located.
+     * @throws IOException 
+     * @throws  SecurityException if a security manager exists and its
+     *             <code>checkLink</code> method doesn't allow
+     *             loading of the specified dynamic library
+     * @throws  UnsatisfiedLinkError if the file does not exist.
+     * @throws  NullPointerException if <code>filename</code> is
+     *             <code>null</code>
+     * @see        java.lang.System#load(java.lang.String)
+     */
+    static void loadPlatformDependentLibrary(String libname, String platform, String... paths) throws IOException {    
+    	URL url;
+    	// Package version (according to Maven module)
+    	url = getPlatformDependentLibrary(paths, libname, null);
+    	if (url!=null) {
+			try {
+				load(url);
+				// library loaded
+				return;
+			}
+			catch(Throwable e) {
+				System.err.println("could not load "+url); //$NON-NLS-1$
+				e.printStackTrace();
+			}
+    	}
+    	// Eclipse version  (according to Maven module)
+    	if (platform!=null) {
+        	url = getPlatformDependentLibrary(paths, libname, platform);
+        	if (url!=null) {
+    			try {
+    				load(url);
+    				// library loaded
+    				return;
+    			}
+    			catch(Throwable e) {
+    				System.err.println("could not load "+url); //$NON-NLS-1$
+    				e.printStackTrace();
+    			}
+        	}
+    	}
+    	
+		// System-based loading
+		loadLibrary(libname);
+    }
+
+}

Added: tags/afc-2.0/arakhneVmutils/java/src/main/java/org/arakhne/vmutil/MACNumber.java
===================================================================
--- tags/afc-2.0/arakhneVmutils/java/src/main/java/org/arakhne/vmutil/MACNumber.java	                        (rev 0)
+++ tags/afc-2.0/arakhneVmutils/java/src/main/java/org/arakhne/vmutil/MACNumber.java	2010-01-21 08:29:52 UTC (rev 117)
@@ -0,0 +1,379 @@
+/* 
+ * $Id$
+ * 
+ * Copyright (C) 2005-2010 St&eacute;phane GALLAND
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * This program is free software; you can redistribute it and/or modify
+ */
+package org.arakhne.vmutil;
+
+import java.net.InetAddress;
+import java.net.NetworkInterface;
+import java.net.SocketException;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/** A MACNumber is the unique number associated to a network interface.
+ * 
+ * @author St&eacute;phane GALLAND &lt;galland@xxxxxxxxxxx&gt;
+ * @version $Name$ $Revision$ $Date$
+ * @see NetworkInterface
+ */
+public final class MACNumber {
+	
+	/**
+	 * Character that is used as separator inside MAC addresses.
+	 */
+	public static final char MACNUMBER_SEPARATOR = '/';
+
+	/** Parse the specified string an repleis the corresponding MAC numbers.
+	 * 
+	 * @param addresses is the string to parse
+	 * @return a list of addresses.
+	 * @throws IllegalArgumentException is the argument has not the right syntax. 
+	 */
+	public static MACNumber[] parse(String addresses) {
+		if ((addresses==null)||("".equals(addresses))) return new MACNumber[0]; //$NON-NLS-1$
+		String[] adrs = addresses.split(Character.toString(MACNUMBER_SEPARATOR));
+		ArrayList<MACNumber> list = new ArrayList<MACNumber>();
+		for (String adr : adrs) {
+			list.add(new MACNumber(adr));
+		}
+		MACNumber[] tab = new MACNumber[list.size()];
+		list.toArray(tab);
+		list.clear();
+		return tab;
+	}
+
+	/** Parse the specified string an repleis the corresponding MAC numbers.
+	 * 
+	 * @param addresses is the string to parse
+	 * @return a list of addresses.
+	 * @throws IllegalArgumentException is the argument has not the right syntax. 
+	 */
+	public static String[] parseAsString(String addresses) {
+		if ((addresses==null)||("".equals(addresses))) return new String[0]; //$NON-NLS-1$
+		String[] adrs = addresses.split(Character.toString(MACNUMBER_SEPARATOR));
+		ArrayList<String> list = new ArrayList<String>();
+		for (String adr : adrs) {
+			list.add(new MACNumber(adr).toString());
+		}
+		String[] tab = new String[list.size()];
+		list.toArray(tab);
+		list.clear();
+		return tab;
+	}
+
+	/** Join the specified MAC numbers to reply a string.
+	 * 
+	 * @param addresses is the list of mac addresses to join.
+	 * @return the joined string. 
+	 */
+	public static String join(MACNumber... addresses) {
+		if ((addresses==null)||(addresses.length==0)) return null;
+		StringBuffer buf = new StringBuffer();
+		for (MACNumber number : addresses) {
+			if (buf.length()>0) buf.append(MACNUMBER_SEPARATOR);
+			buf.append(number);
+		}
+		return buf.toString();
+	}
+
+	/** Get all of the ethernet addresses associated with the local machine.
+	 * <p>
+	 * This method will try and find ALL of the ethernet adapters
+	 * which are currently available on the system. This is heavily OS
+	 * dependent and may not be supported on all platforms. When not
+	 * supported, you should still get back a collection with the {@link
+	 * #getPrimaryAdapter primary adapter} in it.
+	 *
+	 * @return the list of MAC numbers associated to the physical devices.
+	 * @see #getPrimaryAdapter
+	 */
+	public static Collection<MACNumber> getAllAdapters() {
+		List<MACNumber> av = new ArrayList<MACNumber>();
+		try {
+			Enumeration<NetworkInterface> interfaces = NetworkInterface.getNetworkInterfaces();
+			if (interfaces!=null) {
+				NetworkInterface inter;
+				while (interfaces.hasMoreElements()) {
+					inter = interfaces.nextElement();
+					try {
+						byte[] addr = inter.getHardwareAddress();
+						if (addr!=null) av.add(new MACNumber(addr));
+					}
+					catch(SocketException _) {
+						//
+					}
+				}
+			}
+		}
+		catch(SocketException _) {
+			//
+		}
+		return av;
+	}
+
+	/** Get all of the internet address and ethernet address mappings
+	 * on the local machine.
+	 * <p>
+	 * This method will try and find ALL of the ethernet adapters
+	 * which are currently available on the system. This is heavily OS
+	 * dependent and may not be supported on all platforms. When not
+	 * supported, you should still get back a collection with the {@link
+	 * #getPrimaryAdapterAddresses primary adapter} in it.
+	 *
+	 * @return the map internet address and ethernet address mapping.
+	 * @see #getPrimaryAdapterAddresses
+	 */
+	public static Map<InetAddress, MACNumber> getAllMappings() {
+		Map<InetAddress,MACNumber> av = new HashMap<InetAddress,MACNumber>();
+		try {
+			Enumeration<NetworkInterface> interfaces = NetworkInterface.getNetworkInterfaces();
+			if (interfaces!=null) {
+				NetworkInterface inter;
+				MACNumber mac;
+				InetAddress inet;
+				while (interfaces.hasMoreElements()) {
+					inter = interfaces.nextElement();
+					try {
+						byte[] addr = inter.getHardwareAddress();
+						if (addr!=null) {
+							mac = new MACNumber(addr);
+							Enumeration<InetAddress> inets = inter.getInetAddresses();
+							while (inets.hasMoreElements()) {
+								inet = inets.nextElement();
+								av.put(inet, mac);
+							}
+						}
+					}
+					catch(SocketException _) {
+						//
+					}
+				}
+			}
+		}
+		catch(SocketException _) {
+			//
+		}
+		return av;
+	}
+
+	/** Try to determine the primary ethernet address of the machine.
+	 * 
+	 * @return the primary MACNumber or <code>null</code>
+	 */
+	public static MACNumber getPrimaryAdapter() {
+		try {
+			Enumeration<NetworkInterface> interfaces = NetworkInterface.getNetworkInterfaces();
+			if (interfaces!=null) {
+				NetworkInterface inter;
+				while (interfaces.hasMoreElements()) {
+					inter = interfaces.nextElement();
+					try {
+						byte[] addr = inter.getHardwareAddress();
+						if (addr!=null) return new MACNumber(addr);
+					}
+					catch(SocketException _) {
+						//
+					}
+				}
+			}
+		}
+		catch(SocketException _) {
+			//
+		}
+		return null;
+	}
+
+	/** Try to determine the primary ethernet address of the machine and
+	 * replies the associated internet addresses.
+	 * 
+	 * @return the internet addresses of the primary network interface.
+	 */
+	public static Collection<InetAddress> getPrimaryAdapterAddresses() {
+		try {
+			Enumeration<NetworkInterface> interfaces = NetworkInterface.getNetworkInterfaces();
+			if (interfaces!=null) {
+				NetworkInterface inter;
+				while (interfaces.hasMoreElements()) {
+					inter = interfaces.nextElement();
+					try {
+						byte[] addr = inter.getHardwareAddress();
+						if (addr!=null) {
+							Collection<InetAddress> inetList = new ArrayList<InetAddress>();
+							Enumeration<InetAddress> inets = inter.getInetAddresses();
+							while (inets.hasMoreElements()) {
+								inetList.add(inets.nextElement());
+							}
+							
+							return inetList;
+						}
+					}
+					catch(SocketException _) {
+						//
+					}
+				}
+			}
+		}
+		catch(SocketException _) {
+			//
+		}
+		return null;
+	}
+
+	/** Constant ethernet address object which has the "null address".
+	 * 
+	 * <p>This constant can be used when you want a non-null
+	 * MACAddress object reference, but want a invalid (or null)
+	 * MAC address contained.
+	 * 
+	 * @see #isNull()
+	 */
+	public static final MACNumber NULL = new MACNumber();
+
+	/**
+	 * Content of the MAC address.
+	 */
+	private final byte[] bytes;
+
+
+	/** Constructs object with "null values" (address of "0:0:0:0:0:0").
+	 */
+	public MACNumber() {
+		this.bytes = new byte[6];
+	}
+
+	/** Build a MACNumber from a set of bytes.
+	 * The byte array must contains 6 elements.
+	 * 
+	 * @param bytes is the list of bytes from which the address must be built.
+	 * @throws IllegalArgumentException if the byte array does not corresponds to a valid MAC Number.
+	 */
+	public MACNumber(byte[] bytes) {
+		if (bytes == null || bytes.length != 6) {
+			throw new IllegalArgumentException("mac address not 6 bytes long"); //$NON-NLS-1$
+		}
+		this.bytes = new byte[6];
+		System.arraycopy(bytes, 0, this.bytes, 0, 6);
+	}
+
+	/** Build a MACNumber from a string representation.
+	 * 
+	 * @param address is the string representation of a MAC address
+	 * @throws IllegalArgumentException if the byte array does not corresponds to a valid MAC Number.
+	 * @see #toString()
+	 */
+	public MACNumber(String address) {
+		if (address==null)
+			throw new IllegalArgumentException("mac address not 6 bytes long"); //$NON-NLS-1$
+		String[] parts = address.split(":"); //$NON-NLS-1$
+		if (parts.length!=6)
+			throw new IllegalArgumentException("mac address not 6 bytes long"); //$NON-NLS-1$
+		this.bytes = new byte[6];
+		try {
+			int val;
+			for(int i=0; i<6; i++) {
+				val = Integer.parseInt(parts[i],16);
+				this.bytes[i] = (byte)val;
+			}
+		}
+		catch(Exception _) {
+			throw new IllegalArgumentException("mac address not 6 bytes long"); //$NON-NLS-1$
+		}
+	}
+
+	/**
+	 * {@inheritDoc}
+	 * 
+	 * @param o {@inheritDoc}
+	 * @return {@inheritDoc}
+	 */
+	@Override
+	public boolean equals(Object o) {
+		if (!(o instanceof MACNumber)) return false;
+
+		byte[] bao = ((MACNumber) o).bytes;
+		if (bao.length != this.bytes.length) return false;
+
+		for (int i = 0; i < bao.length; i++) if (bao[i] != this.bytes[i]) return false;
+		return true;
+	}
+
+	/**
+	 * {@inheritDoc}
+	 * 
+	 * @return {@inheritDoc}
+	 */
+	@Override
+	public int hashCode() {
+		int blen = this.bytes.length;
+		if (blen == 0) return 0;
+
+		int hc = this.bytes[0];
+		for (int i = 1; i < blen; i++) {
+			hc *= 37;
+			hc += this.bytes[i];
+		}
+		return hc;
+	}
+
+	/**
+	 * {@inheritDoc}
+	 * 
+	 * @return {@inheritDoc}
+	 */
+	@Override
+	public String toString() {
+		int blen = this.bytes.length;
+		StringBuffer sb = new StringBuffer(blen*3);
+		for (int i = 0; i < blen; i++) {
+			int lo = this.bytes[i];
+			int hi = ((lo >> 4) & 0xF);
+			lo &= 0xF;
+			if (i != 0) sb.append(':');
+			sb.append(Character.forDigit(hi,16));
+			sb.append(Character.forDigit(lo,16));
+		}
+		return sb.toString();
+	}
+
+	/** Replies if all the MAC address number are equal to zero.
+	 * 
+	 * @return <code>true</code> if all the bytes are zero.
+	 * @see #NULL
+	 */
+	public boolean isNull() {
+		for (int i = 0; i < this.bytes.length; i++) {
+			if (this.bytes[i]!=0) return false;
+		}
+		return true;
+	}
+
+	/** Replies the bytes that compose this MAC Address.
+	 * 
+	 * @return a copy of the current bytes.
+	 */
+	public byte[] getBytes() {
+		return this.bytes.clone();
+	}
+	
+}
+

Added: tags/afc-2.0/arakhneVmutils/java/src/main/java/org/arakhne/vmutil/OperatingSystem.java
===================================================================
--- tags/afc-2.0/arakhneVmutils/java/src/main/java/org/arakhne/vmutil/OperatingSystem.java	                        (rev 0)
+++ tags/afc-2.0/arakhneVmutils/java/src/main/java/org/arakhne/vmutil/OperatingSystem.java	2010-01-21 08:29:52 UTC (rev 117)
@@ -0,0 +1,242 @@
+/* 
+  * $Id$
+ * 
+ * Copyright (C) 2004-2009 St&eacute;phane GALLAND
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * This program is free software; you can redistribute it and/or modify
+ */
+
+package org.arakhne.vmutil;
+
+import java.io.IOError;
+import java.io.IOException;
+
+/**
+ * This is a list of supported operating system.  
+ *
+ * @author St&eacute;phane GALLAND &lt;galland@xxxxxxxxxxx&gt;
+ * @version $Name:  $ $Revision: 1.2 $ $Date: 2007-04-26 11:32:44 $
+ */
+public enum OperatingSystem {
+
+	/**
+	 * Windows&reg;.
+	 */
+	WIN,
+	
+	/**
+	 * Linux distribution.
+	 */
+	LINUX,
+	
+	/**
+	 * Solaris&reg;.
+	 */
+	SOLARIS,
+
+	/**
+	 * Mac OS X&reg;.
+	 */
+	MACOSX,
+	
+	/**
+	 * Free BSD.
+	 */
+	FREEBSD,
+
+	/**
+	 * Net BSD.
+	 */
+    NETBSD,
+    
+	/**
+	 * Standard BSD.
+	 */
+    BSD,
+    
+	/**
+	 * Open BSD.
+	 */
+    OPENBSD,
+    
+	/**
+	 * AIX&reg;.
+	 */
+    AIX,
+    
+	/**
+	 * HPUX&reg;.
+	 */
+    HPUX,
+    
+	/**
+	 * Unknown operating systems.
+	 */
+    OTHER;
+	
+	/** Replies if the current OperatingSystem constant is corresponding
+	 * to the current operating system.
+	 * 
+	 * @return <code>true</code> if the current operating system corresponds to this constant,
+	 * otherwise <code>false</code>
+	 */
+	public boolean isCurrentOS() {
+		return getCurrentOS()==this;
+	}
+
+	/** Replies of this OS is Unix compliant.
+	 * 
+	 * @return <code>true</code> if this constant corresponds to a Unix-like operating system,
+	 * otherwise <code>false</code>
+	 */
+	public boolean isUnixCompliant() {
+		switch(this) {
+		case AIX:
+		case BSD:
+		case FREEBSD:
+		case HPUX:
+		case LINUX:
+		case MACOSX:
+		case NETBSD:
+		case OPENBSD:
+		case SOLARIS:
+			return true;
+		default:
+			return false;
+		}
+	}
+	
+
+	/** Replies the name of the current OS.
+	 * 
+	 * @return the name of the current operating system.
+	 * @see System#getProperty(java.lang.String)
+	 */
+	public static String getCurrentOSName() {
+		return System.getProperty("os.name"); //$NON-NLS-1$
+	}
+	
+	/** Replies the version of the current OS.
+	 * 
+	 * @return the version of the current operating system.
+	 * @see System#getProperty(java.lang.String)
+	 */
+	public static String getCurrentOSVersion() {
+		return System.getProperty("os.version"); //$NON-NLS-1$
+	}
+
+	/** Replies the current operating system.
+	 * 
+	 * @return the current operating system constant.
+	 */
+	public static OperatingSystem getCurrentOS() {
+	      String os = System.getProperty("os.name").trim().toLowerCase(); //$NON-NLS-1$
+
+	      /* Let's try to figure canonical OS name, just in case some
+	       * JVMs use funny values (unlikely)
+	       */
+	      if (os.indexOf("windows") >= 0) { //$NON-NLS-1$
+	          return WIN;
+	      }
+	      else if (os.indexOf("linux") >= 0) { //$NON-NLS-1$
+	          return LINUX;
+	      }
+	      else if ((os.indexOf("solaris") >= 0)|| //$NON-NLS-1$
+	               (os.indexOf("sunos") >= 0)) { //$NON-NLS-1$
+	          return SOLARIS;
+	      }
+	      else if ((os.indexOf("mac os x") >= 0)|| //$NON-NLS-1$
+	               (os.indexOf("macosx") >= 0)) { //$NON-NLS-1$
+	          return MACOSX;
+	      }
+	      else if (os.indexOf("bsd") >= 0) { //$NON-NLS-1$
+	          if (os.indexOf("freebsd") >= 0) { //$NON-NLS-1$
+	              return FREEBSD;
+	          }
+	          else if (os.indexOf("netbsd") >= 0) { //$NON-NLS-1$
+	              return NETBSD;
+	          }
+	          else if (os.indexOf("openbsd") >= 0) { //$NON-NLS-1$
+	              return OPENBSD;
+	          }
+	          else { // default
+	              return BSD;
+	          }
+	      }
+	      else if (os.indexOf("aix") >= 0) { //$NON-NLS-1$
+	          return AIX;
+	      }
+	      else if (os.indexOf("hp ux") >= 0) { //$NON-NLS-1$
+	          return HPUX;
+	      }
+	      else {
+	          return OTHER;
+	      }
+	}
+	
+	/** Replies the data model of the current operating system: 32 or 64 bits.
+	 * 
+	 * @return the integer which is corresponding to the data model, or <code>0</code> if
+	 * it could not be determined.
+	 */
+	public static int getOperatingSystemArchitectureDataModel() {
+		return LibraryLoader.getOperatingSystemArchitectureDataModel();
+	}
+
+	/** Replies if the current operating system is 64bit.
+	 * 
+	 * @return <code>true</code> if the operating system is 64bits, othewise
+	 * <code>false</code>
+	 */
+	public static boolean is64BitOperatingSystem() {
+		return getOperatingSystemArchitectureDataModel()==64;
+	}
+
+	/** Replies if the current operating system is 32bit.
+	 * 
+	 * @return <code>true</code> if the operating system is 32bits, othewise
+	 * <code>false</code>
+	 */
+	public static boolean is32BitOperatingSystem() {
+		int dataModel = getOperatingSystemArchitectureDataModel();
+		return dataModel==32 || dataModel==0;
+	}
+
+	/** Get the OS serial number.
+	 * 
+	 * @return the serial number associated to the current operating system.
+	 */
+	public static native String getOSSerialNumber();
+
+	/** Get the OS UUID.
+	 * 
+	 * @return an unique identifier for the current operating system.
+	 */
+	public static native String getOSUUID();
+	
+	static {
+		try {
+			LibraryLoader.loadPlatformDependentLibrary(
+					"josuuid", //$NON-NLS-1$
+					System.getProperty("os.name").trim().toLowerCase(), //$NON-NLS-1$
+					"org/arakhne/vmutil"); //$NON-NLS-1$
+		}
+		catch (IOException e) {
+			throw new IOError(e);
+		}
+	}
+
+}

Added: tags/afc-2.0/arakhneVmutils/java/src/main/java/org/arakhne/vmutil/OperatingSystemInfo.java
===================================================================
--- tags/afc-2.0/arakhneVmutils/java/src/main/java/org/arakhne/vmutil/OperatingSystemInfo.java	                        (rev 0)
+++ tags/afc-2.0/arakhneVmutils/java/src/main/java/org/arakhne/vmutil/OperatingSystemInfo.java	2010-01-21 08:29:52 UTC (rev 117)
@@ -0,0 +1,79 @@
+/* 
+ * $Id$
+ * 
+ * Copyright (C) 2009 St&eacute;phane GALLAND
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * This program is free software; you can redistribute it and/or modify
+ */
+
+package org.arakhne.vmutil;
+
+/**
+ * This class print on the standard output several informations
+ * about your operating system.
+ * These informations are extracted by the Java or the native
+ * libraries from <code>arakhneVmutils</code>.  
+ *
+ * @author St&eacute;phane GALLAND &lt;galland@xxxxxxxxxxx&gt;
+ * @version $Name$ $Revision$ $Date$
+ */
+public class OperatingSystemInfo {
+
+	private static void showTitle(String title) {
+		System.out.print("#######################################\n# "); //$NON-NLS-1$
+		System.out.println(title);
+		System.out.println("#######################################"); //$NON-NLS-1$
+	}
+	
+	private static void showPropertyValue(String name) {
+		showValue(name, System.getProperty(name));
+	}
+	
+	private static void showValue(String name, String value) {
+		System.out.print(name);
+		System.out.print(" = "); //$NON-NLS-1$
+		System.out.println(value);
+	}
+
+	/**
+	 * @param args
+	 */
+	public static void main(String[] args) {
+		
+		showTitle("JRE Properties"); //$NON-NLS-1$
+		
+		showPropertyValue("java.class.path"); //$NON-NLS-1$
+		showPropertyValue("java.library.path"); //$NON-NLS-1$
+		showPropertyValue("java.home"); //$NON-NLS-1$
+		showPropertyValue("os.name"); //$NON-NLS-1$
+		showPropertyValue("path.separator"); //$NON-NLS-1$
+		showPropertyValue("sun.arch.data.model"); //$NON-NLS-1$
+		showPropertyValue("user.dir"); //$NON-NLS-1$
+		showPropertyValue("user.name"); //$NON-NLS-1$
+		
+		showTitle("OperatingSystem"); //$NON-NLS-1$
+		
+		showValue("getCurrentOSName()", OperatingSystem.getCurrentOSName()); //$NON-NLS-1$
+		showValue("getCurrentOSVersion()", OperatingSystem.getCurrentOSVersion()); //$NON-NLS-1$
+		showValue("getOSSerialNumber()", OperatingSystem.getOSSerialNumber()); //$NON-NLS-1$
+		showValue("getOSUUID()", OperatingSystem.getOSUUID()); //$NON-NLS-1$
+		showValue("getOperatingSystemArchitectureDataModel()", Integer.toString(OperatingSystem.getOperatingSystemArchitectureDataModel())); //$NON-NLS-1$
+		showValue("getCurrentOS()", OperatingSystem.getCurrentOS().name()); //$NON-NLS-1$
+		showValue("is32BitOperatingSystem()", Boolean.toString(OperatingSystem.is32BitOperatingSystem())); //$NON-NLS-1$
+		showValue("is64BitOperatingSystem()", Boolean.toString(OperatingSystem.is64BitOperatingSystem())); //$NON-NLS-1$
+	}
+
+}

Added: tags/afc-2.0/arakhneVmutils/java/src/main/java/org/arakhne/vmutil/ReflectionUtil.java
===================================================================
--- tags/afc-2.0/arakhneVmutils/java/src/main/java/org/arakhne/vmutil/ReflectionUtil.java	                        (rev 0)
+++ tags/afc-2.0/arakhneVmutils/java/src/main/java/org/arakhne/vmutil/ReflectionUtil.java	2010-01-21 08:29:52 UTC (rev 117)
@@ -0,0 +1,465 @@
+/* 
+ * $Id$
+ * 
+ * Copyright (C) 2004-2009 St&eacute;phane GALLAND
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * This program is free software; you can redistribute it and/or modify
+ */
+
+package org.arakhne.vmutil;
+
+import java.io.File;
+import java.io.IOException;
+import java.lang.reflect.Modifier;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Enumeration;
+import java.util.List;
+import java.util.jar.JarEntry;
+import java.util.jar.JarFile;
+
+/**
+ * This utility class provides a way to extend the reflection API and
+ * the Class class with autoboxing-compliant functions.
+ * 
+ * @author St&eacute;phane GALLAND &lt;galland@xxxxxxxxxxx&gt;
+ * @version $Name$ $Revision$ $Date$
+ * @since since JDK 1.5
+ */
+public class ReflectionUtil {
+
+    /**
+     * Determines if the specified <code>Object</code> is assignment-compatible
+     * with the object represented by the <code>Class</code>.  This method extends
+     * {@link Class#isInstance(Object)} with autoboxing support.
+     *
+     * @param type is the class against which the object must be test
+     * @param obj is the object to check
+     * @return <code>true</code> if <code>obj</code> is an instance of the type
+     * @see Class#isInstance(Object)
+     */
+    public static boolean isInstance(Class<?> type, Object obj) {
+    	assert(type!=null);
+    	if (obj==null) return false;
+
+    	// Test according to the Class's behaviour
+    	if (type.isInstance(obj)) return true;
+    	
+    	// Test according to autoboxing
+    	if (type.isPrimitive()
+    			&&
+    			type!=Void.class && type!=void.class) {
+    		
+    		if (type==Boolean.class) return boolean.class.isInstance(obj);
+    		if (type==boolean.class) return Boolean.class.isInstance(obj);
+    		
+    		if (type==Character.class) return char.class.isInstance(obj);
+    		if (type==char.class) return Character.class.isInstance(obj);
+
+    		if (type==Byte.class) return byte.class.isInstance(obj);
+    		if (type==byte.class) return Byte.class.isInstance(obj);
+
+    		if (type==Short.class) return short.class.isInstance(obj);
+    		if (type==short.class) return Short.class.isInstance(obj);
+
+    		if (type==Integer.class) return int.class.isInstance(obj);
+    		if (type==int.class) return Integer.class.isInstance(obj);
+
+    		if (type==Long.class) return long.class.isInstance(obj);
+    		if (type==long.class) return Long.class.isInstance(obj);
+
+    		if (type==Float.class) return float.class.isInstance(obj);
+    		if (type==float.class) return Float.class.isInstance(obj);
+    		
+    		if (type==Double.class) return double.class.isInstance(obj);
+    		if (type==double.class) return Double.class.isInstance(obj);
+
+    		if (type==Void.class) return void.class.isInstance(obj);
+    		if (type==void.class) return Void.class.isInstance(obj);
+    		
+    		assert false: "Unsupported primitive type"; //$NON-NLS-1$
+    	}
+    	
+    	return false;
+    }
+
+
+    /**
+     * Determines if the <code>assignmentTarget</code> object is either the same as,
+     * or is a superclass or superinterface of, the class or interface 
+     * represented by the specified
+     * <code>assignementSource</code> parameter. This method extends
+     * {@link Class#isAssignableFrom(Class)} with autoboxing support.
+     * 
+     * @param assignementTarget is the class that is tested to be a super class.
+     * @param assignementSource is the class that is tested to be a sub class.
+     * @return <code>true</code> if an object of the <var>assignementSource</var> type
+     * could be assigned to a variable of <var>assignementTarget</var> type,
+     * otherwise <code>false</code>.
+     */
+    public static boolean isAssignableFrom(Class<?> assignementTarget, Class<?> assignementSource) {
+    	assert(assignementSource!=null);
+    	assert(assignementTarget!=null);
+    	
+    	// Test according to the Class's behaviour
+    	if (assignementTarget.isAssignableFrom(assignementSource)) return true;
+    	
+    	// Test according to autoboxing
+    	if (assignementTarget.isPrimitive() && assignementSource.isPrimitive()
+    			&&
+    			assignementTarget!=Void.class && assignementTarget!=void.class
+    			&&
+    			assignementSource!=Void.class && assignementSource!=void.class) {
+    		return true;
+    	}
+    	
+    	return false;
+    }
+
+	/** Replies the type that corresponds to the specified class.
+	 * If the name corresponds to a primitive type, the low-level type
+	 * will be replied.
+	 * This method extends
+     * {@link Class#forName(String)} with autoboxing support.
+	 * 
+	 * @param name is the name of the class to load.
+	 * @return the loaded class
+	 * @throws ClassNotFoundException  if name names an
+	 * unknown class or primitive
+	 */
+	public static Class<?> forName(String name) throws ClassNotFoundException {
+		if (name == null || "".equals(name) || "null".equals(name) || "void".equals(name)) { //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+			return void.class;
+		}
+		if ("boolean".equals(name)) { //$NON-NLS-1$
+			return boolean.class;
+		}
+		if ("byte".equals(name)) { //$NON-NLS-1$
+			return byte.class;
+		}
+		if ("char".equals(name)) { //$NON-NLS-1$
+			return char.class;
+		}
+		if ("double".equals(name)) { //$NON-NLS-1$
+			return double.class;
+		}
+		if ("float".equals(name)) { //$NON-NLS-1$
+			return float.class;
+		}
+		if ("int".equals(name)) { //$NON-NLS-1$
+			return int.class;
+		}
+		if ("long".equals(name)) { //$NON-NLS-1$
+			return long.class;
+		}
+		if ("short".equals(name)) { //$NON-NLS-1$
+			return short.class;
+		}
+		return Class.forName(name);
+	}
+
+	/** Replies the type that corresponds to the specified class.
+	 * If the name corresponds to a primitive type, the low-level type
+	 * will be replied.
+	 * This method extends
+     * {@link Class#forName(String)} with autoboxing support.
+	 * 
+	 * @param name is the name of the class to load.
+	 * @param loader is the class loader to use.
+	 * @return the loaded class
+	 * @throws ClassNotFoundException  if name names an
+	 * unknown class or primitive
+	 */
+	public static Class<?> forName(String name, ClassLoader loader) throws ClassNotFoundException {
+		return forName(name, true, loader);
+	}
+
+	/** Replies the type that corresponds to the specified class.
+	 * If the name corresponds to a primitive type, the low-level type
+	 * will be replied.
+	 * This method extends
+     * {@link Class#forName(String)} with autoboxing support.
+	 * 
+	 * @param name is the name of the class to load.
+	 * @param typeInitialization must be <code>true</code> to initialize the type, <code>false</code> otherwise.
+	 * @param loader is the class loader to use.
+	 * @return the loaded class
+	 * @throws ClassNotFoundException  if name names an
+	 * unknown class or primitive
+	 */
+	public static Class<?> forName(String name, boolean typeInitialization, ClassLoader loader) throws ClassNotFoundException {
+		if (name == null || "".equals(name) || "null".equals(name) || "void".equals(name)) { //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+			return void.class;
+		}
+		if ("boolean".equals(name)) { //$NON-NLS-1$
+			return boolean.class;
+		}
+		if ("byte".equals(name)) { //$NON-NLS-1$
+			return byte.class;
+		}
+		if ("char".equals(name)) { //$NON-NLS-1$
+			return char.class;
+		}
+		if ("double".equals(name)) { //$NON-NLS-1$
+			return double.class;
+		}
+		if ("float".equals(name)) { //$NON-NLS-1$
+			return float.class;
+		}
+		if ("int".equals(name)) { //$NON-NLS-1$
+			return int.class;
+		}
+		if ("long".equals(name)) { //$NON-NLS-1$
+			return long.class;
+		}
+		if ("short".equals(name)) { //$NON-NLS-1$
+			return short.class;
+		}
+		return Class.forName(name, typeInitialization, loader);
+	}
+
+	/**
+	 * Replies the list of the classes in the given package.
+	 * @param pkg is the package to explore.
+	 * @return the list of classes in the package.
+	 */
+	public static Collection<Class<?>> getPackageClasses(Package pkg) {
+		return getPackageClasses(pkg.getName());
+	}
+
+	/**
+	 * Replies the list of the classes in the given package.
+	 * @param packageName is the name of the package to explore.
+	 * @return the list of classes in the package.
+	 */
+	public static Collection<Class<?>> getPackageClasses(String packageName) {
+		Collection<Class<?>> classes = new ArrayList<Class<?>>();
+	 
+		String[] entries = System.getProperty("java.class.path").split(System.getProperty("path.separator")); //$NON-NLS-1$//$NON-NLS-2$
+		String lentry;			
+		
+		for(String path : entries) {
+			lentry = path.toLowerCase();
+			if(lentry.endsWith(".jar") || lentry.endsWith(".war")) { //$NON-NLS-1$//$NON-NLS-2$
+				getPackageClassesFromJar(classes, path, packageName);
+			}else{
+				getPackageClassesFromFileSystem(classes, path, packageName);
+			}
+	 
+		}
+	 
+		return classes;
+	}
+	
+	private static String basename(String name) {
+		int idx = name.lastIndexOf('/');
+		if (idx>=0 && idx<name.length()) {
+			return name.substring(idx+1);
+		}
+		return name;
+	}
+
+	private static String filename(String name) {
+		String basename = basename(name);
+		int idx = basename.indexOf('.');
+		if (idx>=0 && idx<basename.length()) {
+			return basename.substring(0,idx);
+		}
+		return name;
+	}
+
+	private static void getPackageClassesFromJar(Collection<Class<?>> classes, String jarFilename, String packageName) {
+		try {
+			JarFile jarFile = new JarFile(jarFilename);
+			String packagePath = packageName.replace(".", "/"); //$NON-NLS-1$//$NON-NLS-2$
+	
+			Enumeration<JarEntry> entries = jarFile.entries();
+			JarEntry entry;
+			String entryPath, entryClassname;
+			
+			while (entries.hasMoreElements()) {
+				entry = entries.nextElement();
+				entryPath = entry.getName();
+	
+				// In package and not inner class
+				if (entryPath.startsWith(packagePath)
+					&& !entryPath.endsWith("/") //$NON-NLS-1$
+					&& !entryPath.contains("$")) { //$NON-NLS-1$
+					entryClassname = packageName + "." + filename(entryPath); //$NON-NLS-1$
+					try {
+						classes.add(Class.forName(entryClassname));
+					}
+					catch(ClassNotFoundException _) {
+						//
+					}
+				}	
+			}
+		}
+		catch(IOException _) {
+			//
+		}
+	}
+
+	private static void getPackageClassesFromFileSystem(Collection<Class<?>> classes, String directory, String packageName) {
+		String packagePath = packageName.replace(".", File.separator); //$NON-NLS-1$
+		File packageDirectory = new File(directory, packagePath);
+		String entryClassname;
+		
+		if (packageDirectory.isDirectory()) {
+			for(String entryPath : packageDirectory.list()) {
+	
+				// In package and not inner class
+				if (!entryPath.contains("$")) { //$NON-NLS-1$
+					entryClassname = packageName + "." + FileSystem.shortBasename(entryPath); //$NON-NLS-1$
+					try {
+						classes.add(Class.forName(entryClassname));
+					}
+					catch(Throwable _) {
+						//
+					}
+				}
+			}
+		}
+	}
+	
+	/**
+	 * Replies the list of all the subclasses of the given class
+	 * in the current classpath.
+	 * 
+	 * @param <T> is the type of the superclass.
+	 * @param className is the name of the class to explore.
+	 * @return the list of subclasses.
+	 */
+	public static <T> Collection<Class<? extends T>> getSubClasses(Class<T> className) {
+		Collection<Class<? extends T>> list = new ArrayList<Class<? extends T>>();
+		getSubClasses(className, true, true, true, list);
+		return list;
+	}
+
+	/**
+	 * Replies the list of all the subclasses of the given class
+	 * in the current classpath.
+	 * 
+	 * @param <T> is the type of the superclass.
+	 * @param className is the name of the class to explore.
+	 * @param allowAbstract is <code>true</code> to allow abstract classes to be put in the replied list
+	 * @param allowInterface is <code>true</code> to allow interfaces to be put in the replied list.
+	 * @param allowEnum is <code>true</code> to allow enumeration to be put in the replied list.
+	 * @param result is the list of subclasses which will be filled by this function.
+	 */
+	public static <T> void getSubClasses(Class<T> className, boolean allowAbstract, boolean allowInterface, boolean allowEnum, Collection<Class<? extends T>> result) {
+		String[] entries = System.getProperty("java.class.path").split(System.getProperty("path.separator")); //$NON-NLS-1$//$NON-NLS-2$
+		String lentry;			
+		
+		for(String path : entries) {
+			lentry = path.toLowerCase();
+			if(lentry.endsWith(".jar") || lentry.endsWith(".war")) { //$NON-NLS-1$//$NON-NLS-2$
+				getSubClassesFromJar(result, path, className, allowAbstract, allowInterface, allowEnum);
+			}else{
+				getSubClassesFromFileSystem(result, path, className, allowAbstract, allowInterface, allowEnum);
+			}
+	 
+		}
+	}
+
+	@SuppressWarnings("unchecked")
+	private static <T> void getSubClassesFromJar(Collection<Class<? extends T>> classes, String jarFilename, Class<T> className, boolean allowAbstract, boolean allowInterface, boolean allowEnum) {
+		try {
+			JarFile jarFile = new JarFile(jarFilename);
+			String classN = className.getCanonicalName();
+			if (classN!=null) {
+				Enumeration<JarEntry> entries = jarFile.entries();
+				JarEntry entry;
+				String entryPath, entryClassname;
+				
+				while (entries.hasMoreElements()) {
+					entry = entries.nextElement();
+					entryPath = entry.getName();
+		
+					// In package and not inner class
+					if (entryPath.endsWith(".class") //$NON-NLS-1$
+						&& !entryPath.contains("$")) { //$NON-NLS-1$
+						entryClassname = entryPath.substring(0, entryPath.length()-6).replaceAll(File.separator, "."); //$NON-NLS-1$
+						try {
+							Class<?> clazz = Class.forName(entryClassname);
+							if ((className.isAssignableFrom(clazz))
+								&&(allowAbstract || !Modifier.isAbstract(clazz.getModifiers()))
+								&&(allowInterface || !clazz.isInterface())
+								&&(allowEnum || !clazz.isEnum()))
+								classes.add((Class<? extends T>)clazz);
+						}
+						catch(Throwable _) {
+							//
+						}
+					}	
+				}
+			}
+		}
+		catch(IOException _) {
+			//
+		}
+	}
+
+	@SuppressWarnings("unchecked")
+	private static <T> void getSubClassesFromFileSystem(Collection<Class<? extends T>> classes, String directory, Class<T> className, boolean allowAbstract, boolean allowInterface, boolean allowEnum) {
+		String classN = className.getCanonicalName();
+		if (classN!=null) {
+			List<String> directories = new ArrayList<String>();
+			directories.add(""); //$NON-NLS-1$
+			
+			String ldir, entryClassname;
+			File dir, fullFile;
+			
+			while (!directories.isEmpty()) {
+				ldir = directories.remove(0);
+				dir = new File(directory, ldir);
+				if (dir.isDirectory()) {
+					for(String entryPath : dir.list()) {
+			
+						fullFile = new File(dir,entryPath);
+						
+						if (fullFile.isDirectory()) {
+							if (ldir==null || "".equals(ldir)) { //$NON-NLS-1$
+								directories.add(entryPath);
+							}
+							else {
+								directories.add(new File(ldir,entryPath).toString());
+							}
+						}
+						// In package and not inner class
+						else if (entryPath.endsWith(".class") //$NON-NLS-1$
+							&& !entryPath.contains("$")) { //$NON-NLS-1$
+							assert(ldir!=null);
+							entryClassname = ldir.replaceAll(File.separator, ".") + "." + FileSystem.shortBasename(entryPath); //$NON-NLS-1$ //$NON-NLS-2$
+							try {
+								Class<?> clazz = Class.forName(entryClassname);
+								if ((className.isAssignableFrom(clazz))
+									&&(allowAbstract || !Modifier.isAbstract(clazz.getModifiers()))
+									&&(allowInterface || !clazz.isInterface())
+									&&(allowEnum || !clazz.isEnum()))
+									classes.add((Class<? extends T>)clazz);
+							}
+							catch(Throwable _) {
+								//
+							}
+						}
+					}
+				}
+			}
+		}
+	}
+	
+}

Added: tags/afc-2.0/arakhneVmutils/java/src/main/java/org/arakhne/vmutil/ResourceNotFoundException.java
===================================================================
--- tags/afc-2.0/arakhneVmutils/java/src/main/java/org/arakhne/vmutil/ResourceNotFoundException.java	                        (rev 0)
+++ tags/afc-2.0/arakhneVmutils/java/src/main/java/org/arakhne/vmutil/ResourceNotFoundException.java	2010-01-21 08:29:52 UTC (rev 117)
@@ -0,0 +1,64 @@
+/* 
+ * $Id$
+ * 
+ * Copyright (C) 2010 Alexandre WILLAUME, St&eacute;phane GALLAND
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * This program is free software; you can redistribute it and/or modify
+ */
+package org.arakhne.vmutil;
+
+import java.io.IOException;
+
+/**
+ * The exception <code>ResourceNotFoundException</code> is 
+ * thrown when a required Java resource was not found.
+ * 
+ * @author St&eacute;phane GALLAND &lt;galland@xxxxxxxxxxx&gt;
+ * @version $Name$ $Revision$ $Date$
+ */
+public class ResourceNotFoundException extends IOException {
+
+	private static final long serialVersionUID = 4951959393164477007L;
+
+	/**
+	 */
+	public ResourceNotFoundException() {
+		super();
+	}
+		
+	/**
+	 * @param message
+	 */
+	public ResourceNotFoundException(String message) {
+		super(message);
+	}
+
+	/**
+	 * @param cause
+	 */
+	public ResourceNotFoundException(Throwable cause) {
+		super(cause);
+	}
+
+	/**
+	 * @param message
+	 * @param cause
+	 */
+	public ResourceNotFoundException(String message, Throwable cause) {
+		super(message, cause);
+	}
+
+}

Added: tags/afc-2.0/arakhneVmutils/java/src/main/java/org/arakhne/vmutil/ResourceURLConnection.java
===================================================================
--- tags/afc-2.0/arakhneVmutils/java/src/main/java/org/arakhne/vmutil/ResourceURLConnection.java	                        (rev 0)
+++ tags/afc-2.0/arakhneVmutils/java/src/main/java/org/arakhne/vmutil/ResourceURLConnection.java	2010-01-21 08:29:52 UTC (rev 117)
@@ -0,0 +1,154 @@
+/* 
+ * $Id$
+ * 
+ * Copyright (C) 2010 Alexandre WILLAUME, St&eacute;phane GALLAND
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * This program is free software; you can redistribute it and/or modify
+ */
+package org.arakhne.vmutil;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.net.URL;
+import java.net.URLConnection;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * The class <code>ResourceURLConnection</code> is implementing
+ * connection between an URL and a Java resource.
+ * Instances of this class can be used to
+ * read from the resource referenced by the resource URL. Write
+ * is allowed depending on where resource is located.
+ * <p>
+ * Supported header fields are the same as the real resource URL
+ * (basicaly, file or jar protocols).
+ * 
+ * @author St&eacute;phane GALLAND &lt;galland@xxxxxxxxxxx&gt;
+ * @version $Name$ $Revision$ $Date$
+ * @see URLConnection
+ */
+class ResourceURLConnection extends URLConnection {
+
+	private URL location = null;
+	private URLConnection connection = null;
+	
+	/**
+	 * @param url is the "file"-protocol url to use.
+	 */
+	protected ResourceURLConnection(URL url) {
+		super(url);
+	}
+	
+	/**
+     * {@inheritDoc}
+     */
+	@Override
+    public String getHeaderField(int n) {
+		try {
+			connect();
+		}
+		catch(IOException e) {
+			throw new IllegalStateException(e);
+		}
+    	return this.connection.getHeaderField(n);
+    }
+	
+    /**
+     * {@inheritDoc}
+     */
+	@Override
+    public String getHeaderField(String name) {
+		try {
+			connect();
+		}
+		catch(IOException e) {
+			throw new IllegalStateException(e);
+		}
+    	return this.connection.getHeaderField(name);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+	@Override
+    public String getHeaderFieldKey(int n) {
+		try {
+			connect();
+		}
+		catch(IOException e) {
+			throw new IllegalStateException(e);
+		}
+    	return this.connection.getHeaderFieldKey(n);
+    }
+		
+    /**
+     * {@inheritDoc}
+     */
+	@Override
+    public Map<String,List<String>> getHeaderFields() {
+		try {
+			connect();
+		}
+		catch(IOException e) {
+			throw new IllegalStateException(e);
+		}
+    	return this.connection.getHeaderFields();
+    }
+	
+    /**
+	 * {@inheritDoc}
+	 */
+	@Override
+	public void connect() throws IOException {
+		if (!this.connected) {
+			this.location = Resources.getResource(this.url.getFile());
+			if (this.location==null)
+				throw new ResourceNotFoundException(this.url.toExternalForm());
+			this.connection = this.location.openConnection();
+			if (this.connection==null)
+				throw new ResourceNotFoundException(this.url.toExternalForm());
+			this.connection.setDoInput(getDoInput());
+			this.connection.setDoOutput(getDoOutput());
+			this.connection.setAllowUserInteraction(getAllowUserInteraction());
+			this.connection.setConnectTimeout(getConnectTimeout());
+			this.connection.setDefaultUseCaches(getDefaultUseCaches());
+			this.connection.setReadTimeout(getReadTimeout());
+			this.connection.setIfModifiedSince(getIfModifiedSince());
+			this.connected = true;
+		}
+	}
+	
+	/**
+	 * {@inheritDoc}
+	 */
+	@Override
+	public OutputStream getOutputStream() throws IOException {
+        connect();
+        return this.connection.getOutputStream();
+    }
+	
+	/**
+	 * {@inheritDoc}
+	 */
+	@Override
+	public InputStream getInputStream() throws IOException {
+        connect();
+        return this.connection.getInputStream();
+    }
+	
+}

Added: tags/afc-2.0/arakhneVmutils/java/src/main/java/org/arakhne/vmutil/ResourceURLStreamHandler.java
===================================================================
--- tags/afc-2.0/arakhneVmutils/java/src/main/java/org/arakhne/vmutil/ResourceURLStreamHandler.java	                        (rev 0)
+++ tags/afc-2.0/arakhneVmutils/java/src/main/java/org/arakhne/vmutil/ResourceURLStreamHandler.java	2010-01-21 08:29:52 UTC (rev 117)
@@ -0,0 +1,60 @@
+/* 
+ * $Id$
+ * 
+ * Copyright (C) 2010 Alexandre WILLAUME, St&eacute;phane GALLAND
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * This program is free software; you can redistribute it and/or modify
+ */
+package org.arakhne.vmutil;
+
+import java.io.IOException;
+import java.net.URL;
+import java.net.URLConnection;
+import java.net.URLStreamHandler;
+
+/**
+ * The class <code>ResourceURLStreamHandler</code> is supporting resource protocol
+ * for URL streams. This stream protocol
+ * handler knows how to make a connection for "resource" protocol.
+ * <p>
+ * In most cases, an instance of a <code>URLStreamHandler</code>
+ * subclass is not created directly by an application. Rather, the
+ * first time a protocol name is encountered when constructing a
+ * <code>URL</code>, the appropriate stream protocol handler is
+ * automatically loaded.
+ * <p>
+ * To use this factory, invoke the following code only ONCE time:
+ * <code>URL.setURLStreamHandlerFactory(new ResourceURLStreamHandlerFactory());</code>.
+ * 
+ * @author St&eacute;phane GALLAND &lt;galland@xxxxxxxxxxx&gt;
+ * @version $Name$ $Revision$ $Date$
+ * @see URLStreamHandler
+ * @see ResourceURLStreamHandlerFactory
+ */
+class ResourceURLStreamHandler extends URLStreamHandler {
+
+	/**
+	 * {@inheritDoc}
+	 */
+	@Override
+	protected URLConnection openConnection(URL url) throws IOException {
+		if ("resource".equalsIgnoreCase(url.getProtocol())) { //$NON-NLS-1$
+			return new ResourceURLConnection(url);
+		}
+		throw new UnsupportedOperationException("Unsupported protocol: "+url); //$NON-NLS-1$
+	}
+
+}

Added: tags/afc-2.0/arakhneVmutils/java/src/main/java/org/arakhne/vmutil/ResourceURLStreamHandlerFactory.java
===================================================================
--- tags/afc-2.0/arakhneVmutils/java/src/main/java/org/arakhne/vmutil/ResourceURLStreamHandlerFactory.java	                        (rev 0)
+++ tags/afc-2.0/arakhneVmutils/java/src/main/java/org/arakhne/vmutil/ResourceURLStreamHandlerFactory.java	2010-01-21 08:29:52 UTC (rev 117)
@@ -0,0 +1,56 @@
+/* 
+ * $Id$
+ * 
+ * Copyright (C) 2010 St&eacute;phane GALLAND
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * This program is free software; you can redistribute it and/or modify
+ */
+package org.arakhne.vmutil;
+
+import java.net.URL;
+import java.net.URLStreamHandler;
+import java.net.URLStreamHandlerFactory;
+
+/**
+ * This class defines a factory for <code>URL</code> stream
+ * "resource" protocol handlers.
+ * <p>
+ * It is used by the <code>URL</code> class to create a
+ * <code>URLStreamHandler</code> for a "resource" protocol.
+ * <p>
+ * To use this factory, invoke the following code only ONCE time:
+ * <code>URL.setURLStreamHandlerFactory(new ResourceURLStreamHandlerFactory());</code>.
+ * 
+ * @author St&eacute;phane GALLAND &lt;galland@xxxxxxxxxxx&gt;
+ * @version $Name$ $Revision$ $Date$
+ * @see URLStreamHandlerFactory
+ * @see URL#setURLStreamHandlerFactory(URLStreamHandlerFactory)
+ */
+public class ResourceURLStreamHandlerFactory
+implements URLStreamHandlerFactory {
+
+	/**
+	 * {@inheritDoc}
+	 */
+	@Override
+	public URLStreamHandler createURLStreamHandler(String protocol) {
+		if ("resource".equalsIgnoreCase(protocol)) //$NON-NLS-1$
+            return new ResourceURLStreamHandler();
+		// Force the default factory to retreive stream handler.
+		return null;
+	}
+
+}

Added: tags/afc-2.0/arakhneVmutils/java/src/main/java/org/arakhne/vmutil/Resources.java
===================================================================
--- tags/afc-2.0/arakhneVmutils/java/src/main/java/org/arakhne/vmutil/Resources.java	                        (rev 0)
+++ tags/afc-2.0/arakhneVmutils/java/src/main/java/org/arakhne/vmutil/Resources.java	2010-01-21 08:29:52 UTC (rev 117)
@@ -0,0 +1,152 @@
+/* 
+ * $Id$
+ * 
+ * Copyright (C) 2004-2009 St&eacute;phane GALLAND
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * This program is free software; you can redistribute it and/or modify
+ */
+
+package org.arakhne.vmutil;
+
+import java.io.InputStream;
+import java.net.URL;
+
+/**
+ * This utility class provides to load resources according to
+ * several heuristics:<ul>
+ * <li>search the resource in class paths;</li>
+ * <li>search the resource in ./resources subdirectory in class paths.</li>
+ * </ul>
+ * 
+ * @author St&eacute;phane GALLAND &lt;galland@xxxxxxxxxxx&gt;
+ * @version $Name$ $Revision$ $Date$
+ * @since since JDK 1.5
+ */
+public class Resources {
+
+    /**
+     * Replies the URL of a resource.
+     * <p>
+     * You may use Unix-like syntax to write the resource path, ie.
+     * you may use slashs to separate filenames, and may not start the
+     * path with a slash.
+     *
+     * @param path is the absolute path of the resource. 
+     * @return the url of the resource or <code>null</code> if the resource was
+     * not found in class paths.
+     */
+    public static URL getResource(String path) {
+    	return getResource(ClassLoaderFinder.findClassLoader(), path);
+    }
+
+   	/**
+     * Replies the URL of a resource.
+     * <p>
+     * You may use Unix-like syntax to write the resource path, ie.
+     * you may use slashs to separate filenames, and may not start the
+     * path with a slash.
+     *
+     * @param clazz is the class which is restricting the scope of the search.
+     * @param path is the absolute path of the resource. 
+     * @return the url of the resource or <code>null</code> if the resource was
+     * not found in class paths.
+     */
+    public static URL getResource(Class<?> clazz, String path) {
+    	return getResource(clazz.getClassLoader(), path);
+    }
+
+   	/**
+     * Replies the URL of a resource.
+     * <p>
+     * You may use Unix-like syntax to write the resource path, ie.
+     * you may use slashs to separate filenames, and may not start the
+     * path with a slash.
+     *
+     * @param classLoader is the research scope.
+     * @param path is the absolute path of the resource. 
+     * @return the url of the resource or <code>null</code> if the resource was
+     * not found in class paths.
+     */
+    public static URL getResource(ClassLoader classLoader, String path) {
+    	String resourcePath = path;
+    	if (path.startsWith("/")) { //$NON-NLS-1$
+    		resourcePath = path.substring(1);
+    	}
+    	URL url = classLoader.getResource(resourcePath);
+    	if (url==null) {
+    		// Try to find in ./resources sub directory
+    		url = classLoader.getResource("resources/"+resourcePath); //$NON-NLS-1$
+    	}
+    	return url;
+    }
+    
+    /**
+     * Replies the input stream of a resource.
+     * <p>
+     * You may use Unix-like syntax to write the resource path, ie.
+     * you may use slashs to separate filenames, and may not start the
+     * path with a slash.
+     *
+     * @param path is the absolute path of the resource. 
+     * @return the url of the resource or <code>null</code> if the resource was
+     * not found in class paths.
+     */
+    public static InputStream getResourceAsStream(String path) {
+    	return getResourceAsStream(ClassLoaderFinder.findClassLoader(), path);
+    }
+    
+    /**
+     * Replies the input stream of a resource.
+     * <p>
+     * You may use Unix-like syntax to write the resource path, ie.
+     * you may use slashs to separate filenames, and may not start the
+     * path with a slash.
+     *
+     * @param clazz is the class which is restricting the scope of the search.
+     * @param path is the absolute path of the resource. 
+     * @return the url of the resource or <code>null</code> if the resource was
+     * not found in class paths.
+     */
+    public static InputStream getResourceAsStream(Class<?> clazz, String path) {
+    	return getResourceAsStream(clazz.getClassLoader(), path);
+    }
+
+    /**
+     * Replies the input stream of a resource.
+     * <p>
+     * You may use Unix-like syntax to write the resource path, ie.
+     * you may use slashs to separate filenames, and may not start the
+     * path with a slash.
+     *
+     * @param classLoader is the research scope.
+     * @param path is the absolute path of the resource. 
+     * @return the url of the resource or <code>null</code> if the resource was
+     * not found in class paths.
+     */
+    public static InputStream getResourceAsStream(ClassLoader classLoader, String path) {
+    	String resourcePath = path;
+    	if (path.startsWith("/")) { //$NON-NLS-1$
+    		resourcePath = path.substring(1);
+    	}
+    	InputStream is = classLoader.getResourceAsStream(resourcePath);
+    	if (is==null) {
+    		// Try to find in ./resources sub directory
+    		is = classLoader.getResourceAsStream("resources/"+resourcePath); //$NON-NLS-1$
+    	}
+    	return is;
+    }
+
+}

Added: tags/afc-2.0/arakhneVmutils/java/src/main/java/org/arakhne/vmutil/ThreadServiceFinder.java
===================================================================
--- tags/afc-2.0/arakhneVmutils/java/src/main/java/org/arakhne/vmutil/ThreadServiceFinder.java	                        (rev 0)
+++ tags/afc-2.0/arakhneVmutils/java/src/main/java/org/arakhne/vmutil/ThreadServiceFinder.java	2010-01-21 08:29:52 UTC (rev 117)
@@ -0,0 +1,119 @@
+/* 
+ * $Id$
+ * 
+ * Copyright (C) 2005-2010 St&eacute;phane GALLAND
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * This program is free software; you can redistribute it and/or modify
+ */
+package org.arakhne.vmutil;
+
+import java.util.EmptyStackException;
+import java.util.Stack;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.ScheduledExecutorService;
+
+/**
+ * This class permits to centralize the identify of the thread service providers. 
+ *
+ * @author St&eacute;phane GALLAND &lt;galland@xxxxxxxxxxx&gt;
+ * @version $Name$ $Revision$ $Date$
+ */
+public class ThreadServiceFinder {
+
+	private static final Stack<ThreadServiceProvider> __services = new Stack<ThreadServiceProvider>();
+	
+	static {
+		// Add the default provider
+		__services.push(new DefaultProvider());
+	}
+	
+    /**
+     * Replies the current service provider.
+	 * 
+     * @return the thread service provider or <code>null</code>
+     */
+    public static ThreadServiceProvider getProvider() {
+    	try {
+    		return __services.peek();
+    	}
+    	catch(EmptyStackException _) {
+    		return null;
+    	}
+    }
+
+    /**
+     * Add a preferred provider.
+	 * 
+     * @param provider is the preferred thread service provider
+     */
+    public static void addPreferredProvider(ThreadServiceProvider provider) {
+    	__services.push(provider);
+    }
+
+    /**
+     * Remove a provider.
+	 * 
+     * @param provider is the preferred thread service provider
+     */
+    public static void removeProvider(ThreadServiceProvider provider) {
+    	__services.remove(provider);
+    }
+
+    /**
+     * Remove a provider.
+     */
+    public static void removeProvider() {
+    	__services.pop();
+    }
+
+    /**
+     * @author St&eacute;phane GALLAND &lt;stephane.galland@xxxxxxx&gt;
+     * @version $Name$ $Revision$ $Date$
+     * @mavengroupid fr.utbm.set
+     * @mavenartifactid setutil
+     */
+    static class DefaultProvider implements ThreadServiceProvider {
+
+    	private ExecutorService __executor_service = null;
+    	
+    	private ScheduledExecutorService __scheduled_executor_service = null;
+    	
+		/** {@inheritDoc}
+		 * 
+		 * @return {@inheritDoc}
+		 */
+		public ExecutorService getExecutorService() {
+			if (this.__executor_service==null) {
+				this.__executor_service = Executors.newCachedThreadPool();
+			}
+			return this.__executor_service;
+		}
+
+		/** {@inheritDoc}
+		 * 
+		 * @return {@inheritDoc}
+		 */
+		public ScheduledExecutorService getScheduledExecutorService() {
+			if (this.__scheduled_executor_service==null) {
+				this.__scheduled_executor_service = Executors.newScheduledThreadPool(3);
+			}
+			return this.__scheduled_executor_service;
+		}
+
+    }
+    
+}

Added: tags/afc-2.0/arakhneVmutils/java/src/main/java/org/arakhne/vmutil/ThreadServiceProvider.java
===================================================================
--- tags/afc-2.0/arakhneVmutils/java/src/main/java/org/arakhne/vmutil/ThreadServiceProvider.java	                        (rev 0)
+++ tags/afc-2.0/arakhneVmutils/java/src/main/java/org/arakhne/vmutil/ThreadServiceProvider.java	2010-01-21 08:29:52 UTC (rev 117)
@@ -0,0 +1,46 @@
+/* 
+ * $Id$
+ * 
+ * Copyright (C) 2005-2010 St&eacute;phane GALLAND
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * This program is free software; you can redistribute it and/or modify
+ */
+package org.arakhne.vmutil;
+
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.ScheduledExecutorService;
+
+/**
+ * This interface describes a provider of thread's service.. 
+ *
+ * @author St&eacute;phane GALLAND &lt;galland@xxxxxxxxxxx&gt;
+ * @version $Name$ $Revision$ $Date$
+ */
+public interface ThreadServiceProvider {
+
+	/** Replies the thread executor for this provider.
+	 * 
+	 * @return the default executor service.
+	 */
+	public ExecutorService getExecutorService();
+	
+	/** Replies the scheduled thread executor for this provider.
+	 * 
+	 * @return the default scheduled executor service.
+	 */
+	public ScheduledExecutorService getScheduledExecutorService();
+	
+}

Added: tags/afc-2.0/arakhneVmutils/java/src/main/java/org/arakhne/vmutil/VMCommandLine.java
===================================================================
--- tags/afc-2.0/arakhneVmutils/java/src/main/java/org/arakhne/vmutil/VMCommandLine.java	                        (rev 0)
+++ tags/afc-2.0/arakhneVmutils/java/src/main/java/org/arakhne/vmutil/VMCommandLine.java	2010-01-21 08:29:52 UTC (rev 117)
@@ -0,0 +1,749 @@
+/* 
+ * $Id$
+ * 
+ * Copyright (C) 2004-2009 St&eacute;phane GALLAND
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * This program is free software; you can redistribute it and/or modify
+ */
+
+package org.arakhne.vmutil;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import java.util.SortedMap;
+import java.util.TreeMap;
+import java.util.Map.Entry;
+
+/**
+ * This utility class permits to get the java command line for the current VM.  
+ *
+ * @author St&eacute;phane GALLAND &lt;galland@xxxxxxxxxxx&gt;
+ * @version $Name$ $Revision$ $Date$
+ */
+public class VMCommandLine {
+
+	private static Class<?> classToLaunch = null;
+	private static boolean analyzed = false;
+	private static SortedMap<String,List<Object>> commandLineOptions = null;
+	private static String[] commandLineParameters = null;
+	
+	/** Replies a binary executable filename depending of the current platform.
+	 * 
+	 * @param name is the name which must be converted into a binary executable filename.
+	 * @return the binary executable filename.
+	 */
+	public static String getExecutableFilename(String name) {
+		if (OperatingSystem.WIN.isCurrentOS()) return name+".exe"; //$NON-NLS-1$
+		return name;
+	}
+	
+	/** Replies the current java VM binary.
+	 * 
+	 * @return the binary executable filename that was used to launch the virtual machine.
+	 */
+	public static String getVMBinary() {
+		String java_home = System.getProperty("java.home"); //$NON-NLS-1$
+		File bin_dir = new File(new File(java_home),"bin"); //$NON-NLS-1$
+		if (bin_dir.isDirectory()) {
+			File exec = new File(bin_dir,getExecutableFilename("javaw")); //$NON-NLS-1$
+			if (exec.isFile()) {
+				return exec.getAbsolutePath();
+			}
+			exec = new File(bin_dir,getExecutableFilename("java")); //$NON-NLS-1$
+			if (exec.isFile()) {
+				return exec.getAbsolutePath();
+			}			
+		}
+		return null;
+	}
+	
+	/** Run a new VM with the class path of the current VM.
+	 * 
+	 * @param class_to_launch is the class to launch.
+	 * @param additional_params is the list of additional parameters
+	 * @return the process that is running the new virtual machine, neither <code>null</code>
+	 * @throws IOException 
+	 */
+	public static Process launchVM(Class<?> class_to_launch, String... additional_params) throws IOException {
+		String java_bin = getVMBinary();
+		if (java_bin==null) throw new FileNotFoundException("java"); //$NON-NLS-1$
+		long totalMemory = Runtime.getRuntime().maxMemory() / 1024;
+		String classpath = System.getProperty("java.class.path"); //$NON-NLS-1$
+		String user_dir = System.getProperty("user.dir"); //$NON-NLS-1$
+		String[] params = new String[additional_params.length+5];
+		params[0] = java_bin;
+		params[1] = "-Xmx"+totalMemory+"k"; //$NON-NLS-1$ //$NON-NLS-2$
+		params[2] = "-classpath"; //$NON-NLS-1$
+		params[3] = classpath;
+		params[4] = class_to_launch.getCanonicalName();
+		System.arraycopy(additional_params,0,params,5,additional_params.length);
+		return Runtime.getRuntime().exec(params,null,new File(user_dir));
+	}
+
+	/** Save parameters that permit to relaunch a VM with
+	 * {@link #relaunchVM()}.
+	 * 
+	 * @param class_to_launch is the class which contains a <code>main</code>.
+	 * @param parameters is the parameters to pass to the <code>main</code>.
+	 */
+	public static void saveVMParameters(Class<?> class_to_launch, String... parameters) {
+		classToLaunch = class_to_launch;
+		commandLineParameters = parameters;
+		if (commandLineOptions!=null) commandLineOptions.clear();
+		commandLineOptions = null;
+		analyzed = false;
+	}
+
+	/** Save parameters that permit to relaunch a VM with
+	 * {@link #relaunchVM()}.
+	 * 
+	 * @param class_to_launch is the class which contains a <code>main</code>.
+	 * @param parameters is the parameters to pass to the <code>main</code>.
+	 */
+	public static void saveVMParametersIfNotSet(Class<?> class_to_launch, String... parameters) {
+		if (classToLaunch==null) {
+			saveVMParameters(class_to_launch, parameters);
+		}
+	}
+
+	/** Launch a VM with the same parameters as ones saved by
+	 * {@link #saveVMParameters(Class, String[])}.
+	 * 
+	 * @return the process that is running the new virtual machine, neither <code>null</code>
+	 * @throws IOException 
+	 */
+	public static Process relaunchVM() throws IOException {
+		if (classToLaunch==null) return null;		
+		return launchVM(classToLaunch, getAllCommandLineParameters());
+	}
+
+	/** Replies the command line including the options and the standard parameters.
+	 * 
+	 * @return  the command line.
+	 */
+	public static String[] getAllCommandLineParameters() {
+		int osize = commandLineOptions==null ? 0 : commandLineOptions.size();
+		int psize = commandLineParameters==null ? 0 : commandLineParameters.length;
+		int tsize = (osize>0 && psize>0) ? 1 : 0;
+		List<String> params = new ArrayList<String>(osize+tsize);
+		if (osize>0) {
+			List<Object> values;
+			String name, prefix, v;
+			for(Entry<String,List<Object>> entry : commandLineOptions.entrySet()) {
+				name = entry.getKey();
+				prefix = (name.length()>1) ? "--" : "-"; //$NON-NLS-1$ //$NON-NLS-2$
+				values = entry.getValue();
+				if (values==null || values.isEmpty()) {
+					params.add(prefix+name);
+				}
+				else {
+					for(Object value : values) {
+						if (value!=null) {
+							v = value.toString();
+							if (v!=null && v.length()>0) {
+								params.add(prefix+name+"="+v); //$NON-NLS-1$
+							}
+							else {
+								params.add(prefix+name);
+							}
+						}
+					}
+				}
+			}
+		}
+		if (tsize>0) params.add("--"); //$NON-NLS-1$
+		
+		String[] tab = new String[params.size()+psize];
+		params.toArray(tab);
+		params.clear();
+		
+		if (psize>0)
+			System.arraycopy(commandLineParameters, 0, tab, osize+tsize, psize);
+		
+		return tab;
+	}
+
+	/** Replies the command line parameters.
+	 * 
+	 * @return the list of the parameters on the command line
+	 */
+	public static String[] getCommandLineParameters() {
+		return commandLineParameters==null ? new String[0] : commandLineParameters;
+	}
+	
+	/** Shift the command line parameters by one on the left.
+	 * The first parameter is removed from the list.
+	 * 
+	 * @return the removed element or <code>null</code>
+	 */
+	public static String shiftCommandLineParameters() {
+		String removed = null;
+		if (commandLineParameters!=null) {
+			if (commandLineParameters.length==0) {
+				commandLineParameters = null;
+			}
+			else if (commandLineParameters.length==1) {
+				removed = commandLineParameters[0];
+				commandLineParameters = null;
+			}
+			else {
+				removed = commandLineParameters[0];
+				String[] newTab = new String[commandLineParameters.length-1];
+				System.arraycopy(commandLineParameters,1,newTab,0,commandLineParameters.length-1);
+				commandLineParameters = newTab;
+			}
+		}
+		return removed;
+	}
+
+	/** Replies the command line options.
+	 * 
+	 * @return the list of options passed on the command line
+	 */
+	public static Map<String,List<Object>> getCommandLineOptions() {
+		if (commandLineOptions!=null)
+			return Collections.unmodifiableSortedMap(commandLineOptions);
+		return Collections.emptyMap();
+	}
+	
+	/** Replies one command option.
+	 *
+	 * @param name is the name of the option
+	 * @return the option value or <code>null</code> if the option is not on the command line.
+	 */
+	public static List<Object> getCommandLineOption(String name) {
+		if (commandLineOptions!=null) {
+			if (commandLineOptions.containsKey(name)) {
+				List<Object> value = commandLineOptions.get(name);
+				return value==null ? Collections.emptyList() : value;
+			}
+		}
+		return null;
+	}
+
+	/** Replies if an option was specified on the command line.
+	 *
+	 * @param name is the name of the option
+	 * @return <code>true</code> if the option was found on the command line, otherwise <code>false</code>.
+	 */
+	public static boolean hasCommandLineOption(String name) {
+		return (commandLineOptions!=null && commandLineOptions.containsKey(name));
+	}
+
+	private static boolean registerOptionValue(SortedMap<String,List<Object>> options, String name, Object value, OptionType type) {
+		boolean success = true;
+		
+		Object optValue = value;
+		
+		List<Object> values = options.get(name);
+		if (values==null) {
+			values = new ArrayList<Object>();
+			options.put(name, values);
+		}
+		switch(type) {
+		case AUTO_INCREMENTED:
+			{
+				long v;
+				if (values.isEmpty()) v = -1;
+				else {
+					optValue = values.get(0);
+					if (optValue==null) v = 0;
+					else if (!(optValue instanceof Number)) {
+						v = Long.parseLong(optValue.toString());
+					}
+					else {
+						v = ((Number)optValue).longValue();
+					}
+				}
+				if (values.isEmpty()) values.add(Long.valueOf(v+1));
+				else values.set(0, Long.valueOf(v+1));
+			}
+			break;
+		case FLAG:
+			if (optValue==null) {
+				if (values.isEmpty())
+					optValue = Boolean.TRUE;
+				else
+					optValue = values.get(0);
+			}
+			else if (!(optValue instanceof Boolean)) {
+				optValue = Boolean.parseBoolean(optValue.toString());
+			}
+			if (values.isEmpty()) values.add(optValue);
+			else values.set(0, optValue);
+			break;
+		case MANDATORY_BOOLEAN:
+		case OPTIONAL_BOOLEAN:
+			if (optValue==null) {
+				optValue = Boolean.TRUE;
+			}
+			else if (!(optValue instanceof Boolean)) {
+				optValue = Boolean.parseBoolean(optValue.toString());
+			}
+			values.add(optValue);
+			break;
+		case MANDATORY_FLOAT:
+		case OPTIONAL_FLOAT:
+			try {
+				if (optValue==null) {
+					optValue = Double.valueOf(0.);
+				}
+				else if (!(optValue instanceof Number)) {
+					optValue = Double.parseDouble(optValue.toString());
+				}
+				else {
+					optValue = Double.valueOf(((Number)optValue).doubleValue());
+				}
+			}
+			catch(NumberFormatException e) {
+				if (type.isOptional()) {
+					success = false;
+					optValue = Double.valueOf(0.);
+				}
+				else throw e;
+			}
+			values.add(optValue);
+			break;
+		case MANDATORY_INTEGER:
+		case OPTIONAL_INTEGER:
+			try {
+				if (optValue==null) {
+					optValue = Long.valueOf(0);
+				}
+				else if (!(optValue instanceof Number)) {
+					optValue = Long.parseLong(optValue.toString());
+				}
+				else {
+					optValue = Long.valueOf(((Number)optValue).longValue());
+				}
+			}
+			catch(NumberFormatException e) {
+				if (type.isOptional()) {
+					success = false;
+					optValue = Long.valueOf(0);
+				}
+				else throw e;
+			}
+			values.add(optValue);
+			break;
+		case MANDATORY_STRING:
+		case OPTIONAL_STRING:
+			values.add(optValue==null ? "" : optValue.toString()); //$NON-NLS-1$
+			break;
+		case SIMPLE:
+			values.add(optValue);
+			break;
+		}
+		
+		return success;
+	}
+	
+	/** Analyse the command line to extract the options.
+	 * <p>
+	 * The options will be recognized thanks to the <var>optionDefinitions</var>.
+	 * Each entry of <var>optionDefinitions</var> describes an option. They must
+	 * have one of the following formats:
+	 * <ul>
+	 * <li>{@code name}: a simple option without value or flag,</li>
+	 * <li>{@code name=s}: an option with a mandatory string value,</li>
+	 * <li>{@code name:s}: an option with an optional string value,</li>
+	 * <li>{@code name=i}: an option with a mandatory integer value,</li>
+	 * <li>{@code name:i}: an option with an optional integer value,</li>
+	 * <li>{@code name=f}: an option with a mandatory floating-point value,</li>
+	 * <li>{@code name:f}: an option with an optional floating-point value,</li>
+	 * <li>{@code name=b}: an option with a mandatory boolean value,</li>
+	 * <li>{@code name:b}: an option with an optional boolean value,</li>
+	 * <li>{@code name+}: an option with an autoincremented integer value,</li>
+	 * <li>{@code name!}: an option which could be flaged or not: {@code --name} or {@code --noname}.</li>
+	 * </ul>
+	 * 
+	 * @param optionDefinitions is the list of definitions of the available command line options.
+	 */
+	public static void splitOptionsAndParameters(String... optionDefinitions) {
+		if (analyzed) return;
+		
+		List<String> params = new ArrayList<String>();
+		SortedMap<String,List<Object>> options = new TreeMap<String,List<Object>>();
+		String opt;
+
+		// Analyze definitions
+		Map<String,OptionType> defs = new TreeMap<String,OptionType>();
+		for (String def : optionDefinitions) {
+			if (def.endsWith("!")) { //$NON-NLS-1$
+				opt = def.substring(0, def.length()-1);
+				defs.put(opt, OptionType.FLAG);
+				registerOptionValue(options, opt, Boolean.FALSE, OptionType.FLAG);
+			}
+			else if (def.endsWith("+")) { //$NON-NLS-1$
+				opt = def.substring(0, def.length()-1);
+				defs.put(opt, OptionType.AUTO_INCREMENTED);
+				registerOptionValue(options, opt, Long.valueOf(0), OptionType.AUTO_INCREMENTED);
+			}
+			else if (def.endsWith("=b")) { //$NON-NLS-1$
+				opt = def.substring(0, def.length()-2);
+				defs.put(opt, OptionType.MANDATORY_BOOLEAN);
+			}
+			else if (def.endsWith(":b")) { //$NON-NLS-1$
+				opt = def.substring(0, def.length()-2);
+				defs.put(opt, OptionType.OPTIONAL_BOOLEAN);
+			}
+			else if (def.endsWith("=f")) { //$NON-NLS-1$
+				opt = def.substring(0, def.length()-2);
+				defs.put(opt, OptionType.MANDATORY_FLOAT);
+			}
+			else if (def.endsWith(":f")) { //$NON-NLS-1$
+				opt = def.substring(0, def.length()-2);
+				defs.put(opt, OptionType.OPTIONAL_FLOAT);
+			}
+			else if (def.endsWith("=i")) { //$NON-NLS-1$
+				opt = def.substring(0, def.length()-2);
+				defs.put(opt, OptionType.MANDATORY_INTEGER);
+			}
+			else if (def.endsWith(":i")) { //$NON-NLS-1$
+				opt = def.substring(0, def.length()-2);
+				defs.put(opt, OptionType.OPTIONAL_INTEGER);
+			}
+			else if (def.endsWith("=s")) { //$NON-NLS-1$
+				opt = def.substring(0, def.length()-2);
+				defs.put(opt, OptionType.MANDATORY_STRING);
+			}
+			else if (def.endsWith(":s")) { //$NON-NLS-1$
+				opt = def.substring(0, def.length()-2);
+				defs.put(opt, OptionType.OPTIONAL_STRING);
+			}
+			else {
+				defs.put(def, OptionType.SIMPLE);
+			}
+		}
+		
+		int idx;
+		String base, nbase, val;
+		OptionType type;
+		OptionType waitingValue = null;
+		String valueOptionName = null;
+		boolean allParameters = false;
+		boolean success;
+		
+		for(String param : commandLineParameters) {
+			if (allParameters) {
+				params.add(param);
+				continue;
+			}
+			
+			if (waitingValue!=null && waitingValue.isMandatory()) {
+				// Expect a value as the next parameter
+				success = registerOptionValue(options, valueOptionName, param, waitingValue);
+				waitingValue = null;
+				valueOptionName = null;
+				if (success) continue;
+			}
+			
+			if ("--".equals(param)) { //$NON-NLS-1$
+				if (waitingValue!=null) {
+					registerOptionValue(options, valueOptionName, null, waitingValue);
+					waitingValue = null;
+					valueOptionName = null;
+				}
+				allParameters = true;
+				continue;
+			}
+			else if ((File.separatorChar!='/')&&(param.startsWith("/"))) { //$NON-NLS-1$
+				opt = param.substring(1);
+			}
+			else if (param.startsWith("--")) { //$NON-NLS-1$
+				opt = param.substring(2);
+			}
+			else if (param.startsWith("-")) { //$NON-NLS-1$
+				opt = param.substring(1);
+			}
+			else if (waitingValue!=null) {
+				success = registerOptionValue(options, valueOptionName, param, waitingValue);
+				waitingValue = null;
+				valueOptionName = null;
+				if (!success) params.add(param);
+				continue;
+			}
+			else {
+				params.add(param);
+				continue;
+			}
+			
+			if (waitingValue!=null) {
+				success = registerOptionValue(options, valueOptionName, param, waitingValue);
+				waitingValue = null;
+				valueOptionName = null;
+				if (success) continue;
+			}
+
+			idx = opt.indexOf('=');
+			if (idx>0) {
+				base = opt.substring(0,idx);
+				val = opt.substring(idx+1);
+			}
+			else {
+				base = opt;
+				val = null;
+			}
+
+			nbase = null;
+			type = defs.get(base);
+			if (type==null && base.toLowerCase().startsWith("no")) { //$NON-NLS-1$
+				nbase = base.substring(2);
+				type = defs.get(nbase);
+			}
+			if (type!=null) {
+				switch(type) {
+				case FLAG:
+					if (nbase==null)
+						registerOptionValue(options, base, Boolean.TRUE, type);
+					else
+						registerOptionValue(options, nbase, Boolean.FALSE, type);
+					break;
+				case MANDATORY_FLOAT:
+				case MANDATORY_BOOLEAN:
+				case MANDATORY_INTEGER:
+				case MANDATORY_STRING:
+				case OPTIONAL_FLOAT:
+				case OPTIONAL_BOOLEAN:
+				case OPTIONAL_INTEGER:
+				case OPTIONAL_STRING:
+					if (val!=null) {
+						registerOptionValue(options, base, val, type);
+					}
+					else {
+						waitingValue = type;
+						valueOptionName = base;
+					}
+					break;
+				default:
+					registerOptionValue(options, base, val, type);
+				}
+			}
+			else {
+				// Not a recognized option, assuming simple
+				registerOptionValue(options, base, val, OptionType.SIMPLE);
+			}
+		}
+		
+		if (waitingValue!=null && waitingValue.isMandatory()) {
+			throw new IllegalStateException("expected a value for command line option "+valueOptionName); //$NON-NLS-1$
+		}
+		
+		commandLineParameters = new String[params.size()];
+		params.toArray(commandLineParameters);
+		params.clear();
+
+		commandLineOptions = options;
+		
+		analyzed = true;
+	}
+	
+	/**
+	 * Create a interface to the command line options.
+	 * 
+	 * @param class_to_launch is the class which contains a <code>main</code>.
+	 * @param parameters is the parameters to pass to the <code>main</code>.
+	 * @see #saveVMParametersIfNotSet(Class, String[])
+	 */
+	public VMCommandLine(Class<?> class_to_launch, String... parameters) {
+		saveVMParametersIfNotSet(class_to_launch, parameters);
+	}
+	
+	/**
+	 * Create a interface to the command line options.
+	 * 
+	 * @param class_to_launch is the class which contains a <code>main</code>.
+	 * @param optionDefinitions is the list of definitions of the available command line options.
+	 * @param parameters is the parameters to pass to the <code>main</code>.
+	 * @see #saveVMParametersIfNotSet(Class, String[])
+	 * @see #splitOptionsAndParameters(String[])
+	 */
+	public VMCommandLine(Class<?> class_to_launch, String[] optionDefinitions, String... parameters) {
+		saveVMParametersIfNotSet(class_to_launch, parameters);
+		splitOptionsAndParameters(optionDefinitions);
+	}
+
+	/**
+	 * Create a interface to the command line options.
+	 * 
+	 * @see #VMCommandLine(Class, String[], String[])
+	 * @see #VMCommandLine(Class, String[])
+	 */
+	public VMCommandLine() {
+		if (classToLaunch==null) {
+			throw new IllegalArgumentException("you must call the other constructor previously"); //$NON-NLS-1$
+		}
+	}
+	
+	/** Replies if the given option is present on the command line.
+	 * 
+	 * @param optionLabel is the name of the option
+	 * @return <code>true</code> if the option is present, otherwise <code>false</code>
+	 */
+	public boolean hasOption(String optionLabel) {
+		return hasCommandLineOption(optionLabel);
+	}
+
+	/** Replies the first value of the option.
+	 * 
+	 * @param optionLabel is the name of the option
+	 * @return the option value or <code>null</code> if the option is not present or has no value.
+	 */
+	public Object getFirstOptionValue(String optionLabel) {
+		List<Object> options = getCommandLineOption(optionLabel);
+		if (options==null || options.isEmpty()) return null;
+		return options.get(0);
+	}
+
+	/** Replies the values of the option.
+	 * 
+	 * @param optionLabel is the name of the option
+	 * @return the option values or <code>null</code> if the option is not present.
+	 */
+	public List<Object> getOptionValues(String optionLabel) {
+		List<Object> options = getCommandLineOption(optionLabel);
+		if (options==null) return null;
+		return Collections.unmodifiableList(options);
+	}
+
+	/** Replies the parameters on the command line that are not options.
+	 * 
+	 * @return the parameters.
+	 */
+	public String[] getParameters() {
+		return getCommandLineParameters();
+	}
+
+	/** Shift the command line parameters by one on the left.
+	 * The first parameter is removed from the list.
+	 * 
+	 * @return the removed element or <code>null</code>
+	 */
+	public String shiftParameters() {
+		return shiftCommandLineParameters();
+	}
+
+	/** Replies the count of parameters on the command line that are not options.
+	 * 
+	 * @return the count of parameters
+	 */
+	public int getParameterCount() {
+		return getCommandLineParameters().length;
+	}
+
+	/** Replies the parameter at the specified index.
+	 * 
+	 * @param index
+	 * @return the value of the parameter.
+	 * @throws IndexOutOfBoundsException
+	 */
+	public String getParameterAt(int index) {
+		return getCommandLineParameters()[index];
+	}
+
+	/** Replies if the given index corresponds to a command line parameter.
+	 * 
+	 * @param index
+	 * @return <code>true</code> if the given index corresponds to a parameter,
+	 * otherwise <code>false</code>
+	 * @throws IndexOutOfBoundsException
+	 */
+	public boolean isParameterExists(int index) {
+		String[] params = getCommandLineParameters();
+		return index>=0 && index<params.length && params[index]!=null;
+	}
+
+	/**
+	 * @author St&eacute;phane GALLAND &lt;galland@xxxxxxxxxxx&gt;
+	 * @version $Name$ $Revision$ $Date$
+	 */
+	private static enum OptionType {
+
+		/**
+		 * a simple option without value or flag.
+		 */
+		SIMPLE,
+		
+		/** an option with a mandatory string value.
+		 */
+		MANDATORY_STRING,
+
+		/** an option with an optional string value.
+		 */
+		OPTIONAL_STRING,
+
+		/** an option with a mandatory integer value.
+		 */
+		MANDATORY_INTEGER,
+
+		/** an option with an optional integer value.
+		 */
+		OPTIONAL_INTEGER,
+
+		/** an option with a mandatory floating-point value.
+		 */
+		MANDATORY_FLOAT,
+
+		/** an option with an optional floating-point value.
+		 */
+		OPTIONAL_FLOAT,
+
+		/** an option with a mandatory boolean value.
+		 */
+		MANDATORY_BOOLEAN,
+
+		/** an option with an optional boolean value.
+		 */
+		OPTIONAL_BOOLEAN,
+
+		/** an option with an auto-incremented integer value.
+		 */
+		AUTO_INCREMENTED,
+
+		/** an option which could be flaged or not: {@code --name} or {@code --noname}.
+		 */
+		FLAG;
+		
+		/** Replies if the value is mandatory.
+		 * 
+		 * @return <code>true</code> if the value is mandatory, otherwise <code>false</code>
+		 */
+		public boolean isMandatory() {
+			return this==MANDATORY_BOOLEAN
+			|| this==MANDATORY_FLOAT
+			|| this==MANDATORY_STRING
+			|| this==MANDATORY_INTEGER;
+		}
+		
+		/** Replies if the value is optional.
+		 * 
+		 * @return <code>true</code> if the value is not mandatory, otherwise <code>false</code>
+		 */
+		public boolean isOptional() {
+			return this==OPTIONAL_BOOLEAN
+			|| this==OPTIONAL_FLOAT
+			|| this==OPTIONAL_STRING
+			|| this==OPTIONAL_INTEGER;
+		}
+
+	}
+
+}

Added: tags/afc-2.0/arakhneVmutils/java/src/main/resources/AUTHORS
===================================================================
--- tags/afc-2.0/arakhneVmutils/java/src/main/resources/AUTHORS	                        (rev 0)
+++ tags/afc-2.0/arakhneVmutils/java/src/main/resources/AUTHORS	2010-01-21 08:29:52 UTC (rev 117)
@@ -0,0 +1 @@
+Stephane GALLAND <galland@xxxxxxxxxxx>

Added: tags/afc-2.0/arakhneVmutils/java/src/main/resources/COPYING
===================================================================
--- tags/afc-2.0/arakhneVmutils/java/src/main/resources/COPYING	                        (rev 0)
+++ tags/afc-2.0/arakhneVmutils/java/src/main/resources/COPYING	2010-01-21 08:29:52 UTC (rev 117)
@@ -0,0 +1,165 @@
+		   GNU LESSER GENERAL PUBLIC LICENSE
+                       Version 3, 29 June 2007
+
+ Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+
+  This version of the GNU Lesser General Public License incorporates
+the terms and conditions of version 3 of the GNU General Public
+License, supplemented by the additional permissions listed below.
+
+  0. Additional Definitions. 
+
+  As used herein, "this License" refers to version 3 of the GNU Lesser
+General Public License, and the "GNU GPL" refers to version 3 of the GNU
+General Public License.
+
+  "The Library" refers to a covered work governed by this License,
+other than an Application or a Combined Work as defined below.
+
+  An "Application" is any work that makes use of an interface provided
+by the Library, but which is not otherwise based on the Library.
+Defining a subclass of a class defined by the Library is deemed a mode
+of using an interface provided by the Library.
+
+  A "Combined Work" is a work produced by combining or linking an
+Application with the Library.  The particular version of the Library
+with which the Combined Work was made is also called the "Linked
+Version".
+
+  The "Minimal Corresponding Source" for a Combined Work means the
+Corresponding Source for the Combined Work, excluding any source code
+for portions of the Combined Work that, considered in isolation, are
+based on the Application, and not on the Linked Version.
+
+  The "Corresponding Application Code" for a Combined Work means the
+object code and/or source code for the Application, including any data
+and utility programs needed for reproducing the Combined Work from the
+Application, but excluding the System Libraries of the Combined Work.
+
+  1. Exception to Section 3 of the GNU GPL.
+
+  You may convey a covered work under sections 3 and 4 of this License
+without being bound by section 3 of the GNU GPL.
+
+  2. Conveying Modified Versions.
+
+  If you modify a copy of the Library, and, in your modifications, a
+facility refers to a function or data to be supplied by an Application
+that uses the facility (other than as an argument passed when the
+facility is invoked), then you may convey a copy of the modified
+version:
+
+   a) under this License, provided that you make a good faith effort to
+   ensure that, in the event an Application does not supply the
+   function or data, the facility still operates, and performs
+   whatever part of its purpose remains meaningful, or
+
+   b) under the GNU GPL, with none of the additional permissions of
+   this License applicable to that copy.
+
+  3. Object Code Incorporating Material from Library Header Files.
+
+  The object code form of an Application may incorporate material from
+a header file that is part of the Library.  You may convey such object
+code under terms of your choice, provided that, if the incorporated
+material is not limited to numerical parameters, data structure
+layouts and accessors, or small macros, inline functions and templates
+(ten or fewer lines in length), you do both of the following:
+
+   a) Give prominent notice with each copy of the object code that the
+   Library is used in it and that the Library and its use are
+   covered by this License.
+
+   b) Accompany the object code with a copy of the GNU GPL and this license
+   document.
+
+  4. Combined Works.
+
+  You may convey a Combined Work under terms of your choice that,
+taken together, effectively do not restrict modification of the
+portions of the Library contained in the Combined Work and reverse
+engineering for debugging such modifications, if you also do each of
+the following:
+
+   a) Give prominent notice with each copy of the Combined Work that
+   the Library is used in it and that the Library and its use are
+   covered by this License.
+
+   b) Accompany the Combined Work with a copy of the GNU GPL and this license
+   document.
+
+   c) For a Combined Work that displays copyright notices during
+   execution, include the copyright notice for the Library among
+   these notices, as well as a reference directing the user to the
+   copies of the GNU GPL and this license document.
+
+   d) Do one of the following:
+
+       0) Convey the Minimal Corresponding Source under the terms of this
+       License, and the Corresponding Application Code in a form
+       suitable for, and under terms that permit, the user to
+       recombine or relink the Application with a modified version of
+       the Linked Version to produce a modified Combined Work, in the
+       manner specified by section 6 of the GNU GPL for conveying
+       Corresponding Source.
+
+       1) Use a suitable shared library mechanism for linking with the
+       Library.  A suitable mechanism is one that (a) uses at run time
+       a copy of the Library already present on the user's computer
+       system, and (b) will operate properly with a modified version
+       of the Library that is interface-compatible with the Linked
+       Version. 
+
+   e) Provide Installation Information, but only if you would otherwise
+   be required to provide such information under section 6 of the
+   GNU GPL, and only to the extent that such information is
+   necessary to install and execute a modified version of the
+   Combined Work produced by recombining or relinking the
+   Application with a modified version of the Linked Version. (If
+   you use option 4d0, the Installation Information must accompany
+   the Minimal Corresponding Source and Corresponding Application
+   Code. If you use option 4d1, you must provide the Installation
+   Information in the manner specified by section 6 of the GNU GPL
+   for conveying Corresponding Source.)
+
+  5. Combined Libraries.
+
+  You may place library facilities that are a work based on the
+Library side by side in a single library together with other library
+facilities that are not Applications and are not covered by this
+License, and convey such a combined library under terms of your
+choice, if you do both of the following:
+
+   a) Accompany the combined library with a copy of the same work based
+   on the Library, uncombined with any other library facilities,
+   conveyed under the terms of this License.
+
+   b) Give prominent notice with the combined library that part of it
+   is a work based on the Library, and explaining where to find the
+   accompanying uncombined form of the same work.
+
+  6. Revised Versions of the GNU Lesser General Public License.
+
+  The Free Software Foundation may publish revised and/or new versions
+of the GNU Lesser General Public License from time to time. Such new
+versions will be similar in spirit to the present version, but may
+differ in detail to address new problems or concerns.
+
+  Each version is given a distinguishing version number. If the
+Library as you received it specifies that a certain numbered version
+of the GNU Lesser General Public License "or any later version"
+applies to it, you have the option of following the terms and
+conditions either of that published version or of any later version
+published by the Free Software Foundation. If the Library as you
+received it does not specify a version number of the GNU Lesser
+General Public License, you may choose any version of the GNU Lesser
+General Public License ever published by the Free Software Foundation.
+
+  If the Library as you received it specifies that a proxy can decide
+whether future versions of the GNU Lesser General Public License shall
+apply, that proxy's public statement of acceptance of any version is
+permanent authorization for you to choose that version for the
+Library.

Added: tags/afc-2.0/arakhneVmutils/java/src/main/resources/Changelog
===================================================================
--- tags/afc-2.0/arakhneVmutils/java/src/main/resources/Changelog	                        (rev 0)
+++ tags/afc-2.0/arakhneVmutils/java/src/main/resources/Changelog	2010-01-21 08:29:52 UTC (rev 117)
@@ -0,0 +1,42 @@
+arakhneVmutils-4.1
+
+* Add a more generic getSubClasses() function in ReflectionUtil class.
+
+-- Stephane GALLAND <galland@xxxxxxxxxxx> Fri, 03 Apr 2009 20:12:44 +0200
+
+arakhneVmutils-4.0
+
+* Add function getSubClasses() in ReflectionUtil class.
+
+-- Stephane GALLAND <galland@xxxxxxxxxxx> Fri, 03 Apr 2009 01:03:45 +0200
+
+arakhneVmutils-3.0
+
+* Add class ReflectionUtil.
+
+-- Stephane GALLAND <galland@xxxxxxxxxxx> Tue, 10 Mar 2009 10:51:07 +0100
+
+arakhneVmutils-2.2
+
+* Bug fix: the FileSystem#split(File) function should not use the
+  absolute path of the given file.
+
+-- Stephane GALLAND <galland@xxxxxxxxxxx> Thu, 05 Mar 2009 15:08:29 +0100
+
+arakhneVmutils-2.1
+
+* HAL changed the name of the properties where the serial number and
+  system UUID were stored. Reflect this change in josuuid.
+* OperatingSystem is now able to indicate if the current operating
+  system is 32 or 64 bits compliant.
+* LibraryLoader is now able to load 64 or 32 bits library accordingly
+  to the current operating system.
+
+-- Stephane GALLAND <galland@xxxxxxxxxxx> Wed, 10 Dec 2008 14:33:19 +0100
+
+arakhneVmutils-1.0
+
+ * First public release
+
+ -- Stephane GALLAND <galland@xxxxxxxxxxx> Sat, 04 Oct 2008 09:51:52 +0200
+

Added: tags/afc-2.0/arakhneVmutils/java/src/main/resources/VERSION
===================================================================
--- tags/afc-2.0/arakhneVmutils/java/src/main/resources/VERSION	                        (rev 0)
+++ tags/afc-2.0/arakhneVmutils/java/src/main/resources/VERSION	2010-01-21 08:29:52 UTC (rev 117)
@@ -0,0 +1 @@
+arakhneVmutils 4.1

Added: tags/afc-2.0/arakhneVmutils/java/src/test/java/org/arakhne/vmutil/FileSystemTest.java
===================================================================
--- tags/afc-2.0/arakhneVmutils/java/src/test/java/org/arakhne/vmutil/FileSystemTest.java	                        (rev 0)
+++ tags/afc-2.0/arakhneVmutils/java/src/test/java/org/arakhne/vmutil/FileSystemTest.java	2010-01-21 08:29:52 UTC (rev 117)
@@ -0,0 +1,807 @@
+/* $Id$
+ * 
+ * Copyright (C) 2007-09 St&eacute;phane GALLAND
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * This program is free software; you can redistribute it and/or modify
+ */
+package org.arakhne.vmutil;
+
+import java.io.File;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.Arrays;
+
+import junit.framework.AssertionFailedError;
+import junit.framework.TestCase;
+
+/**
+* @author St&eacute;phane GALLAND &lt;galland@xxxxxxxxxxx&gt;
+* @version $Name$ $Revision$ $Date$
+*/
+public class FileSystemTest extends TestCase {
+
+	private static final File f1 = new File("/home/test.x.z.z"); //$NON-NLS-1$
+	private static final File f2 = new File("/home"); //$NON-NLS-1$
+	private static final File pf1 = f1.getParentFile();
+	private static final File pf2 = f2.getParentFile();
+	private static final URL u1, u2, u3, u4, u5, u6, u7, u8, u9, u10, u11, u13, u14, u15;
+	private static final URL pu1, pu2, pu3, pu7, pu13;
+	private static final String TEST_URL1 = "http://toto:titi@xxxxxxxxxxxxxxx/path/to/file.x.z.z?toto#frag";; //$NON-NLS-1$
+	private static final String JOIN_TEST_URL1 = "http://toto:titi@xxxxxxxxxxxxxxx/path/to/file.x.z.z/home/test.x.z.z?toto#frag";; //$NON-NLS-1$
+	private static final String PARENT_TEST_URL1 = "http://toto:titi@xxxxxxxxxxxxxxx/path/to/";; //$NON-NLS-1$
+	private static final String WOEXT_TEST_URL1 = "http://toto:titi@xxxxxxxxxxxxxxx/path/to/file.x.z?toto#frag";; //$NON-NLS-1$
+	private static final String REPEXT_TEST_URL1 = "http://toto:titi@xxxxxxxxxxxxxxx/path/to/file.x.z.toto?toto#frag";; //$NON-NLS-1$
+	private static final String TEST_URL2 = "jar:file:/home/test/j.jar!/org/arakhne/vmutil/file.x.z.z"; //$NON-NLS-1$
+	private static final String PARENT_TEST_URL2 = "jar:file:/home/test/j.jar!/org/arakhne/vmutil/"; //$NON-NLS-1$
+	private static final String JOIN_TEST_URL2 = "jar:file:/home/test/j.jar!/org/arakhne/vmutil/file.x.z.z/home/test.x.z.z"; //$NON-NLS-1$
+	private static final String WOEXT_TEST_URL2 = "jar:file:/home/test/j.jar!/org/arakhne/vmutil/file.x.z"; //$NON-NLS-1$
+	private static final String REPEXT_TEST_URL2 = "jar:file:/home/test/j.jar!/org/arakhne/vmutil/file.x.z.toto"; //$NON-NLS-1$
+	private static final String JARPART_TEST_URL2 = "file:/home/test/j.jar"; //$NON-NLS-1$
+	private static final File f3 = new File("/home/test/j.jar"); //$NON-NLS-1$
+	private static final File f4 = new File("/org/arakhne/vmutil/file.x.z.z"); //$NON-NLS-1$
+	private static final String TEST_URL3 = "jar:jar:http://www.arakhne.org/j.jar!/inner/myjar.jar!/org/arakhne/vmutil/file.x.z.z";; //$NON-NLS-1$
+	private static final String PARENT_TEST_URL3 = "jar:jar:http://www.arakhne.org/j.jar!/inner/myjar.jar!/org/arakhne/vmutil/";; //$NON-NLS-1$
+	private static final String JARPART_TEST_URL3 = "jar:http://www.arakhne.org/j.jar!/inner/myjar.jar";; //$NON-NLS-1$
+	private static final String JOIN_TEST_URL3 = "jar:jar:http://www.arakhne.org/j.jar!/inner/myjar.jar!/org/arakhne/vmutil/file.x.z.z/home/test.x.z.z";; //$NON-NLS-1$
+	
+	static {
+		try {
+			u1 = f1.toURI().toURL();
+			u2 = f2.toURI().toURL();
+			u3 = new URL(TEST_URL1);
+			u4 = new URL(JOIN_TEST_URL1);
+			u5 = new URL(WOEXT_TEST_URL1);
+			u6 = new URL(REPEXT_TEST_URL1);
+			u7 = new URL(TEST_URL2);
+			u8 = new URL(JOIN_TEST_URL2);
+			u9 = new URL(WOEXT_TEST_URL2);
+			u10 = new URL(REPEXT_TEST_URL2);
+			u11 = new URL(JARPART_TEST_URL2);
+			u13 = new URL(TEST_URL3);
+			u14 = new URL(JARPART_TEST_URL3);
+			u15 = new URL(JOIN_TEST_URL3);
+			pu1 = pf1.toURI().toURL();
+			pu2 = pf2.toURI().toURL();
+			pu3 = new URL(PARENT_TEST_URL1);
+			pu7 = new URL(PARENT_TEST_URL2);
+			pu13 = new URL(PARENT_TEST_URL3);
+		}
+		catch(Throwable e) {
+			throw new AssertionFailedError(e.getLocalizedMessage());
+		}
+	}
+	
+	/**
+	 */
+	public void tetIsJarURLURL() {
+		assertFalse(FileSystem.isJarURL(u1));
+		assertFalse(FileSystem.isJarURL(u2));
+		assertFalse(FileSystem.isJarURL(u3));
+		assertTrue(FileSystem.isJarURL(u7));
+		assertTrue(FileSystem.isJarURL(u13));
+	}
+	
+	/**
+	 */
+	public void testGetJarURLURL() {
+		assertNull(FileSystem.getJarURL(u1));
+		assertNull(FileSystem.getJarURL(u2));
+		assertNull(FileSystem.getJarURL(u3));
+		assertEquals(u11, FileSystem.getJarURL(u7));
+		assertEquals(u14, FileSystem.getJarURL(u13));
+	}
+
+	/**
+	 */
+	public void testGetJarFileURL() {
+		assertNull(FileSystem.getJarFile(u1));
+		assertNull(FileSystem.getJarFile(u2));
+		assertNull(FileSystem.getJarFile(u3));
+		assertEquals(f4, FileSystem.getJarFile(u7));
+		assertEquals(f4, FileSystem.getJarFile(u13));
+	}
+
+	/**
+	 * @throws MalformedURLException
+	 */
+	public void testToJarURLFileFile() throws MalformedURLException {
+		assertEquals(u7, FileSystem.toJarURL(f3, f4));
+	}
+
+	/**
+	 * @throws MalformedURLException
+	 */
+	public void testToJarURLFileString() throws MalformedURLException {
+		assertEquals(u7, FileSystem.toJarURL(f3, f4.getPath()));
+	}
+
+	/**
+	 * @throws MalformedURLException
+	 */
+	public void testToJarURLURLFile() throws MalformedURLException {
+		assertEquals(u7, FileSystem.toJarURL(u11, f4));
+	}
+
+	/**
+	 * @throws MalformedURLException
+	 */
+	public void testToJarURLURLString() throws MalformedURLException {
+		assertEquals(u7, FileSystem.toJarURL(u11, f4.getPath()));
+	}
+
+	/**
+	 */
+	public void testDirnameFile() {
+		assertEquals(pf1, FileSystem.dirname(f1));
+		assertEquals(pf2, FileSystem.dirname(f2));
+	}
+
+	/**
+	 */
+	public void testDirnameURL() {
+		assertEquals(pu1, FileSystem.dirname(u1));
+		assertEquals(pu2, FileSystem.dirname(u2));
+		assertEquals(pu3, FileSystem.dirname(u3));
+		assertEquals(pu7, FileSystem.dirname(u7));
+		assertEquals(pu13, FileSystem.dirname(u13));
+	}
+
+	/**
+	 */
+	public void testLargeBasenameString() {
+		assertEquals("test.x.z.z", FileSystem.largeBasename(f1.getAbsolutePath())); //$NON-NLS-1$
+		assertEquals("home", FileSystem.largeBasename(f2.getAbsolutePath())); //$NON-NLS-1$
+	}
+
+	/**
+	 */
+	public void testLargeBasenameFile() {
+		assertEquals("test.x.z.z", FileSystem.largeBasename(f1)); //$NON-NLS-1$
+		assertEquals("home", FileSystem.largeBasename(f2)); //$NON-NLS-1$
+	}
+
+	/**
+	 */
+	public void testLargeBasenameURL() {
+		assertEquals("test.x.z.z", FileSystem.largeBasename(u1)); //$NON-NLS-1$
+		assertEquals("home", FileSystem.largeBasename(u2)); //$NON-NLS-1$
+		assertEquals("file.x.z.z", FileSystem.largeBasename(u3)); //$NON-NLS-1$
+		assertEquals("file.x.z.z", FileSystem.largeBasename(u7)); //$NON-NLS-1$
+	}
+
+	/**
+	 */
+	public void testBasenameString() {
+		assertEquals("test.x.z", FileSystem.basename(f1.getAbsolutePath())); //$NON-NLS-1$
+		assertEquals("home", FileSystem.basename(f2.getAbsolutePath())); //$NON-NLS-1$
+	}
+
+	/**
+	 */
+	public void testBasenameFile() {
+		assertEquals("test.x.z", FileSystem.basename(f1)); //$NON-NLS-1$
+		assertEquals("home", FileSystem.basename(f2)); //$NON-NLS-1$
+	}
+
+	/**
+	 */
+	public void testBasenameURL() {
+		assertEquals("test.x.z", FileSystem.basename(u1)); //$NON-NLS-1$
+		assertEquals("home", FileSystem.basename(u2)); //$NON-NLS-1$
+		assertEquals("file.x.z", FileSystem.basename(u3)); //$NON-NLS-1$
+		assertEquals("file.x.z", FileSystem.basename(u7)); //$NON-NLS-1$
+	}
+
+	/**
+	 */
+	public void testShortBasenameString() {
+		assertEquals("test", FileSystem.shortBasename(f1.getAbsolutePath())); //$NON-NLS-1$
+		assertEquals("home", FileSystem.shortBasename(f2.getAbsolutePath())); //$NON-NLS-1$
+	}
+
+	/**
+	 */
+	public void testShortBasenameFile() {
+		assertEquals("test", FileSystem.shortBasename(f1)); //$NON-NLS-1$
+		assertEquals("home", FileSystem.shortBasename(f2)); //$NON-NLS-1$
+	}
+
+	/**
+	 */
+	public void testShortBasenameURL() {
+		assertEquals("test", FileSystem.shortBasename(u1)); //$NON-NLS-1$
+		assertEquals("home", FileSystem.shortBasename(u2)); //$NON-NLS-1$
+		assertEquals("file", FileSystem.shortBasename(u3)); //$NON-NLS-1$
+		assertEquals("file", FileSystem.shortBasename(u7)); //$NON-NLS-1$
+	}
+
+	/**
+	 */
+	public void testExtensionFile() {
+		assertEquals(".z", FileSystem.extension(f1)); //$NON-NLS-1$
+		assertEquals("", FileSystem.extension(f2)); //$NON-NLS-1$
+	}
+
+	/**
+	 */
+	public void testExtensionURL() {
+		assertEquals(".z", FileSystem.extension(u1)); //$NON-NLS-1$
+		assertEquals("", FileSystem.extension(u2)); //$NON-NLS-1$
+		assertEquals(".z", FileSystem.extension(u3)); //$NON-NLS-1$
+		assertEquals(".z", FileSystem.extension(u7)); //$NON-NLS-1$
+		assertEquals(".z", FileSystem.extension(u13)); //$NON-NLS-1$
+	}
+
+	/**
+	 */
+	public void testExtensionsFile() {
+		assertTrue(Arrays.equals(new String[]{"x","z","z"}, FileSystem.extensions(f1))); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+		assertTrue(Arrays.equals(new String[0], FileSystem.extensions(f2)));
+	}
+
+	/**
+	 */
+	public void testExtensionsURL() {
+		assertTrue(Arrays.equals(new String[]{"x","z","z"}, FileSystem.extensions(u1))); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+		assertTrue(Arrays.equals(new String[0], FileSystem.extensions(u2)));
+		assertTrue(Arrays.equals(new String[]{"x","z","z"}, FileSystem.extensions(u3))); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+		assertTrue(Arrays.equals(new String[]{"x","z","z"}, FileSystem.extensions(u7))); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+	}
+
+	/**
+	 */
+	public void testSplitFile() {
+		assertTrue(Arrays.equals(
+				new String[] {
+					"", //$NON-NLS-1$
+					"home", //$NON-NLS-1$
+					"test.x.z.z", //$NON-NLS-1$
+				},
+				FileSystem.split(f1)));
+		assertTrue(Arrays.equals(
+				new String[] {
+					"", //$NON-NLS-1$
+					"home", //$NON-NLS-1$
+				},
+				FileSystem.split(f2)));
+	}
+
+	/**
+	 */
+	public void testSplitURL() {
+		String[] tab;
+		
+		tab = FileSystem.split(u1);
+		assertTrue(Arrays.equals(
+				new String[] {
+					"", //$NON-NLS-1$
+					"home", //$NON-NLS-1$
+					"test.x.z.z", //$NON-NLS-1$
+				},
+				tab));
+		
+		tab = FileSystem.split(u2);
+		assertTrue(Arrays.equals(
+				new String[] {
+					"", //$NON-NLS-1$
+					"home", //$NON-NLS-1$
+				},
+				tab));
+		
+		tab = FileSystem.split(u7);
+		assertTrue(Arrays.equals(
+				new String[] {
+					"", //$NON-NLS-1$
+					"org", //$NON-NLS-1$
+					"arakhne", //$NON-NLS-1$
+					"vmutil", //$NON-NLS-1$
+					"file.x.z.z", //$NON-NLS-1$
+				},
+				tab));
+		
+		tab = FileSystem.split(u13);
+		assertTrue(Arrays.equals(
+				new String[] {
+					"", //$NON-NLS-1$
+					"org", //$NON-NLS-1$
+					"arakhne", //$NON-NLS-1$
+					"vmutil", //$NON-NLS-1$
+					"file.x.z.z", //$NON-NLS-1$
+				},
+				tab));
+	}
+
+	/**
+	 */
+	public void testJoinFileStringArray() {
+		assertEquals(new File(new File(f1, "home"), "test.x.z.z"), //$NON-NLS-1$ //$NON-NLS-2$
+				FileSystem.join(f1,
+				"", //$NON-NLS-1$
+				"home", //$NON-NLS-1$
+				"test.x.z.z")); //$NON-NLS-1$
+	}
+
+	/**
+	 */
+	public void testJoinFileFileArray() {
+		assertEquals(new File(new File(f1, "home"), "test.x.z.z"), //$NON-NLS-1$ //$NON-NLS-2$
+				FileSystem.join(f1,
+				new File("home"), //$NON-NLS-1$
+				new File("test.x.z.z"))); //$NON-NLS-1$
+		assertEquals(new File(new File(f1, "home"), "test.x.z.z"), //$NON-NLS-1$ //$NON-NLS-2$
+				FileSystem.join(f1,
+				new File(File.separator+"home"), //$NON-NLS-1$
+				new File("test.x.z.z"))); //$NON-NLS-1$
+	}
+
+	/**
+	 * @throws Exception
+	 */
+	public void testJoinURLStringArray() throws Exception {
+		assertEquals(new File(new File(f1, "home"), "test.x.z.z").toURI().toURL(), //$NON-NLS-1$ //$NON-NLS-2$
+				FileSystem.join(u1,
+				"", //$NON-NLS-1$
+				"home", //$NON-NLS-1$
+				"test.x.z.z")); //$NON-NLS-1$
+
+		assertEquals(u4,
+				FileSystem.join(u3,
+				"", //$NON-NLS-1$
+				"home", //$NON-NLS-1$
+				"test.x.z.z")); //$NON-NLS-1$
+
+		assertEquals(u8,
+				FileSystem.join(u7,
+				"", //$NON-NLS-1$
+				"home", //$NON-NLS-1$
+				"test.x.z.z")); //$NON-NLS-1$
+
+		assertEquals(u15,
+				FileSystem.join(u13,
+				"", //$NON-NLS-1$
+				"home", //$NON-NLS-1$
+				"test.x.z.z")); //$NON-NLS-1$
+	}
+
+	/**
+	 * @throws Exception
+	 */
+	public void testJoinURLFileArray() throws Exception {
+		assertEquals(new File(new File(f1, "home"), "test.x.z.z").toURI().toURL(), //$NON-NLS-1$ //$NON-NLS-2$
+				FileSystem.join(u1,
+				new File("home"), //$NON-NLS-1$
+				new File("test.x.z.z"))); //$NON-NLS-1$
+		assertEquals(new File(new File(f1, "home"), "test.x.z.z").toURI().toURL(), //$NON-NLS-1$ //$NON-NLS-2$
+				FileSystem.join(u1,
+				new File(File.separator+"home"), //$NON-NLS-1$
+				new File("test.x.z.z"))); //$NON-NLS-1$
+		assertEquals(u4,
+				FileSystem.join(u3,
+				new File(File.separator+"home"), //$NON-NLS-1$
+				new File("test.x.z.z"))); //$NON-NLS-1$
+		assertEquals(u8,
+				FileSystem.join(u7,
+				new File(File.separator+"home"), //$NON-NLS-1$
+				new File("test.x.z.z"))); //$NON-NLS-1$
+		assertEquals(u15,
+				FileSystem.join(u13,
+				new File(File.separator+"home"), //$NON-NLS-1$
+				new File("test.x.z.z"))); //$NON-NLS-1$
+	}
+
+	/**
+	 */
+	public void testHasExtensionFileString() {
+		assertTrue(FileSystem.hasExtension(f1, ".z")); //$NON-NLS-1$
+		assertTrue(FileSystem.hasExtension(f1, "z")); //$NON-NLS-1$
+		assertFalse(FileSystem.hasExtension(f1, ".x")); //$NON-NLS-1$
+		assertFalse(FileSystem.hasExtension(f1, "")); //$NON-NLS-1$
+		assertTrue(FileSystem.hasExtension(f2, "")); //$NON-NLS-1$
+		assertFalse(FileSystem.hasExtension(f2, ".z")); //$NON-NLS-1$
+	}
+
+	/**
+	 */
+	public void testHasExtensionURLString() {
+		assertTrue(FileSystem.hasExtension(u1, ".z")); //$NON-NLS-1$
+		assertTrue(FileSystem.hasExtension(u1, "z")); //$NON-NLS-1$
+		assertFalse(FileSystem.hasExtension(u1, ".x")); //$NON-NLS-1$
+		assertFalse(FileSystem.hasExtension(u1, "")); //$NON-NLS-1$
+		assertTrue(FileSystem.hasExtension(u2, "")); //$NON-NLS-1$
+		assertFalse(FileSystem.hasExtension(u2, ".z")); //$NON-NLS-1$
+		assertTrue(FileSystem.hasExtension(u3, ".z")); //$NON-NLS-1$
+		assertTrue(FileSystem.hasExtension(u3, "z")); //$NON-NLS-1$
+		assertFalse(FileSystem.hasExtension(u3, ".x")); //$NON-NLS-1$
+		assertFalse(FileSystem.hasExtension(u3, "")); //$NON-NLS-1$
+		assertTrue(FileSystem.hasExtension(u7, ".z")); //$NON-NLS-1$
+		assertTrue(FileSystem.hasExtension(u7, "z")); //$NON-NLS-1$
+		assertFalse(FileSystem.hasExtension(u7, ".x")); //$NON-NLS-1$
+		assertFalse(FileSystem.hasExtension(u7, "")); //$NON-NLS-1$
+	}
+
+	/**
+	 */
+	public void testRemoveExtensionFile() {
+		assertEquals(new File("/home/test.x.z"), FileSystem.removeExtension(f1)); //$NON-NLS-1$
+		assertEquals(new File("/home"), FileSystem.removeExtension(f2)); //$NON-NLS-1$
+	}
+
+	/**
+	 * @throws Exception
+	 */
+	public void testRemoveExtensionURL() throws Exception {
+		assertEquals(new File("/home/test.x.z").toURI().toURL(), //$NON-NLS-1$
+				FileSystem.removeExtension(u1));
+		assertEquals(new File("/home").toURI().toURL(), //$NON-NLS-1$ 
+				FileSystem.removeExtension(u2));
+		assertEquals(u5, FileSystem.removeExtension(u3));
+		assertEquals(u9, FileSystem.removeExtension(u7));
+	}
+
+	/**
+	 */
+	public void testReplaceExtensionFileString() {
+		assertEquals(new File("/home/test.x.z.toto"), FileSystem.replaceExtension(f1, ".toto")); //$NON-NLS-1$ //$NON-NLS-2$
+		assertEquals(new File("/home.toto"), FileSystem.replaceExtension(f2, ".toto")); //$NON-NLS-1$ //$NON-NLS-2$
+	}
+
+	/**
+	 * @throws Exception
+	 */
+	public void testReplaceExtensionURLString() throws Exception {
+		assertEquals(new File("/home/test.x.z.toto").toURI().toURL(), //$NON-NLS-1$ 
+				FileSystem.replaceExtension(u1, ".toto")); //$NON-NLS-1$
+		assertEquals(new File("/home.toto").toURI().toURL(), //$NON-NLS-1$ 
+				FileSystem.replaceExtension(u2, ".toto")); //$NON-NLS-1$
+		assertEquals(u6, FileSystem.replaceExtension(u3, ".toto")); //$NON-NLS-1$
+		assertEquals(u10, FileSystem.replaceExtension(u7, ".toto")); //$NON-NLS-1$
+	}
+
+	/**
+	 * @throws Exception
+	 */
+	public void testConvertStringToUrl() throws Exception {
+		assertNull(FileSystem.convertStringToUrl(null, true));
+		assertNull(FileSystem.convertStringToUrl("", true)); //$NON-NLS-1$
+		assertNull(FileSystem.convertStringToUrl(null, false));
+		assertNull(FileSystem.convertStringToUrl("", false)); //$NON-NLS-1$
+
+		assertEquals(new URL("http://www.arakhne.org/";), //$NON-NLS-1$
+					 FileSystem.convertStringToUrl("http://www.arakhne.org/";, true)); //$NON-NLS-1$
+		assertEquals(new URL("http://www.arakhne.org/";), //$NON-NLS-1$
+				 FileSystem.convertStringToUrl("http://www.arakhne.org/";, false)); //$NON-NLS-1$
+
+		assertEquals(new URL("file:"+f1.getAbsolutePath()), //$NON-NLS-1$
+				 FileSystem.convertStringToUrl("file:"+f1.getAbsolutePath(), true)); //$NON-NLS-1$
+		assertEquals(new URL("file:"+f1.getAbsolutePath()), //$NON-NLS-1$
+			 FileSystem.convertStringToUrl("file:"+f1.getAbsolutePath(), false)); //$NON-NLS-1$
+		assertEquals(new URL("file:./toto"), //$NON-NLS-1$
+				 FileSystem.convertStringToUrl("file:./toto", false)); //$NON-NLS-1$
+
+		assertEquals(new File("jar:/home/test/j.jar").toURI().toURL(), //$NON-NLS-1$
+				FileSystem.convertStringToUrl("jar:/home/test/j.jar", true)); //$NON-NLS-1$
+		assertEquals(new File("jar:/home/test/j.jar").toURI().toURL(), //$NON-NLS-1$
+				FileSystem.convertStringToUrl("jar:/home/test/j.jar", false)); //$NON-NLS-1$
+
+		assertEquals(new File("jar:/home/test/j.jar!/org/arakhne/vmutil/ff.properties").toURI().toURL(), //$NON-NLS-1$
+				FileSystem.convertStringToUrl("jar:/home/test/j.jar!/org/arakhne/vmutil/ff.properties", true)); //$NON-NLS-1$
+		assertEquals(new File("jar:/home/test/j.jar!/org/arakhne/vmutil/ff.properties").toURI().toURL(), //$NON-NLS-1$
+				FileSystem.convertStringToUrl("jar:/home/test/j.jar!/org/arakhne/vmutil/ff.properties", false)); //$NON-NLS-1$
+		
+		assertEquals(new URL("jar:file:/home/test/j.jar!/org/arakhne/vmutil/ff.properties"), //$NON-NLS-1$
+				FileSystem.convertStringToUrl("jar:file:/home/test/j.jar!/org/arakhne/vmutil/ff.properties", true)); //$NON-NLS-1$
+		assertEquals(new URL("jar:file:/home/test/j.jar!/org/arakhne/vmutil/ff.properties"), //$NON-NLS-1$
+				FileSystem.convertStringToUrl("jar:file:/home/test/j.jar!/org/arakhne/vmutil/ff.properties", false)); //$NON-NLS-1$
+
+		URL testResource = Resources.getResource("/org/arakhne/vmutil/test.txt"); //$NON-NLS-1$
+		assertNotNull(testResource);
+		URL testResourceFileRel = new File("org/arakhne/vmutil/test.txt").toURI().toURL(); //$NON-NLS-1$
+		URL testResourceFileAbs = new File("/org/arakhne/vmutil/test.txt").toURI().toURL(); //$NON-NLS-1$
+		
+		assertEquals(testResource,
+				 FileSystem.convertStringToUrl("resource:/org/arakhne/vmutil/test.txt", true)); //$NON-NLS-1$
+		assertEquals(null,
+				 FileSystem.convertStringToUrl("resource:/org/arakhne/vmutil/test.txt", false)); //$NON-NLS-1$
+
+		assertEquals(testResource,
+				 FileSystem.convertStringToUrl("resource:org/arakhne/vmutil/test.txt", true)); //$NON-NLS-1$
+		assertEquals(null,
+				 FileSystem.convertStringToUrl("resource:org/arakhne/vmutil/test.txt", false)); //$NON-NLS-1$
+
+		assertEquals(testResource,
+				 FileSystem.convertStringToUrl("/org/arakhne/vmutil/test.txt", true)); //$NON-NLS-1$
+		assertEquals(testResourceFileAbs,
+				 FileSystem.convertStringToUrl("/org/arakhne/vmutil/test.txt", false)); //$NON-NLS-1$
+
+		assertEquals(testResource,
+				 FileSystem.convertStringToUrl("org/arakhne/vmutil/test.txt", true)); //$NON-NLS-1$
+		assertEquals(testResourceFileRel,
+				 FileSystem.convertStringToUrl("org/arakhne/vmutil/test.txt", false)); //$NON-NLS-1$
+	}
+
+	/**
+	 * @throws Exception
+	 */
+	public void testConvertUrlToFile() throws Exception {
+		assertEquals(f1,
+				 FileSystem.convertUrlToFile(new URL("file:"+f1.getAbsolutePath()))); //$NON-NLS-1$
+
+		try {
+			FileSystem.convertUrlToFile(new URL("http://www.arakhne.org";)); //$NON-NLS-1$
+			fail("not a file URL"); //$NON-NLS-1$
+		}
+		catch(IllegalArgumentException _) {
+			//
+		}
+		
+		assertEquals(new File("toto").getCanonicalPath(), //$NON-NLS-1$
+				 FileSystem.convertUrlToFile(new URL("file:./toto")).getCanonicalPath()); //$NON-NLS-1$
+
+		assertEquals(new File("toto").getCanonicalPath(), //$NON-NLS-1$
+				 FileSystem.convertUrlToFile(new URL("file:toto")).getCanonicalPath()); //$NON-NLS-1$
+
+		assertEquals(new File("toto").getCanonicalPath(), //$NON-NLS-1$
+				 FileSystem.convertUrlToFile(new URL("file:./abs/../toto")).getCanonicalPath()); //$NON-NLS-1$
+
+		assertEquals(new File("/toto").getCanonicalPath(), //$NON-NLS-1$
+				 FileSystem.convertUrlToFile(new URL("file:/toto")).getCanonicalPath()); //$NON-NLS-1$
+	}
+	
+	/**
+	 */
+	public void testMakeAbsoluteFileFile() {
+		File root = new File(File.separator+"myroot"); //$NON-NLS-1$
+
+		assertNull(FileSystem.makeAbsolute((File)null, null));
+		assertNull(FileSystem.makeAbsolute((File)null, root));
+
+		assertEquals(new File(File.separator+"toto"), //$NON-NLS-1$
+				FileSystem.makeAbsolute(new File(File.separator+"toto"), null)); //$NON-NLS-1$
+		assertEquals(new File("toto"), //$NON-NLS-1$
+				FileSystem.makeAbsolute(new File("toto"), null)); //$NON-NLS-1$
+
+		assertEquals(new File(File.separator+"toto"), //$NON-NLS-1$
+				FileSystem.makeAbsolute(new File(File.separator+"toto"), root)); //$NON-NLS-1$
+		assertEquals(new File(File.separator+"myroot"+File.separator+"toto"), //$NON-NLS-1$ //$NON-NLS-2$
+				FileSystem.makeAbsolute(new File("toto"), root)); //$NON-NLS-1$
+	}
+
+	/**
+	 * @throws Exception
+	 */
+	public void testMakeAbsoluteURLFile() throws Exception {
+		File root = new File(File.separator+"myroot"); //$NON-NLS-1$
+
+		assertNull(FileSystem.makeAbsolute((URL)null, (File)null));
+		assertNull(FileSystem.makeAbsolute((URL)null, root));
+
+		assertEquals(new URL("file:/toto"), //$NON-NLS-1$
+				FileSystem.makeAbsolute(new URL("file:/toto"), (File)null)); //$NON-NLS-1$
+		assertEquals(new URL("file:toto"), //$NON-NLS-1$
+				FileSystem.makeAbsolute(new URL("file:toto"), (File)null)); //$NON-NLS-1$
+		assertEquals(new URL("file:/toto"), //$NON-NLS-1$
+				FileSystem.makeAbsolute(new URL("file:/toto"), root)); //$NON-NLS-1$
+		assertEquals(new URL("file:/myroot/toto"), //$NON-NLS-1$
+				FileSystem.makeAbsolute(new URL("file:toto"), root)); //$NON-NLS-1$
+
+		assertEquals(new URL("http://www.arakhne.org/toto";), //$NON-NLS-1$
+				FileSystem.makeAbsolute(new URL("http://www.arakhne.org/toto";), (File)null)); //$NON-NLS-1$
+		assertEquals(new URL("http://www.arakhne.org/./toto";), //$NON-NLS-1$
+				FileSystem.makeAbsolute(new URL("http://www.arakhne.org/./toto";), (File)null)); //$NON-NLS-1$
+		assertEquals(new URL("http://www.arakhne.org/toto";), //$NON-NLS-1$
+				FileSystem.makeAbsolute(new URL("http://www.arakhne.org/toto";), root)); //$NON-NLS-1$
+		assertEquals(new URL("http://www.arakhne.org/./toto";), //$NON-NLS-1$
+				FileSystem.makeAbsolute(new URL("http://www.arakhne.org/./toto";), root)); //$NON-NLS-1$
+
+		assertEquals(new URL("https://www.arakhne.org/toto";), //$NON-NLS-1$
+				FileSystem.makeAbsolute(new URL("https://www.arakhne.org/toto";), (File)null)); //$NON-NLS-1$
+		assertEquals(new URL("https://www.arakhne.org/./toto";), //$NON-NLS-1$
+				FileSystem.makeAbsolute(new URL("https://www.arakhne.org/./toto";), (File)null)); //$NON-NLS-1$
+		assertEquals(new URL("https://www.arakhne.org/toto";), //$NON-NLS-1$
+				FileSystem.makeAbsolute(new URL("https://www.arakhne.org/toto";), root)); //$NON-NLS-1$
+		assertEquals(new URL("https://www.arakhne.org/./toto";), //$NON-NLS-1$
+				FileSystem.makeAbsolute(new URL("https://www.arakhne.org/./toto";), root)); //$NON-NLS-1$
+
+		assertEquals(new URL("ftp://www.arakhne.org/toto";), //$NON-NLS-1$
+				FileSystem.makeAbsolute(new URL("ftp://www.arakhne.org/toto";), (File)null)); //$NON-NLS-1$
+		assertEquals(new URL("ftp://www.arakhne.org/./toto";), //$NON-NLS-1$
+				FileSystem.makeAbsolute(new URL("ftp://www.arakhne.org/./toto";), (File)null)); //$NON-NLS-1$
+		assertEquals(new URL("ftp://www.arakhne.org/toto";), //$NON-NLS-1$
+				FileSystem.makeAbsolute(new URL("ftp://www.arakhne.org/toto";), root)); //$NON-NLS-1$
+		assertEquals(new URL("ftp://www.arakhne.org/./toto";), //$NON-NLS-1$
+				FileSystem.makeAbsolute(new URL("ftp://www.arakhne.org/./toto";), root)); //$NON-NLS-1$
+
+		assertEquals(new URL("jar:file:/home/test/j.jar!/org/arakhne/vmutil/ff.properties"), //$NON-NLS-1$
+				FileSystem.makeAbsolute(new URL("jar:file:/home/test/j.jar!/org/arakhne/vmutil/ff.properties"), (File)null)); //$NON-NLS-1$
+		assertEquals(new URL("jar:file:home/test/j.jar!/org/arakhne/vmutil/ff.properties"), //$NON-NLS-1$
+				FileSystem.makeAbsolute(new URL("jar:file:home/test/j.jar!/org/arakhne/vmutil/ff.properties"), (File)null)); //$NON-NLS-1$
+		assertEquals(new URL("jar:file:/home/test/j.jar!/org/arakhne/vmutil/ff.properties"), //$NON-NLS-1$
+				FileSystem.makeAbsolute(new URL("jar:file:/home/test/j.jar!/org/arakhne/vmutil/ff.properties"), root)); //$NON-NLS-1$
+		assertEquals(new URL("jar:file:/myroot/home/test/j.jar!/org/arakhne/vmutil/ff.properties"), //$NON-NLS-1$
+				FileSystem.makeAbsolute(new URL("jar:file:home/test/j.jar!/org/arakhne/vmutil/ff.properties"), root)); //$NON-NLS-1$
+	}
+
+	/**
+	 * @throws Exception
+	 */
+	public void testMakeAbsoluteURLURL() throws Exception {
+		URL root = new File(File.separator+"myroot").toURI().toURL(); //$NON-NLS-1$
+
+		assertNull(FileSystem.makeAbsolute((URL)null, (URL)null));
+		assertNull(FileSystem.makeAbsolute((URL)null, root));
+
+		assertEquals(new URL("file:/toto"), //$NON-NLS-1$
+				FileSystem.makeAbsolute(new URL("file:/toto"), (URL)null)); //$NON-NLS-1$
+		assertEquals(new URL("file:toto"), //$NON-NLS-1$
+				FileSystem.makeAbsolute(new URL("file:toto"), (URL)null)); //$NON-NLS-1$
+		assertEquals(new URL("file:/toto"), //$NON-NLS-1$
+				FileSystem.makeAbsolute(new URL("file:/toto"), root)); //$NON-NLS-1$
+		assertEquals(new URL("file:/myroot/toto"), //$NON-NLS-1$
+				FileSystem.makeAbsolute(new URL("file:toto"), root)); //$NON-NLS-1$
+
+		assertEquals(new URL("http://www.arakhne.org/toto";), //$NON-NLS-1$
+				FileSystem.makeAbsolute(new URL("http://www.arakhne.org/toto";), (URL)null)); //$NON-NLS-1$
+		assertEquals(new URL("http://www.arakhne.org/./toto";), //$NON-NLS-1$
+				FileSystem.makeAbsolute(new URL("http://www.arakhne.org/./toto";), (URL)null)); //$NON-NLS-1$
+		assertEquals(new URL("http://www.arakhne.org/toto";), //$NON-NLS-1$
+				FileSystem.makeAbsolute(new URL("http://www.arakhne.org/toto";), root)); //$NON-NLS-1$
+		assertEquals(new URL("http://www.arakhne.org/./toto";), //$NON-NLS-1$
+				FileSystem.makeAbsolute(new URL("http://www.arakhne.org/./toto";), root)); //$NON-NLS-1$
+
+		assertEquals(new URL("https://www.arakhne.org/toto";), //$NON-NLS-1$
+				FileSystem.makeAbsolute(new URL("https://www.arakhne.org/toto";), (URL)null)); //$NON-NLS-1$
+		assertEquals(new URL("https://www.arakhne.org/./toto";), //$NON-NLS-1$
+				FileSystem.makeAbsolute(new URL("https://www.arakhne.org/./toto";), (URL)null)); //$NON-NLS-1$
+		assertEquals(new URL("https://www.arakhne.org/toto";), //$NON-NLS-1$
+				FileSystem.makeAbsolute(new URL("https://www.arakhne.org/toto";), root)); //$NON-NLS-1$
+		assertEquals(new URL("https://www.arakhne.org/./toto";), //$NON-NLS-1$
+				FileSystem.makeAbsolute(new URL("https://www.arakhne.org/./toto";), root)); //$NON-NLS-1$
+
+		assertEquals(new URL("ftp://www.arakhne.org/toto";), //$NON-NLS-1$
+				FileSystem.makeAbsolute(new URL("ftp://www.arakhne.org/toto";), (URL)null)); //$NON-NLS-1$
+		assertEquals(new URL("ftp://www.arakhne.org/./toto";), //$NON-NLS-1$
+				FileSystem.makeAbsolute(new URL("ftp://www.arakhne.org/./toto";), (URL)null)); //$NON-NLS-1$
+		assertEquals(new URL("ftp://www.arakhne.org/toto";), //$NON-NLS-1$
+				FileSystem.makeAbsolute(new URL("ftp://www.arakhne.org/toto";), root)); //$NON-NLS-1$
+		assertEquals(new URL("ftp://www.arakhne.org/./toto";), //$NON-NLS-1$
+				FileSystem.makeAbsolute(new URL("ftp://www.arakhne.org/./toto";), root)); //$NON-NLS-1$
+
+		assertEquals(new URL("jar:file:/home/test/j.jar!/org/arakhne/vmutil/ff.properties"), //$NON-NLS-1$
+				FileSystem.makeAbsolute(new URL("jar:file:/home/test/j.jar!/org/arakhne/vmutil/ff.properties"), (URL)null)); //$NON-NLS-1$
+		assertEquals(new URL("jar:file:home/test/j.jar!/org/arakhne/vmutil/ff.properties"), //$NON-NLS-1$
+				FileSystem.makeAbsolute(new URL("jar:file:home/test/j.jar!/org/arakhne/vmutil/ff.properties"), (URL)null)); //$NON-NLS-1$
+		assertEquals(new URL("jar:file:/home/test/j.jar!/org/arakhne/vmutil/ff.properties"), //$NON-NLS-1$
+				FileSystem.makeAbsolute(new URL("jar:file:/home/test/j.jar!/org/arakhne/vmutil/ff.properties"), root)); //$NON-NLS-1$
+		assertEquals(new URL("jar:file:/myroot/home/test/j.jar!/org/arakhne/vmutil/ff.properties"), //$NON-NLS-1$
+				FileSystem.makeAbsolute(new URL("jar:file:home/test/j.jar!/org/arakhne/vmutil/ff.properties"), root)); //$NON-NLS-1$
+	}
+	
+	/**
+	 * @throws Exception
+	 */
+	public void testGetParentURLURL() throws Exception {
+		assertEquals(
+				new URL("http://www.arakhne.org/";), //$NON-NLS-1$
+				FileSystem.getParentURL(new URL("http://www.arakhne.org";))); //$NON-NLS-1$
+		assertEquals(
+				new URL("http://www.arakhne.org/";), //$NON-NLS-1$
+				FileSystem.getParentURL(new URL("http://www.arakhne.org/";))); //$NON-NLS-1$
+		assertEquals(
+				new URL("http://www.arakhne.org/";), //$NON-NLS-1$
+				FileSystem.getParentURL(new URL("http://www.arakhne.org/toto";))); //$NON-NLS-1$
+		assertEquals(
+				new URL("http://www.arakhne.org/";), //$NON-NLS-1$
+				FileSystem.getParentURL(new URL("http://www.arakhne.org/toto/";))); //$NON-NLS-1$
+		assertEquals(
+				new URL("http://www.arakhne.org/toto/";), //$NON-NLS-1$
+				FileSystem.getParentURL(new URL("http://www.arakhne.org/toto/titi";))); //$NON-NLS-1$
+		assertEquals(
+				new URL("http://www.arakhne.org/toto/";), //$NON-NLS-1$
+				FileSystem.getParentURL(new URL("http://www.arakhne.org/toto/titi/";))); //$NON-NLS-1$
+
+		assertEquals(
+				new URL("https://www.arakhne.org/";), //$NON-NLS-1$
+				FileSystem.getParentURL(new URL("https://www.arakhne.org";))); //$NON-NLS-1$
+		assertEquals(
+				new URL("https://www.arakhne.org/";), //$NON-NLS-1$
+				FileSystem.getParentURL(new URL("https://www.arakhne.org/";))); //$NON-NLS-1$
+		assertEquals(
+				new URL("https://www.arakhne.org/";), //$NON-NLS-1$
+				FileSystem.getParentURL(new URL("https://www.arakhne.org/toto";))); //$NON-NLS-1$
+		assertEquals(
+				new URL("https://www.arakhne.org/";), //$NON-NLS-1$
+				FileSystem.getParentURL(new URL("https://www.arakhne.org/toto/";))); //$NON-NLS-1$
+		assertEquals(
+				new URL("https://www.arakhne.org/toto/";), //$NON-NLS-1$
+				FileSystem.getParentURL(new URL("https://www.arakhne.org/toto/titi";))); //$NON-NLS-1$
+		assertEquals(
+				new URL("https://www.arakhne.org/toto/";), //$NON-NLS-1$
+				FileSystem.getParentURL(new URL("https://www.arakhne.org/toto/titi/";))); //$NON-NLS-1$
+
+		assertEquals(
+				new URL("ftp://www.arakhne.org/";), //$NON-NLS-1$
+				FileSystem.getParentURL(new URL("ftp://www.arakhne.org";))); //$NON-NLS-1$
+		assertEquals(
+				new URL("ftp://www.arakhne.org/";), //$NON-NLS-1$
+				FileSystem.getParentURL(new URL("ftp://www.arakhne.org/";))); //$NON-NLS-1$
+		assertEquals(
+				new URL("ftp://www.arakhne.org/";), //$NON-NLS-1$
+				FileSystem.getParentURL(new URL("ftp://www.arakhne.org/toto";))); //$NON-NLS-1$
+		assertEquals(
+				new URL("ftp://www.arakhne.org/";), //$NON-NLS-1$
+				FileSystem.getParentURL(new URL("ftp://www.arakhne.org/toto/";))); //$NON-NLS-1$
+		assertEquals(
+				new URL("ftp://www.arakhne.org/toto/";), //$NON-NLS-1$
+				FileSystem.getParentURL(new URL("ftp://www.arakhne.org/toto/titi";))); //$NON-NLS-1$
+		assertEquals(
+				new URL("ftp://www.arakhne.org/toto/";), //$NON-NLS-1$
+				FileSystem.getParentURL(new URL("ftp://www.arakhne.org/toto/titi/";))); //$NON-NLS-1$
+
+		assertEquals(
+				new URL("file:/toto/"), //$NON-NLS-1$
+				FileSystem.getParentURL(new URL("file:/toto/titi"))); //$NON-NLS-1$
+		assertEquals(
+				new URL("file:/toto/"), //$NON-NLS-1$
+				FileSystem.getParentURL(new URL("file:/toto/titi/"))); //$NON-NLS-1$
+		assertEquals(
+				new URL("file:/"), //$NON-NLS-1$
+				FileSystem.getParentURL(new URL("file:/toto"))); //$NON-NLS-1$
+		assertEquals(
+				new URL("file:/"), //$NON-NLS-1$
+				FileSystem.getParentURL(new URL("file:/toto/"))); //$NON-NLS-1$
+		assertEquals(
+				new URL("file:./toto/"), //$NON-NLS-1$
+				FileSystem.getParentURL(new URL("file:./toto/titi"))); //$NON-NLS-1$
+		assertEquals(
+				new URL("file:./toto/"), //$NON-NLS-1$
+				FileSystem.getParentURL(new URL("file:./toto/titi/"))); //$NON-NLS-1$
+		assertEquals(
+				new URL("file:./"), //$NON-NLS-1$
+				FileSystem.getParentURL(new URL("file:./toto"))); //$NON-NLS-1$
+		assertEquals(
+				new URL("file:./"), //$NON-NLS-1$
+				FileSystem.getParentURL(new URL("file:./toto/"))); //$NON-NLS-1$
+		assertEquals(
+				new URL("file:../"), //$NON-NLS-1$
+				FileSystem.getParentURL(new URL("file:."))); //$NON-NLS-1$
+		assertEquals(
+				new URL("file:../"), //$NON-NLS-1$
+				FileSystem.getParentURL(new URL("file:./"))); //$NON-NLS-1$
+		assertEquals(
+				new URL("file:../"), //$NON-NLS-1$
+				FileSystem.getParentURL(new URL("file:toto"))); //$NON-NLS-1$
+		assertEquals(
+				new URL("file:../"), //$NON-NLS-1$
+				FileSystem.getParentURL(new URL("file:toto/"))); //$NON-NLS-1$
+
+		assertEquals(
+				new URL("jar:file:test.jar!/toto/"), //$NON-NLS-1$
+				FileSystem.getParentURL(new URL("jar:file:test.jar!/toto/titi"))); //$NON-NLS-1$
+		assertEquals(
+				new URL("jar:file:test.jar!/toto/"), //$NON-NLS-1$
+				FileSystem.getParentURL(new URL("jar:file:test.jar!/toto/titi/"))); //$NON-NLS-1$
+		assertEquals(
+				new URL("jar:file:test.jar!/"), //$NON-NLS-1$
+				FileSystem.getParentURL(new URL("jar:file:test.jar!/toto"))); //$NON-NLS-1$
+		assertEquals(
+				new URL("jar:file:test.jar!/"), //$NON-NLS-1$
+				FileSystem.getParentURL(new URL("jar:file:test.jar!/toto/"))); //$NON-NLS-1$
+		assertEquals(
+				new URL("jar:file:test.jar!/"), //$NON-NLS-1$
+				FileSystem.getParentURL(new URL("jar:file:test.jar!/"))); //$NON-NLS-1$
+	}
+
+}

Added: tags/afc-2.0/arakhneVmutils/java/src/test/java/org/arakhne/vmutil/FileURLConnectionTest.java
===================================================================
--- tags/afc-2.0/arakhneVmutils/java/src/test/java/org/arakhne/vmutil/FileURLConnectionTest.java	                        (rev 0)
+++ tags/afc-2.0/arakhneVmutils/java/src/test/java/org/arakhne/vmutil/FileURLConnectionTest.java	2010-01-21 08:29:52 UTC (rev 117)
@@ -0,0 +1,144 @@
+/* 
+ * $Id$
+ * 
+ * Copyright (C) 2010 St&eacute;phane GALLAND
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * This program is free software; you can redistribute it and/or modify
+ */
+package org.arakhne.vmutil;
+
+import java.io.BufferedReader;
+import java.io.BufferedWriter;
+import java.io.File;
+import java.io.FileReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.OutputStream;
+import java.io.OutputStreamWriter;
+import java.net.URL;
+import java.net.URLConnection;
+import java.util.Collections;
+import java.util.Map;
+
+import junit.framework.TestCase;
+
+/**
+ * @author St&eacute;phane GALLAND &lt;galland@xxxxxxxxxxx&gt;
+ * @version $Name$ $Revision$ $Date$
+ */
+public class FileURLConnectionTest extends TestCase {
+
+	private FileURLConnection connection;
+	
+	static {
+		URL.setURLStreamHandlerFactory(new FileURLStreamHandlerFactory());
+	}
+	
+	/**
+	 * {@inheritDoc}
+	 */
+	@Override
+	public void setUp() throws Exception {
+		super.setUp();
+		URL resourceUrl = Resources.getResource("org/arakhne/vmutil/test.txt"); //$NON-NLS-1$
+		assertNotNull(resourceUrl);
+		this.connection = new FileURLConnection(resourceUrl);
+	}
+	
+	/**
+	 * {@inheritDoc}
+	 */
+	@Override
+	public void tearDown() throws Exception {
+		this.connection = null;
+		super.tearDown();
+	}
+
+    /**
+     */
+    public void testGetHeaderFieldKeyInt() {
+    	assertEquals("content-type", this.connection.getHeaderFieldKey(0)); //$NON-NLS-1$
+    	assertEquals("content-length", this.connection.getHeaderFieldKey(1)); //$NON-NLS-1$
+    	assertEquals("last-modified", this.connection.getHeaderFieldKey(2)); //$NON-NLS-1$
+    	assertNull(this.connection.getHeaderFieldKey(3));
+    }
+
+    /**
+     */
+    public void testGetHeaderFieldInt() {
+    	assertEquals("text/plain", this.connection.getHeaderField(0)); //$NON-NLS-1$
+    	assertEquals("19", this.connection.getHeaderField(1)); //$NON-NLS-1$
+    	assertNotNull(this.connection.getHeaderField(2));
+    	assertNull(this.connection.getHeaderField(3));
+    }
+	
+    /**
+     */
+    public void testGetHeaderFieldString() {
+    	assertEquals("text/plain", this.connection.getHeaderField("content-type")); //$NON-NLS-1$ //$NON-NLS-2$
+    	assertEquals("19", this.connection.getHeaderField("content-length")); //$NON-NLS-1$ //$NON-NLS-2$
+    	assertNotNull(this.connection.getHeaderField("last-modified")); //$NON-NLS-1$
+    	assertNull(this.connection.getHeaderField("expires")); //$NON-NLS-1$
+    }
+		
+    /**
+     */
+    public void testGetHeaderFields() {
+    	Map<?,?> map = this.connection.getHeaderFields();
+    	assertNotNull(map);
+    	assertEquals(3, map.size());
+    	assertEquals(Collections.singletonList("text/plain"), map.get("content-type")); //$NON-NLS-1$ //$NON-NLS-2$
+    	assertEquals(Collections.singletonList("19"), map.get("content-length")); //$NON-NLS-1$ //$NON-NLS-2$
+    	assertNotNull(map.get("last-modified")); //$NON-NLS-1$
+    	assertNull(map.get("expires")); //$NON-NLS-1$
+    }
+	
+	/**
+	 * @throws IOException
+	 */
+	public void testGetInputStream() throws IOException {
+		InputStream is = this.connection.getInputStream();
+		BufferedReader br = new BufferedReader(new InputStreamReader(is));
+		String line = br.readLine();
+		br.close();
+		assertEquals("FOR UNIT TEST ONLY ", line); //$NON-NLS-1$
+    }
+
+	/**
+	 * @throws IOException
+	 */
+	public void testGetOutputStream() throws IOException {
+		File tmpFile = File.createTempFile("unittest", ".txt"); //$NON-NLS-1$ //$NON-NLS-2$
+		tmpFile.deleteOnExit();
+
+		URLConnection con = new FileURLConnection(tmpFile.toURI().toURL());
+		con.setDoOutput(true);
+		
+		OutputStream os = con.getOutputStream();
+		BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(os));
+		bw.write("HELLO WORLD!"); //$NON-NLS-1$
+		bw.close();
+		
+		assertEquals(12, tmpFile.length());
+		
+		BufferedReader br = new BufferedReader(new FileReader(tmpFile));
+		String line = br.readLine();
+		br.close();
+		assertEquals("HELLO WORLD!", line); //$NON-NLS-1$
+    }
+		
+}

Added: tags/afc-2.0/arakhneVmutils/java/src/test/java/org/arakhne/vmutil/ResourceURLConnectionTest.java
===================================================================
--- tags/afc-2.0/arakhneVmutils/java/src/test/java/org/arakhne/vmutil/ResourceURLConnectionTest.java	                        (rev 0)
+++ tags/afc-2.0/arakhneVmutils/java/src/test/java/org/arakhne/vmutil/ResourceURLConnectionTest.java	2010-01-21 08:29:52 UTC (rev 117)
@@ -0,0 +1,74 @@
+/* 
+ * $Id$
+ * 
+ * Copyright (C) 2010 St&eacute;phane GALLAND
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * This program is free software; you can redistribute it and/or modify
+ */
+package org.arakhne.vmutil;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.net.URL;
+
+import junit.framework.TestCase;
+
+/**
+ * @author St&eacute;phane GALLAND &lt;galland@xxxxxxxxxxx&gt;
+ * @version $Name$ $Revision$ $Date$
+ */
+public class ResourceURLConnectionTest extends TestCase {
+
+	private ResourceURLConnection connection;
+	
+	static {
+		URL.setURLStreamHandlerFactory(new ResourceURLStreamHandlerFactory());
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	@Override
+	public void setUp() throws Exception {
+		super.setUp();
+		URL resourceUrl = new URL("resource:org/arakhne/vmutil/test.txt"); //$NON-NLS-1$
+		assertNotNull(resourceUrl);
+		this.connection = new ResourceURLConnection(resourceUrl);
+	}
+	
+	/**
+	 * {@inheritDoc}
+	 */
+	@Override
+	public void tearDown() throws Exception {
+		this.connection = null;
+		super.tearDown();
+	}
+	
+	/**
+	 * @throws IOException
+	 */
+	public void testGetInputStream() throws IOException {
+		InputStream is = this.connection.getInputStream();
+		BufferedReader br = new BufferedReader(new InputStreamReader(is));
+		String line = br.readLine();
+		br.close();
+		assertEquals("FOR UNIT TEST ONLY ", line); //$NON-NLS-1$
+    }
+
+}

Added: tags/afc-2.0/arakhneVmutils/java/src/test/java/org/arakhne/vmutil/ResourcesTest.java
===================================================================
--- tags/afc-2.0/arakhneVmutils/java/src/test/java/org/arakhne/vmutil/ResourcesTest.java	                        (rev 0)
+++ tags/afc-2.0/arakhneVmutils/java/src/test/java/org/arakhne/vmutil/ResourcesTest.java	2010-01-21 08:29:52 UTC (rev 117)
@@ -0,0 +1,99 @@
+/* $Id$
+ * 
+ * Copyright (C) 2007-09 St&eacute;phane GALLAND
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * This program is free software; you can redistribute it and/or modify
+ */
+package org.arakhne.vmutil;
+
+import java.io.InputStream;
+import java.net.URL;
+
+import junit.framework.TestCase;
+
+/**
+* @author St&eacute;phane GALLAND &lt;galland@xxxxxxxxxxx&gt;
+* @version $Name$ $Revision$ $Date$
+*/
+public class ResourcesTest extends TestCase {
+
+    /**
+     */
+    public void testGetResourceString() {
+    	URL u1 = Resources.getResource("/org/arakhne/vmutil/test.txt"); //$NON-NLS-1$
+    	assertNotNull(u1);
+    	
+    	URL u2 = Resources.getResource("org/arakhne/vmutil/test.txt"); //$NON-NLS-1$
+    	assertNotNull(u2);
+    	
+    	assertEquals(u1,u2);
+    }
+
+   	/**
+     */
+    public void testGetResourceClassString() {
+    	URL u1 = Resources.getResource(ResourcesTest.class, "/org/arakhne/vmutil/test.txt"); //$NON-NLS-1$
+    	assertNotNull(u1);
+    	
+    	URL u2 = Resources.getResource(ResourcesTest.class, "org/arakhne/vmutil/test.txt"); //$NON-NLS-1$
+    	assertNotNull(u2);
+    	
+    	assertEquals(u1,u2);
+    }
+
+   	/**
+     */
+    public void testGetResourceClassLoaderString() {
+    	URL u1 = Resources.getResource(ResourcesTest.class.getClassLoader(), "/org/arakhne/vmutil/test.txt"); //$NON-NLS-1$
+    	assertNotNull(u1);
+    	
+    	URL u2 = Resources.getResource(ResourcesTest.class.getClassLoader(), "org/arakhne/vmutil/test.txt"); //$NON-NLS-1$
+    	assertNotNull(u2);
+    	
+    	assertEquals(u1,u2);
+    }
+    
+    /**
+     */
+    public void testGetResourceAsStreamString() {
+    	InputStream is = Resources.getResourceAsStream("/org/arakhne/vmutil/test.txt"); //$NON-NLS-1$
+    	assertNotNull(is);
+    	
+    	is = Resources.getResourceAsStream("org/arakhne/vmutil/test.txt"); //$NON-NLS-1$
+    	assertNotNull(is);
+    }
+
+   	/**
+     */
+    public void testGetResourceAsStreamClassString() {
+    	InputStream is = Resources.getResourceAsStream(ResourcesTest.class, "/org/arakhne/vmutil/test.txt"); //$NON-NLS-1$
+    	assertNotNull(is);
+    	
+    	is = Resources.getResourceAsStream(ResourcesTest.class, "org/arakhne/vmutil/test.txt"); //$NON-NLS-1$
+    	assertNotNull(is);
+    }
+
+   	/**
+     */
+    public void testGetResourceAsStreamClassLoaderString() {
+    	InputStream is = Resources.getResourceAsStream(ResourcesTest.class.getClassLoader(), "/org/arakhne/vmutil/test.txt"); //$NON-NLS-1$
+    	assertNotNull(is);
+    	
+    	is = Resources.getResourceAsStream(ResourcesTest.class.getClassLoader(), "org/arakhne/vmutil/test.txt"); //$NON-NLS-1$
+    	assertNotNull(is);
+    }
+
+}

Added: tags/afc-2.0/arakhneVmutils/java/src/test/java/org/arakhne/vmutil/VMCommandLineTest.java
===================================================================
--- tags/afc-2.0/arakhneVmutils/java/src/test/java/org/arakhne/vmutil/VMCommandLineTest.java	                        (rev 0)
+++ tags/afc-2.0/arakhneVmutils/java/src/test/java/org/arakhne/vmutil/VMCommandLineTest.java	2010-01-21 08:29:52 UTC (rev 117)
@@ -0,0 +1,294 @@
+/* $Id$
+ * 
+ * Copyright (C) 2007-09 St&eacute;phane GALLAND
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * This program is free software; you can redistribute it and/or modify
+ */
+package org.arakhne.vmutil;
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+
+import junit.framework.TestCase;
+
+/**
+* @author St&eacute;phane GALLAND &lt;galland@xxxxxxxxxxx&gt;
+* @version $Name$ $Revision$ $Date$
+*/
+public class VMCommandLineTest extends TestCase {
+
+	private static final String[] commandLine = new String[] { 
+			"-D=true", "-v", "clean", "-v", //$NON-NLS-1$//$NON-NLS-2$//$NON-NLS-3$//$NON-NLS-4$
+			"-F", "-b", "-v", "package", //$NON-NLS-1$//$NON-NLS-2$//$NON-NLS-3$//$NON-NLS-4$
+			"-F", "123", "-nob", "installters", //$NON-NLS-1$//$NON-NLS-2$//$NON-NLS-3$//$NON-NLS-4$
+			"-S", "-b", "--", "-v"}; //$NON-NLS-1$//$NON-NLS-2$//$NON-NLS-3$//$NON-NLS-4$
+	
+	private static final String[] commandLine2 = new String[] {"-D=true"}; //$NON-NLS-1$
+
+	private static final String[] optionDefinitions = new String[] {
+			"D=b", "S=s", "F:f", "v+", "b!"}; //$NON-NLS-1$//$NON-NLS-2$//$NON-NLS-3$//$NON-NLS-4$//$NON-NLS-5$
+
+	@Override
+	protected void setUp() throws Exception {
+		super.setUp();
+		VMCommandLine.saveVMParameters(null, new String[0]);
+	}
+	
+	/**
+	 */
+	public final void testSaveVMParameters() {
+		assertTrue(Arrays.equals(new String[0], VMCommandLine.getCommandLineParameters()));
+		VMCommandLine.saveVMParameters(VMCommandLineTest.class, commandLine);
+		assertTrue(Arrays.equals(commandLine, VMCommandLine.getCommandLineParameters()));
+		VMCommandLine.saveVMParameters(VMCommandLineTest.class, commandLine2);
+		assertTrue(Arrays.equals(commandLine2, VMCommandLine.getCommandLineParameters()));
+	}
+
+	/**
+	 */
+	public final void testSaveVMParametersIfNotSet() {
+		assertTrue(Arrays.equals(new String[0], VMCommandLine.getCommandLineParameters()));
+		VMCommandLine.saveVMParametersIfNotSet(VMCommandLineTest.class, commandLine);
+		assertTrue(Arrays.equals(commandLine, VMCommandLine.getCommandLineParameters()));
+		VMCommandLine.saveVMParametersIfNotSet(VMCommandLineTest.class, commandLine2);
+		assertTrue(Arrays.equals(commandLine, VMCommandLine.getCommandLineParameters()));
+	}
+
+	/**
+	 */
+	public final void testShiftCommandLineParameters() {
+		VMCommandLine.saveVMParameters(VMCommandLineTest.class, commandLine);
+		assertEquals("-D=true", VMCommandLine.shiftCommandLineParameters()); //$NON-NLS-1$
+		assertTrue(Arrays.equals(new String[] { 
+				"-v", "clean", "-v", //$NON-NLS-1$//$NON-NLS-2$//$NON-NLS-3$
+				"-F", "-b", "-v", "package", //$NON-NLS-1$//$NON-NLS-2$//$NON-NLS-3$//$NON-NLS-4$
+				"-F", "123", "-nob", "installters", //$NON-NLS-1$//$NON-NLS-2$//$NON-NLS-3$//$NON-NLS-4$
+				"-S", "-b", "--", "-v"}, //$NON-NLS-1$//$NON-NLS-2$//$NON-NLS-3$//$NON-NLS-4$
+				VMCommandLine.getCommandLineParameters()));
+	}
+
+	/**
+	 */
+	public final void testGetCommandLineOptions() {
+		assertEquals(Collections.emptyMap(), VMCommandLine.getCommandLineOptions());
+	}
+
+	/**
+	 */
+	public final void testSplitOptionsAndParameters() {
+		VMCommandLine.saveVMParameters(VMCommandLineTest.class, commandLine);
+		VMCommandLine.splitOptionsAndParameters(optionDefinitions);
+
+		Map<String,List<Object>> options = VMCommandLine.getCommandLineOptions();
+		String[] parameters = VMCommandLine.getCommandLineParameters();
+		List<Object> values;
+		
+		assertNotNull(options);
+		assertEquals(5, options.size());
+		
+		assertTrue(options.containsKey("D")); //$NON-NLS-1$
+		values = options.get("D"); //$NON-NLS-1$
+		assertNotNull(values);
+		assertEquals(1, values.size());
+		assertEquals(true, values.get(0));
+
+		assertTrue(options.containsKey("v")); //$NON-NLS-1$
+		values = options.get("v"); //$NON-NLS-1$
+		assertNotNull(values);
+		assertEquals(1, values.size());
+		assertEquals((long)3, values.get(0));
+
+		assertTrue(options.containsKey("F")); //$NON-NLS-1$
+		values = options.get("F"); //$NON-NLS-1$
+		assertNotNull(values);
+		assertEquals(2, values.size());
+		assertEquals(0., values.get(0));
+		assertEquals(123., values.get(1));
+
+		assertTrue(options.containsKey("b")); //$NON-NLS-1$
+		values = options.get("b"); //$NON-NLS-1$
+		assertNotNull(values);
+		assertEquals(1, values.size());
+		assertEquals(false, values.get(0));
+
+		assertTrue(options.containsKey("S")); //$NON-NLS-1$
+		values = options.get("S"); //$NON-NLS-1$
+		assertNotNull(values);
+		assertEquals(1, values.size());
+		assertEquals("-b", values.get(0)); //$NON-NLS-1$
+		
+		values = options.get("nob"); //$NON-NLS-1$
+		assertNull(values);
+
+		assertNotNull(parameters);
+		assertEquals(4, parameters.length);
+		assertEquals("clean", parameters[0]); //$NON-NLS-1$
+		assertEquals("package", parameters[1]); //$NON-NLS-1$
+		assertEquals("installters", parameters[2]); //$NON-NLS-1$
+		assertEquals("-v", parameters[3]); //$NON-NLS-1$
+	}
+
+	/**
+	 */
+	public final void testGetCommandLineOption() {
+		assertNull(VMCommandLine.getCommandLineOption("S")); //$NON-NLS-1$
+		
+		VMCommandLine.saveVMParameters(VMCommandLineTest.class, commandLine);
+		VMCommandLine.splitOptionsAndParameters(optionDefinitions);
+		
+		List<Object> values;
+		values = VMCommandLine.getCommandLineOption("S"); //$NON-NLS-1$
+		assertNotNull(values);
+		assertEquals(1, values.size());
+		assertEquals("-b", values.get(0)); //$NON-NLS-1$
+
+		assertNull(VMCommandLine.getCommandLineOption("nob")); //$NON-NLS-1$
+	}
+
+	/**
+	 */
+	public final void testHasCommandLineOption() {
+		assertFalse(VMCommandLine.hasCommandLineOption("S")); //$NON-NLS-1$
+		
+		VMCommandLine.saveVMParameters(VMCommandLineTest.class, commandLine);
+		VMCommandLine.splitOptionsAndParameters(optionDefinitions);
+		
+		assertTrue(VMCommandLine.hasCommandLineOption("S")); //$NON-NLS-1$
+		assertFalse(VMCommandLine.hasCommandLineOption("nob")); //$NON-NLS-1$
+	}
+
+	/**
+	 */
+	public final void testVMCommandLineClassOfQStringArray() {
+		VMCommandLine c = new VMCommandLine(VMCommandLineTest.class, commandLine);
+		assertTrue(Arrays.equals(commandLine, c.getParameters()));
+	}
+
+	/**
+	 */
+	public final void testVMCommandLineClassOfQStringArrayStringArray() {
+		VMCommandLine c = new VMCommandLine(VMCommandLineTest.class, optionDefinitions, commandLine);
+		assertTrue(Arrays.equals(new String[] {
+				"clean", "package", "installters", "-v" //$NON-NLS-1$//$NON-NLS-2$//$NON-NLS-3$//$NON-NLS-4$
+		}, c.getParameters()));
+	}
+
+	/**
+	 */
+	public final void testHasOption() {
+		VMCommandLine c = new VMCommandLine(VMCommandLineTest.class, optionDefinitions, commandLine);
+		assertTrue(c.hasOption("S")); //$NON-NLS-1$
+		assertTrue(c.hasOption("b")); //$NON-NLS-1$
+		assertFalse(c.hasOption("nob")); //$NON-NLS-1$
+	}
+
+	/**
+	 */
+	public final void testGetFirstOptionValue() {
+		VMCommandLine c = new VMCommandLine(VMCommandLineTest.class, optionDefinitions, commandLine);
+		assertEquals("-b", c.getFirstOptionValue("S")); //$NON-NLS-1$ //$NON-NLS-2$
+		assertEquals(false, c.getFirstOptionValue("b")); //$NON-NLS-1$
+		assertEquals(0., c.getFirstOptionValue("F")); //$NON-NLS-1$
+		assertNull(c.getFirstOptionValue("nob")); //$NON-NLS-1$
+	}
+
+	/**
+	 */
+	public final void testGetOptionValues() {
+		VMCommandLine c = new VMCommandLine(VMCommandLineTest.class, optionDefinitions, commandLine);
+		List<Object> values;
+		
+		values = c.getOptionValues("D"); //$NON-NLS-1$
+		assertNotNull(values);
+		assertEquals(1, values.size());
+		assertEquals(true, values.get(0));
+
+		values = c.getOptionValues("v"); //$NON-NLS-1$
+		assertNotNull(values);
+		assertEquals(1, values.size());
+		assertEquals((long)3, values.get(0));
+
+		values = c.getOptionValues("F"); //$NON-NLS-1$
+		assertNotNull(values);
+		assertEquals(2, values.size());
+		assertEquals(0., values.get(0));
+		assertEquals(123., values.get(1));
+
+		values = c.getOptionValues("b"); //$NON-NLS-1$
+		assertNotNull(values);
+		assertEquals(1, values.size());
+		assertEquals(false, values.get(0));
+
+		values = c.getOptionValues("S"); //$NON-NLS-1$
+		assertNotNull(values);
+		assertEquals(1, values.size());
+		assertEquals("-b", values.get(0)); //$NON-NLS-1$
+
+		assertNull(c.getOptionValues("nob")); //$NON-NLS-1$
+	}
+
+	/**
+	 */
+	public final void testGetParameters() {
+		VMCommandLine c = new VMCommandLine(VMCommandLineTest.class, optionDefinitions, commandLine);
+		assertNotSame(commandLine, c.getParameters());
+		assertTrue(Arrays.equals(new String[] {
+				"clean", "package", "installters", "-v" //$NON-NLS-1$//$NON-NLS-2$//$NON-NLS-3$//$NON-NLS-4$
+		}, c.getParameters()));
+	}
+
+	/**
+	 */
+	public final void testShiftParameters() {
+		VMCommandLine c = new VMCommandLine(VMCommandLineTest.class, optionDefinitions, commandLine);
+		assertEquals("clean", c.shiftParameters()); //$NON-NLS-1$
+		assertNotSame(commandLine, c.getParameters());
+		assertTrue(Arrays.equals(new String[] {
+				"package", "installters", "-v" //$NON-NLS-1$//$NON-NLS-2$//$NON-NLS-3$
+		}, c.getParameters()));
+	}
+
+	/**
+	 */
+	public final void testGetParameterCount() {
+		VMCommandLine c = new VMCommandLine(VMCommandLineTest.class, optionDefinitions, commandLine);
+		assertEquals(4, c.getParameterCount());
+	}
+
+	/**
+	 */
+	public final void testGetParameterAt() {
+		VMCommandLine c = new VMCommandLine(VMCommandLineTest.class, optionDefinitions, commandLine);
+		assertEquals("clean", c.getParameterAt(0)); //$NON-NLS-1$
+		assertEquals("package", c.getParameterAt(1)); //$NON-NLS-1$
+		assertEquals("installters", c.getParameterAt(2)); //$NON-NLS-1$
+		assertEquals("-v", c.getParameterAt(3)); //$NON-NLS-1$
+	}
+
+	/**
+	 */
+	public final void testIsParameterExists() {
+		VMCommandLine c = new VMCommandLine(VMCommandLineTest.class, optionDefinitions, commandLine);
+		assertTrue(c.isParameterExists(0));
+		assertTrue(c.isParameterExists(1));
+		assertTrue(c.isParameterExists(2));
+		assertTrue(c.isParameterExists(3));
+		assertFalse(c.isParameterExists(5));
+	}
+
+}

Added: tags/afc-2.0/arakhneVmutils/java/src/test/resources/org/arakhne/vmutil/test.txt
===================================================================
--- tags/afc-2.0/arakhneVmutils/java/src/test/resources/org/arakhne/vmutil/test.txt	                        (rev 0)
+++ tags/afc-2.0/arakhneVmutils/java/src/test/resources/org/arakhne/vmutil/test.txt	2010-01-21 08:29:52 UTC (rev 117)
@@ -0,0 +1 @@
+FOR UNIT TEST ONLY 
\ No newline at end of file

Added: tags/afc-2.0/arakhneVmutils/native/josuuid/linux32/pom.xml
===================================================================
--- tags/afc-2.0/arakhneVmutils/native/josuuid/linux32/pom.xml	                        (rev 0)
+++ tags/afc-2.0/arakhneVmutils/native/josuuid/linux32/pom.xml	2010-01-21 08:29:52 UTC (rev 117)
@@ -0,0 +1,94 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"; xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"; xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd";>
+
+  <modelVersion>4.0.0</modelVersion>
+
+  <parent>
+  	<artifactId>josuuid</artifactId>
+	<groupId>org.arakhne.afc</groupId>
+	<version>4.2</version>
+  </parent>
+
+  <groupId>org.arakhne.afc</groupId>
+  <artifactId>josuuid-linux32</artifactId>
+  <packaging>so</packaging>
+  <version>4.2</version>
+  <name>${pom.artifactId}</name>
+
+	<!-- ======================================= -->
+	<!-- ====       Project Information      === -->
+	<!-- ======================================= -->
+		
+	<dependencies>
+		<dependency>
+			<groupId>org.arakhne.afc</groupId>
+			<artifactId>arakhneVmutils-java</artifactId>
+		    <version>${pom.version}</version>
+		</dependency>    
+	</dependencies>
+
+  <build>
+    <finalName>${artifactId}</finalName>
+    
+    <plugins>
+      <plugin>
+        <groupId>org.codehaus.mojo</groupId>
+        <artifactId>native-maven-plugin</artifactId>
+        <extensions>true</extensions>       
+        <configuration>
+          <compilerProvider>generic</compilerProvider>
+          <compilerStartOptions>
+            <compilerStartOption>-m32 -O3 -Wall -Werror -fmessage-length=0</compilerStartOption>
+          </compilerStartOptions>
+          
+          <javahOS>linux</javahOS>
+          
+          <sources>
+            <source>
+	      <directory>../src/main/native</directory>
+	      <fileNames>
+                <fileName>josuuid.cpp</fileName>
+                <fileName>OperatingSystemJNI.cpp</fileName>
+	      </fileNames>
+            </source>
+
+          </sources>
+            
+          <linkerStartOptions>
+            <linkerStartOption>-m32 -shared -lstdc++</linkerStartOption>
+          </linkerStartOptions>
+                    
+        </configuration>
+        
+        <executions>
+          <execution>
+            <id>javah</id>
+            <phase>generate-sources</phase>
+            <configuration>
+              <classNames>
+                <className>org.arakhne.vmutil.OperatingSystem</className>
+              </classNames>
+            </configuration>
+            <goals>
+              <goal>javah</goal> 
+            </goals>
+          </execution>
+        </executions>
+      </plugin>
+
+      <plugin>
+        <artifactId>maven-surefire-plugin</artifactId>
+        <configuration>
+          <forkMode>once</forkMode>
+          <environmentVariables>
+            <LD_LIBRARY_PATH>${project.build.directory}</LD_LIBRARY_PATH>
+          </environmentVariables>
+        </configuration>
+      </plugin>
+	
+    </plugins>    
+
+  </build>
+
+
+</project>

Added: tags/afc-2.0/arakhneVmutils/native/josuuid/linux64/pom.xml
===================================================================
--- tags/afc-2.0/arakhneVmutils/native/josuuid/linux64/pom.xml	                        (rev 0)
+++ tags/afc-2.0/arakhneVmutils/native/josuuid/linux64/pom.xml	2010-01-21 08:29:52 UTC (rev 117)
@@ -0,0 +1,94 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"; xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"; xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd";>
+
+  <modelVersion>4.0.0</modelVersion>
+
+  <parent>
+  	<artifactId>josuuid</artifactId>
+	<groupId>org.arakhne.afc</groupId>
+	<version>4.2</version>
+  </parent>
+
+  <groupId>org.arakhne.afc</groupId>
+  <artifactId>josuuid-linux64</artifactId>
+  <packaging>so</packaging>
+  <version>4.2</version>
+  <name>${pom.artifactId}</name>
+
+	<!-- ======================================= -->
+	<!-- ====       Project Information      === -->
+	<!-- ======================================= -->
+		
+	<dependencies>
+		<dependency>
+			<groupId>org.arakhne.afc</groupId>
+			<artifactId>arakhneVmutils-java</artifactId>
+		    <version>${pom.version}</version>
+		</dependency>    
+	</dependencies>
+
+  <build>
+    <finalName>${artifactId}</finalName>
+    
+    <plugins>
+      <plugin>
+        <groupId>org.codehaus.mojo</groupId>
+        <artifactId>native-maven-plugin</artifactId>
+        <extensions>true</extensions>       
+        <configuration>
+          <compilerProvider>generic</compilerProvider>
+          <compilerStartOptions>
+            <compilerStartOption>-m64 -fPIC -O3 -Wall -Werror -fmessage-length=0</compilerStartOption>
+          </compilerStartOptions>
+          
+          <javahOS>linux</javahOS>
+          
+          <sources>
+            <source>
+	      <directory>../src/main/native</directory>
+	      <fileNames>
+                <fileName>josuuid.cpp</fileName>
+                <fileName>OperatingSystemJNI.cpp</fileName>
+	      </fileNames>
+            </source>
+
+          </sources>
+            
+          <linkerStartOptions>
+            <linkerStartOption>-m64 -shared -lstdc++</linkerStartOption>
+          </linkerStartOptions>
+                    
+        </configuration>
+        
+        <executions>
+          <execution>
+            <id>javah</id>
+            <phase>generate-sources</phase>
+            <configuration>
+              <classNames>
+                <className>org.arakhne.vmutil.OperatingSystem</className>
+              </classNames>
+            </configuration>
+            <goals>
+              <goal>javah</goal> 
+            </goals>
+          </execution>
+        </executions>
+      </plugin>
+
+      <plugin>
+        <artifactId>maven-surefire-plugin</artifactId>
+        <configuration>
+          <forkMode>once</forkMode>
+          <environmentVariables>
+            <LD_LIBRARY_PATH>${project.build.directory}</LD_LIBRARY_PATH>
+          </environmentVariables>
+        </configuration>
+      </plugin>
+	
+    </plugins>    
+
+  </build>
+
+
+</project>

Added: tags/afc-2.0/arakhneVmutils/native/josuuid/mingw/pom.xml
===================================================================
--- tags/afc-2.0/arakhneVmutils/native/josuuid/mingw/pom.xml	                        (rev 0)
+++ tags/afc-2.0/arakhneVmutils/native/josuuid/mingw/pom.xml	2010-01-21 08:29:52 UTC (rev 117)
@@ -0,0 +1,130 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"; xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"; xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd";>
+
+  <modelVersion>4.0.0</modelVersion>
+
+  <parent>
+  	<artifactId>josuuid</artifactId>
+	<groupId>org.arakhne.afc</groupId>
+	<version>4.2</version>
+  </parent>
+
+  <groupId>org.arakhne.afc</groupId>
+  <artifactId>josuuid-mingw</artifactId>
+  <packaging>dll</packaging>
+  <version>4.2</version>
+  <name>${pom.artifactId}</name>
+
+	<!-- ======================================= -->
+	<!-- ====       Project Information      === -->
+	<!-- ======================================= -->
+		
+	<dependencies>
+		<dependency>
+			<groupId>org.arakhne.afc</groupId>
+			<artifactId>arakhneVmutils-java</artifactId>
+			<version>${pom.version}</version>
+		</dependency>    
+	</dependencies>
+
+  <build>
+    <finalName>${artifactId}</finalName>
+    
+    <plugins>
+
+     <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-enforcer-plugin</artifactId>
+        <executions>
+          <execution>
+            <id>enforce-beanshell</id>
+            <goals>
+              <goal>enforce</goal>
+            </goals>
+            <configuration>
+              <rules>
+                <evaluateBeanshell>
+                  <condition>
+			String path = System.getenv("PATH");
+			String[] parts = path.split(File.pathSeparator);
+			boolean ok = false;
+			for(int i=0; !ok &amp;&amp; i&lt;parts.length; i++) {
+				ok = new File(parts[i],"i586-mingw32msvc-g++").canExecute();
+			}
+			ok
+		  </condition>
+                </evaluateBeanshell>
+		<requireOS>
+		  <name>linux</name>
+		  <family>unix</family>
+		</requireOS>
+              </rules>  
+              <fail>true</fail>
+            </configuration>
+          </execution>
+        </executions>
+      </plugin>
+
+      <plugin>
+        <groupId>org.codehaus.mojo</groupId>
+        <artifactId>native-maven-plugin</artifactId>
+        <extensions>true</extensions>       
+        <configuration>
+          <compilerProvider>generic</compilerProvider>
+	  <compilerExecutable>i586-mingw32msvc-g++</compilerExecutable>
+          <compilerStartOptions>
+            <compilerStartOption>-O0 -Wall -Werror -fmessage-length=0</compilerStartOption>
+          </compilerStartOptions>
+          
+          <javahOS>linux</javahOS> <!-- not 'windows' to retreive the jni_md.h file -->
+          
+          <sources>
+            <source>
+	      <directory>../src/main/native</directory>
+	      <fileNames>
+                <fileName>josuuid.cpp</fileName>
+                <fileName>winos.cpp</fileName>
+                <fileName>OperatingSystemJNI.cpp</fileName>
+	      </fileNames>
+            </source>
+          </sources>
+            
+	  <linkerExecutable>i586-mingw32msvc-g++</linkerExecutable>
+          <linkerStartOptions>
+            <linkerStartOption>-shared</linkerStartOption>
+          </linkerStartOptions>
+                    
+        </configuration>
+        
+        <executions>
+          <execution>
+            <id>javah</id>
+            <phase>generate-sources</phase>
+            <configuration>
+              <classNames>
+                <className>org.arakhne.vmutil.OperatingSystem</className>
+              </classNames>
+            </configuration>
+            <goals>
+              <goal>javah</goal> 
+            </goals>
+          </execution>
+        </executions>
+      </plugin>
+
+      <plugin>
+        <artifactId>maven-surefire-plugin</artifactId>
+        <configuration>
+          <forkMode>once</forkMode>
+          <environmentVariables>
+            <LD_LIBRARY_PATH>${project.build.directory}</LD_LIBRARY_PATH>
+          </environmentVariables>
+        </configuration>
+      </plugin>
+	
+    </plugins>    
+
+  </build>
+
+
+</project>

Added: tags/afc-2.0/arakhneVmutils/native/josuuid/pom.xml
===================================================================
--- tags/afc-2.0/arakhneVmutils/native/josuuid/pom.xml	                        (rev 0)
+++ tags/afc-2.0/arakhneVmutils/native/josuuid/pom.xml	2010-01-21 08:29:52 UTC (rev 117)
@@ -0,0 +1,94 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"; xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"; xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd";>
+  <modelVersion>4.0.0</modelVersion>
+
+  <parent>
+  	<artifactId>arakhneVmutils-native</artifactId>
+	<groupId>org.arakhne.afc</groupId>
+	<version>4.2</version>
+  </parent>
+
+  <groupId>org.arakhne.afc</groupId>
+  <artifactId>josuuid</artifactId>
+  <packaging>pom</packaging>
+  <version>4.2</version>
+  <name>${pom.artifactId}</name>
+
+	<!-- ======================================= -->
+	<!-- ====       Project Information      === -->
+	<!-- ======================================= -->
+		
+  <profiles>
+  
+    <profile>
+      <id>linux-hosted</id>
+      <activation>
+	<os>
+		<name>linux</name>
+		<family>unix</family>
+	</os>
+      </activation>
+      <modules>
+        <module>linux32</module>
+        <module>linux64</module>
+        <module>mingw</module>
+      </modules>
+    </profile>
+    
+    <!--profile>
+      <id>win32</id>
+      <activation>
+	<os>
+		<name>Windows&reg;</name>
+		<family>Windows</family>
+		<arch>x86</arch>
+		<version>5.1.2600</version>
+	</os>
+      </activation>
+      <modules>
+        <module>win32</module>
+      </modules>
+    </profile>
+
+    <profile>
+      <id>macosx</id>
+      <activation>
+        <property>
+          <name>platform</name>
+          <value>macosx</value>
+        </property>
+      </activation>
+      <modules>
+        <module>macosx</module>
+      </modules>
+    </profile>
+    
+    <profile>
+      <id>aix</id>
+      <activation>
+        <property>
+          <name>platform</name>
+          <value>aix</value>
+        </property>
+      </activation>
+      <modules>
+        <module>aix</module>
+      </modules>
+    </profile>
+
+    <profile>
+      <id>solaris</id>
+      <activation>
+        <property>
+          <name>platform</name>
+          <value>solaris</value>
+        </property>
+      </activation>
+      <modules>
+        <module>solaris</module>
+      </modules>
+    </profile-->
+    
+  </profiles>
+
+</project>

Added: tags/afc-2.0/arakhneVmutils/native/josuuid/src/main/native/OperatingSystemJNI.cpp
===================================================================
--- tags/afc-2.0/arakhneVmutils/native/josuuid/src/main/native/OperatingSystemJNI.cpp	                        (rev 0)
+++ tags/afc-2.0/arakhneVmutils/native/josuuid/src/main/native/OperatingSystemJNI.cpp	2010-01-21 08:29:52 UTC (rev 117)
@@ -0,0 +1,65 @@
+/* 
+ * $Id$
+ * 
+ * Copyright (C) 2005-2008 St&eacute;phane GALLAND
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * This program is free software; you can redistribute it and/or modify
+ */
+ 
+#ifdef DEBUG
+# warning THE LIBRARY IS COMPILED WITH DEBUG INFORMATION
+#endif
+
+#include <jni.h>
+#include <stdlib.h>
+
+#include "org_arakhne_vmutil_OperatingSystem.h"
+#include "josuuid.h"
+
+/*
+ * Class:     org_arakhne_vmutil_OperatingSystem
+ * Method:    getOSSerialNumber
+ * Signature: ()Ljava/lang/String;
+ */
+JNIEXPORT jstring JNICALL
+Java_org_arakhne_vmutil_OperatingSystem_getOSSerialNumber
+(JNIEnv * env, jclass clazz) {
+	jstring jSerial = NULL;
+	char* cSerial = getOSSerial();
+	if (cSerial!=NULL) {
+		jSerial = env->NewStringUTF (cSerial);
+		free(cSerial);
+	}
+	return jSerial;
+}
+
+
+/*
+ * Class:     org_arakhne_vmutil_OperatingSystem
+ * Method:    getOSUUID
+ * Signature: ()Ljava/lang/String;
+ */
+JNIEXPORT jstring JNICALL
+Java_org_arakhne_vmutil_OperatingSystem_getOSUUID
+(JNIEnv *env, jclass clazz) {
+	jstring jUUID = NULL;
+	char* cUUID = getOSUUID();
+	if (cUUID!=NULL) {
+		jUUID = env->NewStringUTF (cUUID);
+		free(cUUID);
+	}
+	return jUUID;
+}

Added: tags/afc-2.0/arakhneVmutils/native/josuuid/src/main/native/josuuid.cpp
===================================================================
--- tags/afc-2.0/arakhneVmutils/native/josuuid/src/main/native/josuuid.cpp	                        (rev 0)
+++ tags/afc-2.0/arakhneVmutils/native/josuuid/src/main/native/josuuid.cpp	2010-01-21 08:29:52 UTC (rev 117)
@@ -0,0 +1,193 @@
+/* 
+ * $Id$
+ * 
+ * Copyright (C) 2005-2008 St&eacute;phane GALLAND
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * This program is free software; you can redistribute it and/or modify
+ */
+ 
+#ifdef DEBUG
+# warning THE LIBRARY IS COMPILED WITH DEBUG INFORMATION
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+
+#include "osmacro.h"
+
+#ifdef __WINDOWS__
+# include <windows.h>
+# include "winos.h"
+# define WINUUID_PART_COUNT 4
+static char hexCharacters[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
+#else
+# include <unistd.h>
+# define DWORD unsigned long int
+#endif
+
+#include "josuuid.h"
+
+/* Remove white spaces at the begining and at the end of a string */
+static void trim(char** text) {
+	char* t;
+	unsigned long startIdx, endIdx;
+	unsigned long len, i;
+	if ((text==NULL)||(*text==NULL)) return;
+    len = strlen(*text);
+    // Search starting character
+    for(startIdx=0; startIdx<len; startIdx++) {
+    	if (!isspace((*text)[startIdx])) break;
+    }
+    if (startIdx>=len) {
+    	free(*text);
+    	*text = strdup("");
+    	return;
+    }
+    // Search ending character
+    for(endIdx=len-1; endIdx>=0; endIdx--) {
+    	if (!isspace((*text)[endIdx])) break;
+    }
+    if (endIdx<0) {
+    	free(*text);
+    	*text = strdup("");
+    	return;
+    }
+    // Create the new string
+    t = (char*)malloc(sizeof(char)*(endIdx-startIdx+2));
+    for(i=0; startIdx<=endIdx; i++, startIdx++) {
+    	t[i] = (*text)[startIdx];
+    }
+    t[i] = '\0';
+    free(*text);
+    *text = t;
+}
+
+#ifndef __WINDOWS__
+/* Run the specified shell command and replies its standard output */
+static char* runCommand(const char* cmd) {
+	FILE* cmdOutput;
+	char* result = NULL;
+	
+	cmdOutput = popen(cmd, "r");
+	
+	if (cmdOutput!=NULL) {
+		char buffer[128];
+		unsigned long i,j, count = 0;
+		unsigned long charCount;
+		
+		charCount = fread(buffer, sizeof(char), 128, cmdOutput);
+		while (charCount>0) {
+			result = (char*)realloc(result,sizeof(char)*(count+charCount+1));
+			for(i=0, j=count; i<charCount; i++, j++) {
+				result[j] = buffer[i];
+			} 
+			count += charCount;
+			result[count] = '\0';
+			charCount = fread(buffer, sizeof(char), 128, cmdOutput);
+		}
+	
+		pclose(cmdOutput);
+	}
+	
+    return result;
+}
+#endif
+
+/* Replies the serial number of the system */
+char* getOSSerial() {
+#ifdef __WINDOWS__
+  	DWORD size = 0;
+  	BYTE* data = NULL;
+  	if (getWindowsSerial(&data, &size)) {
+	  	char* serial = new char[size];
+	  	for(unsigned long i=0; i<size; i++) {
+	  		serial[i] = data[i];
+	  	}
+	  	free(data);
+	  	trim(&serial);
+	  	return serial;
+  	}
+  	return NULL;
+#else
+	char* result = runCommand("hal-get-property --udi /org/freedesktop/Hal/devices/computer --key system.hardware.serial");
+	if (result!=NULL) {
+		trim(&result);
+	}
+	else {
+		result = runCommand("hal-get-property --udi /org/freedesktop/Hal/devices/computer --key smbios.system.serial");
+		if (result!=NULL) {
+			trim(&result);
+		}
+	}
+	return result;
+#endif
+}
+
+/* Replies the UUID of the system */
+char* getOSUUID() {
+#ifdef __WINDOWS__
+	DWORD size;
+	BYTE* data;
+  	if (getWindowsSerial(&data, &size)) {
+  		unsigned long i, j, k, totalSize = 2*(size-1);
+	  	char* serial = (char*)malloc(sizeof(char)*(totalSize+(totalSize/WINUUID_PART_COUNT)+2));
+  		char characterToTreat;
+  		short b0, b1;
+  		bool lastIsSeparator = false;
+	  	
+	  	for(i=0, j=0, k=WINUUID_PART_COUNT; i<size; i++) {
+	  		characterToTreat = data[i];
+	  		if (isalnum(characterToTreat)) {
+		  		b0 = (characterToTreat & 0x0F) ^ 0x0F;
+		  		b1 = ((characterToTreat & 0xF0) >> 4) ^ 0x0F;
+				serial[j++] = hexCharacters[b0];
+				serial[j++] = hexCharacters[b1];
+				k --;
+				if (k<=0) {
+					serial[j++] = '-';
+					k = WINUUID_PART_COUNT;
+					lastIsSeparator = true;
+				}
+				else {
+					lastIsSeparator = false;
+				}
+	  		}
+	  	}
+	  	if (lastIsSeparator) j--;
+	  	serial[j] = '\0';
+	  	free(data);
+	  	
+	  	trim(&serial);
+	  	
+	  	return serial;
+  	}
+  	return NULL;
+#else
+	char* result = runCommand("hal-get-property --udi /org/freedesktop/Hal/devices/computer --key system.hardware.uuid");
+	if (result!=NULL) {
+		trim(&result);
+	}
+	else {
+		result = runCommand("hal-get-property --udi /org/freedesktop/Hal/devices/computer --key smbios.system.uuid");
+		if (result!=NULL) {
+			trim(&result);
+		}
+	}
+	return result;
+#endif
+}

Added: tags/afc-2.0/arakhneVmutils/native/josuuid/src/main/native/josuuid.h
===================================================================
--- tags/afc-2.0/arakhneVmutils/native/josuuid/src/main/native/josuuid.h	                        (rev 0)
+++ tags/afc-2.0/arakhneVmutils/native/josuuid/src/main/native/josuuid.h	2010-01-21 08:29:52 UTC (rev 117)
@@ -0,0 +1,33 @@
+/* 
+ * $Id$
+ * 
+ * Copyright (C) 2005-2009 St&eacute;phane GALLAND
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * This program is free software; you can redistribute it and/or modify
+ */
+ 
+#ifndef __JOSUUID_H__
+#  define __JOSUUID_H__
+
+#  include "osmacro.h"
+
+/* Replies the serial number of the system */
+char* getOSSerial();
+
+/* Replies the UUID of the system */
+char* getOSUUID();
+
+#endif /* __JOSUUID_H__ */

Added: tags/afc-2.0/arakhneVmutils/native/josuuid/src/main/native/osmacro.h
===================================================================
--- tags/afc-2.0/arakhneVmutils/native/josuuid/src/main/native/osmacro.h	                        (rev 0)
+++ tags/afc-2.0/arakhneVmutils/native/josuuid/src/main/native/osmacro.h	2010-01-21 08:29:52 UTC (rev 117)
@@ -0,0 +1,33 @@
+/* 
+ * $Id$
+ * 
+ * Copyright (C) 2009 St&eacute;phane GALLAND
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * This program is free software; you can redistribute it and/or modify
+ */
+ 
+#ifndef __OSMACRO_H__
+#  define __OSMACRO_H__
+
+#  if defined(WINDOWS) || defined(WIN32) || defined(WIN64) || defined(WINNT)
+#    define __WINDOWS__
+#    undef __UNIX__
+#  else
+#    define __UNIX__
+#    undef __WINDOWS__
+#  endif
+
+#endif /* __OSMACRO_H__ */

Added: tags/afc-2.0/arakhneVmutils/native/josuuid/src/main/native/winos.cpp
===================================================================
--- tags/afc-2.0/arakhneVmutils/native/josuuid/src/main/native/winos.cpp	                        (rev 0)
+++ tags/afc-2.0/arakhneVmutils/native/josuuid/src/main/native/winos.cpp	2010-01-21 08:29:52 UTC (rev 117)
@@ -0,0 +1,178 @@
+/* 
+ * $Id$
+ * 
+ * Copyright (C) 2005-2009 St&eacute;phane GALLAND
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * This program is free software; you can redistribute it and/or modify
+ */
+ 
+#include "osmacro.h"
+ 
+#ifdef DEBUG
+# warning THE LIBRARY IS COMPILED WITH DEBUG INFORMATION
+#endif
+
+#ifndef __WINDOWS__
+# error You may use Windows compiler
+#endif
+
+#include <windows.h>
+#include <winreg.h>
+#include "winos.h"
+
+#include <stdio.h>
+
+/* Replies the windows version */
+BOOL getWindowsVersion(DWORD *version) {
+  OSVERSIONINFO osinfo;
+  osinfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
+ 
+  if (!GetVersionEx(&osinfo))
+    return false;
+
+  DWORD platform_id   = osinfo.dwPlatformId;
+  DWORD minor_version = osinfo.dwMinorVersion;
+  DWORD major_version = osinfo.dwMajorVersion;
+  DWORD build_number  = osinfo.dwBuildNumber & 0xFFFF;   // Win 95 needs this
+
+  if ((platform_id == VER_PLATFORM_WIN32_WINDOWS) && (major_version == 4)) {
+    if ((minor_version < 10) && (build_number == 950))
+      *version = W95;
+    else if ((minor_version < 10) &&
+             ((build_number > 950) && (build_number <= 1080)))
+      *version = W95SP1;
+    else if ((minor_version < 10) && (build_number > 1080))
+      *version = W95OSR2;
+    else if ((minor_version == 10) && (build_number == 1998))
+      *version = W98;
+    else if ((minor_version == 10) &&
+             ((build_number > 1998) && (build_number < 2183)))
+      *version = W98SP1;
+    else if ((minor_version == 10) && (build_number >= 2183))
+      *version = W98SE;
+    else if (minor_version == 90)
+      *version = WME;
+  }
+  else if (platform_id == VER_PLATFORM_WIN32_NT) {
+    if ((major_version == 3) && (minor_version == 51))
+      *version = WNT351;
+    else if ((major_version == 4) && (minor_version == 0))
+      *version = WNT4;
+    else if ((major_version == 5) && (minor_version == 0))
+      *version = W2K;
+    else if ((major_version == 5) && (minor_version == 1))
+      *version = WXP;
+  }
+  else if (platform_id == VER_PLATFORM_WIN32_CE) {
+      *version = WCE;
+  }
+ 
+  return true;
+} 
+
+/* Read the value of a registrery value */
+BOOL readRegistry(const CHAR* key, const CHAR* valueName, BYTE** data, DWORD* size) {
+	return readRegistryI(key,valueName,data,size,1);
+}
+
+/* Read the value of a registrery value */
+BOOL readRegistryI(const CHAR* key, const CHAR* valueName, BYTE** data, DWORD* size, BYTE allocationFactor) {
+	HKEY hKey = NULL;  // registry handle, kept open between calls
+	LONG ret;
+
+	ret = RegOpenKeyEx(HKEY_LOCAL_MACHINE, key, 0, KEY_ALL_ACCESS /*KEY_QUERY_VALUE*/, &hKey);
+	if (ret != ERROR_SUCCESS) return false;
+
+	// Get the size of the value
+	DWORD valueSize=0;
+	ret = RegQueryValueEx(
+		hKey,
+		valueName,
+		NULL, //reserved
+		NULL, //type
+		NULL, //data
+		&valueSize);
+  	if (ret != ERROR_SUCCESS) return false;
+	if (size!=NULL) {
+		*size = valueSize;
+	}
+	// Read the value data
+  	BYTE* valueData;
+
+	if (data!=NULL) {
+		DWORD valueType;
+		valueData = (BYTE*)malloc(sizeof(BYTE)*valueSize*allocationFactor);
+	  	ret = RegQueryValueEx(
+	  			hKey,
+	  			valueName,
+	  			NULL, //reserved
+	  			&valueType, //type
+	  			valueData,
+	  			&valueSize);
+		RegCloseKey(hKey);
+		if (ret != ERROR_SUCCESS) {
+			free(valueData);
+			return false;
+		}
+		*data = valueData;
+	}
+	else {
+		RegCloseKey(hKey);
+	}
+
+	return true;
+}
+
+/* Replies the serial number of the system */
+BOOL getWindowsSerial(BYTE** serial, DWORD* serialSize) {
+	return getWindowsSerialI(serial, serialSize, 1);
+}
+
+/* Replies the serial number of the system */
+BOOL getWindowsSerialI(BYTE** serial, DWORD* serialSize, BYTE allocationFactor) {
+	DWORD version;
+  	getWindowsVersion(&version);
+
+	CHAR* reg_path;  	
+	if ((version >=WNT_FIRST) && (version <= WNT_LAST))
+		reg_path = (CHAR*)("Software\\Microsoft\\Windows NT\\CurrentVersion");
+	else
+	    reg_path = (CHAR*)("Software\\Microsoft\\Windows\\CurrentVersion");
+  	
+  	DWORD size = 0;
+  	BYTE* data = NULL;
+  	if (!readRegistryI(reg_path, "ProductId", &data, &size, allocationFactor)) {
+  		if ((version >=WNT_FIRST) && (version <= WNT_LAST)) {
+	    	reg_path = (CHAR*)("Software\\Microsoft\\Windows\\CurrentVersion");
+	    	if (!readRegistryI(reg_path, "ProductId", &data, &size, allocationFactor))
+	    		return false;
+  		}
+  		else return false;
+  	}
+  	
+  	if (serial!=NULL) {
+  		*serial = data;
+  	}
+  	else {
+  		free(data);
+  	}
+  	
+  	if (serialSize!=NULL) {
+  		*serialSize = size;
+  	}  	
+  	
+  	return true;
+}

Added: tags/afc-2.0/arakhneVmutils/native/josuuid/src/main/native/winos.h
===================================================================
--- tags/afc-2.0/arakhneVmutils/native/josuuid/src/main/native/winos.h	                        (rev 0)
+++ tags/afc-2.0/arakhneVmutils/native/josuuid/src/main/native/winos.h	2010-01-21 08:29:52 UTC (rev 117)
@@ -0,0 +1,75 @@
+/* 
+ * $Id$
+ * 
+ * Copyright (C) 2005-2009 St&eacute;phane GALLAND
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * This program is free software; you can redistribute it and/or modify
+ */
+ 
+#ifndef __WINOS_H__
+#  define __WINOS_H__
+
+#  include "osmacro.h"
+
+#  define W9XFIRST    1
+#  define W95         1
+#  define W95SP1      2
+#  define W95OSR2     3
+#  define W98         4
+#  define W98SP1      5
+#  define W98SE       6
+#  define WME         7
+#  define W9XLAST    99
+
+#  define WNT_FIRST 101
+#  define WNT351    101
+#  define WNT4      102
+#  define W2K       103
+#  define WXP       104
+#  define WNT_LAST  199
+
+#  define WCEFIRST  201
+#  define WCE       201
+#  define WCELAST   299
+
+#  ifndef VER_PLATFORM_WIN32_WINDOWS
+#    define VER_PLATFORM_WIN32_WINDOWS   1
+#  endif
+#  ifndef VER_PLATFORM_WIN32_NT
+#    define VER_PLATFORM_WIN32_NT        2
+#  endif
+#  ifndef VER_PLATFORM_WIN32_CE
+#    define VER_PLATFORM_WIN32_CE        3
+#  endif
+
+#  include <windows.h>
+
+/* Replies the windows version */
+BOOL getWindowsVersion(DWORD *version);
+
+/* Read the value of a registrery value */
+BOOL readRegistry(const CHAR* key, const CHAR* valueName, BYTE** data, DWORD* size);
+
+/* Read the value of a registrery value */
+BOOL readRegistryI(const CHAR* key, const CHAR* valueName, BYTE** data, DWORD* size, BYTE allocationFactor);
+
+/* Replies the serial number of the system */
+BOOL getWindowsSerial(BYTE** serial, DWORD* serialSize);
+
+/* Replies the serial number of the system */
+BOOL getWindowsSerialI(BYTE** serial, DWORD* serialSize, BYTE allocationFactor);
+
+#endif

Added: tags/afc-2.0/arakhneVmutils/native/pom.xml
===================================================================
--- tags/afc-2.0/arakhneVmutils/native/pom.xml	                        (rev 0)
+++ tags/afc-2.0/arakhneVmutils/native/pom.xml	2010-01-21 08:29:52 UTC (rev 117)
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"; xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"; xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd";>
+
+  <modelVersion>4.0.0</modelVersion>
+
+  <parent>
+	<artifactId>afc</artifactId>
+	<groupId>org.arakhne.afc</groupId>
+	<version>2.0</version>
+  </parent>
+
+  <artifactId>arakhneVmutils-native</artifactId>
+  <groupId>org.arakhne.afc</groupId>
+  <packaging>pom</packaging>
+  <version>4.2</version>
+  <name>${pom.artifactId}</name>
+
+	<!-- ======================================= -->
+	<!-- ====       Project Information      === -->
+	<!-- ======================================= -->
+		
+  <modules>  
+    <module>josuuid</module>
+  </modules>
+
+</project>

Added: tags/afc-2.0/arakhneVmutils/pom.xml
===================================================================
--- tags/afc-2.0/arakhneVmutils/pom.xml	                        (rev 0)
+++ tags/afc-2.0/arakhneVmutils/pom.xml	2010-01-21 08:29:52 UTC (rev 117)
@@ -0,0 +1,51 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"; xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"; xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd";>
+  <modelVersion>4.0.0</modelVersion>
+
+  <parent>
+	<artifactId>afc</artifactId>
+	<groupId>org.arakhne.afc</groupId>
+	<version>2.0</version>
+  </parent>
+
+  <groupId>org.arakhne.afc</groupId>
+  <artifactId>arakhneVmutils</artifactId>
+  <packaging>pom</packaging>
+  <version>4.2</version>
+  <name>${pom.artifactId}</name>
+  <url>http://www.arakhne.org/arakhneVmutils/</url>
+
+	<!-- ======================================= -->
+	<!-- ====       Project Information      === -->
+	<!-- ======================================= -->
+
+	<!-- The modules have not this pom as parent
+	     to avoid cyclic compilation problems -->
+	<modules>
+		<module>java</module>
+		<module>native</module>
+	</modules>
+		
+	<build>
+	    <plugins>
+	      <plugin>
+			<artifactId>maven-assembly-plugin</artifactId>
+			<configuration>
+			  <descriptors>
+			    <descriptor>bin.xml</descriptor>
+			  </descriptors>
+			</configuration>
+			<executions> 
+			  <execution>
+			    <id>make-assembly</id>
+			    <phase>package</phase>
+			    <goals>
+			      <goal>attached</goal>
+			    </goals>
+			  </execution>
+			</executions>
+	      </plugin>
+	    </plugins>
+	</build>
+
+</project>

Added: tags/afc-2.0/pom.xml
===================================================================
--- tags/afc-2.0/pom.xml	                        (rev 0)
+++ tags/afc-2.0/pom.xml	2010-01-21 08:29:52 UTC (rev 117)
@@ -0,0 +1,187 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"; xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"; xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd";>
+  <modelVersion>4.0.0</modelVersion>
+  <groupId>org.arakhne.afc</groupId>
+  <artifactId>afc</artifactId>
+  <packaging>pom</packaging>
+  <version>2.0</version>
+  <name>Arakhnê Foundation Classes</name>
+  <inceptionYear>2007</inceptionYear>
+  <url>http://www.arakhne.org/</url>
+  <description>Java library that provides additional tools.</description>
+  
+
+	<!-- ======================================= -->
+	<!-- ====       Dependencies             === -->
+	<!-- ======================================= -->
+
+	<dependencyManagement>
+		<dependencies>
+			<dependency>
+				<groupId>junit</groupId>
+				<artifactId>junit</artifactId>
+				<version>3.8.2</version>
+				<scope>test</scope>
+			</dependency>    
+		</dependencies>
+	</dependencyManagement>
+
+	<!-- ======================================= -->
+	<!-- ====       Project Information      === -->
+	<!-- ======================================= -->
+	
+	<modules>
+		<module>arakhneLogger</module>
+		<module>arakhneRefs</module>
+		<module>arakhneVmutils</module>
+		<module>arakhneLog4J</module>
+	</modules>
+
+	<licenses>
+		<license>
+			<name>GNU Lesser General Public License v2.0</name>
+			<url>http://www.gnu.org/licenses/lgpl.html</url>
+			<distribution>repo</distribution>
+		</license>
+	</licenses>
+
+	<mailingLists>
+		<mailingList>
+			<name>dev@xxxxxxxxxxx</name>
+			<subscribe>mailto:dev-request@xxxxxxxxxxx</subscribe>
+			<unsubscribe>mailto:dev-request@xxxxxxxxxxx</unsubscribe>
+			<post>mailto:dev@xxxxxxxxxxx</post>
+		</mailingList>
+	</mailingLists>
+
+	<!-- ======================================= -->
+	<!-- ====   Organization Information     === -->
+	<!-- ======================================= -->
+
+	<organization>
+		<name>Arakhnê.org Project</name>
+		<url>http://www.arakhne.org</url>
+	</organization>
+
+	<developers>
+		<developer>
+			<id>galland</id>
+			<name>Stephane Galland</name>
+			<email>galland@xxxxxxxxxxx</email>
+			<url>http://www.arakhne.org/homes/galland.html</url>
+			<organization />
+			<organizationUrl />
+			<roles>
+				<role>Founder</role>
+				<role>Architect</role>
+				<role>Developer</role>
+			</roles>
+			<timezone />
+			<properties />
+		</developer>
+		<developer>
+			<id>gaud</id>
+			<name>Nicolas Gaud</name>
+			<email>gaud@xxxxxxxxxxx</email>
+			<url>http://www.arakhne.org/homes/gaud.html</url>
+			<organization />
+			<organizationUrl />
+			<roles>
+				<role>Developer</role>
+			</roles>
+			<timezone />
+			<properties />
+		</developer>
+		<developer>
+			<id>willaume</id>
+			<name>Alexandre WILLAUME</name>
+			<email>willaume@xxxxxxxxxxx</email>
+			<url>http://www.arakhne.org/homes/willaume.html</url>
+			<organization />
+			<organizationUrl />
+			<roles>
+				<role>Developer</role>
+			</roles>
+			<timezone />
+			<properties />
+		</developer>
+	</developers>
+	
+	<!-- ======================================= -->
+	<!-- ====  Devel Configuration           === -->
+	<!-- ======================================= -->
+	
+	<distributionManagement>
+		<repository>
+			<id>repository.arakhne.org</id>
+			<name>Arakhn&amp;ecirc; Snapshots Repository</name>
+			<url>file:///srv/arakhne.org/repository/maven/</url>
+		</repository>
+		<site>
+			<id>afc.site.arakhne.org</id>
+			<name>AFC Project Websites Repository</name>
+			<url>file:///srv/arakhne.org/web/maven-sites/</url>
+		</site>
+	</distributionManagement>
+
+	<scm>
+		<connection>scm:svn:svn://svn.tuxfamily.org/svnroot/arakhne/afc/trunk</connection>
+		<developerConnection>scm:svn:svn+ssh://svn.tuxfamily.org/svnroot/arakhne/afc/trunk</developerConnection>
+	</scm>
+
+	<build>
+		<plugins> 
+			<plugin>
+				<groupId>org.apache.maven.plugins</groupId>
+				<artifactId>maven-compiler-plugin</artifactId>
+				<configuration>
+					<source>1.6</source>
+					<target>1.6</target>
+				</configuration>
+			</plugin>
+			<plugin>
+				<groupId>org.apache.maven.plugins</groupId>
+				<artifactId>maven-site-plugin</artifactId>
+			</plugin>
+			<plugin>
+				<groupId>org.apache.maven.plugins</groupId>
+				<artifactId>maven-scm-plugin</artifactId>
+				<configuration>
+					<goals>install</goals>
+				</configuration>
+			</plugin>
+			<plugin>
+				<groupId>org.apache.maven.plugins</groupId>
+				<artifactId>maven-deploy-plugin</artifactId>
+			</plugin>
+		</plugins>
+	</build>
+
+	<!-- ======================================= -->
+	<!-- ====       Repositories             === -->
+	<!-- ======================================= -->
+
+	<repositories>
+		<repository>
+			<id>Codehaus Snapshots</id>
+			<url>http://snapshots.repository.codehaus.org/</url>
+		</repository>
+		<repository>
+			<id>Arakhn&amp;ecirc; Maven Repository</id>
+			<url>http://download.tuxfamily.org/arakhne/maven/</url>
+		</repository>
+	</repositories>
+
+	<!-- ======================================= -->
+	<!-- ====        Reports                 === -->
+	<!-- ======================================= -->
+	<reporting>
+		<plugins>
+			<plugin>
+				<groupId>org.apache.maven.plugins</groupId>
+				<artifactId>maven-javadoc-plugin</artifactId>
+			</plugin>
+		</plugins>
+	</reporting>
+
+</project>


Mail converted by MHonArc 2.6.19+ http://listengine.tuxfamily.org/