changeset 28:caa0bf9511bc

merge
author Sebastien Jodogne <s.jodogne@gmail.com>
date Fri, 03 Jul 2015 10:46:05 +0200
parents 56a4d23ab688 (current diff) 1796c2dce76e (diff)
children 1ffcfc3b0e24
files Core/MultipartWriter.cpp Core/MultipartWriter.h Resources/CMake/GdcmConfiguration.cmake
diffstat 14 files changed, 103 insertions(+), 163 deletions(-) [+]
line wrap: on
line diff
--- a/CMakeLists.txt	Fri Jul 03 10:45:38 2015 +0200
+++ b/CMakeLists.txt	Fri Jul 03 10:46:05 2015 +0200
@@ -82,7 +82,6 @@
   Core/Configuration.cpp
   Core/Dicom.cpp
   Core/DicomResults.cpp
-  Core/MultipartWriter.cpp
   Core/Toolbox.cpp
   )
 
--- a/Core/Dicom.cpp	Fri Jul 03 10:45:38 2015 +0200
+++ b/Core/Dicom.cpp	Fri Jul 03 10:46:05 2015 +0200
@@ -21,7 +21,6 @@
 #include "Dicom.h"
 
 #include "ChunkedBuffer.h"
-#include "MultipartWriter.h"
 
 #include <gdcmDictEntry.h>
 #include <gdcmStringFilter.h>
--- a/Core/DicomResults.cpp	Fri Jul 03 10:45:38 2015 +0200
+++ b/Core/DicomResults.cpp	Fri Jul 03 10:46:05 2015 +0200
@@ -24,15 +24,24 @@
 
 namespace OrthancPlugins
 {
-  DicomResults::DicomResults(const gdcm::Dict& dictionary,
+  DicomResults::DicomResults(OrthancPluginContext* context,
+                             OrthancPluginRestOutput* output,
+                             const gdcm::Dict& dictionary,
                              bool isXml,
                              bool isBulkAccessible) :
+    context_(context),
+    output_(output),
     dictionary_(dictionary),
-    xmlWriter_("application/dicom+xml"),
     isFirst_(true),
     isXml_(isXml),
     isBulkAccessible_(isBulkAccessible)
   {
+    if (isXml_ &&
+        OrthancPluginStartMultipartAnswer(context_, output_, "related", "application/dicom+xml") != 0)
+    {
+      throw std::runtime_error("Unable to create a multipart stream of DICOM+XML answers");
+    }
+
     jsonWriter_.AddChunk("[\n");
   }
 
@@ -44,7 +53,11 @@
     {
       std::string answer;
       GenerateSingleDicomAnswer(answer, dictionary_, file, dicom, true, isBulkAccessible_);
-      xmlWriter_.AddPart(answer);
+
+      if (OrthancPluginSendMultipartItem(context_, output_, answer.c_str(), answer.size()) != 0)
+      {
+        throw std::runtime_error("Unable to write an item to a multipart stream of DICOM+XML answers");
+      }
     }
     else
     {
@@ -61,12 +74,11 @@
     isFirst_ = false;
   }
 
-  void DicomResults::Answer(OrthancPluginContext* context,
-                            OrthancPluginRestOutput* output)
+  void DicomResults::Answer()
   {
     if (isXml_)
     {
-      xmlWriter_.Answer(context, output);
+      // Nothing to do in this case
     }
     else
     {
@@ -74,7 +86,7 @@
 
       std::string answer;
       jsonWriter_.Flatten(answer);
-      OrthancPluginAnswerBuffer(context, output, answer.c_str(), answer.size(), "application/json");
+      OrthancPluginAnswerBuffer(context_, output_, answer.c_str(), answer.size(), "application/json");
     }
   }
 }
--- a/Core/DicomResults.h	Fri Jul 03 10:45:38 2015 +0200
+++ b/Core/DicomResults.h	Fri Jul 03 10:46:05 2015 +0200
@@ -20,9 +20,9 @@
 
 #pragma once
 
-#include "MultipartWriter.h"
 #include "ChunkedBuffer.h"
 
+#include <orthanc/OrthancCPlugin.h>
 #include <gdcmDataSet.h>
 #include <gdcmDict.h>
 #include <gdcmFile.h>
@@ -32,18 +32,21 @@
   class DicomResults
   {
   private:
-    const gdcm::Dict& dictionary_;
-    MultipartWriter   xmlWriter_;  // Used for XML output
-    ChunkedBuffer     jsonWriter_;  // Used for JSON output
-    bool              isFirst_; 
-    bool              isXml_;
-    bool              isBulkAccessible_;
+    OrthancPluginContext*     context_;
+    OrthancPluginRestOutput*  output_;
+    const gdcm::Dict&         dictionary_;
+    ChunkedBuffer             jsonWriter_;  // Used for JSON output
+    bool                      isFirst_; 
+    bool                      isXml_;
+    bool                      isBulkAccessible_;
 
     void AddInternal(const gdcm::File* file,
                      const gdcm::DataSet& dicom);
 
   public:
-    DicomResults(const gdcm::Dict& dictionary,
+    DicomResults(OrthancPluginContext* context,
+                 OrthancPluginRestOutput* output,
+                 const gdcm::Dict& dictionary,
                  bool isXml,
                  bool isBulkAccessible);
 
@@ -58,7 +61,6 @@
       AddInternal(&file, subset);
     }
 
-    void Answer(OrthancPluginContext* context,
-                OrthancPluginRestOutput* output);
+    void Answer();
   };
 }
--- a/Core/MultipartWriter.cpp	Fri Jul 03 10:45:38 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,57 +0,0 @@
-/**
- * Orthanc - A Lightweight, RESTful DICOM Store
- * Copyright (C) 2012-2015 Sebastien Jodogne, Medical Physics
- * Department, University Hospital of Liege, Belgium
- *
- * This program is free software: you can redistribute it and/or
- * modify it under the terms of the GNU Affero General Public License
- * as published by the Free Software Foundation, either version 3 of
- * the License, or (at your option) any later version.
- *
- * This program 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
- * Affero General Public License for more details.
- * 
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- **/
-
-
-#include "MultipartWriter.h"
-
-#include <boost/lexical_cast.hpp>
-
-namespace OrthancPlugins
-{
-  MultipartWriter::MultipartWriter(const std::string& contentType) : 
-    contentType_(contentType)
-  {
-    // Some random string
-    boundary_ = "123456789abcdefghijklmnopqrstuvwxyz@^";
-  }
-
-  void MultipartWriter::AddPart(const std::string& part)
-  {
-    std::string header = "--" + boundary_ + "\n";
-    header += "Content-Type: " + contentType_ + "\n";
-    header += "Content-Length: " + boost::lexical_cast<std::string>(part.size()) + "\n";
-    header += "MIME-Version: 1.0\n\n";
-    chunks_.AddChunk(header);
-    chunks_.AddChunk(part);
-    chunks_.AddChunk("\n");
-  }
-
-  void MultipartWriter::Answer(OrthancPluginContext* context,
-                               OrthancPluginRestOutput* output)
-  {
-    // Close the body
-    chunks_.AddChunk("--" + boundary_ + "--\n");
-
-    std::string header = "multipart/related; type=" + contentType_ + "; boundary=" + boundary_;
-
-    std::string body;
-    chunks_.Flatten(body);
-    OrthancPluginAnswerBuffer(context, output, body.c_str(), body.size(), header.c_str());
-  }
-}
--- a/Core/MultipartWriter.h	Fri Jul 03 10:45:38 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,44 +0,0 @@
-/**
- * Orthanc - A Lightweight, RESTful DICOM Store
- * Copyright (C) 2012-2015 Sebastien Jodogne, Medical Physics
- * Department, University Hospital of Liege, Belgium
- *
- * This program is free software: you can redistribute it and/or
- * modify it under the terms of the GNU Affero General Public License
- * as published by the Free Software Foundation, either version 3 of
- * the License, or (at your option) any later version.
- *
- * This program 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
- * Affero General Public License for more details.
- * 
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- **/
-
-
-#pragma once
-
-#include "ChunkedBuffer.h"
-
-#include <orthanc/OrthancCPlugin.h>
-
-namespace OrthancPlugins
-{
-  class MultipartWriter
-  {
-  private:
-    ChunkedBuffer  chunks_;
-    std::string    contentType_;
-    std::string    boundary_;
-
-  public:
-    MultipartWriter(const std::string& contentType);
-
-    void AddPart(const std::string& part);
-
-    void Answer(OrthancPluginContext* context,
-                OrthancPluginRestOutput* output);
-  };
-}
--- a/NEWS	Fri Jul 03 10:45:38 2015 +0200
+++ b/NEWS	Fri Jul 03 10:46:05 2015 +0200
@@ -3,6 +3,7 @@
 
 No official release yet. Still work in progress.
 
+* Use of Orthanc built-in API for multipart answers (requires Orthanc >= 0.9.1)
 * Support of WADO-RS - RetrieveMetadata
 * Support of Visual Studio 2008
 * Support of FreeBSD
--- a/Plugin/QidoRs.cpp	Fri Jul 03 10:45:38 2015 +0200
+++ b/Plugin/QidoRs.cpp	Fri Jul 03 10:46:05 2015 +0200
@@ -26,7 +26,6 @@
 #include "../Core/DicomResults.h"
 #include "../Core/Toolbox.h"
 #include "../Core/Configuration.h"
-#include "../Core/MultipartWriter.h"
 
 #include <gdcmTag.h>
 #include <list>
@@ -747,7 +746,7 @@
 
   std::string wadoBase = OrthancPlugins::Configuration::GetBaseUrl(configuration_, request) + "/wado-rs";
 
-  OrthancPlugins::DicomResults results(*dictionary_, IsXmlExpected(request), true);
+  OrthancPlugins::DicomResults results(context_, output, *dictionary_, IsXmlExpected(request), true);
 
   for (std::list<std::string>::const_iterator
          it = resources.begin(); it != resources.end(); it++)
@@ -765,7 +764,7 @@
     }
   }
 
-  results.Answer(context_, output);
+  results.Answer();
 }
 
 
--- a/Plugin/WadoRs.cpp	Fri Jul 03 10:45:38 2015 +0200
+++ b/Plugin/WadoRs.cpp	Fri Jul 03 10:46:05 2015 +0200
@@ -25,8 +25,6 @@
 #include "../Core/Configuration.h"
 #include "../Core/Dicom.h"
 #include "../Core/DicomResults.h"
-#include "../Core/MultipartWriter.h"
-
 
 static bool AcceptMultipartDicom(const OrthancPluginHttpRequest* request)
 {
@@ -182,20 +180,23 @@
     OrthancPluginSendHttpStatusCode(context_, output, 400);
     return 0;
   }
-  
+
+  if (OrthancPluginStartMultipartAnswer(context_, output, "related", "application/dicom"))
+  {
+    return -1;
+  }
   
-  OrthancPlugins::MultipartWriter writer("application/dicom");
   for (Json::Value::ArrayIndex i = 0; i < instances.size(); i++)
   {
     std::string uri = "/instances/" + instances[i]["ID"].asString() + "/file";
     std::string dicom;
-    if (OrthancPlugins::RestApiGetString(dicom, context_, uri))
+    if (OrthancPlugins::RestApiGetString(dicom, context_, uri) &&
+        OrthancPluginSendMultipartItem(context_, output, dicom.c_str(), dicom.size()) != 0)
     {
-      writer.AddPart(dicom);
+      return -1;
     }
   }
 
-  writer.Answer(context_, output);
   return 0;
 }
 
@@ -227,7 +228,7 @@
     }
   }
 
-  OrthancPlugins::DicomResults results(*dictionary_, isXml, true);
+  OrthancPlugins::DicomResults results(context_, output, *dictionary_, isXml, true);
   
   for (std::list<std::string>::const_iterator
          it = files.begin(); it != files.end(); ++it)
@@ -240,7 +241,7 @@
     }
   }
 
-  results.Answer(context_, output);
+  results.Answer();
 }
 
 
@@ -445,14 +446,17 @@
     std::string uri;
     if (LocateInstance(output, uri, request))
     {
-      OrthancPlugins::MultipartWriter writer("application/dicom");
-      std::string dicom;
-      if (OrthancPlugins::RestApiGetString(dicom, context_, uri + "/file"))
+      if (OrthancPluginStartMultipartAnswer(context_, output, "related", "application/dicom"))
       {
-        writer.AddPart(dicom);
+        return -1;
       }
-
-      writer.Answer(context_, output);
+  
+      std::string dicom;
+      if (OrthancPlugins::RestApiGetString(dicom, context_, uri + "/file") &&
+          OrthancPluginSendMultipartItem(context_, output, dicom.c_str(), dicom.size()) != 0)
+      {
+        return -1;
+      }
     }
 
     return 0;
@@ -649,9 +653,11 @@
       if (path.size() % 2 == 1 &&
           ExploreBulkData(result, path, 0, dicom.GetDataSet()))
       {
-        OrthancPlugins::MultipartWriter writer("application/octet-stream");
-        writer.AddPart(result);
-        writer.Answer(context_, output);
+        if (OrthancPluginStartMultipartAnswer(context_, output, "related", "application/octet-stream") != 0 ||
+            OrthancPluginSendMultipartItem(context_, output, result.c_str(), result.size()) != 0)
+        {
+          return -1;
+        }
       }
       else
       {
--- a/Resources/BuildInstructions.txt	Fri Jul 03 10:45:38 2015 +0200
+++ b/Resources/BuildInstructions.txt	Fri Jul 03 10:46:05 2015 +0200
@@ -7,6 +7,15 @@
 # make
 
 
+Dynamic linking for Ubuntu 14.04
+================================
+
+# mkdir Build
+# cd Build
+# cmake .. -DCMAKE_BUILD_TYPE=Debug -DUSE_GTEST_DEBIAN_SOURCE_PACKAGE=ON
+# make
+
+
 Dynamic linking for Ubuntu 12.10
 ================================
 
--- a/Resources/CMake/GdcmConfiguration.cmake	Fri Jul 03 10:45:38 2015 +0200
+++ b/Resources/CMake/GdcmConfiguration.cmake	Fri Jul 03 10:46:05 2015 +0200
@@ -50,11 +50,11 @@
     )
 
   if(MSVC)
+    set(Suffix ".lib")
     set(Prefix "")
-    set(Suffix ".lib")
   else()
+    set(Suffix ".a")
     list(GET CMAKE_FIND_LIBRARY_PREFIXES 0 Prefix)
-    set(Suffix ".a")
   endif()
 
   set(GDCM_LIBRARIES 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Resources/MinGW-W64-Toolchain32.cmake	Fri Jul 03 10:46:05 2015 +0200
@@ -0,0 +1,17 @@
+# the name of the target operating system
+set(CMAKE_SYSTEM_NAME Windows)
+
+# which compilers to use for C and C++
+set(CMAKE_C_COMPILER i686-w64-mingw32-gcc)
+set(CMAKE_CXX_COMPILER i686-w64-mingw32-g++)
+set(CMAKE_RC_COMPILER i686-w64-mingw32-windres)
+
+# here is the target environment located
+set(CMAKE_FIND_ROOT_PATH /usr/i686-w64-mingw32)
+
+# adjust the default behaviour of the FIND_XXX() commands:
+# search headers and libraries in the target environment, search 
+# programs in the host environment
+set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
+set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
+set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Resources/MinGW-W64-Toolchain64.cmake	Fri Jul 03 10:46:05 2015 +0200
@@ -0,0 +1,17 @@
+# the name of the target operating system
+set(CMAKE_SYSTEM_NAME Windows)
+
+# which compilers to use for C and C++
+set(CMAKE_C_COMPILER x86_64-w64-mingw32-gcc)
+set(CMAKE_CXX_COMPILER x86_64-w64-mingw32-g++)
+set(CMAKE_RC_COMPILER x86_64-w64-mingw32-windres)
+
+# here is the target environment located
+set(CMAKE_FIND_ROOT_PATH /usr/i686-w64-mingw32)
+
+# adjust the default behaviour of the FIND_XXX() commands:
+# search headers and libraries in the target environment, search 
+# programs in the host environment
+set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
+set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
+set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
--- a/Resources/MinGWToolchain.cmake	Fri Jul 03 10:45:38 2015 +0200
+++ b/Resources/MinGWToolchain.cmake	Fri Jul 03 10:46:05 2015 +0200
@@ -1,23 +1,3 @@
-# Orthanc - A Lightweight, RESTful DICOM Store
-# Copyright (C) 2012-2015 Sebastien Jodogne, Medical Physics
-# Department, University Hospital of Liege, Belgium
-#
-# This program is free software: you can redistribute it and/or
-# modify it under the terms of the GNU Affero General Public License
-# as published by the Free Software Foundation, either version 3 of
-# the License, or (at your option) any later version.
-#
-# This program 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
-# Affero General Public License for more details.
-# 
-# You should have received a copy of the GNU Affero General Public License
-# along with this program. If not, see <http://www.gnu.org/licenses/>.
-
-
-# http://www.vtk.org/Wiki/CmakeMingw
-
 # the name of the target operating system
 set(CMAKE_SYSTEM_NAME Windows)