[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