Java tutorial
/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.taverna.activities.interaction; import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.OutputStream; import java.io.StringWriter; import java.net.HttpURLConnection; import java.net.URL; import java.util.Date; import java.util.Map; import java.util.UUID; import org.apache.taverna.activities.interaction.atom.AtomUtils; import org.apache.taverna.activities.interaction.jetty.InteractionJetty; import org.apache.taverna.activities.interaction.preference.InteractionPreference; import org.apache.taverna.activities.interaction.velocity.InteractionVelocity; import org.apache.taverna.security.credentialmanager.CredentialManager; import org.apache.abdera.Abdera; import org.apache.abdera.i18n.text.Normalizer; import org.apache.abdera.i18n.text.Sanitizer; import org.apache.abdera.model.Element; import org.apache.abdera.model.Entry; import org.apache.abdera.parser.stax.FOMElement; import org.apache.commons.io.IOUtils; import org.apache.commons.lang.StringEscapeUtils; import org.apache.log4j.Logger; import org.apache.velocity.Template; import org.apache.velocity.VelocityContext; public final class InteractionActivityRunnable implements Runnable { private static final Logger logger = Logger.getLogger(InteractionActivityRunnable.class); private static final Abdera ABDERA = Abdera.getInstance(); private final Template presentationTemplate; private final InteractionRequestor requestor; private CredentialManager credentialManager; private InteractionRecorder interactionRecorder; private InteractionUtils interactionUtils; private InteractionJetty interactionJetty; private InteractionPreference interactionPreference; private ResponseFeedListener responseFeedListener; private InteractionVelocity interactionVelocity; public InteractionActivityRunnable(final InteractionRequestor requestor, final Template presentationTemplate, final CredentialManager credentialManager, final InteractionRecorder interactionRecorder, final InteractionUtils interactionUtils, final InteractionJetty interactionJetty, final InteractionPreference interactionPreference, final ResponseFeedListener responseFeedListener, final InteractionVelocity interactionVelocity) { this.requestor = requestor; this.presentationTemplate = presentationTemplate; this.credentialManager = credentialManager; this.interactionRecorder = interactionRecorder; this.interactionUtils = interactionUtils; this.interactionJetty = interactionJetty; this.interactionPreference = interactionPreference; this.responseFeedListener = responseFeedListener; this.interactionVelocity = interactionVelocity; } @Override public void run() { /* * InvocationContext context = callback.getContext(); */ final String runId = InteractionUtils.getUsedRunId(this.requestor.getRunId()); final String id = Sanitizer.sanitize(UUID.randomUUID().toString(), "", true, Normalizer.Form.D); final Map<String, Object> inputData = this.requestor.getInputData(); if (interactionPreference.getUseJetty()) { interactionJetty.startJettyIfNecessary(credentialManager); } interactionJetty.startListenersIfNecessary(); try { interactionUtils.copyFixedFile("pmrpc.js"); interactionUtils.copyFixedFile("interaction.css"); } catch (final IOException e1) { logger.error(e1); this.requestor.fail("Unable to copy necessary fixed file"); return; } synchronized (ABDERA) { final Entry interactionNotificationMessage = this.createBasicInteractionMessage(id, runId); for (final String key : inputData.keySet()) { final Object value = inputData.get(key); if (value instanceof byte[]) { final String replacementUrl = interactionPreference.getPublicationUrlString(id, key); final ByteArrayInputStream bais = new ByteArrayInputStream((byte[]) value); try { interactionUtils.publishFile(replacementUrl, bais, runId, id); bais.close(); inputData.put(key, replacementUrl); } catch (final IOException e) { logger.error(e); this.requestor.fail("Unable to publish to " + replacementUrl); return; } } } final String inputDataString = this.createInputDataJson(inputData); if (inputDataString == null) { return; } final String inputDataUrl = interactionPreference.getInputDataUrlString(id); try { interactionUtils.publishFile(inputDataUrl, inputDataString, runId, id); } catch (final IOException e) { logger.error(e); this.requestor.fail("Unable to publish to " + inputDataUrl); return; } String outputDataUrl = null; if (!this.requestor.getInteractionType().equals(InteractionType.Notification)) { outputDataUrl = interactionPreference.getOutputDataUrlString(id); } final String interactionUrlString = this.generateHtml(inputDataUrl, outputDataUrl, inputData, runId, id); try { this.postInteractionMessage(id, interactionNotificationMessage, interactionUrlString, runId); } catch (IOException e) { logger.error(e); this.requestor.fail("Unable to post message"); return; } if (!this.requestor.getInteractionType().equals(InteractionType.Notification)) { responseFeedListener.registerInteraction(interactionNotificationMessage, this.requestor); } else { this.requestor.carryOn(); } } } private String createInputDataJson(final Map<String, Object> inputData) { try { return InteractionUtils.objectToJson(inputData); } catch (final IOException e) { logger.error(e); this.requestor.fail("Unable to generate JSON"); } return null; } private Entry createBasicInteractionMessage(final String id, final String runId) { final Entry interactionNotificationMessage = ABDERA.newEntry(); interactionNotificationMessage.setId(id); final Date timestamp = new Date(); interactionNotificationMessage.setPublished(timestamp); interactionNotificationMessage.setUpdated(timestamp); interactionNotificationMessage.addAuthor("Taverna"); interactionNotificationMessage.setTitle("Interaction from Taverna for " + this.requestor.generateId()); final Element runIdElement = interactionNotificationMessage.addExtension(AtomUtils.getRunIdQName()); runIdElement.setText(StringEscapeUtils.escapeJavaScript(runId)); final Element pathIdElement = interactionNotificationMessage.addExtension(AtomUtils.getPathIdQName()); pathIdElement.setText(StringEscapeUtils.escapeJavaScript(this.requestor.getPath())); final Element countElement = interactionNotificationMessage.addExtension(AtomUtils.getCountQName()); countElement.setText(StringEscapeUtils.escapeJavaScript(this.requestor.getInvocationCount().toString())); if (this.requestor.getInteractionType().equals(InteractionType.Notification)) { interactionNotificationMessage.addExtension(AtomUtils.getProgressQName()); } final Element idElement = interactionNotificationMessage.addExtension(AtomUtils.getIdQName()); idElement.setText(id); return interactionNotificationMessage; } private void postInteractionMessage(final String id, final Entry entry, final String interactionUrlString, final String runId) throws IOException { entry.addLink(StringEscapeUtils.escapeXml(interactionUrlString), "presentation"); entry.setContentAsXhtml("<p><a href=\"" + StringEscapeUtils.escapeXml(interactionUrlString) + "\">Open: " + StringEscapeUtils.escapeXml(interactionUrlString) + "</a></p>"); URL feedUrl; feedUrl = new URL(interactionPreference.getFeedUrlString()); final String entryContent = ((FOMElement) entry).toFormattedString(); final HttpURLConnection httpCon = (HttpURLConnection) feedUrl.openConnection(); httpCon.setDoOutput(true); httpCon.setRequestProperty("Content-Type", "application/atom+xml;type=entry;charset=UTF-8"); httpCon.setRequestProperty("Content-Length", "" + entryContent.length()); httpCon.setRequestProperty("Slug", id); httpCon.setRequestMethod("POST"); httpCon.setConnectTimeout(5000); final OutputStream outputStream = httpCon.getOutputStream(); IOUtils.write(entryContent, outputStream, "UTF-8"); outputStream.close(); final int response = httpCon.getResponseCode(); if ((response < 0) || (response >= 400)) { logger.error("Received response code" + response); throw (new IOException("Received response code " + response)); } if (response == HttpURLConnection.HTTP_CREATED) { interactionRecorder.addResource(runId, id, httpCon.getHeaderField("Location")); } } String generateHtml(final String inputDataUrl, final String outputDataUrl, final Map<String, Object> inputData, final String runId, final String id) { final VelocityContext velocityContext = new VelocityContext(); for (final String inputName : inputData.keySet()) { final Object input = inputData.get(inputName); velocityContext.put(inputName, input); } velocityContext.put("feed", interactionPreference.getFeedUrlString()); velocityContext.put("runId", runId); velocityContext.put("entryId", id); final String pmrpcUrl = interactionPreference.getLocationUrl() + "/pmrpc.js"; velocityContext.put("pmrpcUrl", pmrpcUrl); velocityContext.put("inputDataUrl", inputDataUrl); velocityContext.put("outputDataUrl", outputDataUrl); final String interactionUrl = interactionPreference.getInteractionUrlString(id); velocityContext.put("interactionUrl", interactionUrl); String presentationUrl = ""; final String authorizeUrl = ""; try { if (this.requestor.getPresentationType().equals(InteractionActivityType.VelocityTemplate)) { presentationUrl = interactionPreference.getPresentationUrlString(id); final String presentationString = this.processTemplate(this.presentationTemplate, velocityContext); interactionUtils.publishFile(presentationUrl, presentationString, runId, id); } else if (this.requestor.getPresentationType().equals(InteractionActivityType.LocallyPresentedHtml)) { presentationUrl = this.requestor.getPresentationOrigin(); } velocityContext.put("presentationUrl", presentationUrl); final String interactionString = this.processTemplate(interactionVelocity.getInteractionTemplate(), velocityContext); interactionUtils.publishFile(interactionUrl, interactionString, runId, id); if (!authorizeUrl.isEmpty()) { return authorizeUrl; } return interactionUrl; } catch (final IOException e) { logger.error(e); this.requestor.fail("Unable to generate HTML"); return null; } } private String processTemplate(final Template template, final VelocityContext context) throws IOException { final StringWriter resultWriter = new StringWriter(); template.merge(context, resultWriter); resultWriter.close(); return resultWriter.toString(); } }