org.springframework.aop,
org.springframework.aop.framework,
org.springframework.aop.scope,
- org.springframework.beans.factory.config
+ org.springframework.beans.factory.config,
+ org.springframework.core.io
<property name="testData" ref="ref1" />\r
</bean>\r
\r
+ <bean parent="task.uploadAttachments">\r
+ <property name="attachmentUploader" ref="attachmentUploader" />\r
+ <property name="attachments">\r
+ <map>\r
+ <entry>\r
+ <key>\r
+ <bean class="org.argeo.slc.core.attachment.SimpleAttachment">\r
+ <property name="name" value="myAttachment" />\r
+ <property name="contentType" value="text/xml" />\r
+ <property name="uuid" value="1" />\r
+ </bean>\r
+ </key>\r
+ <bean class="org.springframework.core.io.FileSystemResource">\r
+ <constructor-arg value="/home/mbaudier/dev/work/tests/test.xml" />\r
+ </bean>\r
+ </entry>\r
+ </map>\r
+ </property>\r
+ <property name="attachTo">\r
+ <list>\r
+ <ref bean="basic.testResult" />\r
+ </list>\r
+ </property>\r
+ </bean>\r
+\r
<bean parent="task.closeTestResult" scope="execution">\r
<property name="testResult" ref="basic.testResult" />\r
</bean>\r
<service interface="org.argeo.slc.execution.ExecutionModule"\r
ref="executionModule" />\r
\r
- <list id="resultListeners" interface="org.argeo.slc.test.TestResultListener" />\r
+ <reference id="attachmentUploader" interface="org.argeo.slc.core.attachment.AttachmentUploader" />\r
+\r
+ <list id="resultListeners" interface="org.argeo.slc.core.test.tree.TreeTestResultListener" />\r
</beans:beans>
\ No newline at end of file
import org.argeo.slc.SlcException;
import org.argeo.slc.msg.MsgHandler;
import org.argeo.slc.msg.process.SlcExecutionStatusRequest;
+import org.argeo.slc.msg.test.tree.AddTreeTestResultAttachmentRequest;
import org.argeo.slc.msg.test.tree.CloseTreeTestResultRequest;
import org.argeo.slc.msg.test.tree.CreateTreeTestResultRequest;
import org.argeo.slc.msg.test.tree.ResultPartRequest;
else if (msg instanceof CloseTreeTestResultRequest)
testManagerService
.closeTreeTestResult((CloseTreeTestResultRequest) msg);
+ else if (msg instanceof AddTreeTestResultAttachmentRequest)
+ testManagerService
+ .addAttachment((AddTreeTestResultAttachmentRequest) msg);
else
throw new SlcException("Unrecognized message type " + msg);
return null;
import org.argeo.slc.dao.test.TestRunDescriptorDao;\r
import org.argeo.slc.dao.test.tree.TreeTestResultCollectionDao;\r
import org.argeo.slc.dao.test.tree.TreeTestResultDao;\r
+import org.argeo.slc.msg.test.tree.AddTreeTestResultAttachmentRequest;\r
import org.argeo.slc.msg.test.tree.CloseTreeTestResultRequest;\r
import org.argeo.slc.msg.test.tree.CreateTreeTestResultRequest;\r
import org.argeo.slc.msg.test.tree.ResultPartRequest;\r
.getTestResultUuid());\r
}\r
} else {\r
- log\r
+ log\r
.trace("ResultUUID="\r
+ testRunDescriptor.getTestResultUuid());\r
addResultToCollection("default", testRunDescriptor\r
}\r
\r
public void addResultPart(ResultPartRequest msg) {\r
-// registerTestRunDescriptor(msg.getTestRunDescriptor());\r
+ // registerTestRunDescriptor(msg.getTestRunDescriptor());\r
\r
if (log.isTraceEnabled())\r
log.trace("Adding result part to test result #"\r
treeTestResultDao.close(msg.getResultUuid(), msg.getCloseDate());\r
}\r
\r
+ public void addAttachment(AddTreeTestResultAttachmentRequest msg) {\r
+ if (log.isTraceEnabled())\r
+ log.trace("Adding attachment " + msg.getAttachment()\r
+ + " to result #" + msg.getResultUuid());\r
+ treeTestResultDao.addAttachment(msg.getResultUuid(), msg\r
+ .getAttachment());\r
+\r
+ }\r
+\r
}\r
package org.argeo.slc.services.test;\r
\r
+import org.argeo.slc.msg.test.tree.AddTreeTestResultAttachmentRequest;\r
import org.argeo.slc.msg.test.tree.CloseTreeTestResultRequest;\r
import org.argeo.slc.msg.test.tree.CreateTreeTestResultRequest;\r
import org.argeo.slc.msg.test.tree.ResultPartRequest;\r
\r
public void addResultPart(ResultPartRequest msg);\r
\r
+ public void addAttachment(AddTreeTestResultAttachmentRequest msg);\r
+\r
public void closeTreeTestResult(CloseTreeTestResultRequest msg);\r
}\r
--- /dev/null
+package org.argeo.slc.web.mvc.attachment;\r
+\r
+import java.io.IOException;\r
+\r
+import javax.servlet.ServletException;\r
+import javax.servlet.ServletOutputStream;\r
+import javax.servlet.http.HttpServletRequest;\r
+import javax.servlet.http.HttpServletResponse;\r
+\r
+import org.argeo.slc.core.attachment.AttachmentsStorage;\r
+import org.argeo.slc.core.attachment.SimpleAttachment;\r
+import org.springframework.web.HttpRequestHandler;\r
+\r
+/** Returns one single result. */\r
+public class GetAttachmentHandler implements HttpRequestHandler {\r
+ private AttachmentsStorage attachmentsStorage;\r
+\r
+ public void handleRequest(HttpServletRequest request,\r
+ HttpServletResponse response) throws ServletException, IOException {\r
+ String uuid = request.getParameter("uuid");\r
+ String contentType = request.getParameter("contentType");\r
+ SimpleAttachment resourceDescriptor = new SimpleAttachment();\r
+ resourceDescriptor.setUuid(uuid);\r
+ resourceDescriptor.setContentType(contentType);\r
+\r
+ response.setContentType(contentType);\r
+ ServletOutputStream outputStream = response.getOutputStream();\r
+ attachmentsStorage.retrieveAttachment(resourceDescriptor, outputStream);\r
+ }\r
+\r
+ public void setAttachmentsStorage(AttachmentsStorage attachmentsStorage) {\r
+ this.attachmentsStorage = attachmentsStorage;\r
+ }\r
+\r
+}\r
--- /dev/null
+package org.argeo.slc.jms;
+
+import java.io.ByteArrayInputStream;
+import java.io.InputStream;
+
+import javax.jms.BytesMessage;
+import javax.jms.JMSException;
+import javax.jms.Message;
+import javax.jms.MessageListener;
+
+import org.apache.commons.io.IOUtils;
+import org.argeo.slc.SlcException;
+import org.argeo.slc.core.attachment.AttachmentsStorage;
+import org.argeo.slc.core.attachment.SimpleAttachment;
+
+public class JmsAttachmentListener implements MessageListener {
+ private AttachmentsStorage attachmentsStorage;
+
+ public void onMessage(Message msg) {
+ BytesMessage message = (BytesMessage) msg;
+
+ InputStream in = null;
+ try {
+ SimpleAttachment attachment = new SimpleAttachment();
+ attachment.setUuid(msg
+ .getStringProperty(JmsAttachmentUploader.ATTACHMENT_ID));
+ attachment.setName(msg
+ .getStringProperty(JmsAttachmentUploader.ATTACHMENT_NAME));
+ attachment
+ .setContentType(msg
+ .getStringProperty(JmsAttachmentUploader.ATTACHMENT_CONTENT_TYPE));
+
+ byte[] buffer = new byte[(int) message.getBodyLength()];
+ message.readBytes(buffer);
+ in = new ByteArrayInputStream(buffer);
+ attachmentsStorage.storeAttachment(attachment, in);
+ } catch (JMSException e) {
+ throw new SlcException("Could not process attachment message "
+ + msg, e);
+ }
+ IOUtils.closeQuietly(in);
+ }
+
+ public void setAttachmentsStorage(AttachmentsStorage attachmentsStorage) {
+ this.attachmentsStorage = attachmentsStorage;
+ }
+
+}
--- /dev/null
+package org.argeo.slc.jms;
+
+import java.io.BufferedInputStream;
+import java.io.BufferedOutputStream;
+import java.io.IOException;
+
+import javax.jms.BytesMessage;
+import javax.jms.Destination;
+import javax.jms.JMSException;
+import javax.jms.Message;
+import javax.jms.Session;
+
+import org.argeo.slc.SlcException;
+import org.argeo.slc.core.attachment.Attachment;
+import org.argeo.slc.core.attachment.AttachmentUploader;
+import org.springframework.core.io.Resource;
+import org.springframework.jms.core.JmsTemplate;
+import org.springframework.jms.core.MessageCreator;
+
+public class JmsAttachmentUploader implements AttachmentUploader {
+ public final static String ATTACHMENT_ID = "slc_attachmentId";
+ public final static String ATTACHMENT_NAME = "slc_attachmentName";
+ public final static String ATTACHMENT_CONTENT_TYPE = "slc_attachmentContentType";
+
+ private JmsTemplate jmsTemplate;
+ private Destination destination;
+
+ public void upload(final Attachment attachment, final Resource resource) {
+ jmsTemplate.send(destination, new MessageCreator() {
+
+ public Message createMessage(Session session) throws JMSException {
+ BytesMessage message = session.createBytesMessage();
+ message.setStringProperty(ATTACHMENT_ID, attachment.getUuid());
+ message
+ .setStringProperty(ATTACHMENT_NAME, attachment
+ .getName());
+ message.setStringProperty(ATTACHMENT_CONTENT_TYPE, attachment
+ .getContentType());
+
+ try {
+ BufferedInputStream in = new BufferedInputStream(resource
+ .getInputStream());
+ byte[] buffer = new byte[1024 * 1024];
+ while (in.read(buffer) > 0) {
+ message.writeBytes(buffer);
+ }
+ } catch (IOException e) {
+ throw new SlcException(
+ "Cannot write into byte message for attachment "
+ + attachment + " and resource " + resource,
+ e);
+ }
+ return message;
+ }
+ });
+
+ }
+
+ public void setJmsTemplate(JmsTemplate jmsTemplate) {
+ this.jmsTemplate = jmsTemplate;
+ }
+
+ public void setDestination(Destination destination) {
+ this.destination = destination;
+ }
+
+}
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.argeo.slc.SlcException;
+import org.argeo.slc.core.attachment.Attachment;
+import org.argeo.slc.core.attachment.SimpleAttachment;
import org.argeo.slc.core.test.tree.TreeTestResult;
+import org.argeo.slc.core.test.tree.TreeTestResultListener;
+import org.argeo.slc.msg.test.tree.AddTreeTestResultAttachmentRequest;
import org.argeo.slc.msg.test.tree.CloseTreeTestResultRequest;
import org.argeo.slc.msg.test.tree.CreateTreeTestResultRequest;
import org.argeo.slc.msg.test.tree.ResultPartRequest;
import org.argeo.slc.test.TestResultPart;
import org.springframework.jms.core.JmsTemplate;
-public class JmsTreeTestResultListener implements
- TestResultListener<TreeTestResult> {
+public class JmsTreeTestResultListener implements TreeTestResultListener {
private final Log log = LogFactory.getLog(getClass());
private Boolean onlyOnClose = false;
private JmsTemplate jmsTemplate;
private Destination executionEventDestination;
-// private Destination createDestination;
-// private Destination addResultPartDestination;
-// private Destination closeDestination;
+
+ // private Destination createDestination;
+ // private Destination addResultPartDestination;
+ // private Destination closeDestination;
public void resultPartAdded(TreeTestResult testResult,
TestResultPart testResultPart) {
}
}
+ public void addAttachment(TreeTestResult testResult, Attachment attachment) {
+ try {
+ AddTreeTestResultAttachmentRequest req = new AddTreeTestResultAttachmentRequest();
+ req.setResultUuid(testResult.getUuid());
+ req.setAttachment((SimpleAttachment) attachment);
+ jmsTemplate.convertAndSend(executionEventDestination, req);
+
+ } catch (Exception e) {
+ throw new SlcException("Could not notify to JMS", e);
+ }
+
+ }
+
public void setOnlyOnClose(Boolean onlyOnClose) {
this.onlyOnClose = onlyOnClose;
}
this.jmsTemplate = jmsTemplate;
}
- public void setExecutionEventDestination(Destination executionEventDestination) {
+ public void setExecutionEventDestination(
+ Destination executionEventDestination) {
this.executionEventDestination = executionEventDestination;
}
-
-
-
-// public void setCreateDestination(Destination createDestination) {
-// this.createDestination = createDestination;
-// }
-//
-// public void setAddResultPartDestination(Destination addResultPartDestination) {
-// this.addResultPartDestination = addResultPartDestination;
-// }
-//
-// public void setCloseDestination(Destination closeDestination) {
-// this.closeDestination = closeDestination;
-// }
}
<!-- Events -->
<bean id="slcJms.destination.events" p:physicalName="events"
parent="slcJms.amTopic" />
-
+
+ <!-- Attachments -->
+ <bean id="slcJms.destination.attachment.add" p:physicalName="attachment.add"
+ parent="slcJms.amQueue" />
+
<!-- Agent service -->
<bean id="slcJms.destination.agent.register" p:physicalName="agent.register"
parent="slcJms.amTopic" />
<bean id="slcJms.destination.execution.event" p:physicalName="execution.event"
parent="slcJms.amQueue" />
- <!-- Test result service
- <bean id="slcJms.destination.test.create" p:physicalName="test.create"
- parent="slcJms.amQueue" />
- <bean id="slcJms.destination.test.addResultPart" p:physicalName="test.addResultPart"
- parent="slcJms.amQueue" />
- <bean id="slcJms.destination.test.close" p:physicalName="test.close"
+ <!--
+ Test result service <bean id="slcJms.destination.test.create"
+ p:physicalName="test.create" parent="slcJms.amQueue" /> <bean
+ id="slcJms.destination.test.addResultPart"
+ p:physicalName="test.addResultPart" parent="slcJms.amQueue" /> <bean
+ id="slcJms.destination.test.close" p:physicalName="test.close"
parent="slcJms.amQueue" />
- -->
- <!-- TSLC Execution service
- <bean id="slcJms.destination.slcExecution.updateStatus"
+ -->
+ <!--
+ TSLC Execution service <bean
+ id="slcJms.destination.slcExecution.updateStatus"
p:physicalName="slcExecution.updateStatus" parent="slcJms.amQueue" />
- -->
+ -->
<!-- Templates -->
<bean id="slcJms.amQueue" class="org.apache.activemq.command.ActiveMQQueue"
abstract="true" />
</Export-Package>
<Import-Package>org.argeo.slc.*;resolution:=optional,
org.argeo.slc.execution;resolution:=optional,
+ org.argeo.slc.core.attachment;resolution:=optional,
org.argeo.slc.core.structure;resolution:=optional,
org.argeo.slc.core.structure.tree;resolution:=optional,
org.argeo.slc.core.test;resolution:=optional,
--- /dev/null
+<?xml version="1.0"?>\r
+\r
+<!DOCTYPE mapping PUBLIC "-//EXOLAB/Castor Mapping DTD Version 1.0//EN" "http://castor.org/mapping.dtd">\r
+\r
+<mapping>\r
+ <description>Attachment objects XML mapping</description>\r
+\r
+ <class name="org.argeo.slc.core.attachment.SimpleAttachment">\r
+ <map-to ns-uri="http://argeo.org/projects/slc/schemas"\r
+ ns-prefix="slc" />\r
+ <field name="uuid" type="string" />\r
+ <field name="name" type="string" />\r
+ <field name="contentType" type="string" />\r
+ </class>\r
+\r
+</mapping>
\ No newline at end of file
<field name="resultUuid" />
<field name="closeDate" />
</class>
+
+ <class name="org.argeo.slc.msg.test.tree.AddTreeTestResultAttachmentRequest">
+ <map-to ns-uri="http://argeo.org/projects/slc/schemas"
+ ns-prefix="slc" />
+ <field name="resultUuid" />
+ <field name="attachment" type="org.argeo.slc.core.attachment.SimpleAttachment">
+ <bind-xml auto-naming="deriveByClass" />
+ </field>
+ </class>
<class name="org.argeo.slc.msg.test.tree.ResultPartRequest">
<map-to ns-uri="http://argeo.org/projects/slc/schemas"
<value>
classpath:org/argeo/slc/castor/execution.xml
</value>
+ <value>
+ classpath:org/argeo/slc/castor/attachment.xml
+ </value>
</list>
</property>
<property name="whitespacePreserve" value="true" />
<mapping>
<description>Test objects XML mapping</description>
- <class name="org.argeo.slc.test.TestRunDescriptor"
- auto-complete="false">
+ <class name="org.argeo.slc.test.TestRunDescriptor" auto-complete="false">
<map-to ns-uri="http://argeo.org/projects/slc/schemas"
ns-prefix="slc" />
<field name="testRunUuid" />
<field name="attributes" collection="map">
<bind-xml name="attribute" location="attributes">
<class name="org.exolab.castor.mapping.MapItem">
- <map-to
- ns-uri="http://argeo.org/projects/slc/schemas" ns-prefix="slc" />
+ <map-to ns-uri="http://argeo.org/projects/slc/schemas"
+ ns-prefix="slc" />
<field name="key" type="string">
<bind-xml name="name" node="attribute" />
</field>
<field name="resultParts" collection="sortedmap">
<bind-xml name="result-part" location="result-parts">
<class name="org.exolab.castor.mapping.MapItem">
- <map-to
- ns-uri="http://argeo.org/projects/slc/schemas" ns-prefix="slc" />
- <field name="key"
- type="org.argeo.slc.core.structure.tree.TreeSPath"
+ <map-to ns-uri="http://argeo.org/projects/slc/schemas"
+ ns-prefix="slc" />
+ <field name="key" type="org.argeo.slc.core.structure.tree.TreeSPath"
handler="org.argeo.slc.castor.structure.tree.TreeSPathFieldHandler">
<bind-xml name="path" node="attribute" />
</field>
- <field name="value"
- type="org.argeo.slc.core.test.tree.PartSubList">
+ <field name="value" type="org.argeo.slc.core.test.tree.PartSubList">
<bind-xml name="part-sub-list" />
</field>
</class>
<field name="elements" collection="sortedmap">
<bind-xml name="element" location="elements">
<class name="org.exolab.castor.mapping.MapItem">
- <map-to
- ns-uri="http://argeo.org/projects/slc/schemas" ns-prefix="slc" />
- <field name="key"
- type="org.argeo.slc.core.structure.tree.TreeSPath"
+ <map-to ns-uri="http://argeo.org/projects/slc/schemas"
+ ns-prefix="slc" />
+ <field name="key" type="org.argeo.slc.core.structure.tree.TreeSPath"
handler="org.argeo.slc.castor.structure.tree.TreeSPathFieldHandler">
<bind-xml name="path" node="attribute" />
</field>
- <field name="value"
- type="org.argeo.slc.core.structure.SimpleSElement">
+ <field name="value" type="org.argeo.slc.core.structure.SimpleSElement">
<bind-xml auto-naming="deriveByClass" />
</field>
</class>
</bind-xml>
</field>
+ <field name="attachments" collection="arraylist"
+ type="org.argeo.slc.core.attachment.SimpleAttachment">
+ <bind-xml auto-naming="deriveByClass" location="attachments" />
+ </field>
</class>
<class name="org.argeo.slc.core.test.tree.PartSubList"
import java.util.SortedMap;\r
\r
import org.argeo.slc.SlcException;\r
+import org.argeo.slc.core.attachment.SimpleAttachment;\r
import org.argeo.slc.core.structure.tree.TreeSPath;\r
import org.argeo.slc.core.test.SimpleResultPart;\r
import org.argeo.slc.core.test.tree.PartSubList;\r
\r
}\r
\r
+ public void addAttachment(final String testResultId,\r
+ final SimpleAttachment attachment) {\r
+ getHibernateTemplate().execute(new HibernateCallback() {\r
+\r
+ public Object doInHibernate(Session session)\r
+ throws HibernateException, SQLException {\r
+ TreeTestResult treeTestResult = getTreeTestResult(session,\r
+ testResultId);\r
+ treeTestResult.getAttachments().add(attachment);\r
+ session.update(treeTestResult);\r
+ return treeTestResult;\r
+ }\r
+ });\r
+\r
+ }\r
+\r
protected TreeTestResult getTreeTestResult(Session session,\r
String testResultId) {\r
TreeTestResult treeTestResult = (TreeTestResult) session.get(\r
--- /dev/null
+<?xml version="1.0"?>
+<!DOCTYPE hibernate-mapping PUBLIC\r
+ "-//Hibernate/Hibernate Mapping DTD 3.0//EN"\r
+ "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">\r
+<hibernate-mapping package="org.argeo.slc.core.attachment">\r
+ <class name="SimpleAttachment" table="SIMPLE_ATTACHMENT">\r
+ <cache usage="nonstrict-read-write" />\r
+ <id name="uuid" column="UUID" />
+ <property name="name" column="NAME" not-null="true" />\r
+ <property name="contentType" column="CONTENT_TYPE" not-null="true" />\r
+ </class>
+</hibernate-mapping>
\ No newline at end of file
<value>
org/argeo/slc/hibernate/runtime/SlcAgentDescriptor.hbm.xml
</value>
+ <value>
+ org/argeo/slc/hibernate/attachment/SimpleAttachment.hbm.xml
+ </value>
</list>
</property>
<property name="cacheProvider" ref="slcDefault.cacheProvider.ehCache" />
<cache usage="read-write" />\r
<id name="uuid" column="UUID" />\r
\r
- <property name="closeDate" column="CLOSE_DATE" type="timestamp"
+ <property name="closeDate" column="CLOSE_DATE" type="timestamp"\r
not-null="false" />
- <map name="attributes" table="TTR_ATTRS_MAP" cascade="all"
- lazy="false" sort="natural">
+ <map name="attributes" table="TTR_ATTRS_MAP" cascade="all" lazy="false"
+ sort="natural">
<cache usage="read-write" />
<key column="PARENT_ID" />
<map-key column="ATTR_NAME" type="string" />
sort="natural">
<cache usage="nonstrict-read-write" />
<key column="PARENT_ID" />
- <composite-map-key
- class="org.argeo.slc.core.structure.tree.TreeSPath">
+ <composite-map-key class="org.argeo.slc.core.structure.tree.TreeSPath">
<key-property name="asUniqueString" column="PATH" />
</composite-map-key>
<many-to-many class="PartSubList" column="PART_SUB_LIST_ID"
sort="natural">
<cache usage="nonstrict-read-write" />
<key column="PARENT_ID" />
- <composite-map-key
- class="org.argeo.slc.core.structure.tree.TreeSPath">
+ <composite-map-key class="org.argeo.slc.core.structure.tree.TreeSPath">
<key-property name="asUniqueString" column="PATH" />
</composite-map-key>
- <many-to-many
- class="org.argeo.slc.core.structure.SimpleSElement"
+ <many-to-many class="org.argeo.slc.core.structure.SimpleSElement"
column="ELEMENT_ID" unique="true" />
</map>
+
+ <list name="attachments" table="RESULTS_ATTACHMENTS" cascade="all">
+ <cache usage="nonstrict-read-write" />
+ <key column="RESULT_ATTACHMENT_ID" />
+ <list-index column="INDX" />
+ <many-to-many class="org.argeo.slc.core.attachment.SimpleAttachment"
+ column="ATTACHMENT_ID" unique="true" />
+ </list>
</class>
</hibernate-mapping>
\ No newline at end of file
--- /dev/null
+package org.argeo.slc.core.attachment;
+
+public interface Attachment {
+ public String getUuid();
+
+ public String getName();
+
+ public String getContentType();
+}
--- /dev/null
+package org.argeo.slc.core.attachment;
+
+import org.springframework.core.io.Resource;
+
+public interface AttachmentUploader {
+ public void upload(Attachment attachment, Resource resource);
+}
--- /dev/null
+package org.argeo.slc.core.attachment;
+
+public interface AttachmentsEnabled {
+ public void addAttachment(Attachment attachment);
+}
--- /dev/null
+package org.argeo.slc.core.attachment;
+
+import java.io.InputStream;
+import java.io.OutputStream;
+
+
+public interface AttachmentsStorage {
+ public void retrieveAttachment(Attachment attachment,
+ OutputStream outputStream);
+
+ public void storeAttachment(Attachment attachment, InputStream inputStream);
+}
--- /dev/null
+package org.argeo.slc.core.attachment;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+
+import org.apache.commons.io.IOUtils;
+import org.argeo.slc.SlcException;
+
+public class FileAttachmentsStorage implements AttachmentsStorage {
+ private File attachmentsDirectory = new File(System
+ .getProperty("java.io.tmpdir")
+ + File.separator + "slcAttachments");
+
+ public void retrieveAttachment(Attachment attachment,
+ OutputStream outputStream) {
+ File file = getFile(attachment);
+ InputStream in = null;
+ try {
+ byte[] buffer = new byte[1024 * 1024];
+ in = new FileInputStream(file);
+ while (in.read(buffer) >= 0) {
+ outputStream.write(buffer);
+ }
+ } catch (IOException e) {
+ throw new SlcException("Cannot write attachment " + attachment
+ + " to " + file, e);
+ } finally {
+ IOUtils.closeQuietly(in);
+ }
+ }
+
+ public void storeAttachment(Attachment attachment, InputStream inputStream) {
+ File file = getFile(attachment);
+ FileOutputStream out = null;
+ try {
+ byte[] buffer = new byte[1024 * 1024];
+ out = new FileOutputStream(file);
+ while (inputStream.read(buffer) >= 0) {
+ out.write(buffer);
+ }
+ } catch (IOException e) {
+ throw new SlcException("Cannot write attachment " + attachment
+ + " to " + file, e);
+ } finally {
+ IOUtils.closeQuietly(out);
+ }
+
+ }
+
+ protected File getFile(Attachment attachment) {
+ if (!attachmentsDirectory.exists())
+ attachmentsDirectory.mkdirs();
+ File file = new File(attachmentsDirectory + File.separator
+ + attachment.getUuid());
+ return file;
+ }
+}
--- /dev/null
+package org.argeo.slc.core.attachment;
+
+public class SimpleAttachment implements Attachment {
+ private String uuid;
+ private String name;
+ private String contentType;
+
+ public String getUuid() {
+ return uuid;
+ }
+
+ public void setUuid(String uuid) {
+ this.uuid = uuid;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public String getContentType() {
+ return contentType;
+ }
+
+ public void setContentType(String contentType) {
+ this.contentType = contentType;
+ }
+
+ public String toString() {
+ return "Attachment #" + uuid + "(" + name + ", " + contentType + ")";
+ }
+
+ public boolean equals(Object obj) {
+ if (obj instanceof Attachment) {
+ Attachment attachment = (Attachment) obj;
+ if (uuid != null && attachment.getUuid() != null)
+ return uuid.equals(attachment.getUuid());
+
+ if (name != null && attachment.getName() != null)
+ return name.equals(attachment.getName());
+
+ return hashCode() == attachment.hashCode();
+ }
+ return false;
+ }
+}
--- /dev/null
+package org.argeo.slc.core.execution.tasks;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.argeo.slc.core.attachment.Attachment;
+import org.argeo.slc.core.attachment.AttachmentUploader;
+import org.argeo.slc.core.attachment.AttachmentsEnabled;
+import org.springframework.core.io.Resource;
+
+public class UploadAttachments implements Runnable {
+ private AttachmentUploader attachmentUploader;
+ private Map<Attachment, Resource> attachments = new HashMap<Attachment, Resource>();
+ private List<AttachmentsEnabled> attachTo = new ArrayList<AttachmentsEnabled>();
+
+ public void run() {
+ for (Attachment attachment : attachments.keySet()) {
+ Resource resource = attachments.get(attachment);
+ attachmentUploader.upload(attachment, resource);
+ for (AttachmentsEnabled attachmentsEnabled : attachTo) {
+ attachmentsEnabled.addAttachment(attachment);
+ }
+ }
+
+ }
+
+ public void setAttachmentUploader(AttachmentUploader attachmentUploader) {
+ this.attachmentUploader = attachmentUploader;
+ }
+
+ public void setAttachments(Map<Attachment, Resource> attachments) {
+ this.attachments = attachments;
+ }
+
+ public void setAttachTo(List<AttachmentsEnabled> attachTo) {
+ this.attachTo = attachTo;
+ }
+
+
+}
package org.argeo.slc.core.test.tree;\r
\r
+import java.util.ArrayList;\r
import java.util.Date;\r
import java.util.List;\r
import java.util.Map;\r
import org.apache.commons.logging.Log;\r
import org.apache.commons.logging.LogFactory;\r
import org.argeo.slc.SlcException;\r
+import org.argeo.slc.core.attachment.Attachment;\r
+import org.argeo.slc.core.attachment.AttachmentsEnabled;\r
import org.argeo.slc.core.structure.tree.TreeSPath;\r
import org.argeo.slc.structure.StructureAware;\r
import org.argeo.slc.structure.StructureElement;\r
* structure.\r
*/\r
public class TreeTestResult implements TestResult, StructureAware<TreeSPath>,\r
- Comparable<TreeTestResult> {\r
+ Comparable<TreeTestResult>, AttachmentsEnabled {\r
private Log log = LogFactory.getLog(TreeTestResult.class);\r
\r
private List<TestResultListener<TreeTestResult>> listeners = new Vector<TestResultListener<TreeTestResult>>();\r
\r
private SortedMap<TreeSPath, PartSubList> resultParts = new TreeMap<TreeSPath, PartSubList>();\r
private SortedMap<TreeSPath, StructureElement> elements = new TreeMap<TreeSPath, StructureElement>();\r
+ private List<Attachment> attachments = new ArrayList<Attachment>();\r
\r
private Map<String, String> attributes = new TreeMap<String, String>();\r
\r
this.warnIfAlreadyClosed = warnIfAlreadyClosed;\r
}\r
\r
+ public List<Attachment> getAttachments() {\r
+ return attachments;\r
+ }\r
+\r
+ public void setAttachments(List<Attachment> attachments) {\r
+ this.attachments = attachments;\r
+ }\r
+\r
+ public void addAttachment(Attachment attachment) {\r
+ attachments.add(attachment);\r
+ synchronized (listeners) {\r
+ for (TestResultListener<TreeTestResult> listener : listeners) {\r
+ if (listener instanceof TreeTestResultListener)\r
+ ((TreeTestResultListener) listener).addAttachment(this,\r
+ attachment);\r
+ }\r
+ }\r
+ }\r
+\r
}\r
--- /dev/null
+package org.argeo.slc.core.test.tree;
+
+import org.argeo.slc.core.attachment.Attachment;
+import org.argeo.slc.test.TestResultListener;
+
+public interface TreeTestResultListener extends
+ TestResultListener<TreeTestResult> {
+ public void addAttachment(TreeTestResult testResult,
+ Attachment attachment);
+}
\r
import org.apache.commons.logging.Log;\r
import org.apache.commons.logging.LogFactory;\r
-\r
-import org.argeo.slc.test.TestResultListener;\r
+import org.argeo.slc.core.attachment.Attachment;\r
import org.argeo.slc.test.TestResultPart;\r
import org.argeo.slc.test.TestStatus;\r
\r
* @see TreeTestResult\r
* \r
*/\r
-public class TreeTestResultLogger implements TestResultListener<TreeTestResult> {\r
+public class TreeTestResultLogger implements TreeTestResultListener {\r
\r
private static Log log = LogFactory.getLog(TreeTestResultLogger.class);\r
\r
this.logExceptionMessages = logExceptionMessages;\r
}\r
\r
+ public void addAttachment(TreeTestResult treeTestResult,\r
+ Attachment attachment) {\r
+ if (log.isDebugEnabled())\r
+ log.debug("Attachment " + attachment + " added to "\r
+ + treeTestResult.getUuid());\r
+ }\r
+\r
}\r
import java.util.List;\r
import java.util.Map;\r
\r
+import org.argeo.slc.core.attachment.SimpleAttachment;\r
import org.argeo.slc.core.structure.tree.TreeSPath;\r
import org.argeo.slc.core.test.SimpleResultPart;\r
import org.argeo.slc.core.test.tree.TreeTestResult;\r
/** Update attributes */\r
public void updateAttributes(String testResultId,\r
Map<String, String> attributes);\r
+\r
+ public void addAttachment(String testResultId, SimpleAttachment attachment);\r
}\r
--- /dev/null
+package org.argeo.slc.msg.test.tree;
+
+import org.argeo.slc.core.attachment.SimpleAttachment;
+
+public class AddTreeTestResultAttachmentRequest {
+ private String resultUuid;
+ private SimpleAttachment attachment;
+
+ public String getResultUuid() {
+ return resultUuid;
+ }
+
+ public void setResultUuid(String resultUuid) {
+ this.resultUuid = resultUuid;
+ }
+
+ public SimpleAttachment getAttachment() {
+ return attachment;
+ }
+
+ public void setAttachment(SimpleAttachment attachment) {
+ this.attachment = attachment;
+ }
+
+}
abstract="true" />
<bean id="task.overrideContextAware" class="org.argeo.slc.core.execution.tasks.OverrideContextAware"
abstract="true" />
+ <bean id="task.uploadAttachments" class="org.argeo.slc.core.execution.tasks.UploadAttachments"
+ abstract="true" />
</beans>
\ No newline at end of file
</property>
</bean>
+ <bean id="jmsAgent.attachmentUploader" class="org.argeo.slc.jms.JmsAttachmentUploader">
+ <property name="destination" ref="slcJms.destination.attachment.add" />
+ <property name="jmsTemplate" ref="jmsTemplate" />
+ </bean>
+
<bean id="jmsAgent.listener.pingAll" parent="jmsAgent.listener.template">
<property name="destination" ref="slcJms.destination.agent.pingAll" />
<property name="messageListener" ref="jmsAgent" />
<bean id="resultListener" class="org.argeo.slc.jms.JmsTreeTestResultListener">
<!-- <property name="createDestination" ref="slcJms.destination.test.create" />
<property name="addResultPartDestination" ref="slcJms.destination.test.addResultPart" />
- <property name="closeDestination" ref="slcJms.destination.test.close" /> -->
+ <property name="closeDestination" ref="slcJms.destination.test.close" />
+-->
<property name="executionEventDestination" ref="slcJms.destination.execution.event" />
<property name="jmsTemplate" ref="jmsTemplate" />
</bean>
<!-- SLC Execution Listener -->
<bean id="slcExecutionListener" class="org.argeo.slc.jms.JmsSlcExecutionNotifier">
- <!-- <property name="updateStatusDestination" ref="slcJms.destination.slcExecution.updateStatus" /> -->
+ <!-- <property name="updateStatusDestination" ref="slcJms.destination.slcExecution.updateStatus" />
+-->
<property name="jmsTemplate" ref="jmsTemplate" />
<property name="executionEventDestination" ref="slcJms.destination.execution.event" />
</bean>
http://www.springframework.org/schema/beans \r
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">\r
\r
- <service ref="resultListener" interface="org.argeo.slc.test.TestResultListener" />\r
+ <service ref="resultListener" interface="org.argeo.slc.core.test.tree.TreeTestResultListener" />\r
<service ref="slcExecutionListener" interface="org.argeo.slc.process.SlcExecutionNotifier" />\r
\r
<!-- Manager -->\r
\r
<service ref="modulesManager" interface="org.argeo.slc.execution.ExecutionModulesManager" />\r
\r
- <service interface="org.argeo.slc.test.TestResultListener">\r
+ <service ref="jmsAgent.attachmentUploader" interface="org.argeo.slc.core.attachment.AttachmentUploader" />\r
+\r
+ <service interface="org.argeo.slc.core.test.tree.TreeTestResultListener">\r
<beans:bean class="org.argeo.slc.core.test.tree.TreeTestResultLogger" />\r
</service>\r
\r
bean-name="jmsTransactionManager" />
<reference id="agentFactory" interface="org.argeo.slc.runtime.SlcAgentFactory" />
+ <reference id="attachmentsStorage"
+ interface="org.argeo.slc.core.attachment.AttachmentsStorage" />
<service ref="jmsEventListener" interface="org.argeo.slc.msg.event.SlcEventListener" />
<service ref="jmsEventPublisher" interface="org.argeo.slc.msg.event.SlcEventPublisher" />
<import resource="classpath:org/argeo/slc/activemq/spring.xml" />
+ <!-- Attachments -->
+
+ <bean id="attachmentStorage.jmsContainer.add" parent="listenerContainer">
+ <property name="destination" ref="slcJms.destination.attachment.add" />
+ <property name="messageListener">
+ <bean class="org.argeo.slc.jms.JmsAttachmentListener">
+ <property name="attachmentsStorage" ref="attachmentsStorage" />
+ </bean>
+ </property>
+ </bean>
+
<!-- Events -->
<bean id="jmsEventListener" class="org.argeo.slc.jms.JmsSlcEventListener"
init-method="init" destroy-method="close">
<service ref="agentService" interface="org.argeo.slc.services.runtime.AgentService" />
<service ref="slcExecutionService"
interface="org.argeo.slc.services.process.SlcExecutionService" />
+ <service ref="attachmentsStorage"
+ interface="org.argeo.slc.core.attachment.AttachmentsStorage" />
<reference interface="org.argeo.slc.dao.test.tree.TreeTestResultDao"
id="testResultDao" />
</property>
</bean>
+ <!-- Attachments -->
+ <bean id="attachmentsStorage" class="org.argeo.slc.core.attachment.FileAttachmentsStorage"></bean>
+
<!-- Events -->
<aop:aspectj-autoproxy />
<reference id="testManagerService"\r
interface="org.argeo.slc.services.test.TestManagerService" />\r
<reference id="agentService" interface="org.argeo.slc.services.runtime.AgentService" />\r
- <reference id="slcExecutionService" interface="org.argeo.slc.services.process.SlcExecutionService" />\r
+ <reference id="slcExecutionService"\r
+ interface="org.argeo.slc.services.process.SlcExecutionService" />\r
\r
<reference id="hibernateTransactionManager"\r
interface="org.springframework.transaction.PlatformTransactionManager"\r
\r
<reference id="eventListener" interface="org.argeo.slc.msg.event.SlcEventListener" />\r
\r
+ <reference id="attachmentsStorage"\r
+ interface="org.argeo.slc.core.attachment.AttachmentsStorage" />\r
+\r
</beans:beans>
\ No newline at end of file
<aop:scoped-proxy />
</bean>
+ <!-- Attachements -->
+ <bean name="/getAttachment.service" class="org.argeo.slc.web.mvc.attachment.GetAttachmentHandler">
+ <property name="attachmentsStorage" ref="attachmentsStorage" />
+ </bean>
+
<bean id="handlerMapping"
class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping">
<property name="interceptors">