From: Mathieu Baudier Date: Wed, 29 Jul 2009 14:27:55 +0000 (+0000) Subject: Fix issue with RealizedFlow XML too big X-Git-Tag: argeo-slc-2.1.7~1585 X-Git-Url: http://git.argeo.org/?a=commitdiff_plain;ds=sidebyside;h=2e5b26763f0e44d4be7c302aebcb759726de4d1f;hp=75d76f02dc7524ebee6c1996f87222eee991f4e6;p=gpl%2Fargeo-slc.git Fix issue with RealizedFlow XML too big git-svn-id: https://svn.argeo.org/slc/trunk@2829 4cfe0d0a-d680-48aa-b62c-e0a02a3f76cc --- diff --git a/modules/server/org.argeo.slc.webapp.war/WEB-INF/slc-service-servlet.xml b/modules/server/org.argeo.slc.webapp.war/WEB-INF/slc-service-servlet.xml index b4143a3ca..c381a31e3 100644 --- a/modules/server/org.argeo.slc.webapp.war/WEB-INF/slc-service-servlet.xml +++ b/modules/server/org.argeo.slc.webapp.war/WEB-INF/slc-service-servlet.xml @@ -59,6 +59,7 @@ + + diff --git a/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/attachment/AttachmentsStorage.java b/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/attachment/AttachmentsStorage.java index dfb75604e..7a5e8cdc3 100644 --- a/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/attachment/AttachmentsStorage.java +++ b/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/attachment/AttachmentsStorage.java @@ -3,10 +3,10 @@ package org.argeo.slc.core.attachment; 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); } diff --git a/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/attachment/FileAttachmentsStorage.java b/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/attachment/FileAttachmentsStorage.java index 0e70805c0..ed6cf485f 100644 --- a/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/attachment/FileAttachmentsStorage.java +++ b/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/attachment/FileAttachmentsStorage.java @@ -3,30 +3,55 @@ package org.argeo.slc.core.attachment; 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, @@ -40,6 +65,8 @@ public class FileAttachmentsStorage implements AttachmentsStorage { 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); @@ -58,6 +85,9 @@ public class FileAttachmentsStorage implements AttachmentsStorage { 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); @@ -67,9 +97,37 @@ public class FileAttachmentsStorage implements AttachmentsStorage { } + /** 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; diff --git a/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/attachment/SimpleAttachment.java b/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/attachment/SimpleAttachment.java index 1c1f13eb9..29b109311 100644 --- a/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/attachment/SimpleAttachment.java +++ b/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/attachment/SimpleAttachment.java @@ -7,6 +7,16 @@ public class SimpleAttachment implements Attachment { 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; } diff --git a/runtime/org.argeo.slc.server/src/main/java/org/argeo/slc/web/mvc/process/GetSlcExecution.java b/runtime/org.argeo.slc.server/src/main/java/org/argeo/slc/web/mvc/process/GetSlcExecution.java index eea87a6ab..fde2e932e 100644 --- a/runtime/org.argeo.slc.server/src/main/java/org/argeo/slc/web/mvc/process/GetSlcExecution.java +++ b/runtime/org.argeo.slc.server/src/main/java/org/argeo/slc/web/mvc/process/GetSlcExecution.java @@ -1,21 +1,33 @@ package org.argeo.slc.web.mvc.process; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; + import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; +import javax.xml.transform.stream.StreamSource; +import org.apache.commons.io.IOUtils; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.argeo.slc.core.attachment.Attachment; +import org.argeo.slc.core.attachment.AttachmentsStorage; import org.argeo.slc.dao.process.SlcExecutionDao; import org.argeo.slc.msg.ObjectList; import org.argeo.slc.process.SlcExecution; import org.argeo.slc.web.mvc.AbstractServiceController; import org.springframework.oxm.Unmarshaller; import org.springframework.web.servlet.ModelAndView; -import org.springframework.xml.transform.StringSource; /** Lists SLC executions possibly filtering them. */ public class GetSlcExecution extends AbstractServiceController { + private final static Log log = LogFactory.getLog(GetSlcExecution.class); + private SlcExecutionDao slcExecutionDao; private Unmarshaller unmarshaller; + private AttachmentsStorage attachmentsStorage; + @Override protected void handleServiceRequest(HttpServletRequest request, HttpServletResponse response, ModelAndView modelAndView) @@ -23,14 +35,41 @@ public class GetSlcExecution extends AbstractServiceController { String uuid = request.getParameter("uuid"); SlcExecution slcExecution = slcExecutionDao.getSlcExecution(uuid); - StringSource source = new StringSource(slcExecution - .getRealizedFlowsXml()); - ObjectList ol2 = (ObjectList) unmarshaller.unmarshal(source); - ol2.fill(slcExecution.getRealizedFlows()); + // StringSource source = new StringSource(slcExecution + // .getRealizedFlowsXml()); + // ObjectList ol2 = (ObjectList) unmarshaller.unmarshal(source); + // ol2.fill(slcExecution.getRealizedFlows()); + retrieveRealizedFlows(slcExecution); modelAndView.addObject(slcExecution); } + protected void retrieveRealizedFlows(SlcExecution slcExecution) { + Attachment attachment = NewSlcExecutionController + .realizedFlowsAttachment(slcExecution.getRealizedFlowsXml(), + slcExecution); + + ByteArrayOutputStream out = null; + ByteArrayInputStream in = null; + try { + // TODO: optimize with piped streams + out = new ByteArrayOutputStream(); + attachmentsStorage.retrieveAttachment(attachment, out); + + byte[] arr = out.toByteArray(); + in = new ByteArrayInputStream(arr); + StreamSource source = new StreamSource(in); + ObjectList ol = (ObjectList) unmarshaller.unmarshal(source); + ol.fill(slcExecution.getRealizedFlows()); + } catch (Exception e) { + log.error("Could not retrieve realized flows from attachment #" + + attachment.getUuid(), e); + } finally { + IOUtils.closeQuietly(in); + IOUtils.closeQuietly(out); + } + } + public void setSlcExecutionDao(SlcExecutionDao slcExecutionDao) { this.slcExecutionDao = slcExecutionDao; } @@ -39,4 +78,8 @@ public class GetSlcExecution extends AbstractServiceController { this.unmarshaller = unmarshaller; } + public void setAttachmentsStorage(AttachmentsStorage attachmentsStorage) { + this.attachmentsStorage = attachmentsStorage; + } + } diff --git a/runtime/org.argeo.slc.server/src/main/java/org/argeo/slc/web/mvc/process/NewSlcExecutionController.java b/runtime/org.argeo.slc.server/src/main/java/org/argeo/slc/web/mvc/process/NewSlcExecutionController.java index d4a67b19d..5f225bff5 100644 --- a/runtime/org.argeo.slc.server/src/main/java/org/argeo/slc/web/mvc/process/NewSlcExecutionController.java +++ b/runtime/org.argeo.slc.server/src/main/java/org/argeo/slc/web/mvc/process/NewSlcExecutionController.java @@ -1,13 +1,19 @@ package org.argeo.slc.web.mvc.process; import java.io.BufferedReader; +import java.io.ByteArrayInputStream; +import java.io.InputStream; import java.util.UUID; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; +import org.apache.commons.io.IOUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import org.argeo.slc.core.attachment.Attachment; +import org.argeo.slc.core.attachment.AttachmentsStorage; +import org.argeo.slc.core.attachment.SimpleAttachment; import org.argeo.slc.msg.MsgConstants; import org.argeo.slc.msg.ObjectList; import org.argeo.slc.process.SlcExecution; @@ -33,6 +39,8 @@ public class NewSlcExecutionController extends AbstractServiceController { private Marshaller marshaller; private SlcExecutionService slcExecutionService; + private AttachmentsStorage attachmentsStorage; + @Override protected void handleServiceRequest(HttpServletRequest request, HttpServletResponse response, ModelAndView modelAndView) @@ -76,10 +84,11 @@ public class NewSlcExecutionController extends AbstractServiceController { new SlcExecutionStep(SlcExecutionStep.TYPE_START, "Process started from the Web UI")); - ObjectList ol = new ObjectList(slcExecution.getRealizedFlows()); - StringResult result = new StringResult(); - marshaller.marshal(ol, result); - slcExecution.setRealizedFlowsXml(result.toString()); + // ObjectList ol = new ObjectList(slcExecution.getRealizedFlows()); + // StringResult result = new StringResult(); + // marshaller.marshal(ol, result); + // slcExecution.setRealizedFlowsXml(result.toString()); + storeRealizedFlows(slcExecution); slcExecutionService.newExecution(slcExecution); @@ -87,6 +96,29 @@ public class NewSlcExecutionController extends AbstractServiceController { agent.runSlcExecution(slcExecution); } + protected void storeRealizedFlows(SlcExecution slcExecution) { + Attachment attachment = realizedFlowsAttachment(UUID.randomUUID() + .toString(), slcExecution); + InputStream in = null; + try { + + ObjectList ol = new ObjectList(slcExecution.getRealizedFlows()); + StringResult result = new StringResult(); + marshaller.marshal(ol, result); + + in = new ByteArrayInputStream(result.toString().getBytes()); + attachmentsStorage.storeAttachment(attachment, in); + + slcExecution.setRealizedFlowsXml(attachment.getUuid()); + + } catch (Exception e) { + log.error("Could not store realized flows as attachment #" + + attachment.getUuid(), e); + } finally { + IOUtils.closeQuietly(in); + } + } + public void setUnmarshaller(Unmarshaller unmarshaller) { this.unmarshaller = unmarshaller; } @@ -103,4 +135,15 @@ public class NewSlcExecutionController extends AbstractServiceController { this.marshaller = marshaller; } + public void setAttachmentsStorage(AttachmentsStorage attachmentsStorage) { + this.attachmentsStorage = attachmentsStorage; + } + + /** Unify labelling in the package */ + static Attachment realizedFlowsAttachment(String attachmentUuid, + SlcExecution slcExecution) { + return new SimpleAttachment(attachmentUuid, + "RealizedFlows of SlcExecution #" + slcExecution.getUuid(), + "text/xml"); + } } diff --git a/runtime/org.argeo.slc.specs/src/main/java/org/argeo/slc/process/SlcExecution.java b/runtime/org.argeo.slc.specs/src/main/java/org/argeo/slc/process/SlcExecution.java index 626af3eb6..88d37c4f5 100644 --- a/runtime/org.argeo.slc.specs/src/main/java/org/argeo/slc/process/SlcExecution.java +++ b/runtime/org.argeo.slc.specs/src/main/java/org/argeo/slc/process/SlcExecution.java @@ -28,6 +28,8 @@ public class SlcExecution implements Serializable { /** TODO: Synchronize */ private List steps = new ArrayList(); private List realizedFlows = new ArrayList(); + + /** Attachment uuid. */ private String realizedFlowsXml = null; public List getRealizedFlows() { @@ -145,10 +147,16 @@ public class SlcExecution implements Serializable { } } + /** + * Not (yet) a stable API, should not be relied upon! + * + * @return an id or an url allowing to retrieve the XML, not the XML itself! + */ public String getRealizedFlowsXml() { return realizedFlowsXml; } + /** Not (yet) a stable API, should not be relied upon! */ public void setRealizedFlowsXml(String realizedFlowsXml) { this.realizedFlowsXml = realizedFlowsXml; }