[MOBY-guts] biomoby commit

Paul Gordon gordonp at dev.open-bio.org
Thu Feb 14 03:04:44 UTC 2008


gordonp
Wed Feb 13 22:04:44 EST 2008
Update of /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/services
In directory dev.open-bio.org:/tmp/cvs-serv19467/src/main/ca/ucalgary/services

Modified Files:
	ACDService.java CGIService.java 
Added Files:
	LegacyService.java 
Log Message:
Initial commit of CGIService, including ACDServlet refactor causing LegacyService addition
moby-live/Java/src/main/ca/ucalgary/services LegacyService.java,NONE,1.1 ACDService.java,1.9,1.10 CGIService.java,1.1,1.2
===================================================================
RCS file: /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/services/ACDService.java,v
retrieving revision 1.9
retrieving revision 1.10
diff -u -r1.9 -r1.10
--- /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/services/ACDService.java	2008/01/07 22:06:47	1.9
+++ /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/services/ACDService.java	2008/02/14 03:04:44	1.10
@@ -24,29 +24,19 @@
  * stylesheet.  EMBOSS results are conveted to MOBY datatypes using some
  * built-in heuristics.
  */
-public class ACDService extends MobyServlet{
+public class ACDService extends LegacyService{
     // Used for web.xml configuration
     public final static String EMBOSS_ROOT_PARAM = "embossRoot";
     public final static String EMBOSS_PARAMS_PARAM = "embossParams";
     public final static String EMBOSS_ADV_PARAMS_PARAM = "embossUseAdvancedParams";
     public final static String EMBOSS_OUTPUT_PARAM = "embossOutput";
     public final static String ACD_FILE_PARAM = "acdFile";    
-    public final static String ACD_RULES_LOCATION_PARAM = "regexRulesLoc";
-    public final static String MOBY_RULES_LOCATION_PARAM = "xsltRulesLoc";
-    public final static String ACD_RULES_DEFAULT_RESOURCE = "ca/ucalgary/services/resources/acdRules.xml";
-    public final static String MOBY_RULES_DEFAULT_RESOURCE = "ca/ucalgary/services/resources/mobyRules.xsl";
 
     // Used for program execution
     private File programBinaryFile;
     private String embossRootDirName;
     private String acdRootDirName;
 
-    // For converting unstructured dats to MOBY data
-    private MobyClient mobyClient;
-    // For converting MOBY data to plain-text representation
-    private TextClient textClient;
-    private MobyDataType binaryDataType;
-
     // Keep track of what MOBY input parameters are to be converted to what ACD types
     private Map<String,String> acdTypes;
     private Map<String,String> acdBasicTypes;  //holds e.g. string, when acdType for same key is "nucleotide sequence"
@@ -104,13 +94,7 @@
 	    }
 
 	    // Transform the bits of binary data into a MOBY object or collection
-	    MobyDataInstance mdi = null;
-	    try{
-		mdi = mobyClient.getMobyObject(resultParts, mobyOutputTemplate);
-	    } catch(MobyServiceException mse){
-		//getMobyObject() throws untransformed-data warnings
-		addException(mse);
-	    }
+	    MobyDataInstance mdi = getMobyData(resultParts, mobyOutputTemplate);
 	    if(mdi == null){
 		throw new MobyServiceException(MobyServiceException.WARNING, 
 					       MobyServiceException.INTERNAL_PROCESSING_ERROR, 
@@ -144,24 +128,18 @@
 	    // Retrieve the input with the same name as the service template specifies
 	    String paramName = mobyInputTemplate.getName();
 	    MobyDataInstance inputData = request.get(paramName);
-	    byte[] inputDataBytes = null;
 
 	    // Transform the moby data to text, unless it's binary data, which will be passed as decoded bytes
 	    // Now, for binary data, we have to ignore any fields other than the Base64 encoded one.  Sorry!
 	    String tempFileSuffix = ".txt";
 	    if(inputData instanceof MobyDataBytes){
-		//System.err.println("Passing binary data to service");
-		inputDataBytes = ((MobyDataBytes) inputData).getBytes();
 		tempFileSuffix = ".bin";
 	    }
-	    else{
-		String inputTextData = textClient.getText(inputData, acdTypes.get(mobyInputTemplate.getName()));
-		if(inputTextData == null){
-		    throw new NullPointerException("The TextClient returned null after transforming the " +
-						   "input parameter "  + mobyInputTemplate.getName() + 
-						   " to text type " + acdTypes.get(mobyInputTemplate.getName()));
-		}
-		inputDataBytes = inputTextData.getBytes();
+	    byte[] inputDataBytes = getLegacyData(inputData, acdTypes.get(mobyInputTemplate.getName()));
+	    if(inputDataBytes == null){
+		throw new NullPointerException("The TextClient returned null after transforming the " +
+					       "input parameter "  + mobyInputTemplate.getName() + 
+					       " to text type " + acdTypes.get(mobyInputTemplate.getName()));
 	    }
 
 	    // Create the required command-line flag for the parameter
@@ -527,106 +505,6 @@
 	}
 	acdRootDirName = acdFile.getParent();
 
-	URL regexRulesURL = null;
-	if(getCoCInitParameter(ACD_RULES_LOCATION_PARAM) != null){
-	    String rulesLocationName = getCoCInitParameter(ACD_RULES_LOCATION_PARAM);
-	    if(rulesLocationName.length() == 0){
-		throw new Exception("Parameter " + ACD_RULES_LOCATION_PARAM + 
-				    " was blank in the servlet configuration (please " +
-				    "either comment it out, or fill in a value)");
-	    }
-	    
-	    // Is it a URL or a file location?
-	    try{
-		regexRulesURL = new URL(rulesLocationName);
-	    }
-	    catch(Exception e){
-		// Not a properly formatted URL
-		File rulesFile = new File(rulesLocationName);
-		if(rulesFile.exists()){
-		    if(!rulesFile.isFile()){
-			throw new Exception("The rules file inferred from the servlet " +
-					    "configuration (" + rulesFile.getPath() + 
-					    ") exists, but is not a file, as expected");
-		    }
-		    regexRulesURL = rulesFile.toURI().toURL();
-		}
-	    }
-	    // Last ditch, try to get it as a resource
-	    if(regexRulesURL == null){
-		regexRulesURL = getClass().getClassLoader().getResource(rulesLocationName);
-	    }
-
-	    if(regexRulesURL == null){
-		log("Could not find the specified data mapping rules (" + rulesLocationName +
-                    ") as a file, URL or resource, falling back on the default " +
-		    "mapping file included with the servlet");
-            }
-	}
-	// Either no file was specified, or the specified one was not found
-	if(regexRulesURL == null){
-	    regexRulesURL = getClass().getClassLoader().getResource(ACD_RULES_DEFAULT_RESOURCE);
-	}
-	if(regexRulesURL == null){
-	    throw new Exception("The data mapping rules location " + ACD_RULES_DEFAULT_RESOURCE + 
-				") could not be resolved to an existing Java resource");
-	}
-
-	URL xsltRulesURL = null;
-	if(getCoCInitParameter(MOBY_RULES_LOCATION_PARAM) != null){
-	    String rulesLocationName = getCoCInitParameter(MOBY_RULES_LOCATION_PARAM);
-	    if(rulesLocationName.length() == 0){
-		throw new Exception("Parameter " + MOBY_RULES_LOCATION_PARAM + 
-				    " was blank in the servlet configuration (please " +
-				    "either comment it out, or fill in a value)");
-	    }
-	    
-	    // Is it a URL or a file location?
-	    try{
-		xsltRulesURL = new URL(rulesLocationName);
-	    }
-	    catch(Exception e){
-		// Not a properly formatted URL
-		File rulesFile = new File(rulesLocationName);
-		if(rulesFile.exists()){
-		    if(!rulesFile.isFile()){
-			throw new Exception("The XSLT rules file inferred from the servlet " +
-					    "configuration (" + rulesFile.getPath() + 
-					    ") exists, but is not a file, as expected");
-		    }
-		    xsltRulesURL = rulesFile.toURI().toURL();
-		}
-	    }
-	    // Last ditch, try to get it as a resource
-	    if(xsltRulesURL == null){
-		xsltRulesURL = getClass().getClassLoader().getResource(rulesLocationName);
-	    }
-
-	    if(xsltRulesURL == null){
-		log("Could not find the specified XSLT mapping rules (" + rulesLocationName +
-                    ") as a file, URL or resource, falling back on the default " +
-		    "mapping file included with the servlet");
-            }
-	}
-	// Either no file was specified, or the specified one was not found
-	if(xsltRulesURL == null){
-	    xsltRulesURL = getClass().getClassLoader().getResource(MOBY_RULES_DEFAULT_RESOURCE);
-	}
-	if(xsltRulesURL == null){
-	    throw new Exception("The XSLT mapping rules location " + MOBY_RULES_DEFAULT_RESOURCE + 
-				") could not be resolved to an existing Java resource");
-	}
-
-	// Instantiate the string -> MOBY data mapping engine
-	// Load up the rules we can use for data mapping
-	// Could fail from bad XML, non-existent or unreachable URL, etc.
-	System.setProperty(MobyClient.RESOURCE_SYSTEM_PROPERTY, regexRulesURL.toString());
-	mobyClient = new MobyClient(registry);
-
-	// Instantiate the MOBY data -> string mapping engine
-	textClient = new TextClient();
-	textClient.addMappingsFromURL(xsltRulesURL);
-
 	boolean useAdvancedParams = Boolean.parseBoolean(getCoCInitParameter(EMBOSS_ADV_PARAMS_PARAM));
 
 	// All the parameters have been specified correctly, now check the ACD file
@@ -684,8 +562,6 @@
 				    " pattern (" + specs[1] + "):" + e);
 	    }	    
 	}
-
-	binaryDataType = MobyDataType.getDataType(MobyDataBytes.BASE64_DATATYPE, registry);
 	
 	return service;
     }
@@ -774,8 +650,8 @@
 		    continue;
 		}
 
-		if(!textClient.canProduceTextTypeFromMoby(acdTypes.get(acdInputName), 
-							  (MobyPrimaryData) mobyPrimaryInput)){
+		if(!canProduceTextTypeFromMoby(acdTypes.get(acdInputName), 
+					       (MobyPrimaryData) mobyPrimaryInput)){
 		    throw new Exception("No XSLT rules exist that can produce the requested " +
 					"text type '" + acdTypes.get(acdInputName) + 
 					"' (acd input parameter " + acdInputName + 
@@ -841,9 +717,10 @@
 	Map<String,MobyPrimaryData> paramUsed = new HashMap<String,MobyPrimaryData>();
 
 	for(MobyPrimaryData mobyPrimaryOutput: service.getPrimaryOutputs()){
-	    if(!mobyClient.canProduceDataTypeFromString(mobyPrimaryOutput.getDataType())){
+	    if(!canProduceDataTypeFromString(mobyPrimaryOutput.getDataType())){
 		throw new Exception("No data mapping rules exist that can produce the requested " +
-				    "data type (" + mobyPrimaryOutput.getDataType().getName() + ") from plain text");
+				    "data type (" + mobyPrimaryOutput.getDataType().getName() + 
+				    ") from plain text");
 	    }
 	    paramUsed.put(mobyPrimaryOutput.getName(), mobyPrimaryOutput);
 	}

===================================================================
RCS file: /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/services/CGIService.java,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/services/CGIService.java	2008/02/12 09:01:04	1.1
+++ /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/services/CGIService.java	2008/02/14 03:04:44	1.2
@@ -6,6 +6,13 @@
 import org.biomoby.shared.*;
 import org.biomoby.shared.data.*;
 
+import org.apache.commons.httpclient.*;
+import org.apache.commons.httpclient.methods.*;
+import org.apache.commons.httpclient.methods.multipart.*;
+import org.apache.commons.httpclient.params.*;
+import org.apache.commons.httpclient.util.URIUtil;
+
+import java.io.*;
 import java.net.URL;
 import java.util.*;
 
@@ -15,7 +22,7 @@
  * publishing, etc.  The service description fetching, and the command invocation
  * are overridden.
  */
-public class CGIService extends MobyServlet{
+public class CGIService extends LegacyService{
     protected URL remoteFormURL;
     // params that override annoation and servlet context/config params
     protected Map<String,String> cgiConfig; 
@@ -23,8 +30,12 @@
     // mobyParamName -> form fields that used a transformed version of it
     protected Map<String,String[]> mobyPrimary2FormFields;
     protected Map<String,String[]> mobySecondary2FormFields;
-    
+
+    protected HttpClient httpClient;
+    protected MultiThreadedHttpConnectionManager connectionManager; 
+
     public static final String HTML_FORM_URL_PARAM = "htmlFormURL";
+    public static final String CGISERVICE_USERAGENT_NAME = "BioMoby CGIService Servlet";
 
     public void init(){
 	super.init();
@@ -32,29 +43,115 @@
 	cgiConfig = new HashMap<String,String>();
 	mobyPrimary2FormFields = new HashMap<String,String[]>();
 	mobySecondary2FormFields = new HashMap<String,String[]>();
+
+	HttpClientParams params = new HttpClientParams();
+	params.setParameter("http.useragent", CGISERVICE_USERAGENT_NAME);
+	// Make sure we use a thread-safe client, because there can be
+	// concurrent calls to processRequest() below.
+	connectionManager = new MultiThreadedHttpConnectionManager();
+	httpClient = new HttpClient(params, connectionManager);
     }
 
     public void processRequest(MobyDataJob request, MobyDataJob result) throws Exception{
 	MobyService service = getService();
+	// name -> text or binary data
+	Map<String,byte[]> formDataInstanceMap = new HashMap<String,byte[]>();
 
-	// reformat data and send the request via HTTP
+	// Reformat data into format needed by http client
+	for(Map.Entry<String,String> fixedParam: formConfig.getFixedParams().entrySet()){
+	    formDataInstanceMap.put(fixedParam.getKey(), fixedParam.getValue().getBytes());
+	}
+
+	Map<String,String> textFormats = formConfig.getPrimaryInputFormats();
 	for(MobyPrimaryData mobyInputTemplate: service.getPrimaryInputs()){
 	    // Retrieve the input with the same name as the service template specifies
 	    String paramName = mobyInputTemplate.getName();
-	    MobyDataInstance inputData = request.get(paramName);
-
+	    MobyDataInstance mobyData = request.get(paramName);
+	    if(!(mobyData instanceof MobyDataObject) &&
+	       !(mobyData instanceof MobyDataObjectSet)){
+		throw new MobyException("The Moby parameter '" + paramName + 
+					"' is not a priary input as expected (" +
+					"found " + mobyData.getClass().getName() + ")");
+	    }
+	    
+	    // Transform the moby data as required and put it in the form
+	    for(String formFieldName: mobyPrimary2FormFields.get(paramName)){
+		formDataInstanceMap.put(formFieldName,
+				        getLegacyData(mobyData,
+						      textFormats.get(formFieldName)));
+	    }
 	}
 	for(MobySecondaryData mobySecondaryTemplate: service.getSecondaryInputs()){
 	    // Retrieve the input with the same name as the service template specifies
 	    String paramName = mobySecondaryTemplate.getName();
-	    MobyDataInstance inputData = request.get(paramName);
+	    MobyDataInstance mobyData = request.get(paramName);
+	    if(!(mobyData instanceof MobyDataSecondaryInstance)){
+		throw new MobyException("The Moby parameter '" + paramName + 
+					"' is not a secondary as expected (" +
+					"found " + mobyData.getClass().getName() + ")");
+	    }
+
+	    for(String formFieldName: mobySecondary2FormFields.get(paramName)){
+		// TODO: check that the value passed in was acceptable?
+		formDataInstanceMap.put(formFieldName, 
+					((MobyDataSecondaryInstance) mobyData).getValue().getBytes());
+	    }
+	}
+
+	HttpMethod method;
+	if("POST".equals(formConfig.getFormMethod())){
+	    method = new PostMethod(formConfig.getFormAction());
+	    if(XHTMLForm.MULTIPART.toLowerCase().equals(
+			 formConfig.getFormEncodingType().toLowerCase())){
+		((PostMethod) method).setRequestEntity(getMultipartRequest(formDataInstanceMap, 
+									   method.getParams()));
+	    }
+	    else{
+		((PostMethod) method).setRequestBody(getNameValuePairs(formDataInstanceMap));
+	    }
+	}
+	// If not POST, assume GET
+	else{
+	    method = new GetMethod(formConfig.getFormAction()+"?"+getURLQuery(formDataInstanceMap));
+	}
 
+	int statusCode;
+	byte[] responseBody;
+	// Send the request via HTTP
+	try {
+	    // Execute the method
+	    statusCode = httpClient.executeMethod(method);
+	    
+	    // Read the response body
+	    responseBody = method.getResponseBody();
+
+	} catch (HttpException he) {
+	    System.err.println("Fatal protocol violation: " + he.getMessage());
+	    throw he;
+	} catch (IOException ioe) {
+	    System.err.println("Fatal transport error: " + ioe.getMessage());
+	    throw ioe;
+	} finally {
+	    // Release the connection.
+	    method.releaseConnection();
 	}
-	Map <String,String> fixedFormParams = formConfig.getFixedParams();
 
+	if (statusCode != HttpStatus.SC_OK) {
+	    throw new Exception("HTTP CGI call failed: " + method.getStatusLine());
+	}
+	    
 	// parse the results
+	Map<String,byte[]> responseData = new HashMap<String,byte[]>();
+	responseData.put("response", responseBody);
 	for(MobyPrimaryData mobyOutputTemplate: service.getPrimaryOutputs()){
-
+	    MobyDataInstance mdi = getMobyData(responseData, mobyOutputTemplate);
+	    if(mdi == null){
+		throw new Exception("The output parameter '" + mobyOutputTemplate.getName() + 
+				    "' of data type '" + mobyOutputTemplate.getDataType().getName() + 
+				    "' could not be created from the form submission response (" +
+				    "TextClient returned null transforming the legacy data).");
+	    }
+	    result.put(mobyOutputTemplate.getName(), mdi);
 	}
     }
 
@@ -125,11 +222,49 @@
 	// Determine secondary parameters
 	setCoCInitParameter(MOBY_SECONDARYINPUT_PARAM, createSecondarySpecString(formConfig));
 
-	// Determine fixed submission values
-
+	// Set up reusable http client objects
 	return super.createServiceFromConfig(request);
     }
 
+    protected MultipartRequestEntity getMultipartRequest(Map<String,byte[]> dataInstances, 
+							 HttpMethodParams params){
+	Part[] parts = new Part[dataInstances.size()];
+	List<String> fileTypeInputs = formConfig.getFormFiles();
+	int i = 0;
+	for(Map.Entry<String,byte[]> formInput: dataInstances.entrySet()){
+	    String formInputName = formInput.getKey();
+	    if(fileTypeInputs.contains(formInputName)){
+		parts[i++] = new FilePart(formInputName, 
+					  new ByteArrayPartSource(formInputName, 
+								  formInput.getValue()));
+	    }
+	    else{
+		parts[i++] = new StringPart(formInputName, new String(formInput.getValue()));
+	    }
+	}
+	return new MultipartRequestEntity(parts, params);
+    }
+
+    protected NameValuePair[] getNameValuePairs(Map<String,byte[]> dataInstances){
+	NameValuePair[] data = new NameValuePair[dataInstances.size()];
+	int i = 0;
+	for(Map.Entry<String,byte[]> formField: dataInstances.entrySet()){
+	    data[i++] = new NameValuePair(formField.getKey(), 
+					  new String(formField.getValue()));
+	}
+	return data;
+    }
+
+    protected String getURLQuery(Map<String,byte[]> dataInstances) throws URIException{
+	String[] queryItems = new String[dataInstances.size()];
+	int i = 0;
+	for(Map.Entry<String,byte[]> formField: dataInstances.entrySet()){
+	    queryItems[i++] = URIUtil.encodeWithinQuery(formField.getKey()) + "=" + 
+		URIUtil.encodeWithinQuery(new String(formField.getValue()));
+	}
+	return XHTMLForm.join("+", queryItems);
+    }
+
     protected String getCoCInitParameter(String paramName){
 	javax.servlet.ServletConfig config = getServletConfig();
 	if(cgiConfig.containsKey(paramName)){




More information about the MOBY-guts mailing list