<bean name="/getSlcExecution.service" class="org.argeo.slc.web.mvc.process.GetSlcExecution">
<property name="slcExecutionDao" ref="slcExecutionDao" />
<property name="unmarshaller" ref="unmarshaller" />
+ <property name="attachmentsStorage" ref="attachmentsStorage" />
</bean>
<bean name="/newSlcExecution.service"
<property name="unmarshaller" ref="unmarshaller" />
<property name="marshaller" ref="marshaller" />
<property name="slcExecutionService" ref="slcExecutionService" />
+ <property name="attachmentsStorage" ref="attachmentsStorage" />
</bean>
<bean name="/getExecutionDescriptor.service" class="org.argeo.slc.web.mvc.execution.GetModuleDescriptor">
import java.io.InputStream;
import java.io.OutputStream;
-
public interface AttachmentsStorage {
public void retrieveAttachment(Attachment attachment,
OutputStream outputStream);
+ /** Does NOT close the provided input stream. */
public void storeAttachment(Attachment attachment, InputStream inputStream);
}
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
+import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
+import java.text.DateFormat;
+import java.text.SimpleDateFormat;
+import java.util.Date;
import org.apache.commons.io.IOUtils;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
import org.argeo.slc.SlcException;
+import org.springframework.beans.factory.InitializingBean;
+
+public class FileAttachmentsStorage implements AttachmentsStorage,
+ InitializingBean {
+ private final static Log log = LogFactory
+ .getLog(FileAttachmentsStorage.class);
-public class FileAttachmentsStorage implements AttachmentsStorage {
private File attachmentsDirectory;
- public FileAttachmentsStorage() {
- String osgiInstanceArea = System.getProperty("osgi.instance.area");
- if (osgiInstanceArea != null) {
- if (osgiInstanceArea.startsWith("file:"))
- osgiInstanceArea = osgiInstanceArea.substring("file:".length());
- attachmentsDirectory = new File(osgiInstanceArea + File.separator
- + "slcAttachments");
- }
+ private String attachmentsTocFileName = "attachmentsToc.csv";
+
+ private DateFormat dateFormatDay = new SimpleDateFormat("yyyy-MM-dd");
+ private DateFormat dateFormatTime = new SimpleDateFormat("HH:mm:ss");
+ public void afterPropertiesSet() {
if (attachmentsDirectory == null) {
- String tempDir = System.getProperty("java.io.tmpdir");
- attachmentsDirectory = new File(tempDir + File.separator
- + "slcAttachments");
+
+ String osgiInstanceArea = System.getProperty("osgi.instance.area");
+ if (osgiInstanceArea != null) {
+ if (osgiInstanceArea.startsWith("file:"))
+ osgiInstanceArea = osgiInstanceArea.substring("file:"
+ .length());
+ attachmentsDirectory = new File(osgiInstanceArea
+ + File.separator + "slcAttachments");
+ }
+
+ if (attachmentsDirectory == null) {
+ String tempDir = System.getProperty("java.io.tmpdir");
+ attachmentsDirectory = new File(tempDir + File.separator
+ + "slcAttachments");
+ }
}
+ if (!attachmentsDirectory.exists())
+ attachmentsDirectory.mkdirs();
+ if (log.isDebugEnabled())
+ log.debug("File attachment storage initialized in directory "
+ + attachmentsDirectory);
}
public void retrieveAttachment(Attachment attachment,
while ((read = in.read(buffer)) >= 0) {
outputStream.write(buffer, 0, read);
}
+ if (log.isTraceEnabled())
+ log.trace("Read " + attachment + " from " + file);
} catch (IOException e) {
throw new SlcException("Cannot write attachment " + attachment
+ " to " + file, e);
while ((read = inputStream.read(buffer)) >= 0) {
out.write(buffer, 0, read);
}
+ if (log.isTraceEnabled())
+ log.trace("Wrote " + attachment + " to " + file);
+ updateAttachmentToc(attachment, file);
} catch (IOException e) {
throw new SlcException("Cannot write attachment " + attachment
+ " to " + file, e);
}
+ /** For monitoring purposes only */
+ protected void updateAttachmentToc(Attachment attachment, File file) {
+ Date date = new Date(file.lastModified());
+ FileWriter writer = null;
+ try {
+ writer = new FileWriter(attachmentsDirectory + File.separator
+ + attachmentsTocFileName, true);
+ writer.append(dateFormatDay.format(date));
+ writer.append(',');
+ writer.append(dateFormatTime.format(date));
+ writer.append(',');
+ writer.append(attachment.getUuid());
+ writer.append(',');
+ writer.append(attachment.getName());
+ writer.append(',');
+ writer.append(attachment.getContentType());
+ writer.append(',');
+ writer.append(Long.toString(file.length()));
+ writer.append(',');
+ writer.append(file.getCanonicalPath());
+ writer.append('\n');
+ } catch (IOException e) {
+ log.warn("Could not update attachments TOC for " + attachment
+ + " and file " + file, e);
+ } finally {
+ IOUtils.closeQuietly(writer);
+ }
+
+ }
+
protected File getFile(Attachment attachment) {
- if (!attachmentsDirectory.exists())
- attachmentsDirectory.mkdirs();
File file = new File(attachmentsDirectory + File.separator
+ attachment.getUuid());
return file;
private String name;
private String contentType = "";
+ public SimpleAttachment() {
+ }
+
+ public SimpleAttachment(String uuid, String name, String contentType) {
+ super();
+ this.uuid = uuid;
+ this.name = name;
+ this.contentType = contentType;
+ }
+
public String getUuid() {
return uuid;
}
package org.argeo.slc.web.mvc.process;\r
\r
+import java.io.ByteArrayInputStream;\r
+import java.io.ByteArrayOutputStream;\r
+\r
import javax.servlet.http.HttpServletRequest;\r
import javax.servlet.http.HttpServletResponse;\r
+import javax.xml.transform.stream.StreamSource;\r
\r
+import org.apache.commons.io.IOUtils;\r
+import org.apache.commons.logging.Log;\r
+import org.apache.commons.logging.LogFactory;\r
+import org.argeo.slc.core.attachment.Attachment;\r
+import org.argeo.slc.core.attachment.AttachmentsStorage;\r
import org.argeo.slc.dao.process.SlcExecutionDao;\r
import org.argeo.slc.msg.ObjectList;\r
import org.argeo.slc.process.SlcExecution;\r
import org.argeo.slc.web.mvc.AbstractServiceController;\r
import org.springframework.oxm.Unmarshaller;\r
import org.springframework.web.servlet.ModelAndView;\r
-import org.springframework.xml.transform.StringSource;\r
\r
/** Lists SLC executions possibly filtering them. */\r
public class GetSlcExecution extends AbstractServiceController {\r
+ private final static Log log = LogFactory.getLog(GetSlcExecution.class);\r
+\r
private SlcExecutionDao slcExecutionDao;\r
private Unmarshaller unmarshaller;\r
\r
+ private AttachmentsStorage attachmentsStorage;\r
+\r
@Override\r
protected void handleServiceRequest(HttpServletRequest request,\r
HttpServletResponse response, ModelAndView modelAndView)\r
String uuid = request.getParameter("uuid");\r
SlcExecution slcExecution = slcExecutionDao.getSlcExecution(uuid);\r
\r
- StringSource source = new StringSource(slcExecution\r
- .getRealizedFlowsXml());\r
- ObjectList ol2 = (ObjectList) unmarshaller.unmarshal(source);\r
- ol2.fill(slcExecution.getRealizedFlows());\r
+ // StringSource source = new StringSource(slcExecution\r
+ // .getRealizedFlowsXml());\r
+ // ObjectList ol2 = (ObjectList) unmarshaller.unmarshal(source);\r
+ // ol2.fill(slcExecution.getRealizedFlows());\r
+ retrieveRealizedFlows(slcExecution);\r
\r
modelAndView.addObject(slcExecution);\r
}\r
\r
+ protected void retrieveRealizedFlows(SlcExecution slcExecution) {\r
+ Attachment attachment = NewSlcExecutionController\r
+ .realizedFlowsAttachment(slcExecution.getRealizedFlowsXml(),\r
+ slcExecution);\r
+\r
+ ByteArrayOutputStream out = null;\r
+ ByteArrayInputStream in = null;\r
+ try {\r
+ // TODO: optimize with piped streams\r
+ out = new ByteArrayOutputStream();\r
+ attachmentsStorage.retrieveAttachment(attachment, out);\r
+\r
+ byte[] arr = out.toByteArray();\r
+ in = new ByteArrayInputStream(arr);\r
+ StreamSource source = new StreamSource(in);\r
+ ObjectList ol = (ObjectList) unmarshaller.unmarshal(source);\r
+ ol.fill(slcExecution.getRealizedFlows());\r
+ } catch (Exception e) {\r
+ log.error("Could not retrieve realized flows from attachment #"\r
+ + attachment.getUuid(), e);\r
+ } finally {\r
+ IOUtils.closeQuietly(in);\r
+ IOUtils.closeQuietly(out);\r
+ }\r
+ }\r
+\r
public void setSlcExecutionDao(SlcExecutionDao slcExecutionDao) {\r
this.slcExecutionDao = slcExecutionDao;\r
}\r
this.unmarshaller = unmarshaller;\r
}\r
\r
+ public void setAttachmentsStorage(AttachmentsStorage attachmentsStorage) {\r
+ this.attachmentsStorage = attachmentsStorage;\r
+ }\r
+\r
}\r
package org.argeo.slc.web.mvc.process;\r
\r
import java.io.BufferedReader;\r
+import java.io.ByteArrayInputStream;\r
+import java.io.InputStream;\r
import java.util.UUID;\r
\r
import javax.servlet.http.HttpServletRequest;\r
import javax.servlet.http.HttpServletResponse;\r
\r
+import org.apache.commons.io.IOUtils;\r
import org.apache.commons.logging.Log;\r
import org.apache.commons.logging.LogFactory;\r
+import org.argeo.slc.core.attachment.Attachment;\r
+import org.argeo.slc.core.attachment.AttachmentsStorage;\r
+import org.argeo.slc.core.attachment.SimpleAttachment;\r
import org.argeo.slc.msg.MsgConstants;\r
import org.argeo.slc.msg.ObjectList;\r
import org.argeo.slc.process.SlcExecution;\r
private Marshaller marshaller;\r
private SlcExecutionService slcExecutionService;\r
\r
+ private AttachmentsStorage attachmentsStorage;\r
+\r
@Override\r
protected void handleServiceRequest(HttpServletRequest request,\r
HttpServletResponse response, ModelAndView modelAndView)\r
new SlcExecutionStep(SlcExecutionStep.TYPE_START,\r
"Process started from the Web UI"));\r
\r
- ObjectList ol = new ObjectList(slcExecution.getRealizedFlows());\r
- StringResult result = new StringResult();\r
- marshaller.marshal(ol, result);\r
- slcExecution.setRealizedFlowsXml(result.toString());\r
+ // ObjectList ol = new ObjectList(slcExecution.getRealizedFlows());\r
+ // StringResult result = new StringResult();\r
+ // marshaller.marshal(ol, result);\r
+ // slcExecution.setRealizedFlowsXml(result.toString());\r
+ storeRealizedFlows(slcExecution);\r
\r
slcExecutionService.newExecution(slcExecution);\r
\r
agent.runSlcExecution(slcExecution);\r
}\r
\r
+ protected void storeRealizedFlows(SlcExecution slcExecution) {\r
+ Attachment attachment = realizedFlowsAttachment(UUID.randomUUID()\r
+ .toString(), slcExecution);\r
+ InputStream in = null;\r
+ try {\r
+\r
+ ObjectList ol = new ObjectList(slcExecution.getRealizedFlows());\r
+ StringResult result = new StringResult();\r
+ marshaller.marshal(ol, result);\r
+\r
+ in = new ByteArrayInputStream(result.toString().getBytes());\r
+ attachmentsStorage.storeAttachment(attachment, in);\r
+\r
+ slcExecution.setRealizedFlowsXml(attachment.getUuid());\r
+\r
+ } catch (Exception e) {\r
+ log.error("Could not store realized flows as attachment #"\r
+ + attachment.getUuid(), e);\r
+ } finally {\r
+ IOUtils.closeQuietly(in);\r
+ }\r
+ }\r
+\r
public void setUnmarshaller(Unmarshaller unmarshaller) {\r
this.unmarshaller = unmarshaller;\r
}\r
this.marshaller = marshaller;\r
}\r
\r
+ public void setAttachmentsStorage(AttachmentsStorage attachmentsStorage) {\r
+ this.attachmentsStorage = attachmentsStorage;\r
+ }\r
+\r
+ /** Unify labelling in the package */\r
+ static Attachment realizedFlowsAttachment(String attachmentUuid,\r
+ SlcExecution slcExecution) {\r
+ return new SimpleAttachment(attachmentUuid,\r
+ "RealizedFlows of SlcExecution #" + slcExecution.getUuid(),\r
+ "text/xml");\r
+ }\r
}\r
/** TODO: Synchronize */\r
private List<SlcExecutionStep> steps = new ArrayList<SlcExecutionStep>();\r
private List<RealizedFlow> realizedFlows = new ArrayList<RealizedFlow>();\r
+\r
+ /** Attachment uuid. */\r
private String realizedFlowsXml = null;\r
\r
public List<RealizedFlow> getRealizedFlows() {\r
}\r
}\r
\r
+ /**\r
+ * Not (yet) a stable API, should not be relied upon!\r
+ * \r
+ * @return an id or an url allowing to retrieve the XML, not the XML itself!\r
+ */\r
public String getRealizedFlowsXml() {\r
return realizedFlowsXml;\r
}\r
\r
+ /** Not (yet) a stable API, should not be relied upon! */\r
public void setRealizedFlowsXml(String realizedFlowsXml) {\r
this.realizedFlowsXml = realizedFlowsXml;\r
}\r