blob: 6154d0563d1c98a07e9f7ff44bff5a050e0b2aa5 [file] [log] [blame]
/* Part of the KnowARC Janitor Use-case processor for taverna
* written 2007-2010 by Hajo Nils Krabbenhoeft and Steffen Moeller
* University of Luebeck, Institute for Neuro- and Bioinformatics
* University of Luebeck, Institute for Dermatolgy
*
* This package 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 3 of the License, or
* (at your option) any later version.
*
* This package 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 package; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
package de.uni_luebeck.inb.knowarc.usecases.invocation;
import java.io.BufferedWriter;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.HashMap;
import java.util.List;
import java.util.Set;
import org.apache.commons.io.IOUtils;
import net.sf.taverna.t2.invocation.InvocationContext;
import net.sf.taverna.t2.reference.ExternalReferenceSPI;
import net.sf.taverna.t2.reference.Identified;
import net.sf.taverna.t2.reference.IdentifiedList;
import net.sf.taverna.t2.reference.ReferenceService;
import net.sf.taverna.t2.reference.ReferenceServiceException;
import net.sf.taverna.t2.reference.ReferenceSet;
import net.sf.taverna.t2.reference.T2Reference;
import net.sf.taverna.t2.reference.impl.external.object.InlineByteArrayReferenceBuilder;
import net.sf.taverna.t2.reference.impl.external.object.InlineStringReferenceBuilder;
import de.uni_luebeck.inb.knowarc.usecases.ScriptInput;
import de.uni_luebeck.inb.knowarc.usecases.ScriptInputStatic;
import de.uni_luebeck.inb.knowarc.usecases.ScriptInputUser;
import de.uni_luebeck.inb.knowarc.usecases.UseCaseDescription;
/**
* An abstraction of various forms to bring job using the software that is
* referenced as a use case towards their execution.
*
* @author Hajo Nils Krabbenhoeft with some contribution by
* @author Steffen Moeller
*/
public abstract class UseCaseInvocation {
private String runId;
protected static String getActualOsCommand(String osCommand, String pathToOriginal,
String targetName, String pathTarget) {
String actualOsCommand = osCommand;
actualOsCommand = actualOsCommand.replace("%%PATH_TO_ORIGINAL%%", pathToOriginal);
actualOsCommand = actualOsCommand.replace("%%TARGET_NAME%%", targetName);
actualOsCommand = actualOsCommand.replace("%%PATH_TO_TARGET%%", pathTarget);
return actualOsCommand;
}
protected UseCaseDescription usecase;
protected final HashMap<String, String> tags = new HashMap<String, String>();
protected int nTempFiles = 0;
private static int submissionID = 0;
protected static InlineByteArrayReferenceBuilder inlineByteArrayReferenceBuilder = new InlineByteArrayReferenceBuilder();
protected static InlineStringReferenceBuilder inlineStringReferenceBuilder = new InlineStringReferenceBuilder();
private InvocationContext invocationContext;
private boolean retrieveData;
/*
* get the class of the data we expect for a given input
*/
@SuppressWarnings("unchecked")
public Class getType(String inputName) {
if (!usecase.getInputs().containsKey(inputName))
return null;
ScriptInputUser input = (ScriptInputUser) usecase.getInputs().get(inputName);
if (input.isList()) {
if (input.isBinary())
return List.class;
else
return List.class;
} else {
if (input.isBinary())
return byte[].class;
else
return String.class;
}
}
/*
* get a list of all the input port names
*/
public Set<String> getInputs() {
return usecase.getInputs().keySet();
}
/*
* get a id, incremented with each job. thus, this should be thread-wide
* unique
*/
public synchronized int getSubmissionID() {
return submissionID++;
}
/*
* set the data for the input port with given name
*/
@SuppressWarnings("unchecked")
public void setInput(String inputName, ReferenceService referenceService, T2Reference t2Reference) throws InvocationException {
if (t2Reference == null) {
throw new InvocationException("No input specified for " + inputName);
}
ScriptInputUser input = (ScriptInputUser) usecase.getInputs().get(inputName);
if (input.isList()) {
IdentifiedList<T2Reference> listOfReferences = (IdentifiedList<T2Reference>) referenceService
.getListService().getList(t2Reference);
if (!input.isConcatenate()) {
// this is a list input (not concatenated)
// so write every element to its own temporary file
// and create a filelist file
// we need to write the list elements to temporary files
ScriptInputUser listElementTemp = new ScriptInputUser();
listElementTemp.setBinary(input.isBinary());
listElementTemp.setTempFile(true);
String lineEndChar = "\n";
if (!input.isFile() && !input.isTempFile()) {
lineEndChar = " ";
}
String listFileContent = "";
String filenamesFileContent = "";
// create a list of all temp file names
for (T2Reference cur : listOfReferences) {
String tmp = setOneInput(referenceService, cur,
listElementTemp);
listFileContent += tmp + lineEndChar;
int ind = tmp.lastIndexOf('/');
if (ind == -1) {
ind = tmp.lastIndexOf('\\');
}
if (ind != -1) {
tmp = tmp.substring(ind + 1);
}
filenamesFileContent += tmp + lineEndChar;
}
// how do we want the listfile to be stored?
ScriptInputUser listFile = new ScriptInputUser();
listFile.setBinary(false); // since its a list file
listFile.setFile(input.isFile());
listFile.setTempFile(input.isTempFile());
listFile.setTag(input.getTag());
T2Reference listFileContentReference = referenceService
.register(listFileContent, 0, true, invocationContext);
tags.put(listFile.getTag(), setOneInput(referenceService,
listFileContentReference, listFile));
listFile.setTag(input.getTag() + "_NAMES");
T2Reference filenamesFileContentReference = referenceService
.register(filenamesFileContent, 0, true, null);
tags.put(listFile.getTag(), setOneInput(referenceService,
filenamesFileContentReference, listFile));
} else {
try {
// first, concatenate all data
if (input.isBinary()) {
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
BufferedWriter outputWriter = new BufferedWriter(
new OutputStreamWriter(outputStream));
for (T2Reference cur : listOfReferences) {
InputStreamReader inputReader = new InputStreamReader(
getAsStream(referenceService, cur));
IOUtils.copyLarge(inputReader, outputWriter);
inputReader.close();
}
outputWriter.close();
T2Reference binaryReference = referenceService
.register(outputStream.toByteArray(), 0, true,
invocationContext);
tags.put(input.getTag(), setOneInput(referenceService,
binaryReference, input));
} else {
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
BufferedWriter outputWriter = new BufferedWriter(
new OutputStreamWriter(outputStream));
for (T2Reference cur : listOfReferences) {
InputStreamReader inputReader = new InputStreamReader(
getAsStream(referenceService, cur));
IOUtils.copyLarge(inputReader, outputWriter);
outputWriter.write(" ");
inputReader.close();
}
outputWriter.close();
T2Reference binaryReference = referenceService
.register(outputStream.toByteArray(), 0, true,
invocationContext);
tags.put(input.getTag(), setOneInput(referenceService,
binaryReference, input));
}
} catch (IOException e) {
throw new InvocationException(e);
}
}
} else {
tags.put(input.getTag(), setOneInput(referenceService, t2Reference,
input));
}
}
/*
* submit a grid job and wait for it to finish, then get the result as
* on-demand downloads or directly as data (in case of local execution)
*/
public HashMap<String, Object> Submit(ReferenceService referenceService) throws InvocationException {
submit_generate_job(referenceService);
return submit_wait_fetch_results(referenceService);
}
/*
* just submit the job. useful if you want to wait for it to finish later on
*
* Can the statics be made more static?
*/
public void submit_generate_job(ReferenceService referenceService) throws InvocationException {
for (ScriptInputStatic input : usecase.getStatic_inputs()) {
T2Reference ref;
if (input.getUrl() != null) {
// Does this work OK with binary
try {
ref = referenceService.register(new URL(input.getUrl()), 0, true, null);
} catch (ReferenceServiceException e) {
throw new InvocationException(e);
} catch (MalformedURLException e) {
throw new InvocationException(e);
}
} else {
ref = referenceService.register((String) input.getContent(), 0, true, null);
}
tags.put(input.getTag(), setOneInput(referenceService, ref, input));
}
submit_generate_job_inner();
}
protected abstract void submit_generate_job_inner() throws InvocationException;
/*
* wait for a submitted job to finish and fetch the results
*/
public abstract HashMap<String, Object> submit_wait_fetch_results(ReferenceService referenceService) throws InvocationException;
public abstract String setOneInput(ReferenceService referenceService, T2Reference t2Reference, ScriptInput input) throws InvocationException;
protected InputStream getAsStream(ReferenceService referenceService, T2Reference t2Reference) {
Identified identified = referenceService.resolveIdentifier(t2Reference, null, null);
if (identified instanceof ReferenceSet) {
ExternalReferenceSPI ref = ((ReferenceSet) identified).getExternalReferences().iterator().next();
return ref.openStream(invocationContext);
}
return null;
}
public void setContext(InvocationContext context) {
this.invocationContext = context;
}
public InvocationContext getContext() {
return this.invocationContext;
}
public abstract void setStdIn(ReferenceService referenceService,
T2Reference t2Reference);
public abstract void rememberRun(String runId);
/**
* @return the runId
*/
protected String getRunId() {
return runId;
}
/**
* @param runId the runId to set
*/
protected void setRunId(String runId) {
this.runId = runId;
}
/**
* @return the retrieveData
*/
protected boolean isRetrieveData() {
return retrieveData;
}
/**
* @param retrieveData the retrieveData to set
*/
protected void setRetrieveData(boolean retrieveData) {
this.retrieveData = retrieveData;
}
}