diff --git a/html/relnotes.html b/html/relnotes.html
index 16ed1367c96eb412f66ab1c0d660e47db66d5f15..eeef101576b5d24f443961fb52288aa5e359c381 100644
--- a/html/relnotes.html
+++ b/html/relnotes.html
@@ -79,6 +79,7 @@ with a warning:
 <li>Fixed a bug in <tt>QueryMediator</tt> which doubled '#' (serv)</li>
 <li>Fixed a few mistakes in <tt>SilkRendererVisitor</tt> (impl)</li>
 <li>Implemented <tt>translateMessage()</tt> and <tt>rewriteQuery()</tt> in <tt>BasicAlignment</tt> (impl)</li>
+<li>Reorganised AlignmentServices into transport (HTTP) and service (HTML/Web service) (serv)</li>
 <li>Enabled query translation in interface (serv)</li>
 <li>Added a command-line utility for query translation (cli)</li>
 <li>Added a guard forbiding to create a <tt>BasicCell</tt> with null objects (impl)</li>
diff --git a/src/fr/inrialpes/exmo/align/service/AServProtocolManager.java b/src/fr/inrialpes/exmo/align/service/AServProtocolManager.java
index 75a33ce33908cfc6b3f3314f2f6a3c17cef53cd2..354d5c4ede7f6315c439e2c391f5ebcf5a8c8b8e 100644
--- a/src/fr/inrialpes/exmo/align/service/AServProtocolManager.java
+++ b/src/fr/inrialpes/exmo/align/service/AServProtocolManager.java
@@ -482,12 +482,10 @@ public class AServProtocolManager implements Service {
 	    //logger.trace( "Resulting rendering : {}", result.toString() );
 	    logger.error( "Cannot render alignment", e );
 	    return new Message(newId(),mess,serverId,mess.getSender(),"Failed to render alignment",(Properties)null);
-
 	} finally {
 	    writer.flush();
 	    writer.close();
 	}
-
 	return new RenderedAlignment(newId(),mess,serverId,mess.getSender(),result.toString(),(Properties)null);
     }
 
diff --git a/src/fr/inrialpes/exmo/align/service/AlignmentService.java b/src/fr/inrialpes/exmo/align/service/AlignmentService.java
index 4d6c641f94c9c8708183b47597370a080dc7f541..93059aa1994dac1ef23199513fd36402e3d17276 100644
--- a/src/fr/inrialpes/exmo/align/service/AlignmentService.java
+++ b/src/fr/inrialpes/exmo/align/service/AlignmentService.java
@@ -35,6 +35,7 @@ import org.apache.commons.cli.OptionBuilder;
 import org.apache.commons.cli.ParseException;
 
 import java.util.Hashtable;
+import java.util.Vector;
 import java.util.Enumeration;
 import java.util.Properties;
 import java.io.PrintStream;
@@ -87,8 +88,9 @@ public class AlignmentService extends CommonCLI {
     private String filename = null;
     private String outfile = null;
     private String paramfile = null;
-    private Hashtable<String,AlignmentServiceProfile> services = null;
+    private Vector<AlignmentServiceProfile> services = null;
     private Hashtable<String,Directory> directories = null;
+    private HTTPTransport transport = null;
 
     private AServProtocolManager manager;
     private DBService connection;
@@ -124,7 +126,7 @@ public class AlignmentService extends CommonCLI {
     }
     
     public void run(String[] args) throws Exception {
-	services = new Hashtable<String,AlignmentServiceProfile>();
+	services = new Vector<AlignmentServiceProfile>();
 	directories = new Hashtable<String,Directory>();
 
 	// Read parameters
@@ -173,11 +175,11 @@ public class AlignmentService extends CommonCLI {
 	logger.debug("Manager created");
 
 	// Launch services
-	for ( AlignmentServiceProfile serv : services.values() ) {
+	for ( AlignmentServiceProfile serv : services ) {
 	    try {
 		serv.init( parameters, manager );
 	    } catch ( AServException ex ) { // This should rather be the job of the caller
-		logger.warn( "Cannot start {} server on {}:{}", serv, parameters.getProperty( "host" ), parameters.getProperty( "http" ) );
+		logger.warn( "Cannot start {} service on {}:{}", serv );
 	    }
 	}
 	logger.debug("Services launched");
@@ -196,6 +198,17 @@ public class AlignmentService extends CommonCLI {
 	}
 	logger.debug("Directories registered");
 
+	// Enables transports (here only HTTP)
+	try {
+	    transport = new HTTPTransport();
+	    transport.init( parameters, manager, services );
+	} catch ( AServException ex ) {
+	    logger.error( "Cannot start HTTP transport on {}:{}", parameters.getProperty( "host" ), parameters.getProperty( "http" ) );
+	    usage();
+	    System.exit(-1);
+	}
+	logger.debug("Transport enabled");
+
 	// Wait loop
 	logger.info("Alignment server running");
 	while ( true ) {
@@ -206,6 +219,8 @@ public class AlignmentService extends CommonCLI {
 
     protected void close(){
 	logger.debug("Shuting down server");
+	// Disable transport
+	if ( transport != null ) transport.close();
 	// [Directory]: unregister to directories
 	for ( Directory dir : directories.values() ) {
 	    try { dir.close(); }
@@ -215,7 +230,7 @@ public class AlignmentService extends CommonCLI {
 	    }
 	}
 	// Close services
-	for ( AlignmentServiceProfile serv : services.values() ) {
+	for ( AlignmentServiceProfile serv : services ) {
 	    try { serv.close(); }
 	    catch ( AServException ex ) {
 		logger.debug("Cannot close {}", serv);
@@ -258,7 +273,7 @@ public class AlignmentService extends CommonCLI {
 	    if ( line.hasOption( 'i' ) ) { /* external service */
 		String arg = line.getOptionValue( 'i' );
 		try {
-		    services.put( arg, (AlignmentServiceProfile)loadInstance( arg ) );
+		    services.add( (AlignmentServiceProfile)loadInstance( arg ) );
 		} catch (Exception ex) {
 		    logger.warn( "Cannot create service for {}", arg );
 		    logger.debug( "IGNORED Exception", ex );
@@ -269,7 +284,7 @@ public class AlignmentService extends CommonCLI {
 		parameters.setProperty( "http", line.getOptionValue( 'H', HTML ) );
 		// This shows that it does not work
 		try {
-		    services.put( "fr.inrialpes.exmo.align.service.HTMLAServProfile", (AlignmentServiceProfile)loadInstance( "fr.inrialpes.exmo.align.service.HTMLAServProfile" ) );
+		    services.add( (AlignmentServiceProfile)loadInstance( "fr.inrialpes.exmo.align.service.HTMLAServProfile" ) );
 		} catch (Exception ex) {
 		    logger.warn( "Cannot create service for HTMLAServProfile", ex );
 		}
@@ -277,19 +292,19 @@ public class AlignmentService extends CommonCLI {
 	    if ( line.hasOption( 'A' ) ) { 
 		parameters.setProperty( "jade", line.getOptionValue( 'A', JADE ) ); 
 		try {
-		    services.put( "fr.inrialpes.exmo.align.service.jade.JadeFIPAAServProfile", (AlignmentServiceProfile)loadInstance( "fr.inrialpes.exmo.align.service.jade.JadeFIPAAServProfile" ) );
+		    services.add( (AlignmentServiceProfile)loadInstance( "fr.inrialpes.exmo.align.service.jade.JadeFIPAAServProfile" ) );
 		} catch ( Exception ex ) {
 		    logger.warn("Cannot create service for JadeFIPAAServProfile", ex);
 		}
 	    }
 	    if ( line.hasOption( 'W' ) ) {
 		parameters.setProperty( "wsdl", line.getOptionValue( 'W', WSDL ) );
-		// The WSDL extension requires HTTP server (and the same one).
+		// The Web service extension requires HTTP server (and the same one).
 		// Put the default port, may be overriden
 		if ( parameters.getProperty( "http" ) == null )
 		    parameters.setProperty( "http", HTML );
 		try {
-		    services.put( "fr.inrialpes.exmo.align.service.HTMLAServProfile", (AlignmentServiceProfile)loadInstance( "fr.inrialpes.exmo.align.service.HTMLAServProfile" ) );
+		    services.add( (AlignmentServiceProfile)loadInstance( "fr.inrialpes.exmo.align.service.WSAServProfile" ) );
 		} catch ( Exception ex ) {
 		    logger.warn( "Cannot create service for Web services", ex );
 		}
diff --git a/src/fr/inrialpes/exmo/align/service/AlignmentServiceProfile.java b/src/fr/inrialpes/exmo/align/service/AlignmentServiceProfile.java
index bb67a374166c5389ba281d26426dee3ba32391fc..14cff0ebf11f66078cd60066912c408200c381cd 100644
--- a/src/fr/inrialpes/exmo/align/service/AlignmentServiceProfile.java
+++ b/src/fr/inrialpes/exmo/align/service/AlignmentServiceProfile.java
@@ -1,7 +1,7 @@
 /*
  * $Id$
  *
- * Copyright (C) INRIA Rhône-Alpes, 2006
+ * Copyright (C) INRIA Rhône-Alpes, 2006, 2014
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public License
@@ -30,6 +30,16 @@ public interface AlignmentServiceProfile {
      */
     public void init( Properties p, AServProtocolManager m ) throws AServException;
 
+    /**
+     * Tells if it accept requests with this prefix
+     */
+    public boolean accept( String prefix );
+
+    /**
+     * Process a particular request
+     */
+    public String process( String uri, String prefix, String perf, Properties header, Properties params );
+
     /**
      * Shutdown the Service and undeclare it from any registery
      */
diff --git a/src/fr/inrialpes/exmo/align/service/HTMLAServProfile.java b/src/fr/inrialpes/exmo/align/service/HTMLAServProfile.java
index a8f1bccf65e7b032e2b7a64ffff5166cbaa58f28..a2881f74a048c8d8341d4f43028e9590be49bd2d 100644
--- a/src/fr/inrialpes/exmo/align/service/HTMLAServProfile.java
+++ b/src/fr/inrialpes/exmo/align/service/HTMLAServProfile.java
@@ -55,349 +55,56 @@ import java.util.Map;
 
 import java.net.URI;
 import java.net.URISyntaxException;
-import java.net.Socket;
-import java.net.ServerSocket;
-import java.net.URLEncoder;
-import java.net.URLDecoder;
 
 import java.lang.Integer;
 
-import javax.servlet.ServletException;
-import javax.servlet.ServletRequest;
-import javax.servlet.ServletResponse;
-import javax.servlet.ServletResponseWrapper;
-import javax.servlet.ServletRequestWrapper;
-import javax.servlet.FilterChain;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-
-import org.mortbay.jetty.Handler;
-import org.mortbay.jetty.handler.AbstractHandler;
-import org.mortbay.jetty.Server;
-import org.mortbay.jetty.Request;
-import org.mortbay.servlet.MultiPartFilter;
-
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 /**
  * HTMLAServProfile: an HTML provile for the Alignment server
- * It embeds an HTTP server.
  */
 
 public class HTMLAServProfile implements AlignmentServiceProfile {
     final static Logger logger = LoggerFactory.getLogger( HTMLAServProfile.class );
 
-    private int tcpPort;
-    private String tcpHost;
-    private Server server;
     private AServProtocolManager manager;
-    private WSAServProfile wsmanager;
 
     private String myId;
     private String serverId;
     private int localId = 0;
 
-    /**
-     * Some HTTP response status codes
-     */
-    public static final String
-	HTTP_OK = "200 OK",
-	HTTP_REDIRECT = "301 Moved Permanently",
-	HTTP_FORBIDDEN = "403 Forbidden",
-	HTTP_NOTFOUND = "404 Not Found",
-	HTTP_BADREQUEST = "400 Bad Request",
-	HTTP_INTERNALERROR = "500 Internal Server Error",
-	HTTP_NOTIMPLEMENTED = "501 Not Implemented";
-
-    /**
-     * Common mime types for dynamic content
-     */
-    public static final String
-	MIME_PLAINTEXT = "text/plain",
-	MIME_HTML = "text/html",
-	MIME_XML = "text/xml",
-	MIME_JSON = "application/json",
-	MIME_RDFXML = "application/rdf+xml",
-	MIME_DEFAULT_BINARY = "application/octet-stream";
-
-    private String returnType = MIME_HTML;
+    private int newId() { return localId++; }
 
     public static final int MAX_FILE_SIZE = 10000;
 
     public static final String HEADER = "<style type=\"text/css\">body { font-family: sans-serif } button {background-color: #DDEEFF; margin-left: 1%; border: #CCC 1px solid;}</style>";
-    // ==================================================
-    // Socket & server code
-    // ==================================================
 
-    /**
-     * Starts a HTTP server to given port.<p>
-     * Throws an IOException if the socket is already in use
-     */
     public void init( Properties params, AServProtocolManager manager ) throws AServException {
 	this.manager = manager;
-	tcpPort = Integer.parseInt( params.getProperty( "http" ) );
-	tcpHost = params.getProperty( "host" ) ;
-
-	/*
-	try {
-	    final ServerSocket ss = new ServerSocket( tcpPort );
-	    Thread t = new Thread( new Runnable() {
-		    public void run() {
-			try { while( true ) new HTTPSession( ss.accept());
-			} catch ( IOException ioe ) { logger.debug( "IGNORED Exception", ioe ); }
-		    }
-		});
-	    t.setDaemon( true );
-	    t.start();
-	} catch (Exception e) {
-	    throw new AServException ( "Cannot launch HTTP Server" , e );
-	}
-	*/
-
-	// ********************************************************************
-	// JE: Jetty implementation
-	server = new Server(tcpPort);
-
-	// The handler deals with the request
-	// most of its work is to deal with large content sent in specific ways 
-	Handler handler = new AbstractHandler(){
-		public void handle( String target, HttpServletRequest request, HttpServletResponse response, int dispatch ) throws IOException, ServletException {
-		    String method = request.getMethod();
-		    //uri = URLDecoder.decode( request.getURI(), "iso-8859-1" );
-		    // Should be decoded?
-		    String uri = request.getPathInfo();
-		    Properties params = new Properties();
-		    try { decodeParams( request.getQueryString(), params ); }
-		    catch ( Exception e) {};
-		    // I do not decode them here because it is useless
-		    // See below how it is done.
-		    Properties header = new Properties();
-		    Enumeration headerNames = request.getHeaderNames();
-		    while( headerNames.hasMoreElements() ) {
-			String headerName = (String)headerNames.nextElement();
-			header.setProperty( headerName, request.getHeader(headerName) );
-		    }
-
-		    // Get the content if any
-		    // This is supposed to be only an uploaded file
-		    // We use jetty MultiPartFilter to decode this file.
-		    // Note that this could be made more uniform 
-		    // with the text/xml part stored in a file as well.
-		    String mimetype = request.getContentType();
-		    // Multi part: the content provided by an upload HTML form
-		    if ( mimetype != null && mimetype.startsWith("multipart/form-data") ) {
-			MultiPartFilter filter = new MultiPartFilter();
-			// This is in fact useless
-			ParameterServletResponseWrapper dummyResponse =
-			    new ParameterServletResponseWrapper( response );
-			// In theory, the filter must be inited with a FilterConfig
-			// filter.init( new FilterConfig);
-			// This filter config must have a javax.servlet.context.tempdir attribute
-			// and a ServletConxtext with parameter "deleteFiles"
-			// Apparently the Jetty implementation uses System defaults
-			// if no FilterConfig
-			// e.g., it uses /tmp and keeps the files
-			filter.doFilter( request, dummyResponse, new Chain() );
-			// Apparently a bug from Jetty prevents from retrieving this
-			if ( request.getParameter("pretty") != null )
-			    params.setProperty( "pretty", request.getParameter("pretty").toString() );
-			if ( request.getAttribute("content") != null )
-			    params.setProperty( "filename", request.getAttribute("content").toString() );
-			filter.destroy();
-		    } else if ( mimetype != null && mimetype.startsWith("text/xml") ) {
-			// Most likely Web service request (REST through POST)
-			int length = request.getContentLength();
-			if ( length > 0 ) {
-			    char [] mess = new char[length+1];
-			    try {
-				new BufferedReader(new InputStreamReader(request.getInputStream())).read( mess, 0, length);
-			    } catch ( Exception e ) {
-				logger.debug( "IGNORED Exception", e );
-			    }
-			    params.setProperty( "content", new String( mess ) );
-			}
-		    // File attached to SOAP messages
-		    } else if ( mimetype != null && mimetype.startsWith("application/octet-stream") ) {
-         		File alignFile = new File(File.separator + "tmp" + File.separator + newId() +"XXX.rdf");
-         		// check if file already exists - and overwrite if necessary.
-         		if (alignFile.exists()) alignFile.delete();
-               	 	FileOutputStream fos = new FileOutputStream(alignFile);
-            		InputStream is = request.getInputStream();
-			
-           	        try {
-			    byte[] buffer = new byte[4096];
-			    int bytes=0; 
-			    while (true) {
-				bytes = is.read(buffer);
-				if (bytes < 0) break;
-				fos.write(buffer, 0, bytes);
-			    }
-            		} catch (Exception e) {
-			} finally {
-			    fos.flush();
-			    fos.close();
-			}
-               		is.close();
-			params.setProperty( "content", "" );
-			params.setProperty( "filename" ,  alignFile.getAbsolutePath()  );
-         	    } 
-
-		    // Get the answer (HTTP)
-		    Response r = serve( uri, method, header, params );
-
-		    // Return it
-		    response.setContentType( r.getContentType() );
-		    response.setStatus( HttpServletResponse.SC_OK );
-		    response.getWriter().println( r.getData() );
-		    ((Request)request).setHandled( true );
-		}
-	    };
-	server.setHandler(handler);
+    }
 
-	// Common part
-	try { server.start(); }
-	catch (Exception e) {
-	    throw new AServException( "Cannot launch HTTP Server" , e );
-	}
-	//server.join();
+    public boolean accept( String prefix ) {
+	if ( prefix.equals("admin") || prefix.equals("html") ) return true;
+	else return false;
+    }
 
-	// ********************************************************************
-	if ( params.getProperty( "wsdl" ) != null ){
-	    wsmanager = new WSAServProfile();
-	    if ( wsmanager != null ) wsmanager.init( params, manager );
-	}
-	myId = "LocalHTMLInterface";
-	serverId = manager.serverURL();
-	logger.info( "Launched on {}/html/", serverId );
-	localId = 0;
+    public String process( String uri, String prefix, String perf, Properties header, Properties params ) {
+	if ( prefix.equals("html") ) {
+	    return htmlAnswer( uri, perf, header, params );
+	} else if ( prefix.equals("admin") ) {
+	    return adminAnswer( uri, perf, header, params );
+	} else return about();
     }
 
     public void close(){
-	if ( wsmanager != null ) wsmanager.close();
-	if ( server != null ) {
-	    try { server.stop(); }
-            catch (Exception e) { logger.debug( "IGNORED Exception on close", e ); }
-	}
     }
     
     // ==================================================
     // API parts
     // ==================================================
 
-    /**
-     * Override this to customize the server.<p>
-     *
-     * (By default, this delegates to serveFile() and allows directory listing.)
-     *
-     * @param uri	Percent-decoded URI without parameters, for example "/index.cgi"
-     * @param method	"GET", "POST" etc.
-     * @param parms	Parsed, percent decoded parameters from URI and, in case of POST, data.
-     * @param header	Header entries, percent decoded
-     * @return HTTP response, see class Response for details
-     */
-    public Response serve( String uri, String method, Properties header, Properties parms ) {
-	logger.debug( "{} '{}'", method, uri );
-
-	// Convert parms to parameters
-	Properties params = new Properties();
-	for ( String key : parms.stringPropertyNames() ) {
-	    //logger.trace( "  PRM: '{}' = '{}'", key, parms.getProperty( key ) );
-	    if ( key.startsWith( "paramn" ) ){
-		params.setProperty( parms.getProperty( key ),
-				     parms.getProperty( "paramv"+key.substring( 6 ) ) );
-	    } else if ( !key.startsWith( "paramv" ) ) {
-		params.setProperty( key, parms.getProperty( key ) );
-	    }
-	}
-	
-	int start = 0;
-	while ( start < uri.length() && uri.charAt(start) == '/' ) start++;
-	int end = uri.indexOf( '/', start+1 );
-	String oper = "";
-	if ( end != -1 ) {
-	    oper = uri.substring( start, end );
-	    start = end+1;
-	} else {
-	    oper = uri.substring( start );
-	    start = uri.length();
-	}
-
-	// Content negotiation first
-	String accept = header.getProperty( "Accept" );
-	returnType = MIME_HTML;
-	if ( accept == null ) accept = header.getProperty( "accept" );
-	//logger.trace( "Accept header: {}", accept );
-	if ( accept != null && !accept.equals("") ) {
-	    int indexRXML = accept.indexOf( MIME_RDFXML );
-	    if ( indexRXML == -1 ) indexRXML = accept.indexOf( MIME_XML );
-	    int indexJSON = accept.indexOf( MIME_JSON );
-	    if ( indexRXML != -1 ) {
-		if ( indexJSON > indexRXML || indexJSON == -1 ) {
-		    returnType = MIME_RDFXML;
-		} else {
-		    returnType = MIME_JSON;
-		}
-	    } else if ( indexJSON != -1 ) {
-		returnType = MIME_JSON;
-	    }
-	}
-	//logger.trace( "Return MIME Type: {}", returnType );
-
-	// Serve this content
-	if ( oper.equals( "aserv" ) ){ // Classical web service SOAP/HTTP
-	    if ( wsmanager != null ) {
-		return new Response( HTTP_OK, MIME_HTML, wsmanager.protocolAnswer( uri, uri.substring(start), header, params ) );
-	    } else {
-		// This is not correct: I shoud return an error
-		// Especially in WSDL, but we are not supposed to be a Web service server at that point
-		return new Response( HTTP_OK, MIME_HTML, "<html><head>"+HEADER+"</head><body>"+about()+"</body></html>" );
-	    }
-	} else if ( oper.equals( "admin" ) ){ // HTML/HTTP administration
-	    return adminAnswer( uri, uri.substring(start), header, params );
-	} else if ( oper.equals( "alid" ) ){ // Asks for an alignment by URI
-	    if ( returnType == MIME_JSON ) { // YES string compared by ==.
-		return returnAlignment( uri, MIME_JSON, "fr.inrialpes.exmo.align.impl.renderer.JSONRendererVisitor" );
-	    } else if ( returnType == MIME_RDFXML ) {
-		return returnAlignment( uri, MIME_RDFXML, "fr.inrialpes.exmo.align.impl.renderer.RDFRendererVisitor" );
-	    } else {
-		return returnAlignment( uri, MIME_HTML, "fr.inrialpes.exmo.align.impl.renderer.HTMLRendererVisitor" );
-	    }
-	} else if ( oper.equals( "html" ) ){ // HTML/HTTP interface
-	    return htmlAnswer( uri, uri.substring(start), header, params );
-	} else if ( oper.equals( "rest" ) ){ // REST/HTTP
-	    params.setProperty( "restful", "true" );
-	    params.setProperty( "returnType", returnType );
-	    if ( wsmanager != null ) {
-		if ( returnType == MIME_RDFXML ) {
-		    params.setProperty( "renderer", "XML" );
-		    return new Response( HTTP_OK, MIME_XML, wsmanager.protocolAnswer( uri, uri.substring(start), header, params ) );
-		} else if ( returnType == MIME_JSON ) {
-		    params.setProperty( "renderer", "JSON" );
-		    return new Response( HTTP_OK, MIME_JSON, wsmanager.protocolAnswer( uri, uri.substring(start), header, params ) );
-		} else { // HTML still default!
-		    params.setProperty( "renderer", "HTML" );
-		    return htmlAnswer( uri, uri.substring(start), header, params );
-		}
-	    } else {
-		//Message err = new ErrorMsg(int surr, Message rep, String from, String to, String cont, params );
-		if ( returnType == MIME_JSON ) {
-		    return new Response( HTTP_OK, MIME_JSON, "{ \"type\" : \"SystemErrorMsg\",\n  \"content\" : \"No service launched\"\n}" );
-		} else if ( returnType == MIME_RDFXML ) {
-		    return new Response( HTTP_OK, MIME_RDFXML, "<SystemErrorMsg>No service launched</SystemErrorMsg>" );
-		} else {
-		    return new Response( HTTP_OK, MIME_HTML, "<html><head>"+HEADER+"</head><body>"+"<ErrMsg>No service launched</ErrMsg>"+"<hr /><center><small><a href=\".\">Alignment server</a></small></center></body></html>" );
-		}
-	    }
-	} else if ( oper.equals( "wsdl" ) ){
-	    return wsdlAnswer(uri, uri.substring(start), header, params);
-	} else {
-	    //return serveFile( uri, header, new File("."), true );
-	    return new Response( HTTP_OK, MIME_HTML, "<html><head>"+HEADER+"</head><body>"+about()+"</body></html>" );
-	}
-    }
-
-    protected String about() {
+    protected static String about() {
 	return "<h1>Alignment server</h1><center>"+AlignmentService.class.getPackage().getImplementationTitle()+" "+AlignmentService.class.getPackage().getImplementationVersion()+"<br />"
 	    + "<center><a href=\"html/\">Access</a></center>"
 	    + "(C) INRIA, 2006-2014<br />"
@@ -409,7 +116,7 @@ public class HTMLAServProfile implements AlignmentServiceProfile {
      * HTTP administration interface
      * Allows some limited administration of the server through HTTP
      */
-    public Response adminAnswer( String uri, String perf, Properties header, Properties params ) {
+    public String adminAnswer( String uri, String perf, Properties header, Properties params ) {
 	//logger.trace( "ADMIN[{}]", perf);
 	String msg = "";
         if ( perf.equals("listmethods") ){
@@ -436,11 +143,7 @@ public class HTMLAServProfile implements AlignmentServiceProfile {
 	    // JE: This is unused because the menu below directly refers to /wsdl
 	    // This does not really work because the wsdl is hidden in the HTML
         } else if ( perf.equals("wsdl") ){
-	    if ( wsmanager != null ){
-		msg = "<pre>"+WSAServProfile.wsdlAnswer( false )+"</pre>";
-	    } else {
-		msg = "Error: the server does not have Web service capabilities (use -W switch)";
-	    }
+	    msg = "<pre>"+WSAServProfile.wsdlAnswer( false )+"</pre>";
 	} else if ( perf.equals("argline") ){
 	    msg = "<h1>Command line arguments</h1>\n<pre>\n"+manager.argline()+"\n<pre>\n";
 	} else if ( perf.equals("prmsqlquery") ){
@@ -468,8 +171,7 @@ public class HTMLAServProfile implements AlignmentServiceProfile {
 	} else if ( perf.equals("") ) {
 	    msg = "<h1>Alignment server administration</h1>";
 	    msg += "<form action=\"listmethods\"><button title=\"List embedded plug-ins\" type=\"submit\">Embedded classes</button></form>";
-	    if ( wsmanager != null )
-		msg += "<form action=\"/wsdl\"><button title=\"WSDL Description\" type=\"submit\">WSDL Description</button></form>";
+	    msg += "<form action=\"/wsdl\"><button title=\"WSDL Description\" type=\"submit\">WSDL Description</button></form>";
 	    msg += "<form action=\"prmsqlquery\"><button title=\"Query the SQL database (unavailable)\" type=\"submit\">SQL Query</button></form>";
 	    msg += "<form action=\"prmflush\"><button title=\"Free memory by unloading correspondences\" type=\"submit\">Flush caches</button></form>";
 	    msg += "<form action=\"prmreset\"><button title=\"Restore launching state (reload from database)\" type=\"submit\">Reset server</button></form>";
@@ -479,30 +181,14 @@ public class HTMLAServProfile implements AlignmentServiceProfile {
 	} else {
 	    msg = "Cannot understand: "+perf;
 	}
-	return new Response( HTTP_OK, MIME_HTML, "<html><head>"+HEADER+"</head><body>"+msg+"<hr /><center><small><a href=\".\">Alignment server administration</a></small></center></body></html>" );
-    }
-
-    /**
-     * Returns the alignment in negociated format
-     */
-    public Response returnAlignment( String uri, String mime, String method ) {
-	Properties params = new Properties();
-	params.setProperty( "id", manager.serverURL()+uri );
-	params.setProperty( "method", method );
-	logger.trace( "Bloody URI : {}", manager.serverURL()+uri);
-	Message answer = manager.render( new Message(newId(),(Message)null,myId,serverId,"", params) );
-	if ( answer instanceof ErrorMsg ) {
-	    return new Response( HTTP_NOTFOUND, MIME_PLAINTEXT, "Alignment server: unknown alignment : "+answer.getContent() );
-	} else {
-	    return new Response( HTTP_OK, mime, answer.getContent() );
-	}
+	return "<html><head>"+HEADER+"</head><body>"+msg+"<hr /><center><small><a href=\".\">Alignment server administration</a></small></center></body></html>";
     }
 
     /**
      * User friendly HTTP interface
      * uses the protocol but offers user-targeted interaction
      */
-    public Response htmlAnswer( String uri, String perf, Properties header, Properties params ) {
+    public String htmlAnswer( String uri, String perf, Properties header, Properties params ) {
 	//logger.trace("HTML[{}]", perf );
 	// REST get
 	String msg = "";
@@ -747,7 +433,7 @@ public class HTMLAServProfile implements AlignmentServiceProfile {
 	    } else {
 		// Depending on the type we should change the MIME type
 		// This should be returned in answer.getParameters()
-		return new Response( HTTP_OK, MIME_HTML, answer.getContent() );
+		return answer.getContent();
 	    }
 	// Metadata not done yet
 	} else if ( perf.equals("prmmetadata") ) {
@@ -771,7 +457,7 @@ public class HTMLAServProfile implements AlignmentServiceProfile {
 		msg = testErrorMessages( answer, params );
 	    } else {
 		// Depending on the type we should change the MIME type
-		return new Response( HTTP_OK, MIME_HTML, answer.getContent() );
+		return answer.getContent();
 	    }
 	    // render
 	    // Alignment in HTML can be rendre or metadata+tuples
@@ -905,29 +591,30 @@ public class HTMLAServProfile implements AlignmentServiceProfile {
 	} else {
 	    msg = "Cannot understand command "+perf;
 	}
-	return new Response( HTTP_OK, MIME_HTML, "<html><head>"+HEADER+"</head><body>"+msg+"<hr /><center><small><a href=\".\">Alignment server</a></small></center></body></html>" );
+	return "<html><head>"+HEADER+"</head><body>"+msg+"<hr /><center><small><a href=\".\">Alignment server</a></small></center></body></html>";
     }
 
     // ===============================================
     // Util
 
-    public Response wsdlAnswer(String uri, String perf, Properties header, Properties params  ) {
-	return new Response( HTTP_OK, MIME_XML, WSAServProfile.wsdlAnswer( false ) );
-    }	 
-
     private String testErrorMessages( Message answer, Properties param ) {
-	if ( returnType == MIME_RDFXML ) {
+	/*
+	if ( returnType == HTTPResponse.MIME_RDFXML ) {
 	    return answer.RESTString();
-	} else if ( returnType == MIME_JSON ) {
+	} else if ( returnType == HTTPResponse.MIME_JSON ) {
 	    return answer.JSONString();
-	} else {
+	    } else {*/
 	    return "<h1>Alignment error</h1>"+answer.HTMLString();
-	}
+	    /*}*/
     }
 
     private String displayAnswer( Message answer, Properties param ) {
+	return displayAnswer( answer, param, null );
+    }
+
+    private String displayAnswer( Message answer, Properties param, String returnType ) {
 	String result = null;
-	if ( returnType == MIME_RDFXML ) {
+	if ( returnType == HTTPResponse.MIME_RDFXML ) {
 	    if( param.getProperty("return").equals("HTML") ) { // RESTFUL but in HTML ??
 	    	result = answer.HTMLRESTString();
 	    	if ( answer instanceof AlignmentId && ( answer.getParameters() == null || answer.getParameters().getProperty("async") == null ) ) {
@@ -941,7 +628,7 @@ public class HTMLAServProfile implements AlignmentServiceProfile {
 	    } else {
 		result = answer.RESTString();
 	    }
-	} else if ( returnType == MIME_JSON ) {
+	} else if ( returnType == HTTPResponse.MIME_JSON ) {
 	    result = answer.JSONString();
 	} else {
 	    result = answer.HTMLString();
@@ -969,121 +656,5 @@ public class HTMLAServProfile implements AlignmentServiceProfile {
 	return result;
     }
 
-    private int newId() { return localId++; }
-
-    private void decodeParams( String params, Properties p ) throws InterruptedException {
-	if ( params == null ) return;
-	
-	for ( String next : params.split("&") ) {
-	    int sep = next.indexOf( '=' );
-	    if ( sep >= 0 ){
-		try {
-		    p.put( URLDecoder.decode( next.substring( 0, sep ), "iso-8859-1" ).trim(),
-			   // JE: URLDecoder allows for : and / but not #
-			   URLDecoder.decode( next.substring( sep+1 ), "iso-8859-1" ));
-		} catch (Exception e) {}; //never thrown
-	    }
-	}
-    }
-
-    // ==================================================
-    // HTTP Machinery
-
-    /**
-     * HTTP response.
-     * Return one of these from serve().
-     */
-    public class Response {
-	/**
-	 * Default constructor: response = HTTP_OK, data = mime = 'null'
-	 */
-	public Response() {
-	    this.status = HTTP_OK;
-	}
-
-	/**
-	 * Basic constructor.
-	 */
-	public Response( String status, String mimeType, InputStream data ) {
-	    this.status = status;
-	    this.mimeType = mimeType;
-	    this.data = data;
-	}
-
-	/**
-	 * Convenience method that makes an InputStream out of
-	 * given text.
-	 */
-	public Response( String status, String mimeType, String txt ) {
-	    this.status = status;
-	    this.mimeType = mimeType;
-	    this.data = new ByteArrayInputStream( txt.getBytes());
-	    // JE: Added
-	    this.msg = txt;
-	}
-
-	/**
-	 * Adds given line to the header.
-	 */
-	public void addHeader( String name, String value ) {
-	    header.put( name, value );
-	}
-
-
-	/**
-	 * HTTP status code after processing, e.g. "200 OK", HTTP_OK
-	 */
-	public String status;
-
-	/**
-	 * MIME type of content, e.g. "text/html"
-	 */
-	public String mimeType;
-
-	/**
-	 * Data of the response, may be null.
-	 */
-	public InputStream data;
-
-	/**
-	 * Headers for the HTTP response. Use addHeader()
-	 * to add lines.
-	 */
-	public Properties header = new Properties();
-	// JE: Added for testing Jetty
-	public String msg;
-	public String getStatus() { return status; };
-	public String getContentType() { return mimeType; }
-	public String getData() { return msg; }
-
-    }
-
-    /**
-     * Two private cclasses for retrieving parameters
-     */
-    private class ParameterServletResponseWrapper extends ServletResponseWrapper  {
-	private Map parameters;
-
-	public ParameterServletResponseWrapper( ServletResponse r ){
-	    super(r);
-	};
-
-	public Map getParameterMap(){ return parameters; }
- 
-	public void setParameterMap( Map m ){ parameters = m; }
- 
-     }
-
-    private class Chain implements FilterChain {
- 
-	public void doFilter( ServletRequest request, ServletResponse response)
-	    throws IOException, ServletException {
-	    if ( response instanceof ParameterServletResponseWrapper &&
-		 request instanceof ServletRequestWrapper ) {
-		((ParameterServletResponseWrapper)response).setParameterMap( ((ServletRequestWrapper)request).getParameterMap() );
-	    }
-         }
- 
-     }
 }
 
diff --git a/src/fr/inrialpes/exmo/align/service/HTTPResponse.java b/src/fr/inrialpes/exmo/align/service/HTTPResponse.java
new file mode 100644
index 0000000000000000000000000000000000000000..dee4374b50468cf2e08cd18109b9a857079801d7
--- /dev/null
+++ b/src/fr/inrialpes/exmo/align/service/HTTPResponse.java
@@ -0,0 +1,118 @@
+/*
+ * $Id$
+ *
+ * Copyright (C) INRIA, 2014
+ *
+ * This program 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 program 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 program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ */
+
+package fr.inrialpes.exmo.align.service;
+
+import java.io.ByteArrayInputStream;
+import java.io.InputStream;
+import java.util.Properties;
+
+/**
+ * HTTP response.
+ * Return one of these from serve().
+ */
+public class HTTPResponse {
+
+    /**
+     * Some HTTP response status codes
+     */
+    public static final String
+	HTTP_OK = "200 OK",
+	HTTP_REDIRECT = "301 Moved Permanently",
+	HTTP_FORBIDDEN = "403 Forbidden",
+	HTTP_NOTFOUND = "404 Not Found",
+	HTTP_BADREQUEST = "400 Bad Request",
+	HTTP_INTERNALERROR = "500 Internal Server Error",
+	HTTP_NOTIMPLEMENTED = "501 Not Implemented";
+
+    /**
+     * Common mime types for dynamic content
+     */
+    public static final String
+	MIME_PLAINTEXT = "text/plain",
+	MIME_HTML = "text/html",
+	MIME_XML = "text/xml",
+	MIME_JSON = "application/json",
+	MIME_RDFXML = "application/rdf+xml",
+	MIME_DEFAULT_BINARY = "application/octet-stream";
+
+    /**
+     * Default constructor: response = HTTP_OK, data = mime = 'null'
+     */
+    public HTTPResponse() {
+	this.status = HTTP_OK;
+    }
+
+    /**
+     * Basic constructor.
+     */
+    public HTTPResponse( String status, String mimeType, InputStream data ) {
+	this.status = status;
+	this.mimeType = mimeType;
+	this.data = data;
+    }
+
+    /**
+     * Convenience method that makes an InputStream out of
+     * given text.
+     */
+    public HTTPResponse( String status, String mimeType, String txt ) {
+	this.status = status;
+	this.mimeType = mimeType;
+	this.data = new ByteArrayInputStream( txt.getBytes());
+	// JE: Added
+	this.msg = txt;
+    }
+    
+    /**
+     * Adds given line to the header.
+     */
+    public void addHeader( String name, String value ) {
+	header.put( name, value );
+    }
+    
+    /**
+     * HTTP status code after processing, e.g. "200 OK", HTTP_OK
+     */
+    public String status;
+    
+    /**
+     * MIME type of content, e.g. "text/html"
+     */
+    public String mimeType;
+    
+    /**
+     * Data of the response, may be null.
+     */
+    public InputStream data;
+    
+    /**
+     * Headers for the HTTP response. Use addHeader()
+     * to add lines.
+     */
+    public Properties header = new Properties();
+    // JE: Added for testing Jetty
+    public String msg;
+    public String getStatus() { return status; };
+    public String getContentType() { return mimeType; }
+    public String getData() { return msg; }
+    
+}
+
diff --git a/src/fr/inrialpes/exmo/align/service/HTTPTransport.java b/src/fr/inrialpes/exmo/align/service/HTTPTransport.java
new file mode 100644
index 0000000000000000000000000000000000000000..caceb554ea5aaede7b4205e9b50e092ef017fa5c
--- /dev/null
+++ b/src/fr/inrialpes/exmo/align/service/HTTPTransport.java
@@ -0,0 +1,416 @@
+/*
+ * $Id$
+ *
+ * Copyright (C) INRIA, 2006-2014
+ *
+ * This program 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 program 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 program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ */
+
+package fr.inrialpes.exmo.align.service;
+
+import fr.inrialpes.exmo.align.service.msg.Message;
+import fr.inrialpes.exmo.align.service.msg.ErrorMsg;
+
+import java.io.File;
+import java.io.FileReader;
+import java.io.IOException;
+import java.io.FileInputStream;
+import java.io.PrintWriter;
+import java.io.InputStream;
+import java.io.BufferedReader;
+import java.io.InputStreamReader;
+import java.io.OutputStream;
+import java.io.BufferedInputStream;
+import java.io.FileOutputStream;
+
+import java.util.Locale;
+import java.util.TimeZone;
+import java.util.Hashtable;
+import java.util.Vector;
+import java.util.Properties;
+import java.util.Collection;
+import java.util.Date;
+import java.util.Enumeration;
+import java.util.Iterator;
+import java.util.Map;
+
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.net.Socket;
+import java.net.ServerSocket;
+import java.net.URLEncoder;
+import java.net.URLDecoder;
+
+import java.lang.Integer;
+
+import javax.servlet.ServletException;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+import javax.servlet.ServletResponseWrapper;
+import javax.servlet.ServletRequestWrapper;
+import javax.servlet.FilterChain;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.mortbay.jetty.Handler;
+import org.mortbay.jetty.handler.AbstractHandler;
+import org.mortbay.jetty.Server;
+import org.mortbay.jetty.Request;
+import org.mortbay.servlet.MultiPartFilter;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * HTTPTransport: implements the HTTP connection of the server
+ * Dispatch messages to the various services
+ */
+
+public class HTTPTransport {
+    final static Logger logger = LoggerFactory.getLogger( HTTPTransport.class );
+
+    private int tcpPort;
+    private String tcpHost;
+    private Server server;
+    private AServProtocolManager manager;
+    private Vector<AlignmentServiceProfile> services;
+
+    private String myId;
+    private String serverId;
+    private int localId = 0;
+
+    private String returnType = HTTPResponse.MIME_HTML;
+
+    // ==================================================
+    // Socket & server code
+    // ==================================================
+
+    /**
+     * Starts a HTTP server to given port.<p>
+     * Throws an exception if the socket is already in use
+     */
+    public void init( Properties params, AServProtocolManager manager, Vector<AlignmentServiceProfile> serv ) throws AServException {
+	this.manager = manager;
+	services = serv;
+	tcpPort = Integer.parseInt( params.getProperty( "http" ) );
+	tcpHost = params.getProperty( "host" ) ;
+
+	/*
+	try {
+	    final ServerSocket ss = new ServerSocket( tcpPort );
+	    Thread t = new Thread( new Runnable() {
+		    public void run() {
+			try { while( true ) new HTTPSession( ss.accept());
+			} catch ( IOException ioe ) { logger.debug( "IGNORED Exception", ioe ); }
+		    }
+		});
+	    t.setDaemon( true );
+	    t.start();
+	} catch (Exception e) {
+	    throw new AServException ( "Cannot launch HTTP Server" , e );
+	}
+	*/
+
+	// ********************************************************************
+	// JE: Jetty implementation
+	server = new Server(tcpPort);
+
+	// The handler deals with the request
+	// most of its work is to deal with large content sent in specific ways 
+	Handler handler = new AbstractHandler(){
+		public void handle( String target, HttpServletRequest request, HttpServletResponse response, int dispatch ) throws IOException, ServletException {
+		    String method = request.getMethod();
+		    //uri = URLDecoder.decode( request.getURI(), "iso-8859-1" );
+		    // Should be decoded?
+		    String uri = request.getPathInfo();
+		    Properties params = new Properties();
+		    try { decodeParams( request.getQueryString(), params ); }
+		    catch ( Exception e) {};
+		    // I do not decode them here because it is useless
+		    // See below how it is done.
+		    Properties header = new Properties();
+		    Enumeration headerNames = request.getHeaderNames();
+		    while( headerNames.hasMoreElements() ) {
+			String headerName = (String)headerNames.nextElement();
+			header.setProperty( headerName, request.getHeader(headerName) );
+		    }
+
+		    // Get the content if any
+		    // This is supposed to be only an uploaded file
+		    // We use jetty MultiPartFilter to decode this file.
+		    // Note that this could be made more uniform 
+		    // with the text/xml part stored in a file as well.
+		    String mimetype = request.getContentType();
+		    // Multi part: the content provided by an upload HTML form
+		    if ( mimetype != null && mimetype.startsWith("multipart/form-data") ) {
+			MultiPartFilter filter = new MultiPartFilter();
+			// This is in fact useless
+			ParameterServletResponseWrapper dummyResponse =
+			    new ParameterServletResponseWrapper( response );
+			// In theory, the filter must be inited with a FilterConfig
+			// filter.init( new FilterConfig);
+			// This filter config must have a javax.servlet.context.tempdir attribute
+			// and a ServletConxtext with parameter "deleteFiles"
+			// Apparently the Jetty implementation uses System defaults
+			// if no FilterConfig
+			// e.g., it uses /tmp and keeps the files
+			filter.doFilter( request, dummyResponse, new Chain() );
+			// Apparently a bug from Jetty prevents from retrieving this
+			if ( request.getParameter("pretty") != null )
+			    params.setProperty( "pretty", request.getParameter("pretty").toString() );
+			if ( request.getAttribute("content") != null )
+			    params.setProperty( "filename", request.getAttribute("content").toString() );
+			filter.destroy();
+		    } else if ( mimetype != null && mimetype.startsWith("text/xml") ) {
+			// Most likely Web service request (REST through POST)
+			int length = request.getContentLength();
+			if ( length > 0 ) {
+			    char [] mess = new char[length+1];
+			    try {
+				new BufferedReader(new InputStreamReader(request.getInputStream())).read( mess, 0, length);
+			    } catch ( Exception e ) {
+				logger.debug( "IGNORED Exception", e );
+			    }
+			    params.setProperty( "content", new String( mess ) );
+			}
+		    // File attached to SOAP messages
+		    } else if ( mimetype != null && mimetype.startsWith("application/octet-stream") ) {
+         		File alignFile = new File(File.separator + "tmp" + File.separator + newId() +"XXX.rdf");
+         		// check if file already exists - and overwrite if necessary.
+         		if (alignFile.exists()) alignFile.delete();
+               	 	FileOutputStream fos = new FileOutputStream(alignFile);
+            		InputStream is = request.getInputStream();
+			
+           	        try {
+			    byte[] buffer = new byte[4096];
+			    int bytes=0; 
+			    while (true) {
+				bytes = is.read(buffer);
+				if (bytes < 0) break;
+				fos.write(buffer, 0, bytes);
+			    }
+            		} catch (Exception e) {
+			} finally {
+			    fos.flush();
+			    fos.close();
+			}
+               		is.close();
+			params.setProperty( "content", "" );
+			params.setProperty( "filename" ,  alignFile.getAbsolutePath()  );
+         	    } 
+
+		    // Get the answer (HTTP)
+		    HTTPResponse r = serve( uri, method, header, params );
+
+		    // Return it
+		    response.setContentType( r.getContentType() );
+		    response.setStatus( HttpServletResponse.SC_OK );
+		    response.getWriter().println( r.getData() );
+		    ((Request)request).setHandled( true );
+		}
+	    };
+	server.setHandler(handler);
+
+	// Common part
+	try { server.start(); }
+	catch (Exception e) {
+	    throw new AServException( "Cannot launch HTTP Server" , e );
+	}
+	//server.join();
+
+	// ********************************************************************
+	//if ( params.getProperty( "wsdl" ) != null ){
+	//    wsmanager = new WSAServProfile();
+	//    if ( wsmanager != null ) wsmanager.init( params, manager );
+	//}
+	//if ( params.getProperty( "http" ) != null ){
+	//    htmanager = new HTMLAServProfile();
+	//    if ( htmanager != null ) htmanager.init( params, manager );
+	//}
+	myId = "LocalHTMLInterface";
+	serverId = manager.serverURL();
+	logger.info( "Launched on {}/html/", serverId );
+	localId = 0;
+    }
+
+    public void close(){
+	if ( server != null ) {
+	    try { server.stop(); }
+            catch (Exception e) { logger.debug( "IGNORED Exception on close", e ); }
+	}
+    }
+    
+    // ==================================================
+    // API parts
+    // ==================================================
+
+    /**
+     * Override this to customize the server.<p>
+     *
+     * (By default, this delegates to serveFile() and allows directory listing.)
+     *
+     * @param uri	Percent-decoded URI without parameters, for example "/index.cgi"
+     * @param method	"GET", "POST" etc.
+     * @param parms	Parsed, percent decoded parameters from URI and, in case of POST, data.
+     * @param header	Header entries, percent decoded
+     * @return HTTP response, see class Response for details
+     */
+    public HTTPResponse serve( String uri, String method, Properties header, Properties parms ) {
+	logger.debug( "{} '{}'", method, uri );
+
+	// Convert parms to parameters
+	Properties params = new Properties();
+	for ( String key : parms.stringPropertyNames() ) {
+	    //logger.trace( "  PRM: '{}' = '{}'", key, parms.getProperty( key ) );
+	    if ( key.startsWith( "paramn" ) ){
+		params.setProperty( parms.getProperty( key ),
+				     parms.getProperty( "paramv"+key.substring( 6 ) ) );
+	    } else if ( !key.startsWith( "paramv" ) ) {
+		params.setProperty( key, parms.getProperty( key ) );
+	    }
+	}
+	
+	int start = 0;
+	while ( start < uri.length() && uri.charAt(start) == '/' ) start++;
+	int end = uri.indexOf( '/', start+1 );
+	String oper = "";
+	if ( end != -1 ) {
+	    oper = uri.substring( start, end );
+	    start = end+1;
+	} else {
+	    oper = uri.substring( start );
+	    start = uri.length();
+	}
+	logger.trace( "Oper: {}", oper );
+
+	// Content negotiation first
+	String accept = header.getProperty( "Accept" );
+	returnType = HTTPResponse.MIME_HTML;
+	if ( accept == null ) accept = header.getProperty( "accept" );
+	logger.trace( "Accept header: {}", accept );
+	if ( accept != null && !accept.equals("") ) {
+	    int indexRXML = accept.indexOf( HTTPResponse.MIME_RDFXML );
+	    if ( indexRXML == -1 ) indexRXML = accept.indexOf( HTTPResponse.MIME_XML );
+	    int indexJSON = accept.indexOf( HTTPResponse.MIME_JSON );
+	    if ( indexRXML != -1 ) {
+		if ( indexJSON > indexRXML || indexJSON == -1 ) {
+		    returnType = HTTPResponse.MIME_RDFXML;
+		} else {
+		    returnType = HTTPResponse.MIME_JSON;
+		}
+	    } else if ( indexJSON != -1 ) {
+		returnType = HTTPResponse.MIME_JSON;
+	    }
+	}
+	logger.trace( "Return MIME Type: {}", returnType );
+	params.setProperty( "returnType", returnType );
+
+	if ( oper.equals( "alid" ) ){ // Asks for an alignment by URI
+	    return returnAlignment( uri, returnType );
+	} else if ( oper.equals( "" ) ) {
+	    // SHOULD BE ASSIGNED TO CONTENT NEGOCIATION AS WELL... (DEFAULT IN SERVERS)
+	    //return serveFile( uri, header, new File("."), true );
+	    return new HTTPResponse( HTTPResponse.HTTP_OK, HTTPResponse.MIME_HTML, "<html><head>"+HTMLAServProfile.HEADER+"</head><body>"+HTMLAServProfile.about()+"</body></html>" );
+	} else {
+	    // Selects the relevant service for the request
+	    for ( AlignmentServiceProfile serv : services ) {
+		if ( serv.accept( oper ) ) {
+		    return new HTTPResponse( HTTPResponse.HTTP_OK, returnType, serv.process( uri, oper, uri.substring(start), header, params ) );
+		}
+	    }
+	    return noManager( oper );
+	}
+    }
+
+    protected HTTPResponse noManager( String type ) {
+	if ( returnType == HTTPResponse.MIME_JSON ) {
+	    return new HTTPResponse( HTTPResponse.HTTP_OK, HTTPResponse.MIME_JSON, "{ \"type\" : \"AServErrorMsg\",\n  \"content\" : \"No "+type+" service launched\"\n}" );
+	} else if ( returnType == HTTPResponse.MIME_RDFXML ) {
+	    return new HTTPResponse( HTTPResponse.HTTP_OK, HTTPResponse.MIME_RDFXML, "<AServErrorMsg>No "+type+" service launched</AServErrorMsg>" );
+	} else {
+	    return new HTTPResponse( HTTPResponse.HTTP_OK, HTTPResponse.MIME_HTML, "<html><head>"+HTMLAServProfile.HEADER+"</head><body>"+"<ErrMsg>No "+type+" service launched</ErrMsg>"+"<hr /><center><small><a href=\".\">Alignment server</a></small></center></body></html>" );
+	}
+    }
+
+    /**
+     * Returns the alignment in negociated format
+     */
+    public HTTPResponse returnAlignment( String uri, String mimeType ) {
+	Properties params = new Properties();
+	params.setProperty( "id", manager.serverURL()+uri );
+	if ( returnType == HTTPResponse.MIME_JSON ) { // YES string compared by ==.
+	    params.setProperty( "method", "fr.inrialpes.exmo.align.impl.renderer.JSONRendererVisitor" );
+	} else if ( returnType == HTTPResponse.MIME_RDFXML ) {
+	    params.setProperty( "method", "fr.inrialpes.exmo.align.impl.renderer.RDFRendererVisitor" );
+	} else {
+	    params.setProperty( "method", "fr.inrialpes.exmo.align.impl.renderer.HTMLRendererVisitor" );
+	}
+	logger.trace( "Bloody URI : {}", manager.serverURL()+uri);
+	Message answer = manager.render( new Message( newId(), (Message)null, myId, serverId, "", params) );
+	if ( answer instanceof ErrorMsg ) {
+	    return new HTTPResponse( HTTPResponse.HTTP_NOTFOUND, HTTPResponse.MIME_PLAINTEXT, "Alignment server: unknown alignment : "+answer.getContent() );
+	} else {
+	    return new HTTPResponse( HTTPResponse.HTTP_OK, mimeType, answer.getContent() );
+	}
+    }
+
+    // ===============================================
+    // Util
+
+    private int newId() { return localId++; }
+
+    private void decodeParams( String params, Properties p ) throws InterruptedException {
+	if ( params == null ) return;
+	
+	for ( String next : params.split("&") ) {
+	    int sep = next.indexOf( '=' );
+	    if ( sep >= 0 ){
+		try {
+		    p.put( URLDecoder.decode( next.substring( 0, sep ), "iso-8859-1" ).trim(),
+			   // JE: URLDecoder allows for : and / but not #
+			   URLDecoder.decode( next.substring( sep+1 ), "iso-8859-1" ));
+		} catch (Exception e) {}; //never thrown
+	    }
+	}
+    }
+    /**
+     * Two private cclasses for retrieving parameters
+     */
+    private class ParameterServletResponseWrapper extends ServletResponseWrapper  {
+	private Map parameters;
+
+	public ParameterServletResponseWrapper( ServletResponse r ){
+	    super(r);
+	};
+
+	public Map getParameterMap(){ return parameters; }
+ 
+	public void setParameterMap( Map m ){ parameters = m; }
+ 
+     }
+
+    private class Chain implements FilterChain {
+ 
+	public void doFilter( ServletRequest request, ServletResponse response)
+	    throws IOException, ServletException {
+	    if ( response instanceof ParameterServletResponseWrapper &&
+		 request instanceof ServletRequestWrapper ) {
+		((ParameterServletResponseWrapper)response).setParameterMap( ((ServletRequestWrapper)request).getParameterMap() );
+	    }
+         }
+ 
+     }
+}
+
diff --git a/src/fr/inrialpes/exmo/align/service/WSAServProfile.java b/src/fr/inrialpes/exmo/align/service/WSAServProfile.java
index 8043f5550364652b87a7073e84b18614a52d6ce8..6625a82225476556acd5843a8990595260bb091a 100644
--- a/src/fr/inrialpes/exmo/align/service/WSAServProfile.java
+++ b/src/fr/inrialpes/exmo/align/service/WSAServProfile.java
@@ -1,7 +1,7 @@
 /*
  * $Id$
  *
- * Copyright (C) INRIA, 2007-2013
+ * Copyright (C) INRIA, 2007-2014
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public License
@@ -90,6 +90,8 @@ public class WSAServProfile implements AlignmentServiceProfile {
     private AServProtocolManager manager;
     private static String wsdlSpec = "";
 
+    private boolean restful = false;
+
     private String myId;
     private String serverURL;
     private int localId = 0;
@@ -184,6 +186,23 @@ public class WSAServProfile implements AlignmentServiceProfile {
 	}
     }
 
+    public boolean accept( String prefix ) {
+	if ( prefix.equals("aserv") || prefix.equals("rest") || prefix.equals("wsdl") ) return true;
+	else return false;
+    }
+
+    public String process( String uri, String prefix, String perf, Properties header, Properties params ) {
+	restful = false;
+	if ( prefix.equals("rest") ) {
+	    restful = true;
+	    return protocolAnswer( uri, perf, header, params );
+	} else if ( prefix.equals("aserv") ) {
+	    return protocolAnswer( uri, perf, header, params );
+	} else if ( prefix.equals("wsdl") ) {
+	    return wsdlAnswer( false );
+	} else return "";//about();
+    }
+
     public void close(){
 	// This may unregister the WSDL file to some directory
     }
@@ -204,7 +223,6 @@ public class WSAServProfile implements AlignmentServiceProfile {
 	String message = null;
 	Properties newparameters = null;
 	Message answer = null;
-	boolean restful = (param.getProperty("restful")==null)?false:true;
 	String svcNS = "\n       xml:base='"+Namespace.ALIGNSVC.prefix+"'"+
 	    "\n       xmlns='"+Namespace.ALIGNSVC.prefix+"'";
 	String msg = "";
@@ -221,16 +239,19 @@ public class WSAServProfile implements AlignmentServiceProfile {
 		// However, there is a way to pass SOAP messages with attachments
 		// It would be better to implement this. See:
 		// http://www.oracle.com/technology/sample_code/tech/java/codesnippet/webservices/attachment/index.html
-		message = param.getProperty("content").trim();
+		message = param.getProperty("content");
 		// Create the DOM tree for the SOAP message
 		Document domMessage = null;
 		try {
-		    domMessage = BUILDER.parse( new ByteArrayInputStream( message.getBytes()) );
+		    domMessage = BUILDER.parse( new ByteArrayInputStream( message.trim().getBytes() ) );
 		} catch  ( IOException ioex ) {
-		    logger.debug( "IGNORED Exception", ioex );
+		    logger.debug( "IGNORED Exception {}", ioex );
 		    answer = new NonConformParameters(0,(Message)null,myId,"Cannot Parse SOAP message",message,(Properties)null);
 		} catch  ( SAXException saxex ) {
-		    logger.debug( "IGNORED Exception", saxex );
+		    logger.debug( "IGNORED Exception {}", saxex );
+		    answer = new NonConformParameters(0,(Message)null,myId,"Cannot Parse SOAP message",message,(Properties)null);
+		} catch ( NullPointerException npex ) {
+		    logger.debug( "IGNORED Exception {}", npex );
 		    answer = new NonConformParameters(0,(Message)null,myId,"Cannot Parse SOAP message",message,(Properties)null);
 		}
 		newparameters = getParameters( domMessage );
@@ -238,6 +259,7 @@ public class WSAServProfile implements AlignmentServiceProfile {
 		newparameters = new Properties();
 	    }
 	}
+	//logger.debug( "Analised header" );
 
 	// Process the action
 	if ( perf.equals("WSDL") || method.equals("wsdl") || method.equals("wsdlRequest") ) {
diff --git a/src/fr/inrialpes/exmo/align/service/jade/JadeFIPAAServProfile.java b/src/fr/inrialpes/exmo/align/service/jade/JadeFIPAAServProfile.java
index ba25babfc9fd4a636579db1db983b8fbad96dc9e..3c3578360ff8fbc70af1f777ce873969f7d563c6 100755
--- a/src/fr/inrialpes/exmo/align/service/jade/JadeFIPAAServProfile.java
+++ b/src/fr/inrialpes/exmo/align/service/jade/JadeFIPAAServProfile.java
@@ -2,7 +2,7 @@
  * $Id$
  *
  * Copyright (C) Orange R&D, 2006-2007
- * Copyright (C) INRIA, 2006-2007, 2009-2010, 2013
+ * Copyright (C) INRIA, 2006-2007, 2009-2010, 2013-2014
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public License
@@ -41,63 +41,69 @@ import org.slf4j.LoggerFactory;
 public class JadeFIPAAServProfile implements AlignmentServiceProfile {
     final static Logger logger = LoggerFactory.getLogger( JadeFIPAAServProfile.class );
 
-	private AgentContainer mc;
-	private AgentController algagentcontroller;
+    private AgentContainer mc;
+    private AgentController algagentcontroller;
 
-	public void init( Properties params, AServProtocolManager manager ) throws AServException {
-		int port = 8888;
-		Object args[] = new Object[2];
-		
-		//set up the manager as an argument to pass to the JADEFIPAAServiceAgent
-		args[0]=manager;
+    public void init( Properties params, AServProtocolManager manager ) throws AServException {
+	int port = 8888;
+	Object args[] = new Object[2];
+	
+	//set up the manager as an argument to pass to the JADEFIPAAServiceAgent
+	args[0]=manager;
 		
-		// set up the Parameters as an argument to pass to the JADEFIPAServiceAgent
-		args[1]=params;
+	// set up the Parameters as an argument to pass to the JADEFIPAServiceAgent
+	args[1]=params;
 		
-		if ( params.getProperty( "jade" ) != null )
-			port = Integer.parseInt( params.getProperty( "jade" ) );
+	if ( params.getProperty( "jade" ) != null )
+	    port = Integer.parseInt( params.getProperty( "jade" ) );
 
-		/**		
-	Properties props = new Properties();
-		 **/
-		try {
-			// Get a hold on JADE runtime
-			Runtime rt = Runtime.instance();
+	// Properties props = new Properties();
+	try {
+	    // Get a hold on JADE runtime
+	    Runtime rt = Runtime.instance();
 
-			// Exit the JVM when there are no more containers around
-			rt.setCloseVM(true);
+	    // Exit the JVM when there are no more containers around
+	    rt.setCloseVM(true);
 
-			/** Profile with no MTP( Message Transfer Protocol
+	    /** Profile with no MTP( Message Transfer Protocol
 		props.setProperty("nomtp", "true");
 		Profile pMain = new ProfileImpl(props);
-			 **/
-			// create a default Profile
-			Profile pMain = new ProfileImpl(null, port, null);
-
-			//logger.trace( "Launching a whole in-process platform... {}", pMain );
-			mc = rt.createMainContainer(pMain);
-			algagentcontroller = mc.createNewAgent("JadeFIPAAServiceAgent", JadeFIPAAServiceAgent.class.getName(), args);
-			algagentcontroller.start();
-		}
-		catch(Exception e) {
-			throw new AServException ( "Cannot launch Jade Server" , e );
-		}
+	    **/
+	    // create a default Profile
+	    Profile pMain = new ProfileImpl(null, port, null);
+	    
+	    //logger.trace( "Launching a whole in-process platform... {}", pMain );
+	    mc = rt.createMainContainer(pMain);
+	    algagentcontroller = mc.createNewAgent("JadeFIPAAServiceAgent", JadeFIPAAServiceAgent.class.getName(), args);
+	    algagentcontroller.start();
+	} catch(Exception ex) {
+	    throw new AServException ( "Cannot launch Jade Server" , ex );
 	}
+    }
+
 
-	public void close(){
-	    try{
-		algagentcontroller.kill();
-		mc.kill();
-		logger.info( "Agent Alignement closed" );
-	    } catch (ControllerException e) {
-		logger.warn( "Error killing the alignment agent." ); }
-	    try {
-		// Destroy the files please (JE)
-		new File("APDescription.txt").delete();
-		new File("MTPs-Main-Container.txt").delete();
-	    } catch (Exception e) {
-		logger.debug( "IGNORED Exception", e );
-	    }
+    public boolean accept( String prefix ) {
+	return false;
+    }
+
+    public String process( String uri, String prefix, String perf, Properties header, Properties params ) {
+	return "JADE Cannot be invoked this way through HTTP service";
+    }
+
+    public void close(){
+	try{
+	    algagentcontroller.kill();
+	    mc.kill();
+	    logger.info( "Agent Alignement closed" );
+	} catch (ControllerException cex) {
+	    logger.warn( "Error killing the alignment agent." ); 
 	}
-	
+	try {
+	    // Destroy the files please (JE)
+	    new File("APDescription.txt").delete();
+	    new File("MTPs-Main-Container.txt").delete();
+	} catch (Exception ex) {
+	    logger.debug( "IGNORED Exception", ex );
+	}
+    }
 }
diff --git a/src/fr/inrialpes/exmo/align/service/osgi/OSGIAServProfile.java b/src/fr/inrialpes/exmo/align/service/osgi/OSGIAServProfile.java
index 2ccd804faeee117ca012b06ccc5af4976ae7080c..5103615d5b6cbf8f1892062b28b2c1574d160392 100644
--- a/src/fr/inrialpes/exmo/align/service/osgi/OSGIAServProfile.java
+++ b/src/fr/inrialpes/exmo/align/service/osgi/OSGIAServProfile.java
@@ -1,7 +1,7 @@
 /*
  * $Id$
  *
- * Copyright (C) INRIA, 2010, 2013
+ * Copyright (C) INRIA, 2010, 2013-2014
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public License
@@ -56,6 +56,14 @@ public class OSGIAServProfile implements AlignmentServiceProfile, BundleActivato
 	this.manager = manager;
     }
 
+    public boolean accept( String prefix ) {
+	return false;
+    }
+
+    public String process( String uri, String prefix, String perf, Properties header, Properties params ) {
+	return "OSGI Cannot be invoked this way through HTTP service";
+    }
+
     public void close(){
 	// This may unregister the WSDL file to some directory
 	stop( ctxt );