Mentions légales du service

Skip to content
Snippets Groups Projects
Commit 4145b771 authored by Jérôme Euzenat's avatar Jérôme Euzenat
Browse files

- Reorganised AlignmentServices into transport (HTTP) and service (HTML/Web service)

parent 62b4d2ac
No related branches found
No related tags found
No related merge requests found
Showing with 695 additions and 530 deletions
...@@ -79,6 +79,7 @@ with a warning: ...@@ -79,6 +79,7 @@ with a warning:
<li>Fixed a bug in <tt>QueryMediator</tt> which doubled '#' (serv)</li> <li>Fixed a bug in <tt>QueryMediator</tt> which doubled '#' (serv)</li>
<li>Fixed a few mistakes in <tt>SilkRendererVisitor</tt> (impl)</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>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>Enabled query translation in interface (serv)</li>
<li>Added a command-line utility for query translation (cli)</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> <li>Added a guard forbiding to create a <tt>BasicCell</tt> with null objects (impl)</li>
......
...@@ -482,12 +482,10 @@ public class AServProtocolManager implements Service { ...@@ -482,12 +482,10 @@ public class AServProtocolManager implements Service {
//logger.trace( "Resulting rendering : {}", result.toString() ); //logger.trace( "Resulting rendering : {}", result.toString() );
logger.error( "Cannot render alignment", e ); logger.error( "Cannot render alignment", e );
return new Message(newId(),mess,serverId,mess.getSender(),"Failed to render alignment",(Properties)null); return new Message(newId(),mess,serverId,mess.getSender(),"Failed to render alignment",(Properties)null);
} finally { } finally {
writer.flush(); writer.flush();
writer.close(); writer.close();
} }
return new RenderedAlignment(newId(),mess,serverId,mess.getSender(),result.toString(),(Properties)null); return new RenderedAlignment(newId(),mess,serverId,mess.getSender(),result.toString(),(Properties)null);
} }
......
...@@ -35,6 +35,7 @@ import org.apache.commons.cli.OptionBuilder; ...@@ -35,6 +35,7 @@ import org.apache.commons.cli.OptionBuilder;
import org.apache.commons.cli.ParseException; import org.apache.commons.cli.ParseException;
import java.util.Hashtable; import java.util.Hashtable;
import java.util.Vector;
import java.util.Enumeration; import java.util.Enumeration;
import java.util.Properties; import java.util.Properties;
import java.io.PrintStream; import java.io.PrintStream;
...@@ -87,8 +88,9 @@ public class AlignmentService extends CommonCLI { ...@@ -87,8 +88,9 @@ public class AlignmentService extends CommonCLI {
private String filename = null; private String filename = null;
private String outfile = null; private String outfile = null;
private String paramfile = null; private String paramfile = null;
private Hashtable<String,AlignmentServiceProfile> services = null; private Vector<AlignmentServiceProfile> services = null;
private Hashtable<String,Directory> directories = null; private Hashtable<String,Directory> directories = null;
private HTTPTransport transport = null;
private AServProtocolManager manager; private AServProtocolManager manager;
private DBService connection; private DBService connection;
...@@ -124,7 +126,7 @@ public class AlignmentService extends CommonCLI { ...@@ -124,7 +126,7 @@ public class AlignmentService extends CommonCLI {
} }
public void run(String[] args) throws Exception { public void run(String[] args) throws Exception {
services = new Hashtable<String,AlignmentServiceProfile>(); services = new Vector<AlignmentServiceProfile>();
directories = new Hashtable<String,Directory>(); directories = new Hashtable<String,Directory>();
// Read parameters // Read parameters
...@@ -173,11 +175,11 @@ public class AlignmentService extends CommonCLI { ...@@ -173,11 +175,11 @@ public class AlignmentService extends CommonCLI {
logger.debug("Manager created"); logger.debug("Manager created");
// Launch services // Launch services
for ( AlignmentServiceProfile serv : services.values() ) { for ( AlignmentServiceProfile serv : services ) {
try { try {
serv.init( parameters, manager ); serv.init( parameters, manager );
} catch ( AServException ex ) { // This should rather be the job of the caller } 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"); logger.debug("Services launched");
...@@ -196,6 +198,17 @@ public class AlignmentService extends CommonCLI { ...@@ -196,6 +198,17 @@ public class AlignmentService extends CommonCLI {
} }
logger.debug("Directories registered"); 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 // Wait loop
logger.info("Alignment server running"); logger.info("Alignment server running");
while ( true ) { while ( true ) {
...@@ -206,6 +219,8 @@ public class AlignmentService extends CommonCLI { ...@@ -206,6 +219,8 @@ public class AlignmentService extends CommonCLI {
protected void close(){ protected void close(){
logger.debug("Shuting down server"); logger.debug("Shuting down server");
// Disable transport
if ( transport != null ) transport.close();
// [Directory]: unregister to directories // [Directory]: unregister to directories
for ( Directory dir : directories.values() ) { for ( Directory dir : directories.values() ) {
try { dir.close(); } try { dir.close(); }
...@@ -215,7 +230,7 @@ public class AlignmentService extends CommonCLI { ...@@ -215,7 +230,7 @@ public class AlignmentService extends CommonCLI {
} }
} }
// Close services // Close services
for ( AlignmentServiceProfile serv : services.values() ) { for ( AlignmentServiceProfile serv : services ) {
try { serv.close(); } try { serv.close(); }
catch ( AServException ex ) { catch ( AServException ex ) {
logger.debug("Cannot close {}", serv); logger.debug("Cannot close {}", serv);
...@@ -258,7 +273,7 @@ public class AlignmentService extends CommonCLI { ...@@ -258,7 +273,7 @@ public class AlignmentService extends CommonCLI {
if ( line.hasOption( 'i' ) ) { /* external service */ if ( line.hasOption( 'i' ) ) { /* external service */
String arg = line.getOptionValue( 'i' ); String arg = line.getOptionValue( 'i' );
try { try {
services.put( arg, (AlignmentServiceProfile)loadInstance( arg ) ); services.add( (AlignmentServiceProfile)loadInstance( arg ) );
} catch (Exception ex) { } catch (Exception ex) {
logger.warn( "Cannot create service for {}", arg ); logger.warn( "Cannot create service for {}", arg );
logger.debug( "IGNORED Exception", ex ); logger.debug( "IGNORED Exception", ex );
...@@ -269,7 +284,7 @@ public class AlignmentService extends CommonCLI { ...@@ -269,7 +284,7 @@ public class AlignmentService extends CommonCLI {
parameters.setProperty( "http", line.getOptionValue( 'H', HTML ) ); parameters.setProperty( "http", line.getOptionValue( 'H', HTML ) );
// This shows that it does not work // This shows that it does not work
try { 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) { } catch (Exception ex) {
logger.warn( "Cannot create service for HTMLAServProfile", ex ); logger.warn( "Cannot create service for HTMLAServProfile", ex );
} }
...@@ -277,19 +292,19 @@ public class AlignmentService extends CommonCLI { ...@@ -277,19 +292,19 @@ public class AlignmentService extends CommonCLI {
if ( line.hasOption( 'A' ) ) { if ( line.hasOption( 'A' ) ) {
parameters.setProperty( "jade", line.getOptionValue( 'A', JADE ) ); parameters.setProperty( "jade", line.getOptionValue( 'A', JADE ) );
try { 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 ) { } catch ( Exception ex ) {
logger.warn("Cannot create service for JadeFIPAAServProfile", ex); logger.warn("Cannot create service for JadeFIPAAServProfile", ex);
} }
} }
if ( line.hasOption( 'W' ) ) { if ( line.hasOption( 'W' ) ) {
parameters.setProperty( "wsdl", line.getOptionValue( 'W', WSDL ) ); 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 // Put the default port, may be overriden
if ( parameters.getProperty( "http" ) == null ) if ( parameters.getProperty( "http" ) == null )
parameters.setProperty( "http", HTML ); parameters.setProperty( "http", HTML );
try { 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 ) { } catch ( Exception ex ) {
logger.warn( "Cannot create service for Web services", ex ); logger.warn( "Cannot create service for Web services", ex );
} }
......
/* /*
* $Id$ * $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 * This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License * modify it under the terms of the GNU Lesser General Public License
...@@ -30,6 +30,16 @@ public interface AlignmentServiceProfile { ...@@ -30,6 +30,16 @@ public interface AlignmentServiceProfile {
*/ */
public void init( Properties p, AServProtocolManager m ) throws AServException; 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 * Shutdown the Service and undeclare it from any registery
*/ */
......
...@@ -55,349 +55,56 @@ import java.util.Map; ...@@ -55,349 +55,56 @@ import java.util.Map;
import java.net.URI; import java.net.URI;
import java.net.URISyntaxException; 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 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.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
/** /**
* HTMLAServProfile: an HTML provile for the Alignment server * HTMLAServProfile: an HTML provile for the Alignment server
* It embeds an HTTP server.
*/ */
public class HTMLAServProfile implements AlignmentServiceProfile { public class HTMLAServProfile implements AlignmentServiceProfile {
final static Logger logger = LoggerFactory.getLogger( HTMLAServProfile.class ); final static Logger logger = LoggerFactory.getLogger( HTMLAServProfile.class );
private int tcpPort;
private String tcpHost;
private Server server;
private AServProtocolManager manager; private AServProtocolManager manager;
private WSAServProfile wsmanager;
private String myId; private String myId;
private String serverId; private String serverId;
private int localId = 0; private int localId = 0;
/** private int newId() { return localId++; }
* 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;
public static final int MAX_FILE_SIZE = 10000; 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>"; 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 { public void init( Properties params, AServProtocolManager manager ) throws AServException {
this.manager = manager; 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 public boolean accept( String prefix ) {
try { server.start(); } if ( prefix.equals("admin") || prefix.equals("html") ) return true;
catch (Exception e) { else return false;
throw new AServException( "Cannot launch HTTP Server" , e ); }
}
//server.join();
// ******************************************************************** public String process( String uri, String prefix, String perf, Properties header, Properties params ) {
if ( params.getProperty( "wsdl" ) != null ){ if ( prefix.equals("html") ) {
wsmanager = new WSAServProfile(); return htmlAnswer( uri, perf, header, params );
if ( wsmanager != null ) wsmanager.init( params, manager ); } else if ( prefix.equals("admin") ) {
} return adminAnswer( uri, perf, header, params );
myId = "LocalHTMLInterface"; } else return about();
serverId = manager.serverURL();
logger.info( "Launched on {}/html/", serverId );
localId = 0;
} }
public void close(){ 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 // API parts
// ================================================== // ==================================================
/** protected static String about() {
* 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() {
return "<h1>Alignment server</h1><center>"+AlignmentService.class.getPackage().getImplementationTitle()+" "+AlignmentService.class.getPackage().getImplementationVersion()+"<br />" return "<h1>Alignment server</h1><center>"+AlignmentService.class.getPackage().getImplementationTitle()+" "+AlignmentService.class.getPackage().getImplementationVersion()+"<br />"
+ "<center><a href=\"html/\">Access</a></center>" + "<center><a href=\"html/\">Access</a></center>"
+ "(C) INRIA, 2006-2014<br />" + "(C) INRIA, 2006-2014<br />"
...@@ -409,7 +116,7 @@ public class HTMLAServProfile implements AlignmentServiceProfile { ...@@ -409,7 +116,7 @@ public class HTMLAServProfile implements AlignmentServiceProfile {
* HTTP administration interface * HTTP administration interface
* Allows some limited administration of the server through HTTP * 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); //logger.trace( "ADMIN[{}]", perf);
String msg = ""; String msg = "";
if ( perf.equals("listmethods") ){ if ( perf.equals("listmethods") ){
...@@ -436,11 +143,7 @@ public class HTMLAServProfile implements AlignmentServiceProfile { ...@@ -436,11 +143,7 @@ public class HTMLAServProfile implements AlignmentServiceProfile {
// JE: This is unused because the menu below directly refers to /wsdl // 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 // This does not really work because the wsdl is hidden in the HTML
} else if ( perf.equals("wsdl") ){ } else if ( perf.equals("wsdl") ){
if ( wsmanager != null ){ msg = "<pre>"+WSAServProfile.wsdlAnswer( false )+"</pre>";
msg = "<pre>"+WSAServProfile.wsdlAnswer( false )+"</pre>";
} else {
msg = "Error: the server does not have Web service capabilities (use -W switch)";
}
} else if ( perf.equals("argline") ){ } else if ( perf.equals("argline") ){
msg = "<h1>Command line arguments</h1>\n<pre>\n"+manager.argline()+"\n<pre>\n"; msg = "<h1>Command line arguments</h1>\n<pre>\n"+manager.argline()+"\n<pre>\n";
} else if ( perf.equals("prmsqlquery") ){ } else if ( perf.equals("prmsqlquery") ){
...@@ -468,8 +171,7 @@ public class HTMLAServProfile implements AlignmentServiceProfile { ...@@ -468,8 +171,7 @@ public class HTMLAServProfile implements AlignmentServiceProfile {
} else if ( perf.equals("") ) { } else if ( perf.equals("") ) {
msg = "<h1>Alignment server administration</h1>"; msg = "<h1>Alignment server administration</h1>";
msg += "<form action=\"listmethods\"><button title=\"List embedded plug-ins\" type=\"submit\">Embedded classes</button></form>"; 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=\"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=\"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>"; 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 { ...@@ -479,30 +181,14 @@ public class HTMLAServProfile implements AlignmentServiceProfile {
} else { } else {
msg = "Cannot understand: "+perf; 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>" ); return "<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() );
}
} }
/** /**
* User friendly HTTP interface * User friendly HTTP interface
* uses the protocol but offers user-targeted interaction * 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 ); //logger.trace("HTML[{}]", perf );
// REST get // REST get
String msg = ""; String msg = "";
...@@ -747,7 +433,7 @@ public class HTMLAServProfile implements AlignmentServiceProfile { ...@@ -747,7 +433,7 @@ public class HTMLAServProfile implements AlignmentServiceProfile {
} else { } else {
// Depending on the type we should change the MIME type // Depending on the type we should change the MIME type
// This should be returned in answer.getParameters() // This should be returned in answer.getParameters()
return new Response( HTTP_OK, MIME_HTML, answer.getContent() ); return answer.getContent();
} }
// Metadata not done yet // Metadata not done yet
} else if ( perf.equals("prmmetadata") ) { } else if ( perf.equals("prmmetadata") ) {
...@@ -771,7 +457,7 @@ public class HTMLAServProfile implements AlignmentServiceProfile { ...@@ -771,7 +457,7 @@ public class HTMLAServProfile implements AlignmentServiceProfile {
msg = testErrorMessages( answer, params ); msg = testErrorMessages( answer, params );
} else { } else {
// Depending on the type we should change the MIME type // Depending on the type we should change the MIME type
return new Response( HTTP_OK, MIME_HTML, answer.getContent() ); return answer.getContent();
} }
// render // render
// Alignment in HTML can be rendre or metadata+tuples // Alignment in HTML can be rendre or metadata+tuples
...@@ -905,29 +591,30 @@ public class HTMLAServProfile implements AlignmentServiceProfile { ...@@ -905,29 +591,30 @@ public class HTMLAServProfile implements AlignmentServiceProfile {
} else { } else {
msg = "Cannot understand command "+perf; 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 // 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 ) { private String testErrorMessages( Message answer, Properties param ) {
if ( returnType == MIME_RDFXML ) { /*
if ( returnType == HTTPResponse.MIME_RDFXML ) {
return answer.RESTString(); return answer.RESTString();
} else if ( returnType == MIME_JSON ) { } else if ( returnType == HTTPResponse.MIME_JSON ) {
return answer.JSONString(); return answer.JSONString();
} else { } else {*/
return "<h1>Alignment error</h1>"+answer.HTMLString(); return "<h1>Alignment error</h1>"+answer.HTMLString();
} /*}*/
} }
private String displayAnswer( Message answer, Properties param ) { private String displayAnswer( Message answer, Properties param ) {
return displayAnswer( answer, param, null );
}
private String displayAnswer( Message answer, Properties param, String returnType ) {
String result = null; String result = null;
if ( returnType == MIME_RDFXML ) { if ( returnType == HTTPResponse.MIME_RDFXML ) {
if( param.getProperty("return").equals("HTML") ) { // RESTFUL but in HTML ?? if( param.getProperty("return").equals("HTML") ) { // RESTFUL but in HTML ??
result = answer.HTMLRESTString(); result = answer.HTMLRESTString();
if ( answer instanceof AlignmentId && ( answer.getParameters() == null || answer.getParameters().getProperty("async") == null ) ) { if ( answer instanceof AlignmentId && ( answer.getParameters() == null || answer.getParameters().getProperty("async") == null ) ) {
...@@ -941,7 +628,7 @@ public class HTMLAServProfile implements AlignmentServiceProfile { ...@@ -941,7 +628,7 @@ public class HTMLAServProfile implements AlignmentServiceProfile {
} else { } else {
result = answer.RESTString(); result = answer.RESTString();
} }
} else if ( returnType == MIME_JSON ) { } else if ( returnType == HTTPResponse.MIME_JSON ) {
result = answer.JSONString(); result = answer.JSONString();
} else { } else {
result = answer.HTMLString(); result = answer.HTMLString();
...@@ -969,121 +656,5 @@ public class HTMLAServProfile implements AlignmentServiceProfile { ...@@ -969,121 +656,5 @@ public class HTMLAServProfile implements AlignmentServiceProfile {
return result; 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() );
}
}
}
} }
/*
* $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; }
}
/*
* $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() );
}
}
}
}
/* /*
* $Id$ * $Id$
* *
* Copyright (C) INRIA, 2007-2013 * Copyright (C) INRIA, 2007-2014
* *
* This program is free software; you can redistribute it and/or * This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License * modify it under the terms of the GNU Lesser General Public License
...@@ -90,6 +90,8 @@ public class WSAServProfile implements AlignmentServiceProfile { ...@@ -90,6 +90,8 @@ public class WSAServProfile implements AlignmentServiceProfile {
private AServProtocolManager manager; private AServProtocolManager manager;
private static String wsdlSpec = ""; private static String wsdlSpec = "";
private boolean restful = false;
private String myId; private String myId;
private String serverURL; private String serverURL;
private int localId = 0; private int localId = 0;
...@@ -184,6 +186,23 @@ public class WSAServProfile implements AlignmentServiceProfile { ...@@ -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(){ public void close(){
// This may unregister the WSDL file to some directory // This may unregister the WSDL file to some directory
} }
...@@ -204,7 +223,6 @@ public class WSAServProfile implements AlignmentServiceProfile { ...@@ -204,7 +223,6 @@ public class WSAServProfile implements AlignmentServiceProfile {
String message = null; String message = null;
Properties newparameters = null; Properties newparameters = null;
Message answer = null; Message answer = null;
boolean restful = (param.getProperty("restful")==null)?false:true;
String svcNS = "\n xml:base='"+Namespace.ALIGNSVC.prefix+"'"+ String svcNS = "\n xml:base='"+Namespace.ALIGNSVC.prefix+"'"+
"\n xmlns='"+Namespace.ALIGNSVC.prefix+"'"; "\n xmlns='"+Namespace.ALIGNSVC.prefix+"'";
String msg = ""; String msg = "";
...@@ -221,16 +239,19 @@ public class WSAServProfile implements AlignmentServiceProfile { ...@@ -221,16 +239,19 @@ public class WSAServProfile implements AlignmentServiceProfile {
// However, there is a way to pass SOAP messages with attachments // However, there is a way to pass SOAP messages with attachments
// It would be better to implement this. See: // It would be better to implement this. See:
// http://www.oracle.com/technology/sample_code/tech/java/codesnippet/webservices/attachment/index.html // 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 // Create the DOM tree for the SOAP message
Document domMessage = null; Document domMessage = null;
try { try {
domMessage = BUILDER.parse( new ByteArrayInputStream( message.getBytes()) ); domMessage = BUILDER.parse( new ByteArrayInputStream( message.trim().getBytes() ) );
} catch ( IOException ioex ) { } 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); answer = new NonConformParameters(0,(Message)null,myId,"Cannot Parse SOAP message",message,(Properties)null);
} catch ( SAXException saxex ) { } 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); answer = new NonConformParameters(0,(Message)null,myId,"Cannot Parse SOAP message",message,(Properties)null);
} }
newparameters = getParameters( domMessage ); newparameters = getParameters( domMessage );
...@@ -238,6 +259,7 @@ public class WSAServProfile implements AlignmentServiceProfile { ...@@ -238,6 +259,7 @@ public class WSAServProfile implements AlignmentServiceProfile {
newparameters = new Properties(); newparameters = new Properties();
} }
} }
//logger.debug( "Analised header" );
// Process the action // Process the action
if ( perf.equals("WSDL") || method.equals("wsdl") || method.equals("wsdlRequest") ) { if ( perf.equals("WSDL") || method.equals("wsdl") || method.equals("wsdlRequest") ) {
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* $Id$ * $Id$
* *
* Copyright (C) Orange R&D, 2006-2007 * 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 * This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License * modify it under the terms of the GNU Lesser General Public License
...@@ -41,63 +41,69 @@ import org.slf4j.LoggerFactory; ...@@ -41,63 +41,69 @@ import org.slf4j.LoggerFactory;
public class JadeFIPAAServProfile implements AlignmentServiceProfile { public class JadeFIPAAServProfile implements AlignmentServiceProfile {
final static Logger logger = LoggerFactory.getLogger( JadeFIPAAServProfile.class ); final static Logger logger = LoggerFactory.getLogger( JadeFIPAAServProfile.class );
private AgentContainer mc; private AgentContainer mc;
private AgentController algagentcontroller; private AgentController algagentcontroller;
public void init( Properties params, AServProtocolManager manager ) throws AServException { public void init( Properties params, AServProtocolManager manager ) throws AServException {
int port = 8888; int port = 8888;
Object args[] = new Object[2]; Object args[] = new Object[2];
//set up the manager as an argument to pass to the JADEFIPAAServiceAgent //set up the manager as an argument to pass to the JADEFIPAAServiceAgent
args[0]=manager; args[0]=manager;
// set up the Parameters as an argument to pass to the JADEFIPAServiceAgent // set up the Parameters as an argument to pass to the JADEFIPAServiceAgent
args[1]=params; args[1]=params;
if ( params.getProperty( "jade" ) != null ) if ( params.getProperty( "jade" ) != null )
port = Integer.parseInt( params.getProperty( "jade" ) ); port = Integer.parseInt( params.getProperty( "jade" ) );
/** // Properties props = new Properties();
Properties props = new Properties(); try {
**/ // Get a hold on JADE runtime
try { Runtime rt = Runtime.instance();
// Get a hold on JADE runtime
Runtime rt = Runtime.instance();
// Exit the JVM when there are no more containers around // Exit the JVM when there are no more containers around
rt.setCloseVM(true); rt.setCloseVM(true);
/** Profile with no MTP( Message Transfer Protocol /** Profile with no MTP( Message Transfer Protocol
props.setProperty("nomtp", "true"); props.setProperty("nomtp", "true");
Profile pMain = new ProfileImpl(props); Profile pMain = new ProfileImpl(props);
**/ **/
// create a default Profile // create a default Profile
Profile pMain = new ProfileImpl(null, port, null); Profile pMain = new ProfileImpl(null, port, null);
//logger.trace( "Launching a whole in-process platform... {}", pMain ); //logger.trace( "Launching a whole in-process platform... {}", pMain );
mc = rt.createMainContainer(pMain); mc = rt.createMainContainer(pMain);
algagentcontroller = mc.createNewAgent("JadeFIPAAServiceAgent", JadeFIPAAServiceAgent.class.getName(), args); algagentcontroller = mc.createNewAgent("JadeFIPAAServiceAgent", JadeFIPAAServiceAgent.class.getName(), args);
algagentcontroller.start(); algagentcontroller.start();
} } catch(Exception ex) {
catch(Exception e) { throw new AServException ( "Cannot launch Jade Server" , ex );
throw new AServException ( "Cannot launch Jade Server" , e );
}
} }
}
public void close(){ public boolean accept( String prefix ) {
try{ return false;
algagentcontroller.kill(); }
mc.kill();
logger.info( "Agent Alignement closed" ); public String process( String uri, String prefix, String perf, Properties header, Properties params ) {
} catch (ControllerException e) { return "JADE Cannot be invoked this way through HTTP service";
logger.warn( "Error killing the alignment agent." ); } }
try {
// Destroy the files please (JE) public void close(){
new File("APDescription.txt").delete(); try{
new File("MTPs-Main-Container.txt").delete(); algagentcontroller.kill();
} catch (Exception e) { mc.kill();
logger.debug( "IGNORED Exception", e ); 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 );
}
}
} }
/* /*
* $Id$ * $Id$
* *
* Copyright (C) INRIA, 2010, 2013 * Copyright (C) INRIA, 2010, 2013-2014
* *
* This program is free software; you can redistribute it and/or * This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License * modify it under the terms of the GNU Lesser General Public License
...@@ -56,6 +56,14 @@ public class OSGIAServProfile implements AlignmentServiceProfile, BundleActivato ...@@ -56,6 +56,14 @@ public class OSGIAServProfile implements AlignmentServiceProfile, BundleActivato
this.manager = manager; 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(){ public void close(){
// This may unregister the WSDL file to some directory // This may unregister the WSDL file to some directory
stop( ctxt ); stop( ctxt );
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment