+/*
+ * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
+ * Copyright (C) $$Year-Rel$$ The Jalview Authors
+ *
+ * This file is part of Jalview.
+ *
+ * Jalview is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, either version 3
+ * of the License, or (at your option) any later version.
+ *
+ * Jalview 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Jalview. If not, see <http://www.gnu.org/licenses/>.
+ * The Jalview Authors are detailed in the 'AUTHORS' file.
+ */
package jalview.ws.rest;
import jalview.bin.Cache;
import jalview.datamodel.AlignmentI;
import jalview.datamodel.AlignmentOrder;
import jalview.datamodel.Annotation;
-import jalview.datamodel.ColumnSelection;
+import jalview.datamodel.HiddenColumns;
import jalview.datamodel.SequenceGroup;
import jalview.datamodel.SequenceI;
import jalview.gui.AlignFrame;
import jalview.io.NewickFile;
import jalview.io.packed.JalviewDataset;
import jalview.io.packed.JalviewDataset.AlignmentSet;
+import jalview.util.MessageManager;
import jalview.ws.AWSThread;
import jalview.ws.AWsJob;
import java.awt.event.ActionListener;
import java.io.IOException;
import java.util.ArrayList;
-import java.util.Enumeration;
import java.util.Hashtable;
import java.util.List;
import java.util.Map.Entry;
-import java.util.Vector;
import org.apache.axis.transport.http.HTTPConstants;
import org.apache.http.Header;
import org.apache.http.entity.mime.HttpMultipartMode;
import org.apache.http.entity.mime.MultipartEntity;
import org.apache.http.impl.client.DefaultHttpClient;
-import org.apache.http.protocol.BasicHttpContext;
-import org.apache.http.protocol.HttpContext;
import org.apache.http.util.EntityUtils;
public class RestJobThread extends AWSThread
{
jobs = new RestJob[1];
jobs[0] = new RestJob(0, this,
- restClient._input.getVisibleAlignment(restClient.service
- .getGapCharacter()),
+ restClient._input.getVisibleAlignment(
+ restClient.service.getGapCharacter()),
restClient._input.getVisibleContigs());
// need a function to get a range on a view/alignment and return both
// annotation, groups and selection subsetted to just that region.
{
int[] viscontig = restClient._input.getVisibleContigs();
AlignmentI[] viscontigals = restClient._input
- .getVisibleContigAlignments(restClient.service
- .getGapCharacter());
+ .getVisibleContigAlignments(
+ restClient.service.getGapCharacter());
if (viscontigals != null && viscontigals.length > 0)
{
jobs = new RestJob[viscontigals.length];
for (int j = 0; j < jobs.length; j++)
{
- int[] visc = new int[]
- { viscontig[j * 2], viscontig[j * 2 + 1] };
+ int[] visc = new int[] { viscontig[j * 2], viscontig[j * 2 + 1] };
if (j != 0)
{
jobs[j] = new RestJob(j, this, viscontigals[j], visc);
private String getStage(Stage stg)
{
if (stg == Stage.SUBMIT)
+ {
return "submitting ";
+ }
if (stg == Stage.POLL)
+ {
return "checking status of ";
+ }
return (" being confused about ");
}
protected void doHttpReq(Stage stg, RestJob rj, String postUrl)
throws Exception
{
- StringBuffer respText = new StringBuffer();
- // con.setContentHandlerFactory(new
- // jalview.ws.io.mime.HttpContentHandler());
HttpRequestBase request = null;
String messages = "";
if (stg == Stage.SUBMIT)
{
if (input.getValue().validFor(rj))
{
- postentity.addPart(input.getKey(), input.getValue()
- .formatForInput(rj));
+ postentity.addPart(input.getKey(),
+ input.getValue().formatForInput(rj));
}
else
{
{
DefaultHttpClient httpclient = new DefaultHttpClient();
- HttpContext localContext = new BasicHttpContext();
HttpResponse response = null;
try
{
response = httpclient.execute(request);
} catch (ClientProtocolException he)
{
- rj.statMessage = "Web Protocol Exception when attempting to "
- + getStage(stg) + "Job. See Console output for details.";
+ rj.statMessage = "Web Protocol Exception when " + getStage(stg)
+ + "Job. <br>Problematic url was <a href=\""
+ + request.getURI() + "\">" + request.getURI()
+ + "</a><br>See Console output for details.";
rj.setAllowedServerExceptions(0);// unrecoverable;
rj.error = true;
Cache.log.fatal("Unexpected REST Job " + getStage(stg)
throw (he);
} catch (IOException e)
{
- rj.statMessage = "IO Exception when attempting to "
- + getStage(stg) + "Job. See Console output for details.";
+ rj.statMessage = "IO Exception when " + getStage(stg)
+ + "Job. <br>Problematic url was <a href=\""
+ + request.getURI() + "\">" + request.getURI()
+ + "</a><br>See Console output for details.";
Cache.log.warn("IO Exception for REST Job " + getStage(stg)
+ "exception for URL " + rj.rsd.postUrl);
Cache.log.debug("Processing result set.");
processResultSet(rj, response, request);
break;
+
case 202:
- rj.statMessage = "<br>Job submitted successfully. Results available at this URL:\n"
- + "<a href="
- + rj.getJobId()
- + "\">"
- + rj.getJobId()
- + "</a><br>";
- rj.running = true;
+ markJobAsRunning(rj);
break;
+
+ case 201:
+ // Created - redirect may be present. Fallthrough to 302
case 302:
- Header[] loc;
- if (!rj.isSubmitted()
- && (loc = response
- .getHeaders(HTTPConstants.HEADER_LOCATION)) != null
- && loc.length > 0)
- {
- if (loc.length > 1)
- {
- Cache.log
- .warn("Ignoring additional "
- + (loc.length - 1)
- + " location(s) provided in response header ( next one is '"
- + loc[1].getValue() + "' )");
- }
- rj.setJobId(loc[0].getValue());
- rj.setSubmitted(true);
- }
+ extractJobId(rj, response);
completeStatus(rj, response);
break;
case 500:
- // Failed.
- rj.setSubmitted(true);
- rj.setAllowedServerExceptions(0);
- rj.setSubjobComplete(true);
- rj.error = true;
- rj.running = false;
+ markAsFailed(rj, response);
completeStatus(rj, response, "" + getStage(stg)
+ "failed. Reason below:\n");
break;
// TODO: deal with all other HTTP response codes from server.
Cache.log.warn("Unhandled response status when " + getStage(stg)
+ "for " + postUrl + ": " + response.getStatusLine());
+ rj.error = true;
+ rj.setAllowedServerExceptions(0);
+ rj.setSubjobComplete(true);
+ rj.setSubmitted(true);
try
{
- response.getEntity().consumeContent();
+ completeStatus(rj, response, "" + getStage(stg)
+ + " resulted in an unexpected server response.<br/>Url concerned was <a href=\""
+ + request.getURI() + "\">" + request.getURI()
+ + "</a><br/>Filtered response content below:<br/>");
} catch (IOException e)
{
Cache.log.debug("IOException when consuming unhandled response",
}
}
+ private void markAsFailed(RestJob rj, HttpResponse response)
+ {
+ // Failed.
+ rj.setSubmitted(true);
+ rj.setAllowedServerExceptions(0);
+ rj.setSubjobComplete(true);
+ rj.error = true;
+ rj.running = false;
+ }
+
+ /**
+ * set the jobRunning flag and post a link to the physical result page encoded
+ * in rj.getJobId()
+ *
+ * @param rj
+ */
+ private void markJobAsRunning(RestJob rj)
+ {
+ rj.statMessage = "<br>Job submitted successfully. Results available at this URL:\n"
+ + "<a href="
+ + rj.getJobId()
+ + "\">"
+ + rj.getJobId()
+ + "</a><br>";
+ rj.running = true;
+ }
+
+ /**
+ * extract the job ID URL from the redirect page. Does nothing if job is
+ * already running.
+ *
+ * @param rj
+ * @param response
+ */
+ private void extractJobId(RestJob rj, HttpResponse response)
+ {
+ Header[] loc;
+ if (!rj.isSubmitted())
+ {
+
+ // redirect URL - typical for IBIVU type jobs.
+ if ((loc = response.getHeaders(HTTPConstants.HEADER_LOCATION)) != null
+ && loc.length > 0)
+ {
+ if (loc.length > 1)
+ {
+ Cache.log
+ .warn("Ignoring additional "
+ + (loc.length - 1)
+ + " location(s) provided in response header ( next one is '"
+ + loc[1].getValue() + "' )");
+ }
+ rj.setJobId(loc[0].getValue());
+ rj.setSubmitted(true);
+ }
+ }
+ }
+
/**
* job has completed. Something valid should be available from con
*
int body = f.indexOf("<body");
if (body > -1)
{
- content.delete(0, f.indexOf(">", body));
+ content.delete(0, f.indexOf(">", body) + 1);
}
if (body > -1 && sb.length() > 0)
{
{
System.err.println("Debug RestJob: Posting Job");
doPost((RestJob) job);
- }
- catch (NoValidInputDataException erex)
+ } catch (NoValidInputDataException erex)
{
job.setSubjobComplete(true);
job.setSubmitted(true);
- ((RestJob)job).statMessage="<br>It looks like there was a problem with the data sent to the service :<br>"+erex.getMessage()+"\n";
- ((RestJob)job).error=true;
-
- }
- catch (Exception ex)
+ ((RestJob) job).statMessage = "<br>It looks like there was a problem with the data sent to the service :<br>"
+ + erex.getMessage() + "\n";
+ ((RestJob) job).error = true;
+
+ } catch (Exception ex)
{
job.setSubjobComplete(true);
job.setAllowedServerExceptions(-1);
} catch (Error ex)
{
- Cache.log.warn("Failed to finish parsing data for job "
- + rj.getJobId());
+ Cache.log.warn(
+ "Failed to finish parsing data for job " + rj.getJobId());
ex.printStackTrace();
} catch (Exception ex)
{
- Cache.log.warn("Failed to finish parsing data for job "
- + rj.getJobId());
+ Cache.log.warn(
+ "Failed to finish parsing data for job " + rj.getJobId());
ex.printStackTrace();
+ } finally
+ {
+ rj.error = true;
+ rj.statMessage = "Error whilst parsing data for this job.<br>URL for job response is :<a href=\""
+ + rj.resSet.getUrl() + "\">" + rj.resSet.getUrl()
+ + "</a><br>";
}
}
}
/**
* alignment panels derived from each alignment set returned by service.
*/
- ArrayList<jalview.gui.AlignmentPanel> destPanels = new ArrayList<jalview.gui.AlignmentPanel>();
+ ArrayList<jalview.gui.AlignmentPanel> destPanels = new ArrayList<>();
/**
* list of instructions for how to process each distinct alignment set
* returned by the job set
*/
- ArrayList<AddDataTo> resultDest = new ArrayList<AddDataTo>();
+ ArrayList<AddDataTo> resultDest = new ArrayList<>();
/**
* when false, zeroth pane is panel derived from input deta.
*/
boolean vsepjobs = restClient.service.isVseparable();
// total number of distinct alignment sets generated by job set.
int numAlSets = 0, als = 0;
- List<AlignmentI> destAls = new ArrayList<AlignmentI>();
- List<jalview.datamodel.ColumnSelection> destColsel = new ArrayList<jalview.datamodel.ColumnSelection>();
- List<List<NewickFile>> trees = new ArrayList<List<NewickFile>>();
+ List<AlignmentI> destAls = new ArrayList<>();
+ List<jalview.datamodel.HiddenColumns> destColsel = new ArrayList<>();
+ List<List<NewickFile>> trees = new ArrayList<>();
do
{
if (alset.trees != null)
{
- trees.add(new ArrayList<NewickFile>(alset.trees));
+ trees.add(new ArrayList<>(alset.trees));
}
else
{
*/
int vrestjob = 0;
// Destination alignments for all result data.
- ArrayList<SequenceGroup> visgrps = new ArrayList<SequenceGroup>();
- Hashtable<String, SequenceGroup> groupNames = new Hashtable<String, SequenceGroup>();
+ ArrayList<SequenceGroup> visgrps = new ArrayList<>();
+ Hashtable<String, SequenceGroup> groupNames = new Hashtable<>();
ArrayList<AlignmentAnnotation> visAlAn = null;
for (nvertsep = 0; nvertsep < nvertseps; nvertsep++)
{
RestJob rj = (RestJob) jobs[nrj];
int contigs[] = input.getVisibleContigs();
AlignmentI destAl = null;
- jalview.datamodel.ColumnSelection destCs = null;
+ jalview.datamodel.HiddenColumns destHCs = null;
// Resolve destAl for this data.
if (als == 0 && rj.isInputContextModified())
{
if (!restClient.isAlignmentModified() && merge)
{
destAl = restClient.av.getAlignment();
- destCs = restClient.av.getColumnSelection();
- resultDest
- .add(restClient.isShowResultsInNewView() ? AddDataTo.newView
- : AddDataTo.currentView);
+ destHCs = restClient.av.getAlignment().getHiddenColumns();
+ resultDest.add(restClient.isShowResultsInNewView()
+ ? AddDataTo.newView
+ : AddDataTo.currentView);
destPanels.add(restClient.recoverAlignPanelForView());
}
else
newAlignment = true;
// recreate the input alignment data
Object[] idat = input
- .getAlignmentAndColumnSelection(gapCharacter);
+ .getAlignmentAndHiddenColumns(gapCharacter);
destAl = new Alignment((SequenceI[]) idat[0]);
- destCs = (ColumnSelection) idat[1];
+ destHCs = (HiddenColumns) idat[1];
resultDest.add(AddDataTo.newAlignment);
// but do not add to the alignment panel list - since we need to
// create a whole new alignFrame set.
}
destAls.add(destAl);
- destColsel.add(destCs);
+ destColsel.add(destHCs);
}
}
else
{
// TODO: decide if multiple multiple alignments returned by
// non-vseparable services are allowed.
- Cache.log
- .warn("dealing with multiple alignment products returned by non-vertically separable service.");
+ Cache.log.warn(
+ "dealing with multiple alignment products returned by non-vertically separable service.");
}
// recover reference to last alignment created for this rest frame
// ready for extension
destAl = destAls.get(als);
- destCs = destColsel.get(als);
+ destHCs = destColsel.get(als);
}
else
{
newview = input.getUpdatedView(rseqs, orders, gapCharacter);
}
destAl = new Alignment((SequenceI[]) newview[0]);
- destCs = (ColumnSelection) newview[1];
+ destHCs = (HiddenColumns) newview[1];
newAlignment = true;
// TODO create alignment from result data with propagated
// references.
destAls.add(destAl);
- destColsel.add(destCs);
+ destColsel.add(destHCs);
resultDest.add(AddDataTo.newAlignment);
- throw new Error("Impl. Error! TODO: ");
+ throw new Error(
+ MessageManager.getString("error.implementation_error")
+ + "TODO: ");
}
}
/**
visgrps.add(exsg);
exsg.setStartRes(sg.getStartRes() + contigs[ncnt]);
exsg.setEndRes(sg.getEndRes() + contigs[ncnt]);
- } else {
+ }
+ else
+ {
recovered = true;
}
// now replace any references from the result set with
// TODO: cope with recovering hidden sequences from
// resultContext
{
- Vector sqs = sg.getSequences(null);
- for (int sqsi = 0, iSize = sqs.size(); sqsi < iSize; sqsi++)
+ for (SequenceI oseq : sg.getSequences(null))
{
- SequenceI oseq = (SequenceI) sqs.get(sqsi);
SequenceI nseq = getNewSeq(oseq, rseqs[nrj],
ordermap[nrj], destAl);
if (nseq != null)
}
else
{
- Cache.log
- .warn("Couldn't resolve original sequence for new sequence.");
+ Cache.log.warn(
+ "Couldn't resolve original sequence for new sequence.");
}
}
if (sg.hasSeqrep())
{
// adjust boundaries of recovered group w.r.t. new group being
// merged on to original alignment.
- int start = sg.getStartRes() + contigs[ncnt], end = sg
- .getEndRes() + contigs[ncnt];
+ int start = sg.getStartRes() + contigs[ncnt],
+ end = sg.getEndRes() + contigs[ncnt];
if (start < exsg.getStartRes())
{
exsg.setStartRes(start);
grass = groupNames.get(alan[nrj][an].groupRef.getName());
if (grass == null)
{
- Cache.log
- .error("Couldn't relocate group referemce for group "
+ Cache.log.error(
+ "Couldn't relocate group referemce for group "
+ alan[nrj][an].groupRef.getName());
}
}
if (visAlAn == null)
{
- visAlAn = new ArrayList<AlignmentAnnotation>();
+ visAlAn = new ArrayList<>();
}
AlignmentAnnotation visan = null;
for (AlignmentAnnotation v : visAlAn)
visan.sequenceRef = sqass;
visAlAn.add(visan);
}
- if (contigs[ncnt]+alan[nrj][an].annotations.length>visan.annotations.length)
+ if (contigs[ncnt]
+ + alan[nrj][an].annotations.length > visan.annotations.length)
{
// increase width of annotation row
- Annotation[] newannv = new Annotation[contigs[ncnt]+alan[nrj][an].annotations.length];
- System.arraycopy(visan.annotations, 0, newannv, 0, visan.annotations.length);
- visan.annotations=newannv;
+ Annotation[] newannv = new Annotation[contigs[ncnt]
+ + alan[nrj][an].annotations.length];
+ System.arraycopy(visan.annotations, 0, newannv, 0,
+ visan.annotations.length);
+ visan.annotations = newannv;
}
// now copy local annotation data into correct position
System.arraycopy(alan[nrj][an].annotations, 0,
{
// TODO: process each newick file, lifting over sequence refs to
// current alignment, if necessary.
- Cache.log
- .error("Tree recovery from restjob not yet implemented.");
+ Cache.log.error(
+ "Tree recovery from restjob not yet implemented.");
}
}
}
for (AddDataTo action : resultDest)
{
AlignmentI destal;
- ColumnSelection destcs;
- String alTitle = restClient.service.details.Action + " using "
- + restClient.service.details.Name + " on "+restClient.viewTitle;
+ HiddenColumns destcs;
+ String alTitle = MessageManager
+ .formatMessage("label.webservice_job_title_on", new String[]
+ { restClient.service.details.getAction(),
+ restClient.service.details.getName(),
+ restClient.viewTitle });
switch (action)
{
case newAlignment:
destcs = destColsel.get(als);
destaf = new AlignFrame(destal, destcs, AlignFrame.DEFAULT_WIDTH,
AlignFrame.DEFAULT_HEIGHT);
- PaintRefresher.Refresh(destaf, destaf.getViewport().getSequenceSetId());
+ PaintRefresher.Refresh(destaf,
+ destaf.getViewport().getSequenceSetId());
// todo transfer any feature settings and colouring
/*
* destaf.getFeatureRenderer().transferSettings(this.featureSettings);
* i++) { af.addSortByOrderMenuItem( WebServiceName + ((String)
* names.get(i)) + " Ordering", (AlignmentOrder) alorders.get(i)); } } }
*/
- // TODO: modify this and previous alignment's title if many alignments have been returned.
+ // TODO: modify this and previous alignment's title if many alignments
+ // have been returned.
Desktop.addInternalFrame(destaf, alTitle, AlignFrame.DEFAULT_WIDTH,
AlignFrame.DEFAULT_HEIGHT);
{
if (start + width < end)
{
- blocks[c][s] = sequenceIs[s].getSubSequence(start, start
- + width);
+ blocks[c][s] = sequenceIs[s].getSubSequence(start,
+ start + width);
}
else
{
*/
public boolean isValid()
{
- ArrayList<String> _warnings=new ArrayList<String>();
- boolean validt=true;
+ ArrayList<String> _warnings = new ArrayList<>();
+ boolean validt = true;
if (jobs != null)
{
for (RestJob rj : (RestJob[]) jobs)
{
// invalid input for this job
System.err.println("Job " + rj.getJobnum()
- + " has invalid input. ( "+rj.getStatus()+")");
+ + " has invalid input. ( " + rj.getStatus() + ")");
if (rj.hasStatus() && !_warnings.contains(rj.getStatus()))
{
_warnings.add(rj.getStatus());
}
- validt=false;
+ validt = false;
}
}
}
if (!validt)
{
warnings = "";
- for (String st : _warnings) {
- if (warnings.length()>0) { warnings+="\n";
+ for (String st : _warnings)
+ {
+ if (warnings.length() > 0)
+ {
+ warnings += "\n";
}
warnings += st;
-
+
}
}
return validt;
}
protected String warnings;
+
public boolean hasWarnings()
{
// TODO Auto-generated method stub
- return warnings!=null && warnings.length()>0;
+ return warnings != null && warnings.length() > 0;
}
/**
* get any informative messages about why the job thread couldn't start.
+ *
* @return
*/
public String getWarnings()
{
- return isValid() ? "Job can be started. No warnings." : hasWarnings() ? warnings : "";
+ return isValid() ? "Job can be started. No warnings."
+ : hasWarnings() ? warnings : "";
}
}