From 97f8586fa0e7785a846e90a064ce011889afb83d Mon Sep 17 00:00:00 2001 From: Jesse Dowell Date: Wed, 15 Apr 2026 15:10:11 -0600 Subject: [PATCH 1/4] feat: add optional dcm4che5 DICOM backend with abstraction layer Add a dcm4che5 backend for the DICOM connector alongside the existing dcm4che2 backend. Backend selection is controlled at startup by the new dicom.library property in mirth.properties ("dcm4che2" default, "dcm4che5" to opt in). Existing channel configurations work unchanged on either backend. Architecture: - A version-neutral abstraction layer (OieDicomObject, OieDicomElement, OieDicomSender, OieDicomReceiver, OieDicomConverter, OieVR, DicomLibraryFactory) decouples connector logic from library specifics. - Dcm2* implementations wrap the existing dcm4che2 MirthDcmSnd/MirthDcmRcv. - Dcm5* implementations build an equivalent topology from dcm4che5's Device/Connection/ApplicationEntity primitives with the same external behaviour -- source-map keys, C-STORE/C-ECHO handling, storage commitment, transfer-syntax defaults. - MirthLauncher resolves a new variant="dicom.library:xxx" attribute on extension entries so only the configured backend's JARs land on the classpath at runtime. Build: - server/build.xml splits the DICOM extension into three JARs: dicom-server.jar (version-neutral, always loaded) dicom-server-dcm2.jar (loaded when dicom.library=dcm4che2) dicom-server-dcm5.jar (loaded when dicom.library=dcm4che5) The dcm2 JAR bundles the stock dcm4che-tool-dcmrcv/dcmsnd classes via zipfileset with duplicate="preserve" so patched classes take priority. - Adds dcm4che-core-5.34.3.jar and dcm4che-net-5.34.3.jar to server/lib/extensions/dimse/ and updates THIRD-PARTY-README.txt with MPL 1.1 attribution for the new version. Backward compatibility: - DICOMUtil.byteArrayToDicomObject and dicomObjectToByteArray keep their public signatures; the return type becomes OieDicomObject, which mirrors the dcm4che2 DicomObject surface methods (contains, size, isEmpty, getBytes, getDate, getFloat/getDouble with defaults, getStrings, getInts, vrOf, nameOf, vm, getNestedDicomObject). - OieDicomElement.vr() returns an OieVR adapter (code/padding/toString) matching dcm4che2 VR's runtime shape so scripts calling elem.vr().code() or String(elem.vr()) continue to work. - Verified by running identical JavaScript transformer scripts on the pre-patch baseline and on the patched branch: existing scripts that work on dcm4che2 continue to work on both backends unchanged. Tests: - Unit and integration coverage for the abstraction layer, both backends, cross-library parity, loopback C-STORE, C-ECHO, error handling, storage commitment, and TLS with ephemeral self-signed keystores. Integration tests use ephemeral ports and localhost only; all complete within a couple of seconds. - Ready-to-import manual test channels and an API regression script under server/tests/dicom-channels/ that exercise the full OieDicomObject and DICOMUtil surface through a live DICOM pipeline. Documentation: - docs/dcm4che5-migration-guide.md covers enabling the backend, behavioural differences, TLS configuration, custom DICOMConfiguration migration, JAR architecture, verification, and rollback. Signed-off-by: Jesse Dowell --- docs/dcm4che5-migration-guide.md | 302 +++++++++ server/build.xml | 34 +- server/conf/mirth.properties | 4 + server/docs/thirdparty/THIRD-PARTY-README.txt | 4 +- .../extensions/dimse/dcm4che-core-5.34.3.jar | Bin 0 -> 544274 bytes .../extensions/dimse/dcm4che-net-5.34.3.jar | Bin 0 -> 205771 bytes .../connectors/dimse/DICOMConfiguration.java | 63 +- .../dimse/DICOMConfigurationUtil.java | 88 +-- .../connectors/dimse/DICOMDispatcher.java | 99 ++- .../connectors/dimse/DICOMReceiver.java | 112 ++-- .../dimse/DefaultDICOMConfiguration.java | 29 +- .../dimse/DefaultDcm5DICOMConfiguration.java | 61 ++ .../connect/connectors/dimse/destination.xml | 12 +- .../dimse/dicom/DicomConstants.java | 65 ++ .../dimse/dicom/DicomLibraryFactory.java | 205 ++++++ .../dimse/dicom/OieDicomConverter.java | 68 ++ .../dimse/dicom/OieDicomElement.java | 76 +++ .../dimse/dicom/OieDicomObject.java | 123 ++++ .../dimse/dicom/OieDicomReceiver.java | 109 ++++ .../dimse/dicom/OieDicomSender.java | 138 +++++ .../dimse/dicom/OieDimseRspHandler.java | 25 + .../connect/connectors/dimse/dicom/OieVR.java | 31 + .../dicom/dcm2/Dcm2DICOMConfiguration.java | 75 +++ .../dimse/dicom/dcm2/Dcm2DicomConverter.java | 183 ++++++ .../dimse/dicom/dcm2/Dcm2DicomElement.java | 159 +++++ .../dimse/dicom/dcm2/Dcm2DicomObject.java | 265 ++++++++ .../dimse/dicom/dcm2/Dcm2DicomReceiver.java | 205 ++++++ .../dimse/dicom/dcm2/Dcm2DicomSender.java | 294 +++++++++ .../connectors/dimse/dicom/dcm2/Dcm2VR.java | 43 ++ .../dicom/dcm5/Dcm5DICOMConfiguration.java | 69 +++ .../dimse/dicom/dcm5/Dcm5DicomConverter.java | 169 +++++ .../dimse/dicom/dcm5/Dcm5DicomElement.java | 310 +++++++++ .../dimse/dicom/dcm5/Dcm5DicomObject.java | 285 +++++++++ .../dimse/dicom/dcm5/Dcm5DicomReceiver.java | 506 +++++++++++++++ .../dimse/dicom/dcm5/Dcm5DicomSender.java | 586 ++++++++++++++++++ .../dimse/dicom/dcm5/Dcm5TlsUtil.java | 32 + .../connectors/dimse/dicom/dcm5/Dcm5VR.java | 43 ++ .../mirth/connect/connectors/dimse/source.xml | 12 +- .../mirth/connect/model/ExtensionLibrary.java | 11 + .../model/converters/DICOMConverter.java | 109 +--- .../datatypes/dicom/DICOMReference.java | 13 +- .../datatypes/dicom/DICOMSerializer.java | 98 +-- .../dicom/DICOMAttachmentHandler.java | 18 +- .../server/launcher/MirthLauncher.java | 47 +- .../connect/server/userutil/DICOMUtil.java | 62 +- .../connect/server/util/DICOMMessageUtil.java | 21 +- .../org/dcm4che2/tool/dcmrcv/MirthDcmRcv.java | 6 +- .../org/dcm4che2/tool/dcmsnd/MirthDcmSnd.java | 6 +- .../connectors/dimse/DICOMDispatcherTest.java | 187 +++--- .../connectors/dimse/DICOMReceiverTest.java | 186 ++++++ .../dimse/dicom/DicomLibraryFactoryTest.java | 118 ++++ .../dimse/dicom/GenerateDicomTestFiles.java | 117 ++++ .../dcm2/Dcm2DICOMConfigurationTest.java | 109 ++++ .../dcm5/Dcm5DICOMConfigurationTest.java | 77 +++ .../dicom/dcm5/Dcm5DicomConverterTest.java | 156 +++++ .../dicom/dcm5/Dcm5DicomElementTest.java | 244 ++++++++ .../dimse/dicom/dcm5/Dcm5DicomObjectTest.java | 178 ++++++ .../dicom/dcm5/Dcm5DicomReceiverTest.java | 143 +++++ .../dimse/dicom/dcm5/Dcm5DicomSenderTest.java | 55 ++ .../ConverterParityIntegrationTest.java | 139 +++++ .../CrossLibraryIntegrationTest.java | 158 +++++ .../integration/Dcm5CEchoIntegrationTest.java | 76 +++ .../Dcm5ErrorHandlingIntegrationTest.java | 134 ++++ .../Dcm5LoopbackIntegrationTest.java | 231 +++++++ .../Dcm5StorageCommitmentIntegrationTest.java | 186 ++++++ .../integration/Dcm5TlsIntegrationTest.java | 164 +++++ .../integration/DicomIntegrationTestBase.java | 230 +++++++ .../DicomPerformanceBenchmark.java | 494 +++++++++++++++ .../launcher/MirthLauncherVariantTest.java | 65 ++ server/tests/dicom-channels/DICOM_Forward.xml | 221 +++++++ .../tests/dicom-channels/DICOM_Receiver.xml | 327 ++++++++++ server/tests/dicom-channels/README.md | 51 ++ server/tests/dicom-channels/dicom-api-test.js | 129 ++++ server/tests/test-dicom-input-1.dcm | Bin 0 -> 620 bytes server/tests/test-dicom-input-2.dcm | Bin 0 -> 592 bytes server/tests/test-dicom-input-3.dcm | Bin 0 -> 552 bytes server/tests/test-dicom-output-1.xml | 33 + server/tests/test-dicom-output-2.xml | 29 + server/tests/test-dicom-output-3.xml | 9 + 79 files changed, 9029 insertions(+), 492 deletions(-) create mode 100644 docs/dcm4che5-migration-guide.md create mode 100644 server/lib/extensions/dimse/dcm4che-core-5.34.3.jar create mode 100644 server/lib/extensions/dimse/dcm4che-net-5.34.3.jar create mode 100644 server/src/com/mirth/connect/connectors/dimse/DefaultDcm5DICOMConfiguration.java create mode 100644 server/src/com/mirth/connect/connectors/dimse/dicom/DicomConstants.java create mode 100644 server/src/com/mirth/connect/connectors/dimse/dicom/DicomLibraryFactory.java create mode 100644 server/src/com/mirth/connect/connectors/dimse/dicom/OieDicomConverter.java create mode 100644 server/src/com/mirth/connect/connectors/dimse/dicom/OieDicomElement.java create mode 100644 server/src/com/mirth/connect/connectors/dimse/dicom/OieDicomObject.java create mode 100644 server/src/com/mirth/connect/connectors/dimse/dicom/OieDicomReceiver.java create mode 100644 server/src/com/mirth/connect/connectors/dimse/dicom/OieDicomSender.java create mode 100644 server/src/com/mirth/connect/connectors/dimse/dicom/OieDimseRspHandler.java create mode 100644 server/src/com/mirth/connect/connectors/dimse/dicom/OieVR.java create mode 100644 server/src/com/mirth/connect/connectors/dimse/dicom/dcm2/Dcm2DICOMConfiguration.java create mode 100644 server/src/com/mirth/connect/connectors/dimse/dicom/dcm2/Dcm2DicomConverter.java create mode 100644 server/src/com/mirth/connect/connectors/dimse/dicom/dcm2/Dcm2DicomElement.java create mode 100644 server/src/com/mirth/connect/connectors/dimse/dicom/dcm2/Dcm2DicomObject.java create mode 100644 server/src/com/mirth/connect/connectors/dimse/dicom/dcm2/Dcm2DicomReceiver.java create mode 100644 server/src/com/mirth/connect/connectors/dimse/dicom/dcm2/Dcm2DicomSender.java create mode 100644 server/src/com/mirth/connect/connectors/dimse/dicom/dcm2/Dcm2VR.java create mode 100644 server/src/com/mirth/connect/connectors/dimse/dicom/dcm5/Dcm5DICOMConfiguration.java create mode 100644 server/src/com/mirth/connect/connectors/dimse/dicom/dcm5/Dcm5DicomConverter.java create mode 100644 server/src/com/mirth/connect/connectors/dimse/dicom/dcm5/Dcm5DicomElement.java create mode 100644 server/src/com/mirth/connect/connectors/dimse/dicom/dcm5/Dcm5DicomObject.java create mode 100644 server/src/com/mirth/connect/connectors/dimse/dicom/dcm5/Dcm5DicomReceiver.java create mode 100644 server/src/com/mirth/connect/connectors/dimse/dicom/dcm5/Dcm5DicomSender.java create mode 100644 server/src/com/mirth/connect/connectors/dimse/dicom/dcm5/Dcm5TlsUtil.java create mode 100644 server/src/com/mirth/connect/connectors/dimse/dicom/dcm5/Dcm5VR.java create mode 100644 server/test/com/mirth/connect/connectors/dimse/DICOMReceiverTest.java create mode 100644 server/test/com/mirth/connect/connectors/dimse/dicom/DicomLibraryFactoryTest.java create mode 100644 server/test/com/mirth/connect/connectors/dimse/dicom/GenerateDicomTestFiles.java create mode 100644 server/test/com/mirth/connect/connectors/dimse/dicom/dcm2/Dcm2DICOMConfigurationTest.java create mode 100644 server/test/com/mirth/connect/connectors/dimse/dicom/dcm5/Dcm5DICOMConfigurationTest.java create mode 100644 server/test/com/mirth/connect/connectors/dimse/dicom/dcm5/Dcm5DicomConverterTest.java create mode 100644 server/test/com/mirth/connect/connectors/dimse/dicom/dcm5/Dcm5DicomElementTest.java create mode 100644 server/test/com/mirth/connect/connectors/dimse/dicom/dcm5/Dcm5DicomObjectTest.java create mode 100644 server/test/com/mirth/connect/connectors/dimse/dicom/dcm5/Dcm5DicomReceiverTest.java create mode 100644 server/test/com/mirth/connect/connectors/dimse/dicom/dcm5/Dcm5DicomSenderTest.java create mode 100644 server/test/com/mirth/connect/connectors/dimse/dicom/integration/ConverterParityIntegrationTest.java create mode 100644 server/test/com/mirth/connect/connectors/dimse/dicom/integration/CrossLibraryIntegrationTest.java create mode 100644 server/test/com/mirth/connect/connectors/dimse/dicom/integration/Dcm5CEchoIntegrationTest.java create mode 100644 server/test/com/mirth/connect/connectors/dimse/dicom/integration/Dcm5ErrorHandlingIntegrationTest.java create mode 100644 server/test/com/mirth/connect/connectors/dimse/dicom/integration/Dcm5LoopbackIntegrationTest.java create mode 100644 server/test/com/mirth/connect/connectors/dimse/dicom/integration/Dcm5StorageCommitmentIntegrationTest.java create mode 100644 server/test/com/mirth/connect/connectors/dimse/dicom/integration/Dcm5TlsIntegrationTest.java create mode 100644 server/test/com/mirth/connect/connectors/dimse/dicom/integration/DicomIntegrationTestBase.java create mode 100644 server/test/com/mirth/connect/connectors/dimse/dicom/integration/DicomPerformanceBenchmark.java create mode 100644 server/test/com/mirth/connect/server/launcher/MirthLauncherVariantTest.java create mode 100644 server/tests/dicom-channels/DICOM_Forward.xml create mode 100644 server/tests/dicom-channels/DICOM_Receiver.xml create mode 100644 server/tests/dicom-channels/README.md create mode 100644 server/tests/dicom-channels/dicom-api-test.js create mode 100644 server/tests/test-dicom-input-1.dcm create mode 100644 server/tests/test-dicom-input-2.dcm create mode 100644 server/tests/test-dicom-input-3.dcm create mode 100644 server/tests/test-dicom-output-1.xml create mode 100644 server/tests/test-dicom-output-2.xml create mode 100644 server/tests/test-dicom-output-3.xml diff --git a/docs/dcm4che5-migration-guide.md b/docs/dcm4che5-migration-guide.md new file mode 100644 index 0000000000..7de102b78e --- /dev/null +++ b/docs/dcm4che5-migration-guide.md @@ -0,0 +1,302 @@ +# dcm4che5 Migration Guide + +This guide covers migrating the OIE DICOM connector from the dcm4che2 backend to dcm4che5. + +## Overview + +The DICOM connector supports two backends selectable at server startup: + +- **dcm4che2** (default) — The legacy backend wrapping `MirthDcmSnd`/`MirthDcmRcv` +- **dcm4che5** — The modern backend using dcm4che3 APIs (`Device`/`Connection`/`ApplicationEntity`) + +Both backends expose identical behavior through the version-neutral `OieDicomSender`, `OieDicomReceiver`, and `OieDicomConverter` interfaces. Existing channel configurations (DICOM Listener and DICOM Sender properties) work with either backend without modification — with one exception noted in the [TLS section](#tls-configuration). + +## Prerequisites + +- Java 17 or later +- OIE build that includes `dicom-server-dcm5.jar` (the standard build produces it alongside `dicom-server-dcm2.jar`) + +## Enabling dcm4che5 + +Edit `server/conf/mirth.properties` and uncomment or add: + +```properties +dicom.library = dcm4che5 +``` + +**Restart the server.** The property is read once at startup and cached. + +To revert, change the value back to `dcm4che2` (or remove the line) and restart. + +## What Changes + +### Transparent (no action needed) + +| Area | Behavior | +|------|----------| +| Channel properties | All DICOM Listener and Sender properties work identically | +| Source map keys | Same keys populated: `localApplicationEntityTitle`, `remoteApplicationEntityTitle`, `localAddress`, `localPort`, `remoteAddress`, `remotePort` | +| DICOM object serialization | Byte-level output differs (different FMI implementation version UIDs), but all tag values are semantically equivalent | +| C-STORE, C-ECHO | Both work through the standard channel lifecycle | +| Storage commitment | `N-ACTION` → `N-EVENT-REPORT` flow works through `commit()` / `waitForStgCmtResult()` | +| Transfer syntaxes | All standard transfer syntaxes supported | + +### Behavioral Differences + +| Area | dcm4che2 | dcm4che5 | +|------|----------|----------| +| **Architecture** | Thin wrapper around monolithic `MirthDcmSnd`/`MirthDcmRcv` | Composed from `Device` + `Connection` + `ApplicationEntity` + service handlers | +| **Element names** | `"Patient's Name"` (DICOM PS3.6 style) | `"PatientName"` (keyword style) | +| **C-STORE dispatch** | Synchronous — `send()` blocks until receiver processes | Asynchronous — `send()` returns immediately, receiver processes on worker thread | +| **XML serialization** | Standard `TransformerFactory` | Hardened `TransformerFactory` with XXE protections (`ACCESS_EXTERNAL_DTD` and `ACCESS_EXTERNAL_STYLESHEET` disabled) | +| **Keystore type** | Inferred automatically from URL | Inferred from file extension (`.p12`/`.pfx` → PKCS12, otherwise JKS); can be set explicitly via `setKeyStoreType()` | + +### Element Name Difference + +If your channel logic inspects DICOM element names (not tag numbers), be aware that dcm4che5 uses keyword-style names: + +```java +// dcm4che2: "Patient's Name" +// dcm4che5: "PatientName" + +// Safe approach: use tag numbers, which are identical across backends +dicomObject.getString(Tag.PatientName) // works on both +``` + +## TLS Configuration + +### Standard UI TLS Options + +The DICOM connector UI offers three TLS cipher presets: + +| UI Setting | Cipher Suite | Status | +|------------|-------------|--------| +| `aes` | `TLS_RSA_WITH_AES_128_CBC_SHA` | Disabled by default in current JDK security policies | +| `3des` | `SSL_RSA_WITH_3DES_EDE_CBC_SHA` | Disabled by default in current JDK security policies | +| `without` | `SSL_RSA_WITH_NULL_SHA` | Disabled by default in current JDK security policies | + +These legacy cipher suites are disabled by current JDK security policies (Java 17 and later). This affects both backends equally. If your channels use TLS with any of these presets, they will fail with an `SSLHandshakeException` until you supply a custom cipher suite via a `DICOMConfiguration` (see below). + +### Recommended: Custom Cipher Suites via DICOMConfiguration + +For TLS on Java 21, implement a custom `DICOMConfiguration` that uses modern cipher suites: + +**For dcm4che5:** + +```java +import com.mirth.connect.connectors.dimse.dicom.dcm5.Dcm5DICOMConfiguration; +import com.mirth.connect.connectors.dimse.dicom.dcm5.Dcm5DicomReceiver; +import com.mirth.connect.connectors.dimse.dicom.dcm5.Dcm5DicomSender; + +public class MyDcm5DICOMConfiguration implements Dcm5DICOMConfiguration { + + private static final String[] MODERN_CIPHERS = { + "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256", + "TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384" + }; + + @Override + public void configureDcm5Sender(Dcm5DicomSender sender, DICOMDispatcher connector, + DICOMDispatcherProperties props) throws Exception { + // Apply standard config first + DICOMConfigurationUtil.configureSender(sender, connector, props, protocols); + + // Override cipher suites with modern ones + if (!"notls".equals(props.getTls())) { + sender.setTlsCipherSuites(MODERN_CIPHERS); + } + } + + @Override + public void configureDcm5Receiver(Dcm5DicomReceiver receiver, DICOMReceiver connector, + DICOMReceiverProperties props) throws Exception { + DICOMConfigurationUtil.configureReceiver(receiver, connector, props, protocols); + + if (!"notls".equals(props.getTls())) { + receiver.setTlsCipherSuites(MODERN_CIPHERS); + } + } + + // ... remaining methods same as DefaultDcm5DICOMConfiguration +} +``` + +Then register your custom class. The `dicomConfigurationClass` is a Mirth **server configuration property** (stored in the database, not `mirth.properties`). Set it via the Mirth Administrator or REST API: + +``` +PUT /api/server/configuration/DICOM/dicomConfigurationClass +Body: com.example.MyDcm5DICOMConfiguration +``` + +And ensure dcm4che5 is enabled in `mirth.properties`: + +```properties +dicom.library = dcm4che5 +``` + +### Keystore Type + +dcm4che5 requires an explicit keystore/truststore type. The default behavior infers this from the file extension: + +| Extension | Inferred Type | +|-----------|--------------| +| `.p12`, `.pfx` | `PKCS12` | +| `.jks`, or anything else | `JKS` | + +If your keystore URL does not have a standard extension (e.g., loaded from a classpath resource or HTTP URL), set the type explicitly in your custom `DICOMConfiguration`: + +```java +sender.setKeyStoreType("PKCS12"); +sender.setTrustStoreType("PKCS12"); +``` + +## Custom DICOMConfiguration Migration + +If you have a custom `DICOMConfiguration` implementation: + +### If staying on dcm4che2 + +Change your class declaration from: + +```java +// Before (no longer compiles — DICOMConfiguration is now version-neutral) +public class MyConfig implements DICOMConfiguration { + void configureDcmSnd(MirthDcmSnd dcmsnd, ...) { ... } + void configureDcmRcv(MirthDcmRcv dcmrcv, ...) { ... } +} +``` + +To: + +```java +// After (one-line change — same method signatures) +public class MyConfig implements Dcm2DICOMConfiguration { + void configureDcmSnd(MirthDcmSnd dcmsnd, ...) { ... } + void configureDcmRcv(MirthDcmRcv dcmrcv, ...) { ... } +} +``` + +The `Dcm2DICOMConfiguration` interface has the same method signatures as the original pre-abstraction `DICOMConfiguration`. The bridge defaults handle the version-neutral interface methods automatically. + +### If migrating to dcm4che5 + +Implement `Dcm5DICOMConfiguration` instead: + +```java +public class MyConfig implements Dcm5DICOMConfiguration { + + @Override + public void configureDcm5Sender(Dcm5DicomSender sender, DICOMDispatcher connector, + DICOMDispatcherProperties props) throws Exception { + // Use DICOMConfigurationUtil for standard property wiring + DICOMConfigurationUtil.configureSender(sender, connector, props, protocols); + + // Add custom configuration + sender.setTlsCipherSuites(new String[]{"TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256"}); + } + + @Override + public void configureDcm5Receiver(Dcm5DicomReceiver receiver, DICOMReceiver connector, + DICOMReceiverProperties props) throws Exception { + DICOMConfigurationUtil.configureReceiver(receiver, connector, props, protocols); + } + + @Override + public Map getCStoreRequestInformation(Association association) { + // association is org.dcm4che3.net.Association (not org.dcm4che2) + Map map = new HashMap<>(); + map.put("calledAET", association.getCalledAET()); + return map; + } + + @Override + public Connection createDcm5Connection() { + return new Connection(); + } + + // ... +} +``` + +Key differences from `Dcm2DICOMConfiguration`: + +| | `Dcm2DICOMConfiguration` | `Dcm5DICOMConfiguration` | +|---|---|---| +| Receiver method | `configureDcmRcv(MirthDcmRcv, ...)` | `configureDcm5Receiver(Dcm5DicomReceiver, ...)` | +| Sender method | `configureDcmSnd(MirthDcmSnd, ...)` | `configureDcm5Sender(Dcm5DicomSender, ...)` | +| Association type | `org.dcm4che2.net.Association` | `org.dcm4che3.net.Association` | +| Network connection | `createLegacyNetworkConnection()` → `NetworkConnection` | `createDcm5Connection()` → `Connection` | + +## JAR Architecture + +The build produces three JARs: + +| JAR | Contents | When Loaded | +|-----|----------|-------------| +| `dicom-server.jar` | Version-neutral interfaces, factory, connector classes | Always | +| `dicom-server-dcm2.jar` | `Dcm2DicomSender`, `Dcm2DicomReceiver`, `Dcm2DicomConverter`, MirthDcmSnd/Rcv | `dicom.library=dcm4che2` | +| `dicom-server-dcm5.jar` | `Dcm5DicomSender`, `Dcm5DicomReceiver`, `Dcm5DicomConverter` | `dicom.library=dcm4che5` | + +The variant-based loading is controlled by the connector extension XML: + +```xml + + +``` + +Only the JAR matching the configured library is loaded at runtime. The factory uses `Class.forName()` to avoid compile-time dependencies between the version-neutral code and either backend. + +## Verification + +After switching to dcm4che5: + +1. **Check server logs for library detection:** + ``` + DICOM library backend: DCM4CHE5 + ``` + +2. **Test a non-TLS DICOM channel:** Deploy a DICOM Listener on a test port. Use any DICOM SCU (e.g., dcm4che's `storescu` CLI tool, or a DICOM Sender channel) to send a C-STORE. Verify the message arrives and is processed. + +3. **Test TLS channels (if applicable):** If using TLS, verify with a custom `DICOMConfiguration` that uses modern cipher suites (see [TLS section](#recommended-custom-cipher-suites-via-dicomconfiguration)). + +4. **Verify source map:** Check that the source map in received messages contains the expected keys: `localApplicationEntityTitle`, `remoteApplicationEntityTitle`, `localAddress`, `localPort`, `remoteAddress`, `remotePort`. + +5. **Test storage commitment (if applicable):** If any channels use storage commitment, verify the `N-ACTION` / `N-EVENT-REPORT` flow completes. + +## Rollback + +To revert to dcm4che2: + +1. Edit `server/conf/mirth.properties`: + ```properties + dicom.library = dcm4che2 + ``` + (or remove the line entirely — dcm4che2 is the default) + +2. If you changed `dicomConfigurationClass` (Mirth server configuration property) to a dcm5-specific implementation, revert it to your dcm2 implementation or remove the property via the Mirth Administrator or REST API. + +3. Restart the server. + +No channel configuration changes are needed — the version-neutral property model is shared. + +## Troubleshooting + +### `SSLHandshakeException: No appropriate protocol` + +The configured cipher suite is disabled in your JDK's security policy. This affects both backends on current JDKs. Use a custom `DICOMConfiguration` with modern cipher suites (see [TLS section](#tls-configuration)). + +### `IllegalStateException: keyStoreURL requires keyStoreType` + +dcm4che5 requires an explicit keystore type. The default inference handles `.jks`, `.p12`, and `.pfx` extensions. If your keystore URL has a non-standard extension, call `setKeyStoreType()` explicitly in your custom `DICOMConfiguration`. + +### `IncompatibleConnectionException` during sender `open()` + +dcm4che5 requires TLS cipher suites to match on both the local and remote `Connection` objects. This is handled automatically by the `Dcm5DicomSender` implementation — if you see this error, ensure you're calling `setTlsCipherSuites()` (not the individual preset methods) and that `initTLS()` is called after all TLS setters. + +### `NoPresentationContextException` + +The receiver and sender must agree on at least one transfer syntax. Verify that both sides are configured with compatible transfer syntaxes (e.g., `1.2.840.10008.1.2` for Implicit VR Little Endian, `1.2.840.10008.1.2.1` for Explicit VR Little Endian). + +### Element name mismatch in channel scripts + +If your JavaScript/channel scripts compare element names as strings, they may break because dcm4che5 uses keyword-style names (`"PatientName"`) rather than dcm4che2's display names (`"Patient's Name"`). Use tag numbers (`Tag.PatientName` / `0x00100010`) instead. diff --git a/server/build.xml b/server/build.xml index 011b3264e1..7569a28a49 100644 --- a/server/build.xml +++ b/server/build.xml @@ -160,13 +160,39 @@ - + + + + + + + + + + + + + + - + + - - + + + + + + + + + + + + diff --git a/server/conf/mirth.properties b/server/conf/mirth.properties index e3c9719f1f..4367133c60 100644 --- a/server/conf/mirth.properties +++ b/server/conf/mirth.properties @@ -112,3 +112,7 @@ database.connection.retrywaitinmilliseconds = 10000 # database-readonly.url = jdbc:... # database.enable-read-write-split = true + +# DICOM library backend. Supported values: dcm4che2 (default), dcm4che5. +# Changing this value requires a server restart. +# dicom.library = dcm4che2 diff --git a/server/docs/thirdparty/THIRD-PARTY-README.txt b/server/docs/thirdparty/THIRD-PARTY-README.txt index 39227b9af6..54dc4e6541 100644 --- a/server/docs/thirdparty/THIRD-PARTY-README.txt +++ b/server/docs/thirdparty/THIRD-PARTY-README.txt @@ -70,7 +70,9 @@ terms. DcmRcv and DcmSnd were modified to allow overriding of the network connections. - HAPI 2.3 (source code can be downloaded at: + dcm4che 5.34.3 (source code can be downloaded at: http://www.dcm4che.org/) + + HAPI 2.3 (source code can be downloaded at: https://github.com/hapifhir/hapi-hl7v2) iText, a free Java-PDF library version 2.1.7 (source code can be downloaded diff --git a/server/lib/extensions/dimse/dcm4che-core-5.34.3.jar b/server/lib/extensions/dimse/dcm4che-core-5.34.3.jar new file mode 100644 index 0000000000000000000000000000000000000000..696ee7e109e204c1149b0f0d7a8b232e55264bfa GIT binary patch literal 544274 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 z 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%0ACIWMpT+ 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 z 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 z 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 literal 0 HcmV?d00001 diff --git a/server/src/com/mirth/connect/connectors/dimse/DICOMConfiguration.java b/server/src/com/mirth/connect/connectors/dimse/DICOMConfiguration.java index 635ecc6726..d595f8cd7e 100644 --- a/server/src/com/mirth/connect/connectors/dimse/DICOMConfiguration.java +++ b/server/src/com/mirth/connect/connectors/dimse/DICOMConfiguration.java @@ -1,8 +1,8 @@ /* * Copyright (c) Mirth Corporation. All rights reserved. - * + * * http://www.mirthcorp.com - * + * * The software in this package is published under the terms of the MPL license a copy of which has * been included with this distribution in the LICENSE.txt file. */ @@ -11,22 +11,51 @@ import java.util.Map; -import org.dcm4che2.net.Association; -import org.dcm4che2.net.NetworkConnection; -import org.dcm4che2.tool.dcmrcv.MirthDcmRcv; -import org.dcm4che2.tool.dcmsnd.MirthDcmSnd; - +import com.mirth.connect.connectors.dimse.dicom.OieDicomReceiver; +import com.mirth.connect.connectors.dimse.dicom.OieDicomSender; import com.mirth.connect.donkey.server.channel.Connector; +/** + * Version-neutral interface for DICOM connector configuration. Implementations + * configure the DICOM sender and receiver without direct dcm4che library dependencies. + * + *

Custom implementations can cast the sender/receiver to the dcm4che-specific + * type (e.g., Dcm2DicomSender) and call {@code unwrap()} to access the underlying + * MirthDcmSnd/MirthDcmRcv if needed. + */ public interface DICOMConfiguration { - public void configureConnectorDeploy(Connector connector) throws Exception; - - public NetworkConnection createNetworkConnection(); - - public void configureDcmRcv(MirthDcmRcv dcmrcv, DICOMReceiver connector, DICOMReceiverProperties connectorProperties) throws Exception; - - public void configureDcmSnd(MirthDcmSnd dcmsnd, DICOMDispatcher connector, DICOMDispatcherProperties connectorProperties) throws Exception; - - public Map getCStoreRequestInformation(Association as); -} \ No newline at end of file + void configureConnectorDeploy(Connector connector) throws Exception; + + void configureReceiver(OieDicomReceiver receiver, DICOMReceiver connector, DICOMReceiverProperties connectorProperties) throws Exception; + + void configureSender(OieDicomSender sender, DICOMDispatcher connector, DICOMDispatcherProperties connectorProperties) throws Exception; + + /** + * Extracts additional information from a DICOM C-STORE association request. + * The association parameter is the library-specific association object. + * + *

For the dcm4che2 backend the runtime type is + * {@code org.dcm4che2.net.Association}. Custom implementations should cast + * accordingly: + *

{@code
+     * Association as = (Association) association;
+     * map.put("calledAET", as.getCalledAET());
+     * }
+ * + * @param association The library-specific association object + * @return Additional key-value pairs to add to the source map + */ + Map getCStoreRequestInformation(Object association); + + /** + * Optional factory method for creating a custom {@code NetworkConnection}. + * The returned object must be an instance of the library-specific + * NetworkConnection class (e.g., {@code org.dcm4che2.net.NetworkConnection} + * for the dcm4che2 backend). If {@code null} is returned, the default + * NetworkConnection is used. + * + * @return A library-specific NetworkConnection, or {@code null} for the default + */ + default Object createNetworkConnection() { return null; } +} diff --git a/server/src/com/mirth/connect/connectors/dimse/DICOMConfigurationUtil.java b/server/src/com/mirth/connect/connectors/dimse/DICOMConfigurationUtil.java index d873d13244..ba10c3b241 100644 --- a/server/src/com/mirth/connect/connectors/dimse/DICOMConfigurationUtil.java +++ b/server/src/com/mirth/connect/connectors/dimse/DICOMConfigurationUtil.java @@ -1,8 +1,8 @@ /* * Copyright (c) Mirth Corporation. All rights reserved. - * + * * http://www.mirthcorp.com - * + * * The software in this package is published under the terms of the MPL license a copy of which has * been included with this distribution in the LICENSE.txt file. */ @@ -15,49 +15,58 @@ import org.apache.commons.lang3.ArrayUtils; import org.apache.commons.lang3.StringUtils; -import org.dcm4che2.tool.dcmrcv.MirthDcmRcv; -import org.dcm4che2.tool.dcmsnd.MirthDcmSnd; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import com.mirth.connect.connectors.dimse.dicom.OieDicomReceiver; +import com.mirth.connect.connectors.dimse.dicom.OieDicomSender; import com.mirth.connect.util.MirthSSLUtil; public class DICOMConfigurationUtil { - public static void configureDcmRcv(MirthDcmRcv dcmrcv, DICOMReceiver connector, DICOMReceiverProperties connectorProperties, String[] protocols) throws Exception { + private static final Logger logger = LogManager.getLogger(DICOMConfigurationUtil.class); + + public static void configureReceiver(OieDicomReceiver receiver, DICOMReceiver connector, DICOMReceiverProperties connectorProperties, String[] protocols) throws Exception { if (!StringUtils.equals(connectorProperties.getTls(), "notls")) { if (connectorProperties.getTls().equals("without")) { - dcmrcv.setTlsWithoutEncyrption(); + logger.warn("DICOM receiver configured with TLS NULL encryption (SSL_RSA_WITH_NULL_SHA). " + + "This provides authentication only — data is sent in cleartext. " + + "Consider using AES encryption instead."); + receiver.setTlsWithoutEncryption(); } else if (connectorProperties.getTls().equals("3des")) { - dcmrcv.setTls3DES_EDE_CBC(); + logger.warn("DICOM receiver configured with deprecated 3DES cipher suite. " + + "Consider using AES encryption instead."); + receiver.setTls3DES_EDE_CBC(); } else if (connectorProperties.getTls().equals("aes")) { - dcmrcv.setTlsAES_128_CBC(); + receiver.setTlsAES_128_CBC(); } String trustStore = connector.getReplacer().replaceValues(connectorProperties.getTrustStore(), connector.getChannelId(), connector.getChannel().getName()); if (StringUtils.isNotBlank(trustStore)) { - dcmrcv.setTrustStoreURL(trustStore); + receiver.setTrustStoreURL(trustStore); } String trustStorePW = connector.getReplacer().replaceValues(connectorProperties.getTrustStorePW(), connector.getChannelId(), connector.getChannel().getName()); if (StringUtils.isNotBlank(trustStorePW)) { - dcmrcv.setTrustStorePassword(trustStorePW); + receiver.setTrustStorePassword(trustStorePW); } String keyPW = connector.getReplacer().replaceValues(connectorProperties.getKeyPW(), connector.getChannelId(), connector.getChannel().getName()); if (StringUtils.isNotBlank(keyPW)) { - dcmrcv.setKeyPassword(keyPW); + receiver.setKeyPassword(keyPW); } String keyStore = connector.getReplacer().replaceValues(connectorProperties.getKeyStore(), connector.getChannelId(), connector.getChannel().getName()); if (StringUtils.isNotBlank(keyStore)) { - dcmrcv.setKeyStoreURL(keyStore); + receiver.setKeyStoreURL(keyStore); } String keyStorePW = connector.getReplacer().replaceValues(connectorProperties.getKeyStorePW(), connector.getChannelId(), connector.getChannel().getName()); if (StringUtils.isNotBlank(keyStorePW)) { - dcmrcv.setKeyStorePassword(keyStorePW); + receiver.setKeyStorePassword(keyStorePW); } - dcmrcv.setTlsNeedClientAuth(connectorProperties.isNoClientAuth()); + receiver.setTlsNeedClientAuth(connectorProperties.isNoClientAuth()); protocols = ArrayUtils.clone(protocols); @@ -73,31 +82,38 @@ public static void configureDcmRcv(MirthDcmRcv dcmrcv, DICOMReceiver connector, protocols = protocolsList.toArray(new String[protocolsList.size()]); } - dcmrcv.setTlsProtocol(MirthSSLUtil.getEnabledHttpsProtocols(protocols)); + receiver.setTlsProtocol(MirthSSLUtil.getEnabledHttpsProtocols(protocols)); - dcmrcv.initTLS(); + receiver.initTLS(); } } - public static void configureDcmSnd(MirthDcmSnd dcmsnd, DICOMDispatcher connector, DICOMDispatcherProperties connectorProperties, String[] protocols) throws Exception { + public static void configureSender(OieDicomSender sender, DICOMDispatcher connector, DICOMDispatcherProperties connectorProperties, String[] protocols) throws Exception { if (connectorProperties.getTls() != null && !connectorProperties.getTls().equals("notls")) { - if (connectorProperties.getTls().equals("without")) - dcmsnd.setTlsWithoutEncyrption(); - if (connectorProperties.getTls().equals("3des")) - dcmsnd.setTls3DES_EDE_CBC(); + if (connectorProperties.getTls().equals("without")) { + logger.warn("DICOM sender configured with TLS NULL encryption (SSL_RSA_WITH_NULL_SHA). " + + "This provides authentication only — data is sent in cleartext. " + + "Consider using AES encryption instead."); + sender.setTlsWithoutEncryption(); + } + if (connectorProperties.getTls().equals("3des")) { + logger.warn("DICOM sender configured with deprecated 3DES cipher suite. " + + "Consider using AES encryption instead."); + sender.setTls3DES_EDE_CBC(); + } if (connectorProperties.getTls().equals("aes")) - dcmsnd.setTlsAES_128_CBC(); - if (connectorProperties.getTrustStore() != null && !connectorProperties.getTrustStore().equals("")) - dcmsnd.setTrustStoreURL(connectorProperties.getTrustStore()); - if (connectorProperties.getTrustStorePW() != null && !connectorProperties.getTrustStorePW().equals("")) - dcmsnd.setTrustStorePassword(connectorProperties.getTrustStorePW()); - if (connectorProperties.getKeyPW() != null && !connectorProperties.getKeyPW().equals("")) - dcmsnd.setKeyPassword(connectorProperties.getKeyPW()); - if (connectorProperties.getKeyStore() != null && !connectorProperties.getKeyStore().equals("")) - dcmsnd.setKeyStoreURL(connectorProperties.getKeyStore()); - if (connectorProperties.getKeyStorePW() != null && !connectorProperties.getKeyStorePW().equals("")) - dcmsnd.setKeyStorePassword(connectorProperties.getKeyStorePW()); - dcmsnd.setTlsNeedClientAuth(connectorProperties.isNoClientAuth()); + sender.setTlsAES_128_CBC(); + if (StringUtils.isNotBlank(connectorProperties.getTrustStore())) + sender.setTrustStoreURL(connectorProperties.getTrustStore()); + if (StringUtils.isNotBlank(connectorProperties.getTrustStorePW())) + sender.setTrustStorePassword(connectorProperties.getTrustStorePW()); + if (StringUtils.isNotBlank(connectorProperties.getKeyPW())) + sender.setKeyPassword(connectorProperties.getKeyPW()); + if (StringUtils.isNotBlank(connectorProperties.getKeyStore())) + sender.setKeyStoreURL(connectorProperties.getKeyStore()); + if (StringUtils.isNotBlank(connectorProperties.getKeyStorePW())) + sender.setKeyStorePassword(connectorProperties.getKeyStorePW()); + sender.setTlsNeedClientAuth(connectorProperties.isNoClientAuth()); protocols = ArrayUtils.clone(protocols); @@ -115,9 +131,9 @@ public static void configureDcmSnd(MirthDcmSnd dcmsnd, DICOMDispatcher connector protocols = MirthSSLUtil.getEnabledHttpsProtocols(protocols); - dcmsnd.setTlsProtocol(protocols); + sender.setTlsProtocol(protocols); - dcmsnd.initTLS(); + sender.initTLS(); } } -} \ No newline at end of file +} diff --git a/server/src/com/mirth/connect/connectors/dimse/DICOMDispatcher.java b/server/src/com/mirth/connect/connectors/dimse/DICOMDispatcher.java index 656a3e8a49..1fffc973d3 100644 --- a/server/src/com/mirth/connect/connectors/dimse/DICOMDispatcher.java +++ b/server/src/com/mirth/connect/connectors/dimse/DICOMDispatcher.java @@ -1,8 +1,8 @@ /* * Copyright (c) Mirth Corporation. All rights reserved. - * + * * http://www.mirthcorp.com - * + * * The software in this package is published under the terms of the MPL license a copy of which has * been included with this distribution in the LICENSE.txt file. */ @@ -16,16 +16,13 @@ import org.apache.commons.lang3.math.NumberUtils; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; -import org.dcm4che2.data.BasicDicomObject; -import org.dcm4che2.data.DicomElement; -import org.dcm4che2.data.DicomObject; -import org.dcm4che2.data.Tag; -import org.dcm4che2.net.Association; -import org.dcm4che2.net.UserIdentity; -import org.dcm4che2.tool.dcmsnd.CustomDimseRSPHandler; -import org.dcm4che2.tool.dcmsnd.MirthDcmSnd; -import org.dcm4che2.util.StringUtils; +import com.mirth.connect.connectors.dimse.dicom.DicomConstants; +import com.mirth.connect.connectors.dimse.dicom.DicomLibraryFactory; +import com.mirth.connect.connectors.dimse.dicom.OieDicomElement; +import com.mirth.connect.connectors.dimse.dicom.OieDicomObject; +import com.mirth.connect.connectors.dimse.dicom.OieDicomSender; +import com.mirth.connect.connectors.dimse.dicom.OieDimseRspHandler; import com.mirth.connect.donkey.model.channel.ConnectorProperties; import com.mirth.connect.donkey.model.event.ConnectionStatusEventType; import com.mirth.connect.donkey.model.event.ErrorEventType; @@ -59,12 +56,7 @@ public void onDeploy() throws ConnectorTaskException { // load the default configuration String configurationClass = configurationController.getProperty(connectorProperties.getProtocol(), "dicomConfigurationClass"); - try { - configuration = (DICOMConfiguration) Class.forName(configurationClass).newInstance(); - } catch (Throwable t) { - logger.trace("could not find custom configuration class, using default"); - configuration = new DefaultDICOMConfiguration(); - } + configuration = DicomLibraryFactory.loadConfiguration(configurationClass); try { configuration.configureConnectorDeploy(this); @@ -125,7 +117,7 @@ public Response send(ConnectorProperties connectorProperties, ConnectorMessage c Status responseStatus = Status.QUEUED; File tempFile = null; - MirthDcmSnd dcmSnd = getDcmSnd(configuration); + OieDicomSender dcmSnd = createDicomSender(configuration); try { tempFile = File.createTempFile("temp", "tmp"); @@ -175,15 +167,8 @@ else if (dicomDispatcherProperties.getPriority().equals("high")) dcmSnd.setPriority(2); if (dicomDispatcherProperties.getUsername() != null && !dicomDispatcherProperties.getUsername().equals("")) { String username = dicomDispatcherProperties.getUsername(); - UserIdentity userId; - if (dicomDispatcherProperties.getPasscode() != null && !dicomDispatcherProperties.getPasscode().equals("")) { - String passcode = dicomDispatcherProperties.getPasscode(); - userId = new UserIdentity.UsernamePasscode(username, passcode.toCharArray()); - } else { - userId = new UserIdentity.Username(username); - } - userId.setPositiveResponseRequested(dicomDispatcherProperties.isUidnegrsp()); - dcmSnd.setUserIdentity(userId); + String passcode = dicomDispatcherProperties.getPasscode(); + dcmSnd.setUserIdentity(username, passcode, dicomDispatcherProperties.isUidnegrsp()); } dcmSnd.setPackPDV(dicomDispatcherProperties.isPdv1()); @@ -226,7 +211,7 @@ else if (dicomDispatcherProperties.getPriority().equals("high")) dcmSnd.setStorageCommitment(dicomDispatcherProperties.isStgcmt()); dcmSnd.setTcpNoDelay(!dicomDispatcherProperties.isTcpDelay()); - configuration.configureDcmSnd(dcmSnd, this, dicomDispatcherProperties); + configuration.configureSender(dcmSnd, this, dicomDispatcherProperties); dcmSnd.setOfferDefaultTransferSyntaxInSeparatePresentationContext(dicomDispatcherProperties.isTs1()); dcmSnd.configureTransferCapability(); @@ -240,15 +225,22 @@ else if (dicomDispatcherProperties.getPriority().equals("high")) String storageCommitmentFailureReason = "Unknown"; if (dcmSnd.isStorageCommitment()) { if (dcmSnd.commit()) { - DicomObject cmtrslt = dcmSnd.waitForStgCmtResult(); - DicomElement failedSOPSq = cmtrslt.get(Tag.FailedSOPSequence); - if (failedSOPSq != null && failedSOPSq.countItems() > 0) { - storageCommitmentFailed = true; - DicomObject failedSOPItem = failedSOPSq.getDicomObject(); - int failureReason = failedSOPItem.getInt(Tag.FailureReason); - if (failureReason != 0) { - storageCommitmentFailureReason = String.valueOf(failureReason); + OieDicomObject cmtrslt = dcmSnd.waitForStgCmtResult(); + if (cmtrslt != null) { + OieDicomElement failedSOPSq = cmtrslt.get(DicomConstants.TAG_FAILED_SOP_SEQUENCE); + if (failedSOPSq != null && failedSOPSq.countItems() > 0) { + storageCommitmentFailed = true; + OieDicomObject failedSOPItem = failedSOPSq.getDicomObject(); + if (failedSOPItem != null) { + int failureReason = failedSOPItem.getInt(DicomConstants.TAG_FAILURE_REASON); + if (failureReason != 0) { + storageCommitmentFailureReason = String.valueOf(failureReason); + } + } } + } else { + logger.warn("Storage commitment result was null — remote SCP may not have responded"); + storageCommitmentFailed = true; } } else { storageCommitmentFailed = true; @@ -259,16 +251,16 @@ else if (dicomDispatcherProperties.getPriority().equals("high")) int status = rspHandler.getStatus(); - if (status == 0) { + if (status == DicomConstants.STATUS_SUCCESS) { responseStatusMessage = "DICOM message successfully sent"; responseStatus = Status.SENT; - } else if (status == 0xB000 || status == 0xB006 || status == 0xB007) { + } else if (status == DicomConstants.STATUS_WARNING_COERCION || status == DicomConstants.STATUS_WARNING_ELEMENTS_DISCARDED || status == DicomConstants.STATUS_WARNING_DATA_SET_MISMATCH) { // These status codes are used in DcmSnd.onDimseRSP to flag warnings - responseStatusMessage = "DICOM message successfully sent with warning status code: 0x" + StringUtils.shortToHex(status); + responseStatusMessage = "DICOM message successfully sent with warning status code: 0x" + DicomConstants.shortToHex(status); responseStatus = Status.SENT; } else { // Any other status is considered unsuccessful - responseStatusMessage = "Error status code received from DICOM server: 0x" + StringUtils.shortToHex(status); + responseStatusMessage = "Error status code received from DICOM server: 0x" + DicomConstants.shortToHex(status); responseStatus = Status.QUEUED; } @@ -283,6 +275,11 @@ else if (dicomDispatcherProperties.getPriority().equals("high")) responseError = ErrorMessageBuilder.buildErrorMessage(connectorProperties.getName(), e.getMessage(), null); eventController.dispatchEvent(new ErrorEvent(getChannelId(), getMetaDataId(), connectorMessage.getMessageId(), ErrorEventType.DESTINATION_CONNECTOR, getDestinationName(), connectorProperties.getName(), e.getMessage(), null)); } finally { + try { + dcmSnd.close(); + } catch (Exception e) { + logger.debug("Error closing DICOM sender association", e); + } dcmSnd.stop(); if (tempFile != null) { @@ -295,37 +292,37 @@ else if (dicomDispatcherProperties.getPriority().equals("high")) return new Response(responseStatus, responseData, responseStatusMessage, responseError); } - protected MirthDcmSnd getDcmSnd(DICOMConfiguration configuration) { - return new MirthDcmSnd(configuration); + protected OieDicomSender createDicomSender(DICOMConfiguration configuration) { + return DicomLibraryFactory.createSender(configuration); } - protected class CommandDataDimseRSPHandler extends CustomDimseRSPHandler { + protected class CommandDataDimseRSPHandler implements OieDimseRspHandler { - private DicomObject cmd; + private OieDicomObject cmd; @Override - public void onDimseRSP(Association as, DicomObject cmd, DicomObject data) { + public void onDimseRSP(OieDicomObject cmd, OieDicomObject data) { this.cmd = cmd; } public int getStatus() { if (cmd != null) { - return cmd.getInt(Tag.Status); + return cmd.getInt(DicomConstants.TAG_STATUS); } else { return 0; } } public String getCommandData() { - if (cmd instanceof BasicDicomObject) { + if (cmd != null) { try { DonkeyElement dicom = new DonkeyElement(""); - for (Iterator it = ((BasicDicomObject) cmd).commandIterator(); it.hasNext();) { - DicomElement element = it.next(); - String tag = StringUtils.shortToHex(element.tag() >> 16) + StringUtils.shortToHex(element.tag()); + for (Iterator it = cmd.commandIterator(); it.hasNext();) { + OieDicomElement element = it.next(); + String tag = DicomConstants.shortToHex(element.tag() >> 16) + DicomConstants.shortToHex(element.tag()); - DonkeyElement child = dicom.addChildElement("tag" + tag, element.getValueAsString(null, 0)); + DonkeyElement child = dicom.addChildElement("tag" + tag, element.getValueAsString(0)); child.setAttribute("len", String.valueOf(element.length())); child.setAttribute("tag", tag); child.setAttribute("vr", String.valueOf(element.vr())); diff --git a/server/src/com/mirth/connect/connectors/dimse/DICOMReceiver.java b/server/src/com/mirth/connect/connectors/dimse/DICOMReceiver.java index 7a1a9d462b..60e13bc8f8 100644 --- a/server/src/com/mirth/connect/connectors/dimse/DICOMReceiver.java +++ b/server/src/com/mirth/connect/connectors/dimse/DICOMReceiver.java @@ -1,8 +1,8 @@ /* * Copyright (c) Mirth Corporation. All rights reserved. - * + * * http://www.mirthcorp.com - * + * * The software in this package is published under the terms of the MPL license a copy of which has * been included with this distribution in the LICENSE.txt file. */ @@ -13,9 +13,10 @@ import org.apache.commons.lang3.math.NumberUtils; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; -import org.dcm4che2.data.UID; -import org.dcm4che2.tool.dcmrcv.MirthDcmRcv; +import com.mirth.connect.connectors.dimse.dicom.DicomConstants; +import com.mirth.connect.connectors.dimse.dicom.DicomLibraryFactory; +import com.mirth.connect.connectors.dimse.dicom.OieDicomReceiver; import com.mirth.connect.donkey.model.event.ConnectionStatusEventType; import com.mirth.connect.donkey.server.ConnectorTaskException; import com.mirth.connect.donkey.server.channel.DispatchResult; @@ -28,12 +29,12 @@ public class DICOMReceiver extends SourceConnector { private Logger logger = LogManager.getLogger(this.getClass()); - private DICOMReceiverProperties connectorProperties; - private EventController eventController = ControllerFactory.getFactory().createEventController(); + protected DICOMReceiverProperties connectorProperties; + protected EventController eventController = ControllerFactory.getFactory().createEventController(); private ConfigurationController configurationController = ControllerFactory.getFactory().createConfigurationController(); private TemplateValueReplacer replacer = new TemplateValueReplacer(); - private DICOMConfiguration configuration = null; - private MirthDcmRcv dcmrcv; + protected DICOMConfiguration configuration = null; + protected OieDicomReceiver dicomReceiver; @Override public void onDeploy() throws ConnectorTaskException { @@ -42,12 +43,7 @@ public void onDeploy() throws ConnectorTaskException { // load the default configuration String configurationClass = configurationController.getProperty(connectorProperties.getProtocol(), "dicomConfigurationClass"); - try { - configuration = (DICOMConfiguration) Class.forName(configurationClass).newInstance(); - } catch (Throwable t) { - logger.trace("could not find custom configuration class, using default"); - configuration = new DefaultDICOMConfiguration(); - } + configuration = DicomLibraryFactory.loadConfiguration(configurationClass); try { configuration.configureConnectorDeploy(this); @@ -55,7 +51,7 @@ public void onDeploy() throws ConnectorTaskException { throw new ConnectorTaskException(e); } - dcmrcv = new MirthDcmRcv(this, configuration); + dicomReceiver = createDicomReceiver(configuration); } @Override @@ -64,105 +60,123 @@ public void onUndeploy() throws ConnectorTaskException {} @Override public void onStart() throws ConnectorTaskException { try { - dcmrcv.setPort(NumberUtils.toInt(replacer.replaceValues(connectorProperties.getListenerConnectorProperties().getPort(), getChannelId(), getChannel().getName()))); - dcmrcv.setHostname(replacer.replaceValues(connectorProperties.getListenerConnectorProperties().getHost(), getChannelId(), getChannel().getName())); - - String[] only_def_ts = { UID.ImplicitVRLittleEndian }; - String[] native_le_ts = { UID.ImplicitVRLittleEndian }; - String[] native_ts = { UID.ImplicitVRLittleEndian }; - String[] non_retired_ts = { UID.ImplicitVRLittleEndian }; + dicomReceiver.setPort(NumberUtils.toInt(replacer.replaceValues(connectorProperties.getListenerConnectorProperties().getPort(), getChannelId(), getChannel().getName()))); + dicomReceiver.setHostname(replacer.replaceValues(connectorProperties.getListenerConnectorProperties().getHost(), getChannelId(), getChannel().getName())); + + String[] only_def_ts = { DicomConstants.IMPLICIT_VR_LITTLE_ENDIAN }; + String[] native_le_ts = { DicomConstants.EXPLICIT_VR_LITTLE_ENDIAN, + DicomConstants.IMPLICIT_VR_LITTLE_ENDIAN }; + String[] native_ts = { DicomConstants.EXPLICIT_VR_LITTLE_ENDIAN, + DicomConstants.EXPLICIT_VR_BIG_ENDIAN, + DicomConstants.IMPLICIT_VR_LITTLE_ENDIAN }; + String[] non_retired_ts = { + DicomConstants.JPEG_LS_LOSSLESS, + DicomConstants.JPEG_LOSSLESS_SV1, + DicomConstants.JPEG_LOSSLESS_NH14, + DicomConstants.JPEG_2000_LOSSLESS, + DicomConstants.DEFLATED_EXPLICIT_VR_LITTLE_ENDIAN, + DicomConstants.RLE_LOSSLESS, + DicomConstants.EXPLICIT_VR_LITTLE_ENDIAN, + DicomConstants.EXPLICIT_VR_BIG_ENDIAN, + DicomConstants.IMPLICIT_VR_LITTLE_ENDIAN, + DicomConstants.JPEG_BASELINE, + DicomConstants.JPEG_EXTENDED, + DicomConstants.JPEG_LS_NEAR_LOSSLESS, + DicomConstants.JPEG_2000, + DicomConstants.MPEG2, + }; String destination = replacer.replaceValues(connectorProperties.getDest(), getChannelId(), getChannel().getName()); if (StringUtils.isNotBlank(destination)) { - dcmrcv.setDestination(destination); + dicomReceiver.setDestination(destination); } if (connectorProperties.isDefts()) { - dcmrcv.setTransferSyntax(only_def_ts); + dicomReceiver.setTransferSyntax(only_def_ts); } else if (connectorProperties.isNativeData()) { if (connectorProperties.isBigEndian()) { - dcmrcv.setTransferSyntax(native_ts); + dicomReceiver.setTransferSyntax(native_ts); } else { - dcmrcv.setTransferSyntax(native_le_ts); + dicomReceiver.setTransferSyntax(native_le_ts); } } else if (connectorProperties.isBigEndian()) { - dcmrcv.setTransferSyntax(non_retired_ts); + dicomReceiver.setTransferSyntax(non_retired_ts); } String aeTitle = replacer.replaceValues(connectorProperties.getApplicationEntity(), getChannelId(), getChannel().getName()); aeTitle = StringUtils.defaultIfBlank(aeTitle, null); - dcmrcv.setAEtitle(aeTitle); + dicomReceiver.setAEtitle(aeTitle); //TODO Allow variables int value = NumberUtils.toInt(connectorProperties.getReaper()); if (value != 10) { - dcmrcv.setAssociationReaperPeriod(value); + dicomReceiver.setAssociationReaperPeriod(value); } value = NumberUtils.toInt(connectorProperties.getIdleTo()); if (value != 60) { - dcmrcv.setIdleTimeout(value); + dicomReceiver.setIdleTimeout(value); } value = NumberUtils.toInt(connectorProperties.getRequestTo()); if (value != 5) { - dcmrcv.setRequestTimeout(value); + dicomReceiver.setRequestTimeout(value); } value = NumberUtils.toInt(connectorProperties.getReleaseTo()); if (value != 5) { - dcmrcv.setReleaseTimeout(value); + dicomReceiver.setReleaseTimeout(value); } value = NumberUtils.toInt(connectorProperties.getSoCloseDelay()); if (value != 50) { - dcmrcv.setSocketCloseDelay(value); + dicomReceiver.setSocketCloseDelay(value); } value = NumberUtils.toInt(connectorProperties.getRspDelay()); if (value > 0) { - dcmrcv.setDimseRspDelay(value); + dicomReceiver.setDimseRspDelay(value); } value = NumberUtils.toInt(connectorProperties.getRcvpdulen()); if (value != 16) { - dcmrcv.setMaxPDULengthReceive(value); + dicomReceiver.setMaxPDULengthReceive(value); } value = NumberUtils.toInt(connectorProperties.getSndpdulen()); if (value != 16) { - dcmrcv.setMaxPDULengthSend(value); + dicomReceiver.setMaxPDULengthSend(value); } value = NumberUtils.toInt(connectorProperties.getSosndbuf()); if (value > 0) { - dcmrcv.setSendBufferSize(value); + dicomReceiver.setSendBufferSize(value); } value = NumberUtils.toInt(connectorProperties.getSorcvbuf()); if (value > 0) { - dcmrcv.setReceiveBufferSize(value); + dicomReceiver.setReceiveBufferSize(value); } value = NumberUtils.toInt(connectorProperties.getBufSize()); if (value != 1) { - dcmrcv.setFileBufferSize(value); + dicomReceiver.setFileBufferSize(value); } - dcmrcv.setPackPDV(connectorProperties.isPdv1()); - dcmrcv.setTcpNoDelay(!connectorProperties.isTcpDelay()); + dicomReceiver.setPackPDV(connectorProperties.isPdv1()); + dicomReceiver.setTcpNoDelay(!connectorProperties.isTcpDelay()); value = NumberUtils.toInt(connectorProperties.getAsync()); if (value > 0) { - dcmrcv.setMaxOpsPerformed(value); + dicomReceiver.setMaxOpsPerformed(value); } - dcmrcv.initTransferCapability(); + dicomReceiver.initTransferCapability(); - configuration.configureDcmRcv(dcmrcv, this, connectorProperties); + configuration.configureReceiver(dicomReceiver, this, connectorProperties); // start the DICOM port - dcmrcv.start(); + dicomReceiver.start(); eventController.dispatchEvent(new ConnectionStatusEvent(getChannelId(), getMetaDataId(), getSourceName(), ConnectionStatusEventType.IDLE)); } catch (Exception e) { @@ -173,7 +187,7 @@ public void onStart() throws ConnectorTaskException { @Override public void onStop() throws ConnectorTaskException { try { - dcmrcv.stop(); + dicomReceiver.stop(); } catch (Exception e) { logger.error("Unable to close DICOM port.", e); } finally { @@ -196,4 +210,8 @@ public void handleRecoveredResponse(DispatchResult dispatchResult) { public TemplateValueReplacer getReplacer() { return replacer; } -} \ No newline at end of file + + protected OieDicomReceiver createDicomReceiver(DICOMConfiguration configuration) { + return DicomLibraryFactory.createReceiver(this, configuration); + } +} diff --git a/server/src/com/mirth/connect/connectors/dimse/DefaultDICOMConfiguration.java b/server/src/com/mirth/connect/connectors/dimse/DefaultDICOMConfiguration.java index cd2bdf370b..521a06fbaf 100644 --- a/server/src/com/mirth/connect/connectors/dimse/DefaultDICOMConfiguration.java +++ b/server/src/com/mirth/connect/connectors/dimse/DefaultDICOMConfiguration.java @@ -1,8 +1,8 @@ /* * Copyright (c) Mirth Corporation. All rights reserved. - * + * * http://www.mirthcorp.com - * + * * The software in this package is published under the terms of the MPL license a copy of which has * been included with this distribution in the LICENSE.txt file. */ @@ -17,12 +17,15 @@ import org.dcm4che2.tool.dcmrcv.MirthDcmRcv; import org.dcm4che2.tool.dcmsnd.MirthDcmSnd; +import com.mirth.connect.connectors.dimse.dicom.dcm2.Dcm2DICOMConfiguration; +import com.mirth.connect.connectors.dimse.dicom.dcm2.Dcm2DicomReceiver; +import com.mirth.connect.connectors.dimse.dicom.dcm2.Dcm2DicomSender; import com.mirth.connect.donkey.server.channel.Connector; import com.mirth.connect.server.controllers.ConfigurationController; import com.mirth.connect.server.controllers.ControllerFactory; import com.mirth.connect.util.MirthSSLUtil; -public class DefaultDICOMConfiguration implements DICOMConfiguration { +public class DefaultDICOMConfiguration implements Dcm2DICOMConfiguration { private ConfigurationController configurationController = ControllerFactory.getFactory().createConfigurationController(); private String[] protocols; @@ -37,22 +40,24 @@ public void configureConnectorDeploy(Connector connector) throws Exception { } @Override - public NetworkConnection createNetworkConnection() { - return new NetworkConnection(); + public void configureDcmRcv(MirthDcmRcv dcmrcv, DICOMReceiver connector, + DICOMReceiverProperties connectorProperties) throws Exception { + DICOMConfigurationUtil.configureReceiver(new Dcm2DicomReceiver(dcmrcv), connector, connectorProperties, protocols); } @Override - public void configureDcmRcv(MirthDcmRcv dcmrcv, DICOMReceiver connector, DICOMReceiverProperties connectorProperties) throws Exception { - DICOMConfigurationUtil.configureDcmRcv(dcmrcv, connector, connectorProperties, protocols); + public void configureDcmSnd(MirthDcmSnd dcmsnd, DICOMDispatcher connector, + DICOMDispatcherProperties connectorProperties) throws Exception { + DICOMConfigurationUtil.configureSender(new Dcm2DicomSender(dcmsnd), connector, connectorProperties, protocols); } @Override - public void configureDcmSnd(MirthDcmSnd dcmsnd, DICOMDispatcher connector, DICOMDispatcherProperties connectorProperties) throws Exception { - DICOMConfigurationUtil.configureDcmSnd(dcmsnd, connector, connectorProperties, protocols); + public Map getCStoreRequestInformation(Association association) { + return new HashMap(); } @Override - public Map getCStoreRequestInformation(Association as) { - return new HashMap(); + public NetworkConnection createLegacyNetworkConnection() { + return new NetworkConnection(); } -} \ No newline at end of file +} diff --git a/server/src/com/mirth/connect/connectors/dimse/DefaultDcm5DICOMConfiguration.java b/server/src/com/mirth/connect/connectors/dimse/DefaultDcm5DICOMConfiguration.java new file mode 100644 index 0000000000..4a088e20e1 --- /dev/null +++ b/server/src/com/mirth/connect/connectors/dimse/DefaultDcm5DICOMConfiguration.java @@ -0,0 +1,61 @@ +/* + * Copyright (c) Mirth Corporation. All rights reserved. + * + * http://www.mirthcorp.com + * + * The software in this package is published under the terms of the MPL license a copy of which has + * been included with this distribution in the LICENSE.txt file. + */ + +package com.mirth.connect.connectors.dimse; + +import java.util.HashMap; +import java.util.Map; + +import org.dcm4che3.net.Association; +import org.dcm4che3.net.Connection; + +import com.mirth.connect.connectors.dimse.dicom.dcm5.Dcm5DICOMConfiguration; +import com.mirth.connect.connectors.dimse.dicom.dcm5.Dcm5DicomReceiver; +import com.mirth.connect.connectors.dimse.dicom.dcm5.Dcm5DicomSender; +import com.mirth.connect.donkey.server.channel.Connector; +import com.mirth.connect.server.controllers.ConfigurationController; +import com.mirth.connect.server.controllers.ControllerFactory; +import com.mirth.connect.util.MirthSSLUtil; + +public class DefaultDcm5DICOMConfiguration implements Dcm5DICOMConfiguration { + + private ConfigurationController configurationController = ControllerFactory.getFactory().createConfigurationController(); + private String[] protocols; + + @Override + public void configureConnectorDeploy(Connector connector) throws Exception { + if (connector instanceof DICOMReceiver) { + protocols = MirthSSLUtil.getEnabledHttpsProtocols(configurationController.getHttpsServerProtocols()); + } else { + protocols = MirthSSLUtil.getEnabledHttpsProtocols(configurationController.getHttpsClientProtocols()); + } + } + + @Override + public void configureDcm5Receiver(Dcm5DicomReceiver receiver, DICOMReceiver connector, + DICOMReceiverProperties connectorProperties) throws Exception { + DICOMConfigurationUtil.configureReceiver(receiver, connector, connectorProperties, protocols); + } + + @Override + public void configureDcm5Sender(Dcm5DicomSender sender, DICOMDispatcher connector, + DICOMDispatcherProperties connectorProperties) throws Exception { + DICOMConfigurationUtil.configureSender(sender, connector, connectorProperties, protocols); + } + + @Override + public Map getCStoreRequestInformation(Association association) { + return new HashMap(); + } + + @Override + public Connection createDcm5Connection() { + return new Connection(); + } +} diff --git a/server/src/com/mirth/connect/connectors/dimse/destination.xml b/server/src/com/mirth/connect/connectors/dimse/destination.xml index 0c960d726f..9b53c66af5 100644 --- a/server/src/com/mirth/connect/connectors/dimse/destination.xml +++ b/server/src/com/mirth/connect/connectors/dimse/destination.xml @@ -10,13 +10,15 @@ com.mirth.connect.connectors.dimse.DICOMDispatcherProperties - - - - - + + + + + + + dicom DESTINATION diff --git a/server/src/com/mirth/connect/connectors/dimse/dicom/DicomConstants.java b/server/src/com/mirth/connect/connectors/dimse/dicom/DicomConstants.java new file mode 100644 index 0000000000..9e373ec59f --- /dev/null +++ b/server/src/com/mirth/connect/connectors/dimse/dicom/DicomConstants.java @@ -0,0 +1,65 @@ +/* + * Copyright (c) Mirth Corporation. All rights reserved. + * + * http://www.mirthcorp.com + * + * The software in this package is published under the terms of the MPL license a copy of which has + * been included with this distribution in the LICENSE.txt file. + */ + +package com.mirth.connect.connectors.dimse.dicom; + +/** + * Version-neutral DICOM constants. These values are defined by the DICOM standard + * and are identical across all dcm4che library versions. + */ +public final class DicomConstants { + + private DicomConstants() {} + + // DICOM Tags (from the DICOM standard, version-independent) + public static final int TAG_PIXEL_DATA = 0x7FE00010; + public static final int TAG_STATUS = 0x00000900; + public static final int TAG_FAILED_SOP_SEQUENCE = 0x00081198; + public static final int TAG_FAILURE_REASON = 0x00081197; + public static final int TAG_AFFECTED_SOP_CLASS_UID = 0x00000002; + public static final int TAG_AFFECTED_SOP_INSTANCE_UID = 0x00001000; + public static final int TAG_REQUESTED_SOP_CLASS_UID = 0x00000003; + public static final int TAG_REQUESTED_SOP_INSTANCE_UID = 0x00001001; + + // DICOM Value Representations + public static final String VR_OB = "OB"; + public static final String VR_UI = "UI"; + public static final String VR_IS = "IS"; + + // Transfer Syntax UIDs + public static final String IMPLICIT_VR_LITTLE_ENDIAN = "1.2.840.10008.1.2"; + public static final String EXPLICIT_VR_LITTLE_ENDIAN = "1.2.840.10008.1.2.1"; + public static final String EXPLICIT_VR_BIG_ENDIAN = "1.2.840.10008.1.2.2"; + public static final String DEFLATED_EXPLICIT_VR_LITTLE_ENDIAN = "1.2.840.10008.1.2.1.99"; + public static final String JPEG_BASELINE = "1.2.840.10008.1.2.4.50"; + public static final String JPEG_EXTENDED = "1.2.840.10008.1.2.4.51"; + public static final String JPEG_LOSSLESS_NH14 = "1.2.840.10008.1.2.4.57"; + public static final String JPEG_LOSSLESS_SV1 = "1.2.840.10008.1.2.4.70"; + public static final String JPEG_LS_LOSSLESS = "1.2.840.10008.1.2.4.80"; + public static final String JPEG_LS_NEAR_LOSSLESS = "1.2.840.10008.1.2.4.81"; + public static final String JPEG_2000_LOSSLESS = "1.2.840.10008.1.2.4.90"; + public static final String JPEG_2000 = "1.2.840.10008.1.2.4.91"; + public static final String MPEG2 = "1.2.840.10008.1.2.4.100"; + public static final String RLE_LOSSLESS = "1.2.840.10008.1.2.5"; + + // DICOM Status Codes + public static final int STATUS_SUCCESS = 0x0000; + public static final int STATUS_WARNING_COERCION = 0xB000; + public static final int STATUS_WARNING_ELEMENTS_DISCARDED = 0xB006; + public static final int STATUS_WARNING_DATA_SET_MISMATCH = 0xB007; + public static final int STATUS_PROCESSING_FAILURE = 0x0110; + + /** + * Formats a 16-bit status code as a 4-character hex string (e.g., 0xB000 → "B000"). + * Equivalent to dcm4che2's StringUtils.shortToHex(). + */ + public static String shortToHex(int val) { + return String.format("%04X", val & 0xFFFF); + } +} diff --git a/server/src/com/mirth/connect/connectors/dimse/dicom/DicomLibraryFactory.java b/server/src/com/mirth/connect/connectors/dimse/dicom/DicomLibraryFactory.java new file mode 100644 index 0000000000..e6f43f8906 --- /dev/null +++ b/server/src/com/mirth/connect/connectors/dimse/dicom/DicomLibraryFactory.java @@ -0,0 +1,205 @@ +/* + * Copyright (c) Mirth Corporation. All rights reserved. + * + * http://www.mirthcorp.com + * + * The software in this package is published under the terms of the MPL license a copy of which has + * been included with this distribution in the LICENSE.txt file. + */ + +package com.mirth.connect.connectors.dimse.dicom; + +import java.io.File; +import java.io.FileInputStream; +import java.lang.reflect.Constructor; +import java.util.Properties; + +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + +import com.mirth.connect.connectors.dimse.DICOMConfiguration; +import com.mirth.connect.donkey.server.channel.SourceConnector; + +/** + * Factory for creating version-neutral DICOM library instances. Reads the + * {@code dicom.library} property from mirth.properties to determine which + * backend to use. Defaults to {@code dcm4che2}. + * + *

All backend classes are loaded via {@code Class.forName} to avoid + * compile-time dependencies on variant-specific code. + */ +public final class DicomLibraryFactory { + + private static final Logger logger = LogManager.getLogger(DicomLibraryFactory.class); + + private static final String MIRTH_PROPERTIES_FILE = "./conf/mirth.properties"; + private static final String PROPERTY_DICOM_LIBRARY = "dicom.library"; + + // dcm4che2 backend class names + private static final String DCM2_CONVERTER = "com.mirth.connect.connectors.dimse.dicom.dcm2.Dcm2DicomConverter"; + private static final String DCM2_SENDER = "com.mirth.connect.connectors.dimse.dicom.dcm2.Dcm2DicomSender"; + private static final String DCM2_RECEIVER = "com.mirth.connect.connectors.dimse.dicom.dcm2.Dcm2DicomReceiver"; + private static final String DCM2_DEFAULT_CONFIG = "com.mirth.connect.connectors.dimse.DefaultDICOMConfiguration"; + + // dcm4che5 backend class names + private static final String DCM5_CONVERTER = "com.mirth.connect.connectors.dimse.dicom.dcm5.Dcm5DicomConverter"; + private static final String DCM5_SENDER = "com.mirth.connect.connectors.dimse.dicom.dcm5.Dcm5DicomSender"; + private static final String DCM5_RECEIVER = "com.mirth.connect.connectors.dimse.dicom.dcm5.Dcm5DicomReceiver"; + private static final String DCM5_DEFAULT_CONFIG = "com.mirth.connect.connectors.dimse.DefaultDcm5DICOMConfiguration"; + + public enum DicomLibrary { + DCM4CHE2, DCM4CHE5 + } + + private static volatile DicomLibrary activeLibrary; + private static volatile OieDicomConverter converterInstance; + + private DicomLibraryFactory() {} + + /** + * Returns the active DICOM library backend, reading from mirth.properties on first access. + */ + public static DicomLibrary getActiveLibrary() { + if (activeLibrary == null) { + synchronized (DicomLibraryFactory.class) { + if (activeLibrary == null) { + activeLibrary = detectLibrary(); + } + } + } + return activeLibrary; + } + + /** + * Returns a singleton converter instance for the configured DICOM library version. + */ + public static OieDicomConverter getConverter() { + if (converterInstance == null) { + synchronized (DicomLibraryFactory.class) { + if (converterInstance == null) { + converterInstance = createConverterInstance(); + } + } + } + return converterInstance; + } + + /** + * Creates a new DICOM sender for the configured library version. + */ + public static OieDicomSender createSender(DICOMConfiguration configuration) { + try { + String className = getSenderClassName(); + Class clazz = Class.forName(className); + Constructor ctor = clazz.getConstructor(DICOMConfiguration.class); + return (OieDicomSender) ctor.newInstance(configuration); + } catch (Exception e) { + throw new RuntimeException("Failed to create DICOM sender for library: " + getActiveLibrary(), e); + } + } + + /** + * Creates a new DICOM receiver for the configured library version. + */ + public static OieDicomReceiver createReceiver(SourceConnector connector, DICOMConfiguration configuration) { + try { + String className = getReceiverClassName(); + Class clazz = Class.forName(className); + Constructor ctor = clazz.getConstructor(SourceConnector.class, DICOMConfiguration.class); + return (OieDicomReceiver) ctor.newInstance(connector, configuration); + } catch (Exception e) { + throw new RuntimeException("Failed to create DICOM receiver for library: " + getActiveLibrary(), e); + } + } + + /** + * Creates the default DICOMConfiguration for the configured library version. + */ + public static DICOMConfiguration createDefaultConfiguration() { + try { + String className = getDefaultConfigClassName(); + return (DICOMConfiguration) Class.forName(className).getDeclaredConstructor().newInstance(); + } catch (Exception e) { + throw new RuntimeException("Failed to create default DICOMConfiguration for library: " + getActiveLibrary(), e); + } + } + + /** + * Loads a DICOMConfiguration by class name. Falls back to the default configuration + * if the class cannot be loaded or does not implement DICOMConfiguration. + * + * @param className the fully qualified class name, or null/empty for the default + * @return a DICOMConfiguration instance + */ + public static DICOMConfiguration loadConfiguration(String className) { + if (className == null || className.trim().isEmpty()) { + return createDefaultConfiguration(); + } + try { + Object instance = Class.forName(className.trim()).getDeclaredConstructor().newInstance(); + if (instance instanceof DICOMConfiguration) { + return (DICOMConfiguration) instance; + } + logger.warn("Custom DICOMConfiguration class does not implement current interface: " + + className + ". Using default. If this is a legacy class, recompile against Dcm2DICOMConfiguration."); + return createDefaultConfiguration(); + } catch (Exception e) { + logger.warn("Could not load custom DICOMConfiguration class, using default: " + className, e); + return createDefaultConfiguration(); + } + } + + private static OieDicomConverter createConverterInstance() { + try { + String className = getConverterClassName(); + return (OieDicomConverter) Class.forName(className).getDeclaredConstructor().newInstance(); + } catch (Exception e) { + throw new RuntimeException("Failed to create DICOM converter for library: " + getActiveLibrary(), e); + } + } + + private static String getConverterClassName() { + return getActiveLibrary() == DicomLibrary.DCM4CHE5 ? DCM5_CONVERTER : DCM2_CONVERTER; + } + + private static String getSenderClassName() { + return getActiveLibrary() == DicomLibrary.DCM4CHE5 ? DCM5_SENDER : DCM2_SENDER; + } + + private static String getReceiverClassName() { + return getActiveLibrary() == DicomLibrary.DCM4CHE5 ? DCM5_RECEIVER : DCM2_RECEIVER; + } + + private static String getDefaultConfigClassName() { + return getActiveLibrary() == DicomLibrary.DCM4CHE5 ? DCM5_DEFAULT_CONFIG : DCM2_DEFAULT_CONFIG; + } + + private static DicomLibrary detectLibrary() { + DicomLibrary library = DicomLibrary.DCM4CHE2; + try (FileInputStream is = new FileInputStream(new File(MIRTH_PROPERTIES_FILE))) { + Properties props = new Properties(); + props.load(is); + String value = props.getProperty(PROPERTY_DICOM_LIBRARY, "dcm4che2").trim(); + if ("dcm4che5".equalsIgnoreCase(value)) { + library = DicomLibrary.DCM4CHE5; + } else if (!value.isEmpty() && !"dcm4che2".equalsIgnoreCase(value)) { + logger.warn("Unrecognized value for {}: '{}'. Supported values are 'dcm4che2' and 'dcm4che5'. Defaulting to dcm4che2.", + PROPERTY_DICOM_LIBRARY, value); + } + } catch (Exception e) { + // Default to dcm4che2 if properties cannot be read (e.g., in tests) + } + logger.info("DICOM library backend: {}", library); + return library; + } + + /** + * Resets factory state for testing. Not for production use. + */ + public static void resetForTesting(DicomLibrary override) { + synchronized (DicomLibraryFactory.class) { + activeLibrary = override; + converterInstance = null; + } + } +} diff --git a/server/src/com/mirth/connect/connectors/dimse/dicom/OieDicomConverter.java b/server/src/com/mirth/connect/connectors/dimse/dicom/OieDicomConverter.java new file mode 100644 index 0000000000..f17c6b566c --- /dev/null +++ b/server/src/com/mirth/connect/connectors/dimse/dicom/OieDicomConverter.java @@ -0,0 +1,68 @@ +/* + * Copyright (c) Mirth Corporation. All rights reserved. + * + * http://www.mirthcorp.com + * + * The software in this package is published under the terms of the MPL license a copy of which has + * been included with this distribution in the LICENSE.txt file. + */ + +package com.mirth.connect.connectors.dimse.dicom; + +import java.io.IOException; + +/** + * Version-neutral interface for DICOM conversion operations. Abstracts the byte-array, + * XML, and object conversion logic across dcm4che library versions. + */ +public interface OieDicomConverter { + + /** + * Parses a byte array into a DICOM object. + * + * @param bytes The binary DICOM data + * @param decodeBase64 If true, the input is Base64-decoded before parsing + * @return The parsed DICOM object + */ + OieDicomObject byteArrayToDicomObject(byte[] bytes, boolean decodeBase64) throws IOException; + + /** + * Serializes a DICOM object to a byte array. Note: the DICOM object is cleared + * after serialization as a memory optimization. + * + * @param dicomObject The DICOM object to serialize + * @return The serialized byte array + */ + byte[] dicomObjectToByteArray(OieDicomObject dicomObject) throws IOException; + + /** + * Creates a new empty DICOM object. + */ + OieDicomObject createDicomObject(); + + /** + * Converts Base64-encoded DICOM data to its XML representation. + * The XML uses dcm4che's native format with <attr> elements. + * + * @param encodedDicomBytes ASCII bytes of Base64-encoded DICOM data + * @return The XML string representation + */ + String dicomBytesToXml(byte[] encodedDicomBytes) throws Exception; + + /** + * Parses XML (in dcm4che attr format) into a DICOM object. + * + * @param xml The XML string in dcm4che format + * @param charset The character set for the XML bytes + * @return The parsed DICOM object + */ + OieDicomObject xmlToDicomObject(String xml, String charset) throws Exception; + + /** + * Returns the human-readable name for a DICOM tag. + * + * @param tag The DICOM tag number + * @return The element name, or empty string if unknown + */ + String getElementName(int tag); +} diff --git a/server/src/com/mirth/connect/connectors/dimse/dicom/OieDicomElement.java b/server/src/com/mirth/connect/connectors/dimse/dicom/OieDicomElement.java new file mode 100644 index 0000000000..5b7c728ad1 --- /dev/null +++ b/server/src/com/mirth/connect/connectors/dimse/dicom/OieDicomElement.java @@ -0,0 +1,76 @@ +/* + * Copyright (c) Mirth Corporation. All rights reserved. + * + * http://www.mirthcorp.com + * + * The software in this package is published under the terms of the MPL license a copy of which has + * been included with this distribution in the LICENSE.txt file. + */ + +package com.mirth.connect.connectors.dimse.dicom; + +/** + * Version-neutral interface for DICOM data elements. Wraps dcm4che2 DicomElement + * or dcm4che5 element access on Attributes. + */ +public interface OieDicomElement { + + int tag(); + + int length(); + + OieVR vr(); + + String getValueAsString(int index); + + boolean hasItems(); + + int countItems(); + + boolean isEmpty(); + + boolean hasDicomObjects(); + + boolean hasFragments(); + + byte[] getFragment(int index); + + byte[] getBytes(); + + String[] getStrings(); + + int getInt(int defaultValue); + + int[] getInts(); + + float getFloat(float defaultValue); + + float[] getFloats(); + + double getDouble(double defaultValue); + + double[] getDoubles(); + + java.util.Date getDate(); + + java.util.Date[] getDates(); + + void addFragment(byte[] data); + + OieDicomObject getDicomObject(); + + /** + * Returns the sequence item at the given index, or null if the index is out of range + * or this element is not a sequence. + */ + default OieDicomObject getDicomObject(int index) { + return index == 0 ? getDicomObject() : null; + } + + void addDicomObject(OieDicomObject obj); + + /** + * Returns the underlying library-specific element. Use with caution. + */ + Object unwrap(); +} diff --git a/server/src/com/mirth/connect/connectors/dimse/dicom/OieDicomObject.java b/server/src/com/mirth/connect/connectors/dimse/dicom/OieDicomObject.java new file mode 100644 index 0000000000..bab4499156 --- /dev/null +++ b/server/src/com/mirth/connect/connectors/dimse/dicom/OieDicomObject.java @@ -0,0 +1,123 @@ +/* + * Copyright (c) Mirth Corporation. All rights reserved. + * + * http://www.mirthcorp.com + * + * The software in this package is published under the terms of the MPL license a copy of which has + * been included with this distribution in the LICENSE.txt file. + */ + +package com.mirth.connect.connectors.dimse.dicom; + +import java.util.Date; +import java.util.Iterator; + +/** + * Version-neutral interface for DICOM data objects. Wraps dcm4che2 DicomObject/BasicDicomObject + * or dcm4che5 Attributes, providing a consistent API across library versions. + */ +public interface OieDicomObject { + + String getString(int tag); + + /** + * Returns the string value for the given tag, or {@code defaultValue} + * if the tag is not present. + */ + default String getString(int tag, String defaultValue) { + String val = getString(tag); + return val != null ? val : defaultValue; + } + + int getInt(int tag); + + /** + * Returns the integer value for the given tag, or {@code defaultValue} + * if the tag is not present. + */ + default int getInt(int tag, int defaultValue) { + OieDicomElement elem = get(tag); + return elem != null ? getInt(tag) : defaultValue; + } + + OieDicomElement get(int tag); + + boolean contains(int tag); + + int size(); + + boolean isEmpty(); + + byte[] getBytes(int tag); + + int[] getInts(int tag); + + String[] getStrings(int tag); + + float getFloat(int tag, float defaultValue); + + float[] getFloats(int tag); + + double getDouble(int tag, double defaultValue); + + double[] getDoubles(int tag); + + Date getDate(int tag); + + Date[] getDates(int tag); + + OieDicomObject getNestedDicomObject(int tag); + + /** Value multiplicity for the element at {@code tag}. Returns 0 when absent. */ + int vm(int tag); + + /** Two-letter VR code for {@code tag}, derived from the DICOM dictionary. */ + String vrOf(int tag); + + /** Human-readable attribute name for {@code tag}, or {@code null} when unknown. */ + String nameOf(int tag); + + void putString(int tag, String vr, String value); + + void putInt(int tag, String vr, int value); + + void putBytes(int tag, String vr, byte[] value); + + OieDicomElement putSequence(int tag); + + OieDicomElement putFragments(int tag, String vr, boolean bigEndian, int capacity); + + void add(OieDicomElement element); + + OieDicomElement remove(int tag); + + void clear(); + + boolean hasFileMetaInfo(); + + void initFileMetaInformation(String cuid, String iuid, String tsuid); + + boolean bigEndian(); + + /** + * Returns a read-only iterator over the command elements (group 0x0000) of this DICOM object. + * Used for building response XML from DIMSE command responses. + * + *

The returned iterator does not support {@code remove()}. Callers must not + * attempt to modify the iteration — behavior varies by implementation. + */ + Iterator commandIterator(); + + /** + * Returns the underlying library-specific DICOM object (e.g., dcm4che2 DicomObject + * or dcm4che5 Attributes). Use with caution — this breaks version independence. + * + *

Example — accessing dcm4che2 APIs from a user script: + *

{@code
+     * OieDicomObject oie = DICOMUtil.byteArrayToDicomObject(bytes, false);
+     * DicomObject dcm = (DicomObject) oie.unwrap();
+     * dcm.getString(Tag.PatientName, "UNKNOWN");
+     * }
+ */ + Object unwrap(); +} diff --git a/server/src/com/mirth/connect/connectors/dimse/dicom/OieDicomReceiver.java b/server/src/com/mirth/connect/connectors/dimse/dicom/OieDicomReceiver.java new file mode 100644 index 0000000000..b8c55c9921 --- /dev/null +++ b/server/src/com/mirth/connect/connectors/dimse/dicom/OieDicomReceiver.java @@ -0,0 +1,109 @@ +/* + * Copyright (c) Mirth Corporation. All rights reserved. + * + * http://www.mirthcorp.com + * + * The software in this package is published under the terms of the MPL license a copy of which has + * been included with this distribution in the LICENSE.txt file. + */ + +package com.mirth.connect.connectors.dimse.dicom; + +/** + * Version-neutral interface for DICOM C-STORE SCP (receiver). Abstracts dcm4che2's + * MirthDcmRcv/DcmRcv and dcm4che5's StoreSCP. + */ +public interface OieDicomReceiver { + + void setPort(int port); + + void setHostname(String hostname); + + void setDestination(String destination); + + void setTransferSyntax(String[] transferSyntax); + + void setAEtitle(String aeTitle); + + void setAssociationReaperPeriod(int period); + + void setIdleTimeout(int timeout); + + void setRequestTimeout(int timeout); + + void setReleaseTimeout(int timeout); + + void setSocketCloseDelay(int delay); + + void setDimseRspDelay(int delay); + + void setMaxPDULengthReceive(int length); + + void setMaxPDULengthSend(int length); + + void setSendBufferSize(int size); + + void setReceiveBufferSize(int size); + + void setFileBufferSize(int size); + + void setPackPDV(boolean packPDV); + + void setTcpNoDelay(boolean tcpNoDelay); + + void setMaxOpsPerformed(int maxOps); + + void setTlsWithoutEncryption(); + + void setTls3DES_EDE_CBC(); + + void setTlsAES_128_CBC(); + + /** + * Sets custom TLS cipher suites. Use this instead of the preset methods + * (setTlsWithoutEncryption, setTls3DES_EDE_CBC, setTlsAES_128_CBC) when + * those legacy suites are not suitable (e.g., disabled in modern JVMs). + */ + default void setTlsCipherSuites(String[] cipherSuites) {} + + void setTrustStoreURL(String url); + + void setTrustStorePassword(String password); + + void setKeyPassword(String password); + + void setKeyStoreURL(String url); + + void setKeyStorePassword(String password); + + /** + * Sets the keystore type (e.g., "JKS", "PKCS12", "JCEKS"). + * dcm4che2 infers this automatically; dcm4che5 requires it explicitly. + * If not set, dcm4che5 will infer from the keystore URL file extension. + */ + default void setKeyStoreType(String type) {} + + /** + * Sets the truststore type (e.g., "JKS", "PKCS12", "JCEKS"). + * dcm4che2 infers this automatically; dcm4che5 requires it explicitly. + * If not set, dcm4che5 will infer from the truststore URL file extension. + */ + default void setTrustStoreType(String type) {} + + void setTlsNeedClientAuth(boolean needClientAuth); + + void setTlsProtocol(String[] protocols); + + void initTLS() throws Exception; + + void initTransferCapability(); + + void start() throws Exception; + + void stop(); + + /** + * Returns the underlying library-specific receiver object. Use with caution. + */ + Object unwrap(); +} diff --git a/server/src/com/mirth/connect/connectors/dimse/dicom/OieDicomSender.java b/server/src/com/mirth/connect/connectors/dimse/dicom/OieDicomSender.java new file mode 100644 index 0000000000..5a785bed5f --- /dev/null +++ b/server/src/com/mirth/connect/connectors/dimse/dicom/OieDicomSender.java @@ -0,0 +1,138 @@ +/* + * Copyright (c) Mirth Corporation. All rights reserved. + * + * http://www.mirthcorp.com + * + * The software in this package is published under the terms of the MPL license a copy of which has + * been included with this distribution in the LICENSE.txt file. + */ + +package com.mirth.connect.connectors.dimse.dicom; + +import java.io.File; +import java.io.IOException; + +/** + * Version-neutral interface for DICOM C-STORE SCU (sender). Abstracts dcm4che2's + * MirthDcmSnd/DcmSnd and dcm4che5's StoreSCU. + */ +public interface OieDicomSender { + + void setCalledAET(String aet); + + void setRemoteHost(String host); + + void setRemotePort(int port); + + void setCalling(String aet); + + void setLocalHost(String host); + + void setLocalPort(int port); + + void addFile(File file); + + void setAcceptTimeout(int timeout); + + void setMaxOpsInvoked(int maxOps); + + void setTranscoderBufferSize(int size); + + void setConnectTimeout(int timeout); + + void setPriority(int priority); + + void setPackPDV(boolean packPDV); + + void setMaxPDULengthReceive(int length); + + void setMaxPDULengthSend(int length); + + void setReceiveBufferSize(int size); + + void setSendBufferSize(int size); + + void setAssociationReaperPeriod(int period); + + void setReleaseTimeout(int timeout); + + void setDimseRspTimeout(int timeout); + + void setShutdownDelay(int delay); + + void setSocketCloseDelay(int delay); + + void setTcpNoDelay(boolean tcpNoDelay); + + void setOfferDefaultTransferSyntaxInSeparatePresentationContext(boolean ts1); + + void setStorageCommitment(boolean stgcmt); + + void setUserIdentity(String username, String passcode, boolean positiveResponseRequested); + + void setTlsWithoutEncryption(); + + void setTls3DES_EDE_CBC(); + + void setTlsAES_128_CBC(); + + /** + * Sets custom TLS cipher suites. Use this instead of the preset methods + * (setTlsWithoutEncryption, setTls3DES_EDE_CBC, setTlsAES_128_CBC) when + * those legacy suites are not suitable (e.g., disabled in modern JVMs). + */ + default void setTlsCipherSuites(String[] cipherSuites) {} + + void setTrustStoreURL(String url); + + void setTrustStorePassword(String password); + + void setKeyPassword(String password); + + void setKeyStoreURL(String url); + + void setKeyStorePassword(String password); + + /** + * Sets the keystore type (e.g., "JKS", "PKCS12", "JCEKS"). + * dcm4che2 infers this automatically; dcm4che5 requires it explicitly. + * If not set, dcm4che5 will infer from the keystore URL file extension. + */ + default void setKeyStoreType(String type) {} + + /** + * Sets the truststore type (e.g., "JKS", "PKCS12", "JCEKS"). + * dcm4che2 infers this automatically; dcm4che5 requires it explicitly. + * If not set, dcm4che5 will infer from the truststore URL file extension. + */ + default void setTrustStoreType(String type) {} + + void setTlsNeedClientAuth(boolean needClientAuth); + + void setTlsProtocol(String[] protocols); + + void initTLS() throws Exception; + + void configureTransferCapability(); + + void start() throws IOException; + + void open() throws Exception; + + void send(OieDimseRspHandler handler) throws Exception; + + boolean isStorageCommitment(); + + boolean commit() throws Exception; + + OieDicomObject waitForStgCmtResult() throws InterruptedException; + + void close(); + + void stop(); + + /** + * Returns the underlying library-specific sender object. Use with caution. + */ + Object unwrap(); +} diff --git a/server/src/com/mirth/connect/connectors/dimse/dicom/OieDimseRspHandler.java b/server/src/com/mirth/connect/connectors/dimse/dicom/OieDimseRspHandler.java new file mode 100644 index 0000000000..814923bdb2 --- /dev/null +++ b/server/src/com/mirth/connect/connectors/dimse/dicom/OieDimseRspHandler.java @@ -0,0 +1,25 @@ +/* + * Copyright (c) Mirth Corporation. All rights reserved. + * + * http://www.mirthcorp.com + * + * The software in this package is published under the terms of the MPL license a copy of which has + * been included with this distribution in the LICENSE.txt file. + */ + +package com.mirth.connect.connectors.dimse.dicom; + +/** + * Version-neutral interface for handling DIMSE responses. Replaces dcm4che2's + * CustomDimseRSPHandler with a version-independent callback. + */ +public interface OieDimseRspHandler { + + /** + * Called when a DIMSE response is received. + * + * @param cmd The command DICOM object from the response + * @param data The data DICOM object from the response (may be null) + */ + void onDimseRSP(OieDicomObject cmd, OieDicomObject data); +} diff --git a/server/src/com/mirth/connect/connectors/dimse/dicom/OieVR.java b/server/src/com/mirth/connect/connectors/dimse/dicom/OieVR.java new file mode 100644 index 0000000000..6d7e874ee3 --- /dev/null +++ b/server/src/com/mirth/connect/connectors/dimse/dicom/OieVR.java @@ -0,0 +1,31 @@ +/* + * Copyright (c) Mirth Corporation. All rights reserved. + * + * http://www.mirthcorp.com + * + * The software in this package is published under the terms of the MPL license a copy of which has + * been included with this distribution in the LICENSE.txt file. + */ + +package com.mirth.connect.connectors.dimse.dicom; + +/** + * Version-neutral wrapper for a DICOM Value Representation. Matches the runtime + * shape of dcm4che2's {@code VR} class so existing JavaScript transformer + * scripts calling {@code elem.vr().code()} or {@code String(elem.vr())} + * continue to work regardless of the configured DICOM backend. + */ +public interface OieVR { + + /** Two-character VR code (e.g. {@code "UI"}, {@code "SQ"}, {@code "OB"}). */ + String toString(); + + /** Packed 16-bit representation of the VR code, as stored on the wire. */ + int code(); + + /** Pad byte used when the VR's encoded length would otherwise be odd. */ + int padding(); + + /** Underlying library-specific VR object. Use with caution. */ + Object unwrap(); +} diff --git a/server/src/com/mirth/connect/connectors/dimse/dicom/dcm2/Dcm2DICOMConfiguration.java b/server/src/com/mirth/connect/connectors/dimse/dicom/dcm2/Dcm2DICOMConfiguration.java new file mode 100644 index 0000000000..0b8f922ea2 --- /dev/null +++ b/server/src/com/mirth/connect/connectors/dimse/dicom/dcm2/Dcm2DICOMConfiguration.java @@ -0,0 +1,75 @@ +/* + * Copyright (c) Mirth Corporation. All rights reserved. + * + * http://www.mirthcorp.com + * + * The software in this package is published under the terms of the MPL license a copy of which has + * been included with this distribution in the LICENSE.txt file. + */ + +package com.mirth.connect.connectors.dimse.dicom.dcm2; + +import java.util.Map; + +import org.dcm4che2.net.Association; +import org.dcm4che2.net.NetworkConnection; +import org.dcm4che2.tool.dcmrcv.MirthDcmRcv; +import org.dcm4che2.tool.dcmsnd.MirthDcmSnd; + +import com.mirth.connect.connectors.dimse.DICOMConfiguration; +import com.mirth.connect.connectors.dimse.DICOMDispatcher; +import com.mirth.connect.connectors.dimse.DICOMDispatcherProperties; +import com.mirth.connect.connectors.dimse.DICOMReceiver; +import com.mirth.connect.connectors.dimse.DICOMReceiverProperties; +import com.mirth.connect.connectors.dimse.dicom.OieDicomReceiver; +import com.mirth.connect.connectors.dimse.dicom.OieDicomSender; + +/** + * dcm4che2-specific extension of {@link DICOMConfiguration}. Provides the + * legacy dcm4che2-typed method signatures and bridge defaults that delegate + * the version-neutral methods to the legacy ones. + * + *

Custom implementations that need dcm4che2 API access should implement + * this interface. The method signatures match the original pre-abstraction + * {@code DICOMConfiguration} interface, so migrating is a one-line change: + * replace {@code implements DICOMConfiguration} with + * {@code implements Dcm2DICOMConfiguration}. + */ +public interface Dcm2DICOMConfiguration extends DICOMConfiguration { + + // Legacy dcm4che2-typed methods (same signatures as original DICOMConfiguration) + + void configureDcmRcv(MirthDcmRcv dcmrcv, DICOMReceiver connector, + DICOMReceiverProperties connectorProperties) throws Exception; + + void configureDcmSnd(MirthDcmSnd dcmsnd, DICOMDispatcher connector, + DICOMDispatcherProperties connectorProperties) throws Exception; + + Map getCStoreRequestInformation(Association association); + + NetworkConnection createLegacyNetworkConnection(); + + // Bridge defaults: version-neutral methods delegate to legacy-typed methods + + @Override + default void configureReceiver(OieDicomReceiver receiver, DICOMReceiver connector, + DICOMReceiverProperties connectorProperties) throws Exception { + configureDcmRcv((MirthDcmRcv) receiver.unwrap(), connector, connectorProperties); + } + + @Override + default void configureSender(OieDicomSender sender, DICOMDispatcher connector, + DICOMDispatcherProperties connectorProperties) throws Exception { + configureDcmSnd((MirthDcmSnd) sender.unwrap(), connector, connectorProperties); + } + + @Override + default Map getCStoreRequestInformation(Object association) { + return getCStoreRequestInformation((Association) association); + } + + @Override + default Object createNetworkConnection() { + return createLegacyNetworkConnection(); + } +} diff --git a/server/src/com/mirth/connect/connectors/dimse/dicom/dcm2/Dcm2DicomConverter.java b/server/src/com/mirth/connect/connectors/dimse/dicom/dcm2/Dcm2DicomConverter.java new file mode 100644 index 0000000000..50257d8e51 --- /dev/null +++ b/server/src/com/mirth/connect/connectors/dimse/dicom/dcm2/Dcm2DicomConverter.java @@ -0,0 +1,183 @@ +/* + * Copyright (c) Mirth Corporation. All rights reserved. + * + * http://www.mirthcorp.com + * + * The software in this package is published under the terms of the MPL license a copy of which has + * been included with this distribution in the LICENSE.txt file. + */ + +package com.mirth.connect.connectors.dimse.dicom.dcm2; + +import java.io.BufferedInputStream; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.StringWriter; + +import javax.xml.XMLConstants; +import javax.xml.parsers.SAXParser; +import javax.xml.parsers.SAXParserFactory; +import javax.xml.transform.OutputKeys; +import javax.xml.transform.TransformerFactory; +import javax.xml.transform.sax.SAXTransformerFactory; +import javax.xml.transform.sax.TransformerHandler; +import javax.xml.transform.stream.StreamResult; + +import org.apache.commons.codec.binary.Base64InputStream; +import org.apache.commons.io.IOUtils; +import org.dcm4che2.data.BasicDicomObject; +import org.dcm4che2.data.DicomObject; +import org.dcm4che2.data.ElementDictionary; +import org.dcm4che2.data.TransferSyntax; +import org.dcm4che2.io.ContentHandlerAdapter; +import org.dcm4che2.io.DicomInputStream; +import org.dcm4che2.io.DicomOutputStream; +import org.dcm4che2.io.SAXWriter; +import org.xml.sax.InputSource; + +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + +import com.mirth.connect.connectors.dimse.dicom.OieDicomConverter; +import com.mirth.connect.connectors.dimse.dicom.OieDicomObject; +import com.mirth.connect.donkey.util.ByteCounterOutputStream; + +/** + * dcm4che2 implementation of OieDicomConverter. Handles all byte-array, XML, and + * DICOM object conversion using the dcm4che 2.0.29 library. + */ +public class Dcm2DicomConverter implements OieDicomConverter { + + private static final Logger logger = LogManager.getLogger(Dcm2DicomConverter.class); + + @Override + public OieDicomObject byteArrayToDicomObject(byte[] bytes, boolean decodeBase64) throws IOException { + DicomObject basicDicomObject = new BasicDicomObject(); + DicomInputStream dis = null; + + try { + ByteArrayInputStream bais = new ByteArrayInputStream(bytes); + InputStream inputStream; + if (decodeBase64) { + inputStream = new BufferedInputStream(new Base64InputStream(bais)); + } else { + inputStream = bais; + } + dis = new DicomInputStream(inputStream); + /* + * This parameter was added in dcm4che 2.0.28. We use it to retain the memory allocation + * behavior from 2.0.25. http://www.mirthcorp.com/community/issues/browse/MIRTH-2166 + * http://www.dcm4che.org/jira/browse/DCM-554 + */ + dis.setAllocateLimit(-1); + dis.readDicomObject(basicDicomObject, -1); + } catch (IOException e) { + throw e; + } finally { + IOUtils.closeQuietly(dis); + } + + return new Dcm2DicomObject(basicDicomObject); + } + + @Override + public byte[] dicomObjectToByteArray(OieDicomObject dicomObject) throws IOException { + BasicDicomObject basicDicomObject = (BasicDicomObject) dicomObject.unwrap(); + DicomOutputStream dos = null; + + try { + ByteCounterOutputStream bcos = new ByteCounterOutputStream(); + ByteArrayOutputStream baos; + + if (basicDicomObject.fileMetaInfo().isEmpty()) { + try { + dos = new DicomOutputStream(bcos); + dos.writeDataset(basicDicomObject, TransferSyntax.ImplicitVRLittleEndian); + } finally { + IOUtils.closeQuietly(dos); + } + + baos = new ByteArrayOutputStream(bcos.size()); + dos = new DicomOutputStream(baos); + dos.writeDataset(basicDicomObject, TransferSyntax.ImplicitVRLittleEndian); + } else { + try { + dos = new DicomOutputStream(bcos); + dos.writeDicomFile(basicDicomObject); + } finally { + IOUtils.closeQuietly(dos); + } + + baos = new ByteArrayOutputStream(bcos.size()); + dos = new DicomOutputStream(baos); + dos.writeDicomFile(basicDicomObject); + } + + // Memory Optimization since the dicom object is no longer needed at this point. + dicomObject.clear(); + + return baos.toByteArray(); + } catch (IOException e) { + throw e; + } catch (Throwable t) { + logger.error("Failed to serialize DICOM object to byte array", t); + throw new IOException("DICOM serialization failed", t); + } finally { + IOUtils.closeQuietly(dos); + } + } + + @Override + public OieDicomObject createDicomObject() { + return new Dcm2DicomObject(); + } + + @Override + public String dicomBytesToXml(byte[] encodedDicomBytes) throws Exception { + StringWriter output = new StringWriter(); + DicomInputStream dis = new DicomInputStream(new BufferedInputStream(new Base64InputStream(new ByteArrayInputStream(encodedDicomBytes)))); + dis.setAllocateLimit(-1); + + try { + TransformerFactory tf = TransformerFactory.newInstance(); + tf.setAttribute(XMLConstants.ACCESS_EXTERNAL_DTD, ""); + tf.setAttribute(XMLConstants.ACCESS_EXTERNAL_STYLESHEET, ""); + SAXTransformerFactory factory = (SAXTransformerFactory) tf; + TransformerHandler handler = factory.newTransformerHandler(); + handler.getTransformer().setOutputProperty(OutputKeys.INDENT, "no"); + handler.setResult(new StreamResult(output)); + + final SAXWriter writer = new SAXWriter(handler, null); + dis.setHandler(writer); + dis.readDicomObject(new BasicDicomObject(), -1); + + return output.toString(); + } finally { + IOUtils.closeQuietly(dis); + IOUtils.closeQuietly(output); + } + } + + @Override + public OieDicomObject xmlToDicomObject(String xml, String charset) throws Exception { + SAXParserFactory factory = SAXParserFactory.newInstance(); + factory.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true); + SAXParser parser = factory.newSAXParser(); + DicomObject dicomObject = new BasicDicomObject(); + ContentHandlerAdapter contentHandler = new ContentHandlerAdapter(dicomObject); + byte[] documentBytes = xml.trim().getBytes(charset); + parser.parse(new InputSource(new ByteArrayInputStream(documentBytes)), contentHandler); + return new Dcm2DicomObject(dicomObject); + } + + @Override + public String getElementName(int tag) { + try { + return ElementDictionary.getDictionary().nameOf(tag); + } catch (Exception e) { + return ""; + } + } +} diff --git a/server/src/com/mirth/connect/connectors/dimse/dicom/dcm2/Dcm2DicomElement.java b/server/src/com/mirth/connect/connectors/dimse/dicom/dcm2/Dcm2DicomElement.java new file mode 100644 index 0000000000..b8a6b25d17 --- /dev/null +++ b/server/src/com/mirth/connect/connectors/dimse/dicom/dcm2/Dcm2DicomElement.java @@ -0,0 +1,159 @@ +/* + * Copyright (c) Mirth Corporation. All rights reserved. + * + * http://www.mirthcorp.com + * + * The software in this package is published under the terms of the MPL license a copy of which has + * been included with this distribution in the LICENSE.txt file. + */ + +package com.mirth.connect.connectors.dimse.dicom.dcm2; + +import org.dcm4che2.data.DicomElement; +import org.dcm4che2.data.DicomObject; + +import com.mirth.connect.connectors.dimse.dicom.OieDicomElement; +import com.mirth.connect.connectors.dimse.dicom.OieDicomObject; +import com.mirth.connect.connectors.dimse.dicom.OieVR; + +/** + * dcm4che2 implementation of OieDicomElement, wrapping DicomElement. + */ +public class Dcm2DicomElement implements OieDicomElement { + + private final DicomElement delegate; + + public Dcm2DicomElement(DicomElement delegate) { + this.delegate = delegate; + } + + @Override + public int tag() { + return delegate.tag(); + } + + @Override + public int length() { + return delegate.length(); + } + + @Override + public OieVR vr() { + return new Dcm2VR(delegate.vr()); + } + + @Override + public String getValueAsString(int index) { + return delegate.getValueAsString(null, index); + } + + @Override + public boolean hasItems() { + return delegate.hasItems(); + } + + @Override + public int countItems() { + return delegate.countItems(); + } + + @Override + public boolean isEmpty() { + return delegate.isEmpty(); + } + + @Override + public boolean hasDicomObjects() { + return delegate.hasDicomObjects(); + } + + @Override + public boolean hasFragments() { + return delegate.hasFragments(); + } + + @Override + public byte[] getFragment(int index) { + return delegate.getFragment(index); + } + + @Override + public byte[] getBytes() { + return delegate.getBytes(); + } + + @Override + public String[] getStrings() { + return delegate.getStrings(null, false); + } + + @Override + public int getInt(int defaultValue) { + return delegate.isEmpty() ? defaultValue : delegate.getInt(false); + } + + @Override + public int[] getInts() { + return delegate.getInts(false); + } + + @Override + public float getFloat(float defaultValue) { + return delegate.isEmpty() ? defaultValue : delegate.getFloat(false); + } + + @Override + public float[] getFloats() { + return delegate.getFloats(false); + } + + @Override + public double getDouble(double defaultValue) { + return delegate.isEmpty() ? defaultValue : delegate.getDouble(false); + } + + @Override + public double[] getDoubles() { + return delegate.getDoubles(false); + } + + @Override + public java.util.Date getDate() { + return delegate.getDate(false); + } + + @Override + public java.util.Date[] getDates() { + return delegate.getDates(false); + } + + @Override + public void addFragment(byte[] data) { + delegate.addFragment(data); + } + + @Override + public OieDicomObject getDicomObject() { + DicomObject obj = delegate.getDicomObject(); + return obj != null ? new Dcm2DicomObject(obj) : null; + } + + @Override + public OieDicomObject getDicomObject(int index) { + if (index < 0 || index >= delegate.countItems()) { + return null; + } + DicomObject obj = delegate.getDicomObject(index); + return obj != null ? new Dcm2DicomObject(obj) : null; + } + + @Override + public void addDicomObject(OieDicomObject obj) { + delegate.addDicomObject((DicomObject) obj.unwrap()); + } + + @Override + public Object unwrap() { + return delegate; + } +} diff --git a/server/src/com/mirth/connect/connectors/dimse/dicom/dcm2/Dcm2DicomObject.java b/server/src/com/mirth/connect/connectors/dimse/dicom/dcm2/Dcm2DicomObject.java new file mode 100644 index 0000000000..02280b9bde --- /dev/null +++ b/server/src/com/mirth/connect/connectors/dimse/dicom/dcm2/Dcm2DicomObject.java @@ -0,0 +1,265 @@ +/* + * Copyright (c) Mirth Corporation. All rights reserved. + * + * http://www.mirthcorp.com + * + * The software in this package is published under the terms of the MPL license a copy of which has + * been included with this distribution in the LICENSE.txt file. + */ + +package com.mirth.connect.connectors.dimse.dicom.dcm2; + +import java.util.Iterator; +import java.util.NoSuchElementException; + +import org.dcm4che2.data.BasicDicomObject; +import org.dcm4che2.data.DicomElement; +import org.dcm4che2.data.DicomObject; +import org.dcm4che2.data.VR; + +import com.mirth.connect.connectors.dimse.dicom.OieDicomElement; +import com.mirth.connect.connectors.dimse.dicom.OieDicomObject; +import com.mirth.connect.connectors.dimse.dicom.OieVR; + +/** + * dcm4che2 implementation of OieDicomObject, wrapping BasicDicomObject/DicomObject. + */ +public class Dcm2DicomObject implements OieDicomObject { + + static VR toVR(String vrName) { + if (vrName == null || vrName.length() != 2) { + throw new IllegalArgumentException("Invalid VR: " + vrName); + } + return VR.valueOf((vrName.charAt(0) << 8) | vrName.charAt(1)); + } + + private final DicomObject delegate; + + public Dcm2DicomObject(DicomObject delegate) { + this.delegate = delegate; + } + + public Dcm2DicomObject() { + this(new BasicDicomObject()); + } + + @Override + public String getString(int tag) { + return delegate.getString(tag); + } + + @Override + public int getInt(int tag) { + return delegate.getInt(tag); + } + + @Override + public OieDicomElement get(int tag) { + DicomElement element = delegate.get(tag); + return element != null ? new Dcm2DicomElement(element) : null; + } + + @Override + public boolean contains(int tag) { + return delegate.contains(tag); + } + + @Override + public int size() { + return delegate.size(); + } + + @Override + public boolean isEmpty() { + return delegate.isEmpty(); + } + + @Override + public byte[] getBytes(int tag) { + return delegate.getBytes(tag); + } + + @Override + public int[] getInts(int tag) { + return delegate.getInts(tag); + } + + @Override + public String[] getStrings(int tag) { + return delegate.getStrings(tag); + } + + @Override + public float getFloat(int tag, float defaultValue) { + return delegate.getFloat(tag, defaultValue); + } + + @Override + public float[] getFloats(int tag) { + return delegate.getFloats(tag); + } + + @Override + public double getDouble(int tag, double defaultValue) { + return delegate.getDouble(tag, defaultValue); + } + + @Override + public double[] getDoubles(int tag) { + return delegate.getDoubles(tag); + } + + @Override + public java.util.Date getDate(int tag) { + return delegate.getDate(tag); + } + + @Override + public java.util.Date[] getDates(int tag) { + return delegate.getDates(tag); + } + + @Override + public OieDicomObject getNestedDicomObject(int tag) { + DicomObject nested = delegate.getNestedDicomObject(tag); + return nested != null ? new Dcm2DicomObject(nested) : null; + } + + @Override + public int vm(int tag) { + // dcm4che2 returns -1 when the tag is absent; normalize to 0 + // so callers can treat the result as a simple cardinality. + int vm = delegate.vm(tag); + return vm < 0 ? 0 : vm; + } + + @Override + public String vrOf(int tag) { + VR vr = delegate.vrOf(tag); + return vr != null ? vr.toString() : null; + } + + @Override + public String nameOf(int tag) { + return delegate.nameOf(tag); + } + + @Override + public void putString(int tag, String vr, String value) { + delegate.putString(tag, toVR(vr), value); + } + + @Override + public void putInt(int tag, String vr, int value) { + delegate.putInt(tag, toVR(vr), value); + } + + @Override + public void putBytes(int tag, String vr, byte[] value) { + delegate.putBytes(tag, toVR(vr), value); + } + + @Override + public OieDicomElement putSequence(int tag) { + DicomElement element = delegate.putSequence(tag); + return new Dcm2DicomElement(element); + } + + @Override + public OieDicomElement putFragments(int tag, String vr, boolean bigEndian, int capacity) { + DicomElement element = delegate.putFragments(tag, toVR(vr), bigEndian, capacity); + return new Dcm2DicomElement(element); + } + + @Override + public void add(OieDicomElement element) { + if (element instanceof Dcm2DicomElement) { + delegate.add((DicomElement) element.unwrap()); + } else { + // Cross-library element: extract via interface methods. + // Sequences cannot be fully reconstructed across library boundaries without + // a converter round-trip; fragments and plain values transfer cleanly via bytes. + int tag = element.tag(); + String vrName = String.valueOf(element.vr()); + if (element.hasItems() && !"SQ".equals(vrName)) { + // Fragments — binary-compatible across libraries + VR vr = toVR(vrName); + DicomElement frags = delegate.putFragments(tag, vr, false, element.countItems()); + for (int i = 0; i < element.countItems(); i++) { + frags.addFragment(element.getFragment(i)); + } + } else if (!"SQ".equals(vrName)) { + // Plain value — copy raw bytes + byte[] bytes = element.getBytes(); + if (bytes != null) { + delegate.putBytes(tag, toVR(vrName), bytes); + } + } + // Sequences from another library are silently skipped — use the converter + // for full cross-library DICOM object conversion instead. + } + } + + @Override + public OieDicomElement remove(int tag) { + DicomElement element = delegate.remove(tag); + return element != null ? new Dcm2DicomElement(element) : null; + } + + @Override + public void clear() { + delegate.clear(); + } + + @Override + public boolean hasFileMetaInfo() { + if (delegate instanceof BasicDicomObject) { + return !((BasicDicomObject) delegate).fileMetaInfo().isEmpty(); + } + return false; + } + + @Override + public void initFileMetaInformation(String cuid, String iuid, String tsuid) { + if (delegate instanceof BasicDicomObject) { + ((BasicDicomObject) delegate).initFileMetaInformation(cuid, iuid, tsuid); + } + } + + @Override + public boolean bigEndian() { + return delegate.bigEndian(); + } + + @Override + public Iterator commandIterator() { + if (delegate instanceof BasicDicomObject) { + final Iterator dcmIt = ((BasicDicomObject) delegate).commandIterator(); + return new Iterator() { + @Override + public boolean hasNext() { + return dcmIt.hasNext(); + } + + @Override + public OieDicomElement next() { + if (!dcmIt.hasNext()) { + throw new NoSuchElementException(); + } + return new Dcm2DicomElement(dcmIt.next()); + } + + @Override + public void remove() { + dcmIt.remove(); + } + }; + } + return java.util.Collections.emptyIterator(); + } + + @Override + public Object unwrap() { + return delegate; + } +} diff --git a/server/src/com/mirth/connect/connectors/dimse/dicom/dcm2/Dcm2DicomReceiver.java b/server/src/com/mirth/connect/connectors/dimse/dicom/dcm2/Dcm2DicomReceiver.java new file mode 100644 index 0000000000..98788e7bb3 --- /dev/null +++ b/server/src/com/mirth/connect/connectors/dimse/dicom/dcm2/Dcm2DicomReceiver.java @@ -0,0 +1,205 @@ +/* + * Copyright (c) Mirth Corporation. All rights reserved. + * + * http://www.mirthcorp.com + * + * The software in this package is published under the terms of the MPL license a copy of which has + * been included with this distribution in the LICENSE.txt file. + */ + +package com.mirth.connect.connectors.dimse.dicom.dcm2; + +import org.dcm4che2.tool.dcmrcv.MirthDcmRcv; + +import com.mirth.connect.connectors.dimse.DICOMConfiguration; +import com.mirth.connect.connectors.dimse.dicom.OieDicomReceiver; +import com.mirth.connect.donkey.server.channel.SourceConnector; + +/** + * dcm4che2 implementation of OieDicomReceiver, wrapping MirthDcmRcv. + */ +public class Dcm2DicomReceiver implements OieDicomReceiver { + + private final MirthDcmRcv delegate; + + public Dcm2DicomReceiver(SourceConnector sourceConnector, DICOMConfiguration configuration) { + this.delegate = new MirthDcmRcv(sourceConnector, configuration); + } + + /** + * Wrapping constructor for an existing MirthDcmRcv instance. + */ + public Dcm2DicomReceiver(MirthDcmRcv delegate) { + this.delegate = delegate; + } + + @Override + public void setPort(int port) { + delegate.setPort(port); + } + + @Override + public void setHostname(String hostname) { + delegate.setHostname(hostname); + } + + @Override + public void setDestination(String destination) { + delegate.setDestination(destination); + } + + @Override + public void setTransferSyntax(String[] transferSyntax) { + delegate.setTransferSyntax(transferSyntax); + } + + @Override + public void setAEtitle(String aeTitle) { + delegate.setAEtitle(aeTitle); + } + + @Override + public void setAssociationReaperPeriod(int period) { + delegate.setAssociationReaperPeriod(period); + } + + @Override + public void setIdleTimeout(int timeout) { + delegate.setIdleTimeout(timeout); + } + + @Override + public void setRequestTimeout(int timeout) { + delegate.setRequestTimeout(timeout); + } + + @Override + public void setReleaseTimeout(int timeout) { + delegate.setReleaseTimeout(timeout); + } + + @Override + public void setSocketCloseDelay(int delay) { + delegate.setSocketCloseDelay(delay); + } + + @Override + public void setDimseRspDelay(int delay) { + delegate.setDimseRspDelay(delay); + } + + @Override + public void setMaxPDULengthReceive(int length) { + delegate.setMaxPDULengthReceive(length); + } + + @Override + public void setMaxPDULengthSend(int length) { + delegate.setMaxPDULengthSend(length); + } + + @Override + public void setSendBufferSize(int size) { + delegate.setSendBufferSize(size); + } + + @Override + public void setReceiveBufferSize(int size) { + delegate.setReceiveBufferSize(size); + } + + @Override + public void setFileBufferSize(int size) { + delegate.setFileBufferSize(size); + } + + @Override + public void setPackPDV(boolean packPDV) { + delegate.setPackPDV(packPDV); + } + + @Override + public void setTcpNoDelay(boolean tcpNoDelay) { + delegate.setTcpNoDelay(tcpNoDelay); + } + + @Override + public void setMaxOpsPerformed(int maxOps) { + delegate.setMaxOpsPerformed(maxOps); + } + + @Override + public void setTlsWithoutEncryption() { + delegate.setTlsWithoutEncyrption(); + } + + @Override + public void setTls3DES_EDE_CBC() { + delegate.setTls3DES_EDE_CBC(); + } + + @Override + public void setTlsAES_128_CBC() { + delegate.setTlsAES_128_CBC(); + } + + @Override + public void setTrustStoreURL(String url) { + delegate.setTrustStoreURL(url); + } + + @Override + public void setTrustStorePassword(String password) { + delegate.setTrustStorePassword(password); + } + + @Override + public void setKeyPassword(String password) { + delegate.setKeyPassword(password); + } + + @Override + public void setKeyStoreURL(String url) { + delegate.setKeyStoreURL(url); + } + + @Override + public void setKeyStorePassword(String password) { + delegate.setKeyStorePassword(password); + } + + @Override + public void setTlsNeedClientAuth(boolean needClientAuth) { + delegate.setTlsNeedClientAuth(needClientAuth); + } + + @Override + public void setTlsProtocol(String[] protocols) { + delegate.setTlsProtocol(protocols); + } + + @Override + public void initTLS() throws Exception { + delegate.initTLS(); + } + + @Override + public void initTransferCapability() { + delegate.initTransferCapability(); + } + + @Override + public void start() throws Exception { + delegate.start(); + } + + @Override + public void stop() { + delegate.stop(); + } + + @Override + public Object unwrap() { + return delegate; + } +} diff --git a/server/src/com/mirth/connect/connectors/dimse/dicom/dcm2/Dcm2DicomSender.java b/server/src/com/mirth/connect/connectors/dimse/dicom/dcm2/Dcm2DicomSender.java new file mode 100644 index 0000000000..f619029379 --- /dev/null +++ b/server/src/com/mirth/connect/connectors/dimse/dicom/dcm2/Dcm2DicomSender.java @@ -0,0 +1,294 @@ +/* + * Copyright (c) Mirth Corporation. All rights reserved. + * + * http://www.mirthcorp.com + * + * The software in this package is published under the terms of the MPL license a copy of which has + * been included with this distribution in the LICENSE.txt file. + */ + +package com.mirth.connect.connectors.dimse.dicom.dcm2; + +import java.io.File; +import java.io.IOException; + +import org.dcm4che2.data.DicomObject; +import org.dcm4che2.net.Association; +import org.dcm4che2.net.UserIdentity; +import org.dcm4che2.tool.dcmsnd.CustomDimseRSPHandler; +import org.dcm4che2.tool.dcmsnd.MirthDcmSnd; + +import com.mirth.connect.connectors.dimse.DICOMConfiguration; +import com.mirth.connect.connectors.dimse.dicom.OieDicomObject; +import com.mirth.connect.connectors.dimse.dicom.OieDicomSender; +import com.mirth.connect.connectors.dimse.dicom.OieDimseRspHandler; + +/** + * dcm4che2 implementation of OieDicomSender, wrapping MirthDcmSnd. + */ +public class Dcm2DicomSender implements OieDicomSender { + + private final MirthDcmSnd delegate; + + public Dcm2DicomSender(DICOMConfiguration configuration) { + this.delegate = new MirthDcmSnd(configuration); + } + + /** + * Wrapping constructor for an existing MirthDcmSnd instance. + */ + public Dcm2DicomSender(MirthDcmSnd delegate) { + this.delegate = delegate; + } + + @Override + public void setCalledAET(String aet) { + delegate.setCalledAET(aet); + } + + @Override + public void setRemoteHost(String host) { + delegate.setRemoteHost(host); + } + + @Override + public void setRemotePort(int port) { + delegate.setRemotePort(port); + } + + @Override + public void setCalling(String aet) { + delegate.setCalling(aet); + } + + @Override + public void setLocalHost(String host) { + delegate.setLocalHost(host); + } + + @Override + public void setLocalPort(int port) { + delegate.setLocalPort(port); + } + + @Override + public void addFile(File file) { + delegate.addFile(file); + } + + @Override + public void setAcceptTimeout(int timeout) { + delegate.setAcceptTimeout(timeout); + } + + @Override + public void setMaxOpsInvoked(int maxOps) { + delegate.setMaxOpsInvoked(maxOps); + } + + @Override + public void setTranscoderBufferSize(int size) { + delegate.setTranscoderBufferSize(size); + } + + @Override + public void setConnectTimeout(int timeout) { + delegate.setConnectTimeout(timeout); + } + + @Override + public void setPriority(int priority) { + delegate.setPriority(priority); + } + + @Override + public void setPackPDV(boolean packPDV) { + delegate.setPackPDV(packPDV); + } + + @Override + public void setMaxPDULengthReceive(int length) { + delegate.setMaxPDULengthReceive(length); + } + + @Override + public void setMaxPDULengthSend(int length) { + delegate.setMaxPDULengthSend(length); + } + + @Override + public void setReceiveBufferSize(int size) { + delegate.setReceiveBufferSize(size); + } + + @Override + public void setSendBufferSize(int size) { + delegate.setSendBufferSize(size); + } + + @Override + public void setAssociationReaperPeriod(int period) { + delegate.setAssociationReaperPeriod(period); + } + + @Override + public void setReleaseTimeout(int timeout) { + delegate.setReleaseTimeout(timeout); + } + + @Override + public void setDimseRspTimeout(int timeout) { + delegate.setDimseRspTimeout(timeout); + } + + @Override + public void setShutdownDelay(int delay) { + delegate.setShutdownDelay(delay); + } + + @Override + public void setSocketCloseDelay(int delay) { + delegate.setSocketCloseDelay(delay); + } + + @Override + public void setTcpNoDelay(boolean tcpNoDelay) { + delegate.setTcpNoDelay(tcpNoDelay); + } + + @Override + public void setOfferDefaultTransferSyntaxInSeparatePresentationContext(boolean ts1) { + delegate.setOfferDefaultTransferSyntaxInSeparatePresentationContext(ts1); + } + + @Override + public void setStorageCommitment(boolean stgcmt) { + delegate.setStorageCommitment(stgcmt); + } + + @Override + public void setUserIdentity(String username, String passcode, boolean positiveResponseRequested) { + UserIdentity userId; + if (passcode != null && !passcode.isEmpty()) { + userId = new UserIdentity.UsernamePasscode(username, passcode.toCharArray()); + } else { + userId = new UserIdentity.Username(username); + } + userId.setPositiveResponseRequested(positiveResponseRequested); + delegate.setUserIdentity(userId); + } + + @Override + public void setTlsWithoutEncryption() { + delegate.setTlsWithoutEncyrption(); + } + + @Override + public void setTls3DES_EDE_CBC() { + delegate.setTls3DES_EDE_CBC(); + } + + @Override + public void setTlsAES_128_CBC() { + delegate.setTlsAES_128_CBC(); + } + + @Override + public void setTrustStoreURL(String url) { + delegate.setTrustStoreURL(url); + } + + @Override + public void setTrustStorePassword(String password) { + delegate.setTrustStorePassword(password); + } + + @Override + public void setKeyPassword(String password) { + delegate.setKeyPassword(password); + } + + @Override + public void setKeyStoreURL(String url) { + delegate.setKeyStoreURL(url); + } + + @Override + public void setKeyStorePassword(String password) { + delegate.setKeyStorePassword(password); + } + + @Override + public void setTlsNeedClientAuth(boolean needClientAuth) { + delegate.setTlsNeedClientAuth(needClientAuth); + } + + @Override + public void setTlsProtocol(String[] protocols) { + delegate.setTlsProtocol(protocols); + } + + @Override + public void initTLS() throws Exception { + delegate.initTLS(); + } + + @Override + public void configureTransferCapability() { + delegate.configureTransferCapability(); + } + + @Override + public void start() throws IOException { + delegate.start(); + } + + @Override + public void open() throws Exception { + delegate.open(); + } + + @Override + public void send(OieDimseRspHandler handler) throws Exception { + // Bridge from OieDimseRspHandler to dcm4che2's CustomDimseRSPHandler + delegate.send(new CustomDimseRSPHandler() { + @Override + public void onDimseRSP(Association as, DicomObject cmd, DicomObject data) { + OieDicomObject wrappedCmd = cmd != null ? new Dcm2DicomObject(cmd) : null; + OieDicomObject wrappedData = data != null ? new Dcm2DicomObject(data) : null; + handler.onDimseRSP(wrappedCmd, wrappedData); + } + }); + } + + @Override + public boolean isStorageCommitment() { + return delegate.isStorageCommitment(); + } + + @Override + public boolean commit() throws Exception { + return delegate.commit(); + } + + @Override + public OieDicomObject waitForStgCmtResult() throws InterruptedException { + DicomObject result = delegate.waitForStgCmtResult(); + return result != null ? new Dcm2DicomObject(result) : null; + } + + @Override + public void close() { + delegate.close(); + } + + @Override + public void stop() { + delegate.stop(); + } + + @Override + public Object unwrap() { + return delegate; + } +} diff --git a/server/src/com/mirth/connect/connectors/dimse/dicom/dcm2/Dcm2VR.java b/server/src/com/mirth/connect/connectors/dimse/dicom/dcm2/Dcm2VR.java new file mode 100644 index 0000000000..3f500e5d41 --- /dev/null +++ b/server/src/com/mirth/connect/connectors/dimse/dicom/dcm2/Dcm2VR.java @@ -0,0 +1,43 @@ +/* + * Copyright (c) Mirth Corporation. All rights reserved. + * + * http://www.mirthcorp.com + * + * The software in this package is published under the terms of the MPL license a copy of which has + * been included with this distribution in the LICENSE.txt file. + */ + +package com.mirth.connect.connectors.dimse.dicom.dcm2; + +import org.dcm4che2.data.VR; + +import com.mirth.connect.connectors.dimse.dicom.OieVR; + +public class Dcm2VR implements OieVR { + + private final VR vr; + + public Dcm2VR(VR vr) { + this.vr = vr; + } + + @Override + public String toString() { + return vr.toString(); + } + + @Override + public int code() { + return vr.code(); + } + + @Override + public int padding() { + return vr.padding(); + } + + @Override + public Object unwrap() { + return vr; + } +} diff --git a/server/src/com/mirth/connect/connectors/dimse/dicom/dcm5/Dcm5DICOMConfiguration.java b/server/src/com/mirth/connect/connectors/dimse/dicom/dcm5/Dcm5DICOMConfiguration.java new file mode 100644 index 0000000000..1dbfec9ba7 --- /dev/null +++ b/server/src/com/mirth/connect/connectors/dimse/dicom/dcm5/Dcm5DICOMConfiguration.java @@ -0,0 +1,69 @@ +/* + * Copyright (c) Mirth Corporation. All rights reserved. + * + * http://www.mirthcorp.com + * + * The software in this package is published under the terms of the MPL license a copy of which has + * been included with this distribution in the LICENSE.txt file. + */ + +package com.mirth.connect.connectors.dimse.dicom.dcm5; + +import java.util.Map; + +import org.dcm4che3.net.Association; +import org.dcm4che3.net.Connection; + +import com.mirth.connect.connectors.dimse.DICOMConfiguration; +import com.mirth.connect.connectors.dimse.DICOMDispatcher; +import com.mirth.connect.connectors.dimse.DICOMDispatcherProperties; +import com.mirth.connect.connectors.dimse.DICOMReceiver; +import com.mirth.connect.connectors.dimse.DICOMReceiverProperties; +import com.mirth.connect.connectors.dimse.dicom.OieDicomReceiver; +import com.mirth.connect.connectors.dimse.dicom.OieDicomSender; + +/** + * dcm4che5-specific extension of {@link DICOMConfiguration}. Provides dcm4che5-typed + * method signatures and bridge defaults that delegate the version-neutral methods. + * + *

Custom implementations that need dcm4che5 API access should implement this interface. + */ +public interface Dcm5DICOMConfiguration extends DICOMConfiguration { + + // dcm4che5-typed methods + + void configureDcm5Receiver(Dcm5DicomReceiver receiver, DICOMReceiver connector, + DICOMReceiverProperties connectorProperties) throws Exception; + + void configureDcm5Sender(Dcm5DicomSender sender, DICOMDispatcher connector, + DICOMDispatcherProperties connectorProperties) throws Exception; + + Map getCStoreRequestInformation(Association association); + + Connection createDcm5Connection(); + + // Bridge defaults: version-neutral methods delegate to dcm5-typed methods + + @Override + default void configureReceiver(OieDicomReceiver receiver, DICOMReceiver connector, + DICOMReceiverProperties connectorProperties) throws Exception { + // Cast receiver directly — Dcm5DicomReceiver IS the composition (no unwrap) + configureDcm5Receiver((Dcm5DicomReceiver) receiver, connector, connectorProperties); + } + + @Override + default void configureSender(OieDicomSender sender, DICOMDispatcher connector, + DICOMDispatcherProperties connectorProperties) throws Exception { + configureDcm5Sender((Dcm5DicomSender) sender, connector, connectorProperties); + } + + @Override + default Map getCStoreRequestInformation(Object association) { + return getCStoreRequestInformation((Association) association); + } + + @Override + default Object createNetworkConnection() { + return createDcm5Connection(); + } +} diff --git a/server/src/com/mirth/connect/connectors/dimse/dicom/dcm5/Dcm5DicomConverter.java b/server/src/com/mirth/connect/connectors/dimse/dicom/dcm5/Dcm5DicomConverter.java new file mode 100644 index 0000000000..fde390a345 --- /dev/null +++ b/server/src/com/mirth/connect/connectors/dimse/dicom/dcm5/Dcm5DicomConverter.java @@ -0,0 +1,169 @@ +/* + * Copyright (c) Mirth Corporation. All rights reserved. + * + * http://www.mirthcorp.com + * + * The software in this package is published under the terms of the MPL license a copy of which has + * been included with this distribution in the LICENSE.txt file. + */ + +package com.mirth.connect.connectors.dimse.dicom.dcm5; + +import java.io.BufferedInputStream; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.StringWriter; + +import javax.xml.XMLConstants; +import javax.xml.parsers.SAXParser; +import javax.xml.parsers.SAXParserFactory; +import javax.xml.transform.OutputKeys; +import javax.xml.transform.TransformerFactory; +import javax.xml.transform.sax.SAXTransformerFactory; +import javax.xml.transform.sax.TransformerHandler; +import javax.xml.transform.stream.StreamResult; + +import org.apache.commons.codec.binary.Base64InputStream; +import org.apache.commons.io.IOUtils; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.dcm4che3.data.Attributes; +import org.dcm4che3.data.ElementDictionary; +import org.dcm4che3.data.UID; +import org.dcm4che3.io.ContentHandlerAdapter; +import org.dcm4che3.io.DicomInputStream; +import org.dcm4che3.io.DicomOutputStream; +import org.dcm4che3.io.SAXWriter; +import org.xml.sax.InputSource; + +import com.mirth.connect.connectors.dimse.dicom.OieDicomConverter; +import com.mirth.connect.connectors.dimse.dicom.OieDicomObject; + +/** + * dcm4che5 implementation of OieDicomConverter. Handles all byte-array, XML, and + * DICOM object conversion using the dcm4che 5.34.3 library. + * + *

Key differences from dcm2: + *

    + *
  • No {@code setAllocateLimit(-1)} needed
  • + *
  • Single-pass write (no ByteCounterOutputStream)
  • + *
  • FMI is a separate Attributes object
  • + *
  • SAXWriter.write(dataset) instead of stream handler
  • + *
+ */ +public class Dcm5DicomConverter implements OieDicomConverter { + + private static final Logger logger = LogManager.getLogger(Dcm5DicomConverter.class); + + @Override + public OieDicomObject byteArrayToDicomObject(byte[] bytes, boolean decodeBase64) throws IOException { + DicomInputStream dis = null; + + try { + ByteArrayInputStream bais = new ByteArrayInputStream(bytes); + InputStream inputStream; + if (decodeBase64) { + inputStream = new BufferedInputStream(new Base64InputStream(bais)); + } else { + inputStream = bais; + } + dis = new DicomInputStream(inputStream); + Attributes fmi = dis.readFileMetaInformation(); + Attributes dataset = dis.readDataset(-1, -1); + return new Dcm5DicomObject(fmi, dataset); + } catch (IOException e) { + throw e; + } finally { + IOUtils.closeQuietly(dis); + } + } + + @Override + public byte[] dicomObjectToByteArray(OieDicomObject dicomObject) throws IOException { + Dcm5DicomObject dcm5obj = (Dcm5DicomObject) dicomObject; + Attributes dataset = (Attributes) dcm5obj.unwrap(); + Attributes fmi = dcm5obj.getFmi(); + + DicomOutputStream dos = null; + + try { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + + if (fmi != null && !fmi.isEmpty()) { + dos = new DicomOutputStream(baos, UID.ExplicitVRLittleEndian); + dos.writeDataset(fmi, dataset); + } else { + dos = new DicomOutputStream(baos, UID.ImplicitVRLittleEndian); + dos.writeDataset(null, dataset); + } + + // Memory optimization since the dicom object is no longer needed at this point. + dicomObject.clear(); + + return baos.toByteArray(); + } catch (IOException e) { + throw e; + } catch (Throwable t) { + logger.error("Error serializing DICOM object to byte array", t); + return null; + } finally { + IOUtils.closeQuietly(dos); + } + } + + @Override + public OieDicomObject createDicomObject() { + return new Dcm5DicomObject(); + } + + @Override + public String dicomBytesToXml(byte[] encodedDicomBytes) throws Exception { + DicomInputStream dis = new DicomInputStream(new BufferedInputStream(new Base64InputStream(new ByteArrayInputStream(encodedDicomBytes)))); + + try { + Attributes fmi = dis.readFileMetaInformation(); + Attributes dataset = dis.readDataset(-1, -1); + + StringWriter output = new StringWriter(); + TransformerFactory tf = TransformerFactory.newInstance(); + tf.setAttribute(XMLConstants.ACCESS_EXTERNAL_DTD, ""); + tf.setAttribute(XMLConstants.ACCESS_EXTERNAL_STYLESHEET, ""); + SAXTransformerFactory factory = (SAXTransformerFactory) tf; + TransformerHandler handler = factory.newTransformerHandler(); + handler.getTransformer().setOutputProperty(OutputKeys.INDENT, "no"); + handler.setResult(new StreamResult(output)); + + SAXWriter writer = new SAXWriter(handler); + writer.setIncludeKeyword(true); + writer.write(dataset); + + return output.toString(); + } finally { + IOUtils.closeQuietly(dis); + } + } + + @Override + public OieDicomObject xmlToDicomObject(String xml, String charset) throws Exception { + SAXParserFactory factory = SAXParserFactory.newInstance(); + factory.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true); + SAXParser parser = factory.newSAXParser(); + Attributes dataset = new Attributes(); + ContentHandlerAdapter contentHandler = new ContentHandlerAdapter(dataset); + byte[] documentBytes = xml.trim().getBytes(charset); + parser.parse(new InputSource(new ByteArrayInputStream(documentBytes)), contentHandler); + return new Dcm5DicomObject(dataset); + } + + @Override + public String getElementName(int tag) { + try { + String keyword = ElementDictionary.keywordOf(tag, null); + return keyword != null ? keyword : ""; + } catch (Exception e) { + return ""; + } + } +} diff --git a/server/src/com/mirth/connect/connectors/dimse/dicom/dcm5/Dcm5DicomElement.java b/server/src/com/mirth/connect/connectors/dimse/dicom/dcm5/Dcm5DicomElement.java new file mode 100644 index 0000000000..2c8d2be79f --- /dev/null +++ b/server/src/com/mirth/connect/connectors/dimse/dicom/dcm5/Dcm5DicomElement.java @@ -0,0 +1,310 @@ +/* + * Copyright (c) Mirth Corporation. All rights reserved. + * + * http://www.mirthcorp.com + * + * The software in this package is published under the terms of the MPL license a copy of which has + * been included with this distribution in the LICENSE.txt file. + */ + +package com.mirth.connect.connectors.dimse.dicom.dcm5; + +import org.dcm4che3.data.Attributes; +import org.dcm4che3.data.Fragments; +import org.dcm4che3.data.Sequence; +import org.dcm4che3.data.VR; + +import com.mirth.connect.connectors.dimse.dicom.OieDicomElement; +import com.mirth.connect.connectors.dimse.dicom.OieDicomObject; +import com.mirth.connect.connectors.dimse.dicom.OieVR; + +/** + * Synthetic dcm4che5 implementation of OieDicomElement. dcm4che5 has no standalone + * DicomElement class — all element access is done through the parent Attributes object. + * + *

Three modes: + *

    + *
  • VALUE — references parent Attributes + tag for plain value access
  • + *
  • SEQUENCE — wraps a {@link Sequence} (list of Attributes)
  • + *
  • FRAGMENTS — wraps a {@link Fragments} collection
  • + *
+ */ +public class Dcm5DicomElement implements OieDicomElement { + + private enum Mode { VALUE, SEQUENCE, FRAGMENTS } + + private final int tag; + private final Attributes parent; + private final Mode mode; + private final Sequence sequence; + private final Fragments fragments; + private final String vrName; + + /** VALUE mode constructor. */ + Dcm5DicomElement(int tag, Attributes parent) { + this.tag = tag; + this.parent = parent; + this.mode = Mode.VALUE; + this.sequence = null; + this.fragments = null; + VR vr = parent.getVR(tag); + this.vrName = vr != null ? vr.name() : "UN"; + } + + /** SEQUENCE mode constructor. */ + Dcm5DicomElement(int tag, Attributes parent, Sequence sequence) { + this.tag = tag; + this.parent = parent; + this.mode = Mode.SEQUENCE; + this.sequence = sequence; + this.fragments = null; + this.vrName = "SQ"; + } + + /** FRAGMENTS mode constructor. */ + Dcm5DicomElement(int tag, Attributes parent, Fragments fragments, String vrName) { + this.tag = tag; + this.parent = parent; + this.mode = Mode.FRAGMENTS; + this.sequence = null; + this.fragments = fragments; + this.vrName = vrName; + } + + /** Copies this element's data into the target Attributes. Package-visible for Dcm5DicomObject.add(). */ + void copyTo(Attributes target) { + switch (mode) { + case SEQUENCE: + Sequence targetSeq = target.newSequence(tag, sequence.size()); + for (Attributes item : sequence) { + targetSeq.add(new Attributes(item)); + } + break; + case FRAGMENTS: + Fragments targetFrags = target.newFragments(tag, VR.valueOf(vrName), fragments.size()); + for (Object frag : fragments) { + targetFrags.add(frag); + } + break; + default: + try { + byte[] bytes = parent.getBytes(tag); + if (bytes != null) { + target.setBytes(tag, VR.valueOf(vrName), bytes); + } else { + String val = parent.getString(tag); + if (val != null) { + target.setString(tag, VR.valueOf(vrName), val); + } + } + } catch (java.io.IOException e) { + throw new RuntimeException("Failed to copy element " + Integer.toHexString(tag), e); + } + break; + } + } + + @Override + public int tag() { + return tag; + } + + @Override + public int length() { + switch (mode) { + case VALUE: + try { + byte[] bytes = parent.getBytes(tag); + return bytes != null ? bytes.length : -1; + } catch (Exception e) { + return -1; + } + default: + return -1; + } + } + + @Override + public OieVR vr() { + return new Dcm5VR(VR.valueOf(vrName)); + } + + @Override + public String getValueAsString(int index) { + if (mode != Mode.VALUE) { + return null; + } + try { + String[] values = parent.getStrings(tag); + if (values != null && index >= 0 && index < values.length) { + return values[index]; + } + } catch (Exception e) { + // Fall through + } + return null; + } + + @Override + public boolean hasItems() { + switch (mode) { + case SEQUENCE: + return !sequence.isEmpty(); + case FRAGMENTS: + return !fragments.isEmpty(); + default: + return false; + } + } + + @Override + public int countItems() { + switch (mode) { + case SEQUENCE: + return sequence.size(); + case FRAGMENTS: + return fragments.size(); + default: + return 0; + } + } + + @Override + public boolean isEmpty() { + switch (mode) { + case SEQUENCE: + return sequence.isEmpty(); + case FRAGMENTS: + return fragments.isEmpty(); + default: + Object v = parent.getValue(tag); + if (v == null) { + return true; + } + if (v instanceof byte[]) { + return ((byte[]) v).length == 0; + } + return false; + } + } + + @Override + public boolean hasDicomObjects() { + return mode == Mode.SEQUENCE; + } + + @Override + public boolean hasFragments() { + return mode == Mode.FRAGMENTS; + } + + @Override + public byte[] getFragment(int index) { + if (mode != Mode.FRAGMENTS) { + throw new UnsupportedOperationException("getFragment not supported in " + mode + " mode"); + } + Object frag = fragments.get(index); + return frag instanceof byte[] ? (byte[]) frag : null; + } + + @Override + public byte[] getBytes() { + if (mode != Mode.VALUE) { + return null; + } + try { + return parent.getBytes(tag); + } catch (java.io.IOException e) { + return null; + } + } + + @Override + public String[] getStrings() { + return mode == Mode.VALUE ? parent.getStrings(tag) : null; + } + + @Override + public int getInt(int defaultValue) { + return mode == Mode.VALUE ? parent.getInt(tag, defaultValue) : defaultValue; + } + + @Override + public int[] getInts() { + return mode == Mode.VALUE ? parent.getInts(tag) : null; + } + + @Override + public float getFloat(float defaultValue) { + return mode == Mode.VALUE ? parent.getFloat(tag, defaultValue) : defaultValue; + } + + @Override + public float[] getFloats() { + return mode == Mode.VALUE ? parent.getFloats(tag) : null; + } + + @Override + public double getDouble(double defaultValue) { + return mode == Mode.VALUE ? parent.getDouble(tag, defaultValue) : defaultValue; + } + + @Override + public double[] getDoubles() { + return mode == Mode.VALUE ? parent.getDoubles(tag) : null; + } + + @Override + public java.util.Date getDate() { + return mode == Mode.VALUE ? parent.getDate(tag) : null; + } + + @Override + public java.util.Date[] getDates() { + return mode == Mode.VALUE ? parent.getDates(tag) : null; + } + + @Override + public void addFragment(byte[] data) { + if (mode != Mode.FRAGMENTS) { + throw new UnsupportedOperationException("addFragment not supported in " + mode + " mode"); + } + fragments.add(data); + } + + @Override + public OieDicomObject getDicomObject() { + if (mode != Mode.SEQUENCE || sequence.isEmpty()) { + return null; + } + return new Dcm5DicomObject(sequence.get(0)); + } + + @Override + public OieDicomObject getDicomObject(int index) { + if (mode != Mode.SEQUENCE || index < 0 || index >= sequence.size()) { + return null; + } + return new Dcm5DicomObject(sequence.get(index)); + } + + @Override + public void addDicomObject(OieDicomObject obj) { + if (mode != Mode.SEQUENCE) { + throw new UnsupportedOperationException("addDicomObject not supported in " + mode + " mode"); + } + sequence.add((Attributes) obj.unwrap()); + } + + @Override + public Object unwrap() { + switch (mode) { + case SEQUENCE: + return sequence; + case FRAGMENTS: + return fragments; + default: + return parent; + } + } +} diff --git a/server/src/com/mirth/connect/connectors/dimse/dicom/dcm5/Dcm5DicomObject.java b/server/src/com/mirth/connect/connectors/dimse/dicom/dcm5/Dcm5DicomObject.java new file mode 100644 index 0000000000..f6c1a262db --- /dev/null +++ b/server/src/com/mirth/connect/connectors/dimse/dicom/dcm5/Dcm5DicomObject.java @@ -0,0 +1,285 @@ +/* + * Copyright (c) Mirth Corporation. All rights reserved. + * + * http://www.mirthcorp.com + * + * The software in this package is published under the terms of the MPL license a copy of which has + * been included with this distribution in the LICENSE.txt file. + */ + +package com.mirth.connect.connectors.dimse.dicom.dcm5; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.Iterator; +import java.util.List; + +import org.dcm4che3.data.Attributes; +import org.dcm4che3.data.ElementDictionary; +import org.dcm4che3.data.Fragments; +import org.dcm4che3.data.Sequence; +import org.dcm4che3.data.VR; + +import com.mirth.connect.connectors.dimse.dicom.OieDicomElement; +import com.mirth.connect.connectors.dimse.dicom.OieDicomObject; +import com.mirth.connect.connectors.dimse.dicom.OieVR; + +/** + * dcm4che5 implementation of OieDicomObject, wrapping Attributes. + * + *

Key difference from dcm2: File Meta Information is stored as a separate + * Attributes object (not embedded in the dataset). + */ +public class Dcm5DicomObject implements OieDicomObject { + + private final Attributes dataset; + private Attributes fmi; + + public Dcm5DicomObject() { + this(new Attributes()); + } + + public Dcm5DicomObject(Attributes dataset) { + this(null, dataset); + } + + public Dcm5DicomObject(Attributes fmi, Attributes dataset) { + this.fmi = fmi; + this.dataset = dataset != null ? dataset : new Attributes(); + } + + /** Package-visible accessor for Dcm5DicomConverter. */ + Attributes getFmi() { + return fmi; + } + + @Override + public String getString(int tag) { + return dataset.getString(tag); + } + + @Override + public int getInt(int tag) { + return dataset.getInt(tag, 0); + } + + @Override + public OieDicomElement get(int tag) { + if (!dataset.contains(tag)) { + return null; + } + VR vr = dataset.getVR(tag); + if (vr == VR.SQ) { + Sequence seq = dataset.getSequence(tag); + return seq != null ? new Dcm5DicomElement(tag, dataset, seq) : null; + } + Object value = dataset.getValue(tag); + if (value instanceof Fragments) { + return new Dcm5DicomElement(tag, dataset, (Fragments) value, vr.name()); + } + return new Dcm5DicomElement(tag, dataset); + } + + @Override + public boolean contains(int tag) { + return dataset.contains(tag); + } + + @Override + public int size() { + return dataset.size(); + } + + @Override + public boolean isEmpty() { + return dataset.isEmpty(); + } + + @Override + public byte[] getBytes(int tag) { + try { + return dataset.getBytes(tag); + } catch (java.io.IOException e) { + throw new RuntimeException("Unable to read bytes for tag " + Integer.toHexString(tag), e); + } + } + + @Override + public int[] getInts(int tag) { + return dataset.getInts(tag); + } + + @Override + public String[] getStrings(int tag) { + return dataset.getStrings(tag); + } + + @Override + public float getFloat(int tag, float defaultValue) { + return dataset.getFloat(tag, defaultValue); + } + + @Override + public float[] getFloats(int tag) { + return dataset.getFloats(tag); + } + + @Override + public double getDouble(int tag, double defaultValue) { + return dataset.getDouble(tag, defaultValue); + } + + @Override + public double[] getDoubles(int tag) { + return dataset.getDoubles(tag); + } + + @Override + public java.util.Date getDate(int tag) { + return dataset.getDate(tag); + } + + @Override + public java.util.Date[] getDates(int tag) { + return dataset.getDates(tag); + } + + @Override + public OieDicomObject getNestedDicomObject(int tag) { + Attributes nested = dataset.getNestedDataset(tag); + return nested != null ? new Dcm5DicomObject(nested) : null; + } + + @Override + public int vm(int tag) { + if (!dataset.contains(tag)) { + return 0; + } + String[] strings = dataset.getStrings(tag); + return strings != null ? strings.length : 1; + } + + @Override + public String vrOf(int tag) { + VR vr = ElementDictionary.vrOf(tag, dataset.getPrivateCreator(tag)); + return vr != null ? vr.name() : null; + } + + @Override + public String nameOf(int tag) { + return ElementDictionary.keywordOf(tag, dataset.getPrivateCreator(tag)); + } + + @Override + public void putString(int tag, String vr, String value) { + dataset.setString(tag, VR.valueOf(vr), value); + } + + @Override + public void putInt(int tag, String vr, int value) { + dataset.setInt(tag, VR.valueOf(vr), value); + } + + @Override + public void putBytes(int tag, String vr, byte[] value) { + dataset.setBytes(tag, VR.valueOf(vr), value); + } + + @Override + public OieDicomElement putSequence(int tag) { + Sequence seq = dataset.newSequence(tag, 0); + return new Dcm5DicomElement(tag, dataset, seq); + } + + @Override + public OieDicomElement putFragments(int tag, String vr, boolean bigEndian, int capacity) { + Fragments frags = dataset.newFragments(tag, VR.valueOf(vr), capacity); + return new Dcm5DicomElement(tag, dataset, frags, vr); + } + + @Override + public void add(OieDicomElement element) { + if (element instanceof Dcm5DicomElement) { + ((Dcm5DicomElement) element).copyTo(dataset); + } else { + // Cross-library element: extract via interface methods + int tag = element.tag(); + String vrName = String.valueOf(element.vr()); + if ("SQ".equals(vrName)) { + Sequence seq = dataset.newSequence(tag, element.countItems()); + for (int i = 0; i < element.countItems(); i++) { + OieDicomObject item = element.getDicomObject(i); + if (item != null) { + seq.add(new Attributes((Attributes) item.unwrap())); + } + } + } else if (element.hasItems()) { + Fragments frags = dataset.newFragments(tag, VR.valueOf(vrName), element.countItems()); + for (int i = 0; i < element.countItems(); i++) { + frags.add(element.getFragment(i)); + } + } else { + byte[] bytes = element.getBytes(); + if (bytes != null) { + dataset.setBytes(tag, VR.valueOf(vrName), bytes); + } + } + } + } + + @Override + public OieDicomElement remove(int tag) { + if (!dataset.contains(tag)) { + return null; + } + OieDicomElement removed = get(tag); + dataset.remove(tag); + return removed; + } + + @Override + public void clear() { + dataset.clear(); + } + + @Override + public boolean hasFileMetaInfo() { + return fmi != null && !fmi.isEmpty(); + } + + @Override + public void initFileMetaInformation(String cuid, String iuid, String tsuid) { + // dcm4che5 param order: (iuid, cuid, tsuid) — swapped from our interface + this.fmi = Attributes.createFileMetaInformation(iuid, cuid, tsuid); + } + + @Override + public boolean bigEndian() { + return dataset.bigEndian(); + } + + @Override + public Iterator commandIterator() { + final List commandElements = new ArrayList<>(); + try { + dataset.accept(new Attributes.Visitor() { + @Override + public boolean visit(Attributes attrs, int tag, VR vr, Object value) { + // Command group elements have tag group 0x0000 + if ((tag >>> 16) == 0x0000) { + commandElements.add(new Dcm5DicomElement(tag, attrs)); + } + return true; + } + }, false); + } catch (Exception e) { + // Visitor should not throw in practice + } + return Collections.unmodifiableList(commandElements).iterator(); + } + + @Override + public Object unwrap() { + return dataset; + } +} diff --git a/server/src/com/mirth/connect/connectors/dimse/dicom/dcm5/Dcm5DicomReceiver.java b/server/src/com/mirth/connect/connectors/dimse/dicom/dcm5/Dcm5DicomReceiver.java new file mode 100644 index 0000000000..93660769fd --- /dev/null +++ b/server/src/com/mirth/connect/connectors/dimse/dicom/dcm5/Dcm5DicomReceiver.java @@ -0,0 +1,506 @@ +/* + * Copyright (c) Mirth Corporation. All rights reserved. + * + * http://www.mirthcorp.com + * + * The software in this package is published under the terms of the MPL license a copy of which has + * been included with this distribution in the LICENSE.txt file. + */ + +package com.mirth.connect.connectors.dimse.dicom.dcm5; + +import java.io.BufferedOutputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.net.InetSocketAddress; +import java.util.HashMap; +import java.util.LinkedHashMap; +import java.util.Map; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.TimeUnit; + +import org.apache.commons.collections4.MapUtils; +import org.apache.commons.io.IOUtils; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.dcm4che3.data.Attributes; +import org.dcm4che3.data.Tag; +import org.dcm4che3.data.UID; +import org.dcm4che3.data.VR; +import org.dcm4che3.io.DicomOutputStream; +import org.dcm4che3.net.ApplicationEntity; +import org.dcm4che3.net.Association; +import org.dcm4che3.net.Connection; +import org.dcm4che3.net.Device; +import org.dcm4che3.net.PDVInputStream; +import org.dcm4che3.net.Status; +import org.dcm4che3.net.TransferCapability; +import org.dcm4che3.net.pdu.PresentationContext; +import org.dcm4che3.net.pdu.UserIdentityRQ; +import org.dcm4che3.net.service.BasicCEchoSCP; +import org.dcm4che3.net.service.BasicCStoreSCP; +import org.dcm4che3.net.service.DicomServiceException; +import org.dcm4che3.net.service.DicomServiceRegistry; + +import com.mirth.connect.connectors.dimse.DICOMConfiguration; +import com.mirth.connect.connectors.dimse.dicom.DicomConstants; +import com.mirth.connect.connectors.dimse.dicom.OieDicomReceiver; +import com.mirth.connect.donkey.model.message.RawMessage; +import com.mirth.connect.donkey.server.channel.DispatchResult; +import com.mirth.connect.donkey.server.channel.SourceConnector; + +/** + * dcm4che5 implementation of OieDicomReceiver. Composes from Device + Connection + + * ApplicationEntity + BasicCStoreSCP instead of delegating to a monolithic DcmRcv tool class. + * + *

The {@code onCStoreRQ} handler populates the sourceMap with the exact same keys + * as MirthDcmRcv.onCStoreRQ to ensure behavioral parity. + */ +public class Dcm5DicomReceiver implements OieDicomReceiver { + + private static final Logger logger = LogManager.getLogger(Dcm5DicomReceiver.class); + + private final Device device; + private final Connection conn; + private final ApplicationEntity ae; + private final SourceConnector sourceConnector; + private final DICOMConfiguration dicomConfiguration; + + /** + * Default transfer syntaxes matching dcm4che2's NON_RETIRED_LE_TS. + * Registered for all SOP classes when no explicit restriction is configured. + */ + private static final String[] NON_RETIRED_LE_TS = { + DicomConstants.JPEG_LS_LOSSLESS, + DicomConstants.JPEG_LOSSLESS_SV1, + DicomConstants.JPEG_LOSSLESS_NH14, + DicomConstants.JPEG_2000_LOSSLESS, + DicomConstants.DEFLATED_EXPLICIT_VR_LITTLE_ENDIAN, + DicomConstants.RLE_LOSSLESS, + DicomConstants.EXPLICIT_VR_LITTLE_ENDIAN, + DicomConstants.IMPLICIT_VR_LITTLE_ENDIAN, + DicomConstants.JPEG_BASELINE, + DicomConstants.JPEG_EXTENDED, + DicomConstants.JPEG_LS_NEAR_LOSSLESS, + DicomConstants.JPEG_2000, + DicomConstants.MPEG2, + }; + + private String[] transferSyntax = NON_RETIRED_LE_TS; + private ExecutorService executor; + private ScheduledExecutorService scheduledExecutor; + + // TLS config stored for deferred initTLS() + private String keyStoreURL; + private String keyStorePassword; + private String keyPassword; + private String keyStoreType; + private String trustStoreURL; + private String trustStorePassword; + private String trustStoreType; + + public Dcm5DicomReceiver(SourceConnector sourceConnector, DICOMConfiguration configuration) { + this.sourceConnector = sourceConnector; + this.dicomConfiguration = configuration; + this.device = new Device("DCMRCV"); + + if (configuration instanceof Dcm5DICOMConfiguration) { + this.conn = ((Dcm5DICOMConfiguration) configuration).createDcm5Connection(); + } else { + Object custom = configuration.createNetworkConnection(); + this.conn = (custom instanceof Connection) ? (Connection) custom : new Connection(); + } + + device.addConnection(conn); + this.ae = new ApplicationEntity("*"); + ae.setAssociationAcceptor(true); + ae.addConnection(conn); + device.addApplicationEntity(ae); + + // Register DICOM service handlers + DicomServiceRegistry serviceRegistry = new DicomServiceRegistry(); + serviceRegistry.addDicomService(new BasicCStoreSCP("*") { + @Override + protected void store(Association as, PresentationContext pc, Attributes rq, + PDVInputStream data, Attributes rsp) throws IOException { + onCStoreRQ(as, pc, rq, data, rsp); + } + }); + serviceRegistry.addDicomService(new BasicCEchoSCP()); + device.setDimseRQHandler(serviceRegistry); + } + + /** + * Handles incoming C-STORE requests. Populates sourceMap with the same keys as + * MirthDcmRcv.onCStoreRQ for behavioral parity. + */ + private void onCStoreRQ(Association as, PresentationContext pc, Attributes rq, + PDVInputStream data, Attributes rsp) throws IOException { + String cuid = rq.getString(Tag.AffectedSOPClassUID); + String iuid = rq.getString(Tag.AffectedSOPInstanceUID); + String tsuid = pc.getTransferSyntax(); + + Attributes fmi = Attributes.createFileMetaInformation(iuid, cuid, tsuid); + + String originalThreadName = Thread.currentThread().getName(); + ByteArrayOutputStream baos = null; + DicomOutputStream dos = null; + + try { + Thread.currentThread().setName("DICOM Receiver Thread on " + sourceConnector.getChannel().getName() + + " (" + sourceConnector.getChannelId() + ") < " + originalThreadName); + + Map sourceMap = buildSourceMap(as); + sourceMap.putAll(dicomConfiguration.getCStoreRequestInformation(as)); + + // Write DICOM file bytes (FMI + data stream) + baos = new ByteArrayOutputStream(); + BufferedOutputStream bos = new BufferedOutputStream(baos); + dos = new DicomOutputStream(bos, UID.ExplicitVRLittleEndian); + dos.writeFileMetaInformation(fmi); + data.copyTo(dos); + dos.close(); + + byte[] dicomMessage = baos.toByteArray(); + baos = null; + + DispatchResult dispatchResult = null; + try { + dispatchResult = sourceConnector.dispatchRawMessage(new RawMessage(dicomMessage, null, sourceMap)); + + if (dispatchResult != null && dispatchResult.getSelectedResponse() != null + && dispatchResult.getSelectedResponse().getStatus() == com.mirth.connect.donkey.model.message.Status.ERROR) { + throw new DicomServiceException(Status.ProcessingFailure, + dispatchResult.getSelectedResponse().getStatusMessage()); + } + } finally { + sourceConnector.finishDispatch(dispatchResult); + } + } catch (Throwable t) { + logger.error("Error receiving DICOM message on channel " + sourceConnector.getChannelId(), t); + if (t instanceof DicomServiceException) { + throw (DicomServiceException) t; + } else { + throw new DicomServiceException(Status.ProcessingFailure, + "Error processing DICOM message: " + t.getMessage()); + } + } finally { + Thread.currentThread().setName(originalThreadName); + IOUtils.closeQuietly(baos); + } + } + + /** + * Builds the sourceMap from a DICOM association. Package-visible for testing. + * The keys MUST match MirthDcmRcv.onCStoreRQ exactly for behavioral parity. + */ + Map buildSourceMap(Association as) { + Map sourceMap = new HashMap(); + + sourceMap.put("localApplicationEntityTitle", as.getLocalAET()); + sourceMap.put("remoteApplicationEntityTitle", as.getRemoteAET()); + + if (as.getSocket() != null) { + sourceMap.put("localAddress", as.getSocket().getLocalAddress().getHostAddress()); + sourceMap.put("localPort", as.getSocket().getLocalPort()); + if (as.getSocket().getRemoteSocketAddress() instanceof InetSocketAddress) { + sourceMap.put("remoteAddress", ((InetSocketAddress) as.getSocket().getRemoteSocketAddress()).getAddress().getHostAddress()); + sourceMap.put("remotePort", ((InetSocketAddress) as.getSocket().getRemoteSocketAddress()).getPort()); + } + } + + if (as.getAAssociateAC() != null) { + sourceMap.put("associateACProtocolVersion", as.getAAssociateAC().getProtocolVersion()); + sourceMap.put("associateACImplClassUID", as.getAAssociateAC().getImplClassUID()); + sourceMap.put("associateACImplVersionName", as.getAAssociateAC().getImplVersionName()); + sourceMap.put("associateACApplicationContext", as.getAAssociateAC().getApplicationContext()); + + if (as.getAAssociateAC().getNumberOfPresentationContexts() > 0) { + Map pcMap = new LinkedHashMap(); + for (PresentationContext pctx : as.getAAssociateAC().getPresentationContexts()) { + pcMap.put(pctx.getPCID(), pctx.toString()); + } + sourceMap.put("associateACPresentationContexts", MapUtils.unmodifiableMap(pcMap)); + } + } + + if (as.getAAssociateRQ() != null) { + sourceMap.put("associateRQProtocolVersion", as.getAAssociateRQ().getProtocolVersion()); + sourceMap.put("associateRQImplClassUID", as.getAAssociateRQ().getImplClassUID()); + sourceMap.put("associateRQImplVersionName", as.getAAssociateRQ().getImplVersionName()); + sourceMap.put("associateRQApplicationContext", as.getAAssociateRQ().getApplicationContext()); + + if (as.getAAssociateRQ().getNumberOfPresentationContexts() > 0) { + Map pcMap = new LinkedHashMap(); + for (PresentationContext pctx : as.getAAssociateRQ().getPresentationContexts()) { + pcMap.put(pctx.getPCID(), pctx.toString()); + } + sourceMap.put("associateRQPresentationContexts", MapUtils.unmodifiableMap(pcMap)); + } + + if (as.getAAssociateRQ().getUserIdentityRQ() != null) { + UserIdentityRQ uid = as.getAAssociateRQ().getUserIdentityRQ(); + sourceMap.put("username", uid.getUsername()); + sourceMap.put("passcode", String.valueOf(uid.getPasscode())); + + int type = uid.getType(); + String typeString; + switch (type) { + case 1: typeString = "USERNAME"; break; + case 2: typeString = "USERNAME_PASSCODE"; break; + case 3: typeString = "KERBEROS"; break; + case 4: typeString = "SAML"; break; + default: typeString = String.valueOf(type); + } + sourceMap.put("userIdentityType", typeString); + } + } + + return sourceMap; + } + + @Override + public void setPort(int port) { + conn.setPort(port); + } + + @Override + public void setHostname(String hostname) { + conn.setHostname(hostname); + } + + @Override + public void setDestination(String destination) { + // Not used — dcm5 receiver dispatches directly to the channel, not to filesystem + logger.trace("setDestination ignored in dcm5 receiver (no filesystem storage): " + destination); + } + + @Override + public void setTransferSyntax(String[] transferSyntax) { + this.transferSyntax = transferSyntax; + } + + @Override + public void setAEtitle(String aeTitle) { + if (aeTitle != null && !aeTitle.isEmpty()) { + ae.setAETitle(aeTitle); + } + } + + @Override + public void setAssociationReaperPeriod(int period) { + // dcm4che5 manages association lifecycle via idle timeouts, not a reaper period. + // The closest equivalent is the connection idle timeout. + conn.setIdleTimeout(period); + } + + @Override + public void setIdleTimeout(int timeout) { + conn.setIdleTimeout(timeout); + } + + @Override + public void setRequestTimeout(int timeout) { + conn.setRequestTimeout(timeout); + } + + @Override + public void setReleaseTimeout(int timeout) { + conn.setReleaseTimeout(timeout); + } + + @Override + public void setSocketCloseDelay(int delay) { + conn.setSocketCloseDelay(delay); + } + + @Override + public void setDimseRspDelay(int delay) { + // dcm4che5 handles DIMSE response timing internally. + // No direct equivalent — response delay is not configurable. + logger.trace("setDimseRspDelay ignored in dcm5 receiver: " + delay); + } + + @Override + public void setMaxPDULengthReceive(int length) { + conn.setReceivePDULength(length); + } + + @Override + public void setMaxPDULengthSend(int length) { + conn.setSendPDULength(length); + } + + @Override + public void setSendBufferSize(int size) { + conn.setSendBufferSize(size); + } + + @Override + public void setReceiveBufferSize(int size) { + conn.setReceiveBufferSize(size); + } + + @Override + public void setFileBufferSize(int size) { + // dcm5 receiver writes directly to ByteArrayOutputStream, not filesystem. + // No file buffer applicable. + logger.trace("setFileBufferSize ignored in dcm5 receiver: " + size); + } + + @Override + public void setPackPDV(boolean packPDV) { + conn.setPackPDV(packPDV); + } + + @Override + public void setTcpNoDelay(boolean tcpNoDelay) { + conn.setTcpNoDelay(tcpNoDelay); + } + + @Override + public void setMaxOpsPerformed(int maxOps) { + conn.setMaxOpsPerformed(maxOps); + } + + @Override + public void setTlsWithoutEncryption() { + conn.setTlsCipherSuites("SSL_RSA_WITH_NULL_SHA"); + } + + @Override + public void setTls3DES_EDE_CBC() { + conn.setTlsCipherSuites("SSL_RSA_WITH_3DES_EDE_CBC_SHA"); + } + + @Override + public void setTlsAES_128_CBC() { + conn.setTlsCipherSuites("TLS_RSA_WITH_AES_128_CBC_SHA"); + } + + @Override + public void setTlsCipherSuites(String[] cipherSuites) { + conn.setTlsCipherSuites(cipherSuites); + } + + @Override + public void setTrustStoreURL(String url) { + this.trustStoreURL = url; + } + + @Override + public void setTrustStorePassword(String password) { + this.trustStorePassword = password; + } + + @Override + public void setKeyPassword(String password) { + this.keyPassword = password; + } + + @Override + public void setKeyStoreURL(String url) { + this.keyStoreURL = url; + } + + @Override + public void setKeyStorePassword(String password) { + this.keyStorePassword = password; + } + + @Override + public void setKeyStoreType(String type) { + this.keyStoreType = type; + } + + @Override + public void setTrustStoreType(String type) { + this.trustStoreType = type; + } + + @Override + public void setTlsNeedClientAuth(boolean needClientAuth) { + conn.setTlsNeedClientAuth(needClientAuth); + } + + @Override + public void setTlsProtocol(String[] protocols) { + conn.setTlsProtocols(protocols); + } + + @Override + public void initTLS() throws Exception { + if (keyStoreURL != null) { + device.setKeyStoreURL(keyStoreURL); + device.setKeyStoreType(keyStoreType != null ? keyStoreType : Dcm5TlsUtil.inferStoreType(keyStoreURL)); + if (keyStorePassword != null) { + device.setKeyStorePin(keyStorePassword); + } + if (keyPassword != null) { + device.setKeyStoreKeyPin(keyPassword); + } + } + if (trustStoreURL != null) { + device.setTrustStoreURL(trustStoreURL); + device.setTrustStoreType(trustStoreType != null ? trustStoreType : Dcm5TlsUtil.inferStoreType(trustStoreURL)); + if (trustStorePassword != null) { + device.setTrustStorePin(trustStorePassword); + } + } + } + + @Override + public void initTransferCapability() { + if (transferSyntax != null && transferSyntax.length > 0) { + // All transfer syntaxes must be in a single TransferCapability for the wildcard + // abstract syntax, because ApplicationEntity stores TCs in a map keyed by abstract + // syntax — multiple adds with "*" would overwrite each other. + ae.addTransferCapability( + new TransferCapability(null, "*", TransferCapability.Role.SCP, transferSyntax)); + } + // Add verification SOP class + ae.addTransferCapability( + new TransferCapability(null, UID.Verification, TransferCapability.Role.SCP, UID.ImplicitVRLittleEndian)); + } + + @Override + public void start() throws Exception { + executor = Executors.newCachedThreadPool(); + scheduledExecutor = Executors.newSingleThreadScheduledExecutor(); + device.setExecutor(executor); + device.setScheduledExecutor(scheduledExecutor); + device.bindConnections(); + } + + private static final int SHUTDOWN_TIMEOUT_MS = 5000; + + @Override + public void stop() { + device.unbindConnections(); + if (executor != null) { + executor.shutdown(); + } + if (scheduledExecutor != null) { + scheduledExecutor.shutdown(); + } + try { + if (executor != null && !executor.awaitTermination(SHUTDOWN_TIMEOUT_MS, TimeUnit.MILLISECONDS)) { + executor.shutdownNow(); + } + if (scheduledExecutor != null && !scheduledExecutor.awaitTermination(SHUTDOWN_TIMEOUT_MS, TimeUnit.MILLISECONDS)) { + scheduledExecutor.shutdownNow(); + } + } catch (InterruptedException e) { + if (executor != null) executor.shutdownNow(); + if (scheduledExecutor != null) scheduledExecutor.shutdownNow(); + Thread.currentThread().interrupt(); + } + } + + @Override + public Object unwrap() { + return device; + } +} diff --git a/server/src/com/mirth/connect/connectors/dimse/dicom/dcm5/Dcm5DicomSender.java b/server/src/com/mirth/connect/connectors/dimse/dicom/dcm5/Dcm5DicomSender.java new file mode 100644 index 0000000000..609a5aa9b9 --- /dev/null +++ b/server/src/com/mirth/connect/connectors/dimse/dicom/dcm5/Dcm5DicomSender.java @@ -0,0 +1,586 @@ +/* + * Copyright (c) Mirth Corporation. All rights reserved. + * + * http://www.mirthcorp.com + * + * The software in this package is published under the terms of the MPL license a copy of which has + * been included with this distribution in the LICENSE.txt file. + */ + +package com.mirth.connect.connectors.dimse.dicom.dcm5; + +import java.io.File; +import java.io.IOException; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.TimeUnit; + +import org.apache.commons.io.IOUtils; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.dcm4che3.data.Attributes; +import org.dcm4che3.data.Tag; +import org.dcm4che3.data.UID; +import org.dcm4che3.data.VR; +import org.dcm4che3.io.DicomInputStream; +import org.dcm4che3.util.UIDUtils; +import org.dcm4che3.net.ApplicationEntity; +import org.dcm4che3.net.Association; +import org.dcm4che3.net.Commands; +import org.dcm4che3.net.Connection; +import org.dcm4che3.net.DataWriterAdapter; +import org.dcm4che3.net.Device; +import org.dcm4che3.net.DimseRSPHandler; +import org.dcm4che3.net.IncompatibleConnectionException; +import org.dcm4che3.net.Status; +import org.dcm4che3.net.TransferCapability; +import org.dcm4che3.net.pdu.AAssociateRQ; +import org.dcm4che3.net.pdu.PresentationContext; +import org.dcm4che3.net.pdu.UserIdentityRQ; + +import com.mirth.connect.connectors.dimse.DICOMConfiguration; +import com.mirth.connect.connectors.dimse.dicom.OieDicomObject; +import com.mirth.connect.connectors.dimse.dicom.OieDicomSender; +import com.mirth.connect.connectors.dimse.dicom.OieDimseRspHandler; + +/** + * dcm4che5 implementation of OieDicomSender. Composes from Device + Connection + + * ApplicationEntity + Association instead of delegating to a monolithic DcmSnd tool class. + */ +public class Dcm5DicomSender implements OieDicomSender { + + private static final Logger logger = LogManager.getLogger(Dcm5DicomSender.class); + + private final DICOMConfiguration configuration; + private final Device device; + private final Connection localConn; + private final Connection remoteConn; + private final ApplicationEntity localAE; + private final ApplicationEntity remoteAE; + private Association association; + + private final List files = new ArrayList<>(); + private final Map> sopClassToTsMap = new HashMap<>(); + private boolean storageCommitment; + private int priority = 0; + private boolean offerDefaultTsInSeparatePC = false; + private UserIdentityRQ userIdentityRQ; + private int shutdownDelay = 1000; + + private ExecutorService executor; + private ScheduledExecutorService scheduledExecutor; + + // TLS config stored for deferred initTLS() + private String keyStoreURL; + private String keyStorePassword; + private String keyPassword; + private String keyStoreType; + private String trustStoreURL; + private String trustStorePassword; + private String trustStoreType; + + // Storage commitment result (set by N-EVENT-REPORT handler) + private volatile Attributes stgCmtResult; + + /** Tracks sent file metadata for storage commitment. */ + private static final class FileInfo { + final File file; + String cuid; + String iuid; + String tsuid; + boolean transferred; + + FileInfo(File file) { + this.file = file; + } + } + + public Dcm5DicomSender(DICOMConfiguration configuration) { + this.configuration = configuration; + this.device = new Device("DCMSND"); + + if (configuration instanceof Dcm5DICOMConfiguration) { + this.localConn = ((Dcm5DICOMConfiguration) configuration).createDcm5Connection(); + } else { + Object custom = configuration.createNetworkConnection(); + this.localConn = (custom instanceof Connection) ? (Connection) custom : new Connection(); + } + + this.remoteConn = new Connection(); + this.localAE = new ApplicationEntity("DCMSND"); + this.remoteAE = new ApplicationEntity(); + + device.addConnection(localConn); + localAE.addConnection(localConn); + device.addApplicationEntity(localAE); + } + + @Override + public void setCalledAET(String aet) { + remoteAE.setAETitle(aet); + } + + @Override + public void setRemoteHost(String host) { + remoteConn.setHostname(host); + } + + @Override + public void setRemotePort(int port) { + remoteConn.setPort(port); + } + + @Override + public void setCalling(String aet) { + localAE.setAETitle(aet); + } + + @Override + public void setLocalHost(String host) { + localConn.setHostname(host); + } + + @Override + public void setLocalPort(int port) { + localConn.setPort(port); + } + + @Override + public void addFile(File file) { + if (file.isDirectory()) { + File[] children = file.listFiles(); + if (children != null) { + for (File child : children) { + addFile(child); + } + } + } else { + FileInfo info = new FileInfo(file); + files.add(info); + // Scan file for SOP Class UID and Transfer Syntax UID + DicomInputStream dis = null; + try { + dis = new DicomInputStream(file); + Attributes fmi = dis.readFileMetaInformation(); + if (fmi != null) { + info.cuid = fmi.getString(Tag.MediaStorageSOPClassUID); + info.iuid = fmi.getString(Tag.MediaStorageSOPInstanceUID); + info.tsuid = fmi.getString(Tag.TransferSyntaxUID); + if (info.cuid != null && info.tsuid != null) { + sopClassToTsMap.computeIfAbsent(info.cuid, k -> new HashSet<>()).add(info.tsuid); + } + } + } catch (Exception e) { + logger.trace("Could not read DICOM file meta info: " + file, e); + } finally { + IOUtils.closeQuietly(dis); + } + } + } + + @Override + public void setAcceptTimeout(int timeout) { + localConn.setAcceptTimeout(timeout); + } + + @Override + public void setMaxOpsInvoked(int maxOps) { + localConn.setMaxOpsInvoked(maxOps); + } + + @Override + public void setTranscoderBufferSize(int size) { + // dcm4che5 does not have a transcoder buffer — transcoding is handled internally. + logger.trace("setTranscoderBufferSize ignored in dcm5 sender: " + size); + } + + @Override + public void setConnectTimeout(int timeout) { + localConn.setConnectTimeout(timeout); + } + + @Override + public void setPriority(int priority) { + this.priority = priority; + } + + @Override + public void setPackPDV(boolean packPDV) { + localConn.setPackPDV(packPDV); + } + + @Override + public void setMaxPDULengthReceive(int length) { + localConn.setReceivePDULength(length); + } + + @Override + public void setMaxPDULengthSend(int length) { + localConn.setSendPDULength(length); + } + + @Override + public void setReceiveBufferSize(int size) { + localConn.setReceiveBufferSize(size); + } + + @Override + public void setSendBufferSize(int size) { + localConn.setSendBufferSize(size); + } + + @Override + public void setAssociationReaperPeriod(int period) { + // dcm4che5 manages association lifecycle via idle timeouts, not a reaper period. + localConn.setIdleTimeout(period); + } + + @Override + public void setReleaseTimeout(int timeout) { + localConn.setReleaseTimeout(timeout); + } + + @Override + public void setDimseRspTimeout(int timeout) { + localConn.setResponseTimeout(timeout); + } + + @Override + public void setShutdownDelay(int delay) { + this.shutdownDelay = delay; + } + + @Override + public void setSocketCloseDelay(int delay) { + localConn.setSocketCloseDelay(delay); + } + + @Override + public void setTcpNoDelay(boolean tcpNoDelay) { + localConn.setTcpNoDelay(tcpNoDelay); + } + + @Override + public void setOfferDefaultTransferSyntaxInSeparatePresentationContext(boolean ts1) { + this.offerDefaultTsInSeparatePC = ts1; + } + + @Override + public void setStorageCommitment(boolean stgcmt) { + this.storageCommitment = stgcmt; + } + + @Override + public void setUserIdentity(String username, String passcode, boolean positiveResponseRequested) { + if (passcode != null && !passcode.isEmpty()) { + userIdentityRQ = UserIdentityRQ.usernamePasscode(username, passcode.toCharArray(), positiveResponseRequested); + } else { + userIdentityRQ = UserIdentityRQ.username(username, positiveResponseRequested); + } + } + + @Override + public void setTlsWithoutEncryption() { + localConn.setTlsCipherSuites("SSL_RSA_WITH_NULL_SHA"); + remoteConn.setTlsCipherSuites("SSL_RSA_WITH_NULL_SHA"); + } + + @Override + public void setTls3DES_EDE_CBC() { + localConn.setTlsCipherSuites("SSL_RSA_WITH_3DES_EDE_CBC_SHA"); + remoteConn.setTlsCipherSuites("SSL_RSA_WITH_3DES_EDE_CBC_SHA"); + } + + @Override + public void setTlsAES_128_CBC() { + localConn.setTlsCipherSuites("TLS_RSA_WITH_AES_128_CBC_SHA"); + remoteConn.setTlsCipherSuites("TLS_RSA_WITH_AES_128_CBC_SHA"); + } + + @Override + public void setTlsCipherSuites(String[] cipherSuites) { + localConn.setTlsCipherSuites(cipherSuites); + remoteConn.setTlsCipherSuites(cipherSuites); + } + + @Override + public void setTrustStoreURL(String url) { + this.trustStoreURL = url; + } + + @Override + public void setTrustStorePassword(String password) { + this.trustStorePassword = password; + } + + @Override + public void setKeyPassword(String password) { + this.keyPassword = password; + } + + @Override + public void setKeyStoreURL(String url) { + this.keyStoreURL = url; + } + + @Override + public void setKeyStorePassword(String password) { + this.keyStorePassword = password; + } + + @Override + public void setKeyStoreType(String type) { + this.keyStoreType = type; + } + + @Override + public void setTrustStoreType(String type) { + this.trustStoreType = type; + } + + @Override + public void setTlsNeedClientAuth(boolean needClientAuth) { + localConn.setTlsNeedClientAuth(needClientAuth); + } + + @Override + public void setTlsProtocol(String[] protocols) { + localConn.setTlsProtocols(protocols); + remoteConn.setTlsProtocols(protocols); + } + + @Override + public void initTLS() throws Exception { + if (keyStoreURL != null) { + device.setKeyStoreURL(keyStoreURL); + device.setKeyStoreType(keyStoreType != null ? keyStoreType : Dcm5TlsUtil.inferStoreType(keyStoreURL)); + if (keyStorePassword != null) { + device.setKeyStorePin(keyStorePassword); + } + if (keyPassword != null) { + device.setKeyStoreKeyPin(keyPassword); + } + } + if (trustStoreURL != null) { + device.setTrustStoreURL(trustStoreURL); + device.setTrustStoreType(trustStoreType != null ? trustStoreType : Dcm5TlsUtil.inferStoreType(trustStoreURL)); + if (trustStorePassword != null) { + device.setTrustStorePin(trustStorePassword); + } + } + } + + @Override + public void configureTransferCapability() { + for (Map.Entry> entry : sopClassToTsMap.entrySet()) { + String[] tsArray = entry.getValue().toArray(new String[0]); + localAE.addTransferCapability( + new TransferCapability(null, entry.getKey(), TransferCapability.Role.SCU, tsArray)); + + if (offerDefaultTsInSeparatePC && !entry.getValue().contains(UID.ImplicitVRLittleEndian)) { + localAE.addTransferCapability( + new TransferCapability(null, entry.getKey(), TransferCapability.Role.SCU, UID.ImplicitVRLittleEndian)); + } + } + } + + @Override + public void start() throws IOException { + executor = Executors.newCachedThreadPool(); + scheduledExecutor = Executors.newSingleThreadScheduledExecutor(); + device.setExecutor(executor); + device.setScheduledExecutor(scheduledExecutor); + + // Register N-EVENT-REPORT handler for storage commitment responses + if (storageCommitment) { + org.dcm4che3.net.service.DicomServiceRegistry serviceRegistry = new org.dcm4che3.net.service.DicomServiceRegistry(); + serviceRegistry.addDicomService(new org.dcm4che3.net.service.AbstractDicomService(UID.StorageCommitmentPushModel) { + @Override + public void onDimseRQ(Association as, PresentationContext pc, + org.dcm4che3.net.Dimse dimse, Attributes rq, Attributes data) + throws IOException { + if (dimse == org.dcm4che3.net.Dimse.N_EVENT_REPORT_RQ) { + // Send success response + Attributes rsp = org.dcm4che3.net.Commands.mkNEventReportRSP(rq, Status.Success); + as.tryWriteDimseRSP(pc, rsp); + // Notify waitForStgCmtResult + onNEventReportRSP(data); + } + } + }); + device.setDimseRQHandler(serviceRegistry); + localAE.setAssociationAcceptor(true); + } + } + + @Override + public void open() throws Exception { + AAssociateRQ aarq = new AAssociateRQ(); + aarq.setCalledAET(remoteAE.getAETitle()); + aarq.setCallingAET(localAE.getAETitle()); + + if (userIdentityRQ != null) { + aarq.setUserIdentityRQ(userIdentityRQ); + } + + // Add presentation contexts from transfer capabilities + int pcid = 1; + for (Map.Entry> entry : sopClassToTsMap.entrySet()) { + String[] tsArray = entry.getValue().toArray(new String[0]); + aarq.addPresentationContext(new PresentationContext(pcid, entry.getKey(), tsArray)); + pcid += 2; + + if (offerDefaultTsInSeparatePC && !entry.getValue().contains(UID.ImplicitVRLittleEndian)) { + aarq.addPresentationContext(new PresentationContext(pcid, entry.getKey(), UID.ImplicitVRLittleEndian)); + pcid += 2; + } + } + + // Add storage commitment if enabled + if (storageCommitment) { + aarq.addPresentationContext(new PresentationContext(pcid, UID.StorageCommitmentPushModel, UID.ImplicitVRLittleEndian)); + } + + try { + association = localAE.connect(localConn, remoteConn, aarq); + } catch (IncompatibleConnectionException e) { + throw new IOException("Failed to open DICOM association", e); + } + } + + @Override + public void send(OieDimseRspHandler handler) throws Exception { + for (FileInfo info : files) { + DicomInputStream dis = null; + try { + dis = new DicomInputStream(info.file); + Attributes fmi = dis.readFileMetaInformation(); + Attributes dataset = dis.readDataset(-1, -1); + + String cuid = fmi.getString(Tag.MediaStorageSOPClassUID); + String iuid = fmi.getString(Tag.MediaStorageSOPInstanceUID); + String tsuid = fmi.getString(Tag.TransferSyntaxUID); + + DimseRSPHandler rspHandler = new DimseRSPHandler(association.nextMessageID()) { + @Override + public void onDimseRSP(Association as, Attributes cmd, Attributes data) { + super.onDimseRSP(as, cmd, data); + OieDicomObject wrappedCmd = cmd != null ? new Dcm5DicomObject(cmd) : null; + OieDicomObject wrappedData = data != null ? new Dcm5DicomObject(data) : null; + handler.onDimseRSP(wrappedCmd, wrappedData); + } + }; + + association.cstore(cuid, iuid, priority, new DataWriterAdapter(dataset), tsuid, rspHandler); + info.transferred = true; + } finally { + IOUtils.closeQuietly(dis); + } + } + } + + @Override + public boolean isStorageCommitment() { + return storageCommitment; + } + + @Override + public boolean commit() throws Exception { + if (!storageCommitment || association == null) { + return false; + } + + Attributes actionInfo = new Attributes(); + actionInfo.setString(Tag.TransactionUID, VR.UI, UIDUtils.createUID()); + + // Build reference SOP sequence from successfully transferred files + org.dcm4che3.data.Sequence refSOPSeq = actionInfo.newSequence(Tag.ReferencedSOPSequence, files.size()); + for (FileInfo info : files) { + if (info.transferred && info.cuid != null && info.iuid != null) { + Attributes refSOP = new Attributes(2); + refSOP.setString(Tag.ReferencedSOPClassUID, VR.UI, info.cuid); + refSOP.setString(Tag.ReferencedSOPInstanceUID, VR.UI, info.iuid); + refSOPSeq.add(refSOP); + } + } + + try { + stgCmtResult = null; + org.dcm4che3.net.DimseRSP rsp = association.naction( + UID.StorageCommitmentPushModel, + UID.StorageCommitmentPushModelInstance, + 1, actionInfo, UID.ImplicitVRLittleEndian); + rsp.next(); + Attributes cmd = rsp.getCommand(); + int status = cmd.getInt(Tag.Status, -1); + return status == Status.Success; + } catch (Exception e) { + logger.error("Failed to send Storage Commitment request", e); + return false; + } + } + + @Override + public synchronized OieDicomObject waitForStgCmtResult() throws InterruptedException { + while (stgCmtResult == null) { + wait(); + } + return new Dcm5DicomObject(stgCmtResult); + } + + /** + * Called when the remote SCP sends an N-EVENT-REPORT with the storage commitment result. + * Sets the result and wakes up any thread waiting in waitForStgCmtResult(). + */ + synchronized void onNEventReportRSP(Attributes info) { + stgCmtResult = info; + notifyAll(); + } + + @Override + public void close() { + if (association != null) { + try { + association.release(); + } catch (IOException e) { + logger.trace("Error releasing association", e); + } + association = null; + } + } + + @Override + public void stop() { + device.unbindConnections(); + if (executor != null) { + executor.shutdown(); + } + if (scheduledExecutor != null) { + scheduledExecutor.shutdown(); + } + try { + if (executor != null && !executor.awaitTermination(shutdownDelay, TimeUnit.MILLISECONDS)) { + executor.shutdownNow(); + } + if (scheduledExecutor != null && !scheduledExecutor.awaitTermination(shutdownDelay, TimeUnit.MILLISECONDS)) { + scheduledExecutor.shutdownNow(); + } + } catch (InterruptedException e) { + if (executor != null) executor.shutdownNow(); + if (scheduledExecutor != null) scheduledExecutor.shutdownNow(); + Thread.currentThread().interrupt(); + } + } + + @Override + public Object unwrap() { + return device; + } +} diff --git a/server/src/com/mirth/connect/connectors/dimse/dicom/dcm5/Dcm5TlsUtil.java b/server/src/com/mirth/connect/connectors/dimse/dicom/dcm5/Dcm5TlsUtil.java new file mode 100644 index 0000000000..c00fad7ac2 --- /dev/null +++ b/server/src/com/mirth/connect/connectors/dimse/dicom/dcm5/Dcm5TlsUtil.java @@ -0,0 +1,32 @@ +/* + * Copyright (c) Mirth Corporation. All rights reserved. + * + * http://www.mirthcorp.com + * + * The software in this package is published under the terms of the MPL license a copy of which has + * been included with this distribution in the LICENSE.txt file. + */ + +package com.mirth.connect.connectors.dimse.dicom.dcm5; + +/** + * Shared TLS utilities for dcm5 sender and receiver. + */ +final class Dcm5TlsUtil { + + private Dcm5TlsUtil() {} + + /** + * Infers keystore/truststore type from a URL's file extension. + * Returns "PKCS12" for .p12/.pfx files, "JKS" otherwise. + */ + static String inferStoreType(String url) { + if (url != null) { + String lower = url.toLowerCase(); + if (lower.endsWith(".p12") || lower.endsWith(".pfx")) { + return "PKCS12"; + } + } + return "JKS"; + } +} diff --git a/server/src/com/mirth/connect/connectors/dimse/dicom/dcm5/Dcm5VR.java b/server/src/com/mirth/connect/connectors/dimse/dicom/dcm5/Dcm5VR.java new file mode 100644 index 0000000000..0df3cbfb4d --- /dev/null +++ b/server/src/com/mirth/connect/connectors/dimse/dicom/dcm5/Dcm5VR.java @@ -0,0 +1,43 @@ +/* + * Copyright (c) Mirth Corporation. All rights reserved. + * + * http://www.mirthcorp.com + * + * The software in this package is published under the terms of the MPL license a copy of which has + * been included with this distribution in the LICENSE.txt file. + */ + +package com.mirth.connect.connectors.dimse.dicom.dcm5; + +import org.dcm4che3.data.VR; + +import com.mirth.connect.connectors.dimse.dicom.OieVR; + +public class Dcm5VR implements OieVR { + + private final VR vr; + + public Dcm5VR(VR vr) { + this.vr = vr; + } + + @Override + public String toString() { + return vr.toString(); + } + + @Override + public int code() { + return vr.code(); + } + + @Override + public int padding() { + return vr.paddingByte(); + } + + @Override + public Object unwrap() { + return vr; + } +} diff --git a/server/src/com/mirth/connect/connectors/dimse/source.xml b/server/src/com/mirth/connect/connectors/dimse/source.xml index 312120e1ae..fb9024517d 100644 --- a/server/src/com/mirth/connect/connectors/dimse/source.xml +++ b/server/src/com/mirth/connect/connectors/dimse/source.xml @@ -10,13 +10,15 @@ com.mirth.connect.connectors.dimse.DICOMReceiverProperties - - - - - + + + + + + + dicom SOURCE diff --git a/server/src/com/mirth/connect/model/ExtensionLibrary.java b/server/src/com/mirth/connect/model/ExtensionLibrary.java index 7e48b83516..85a3ff87b0 100644 --- a/server/src/com/mirth/connect/model/ExtensionLibrary.java +++ b/server/src/com/mirth/connect/model/ExtensionLibrary.java @@ -28,6 +28,9 @@ public enum Type { @XStreamAsAttribute private Type type; + @XStreamAsAttribute + private String variant; + public Type getType() { return type; } @@ -44,6 +47,14 @@ public void setPath(String path) { this.path = path; } + public String getVariant() { + return variant; + } + + public void setVariant(String variant) { + this.variant = variant; + } + @Override public String toString() { return ToStringBuilder.reflectionToString(this, CalendarToStringStyle.instance()); diff --git a/server/src/com/mirth/connect/model/converters/DICOMConverter.java b/server/src/com/mirth/connect/model/converters/DICOMConverter.java index ee30ece3f1..3c83d4a303 100644 --- a/server/src/com/mirth/connect/model/converters/DICOMConverter.java +++ b/server/src/com/mirth/connect/model/converters/DICOMConverter.java @@ -1,116 +1,31 @@ /* * Copyright (c) Mirth Corporation. All rights reserved. - * + * * http://www.mirthcorp.com - * + * * The software in this package is published under the terms of the MPL license a copy of which has * been included with this distribution in the LICENSE.txt file. */ package com.mirth.connect.model.converters; -import java.io.BufferedInputStream; -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; import java.io.IOException; -import java.io.InputStream; -import org.apache.commons.codec.binary.Base64InputStream; -import org.apache.commons.io.IOUtils; -import org.dcm4che2.data.BasicDicomObject; -import org.dcm4che2.data.DicomObject; -import org.dcm4che2.data.TransferSyntax; -import org.dcm4che2.io.DicomInputStream; -import org.dcm4che2.io.DicomOutputStream; - -import com.mirth.connect.donkey.util.ByteCounterOutputStream; +import com.mirth.connect.connectors.dimse.dicom.DicomLibraryFactory; +import com.mirth.connect.connectors.dimse.dicom.OieDicomConverter; +import com.mirth.connect.connectors.dimse.dicom.OieDicomObject; public class DICOMConverter { - public static DicomObject byteArrayToDicomObject(byte[] bytes, boolean decodeBase64) throws IOException { - DicomObject basicDicomObject = new BasicDicomObject(); - DicomInputStream dis = null; - - try { - ByteArrayInputStream bais = new ByteArrayInputStream(bytes); - InputStream inputStream; - if (decodeBase64) { - inputStream = new BufferedInputStream(new Base64InputStream(bais)); - } else { - inputStream = bais; - } - dis = new DicomInputStream(inputStream); - /* - * This parameter was added in dcm4che 2.0.28. We use it to retain the memory allocation - * behavior from 2.0.25. http://www.mirthcorp.com/community/issues/browse/MIRTH-2166 - * http://www.dcm4che.org/jira/browse/DCM-554 - */ - dis.setAllocateLimit(-1); - dis.readDicomObject(basicDicomObject, -1); - } catch (IOException e) { - throw e; - } finally { - IOUtils.closeQuietly(dis); - } - - return basicDicomObject; + private static OieDicomConverter getConverter() { + return DicomLibraryFactory.getConverter(); } - public static byte[] dicomObjectToByteArray(DicomObject dicomObject) throws IOException { - BasicDicomObject basicDicomObject = (BasicDicomObject) dicomObject; - DicomOutputStream dos = null; - - try { - ByteCounterOutputStream bcos = new ByteCounterOutputStream(); - ByteArrayOutputStream baos; - - if (basicDicomObject.fileMetaInfo().isEmpty()) { - try { - // Create a dicom output stream with the byte counter output stream. - dos = new DicomOutputStream(bcos); - // "Write" the dataset once to determine the total number of bytes required. This is fast because no data is actually being copied. - dos.writeDataset(basicDicomObject, TransferSyntax.ImplicitVRLittleEndian); - } finally { - IOUtils.closeQuietly(dos); - } - - // Create the actual byte array output stream with a buffer size equal to the number of bytes required. - baos = new ByteArrayOutputStream(bcos.size()); - // Create a dicom output stream with the byte array output stream - dos = new DicomOutputStream(baos); - - // Create ACR/NEMA Dump - dos.writeDataset(basicDicomObject, TransferSyntax.ImplicitVRLittleEndian); - } else { - try { - // Create a dicom output stream with the byte counter output stream. - dos = new DicomOutputStream(bcos); - // "Write" the dataset once to determine the total number of bytes required. This is fast because no data is actually being copied. - dos.writeDicomFile(basicDicomObject); - } finally { - IOUtils.closeQuietly(dos); - } - - // Create the actual byte array output stream with a buffer size equal to the number of bytes required. - baos = new ByteArrayOutputStream(bcos.size()); - // Create a dicom output stream with the byte array output stream - dos = new DicomOutputStream(baos); - - // Create DICOM File - dos.writeDicomFile(basicDicomObject); - } - - // Memory Optimization since the dicom object is no longer needed at this point. - dicomObject.clear(); + public static OieDicomObject byteArrayToDicomObject(byte[] bytes, boolean decodeBase64) throws IOException { + return getConverter().byteArrayToDicomObject(bytes, decodeBase64); + } - return baos.toByteArray(); - } catch (IOException e) { - throw e; - } catch (Throwable t) { - t.printStackTrace(); - return null; - } finally { - IOUtils.closeQuietly(dos); - } + public static byte[] dicomObjectToByteArray(OieDicomObject dicomObject) throws IOException { + return getConverter().dicomObjectToByteArray(dicomObject); } } diff --git a/server/src/com/mirth/connect/plugins/datatypes/dicom/DICOMReference.java b/server/src/com/mirth/connect/plugins/datatypes/dicom/DICOMReference.java index 716b863eef..56678404c4 100644 --- a/server/src/com/mirth/connect/plugins/datatypes/dicom/DICOMReference.java +++ b/server/src/com/mirth/connect/plugins/datatypes/dicom/DICOMReference.java @@ -1,22 +1,23 @@ /* * Copyright (c) Mirth Corporation. All rights reserved. - * + * * http://www.mirthcorp.com - * + * * The software in this package is published under the terms of the MPL license a copy of which has * been included with this distribution in the LICENSE.txt file. */ package com.mirth.connect.plugins.datatypes.dicom; -import org.dcm4che2.data.ElementDictionary; +import com.mirth.connect.connectors.dimse.dicom.DicomLibraryFactory; +import com.mirth.connect.connectors.dimse.dicom.OieDicomConverter; public class DICOMReference { private static DICOMReference instance = null; - private ElementDictionary elementDictionary = null; + private OieDicomConverter converter = null; private DICOMReference() { - elementDictionary = ElementDictionary.getDictionary(); + converter = DicomLibraryFactory.getConverter(); } public static DICOMReference getInstance() { @@ -30,7 +31,7 @@ public static DICOMReference getInstance() { public String getDescription(String key, String version) { if (key != null && !key.equals("")) { try { - return elementDictionary.nameOf(Integer.decode("0x" + key).intValue()); + return converter.getElementName(Integer.decode("0x" + key).intValue()); } catch (NumberFormatException e) { return ""; } diff --git a/server/src/com/mirth/connect/plugins/datatypes/dicom/DICOMSerializer.java b/server/src/com/mirth/connect/plugins/datatypes/dicom/DICOMSerializer.java index 9b16c4bbb2..42ebf882e7 100644 --- a/server/src/com/mirth/connect/plugins/datatypes/dicom/DICOMSerializer.java +++ b/server/src/com/mirth/connect/plugins/datatypes/dicom/DICOMSerializer.java @@ -1,47 +1,30 @@ /* * Copyright (c) Mirth Corporation. All rights reserved. - * + * * http://www.mirthcorp.com - * + * * The software in this package is published under the terms of the MPL license a copy of which has * been included with this distribution in the LICENSE.txt file. */ package com.mirth.connect.plugins.datatypes.dicom; -import java.io.BufferedInputStream; -import java.io.ByteArrayInputStream; import java.io.IOException; -import java.io.StringWriter; import java.util.HashMap; import java.util.Map; -import javax.xml.XMLConstants; -import javax.xml.parsers.SAXParser; -import javax.xml.parsers.SAXParserFactory; -import javax.xml.transform.OutputKeys; -import javax.xml.transform.TransformerFactory; -import javax.xml.transform.sax.SAXTransformerFactory; -import javax.xml.transform.sax.TransformerHandler; -import javax.xml.transform.stream.StreamResult; - -import org.apache.commons.codec.binary.Base64InputStream; import org.apache.commons.codec.binary.StringUtils; -import org.apache.commons.io.IOUtils; -import org.dcm4che2.data.BasicDicomObject; -import org.dcm4che2.data.DicomObject; -import org.dcm4che2.data.Tag; -import org.dcm4che2.io.ContentHandlerAdapter; -import org.dcm4che2.io.DicomInputStream; -import org.dcm4che2.io.SAXWriter; import org.w3c.dom.DOMException; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.NamedNodeMap; import org.w3c.dom.Node; import org.w3c.dom.NodeList; -import org.xml.sax.InputSource; +import com.mirth.connect.connectors.dimse.dicom.DicomConstants; +import com.mirth.connect.connectors.dimse.dicom.DicomLibraryFactory; +import com.mirth.connect.connectors.dimse.dicom.OieDicomConverter; +import com.mirth.connect.connectors.dimse.dicom.OieDicomObject; import com.mirth.connect.donkey.model.message.MessageSerializer; import com.mirth.connect.donkey.model.message.MessageSerializerException; import com.mirth.connect.donkey.util.Base64Util; @@ -68,10 +51,11 @@ public static Map getDefaultProperties() { } public static byte[] removePixelData(byte[] content) throws IOException { - DicomObject dicomObject = DICOMConverter.byteArrayToDicomObject(content, false); - dicomObject.remove(Tag.PixelData); + OieDicomConverter converter = DicomLibraryFactory.getConverter(); + OieDicomObject dicomObject = converter.byteArrayToDicomObject(content, false); + dicomObject.remove(DicomConstants.TAG_PIXEL_DATA); - return DICOMConverter.dicomObjectToByteArray(dicomObject); + return converter.dicomObjectToByteArray(dicomObject); } @Override @@ -132,14 +116,10 @@ public String fromXML(String source) throws MessageSerializerException { charset = "utf-8"; } - // parse the Document into a DicomObject - SAXParserFactory factory = SAXParserFactory.newInstance(); - factory.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true); - SAXParser parser = factory.newSAXParser(); - DicomObject dicomObject = new BasicDicomObject(); - ContentHandlerAdapter contentHandler = new ContentHandlerAdapter(dicomObject); - byte[] documentBytes = documentSerializer.toXML(document).trim().getBytes(charset); - parser.parse(new InputSource(new ByteArrayInputStream(documentBytes)), contentHandler); + // parse the Document into a DicomObject via the converter + OieDicomConverter converter = DicomLibraryFactory.getConverter(); + String xmlString = documentSerializer.toXML(document).trim(); + OieDicomObject dicomObject = converter.xmlToDicomObject(xmlString, charset); return StringUtils.newStringUsAscii(Base64Util.encodeBase64(DICOMConverter.dicomObjectToByteArray(dicomObject))); } catch (Exception e) { throw new MessageSerializerException("Error converting XML to DICOM", e, ErrorMessageBuilder.buildErrorMessage(this.getClass().getSimpleName(), "Error converting XML to DICOM", e)); @@ -151,49 +131,19 @@ public String toXML(String source) throws MessageSerializerException { try { byte[] encodedMessage = org.apache.commons.codec.binary.StringUtils.getBytesUsAscii(source); - StringWriter output = new StringWriter(); - DicomInputStream dis = new DicomInputStream(new BufferedInputStream(new Base64InputStream(new ByteArrayInputStream(encodedMessage)))); - /* - * This parameter was added in dcm4che 2.0.28. We use it to retain the memory allocation - * behavior from 2.0.25. http://www.mirthcorp.com/community/issues/browse/MIRTH-2166 - * http://www.dcm4che.org/jira/browse/DCM-554 - */ - dis.setAllocateLimit(-1); - - try { - TransformerFactory tf = TransformerFactory.newInstance(); - tf.setAttribute(XMLConstants.ACCESS_EXTERNAL_DTD, ""); - tf.setAttribute(XMLConstants.ACCESS_EXTERNAL_STYLESHEET, ""); - SAXTransformerFactory factory = (SAXTransformerFactory) tf; - TransformerHandler handler = factory.newTransformerHandler(); - handler.getTransformer().setOutputProperty(OutputKeys.INDENT, "no"); - handler.setResult(new StreamResult(output)); - - final SAXWriter writer = new SAXWriter(handler, null); - dis.setHandler(writer); - dis.readDicomObject(new BasicDicomObject(), -1); - String serializedDicomObject = output.toString(); - - // rename the "attr" element to the tag ID - Document document = documentSerializer.fromXML(serializedDicomObject); - NodeList attrElements = document.getElementsByTagName("attr"); - - for (int i = 0; i < attrElements.getLength(); i++) { - Element attrElement = (Element) attrElements.item(i); - renameAttrToTag(document, attrElement); - } + OieDicomConverter converter = DicomLibraryFactory.getConverter(); + String serializedDicomObject = converter.dicomBytesToXml(encodedMessage); - return documentSerializer.toXML(document); - } catch (Exception e) { - throw e; - } finally { - IOUtils.closeQuietly(dis); - IOUtils.closeQuietly(output); + // rename the "attr" element to the tag ID + Document document = documentSerializer.fromXML(serializedDicomObject); + NodeList attrElements = document.getElementsByTagName("attr"); - if (dis != null) { - dis.close(); - } + for (int i = 0; i < attrElements.getLength(); i++) { + Element attrElement = (Element) attrElements.item(i); + renameAttrToTag(document, attrElement); } + + return documentSerializer.toXML(document); } catch (Exception e) { throw new MessageSerializerException("Error converting DICOM to XML", e, ErrorMessageBuilder.buildErrorMessage(this.getClass().getSimpleName(), "Error converting DICOM to XML", e)); } diff --git a/server/src/com/mirth/connect/server/attachments/dicom/DICOMAttachmentHandler.java b/server/src/com/mirth/connect/server/attachments/dicom/DICOMAttachmentHandler.java index a460fbcbda..eddf7bf6af 100644 --- a/server/src/com/mirth/connect/server/attachments/dicom/DICOMAttachmentHandler.java +++ b/server/src/com/mirth/connect/server/attachments/dicom/DICOMAttachmentHandler.java @@ -1,8 +1,8 @@ /* * Copyright (c) Mirth Corporation. All rights reserved. - * + * * http://www.mirthcorp.com - * + * * The software in this package is published under the terms of the MPL license a copy of which has * been included with this distribution in the LICENSE.txt file. */ @@ -10,10 +10,10 @@ package com.mirth.connect.server.attachments.dicom; import org.apache.commons.codec.binary.StringUtils; -import org.dcm4che2.data.DicomElement; -import org.dcm4che2.data.DicomObject; -import org.dcm4che2.data.Tag; +import com.mirth.connect.connectors.dimse.dicom.DicomConstants; +import com.mirth.connect.connectors.dimse.dicom.OieDicomElement; +import com.mirth.connect.connectors.dimse.dicom.OieDicomObject; import com.mirth.connect.donkey.model.message.RawMessage; import com.mirth.connect.donkey.model.message.attachment.Attachment; import com.mirth.connect.donkey.model.message.attachment.AttachmentException; @@ -25,8 +25,8 @@ public class DICOMAttachmentHandler implements AttachmentHandler { - private DicomObject dicomObject; - private DicomElement dicomElement; + private OieDicomObject dicomObject; + private OieDicomElement dicomElement; private int index; private String attachmentId; @@ -40,7 +40,7 @@ public void initialize(RawMessage message, Channel channel) throws AttachmentExc if (message.isBinary()) { messageBytes = message.getRawBytes(); } else { - // Taking a string is much more inefficient than taking in a byte array. + // Taking a string is much more inefficient than taking in a byte array. // If the user manually sends a message, it will arrive as a base64 encoded string, so we must support Strings for DICOM still. // However, DICOM messages that use this initializer should be relatively small in size. messageBytes = StringUtils.getBytesUsAscii(message.getRawData()); @@ -48,7 +48,7 @@ public void initialize(RawMessage message, Channel channel) throws AttachmentExc } dicomObject = DICOMConverter.byteArrayToDicomObject(messageBytes, decode); - dicomElement = dicomObject.remove(Tag.PixelData); + dicomElement = dicomObject.remove(DicomConstants.TAG_PIXEL_DATA); attachmentId = ServerUUIDGenerator.getUUID(); } catch (Throwable t) { throw new AttachmentException(t); diff --git a/server/src/com/mirth/connect/server/launcher/MirthLauncher.java b/server/src/com/mirth/connect/server/launcher/MirthLauncher.java index cd3d343fd7..5e53c50599 100644 --- a/server/src/com/mirth/connect/server/launcher/MirthLauncher.java +++ b/server/src/com/mirth/connect/server/launcher/MirthLauncher.java @@ -18,6 +18,7 @@ import java.util.ArrayList; import java.util.Collection; import java.util.List; +import java.util.Map; import java.util.Properties; import java.util.jar.JarFile; @@ -47,6 +48,8 @@ public class MirthLauncher { "./server-lib/log4j/log4j-api-2.25.3.jar", "./server-lib/log4j/log4j-1.2-api-2.25.3.jar" }; + static final Map VARIANT_DEFAULTS = Map.of("dicom.library", "dcm4che2"); + private static String appDataDir = null; private static LoggerWrapper logger; @@ -112,7 +115,7 @@ public static void main(String[] args) { String currentVersion = versionProperties.getProperty("mirth.version"); addManifestToClasspath(manifest, classpathUrls); - addExtensionsToClasspath(classpathUrls, currentVersion); + addExtensionsToClasspath(classpathUrls, currentVersion, mirthProperties); URLClassLoader classLoader = new URLClassLoader(classpathUrls.toArray(new URL[classpathUrls.size()]), Thread.currentThread().getContextClassLoader()); Class mirthClass = classLoader.loadClass("com.mirth.connect.server.Mirth"); Thread mirthThread = (Thread) mirthClass.newInstance(); @@ -233,7 +236,7 @@ private static void addManifestToClasspath(ManifestEntry[] manifestEntries, List } } - private static void addExtensionsToClasspath(List urls, String currentVersion) throws Exception { + private static void addExtensionsToClasspath(List urls, String currentVersion, Properties mirthProperties) throws Exception { FileFilter extensionFileFilter = new NameFileFilter(new String[] { "plugin.xml", "source.xml", "destination.xml" }, IOCase.INSENSITIVE); FileFilter directoryFilter = FileFilterUtils.directoryFileFilter(); @@ -266,6 +269,14 @@ private static void addExtensionsToClasspath(List urls, String currentVersi String type = libraryElement.getAttribute("type"); if (type.equalsIgnoreCase("server") || type.equalsIgnoreCase("shared")) { + String variant = libraryElement.getAttribute("variant"); + + if (!shouldLoadLibrary(variant, mirthProperties)) { + File pathFile = new File(directory, libraryElement.getAttribute("path")); + logger.trace("skipping variant-mismatched library: " + pathFile.getAbsolutePath()); + continue; + } + File pathFile = new File(directory, libraryElement.getAttribute("path")); if (pathFile.exists()) { @@ -287,6 +298,38 @@ private static void addExtensionsToClasspath(List urls, String currentVersi } } + /** + * Determines whether a library should be loaded based on its variant attribute + * and the current mirth.properties values. + * + *

Variant format: {@code "propertyKey:requiredValue"} (e.g., {@code "dicom.library:dcm4che2"}). + * Libraries without a variant attribute are always loaded. + * + * @param variant the variant attribute value (may be null or empty) + * @param mirthProperties the loaded mirth.properties + * @return true if the library should be loaded + */ + static boolean shouldLoadLibrary(String variant, Properties mirthProperties) { + if (variant == null || variant.isEmpty()) { + return true; + } + + int colonIdx = variant.indexOf(':'); + if (colonIdx <= 0) { + return true; + } + + String propName = variant.substring(0, colonIdx); + String requiredValue = variant.substring(colonIdx + 1); + String actual = mirthProperties.getProperty(propName); + + if (actual == null || actual.trim().isEmpty()) { + actual = VARIANT_DEFAULTS.getOrDefault(propName, ""); + } + + return requiredValue.equalsIgnoreCase(actual.trim()); + } + private static boolean isExtensionCompatible(String extensionVersion, String currentVersion) { if (extensionVersion != null) { String[] extensionMirthVersions = extensionVersion.split(","); diff --git a/server/src/com/mirth/connect/server/userutil/DICOMUtil.java b/server/src/com/mirth/connect/server/userutil/DICOMUtil.java index 5115700987..2eb087a010 100644 --- a/server/src/com/mirth/connect/server/userutil/DICOMUtil.java +++ b/server/src/com/mirth/connect/server/userutil/DICOMUtil.java @@ -1,8 +1,8 @@ /* * Copyright (c) Mirth Corporation. All rights reserved. - * + * * http://www.mirthcorp.com - * + * * The software in this package is published under the terms of the MPL license a copy of which has * been included with this distribution in the LICENSE.txt file. */ @@ -13,8 +13,7 @@ import java.util.ArrayList; import java.util.List; -import org.dcm4che2.data.DicomObject; - +import com.mirth.connect.connectors.dimse.dicom.OieDicomObject; import com.mirth.connect.donkey.model.message.MessageSerializerException; import com.mirth.connect.donkey.util.Base64Util; import com.mirth.connect.model.converters.DICOMConverter; @@ -30,7 +29,7 @@ private DICOMUtil() {} /** * Re-attaches DICOM attachments with the header data in the connector message and returns the * resulting merged data as a Base64-encoded string. - * + * * @param connectorMessage * The connector message to retrieve merged DICOM data for. * @return The merged DICOM data, Base64-encoded. @@ -42,7 +41,7 @@ public static String getDICOMRawData(ImmutableConnectorMessage connectorMessage) /** * Re-attaches DICOM attachments with the header data in the connector message and returns the * resulting merged data as a byte array. - * + * * @param connectorMessage * The connector message to retrieve merged DICOM data for. * @return The merged DICOM data as a byte array. @@ -54,7 +53,7 @@ public static byte[] getDICOMRawBytes(ImmutableConnectorMessage connectorMessage /** * Re-attaches DICOM attachments with the header data in the connector message and returns the * resulting merged data as a byte array. - * + * * @param connectorMessage * The connector message to retrieve merged DICOM data for. * @return The merged DICOM data as a byte array. @@ -66,7 +65,7 @@ public static byte[] getDICOMMessage(ImmutableConnectorMessage connectorMessage) /** * Re-attaches DICOM attachments with the header data in the connector message and returns the * resulting merged data as a Base-64 encoded String. - * + * * @param connectorMessage * The connector message containing header data to merge DICOM attachments with. * @param attachments @@ -84,7 +83,7 @@ public static String mergeHeaderAttachments(ImmutableConnectorMessage connectorM /** * Re-attaches DICOM attachments with the given header data and returns the resulting merged * data as a Base-64 encoded String. - * + * * @param header * The header data to merge DICOM attachments with. * @param images @@ -107,7 +106,7 @@ public static String mergeHeaderPixelData(byte[] header, List images) th /** * Returns the number of slices in the fully-merged DICOM data associated with a given connector * message. - * + * * @param connectorMessage * The connector message to retrieve DICOM data for. * @return The number of slices in the DICOM data. @@ -118,7 +117,7 @@ public static int getSliceCount(ImmutableConnectorMessage connectorMessage) { /** * Converts merged DICOM data associated with a connector message into a specified image format. - * + * * @param imageType * The image format to convert the DICOM data to (e.g. "jpg"). * @param connectorMessage @@ -133,7 +132,7 @@ public static String convertDICOM(String imageType, ImmutableConnectorMessage co /** * Converts merged DICOM data associated with a connector message into a specified image format. - * + * * @param imageType * The image format to convert the DICOM data to (e.g. "jpg"). * @param connectorMessage @@ -146,7 +145,7 @@ public static String convertDICOM(String imageType, ImmutableConnectorMessage co /** * Converts merged DICOM data associated with a connector message into a specified image format. - * + * * @param imageType * The image format to convert the DICOM data to (e.g. "jpg"). * @param connectorMessage @@ -162,7 +161,7 @@ public static String convertDICOM(String imageType, ImmutableConnectorMessage co /** * Converts merged DICOM data associated with a connector message into a specified image format. - * + * * @param imageType * The image format to convert the DICOM data to (e.g. "jpg"). * @param connectorMessage @@ -180,7 +179,7 @@ public static String convertDICOM(String imageType, ImmutableConnectorMessage co /** * Converts merged DICOM data associated with a connector message into a specified image format. - * + * * @param imageType * The image format to convert the DICOM data to (e.g. "jpg"). * @param connectorMessage @@ -193,7 +192,7 @@ public static byte[] convertDICOMToByteArray(String imageType, ImmutableConnecto /** * Converts merged DICOM data associated with a connector message into a specified image format. - * + * * @param imageType * The image format to convert the DICOM data to (e.g. "jpg"). * @param connectorMessage @@ -209,7 +208,7 @@ public static byte[] convertDICOMToByteArray(String imageType, ImmutableConnecto /** * Converts merged DICOM data associated with a connector message into a specified image format. - * + * * @param imageType * The image format to convert the DICOM data to (e.g. "jpg"). * @param connectorMessage @@ -226,30 +225,39 @@ public static byte[] convertDICOMToByteArray(String imageType, ImmutableConnecto } /** - * Converts a byte array into a dcm4che DicomObject. - * + * Converts a byte array into a version-neutral DICOM object wrapper. + * + *

The returned {@link OieDicomObject} provides common accessors such as + * {@code getString(int)}, {@code getString(int, String)}, and + * {@code getInt(int, int)}. If you need access to library-specific methods + * (e.g., dcm4che2 {@code DicomObject}), call {@link OieDicomObject#unwrap()} + * and cast: + *

{@code
+     * DicomObject dcm = (DicomObject) dicomObj.unwrap();
+     * }
+ * * @param bytes * The binary data to convert. * @param decodeBase64 * If true, the data is assumed to be Base64-encoded. - * @return The converted DicomObject. + * @return The converted OieDicomObject. * @throws IOException - * If Base64 encoding failed. + * If parsing fails. */ - public static DicomObject byteArrayToDicomObject(byte[] bytes, boolean decodeBase64) throws IOException { + public static OieDicomObject byteArrayToDicomObject(byte[] bytes, boolean decodeBase64) throws IOException { return DICOMConverter.byteArrayToDicomObject(bytes, decodeBase64); } /** - * Converts a dcm4che DicomObject into a byte array. - * + * Converts a DICOM object into a byte array. + * * @param dicomObject - * The DicomObject to convert. + * The OieDicomObject to convert. * @return The converted byte array. * @throws IOException - * If Base64 encoding failed. + * If serialization fails. */ - public static byte[] dicomObjectToByteArray(DicomObject dicomObject) throws IOException { + public static byte[] dicomObjectToByteArray(OieDicomObject dicomObject) throws IOException { return DICOMConverter.dicomObjectToByteArray(dicomObject); } } diff --git a/server/src/com/mirth/connect/server/util/DICOMMessageUtil.java b/server/src/com/mirth/connect/server/util/DICOMMessageUtil.java index 57b107840c..d1778743af 100644 --- a/server/src/com/mirth/connect/server/util/DICOMMessageUtil.java +++ b/server/src/com/mirth/connect/server/util/DICOMMessageUtil.java @@ -1,8 +1,8 @@ /* * Copyright (c) Mirth Corporation. All rights reserved. - * + * * http://www.mirthcorp.com - * + * * The software in this package is published under the terms of the MPL license a copy of which has * been included with this distribution in the LICENSE.txt file. */ @@ -31,11 +31,10 @@ import org.apache.commons.io.IOUtils; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; -import org.dcm4che2.data.DicomElement; -import org.dcm4che2.data.DicomObject; -import org.dcm4che2.data.Tag; -import org.dcm4che2.data.VR; +import com.mirth.connect.connectors.dimse.dicom.DicomConstants; +import com.mirth.connect.connectors.dimse.dicom.OieDicomElement; +import com.mirth.connect.connectors.dimse.dicom.OieDicomObject; import com.mirth.connect.donkey.model.message.ConnectorMessage; import com.mirth.connect.donkey.model.message.MessageSerializerException; import com.mirth.connect.donkey.model.message.attachment.Attachment; @@ -134,12 +133,12 @@ public static byte[] mergeHeaderAttachments(ImmutableConnectorMessage message, L public static byte[] mergeHeaderPixelData(byte[] header, List attachments) throws IOException { // 1. read in header - DicomObject dcmObj = DICOMConverter.byteArrayToDicomObject(header, false); + OieDicomObject dcmObj = DICOMConverter.byteArrayToDicomObject(header, false); // 2. Add pixel data to DicomObject if (attachments != null && !attachments.isEmpty()) { if (attachments.size() > 1) { - DicomElement dicomElement = dcmObj.putFragments(Tag.PixelData, VR.OB, dcmObj.bigEndian(), attachments.size()); + OieDicomElement dicomElement = dcmObj.putFragments(DicomConstants.TAG_PIXEL_DATA, DicomConstants.VR_OB, dcmObj.bigEndian(), attachments.size()); for (Attachment attachment : attachments) { dicomElement.addFragment(attachment.getContent()); @@ -147,12 +146,14 @@ public static byte[] mergeHeaderPixelData(byte[] header, List attach dcmObj.add(dicomElement); } else { - dcmObj.putBytes(Tag.PixelData, VR.OB, attachments.get(0).getContent()); + dcmObj.putBytes(DicomConstants.TAG_PIXEL_DATA, DicomConstants.VR_OB, attachments.get(0).getContent()); } } // Memory Optimization. Free the references to the data in the attachments list. - attachments.clear(); + if (attachments != null) { + attachments.clear(); + } return DICOMConverter.dicomObjectToByteArray(dcmObj); } diff --git a/server/src/org/dcm4che2/tool/dcmrcv/MirthDcmRcv.java b/server/src/org/dcm4che2/tool/dcmrcv/MirthDcmRcv.java index d7b390962a..649b65d10e 100644 --- a/server/src/org/dcm4che2/tool/dcmrcv/MirthDcmRcv.java +++ b/server/src/org/dcm4che2/tool/dcmrcv/MirthDcmRcv.java @@ -52,7 +52,11 @@ public NetworkConnection getNetworkConnection() { @Override protected NetworkConnection createNetworkConnection() { - return dicomConfiguration.createNetworkConnection(); + Object custom = dicomConfiguration.createNetworkConnection(); + if (custom instanceof NetworkConnection) { + return (NetworkConnection) custom; + } + return new NetworkConnection(); } @Override diff --git a/server/src/org/dcm4che2/tool/dcmsnd/MirthDcmSnd.java b/server/src/org/dcm4che2/tool/dcmsnd/MirthDcmSnd.java index 122acbd9a8..cd6908186a 100644 --- a/server/src/org/dcm4che2/tool/dcmsnd/MirthDcmSnd.java +++ b/server/src/org/dcm4che2/tool/dcmsnd/MirthDcmSnd.java @@ -41,7 +41,11 @@ public NetworkConnection getRemoteStgcmtNetworkConnection() { @Override protected NetworkConnection createNetworkConnection() { - return dicomConfiguration.createNetworkConnection(); + Object custom = dicomConfiguration.createNetworkConnection(); + if (custom instanceof NetworkConnection) { + return (NetworkConnection) custom; + } + return new NetworkConnection(); } @Override diff --git a/server/test/com/mirth/connect/connectors/dimse/DICOMDispatcherTest.java b/server/test/com/mirth/connect/connectors/dimse/DICOMDispatcherTest.java index 1869f38c06..17a3fbd587 100644 --- a/server/test/com/mirth/connect/connectors/dimse/DICOMDispatcherTest.java +++ b/server/test/com/mirth/connect/connectors/dimse/DICOMDispatcherTest.java @@ -1,24 +1,21 @@ package com.mirth.connect.connectors.dimse; import static org.junit.Assert.assertEquals; -import static org.mockito.Mockito.mock; import java.io.File; import java.io.IOException; +import java.util.Iterator; -import org.dcm4che2.data.BasicDicomObject; -import org.dcm4che2.data.DicomObject; -import org.dcm4che2.data.SequenceDicomElement; -import org.dcm4che2.data.Tag; -import org.dcm4che2.data.VR; -import org.dcm4che2.net.ConfigurationException; -import org.dcm4che2.net.NetworkConnection; -import org.dcm4che2.tool.dcmsnd.CustomDimseRSPHandler; -import org.dcm4che2.tool.dcmsnd.MirthDcmSnd; -import org.dcm4che2.util.StringUtils; import org.junit.Test; import com.mirth.connect.connectors.dimse.DICOMDispatcher.CommandDataDimseRSPHandler; +import com.mirth.connect.connectors.dimse.dicom.DicomConstants; +import com.mirth.connect.connectors.dimse.dicom.OieDicomElement; +import com.mirth.connect.connectors.dimse.dicom.OieDicomObject; +import com.mirth.connect.connectors.dimse.dicom.OieDicomSender; +import com.mirth.connect.connectors.dimse.dicom.OieDimseRspHandler; +import com.mirth.connect.connectors.dimse.dicom.DicomLibraryFactory; +import com.mirth.connect.connectors.dimse.dicom.OieDicomConverter; import com.mirth.connect.donkey.model.message.ConnectorMessage; import com.mirth.connect.donkey.model.message.Response; import com.mirth.connect.donkey.model.message.Status; @@ -32,7 +29,7 @@ public class DICOMDispatcherTest { @Test public void testSendWithStatusCodes() { - // send message using our custom MirthDcmSnd + // send message using our custom sender TestDICOMDispatcher dispatcher = new TestDICOMDispatcher(); dispatcher.configuration = new DefaultDICOMConfiguration(); DICOMDispatcherProperties props = new DICOMDispatcherProperties(); @@ -44,8 +41,8 @@ public void testSendWithStatusCodes() { Status status = null; String statusMessage = null; - TestMirthDcmSnd.setCommitSucceeded(true); - TestMirthDcmSnd.setCmdStatus(0); + TestDicomSender.setCommitSucceeded(true); + TestDicomSender.setCmdStatus(0); response = dispatcher.send(props, message); status = response.getStatus(); statusMessage = response.getStatusMessage(); @@ -55,39 +52,39 @@ public void testSendWithStatusCodes() { assertEquals("DICOM message successfully sent", statusMessage); // check with 0xB000 || 0xB006 || 0xB007 status - TestMirthDcmSnd.setCmdStatus(0xB000); + TestDicomSender.setCmdStatus(0xB000); response = dispatcher.send(props, message); status = response.getStatus(); statusMessage = response.getStatusMessage(); assertEquals(Status.SENT, status); - assertEquals("DICOM message successfully sent with warning status code: 0x" + StringUtils.shortToHex(0xB000), statusMessage); + assertEquals("DICOM message successfully sent with warning status code: 0x" + DicomConstants.shortToHex(0xB000), statusMessage); - TestMirthDcmSnd.setCmdStatus(0xB006); + TestDicomSender.setCmdStatus(0xB006); response = dispatcher.send(props, message); status = response.getStatus(); statusMessage = response.getStatusMessage(); assertEquals(Status.SENT, status); - assertEquals("DICOM message successfully sent with warning status code: 0x" + StringUtils.shortToHex(0xB006), statusMessage); + assertEquals("DICOM message successfully sent with warning status code: 0x" + DicomConstants.shortToHex(0xB006), statusMessage); - TestMirthDcmSnd.setCmdStatus(0xB007); + TestDicomSender.setCmdStatus(0xB007); response = dispatcher.send(props, message); status = response.getStatus(); statusMessage = response.getStatusMessage(); assertEquals(Status.SENT, status); - assertEquals("DICOM message successfully sent with warning status code: 0x" + StringUtils.shortToHex(0xB007), statusMessage); + assertEquals("DICOM message successfully sent with warning status code: 0x" + DicomConstants.shortToHex(0xB007), statusMessage); // check other status == QUEUED - TestMirthDcmSnd.setCmdStatus(0xB008); + TestDicomSender.setCmdStatus(0xB008); response = dispatcher.send(props, message); status = response.getStatus(); statusMessage = response.getStatusMessage(); assertEquals(Status.QUEUED, status); - assertEquals("Error status code received from DICOM server: 0x" + StringUtils.shortToHex(0xB008), statusMessage); + assertEquals("Error status code received from DICOM server: 0x" + DicomConstants.shortToHex(0xB008), statusMessage); } @Test public void testResponseData() throws DonkeyElementException { - // send message using our custom MirthDcmSnd + // send message using our custom sender TestDICOMDispatcher dispatcher = new TestDICOMDispatcher(); dispatcher.configuration = new DefaultDICOMConfiguration(); DICOMDispatcherProperties props = new DICOMDispatcherProperties(); @@ -95,8 +92,8 @@ public void testResponseData() throws DonkeyElementException { props.setPort("9000"); ConnectorMessage message = new ConnectorMessage(); - TestMirthDcmSnd.setCmdStatus(0); - TestMirthDcmSnd.setCommitSucceeded(true); + TestDicomSender.setCmdStatus(0); + TestDicomSender.setCommitSucceeded(true); Response response = dispatcher.send(props, message); String responseData = response.getMessage(); @@ -115,8 +112,8 @@ public void testStorageCommitment() throws Exception { props.setStgcmt(true); ConnectorMessage message = new ConnectorMessage(); - TestMirthDcmSnd.setCmdStatus(0); - TestMirthDcmSnd.setCommitSucceeded(false); + TestDicomSender.setCmdStatus(0); + TestDicomSender.setCommitSucceeded(false); Response response = null; Status status = null; @@ -130,9 +127,9 @@ public void testStorageCommitment() throws Exception { assertEquals("DICOM message successfully sent but Storage Commitment failed with reason: Unknown", statusMessage); // Test the case where the stgcmt request succeeds but contains failed SOP items - TestMirthDcmSnd.setCommitSucceeded(true); - TestMirthDcmSnd.setFailedSOP(true); - TestMirthDcmSnd.setFailureReason(1); + TestDicomSender.setCommitSucceeded(true); + TestDicomSender.setFailedSOP(true); + TestDicomSender.setFailureReason(1); response = dispatcher.send(props, message); status = response.getStatus(); @@ -141,11 +138,11 @@ public void testStorageCommitment() throws Exception { assertEquals(Status.QUEUED, status); assertEquals("DICOM message successfully sent but Storage Commitment failed with reason: 1", statusMessage); - TestMirthDcmSnd.setCommitSucceeded(false); - TestMirthDcmSnd.setFailedSOP(false); - TestMirthDcmSnd.setFailureReason(0); + TestDicomSender.setCommitSucceeded(false); + TestDicomSender.setFailedSOP(false); + TestDicomSender.setFailureReason(0); - // test that a failed storage commitment doesn't cause the message to fail + // test that a failed storage commitment doesn't cause the message to fail // if the dispatcher isn't configured to care props.setStgcmt(false); response = dispatcher.send(props, message); @@ -157,32 +154,32 @@ public void testStorageCommitment() throws Exception { // check with 0xB000 and requesting storage commitment props.setStgcmt(true); - TestMirthDcmSnd.setCmdStatus(0xB000); + TestDicomSender.setCmdStatus(0xB000); response = dispatcher.send(props, message); status = response.getStatus(); statusMessage = response.getStatusMessage(); assertEquals(Status.QUEUED, status); - String expectedMessage = "DICOM message successfully sent with warning status code: 0x" + StringUtils.shortToHex(0xB000) + " but Storage Commitment failed with reason: Unknown"; + String expectedMessage = "DICOM message successfully sent with warning status code: 0x" + DicomConstants.shortToHex(0xB000) + " but Storage Commitment failed with reason: Unknown"; assertEquals(expectedMessage, statusMessage); // check other status and requesting storage commitment - TestMirthDcmSnd.setCmdStatus(0xB008); + TestDicomSender.setCmdStatus(0xB008); response = dispatcher.send(props, message); status = response.getStatus(); statusMessage = response.getStatusMessage(); assertEquals(Status.QUEUED, status); - assertEquals("Error status code received from DICOM server: 0x" + StringUtils.shortToHex(0xB008), statusMessage); + assertEquals("Error status code received from DICOM server: 0x" + DicomConstants.shortToHex(0xB008), statusMessage); } - private static class TestMirthDcmSnd extends MirthDcmSnd { + /** + * Test OieDicomSender that stubs out all network operations. + */ + private static class TestDicomSender implements OieDicomSender { private static int cmdStatus; private static boolean commitSucceeded = true; private static boolean failedSOP = false; private static int failureReason = 0; - - public TestMirthDcmSnd(DICOMConfiguration configuration) { - super(configuration); - } + private boolean storageCommitment = false; public static void setCmdStatus(int status) { cmdStatus = status; @@ -193,69 +190,85 @@ public static void setCommitSucceeded(boolean succeeded) { } public static void setFailedSOP(boolean failedSOP) { - TestMirthDcmSnd.failedSOP = failedSOP; + TestDicomSender.failedSOP = failedSOP; } public static void setFailureReason(int failureReason) { - TestMirthDcmSnd.failureReason = failureReason; - } - - @Override - protected void init() { - conn = createNetworkConnection(); - remoteConn = createNetworkConnection(); + TestDicomSender.failureReason = failureReason; } @Override - public void start() throws IOException {} - - @Override - public void open() throws IOException, ConfigurationException, InterruptedException {} - - @Override - public void close() {} - - @Override - public void stop() {} - - @Override - public void addFile(File f) {} - - @Override - public void send(CustomDimseRSPHandler responseHandler) { - CommandDataDimseRSPHandler handler = (CommandDataDimseRSPHandler) responseHandler; - BasicDicomObject cmd = new BasicDicomObject(); - cmd.putInt(Tag.Status, VR.IS, cmdStatus); - handler.onDimseRSP(null, cmd, null); + public void send(OieDimseRspHandler handler) { + OieDicomConverter converter = DicomLibraryFactory.getConverter(); + OieDicomObject cmd = converter.createDicomObject(); + cmd.putInt(DicomConstants.TAG_STATUS, DicomConstants.VR_IS, cmdStatus); + handler.onDimseRSP(cmd, null); } @Override - public synchronized DicomObject waitForStgCmtResult() throws InterruptedException { - BasicDicomObject rsp = new BasicDicomObject(); + public OieDicomObject waitForStgCmtResult() throws InterruptedException { + OieDicomConverter converter = DicomLibraryFactory.getConverter(); + OieDicomObject rsp = converter.createDicomObject(); if (failedSOP) { - SequenceDicomElement failedSOPSq = (SequenceDicomElement) rsp.putSequence(Tag.FailedSOPSequence); - BasicDicomObject failedSOPItem = new BasicDicomObject(); - failedSOPItem.putInt(Tag.FailureReason, VR.IS, failureReason); + OieDicomElement failedSOPSq = rsp.putSequence(DicomConstants.TAG_FAILED_SOP_SEQUENCE); + OieDicomObject failedSOPItem = converter.createDicomObject(); + failedSOPItem.putInt(DicomConstants.TAG_FAILURE_REASON, DicomConstants.VR_IS, failureReason); failedSOPSq.addDicomObject(failedSOPItem); } return rsp; } - @Override - protected NetworkConnection createNetworkConnection() { - return mock(NetworkConnection.class); - } - - @Override - public boolean commit() { - return commitSucceeded; - } + @Override public boolean commit() { return commitSucceeded; } + @Override public boolean isStorageCommitment() { return storageCommitment; } + @Override public void setCalledAET(String aet) {} + @Override public void setRemoteHost(String host) {} + @Override public void setRemotePort(int port) {} + @Override public void setCalling(String aet) {} + @Override public void setLocalHost(String host) {} + @Override public void setLocalPort(int port) {} + @Override public void addFile(File file) {} + @Override public void setAcceptTimeout(int timeout) {} + @Override public void setMaxOpsInvoked(int maxOps) {} + @Override public void setTranscoderBufferSize(int size) {} + @Override public void setConnectTimeout(int timeout) {} + @Override public void setPriority(int priority) {} + @Override public void setPackPDV(boolean packPDV) {} + @Override public void setMaxPDULengthReceive(int length) {} + @Override public void setMaxPDULengthSend(int length) {} + @Override public void setReceiveBufferSize(int size) {} + @Override public void setSendBufferSize(int size) {} + @Override public void setAssociationReaperPeriod(int period) {} + @Override public void setReleaseTimeout(int timeout) {} + @Override public void setDimseRspTimeout(int timeout) {} + @Override public void setShutdownDelay(int delay) {} + @Override public void setSocketCloseDelay(int delay) {} + @Override public void setTcpNoDelay(boolean tcpNoDelay) {} + @Override public void setOfferDefaultTransferSyntaxInSeparatePresentationContext(boolean ts1) {} + @Override public void setStorageCommitment(boolean stgcmt) { this.storageCommitment = stgcmt; } + @Override public void setUserIdentity(String username, String passcode, boolean positiveResponseRequested) {} + @Override public void setTlsWithoutEncryption() {} + @Override public void setTls3DES_EDE_CBC() {} + @Override public void setTlsAES_128_CBC() {} + @Override public void setTrustStoreURL(String url) {} + @Override public void setTrustStorePassword(String password) {} + @Override public void setKeyPassword(String password) {} + @Override public void setKeyStoreURL(String url) {} + @Override public void setKeyStorePassword(String password) {} + @Override public void setTlsNeedClientAuth(boolean needClientAuth) {} + @Override public void setTlsProtocol(String[] protocols) {} + @Override public void initTLS() {} + @Override public void configureTransferCapability() {} + @Override public void start() {} + @Override public void open() {} + @Override public void close() {} + @Override public void stop() {} + @Override public Object unwrap() { return null; } } private class TestDICOMDispatcher extends DICOMDispatcher { @Override - protected MirthDcmSnd getDcmSnd(DICOMConfiguration configuration) { - return new TestMirthDcmSnd(configuration); + protected OieDicomSender createDicomSender(DICOMConfiguration configuration) { + return new TestDicomSender(); } @Override diff --git a/server/test/com/mirth/connect/connectors/dimse/DICOMReceiverTest.java b/server/test/com/mirth/connect/connectors/dimse/DICOMReceiverTest.java new file mode 100644 index 0000000000..359239d59f --- /dev/null +++ b/server/test/com/mirth/connect/connectors/dimse/DICOMReceiverTest.java @@ -0,0 +1,186 @@ +package com.mirth.connect.connectors.dimse; + +import static org.junit.Assert.assertArrayEquals; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +import java.util.List; + +import org.junit.Test; + +import com.mirth.connect.client.core.ControllerException; +import com.mirth.connect.connectors.dimse.dicom.OieDicomReceiver; +import com.mirth.connect.donkey.model.event.Event; +import com.mirth.connect.donkey.server.channel.Channel; +import com.mirth.connect.model.ServerEvent; +import com.mirth.connect.model.filters.EventFilter; +import com.mirth.connect.server.controllers.EventController; +import com.mirth.connect.server.event.EventListener; + +public class DICOMReceiverTest { + + @Test + public void testOnStartSetsPort() throws Exception { + TestDicomReceiver stub = new TestDicomReceiver(); + TestDICOMReceiver receiver = createTestReceiver(stub); + receiver.connectorProperties.getListenerConnectorProperties().setPort("1234"); + + receiver.onStart(); + + assertEquals(1234, stub.port); + } + + @Test + public void testOnStartSetsHostname() throws Exception { + TestDicomReceiver stub = new TestDicomReceiver(); + TestDICOMReceiver receiver = createTestReceiver(stub); + receiver.connectorProperties.getListenerConnectorProperties().setHost("192.168.1.100"); + + receiver.onStart(); + + assertEquals("192.168.1.100", stub.hostname); + } + + @Test + public void testOnStartSetsAETitle() throws Exception { + TestDicomReceiver stub = new TestDicomReceiver(); + TestDICOMReceiver receiver = createTestReceiver(stub); + receiver.connectorProperties.setDest("MY_AE_TITLE"); + + receiver.onStart(); + + assertEquals("MY_AE_TITLE", stub.destination); + } + + @Test + public void testOnStartTransferSyntax() throws Exception { + TestDicomReceiver stub = new TestDicomReceiver(); + TestDICOMReceiver receiver = createTestReceiver(stub); + receiver.connectorProperties.setDefts(true); + + receiver.onStart(); + + assertArrayEquals(new String[] { "1.2.840.10008.1.2" }, stub.transferSyntax); + } + + @Test + public void testOnStartCallsStart() throws Exception { + TestDicomReceiver stub = new TestDicomReceiver(); + TestDICOMReceiver receiver = createTestReceiver(stub); + + receiver.onStart(); + + assertTrue("start() should have been called", stub.started); + } + + @Test + public void testOnStopCallsStop() throws Exception { + TestDicomReceiver stub = new TestDicomReceiver(); + TestDICOMReceiver receiver = createTestReceiver(stub); + + receiver.onStop(); + + assertTrue("stop() should have been called", stub.stopped); + } + + private TestDICOMReceiver createTestReceiver(TestDicomReceiver stub) { + TestDICOMReceiver receiver = new TestDICOMReceiver(stub); + receiver.connectorProperties = new DICOMReceiverProperties(); + receiver.dicomReceiver = stub; + return receiver; + } + + /** + * Stub OieDicomReceiver that captures setter calls for assertions. + */ + private static class TestDicomReceiver implements OieDicomReceiver { + int port; + String hostname; + String destination; + String[] transferSyntax; + String aeTitle; + boolean started; + boolean stopped; + + @Override public void setPort(int port) { this.port = port; } + @Override public void setHostname(String hostname) { this.hostname = hostname; } + @Override public void setDestination(String destination) { this.destination = destination; } + @Override public void setTransferSyntax(String[] transferSyntax) { this.transferSyntax = transferSyntax; } + @Override public void setAEtitle(String aeTitle) { this.aeTitle = aeTitle; } + @Override public void setAssociationReaperPeriod(int period) {} + @Override public void setIdleTimeout(int timeout) {} + @Override public void setRequestTimeout(int timeout) {} + @Override public void setReleaseTimeout(int timeout) {} + @Override public void setSocketCloseDelay(int delay) {} + @Override public void setDimseRspDelay(int delay) {} + @Override public void setMaxPDULengthReceive(int length) {} + @Override public void setMaxPDULengthSend(int length) {} + @Override public void setSendBufferSize(int size) {} + @Override public void setReceiveBufferSize(int size) {} + @Override public void setFileBufferSize(int size) {} + @Override public void setPackPDV(boolean packPDV) {} + @Override public void setTcpNoDelay(boolean tcpNoDelay) {} + @Override public void setMaxOpsPerformed(int maxOps) {} + @Override public void setTlsWithoutEncryption() {} + @Override public void setTls3DES_EDE_CBC() {} + @Override public void setTlsAES_128_CBC() {} + @Override public void setTrustStoreURL(String url) {} + @Override public void setTrustStorePassword(String password) {} + @Override public void setKeyPassword(String password) {} + @Override public void setKeyStoreURL(String url) {} + @Override public void setKeyStorePassword(String password) {} + @Override public void setTlsNeedClientAuth(boolean needClientAuth) {} + @Override public void setTlsProtocol(String[] protocols) {} + @Override public void initTLS() {} + @Override public void initTransferCapability() {} + @Override public void start() { this.started = true; } + @Override public void stop() { this.stopped = true; } + @Override public Object unwrap() { return null; } + } + + /** + * Test subclass of DICOMReceiver that bypasses deployment and infrastructure + * dependencies. Sets up a no-op EventController and DICOMConfiguration, and + * provides a fake Channel for template value replacement. + */ + private static class TestDICOMReceiver extends DICOMReceiver { + private final OieDicomReceiver stubReceiver; + + TestDICOMReceiver(OieDicomReceiver stubReceiver) { + this.stubReceiver = stubReceiver; + this.configuration = new DefaultDICOMConfiguration() { + @Override + public void configureConnectorDeploy(com.mirth.connect.donkey.server.channel.Connector connector) {} + + @Override + public void configureReceiver(OieDicomReceiver receiver, DICOMReceiver connector, DICOMReceiverProperties connectorProperties) {} + }; + this.eventController = new NoOpEventController(); + + // Set up a minimal Channel so getChannel().getName() works in onStart + Channel ch = new Channel(); + ch.setName("testChannel"); + this.channel = ch; + setChannelId("testChannelId"); + } + + @Override + protected OieDicomReceiver createDicomReceiver(DICOMConfiguration configuration) { + return stubReceiver; + } + } + + private static class NoOpEventController extends EventController { + @Override public void addListener(EventListener listener) {} + @Override public void removeListener(EventListener listener) {} + @Override public void dispatchEvent(Event event) {} + @Override public void insertEvent(ServerEvent serverEvent) {} + @Override public Integer getMaxEventId() throws ControllerException { return 0; } + @Override public List getEvents(EventFilter filter, Integer offset, Integer limit) throws ControllerException { return null; } + @Override public Long getEventCount(EventFilter filter) throws ControllerException { return 0L; } + @Override public void removeAllEvents() {} + @Override public String exportAllEvents() { return null; } + @Override public String exportAndRemoveAllEvents() { return null; } + @Override public List getEventsByAsc(EventFilter filter, Integer offset, Integer limit) throws ControllerException { return null; } + } +} diff --git a/server/test/com/mirth/connect/connectors/dimse/dicom/DicomLibraryFactoryTest.java b/server/test/com/mirth/connect/connectors/dimse/dicom/DicomLibraryFactoryTest.java new file mode 100644 index 0000000000..8d3983ea08 --- /dev/null +++ b/server/test/com/mirth/connect/connectors/dimse/dicom/DicomLibraryFactoryTest.java @@ -0,0 +1,118 @@ +package com.mirth.connect.connectors.dimse.dicom; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertSame; +import static org.junit.Assert.assertTrue; + +import org.junit.After; +import org.junit.Test; + +import com.mirth.connect.connectors.dimse.DICOMConfiguration; +import com.mirth.connect.connectors.dimse.dicom.DicomLibraryFactory.DicomLibrary; + +public class DicomLibraryFactoryTest { + + @After + public void resetFactory() { + DicomLibraryFactory.resetForTesting(null); + } + + @Test + public void testDefaultLibraryIsDcm4che2() { + DicomLibraryFactory.resetForTesting(DicomLibrary.DCM4CHE2); + assertEquals(DicomLibrary.DCM4CHE2, DicomLibraryFactory.getActiveLibrary()); + } + + @Test + public void testGetConverterReturnsSingleton() { + DicomLibraryFactory.resetForTesting(DicomLibrary.DCM4CHE2); + OieDicomConverter c1 = DicomLibraryFactory.getConverter(); + OieDicomConverter c2 = DicomLibraryFactory.getConverter(); + assertNotNull(c1); + assertSame(c1, c2); + } + + @Test + public void testCreateSenderReturnsNonNull() { + DicomLibraryFactory.resetForTesting(DicomLibrary.DCM4CHE2); + // Use a null-safe test configuration + OieDicomSender sender = DicomLibraryFactory.createSender(new TestDICOMConfiguration()); + assertNotNull(sender); + } + + @Test + public void testLoadConfigurationWithNullReturnsDefault() { + DicomLibraryFactory.resetForTesting(DicomLibrary.DCM4CHE2); + DICOMConfiguration config = DicomLibraryFactory.loadConfiguration(null); + assertNotNull(config); + } + + @Test + public void testLoadConfigurationWithEmptyReturnsDefault() { + DicomLibraryFactory.resetForTesting(DicomLibrary.DCM4CHE2); + DICOMConfiguration config = DicomLibraryFactory.loadConfiguration(" "); + assertNotNull(config); + } + + @Test + public void testLoadConfigurationWithInvalidClassReturnsDefault() { + DicomLibraryFactory.resetForTesting(DicomLibrary.DCM4CHE2); + DICOMConfiguration config = DicomLibraryFactory.loadConfiguration("com.nonexistent.FakeClass"); + assertNotNull(config); + } + + @Test + public void testDcm5ConverterCreation() { + DicomLibraryFactory.resetForTesting(DicomLibrary.DCM4CHE5); + OieDicomConverter converter = DicomLibraryFactory.getConverter(); + assertNotNull(converter); + assertEquals("Dcm5DicomConverter", converter.getClass().getSimpleName()); + } + + @Test + public void testDcm5SenderCreation() { + DicomLibraryFactory.resetForTesting(DicomLibrary.DCM4CHE5); + OieDicomSender sender = DicomLibraryFactory.createSender(new TestDICOMConfiguration()); + assertNotNull(sender); + assertEquals("Dcm5DicomSender", sender.getClass().getSimpleName()); + } + + @Test + public void testDcm5ReceiverCreation() { + DicomLibraryFactory.resetForTesting(DicomLibrary.DCM4CHE5); + OieDicomReceiver receiver = DicomLibraryFactory.createReceiver( + org.mockito.Mockito.mock(com.mirth.connect.donkey.server.channel.SourceConnector.class), + new TestDICOMConfiguration()); + assertNotNull(receiver); + assertEquals("Dcm5DicomReceiver", receiver.getClass().getSimpleName()); + } + + @Test + public void testDcm5ConverterSingleton() { + DicomLibraryFactory.resetForTesting(DicomLibrary.DCM4CHE5); + OieDicomConverter c1 = DicomLibraryFactory.getConverter(); + OieDicomConverter c2 = DicomLibraryFactory.getConverter(); + assertSame(c1, c2); + } + + /** + * Minimal DICOMConfiguration for testing — avoids ControllerFactory dependencies. + */ + private static class TestDICOMConfiguration implements DICOMConfiguration { + @Override + public void configureConnectorDeploy(com.mirth.connect.donkey.server.channel.Connector connector) {} + @Override + public void configureReceiver(OieDicomReceiver receiver, + com.mirth.connect.connectors.dimse.DICOMReceiver connector, + com.mirth.connect.connectors.dimse.DICOMReceiverProperties connectorProperties) {} + @Override + public void configureSender(OieDicomSender sender, + com.mirth.connect.connectors.dimse.DICOMDispatcher connector, + com.mirth.connect.connectors.dimse.DICOMDispatcherProperties connectorProperties) {} + @Override + public java.util.Map getCStoreRequestInformation(Object association) { + return new java.util.HashMap<>(); + } + } +} diff --git a/server/test/com/mirth/connect/connectors/dimse/dicom/GenerateDicomTestFiles.java b/server/test/com/mirth/connect/connectors/dimse/dicom/GenerateDicomTestFiles.java new file mode 100644 index 0000000000..9b4150789b --- /dev/null +++ b/server/test/com/mirth/connect/connectors/dimse/dicom/GenerateDicomTestFiles.java @@ -0,0 +1,117 @@ +package com.mirth.connect.connectors.dimse.dicom; + +import java.io.File; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; + +import org.dcm4che3.data.Tag; +import org.dcm4che3.util.UIDUtils; +import org.junit.Test; + +import com.mirth.connect.connectors.dimse.dicom.DicomLibraryFactory.DicomLibrary; +import com.mirth.connect.connectors.dimse.dicom.dcm5.Dcm5DicomConverter; +import com.mirth.connect.connectors.dimse.dicom.dcm5.Dcm5DicomObject; + +/** + * Generates proper DICOM Part 10 test files for manual testing with storescu. + * Run with: ./gradlew :server:test --tests "com.mirth.connect.connectors.dimse.dicom.GenerateDicomTestFiles" + */ +public class GenerateDicomTestFiles { + + private static final String OUTPUT_DIR = "tests"; + + // SOP Class UIDs + private static final String CT_IMAGE_STORAGE = "1.2.840.10008.5.1.4.1.1.2"; + private static final String MR_IMAGE_STORAGE = "1.2.840.10008.5.1.4.1.1.4"; + private static final String US_IMAGE_STORAGE = "1.2.840.10008.5.1.4.1.1.6.1"; + + // Transfer Syntax + private static final String IMPLICIT_VR_LE = "1.2.840.10008.1.2"; + + @Test + public void generateTestFiles() throws Exception { + DicomLibraryFactory.resetForTesting(DicomLibrary.DCM4CHE5); + try { + Path outputDir = Paths.get(OUTPUT_DIR); + Files.createDirectories(outputDir); + + createCtFile(outputDir); + createMrFile(outputDir); + createUsFile(outputDir); + + System.out.println("DICOM Part 10 test files generated in: " + outputDir.toAbsolutePath()); + } finally { + DicomLibraryFactory.resetForTesting(null); + } + } + + private void createCtFile(Path outputDir) throws IOException { + Dcm5DicomConverter converter = new Dcm5DicomConverter(); + Dcm5DicomObject obj = (Dcm5DicomObject) converter.createDicomObject(); + + obj.putString(Tag.PatientName, "PN", "Doe^John"); + obj.putString(Tag.PatientID, "LO", "PAT001"); + obj.putString(Tag.PatientBirthDate, "DA", "19800101"); + obj.putString(Tag.PatientSex, "CS", "M"); + obj.putString(Tag.Modality, "CS", "CT"); + obj.putString(Tag.StudyDate, "DA", "20230101"); + obj.putString(Tag.StudyTime, "TM", "120000"); + obj.putString(Tag.SpecificCharacterSet, "CS", "ISO_IR 100"); + obj.putString(Tag.StudyInstanceUID, "UI", UIDUtils.createUID()); + obj.putString(Tag.SeriesInstanceUID, "UI", UIDUtils.createUID()); + obj.putString(Tag.SOPInstanceUID, "UI", UIDUtils.createUID()); + obj.putString(Tag.SOPClassUID, "UI", CT_IMAGE_STORAGE); + + obj.initFileMetaInformation(CT_IMAGE_STORAGE, UIDUtils.createUID(), IMPLICIT_VR_LE); + + byte[] bytes = converter.dicomObjectToByteArray(obj); + Path file = outputDir.resolve("test-dicom-input-1.dcm"); + Files.write(file, bytes); + System.out.println("Created: " + file + " (" + bytes.length + " bytes) - CT/Doe^John/PAT001"); + } + + private void createMrFile(Path outputDir) throws IOException { + Dcm5DicomConverter converter = new Dcm5DicomConverter(); + Dcm5DicomObject obj = (Dcm5DicomObject) converter.createDicomObject(); + + obj.putString(Tag.PatientName, "PN", "Smith^Jane"); + obj.putString(Tag.PatientID, "LO", "PAT002"); + obj.putString(Tag.PatientSex, "CS", "F"); + obj.putString(Tag.Modality, "CS", "MR"); + obj.putString(Tag.StudyDate, "DA", "20230215"); + obj.putString(Tag.SpecificCharacterSet, "CS", "ISO_IR 100"); + obj.putString(Tag.StudyInstanceUID, "UI", UIDUtils.createUID()); + obj.putString(Tag.SeriesInstanceUID, "UI", UIDUtils.createUID()); + obj.putString(Tag.SOPInstanceUID, "UI", UIDUtils.createUID()); + obj.putString(Tag.SOPClassUID, "UI", MR_IMAGE_STORAGE); + + obj.initFileMetaInformation(MR_IMAGE_STORAGE, UIDUtils.createUID(), IMPLICIT_VR_LE); + + byte[] bytes = converter.dicomObjectToByteArray(obj); + Path file = outputDir.resolve("test-dicom-input-2.dcm"); + Files.write(file, bytes); + System.out.println("Created: " + file + " (" + bytes.length + " bytes) - MR/Smith^Jane/PAT002"); + } + + private void createUsFile(Path outputDir) throws IOException { + Dcm5DicomConverter converter = new Dcm5DicomConverter(); + Dcm5DicomObject obj = (Dcm5DicomObject) converter.createDicomObject(); + + obj.putString(Tag.PatientName, "PN", "Brown^Bob"); + obj.putString(Tag.PatientID, "LO", "PAT003"); + obj.putString(Tag.Modality, "CS", "US"); + obj.putString(Tag.StudyInstanceUID, "UI", UIDUtils.createUID()); + obj.putString(Tag.SeriesInstanceUID, "UI", UIDUtils.createUID()); + obj.putString(Tag.SOPInstanceUID, "UI", UIDUtils.createUID()); + obj.putString(Tag.SOPClassUID, "UI", US_IMAGE_STORAGE); + + obj.initFileMetaInformation(US_IMAGE_STORAGE, UIDUtils.createUID(), IMPLICIT_VR_LE); + + byte[] bytes = converter.dicomObjectToByteArray(obj); + Path file = outputDir.resolve("test-dicom-input-3.dcm"); + Files.write(file, bytes); + System.out.println("Created: " + file + " (" + bytes.length + " bytes) - US/Brown^Bob/PAT003"); + } +} diff --git a/server/test/com/mirth/connect/connectors/dimse/dicom/dcm2/Dcm2DICOMConfigurationTest.java b/server/test/com/mirth/connect/connectors/dimse/dicom/dcm2/Dcm2DICOMConfigurationTest.java new file mode 100644 index 0000000000..453a14306f --- /dev/null +++ b/server/test/com/mirth/connect/connectors/dimse/dicom/dcm2/Dcm2DICOMConfigurationTest.java @@ -0,0 +1,109 @@ +package com.mirth.connect.connectors.dimse.dicom.dcm2; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +import java.util.HashMap; +import java.util.Map; + +import org.dcm4che2.net.Association; +import org.dcm4che2.net.NetworkConnection; +import org.dcm4che2.tool.dcmrcv.MirthDcmRcv; +import org.dcm4che2.tool.dcmsnd.MirthDcmSnd; +import org.junit.Test; + +import com.mirth.connect.connectors.dimse.DICOMDispatcher; +import com.mirth.connect.connectors.dimse.DICOMDispatcherProperties; +import com.mirth.connect.connectors.dimse.DICOMReceiver; +import com.mirth.connect.connectors.dimse.DICOMReceiverProperties; +import com.mirth.connect.connectors.dimse.dicom.OieDicomReceiver; +import com.mirth.connect.connectors.dimse.dicom.OieDicomSender; +import com.mirth.connect.donkey.server.channel.Connector; + +/** + * Tests that the Dcm2DICOMConfiguration bridge defaults correctly delegate + * version-neutral calls to the legacy dcm4che2-typed methods. + */ +public class Dcm2DICOMConfigurationTest { + + @Test + public void testConfigureReceiverBridgesToConfigureDcmRcv() throws Exception { + BridgeTrackingConfig config = new BridgeTrackingConfig(); + + // Use a real Dcm2DicomReceiver wrapping a real MirthDcmRcv. + // The Dcm2DICOMConfiguration default configureReceiver calls unwrap() and casts. + MirthDcmRcv realRcv = new MirthDcmRcv(null, config); + Dcm2DicomReceiver receiver = new Dcm2DicomReceiver(realRcv); + + // Call configureReceiver — this uses the Dcm2DICOMConfiguration default bridge: + // configureReceiver → (MirthDcmRcv) receiver.unwrap() → configureDcmRcv + config.configureReceiver(receiver, null, null); + assertTrue("configureDcmRcv should have been called via bridge default", config.configureDcmRcvCalled); + } + + @Test + public void testConfigureSenderBridgesToConfigureDcmSnd() throws Exception { + BridgeTrackingConfig config = new BridgeTrackingConfig(); + + MirthDcmSnd realSnd = new MirthDcmSnd(config); + Dcm2DicomSender sender = new Dcm2DicomSender(realSnd); + + // Call configureSender — uses the Dcm2DICOMConfiguration default bridge: + // configureSender → (MirthDcmSnd) sender.unwrap() → configureDcmSnd + config.configureSender(sender, null, null); + assertTrue("configureDcmSnd should have been called via bridge default", config.configureDcmSndCalled); + } + + @Test + public void testGetCStoreRequestInfoBridgesToAssociationOverload() { + BridgeTrackingConfig config = new BridgeTrackingConfig(); + Map result = config.getCStoreRequestInformation((Object) null); + assertNotNull(result); + assertTrue("getCStoreRequestInformation(Association) should have been called", + config.getCStoreRequestInfoCalled); + } + + @Test + public void testCreateNetworkConnectionBridgesToLegacy() { + BridgeTrackingConfig config = new BridgeTrackingConfig(); + Object nc = config.createNetworkConnection(); + assertNotNull(nc); + assertTrue(nc instanceof NetworkConnection); + assertTrue("createLegacyNetworkConnection should have been called", + config.createLegacyNetworkConnectionCalled); + } + + /** + * Tracks all bridge paths. Does NOT override configureReceiver/configureSender, + * so the Dcm2DICOMConfiguration interface defaults (the real bridge logic) are exercised. + */ + private static class BridgeTrackingConfig implements Dcm2DICOMConfiguration { + boolean configureDcmRcvCalled = false; + boolean configureDcmSndCalled = false; + boolean getCStoreRequestInfoCalled = false; + boolean createLegacyNetworkConnectionCalled = false; + + @Override + public void configureConnectorDeploy(Connector connector) {} + @Override + public void configureDcmRcv(MirthDcmRcv dcmrcv, DICOMReceiver connector, DICOMReceiverProperties props) { + configureDcmRcvCalled = true; + } + @Override + public void configureDcmSnd(MirthDcmSnd dcmsnd, DICOMDispatcher connector, DICOMDispatcherProperties props) { + configureDcmSndCalled = true; + } + @Override + public Map getCStoreRequestInformation(Association association) { + getCStoreRequestInfoCalled = true; + return new HashMap<>(); + } + @Override + public NetworkConnection createLegacyNetworkConnection() { + createLegacyNetworkConnectionCalled = true; + return new NetworkConnection(); + } + } + +} diff --git a/server/test/com/mirth/connect/connectors/dimse/dicom/dcm5/Dcm5DICOMConfigurationTest.java b/server/test/com/mirth/connect/connectors/dimse/dicom/dcm5/Dcm5DICOMConfigurationTest.java new file mode 100644 index 0000000000..2ef9efa60a --- /dev/null +++ b/server/test/com/mirth/connect/connectors/dimse/dicom/dcm5/Dcm5DICOMConfigurationTest.java @@ -0,0 +1,77 @@ +package com.mirth.connect.connectors.dimse.dicom.dcm5; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +import java.util.HashMap; +import java.util.Map; + +import org.dcm4che3.net.Association; +import org.dcm4che3.net.Connection; +import org.junit.Test; + +import com.mirth.connect.connectors.dimse.DICOMConfiguration; +import com.mirth.connect.connectors.dimse.DICOMDispatcher; +import com.mirth.connect.connectors.dimse.DICOMDispatcherProperties; +import com.mirth.connect.connectors.dimse.DICOMReceiver; +import com.mirth.connect.connectors.dimse.DICOMReceiverProperties; +import com.mirth.connect.connectors.dimse.dicom.OieDicomReceiver; +import com.mirth.connect.connectors.dimse.dicom.OieDicomSender; +import com.mirth.connect.donkey.server.channel.Connector; + +public class Dcm5DICOMConfigurationTest { + + @Test + public void testGetCStoreRequestInfoBridgesToAssociationOverload() { + final boolean[] called = { false }; + Dcm5DICOMConfiguration config = new TestDcm5Config() { + @Override + public Map getCStoreRequestInformation(Association association) { + called[0] = true; + return new HashMap<>(); + } + }; + + config.getCStoreRequestInformation((Object) null); + assertTrue("bridge did not delegate to Association overload", called[0]); + } + + @Test + public void testCreateNetworkConnectionBridgesToDcm5Connection() { + Dcm5DICOMConfiguration config = new TestDcm5Config(); + Object conn = config.createNetworkConnection(); + assertNotNull(conn); + assertTrue(conn instanceof Connection); + } + + @Test + public void testImplementsDICOMConfiguration() { + Dcm5DICOMConfiguration config = new TestDcm5Config(); + assertTrue(config instanceof DICOMConfiguration); + } + + /** Minimal test implementation of Dcm5DICOMConfiguration. */ + private static class TestDcm5Config implements Dcm5DICOMConfiguration { + @Override + public void configureConnectorDeploy(Connector connector) {} + + @Override + public void configureDcm5Receiver(Dcm5DicomReceiver receiver, DICOMReceiver connector, + DICOMReceiverProperties connectorProperties) {} + + @Override + public void configureDcm5Sender(Dcm5DicomSender sender, DICOMDispatcher connector, + DICOMDispatcherProperties connectorProperties) {} + + @Override + public Map getCStoreRequestInformation(Association association) { + return new HashMap<>(); + } + + @Override + public Connection createDcm5Connection() { + return new Connection(); + } + } +} diff --git a/server/test/com/mirth/connect/connectors/dimse/dicom/dcm5/Dcm5DicomConverterTest.java b/server/test/com/mirth/connect/connectors/dimse/dicom/dcm5/Dcm5DicomConverterTest.java new file mode 100644 index 0000000000..baf81920da --- /dev/null +++ b/server/test/com/mirth/connect/connectors/dimse/dicom/dcm5/Dcm5DicomConverterTest.java @@ -0,0 +1,156 @@ +package com.mirth.connect.connectors.dimse.dicom.dcm5; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + +import java.io.ByteArrayOutputStream; +import java.nio.charset.StandardCharsets; +import java.util.Base64; + +import org.dcm4che3.data.Attributes; +import org.dcm4che3.data.Tag; +import org.dcm4che3.data.UID; +import org.dcm4che3.data.VR; +import org.dcm4che3.io.DicomOutputStream; +import org.junit.Test; + +import com.mirth.connect.connectors.dimse.dicom.OieDicomObject; + +public class Dcm5DicomConverterTest { + + private final Dcm5DicomConverter converter = new Dcm5DicomConverter(); + + @Test + public void testByteArrayRoundTripWithoutFmi() throws Exception { + Dcm5DicomObject original = new Dcm5DicomObject(); + original.putString(Tag.PatientName, "PN", "Test^Patient"); + original.putString(Tag.PatientID, "LO", "12345"); + + byte[] bytes = converter.dicomObjectToByteArray(original); + assertNotNull(bytes); + assertTrue(bytes.length > 0); + + OieDicomObject parsed = converter.byteArrayToDicomObject(bytes, false); + assertNotNull(parsed); + assertEquals("Test^Patient", parsed.getString(Tag.PatientName)); + assertEquals("12345", parsed.getString(Tag.PatientID)); + } + + @Test + public void testByteArrayRoundTripWithFmi() throws Exception { + Dcm5DicomObject original = new Dcm5DicomObject(); + original.putString(Tag.PatientName, "PN", "FmiTest"); + original.initFileMetaInformation("1.2.840.10008.5.1.4.1.1.2", "1.2.3.4.5", "1.2.840.10008.1.2"); + + byte[] bytes = converter.dicomObjectToByteArray(original); + assertNotNull(bytes); + + OieDicomObject parsed = converter.byteArrayToDicomObject(bytes, false); + assertNotNull(parsed); + assertTrue(parsed.hasFileMetaInfo()); + } + + @Test + public void testByteArrayBase64RoundTrip() throws Exception { + // Create DICOM bytes + Dcm5DicomObject original = new Dcm5DicomObject(); + original.putString(Tag.PatientName, "PN", "Base64Test"); + original.initFileMetaInformation("1.2.840.10008.5.1.4.1.1.2", "1.2.3.4.5", "1.2.840.10008.1.2"); + byte[] dicomBytes = converter.dicomObjectToByteArray(original); + + // Base64 encode + byte[] base64Bytes = Base64.getEncoder().encode(dicomBytes); + + // Parse with decodeBase64=true + OieDicomObject parsed = converter.byteArrayToDicomObject(base64Bytes, true); + assertNotNull(parsed); + } + + @Test + public void testCreateDicomObject() { + OieDicomObject obj = converter.createDicomObject(); + assertNotNull(obj); + assertTrue(obj instanceof Dcm5DicomObject); + assertFalse(obj.hasFileMetaInfo()); + } + + @Test + public void testGetElementName() { + String name = converter.getElementName(Tag.PatientName); + assertNotNull(name); + assertFalse(name.isEmpty()); + assertEquals("PatientName", name); + } + + @Test + public void testGetElementNameUnknown() { + String name = converter.getElementName(0x99999999); + assertNotNull(name); + // Unknown tags return empty string + } + + @Test + public void testDicomBytesToXml() throws Exception { + // Build a DICOM file with FMI + Attributes fmi = Attributes.createFileMetaInformation("1.2.3.4.5", "1.2.840.10008.5.1.4.1.1.2", "1.2.840.10008.1.2.1"); + Attributes dataset = new Attributes(); + dataset.setString(Tag.PatientName, VR.PN, "XmlTest^Patient"); + dataset.setString(Tag.PatientID, VR.LO, "XML123"); + + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + DicomOutputStream dos = new DicomOutputStream(baos, UID.ExplicitVRLittleEndian); + dos.writeDataset(fmi, dataset); + dos.close(); + + byte[] base64Bytes = Base64.getEncoder().encode(baos.toByteArray()); + + String xml = converter.dicomBytesToXml(base64Bytes); + assertNotNull(xml); + assertTrue(xml.contains("PatientName") || xml.contains("00100010")); + } + + @Test + public void testXmlToDicomObject() throws Exception { + // dcm4che5 XML format uses and + String xml = "" + + "" + + "" + + "Test" + + "" + + "ID123" + + ""; + + OieDicomObject obj = converter.xmlToDicomObject(xml, "UTF-8"); + assertNotNull(obj); + assertEquals("ID123", obj.getString(Tag.PatientID)); + } + + @Test + public void testXxePrevention() { + String maliciousXml = "" + + "]>" + + "&xxe;"; + + try { + converter.xmlToDicomObject(maliciousXml, "UTF-8"); + fail("Expected exception for XXE attack"); + } catch (Exception e) { + // Expected — DOCTYPE is disallowed + } + } + + @Test + public void testDicomObjectToByteArrayClearsObject() throws Exception { + Dcm5DicomObject obj = new Dcm5DicomObject(); + obj.putString(Tag.PatientName, "PN", "ClearTest"); + + converter.dicomObjectToByteArray(obj); + + // After serialization, the object should be cleared + assertNull(obj.getString(Tag.PatientName)); + } +} diff --git a/server/test/com/mirth/connect/connectors/dimse/dicom/dcm5/Dcm5DicomElementTest.java b/server/test/com/mirth/connect/connectors/dimse/dicom/dcm5/Dcm5DicomElementTest.java new file mode 100644 index 0000000000..f6cbd4202d --- /dev/null +++ b/server/test/com/mirth/connect/connectors/dimse/dicom/dcm5/Dcm5DicomElementTest.java @@ -0,0 +1,244 @@ +package com.mirth.connect.connectors.dimse.dicom.dcm5; + +import static org.junit.Assert.assertArrayEquals; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; + +import org.dcm4che3.data.Attributes; +import org.dcm4che3.data.Fragments; +import org.dcm4che3.data.Sequence; +import org.dcm4che3.data.Tag; +import org.dcm4che3.data.VR; +import org.junit.Test; + +public class Dcm5DicomElementTest { + + @Test + public void testValueModeTag() { + Attributes attrs = new Attributes(); + attrs.setString(Tag.PatientName, VR.PN, "Test"); + Dcm5DicomElement elem = new Dcm5DicomElement(Tag.PatientName, attrs); + assertEquals(Tag.PatientName, elem.tag()); + } + + @Test + public void testValueModeVr() { + Attributes attrs = new Attributes(); + attrs.setString(Tag.PatientName, VR.PN, "Test"); + Dcm5DicomElement elem = new Dcm5DicomElement(Tag.PatientName, attrs); + assertEquals("PN", elem.vr().toString()); + } + + @Test + public void testValueModeGetValueAsString() { + Attributes attrs = new Attributes(); + attrs.setString(Tag.PatientName, VR.PN, "Doe^John"); + Dcm5DicomElement elem = new Dcm5DicomElement(Tag.PatientName, attrs); + assertEquals("Doe^John", elem.getValueAsString(0)); + } + + @Test + public void testValueModeGetBytes() { + Attributes attrs = new Attributes(); + byte[] data = new byte[] { 0x01, 0x02, 0x03 }; + attrs.setBytes(Tag.PixelData, VR.OB, data); + Dcm5DicomElement elem = new Dcm5DicomElement(Tag.PixelData, attrs); + assertArrayEquals(data, elem.getBytes()); + } + + @Test + public void testValueModeLength() { + Attributes attrs = new Attributes(); + byte[] data = new byte[] { 0x01, 0x02, 0x03 }; + attrs.setBytes(Tag.PixelData, VR.OB, data); + Dcm5DicomElement elem = new Dcm5DicomElement(Tag.PixelData, attrs); + assertEquals(3, elem.length()); + } + + @Test + public void testValueModeHasItemsFalse() { + Attributes attrs = new Attributes(); + attrs.setString(Tag.PatientName, VR.PN, "Test"); + Dcm5DicomElement elem = new Dcm5DicomElement(Tag.PatientName, attrs); + assertFalse(elem.hasItems()); + assertEquals(0, elem.countItems()); + } + + @Test + public void testValueModeGetDicomObjectNull() { + Attributes attrs = new Attributes(); + attrs.setString(Tag.PatientName, VR.PN, "Test"); + Dcm5DicomElement elem = new Dcm5DicomElement(Tag.PatientName, attrs); + assertNull(elem.getDicomObject()); + } + + @Test + public void testSequenceModeVrIsSQ() { + Attributes attrs = new Attributes(); + Sequence seq = attrs.newSequence(Tag.ReferencedStudySequence, 0); + Dcm5DicomElement elem = new Dcm5DicomElement(Tag.ReferencedStudySequence, attrs, seq); + assertEquals("SQ", elem.vr().toString()); + } + + @Test + public void testSequenceModeHasItemsEmpty() { + Attributes attrs = new Attributes(); + Sequence seq = attrs.newSequence(Tag.ReferencedStudySequence, 0); + Dcm5DicomElement elem = new Dcm5DicomElement(Tag.ReferencedStudySequence, attrs, seq); + assertFalse(elem.hasItems()); + assertEquals(0, elem.countItems()); + } + + @Test + public void testSequenceModeAddAndGetDicomObject() { + Attributes attrs = new Attributes(); + Sequence seq = attrs.newSequence(Tag.ReferencedStudySequence, 0); + Dcm5DicomElement elem = new Dcm5DicomElement(Tag.ReferencedStudySequence, attrs, seq); + + Dcm5DicomObject item = new Dcm5DicomObject(); + item.putString(Tag.StudyInstanceUID, "UI", "1.2.3"); + elem.addDicomObject(item); + + assertTrue(elem.hasItems()); + assertEquals(1, elem.countItems()); + assertNotNull(elem.getDicomObject()); + assertEquals("1.2.3", elem.getDicomObject().getString(Tag.StudyInstanceUID)); + } + + @Test + public void testSequenceModeLength() { + Attributes attrs = new Attributes(); + Sequence seq = attrs.newSequence(Tag.ReferencedStudySequence, 0); + Dcm5DicomElement elem = new Dcm5DicomElement(Tag.ReferencedStudySequence, attrs, seq); + assertEquals(-1, elem.length()); + } + + @Test + public void testSequenceModeGetValueAsStringNull() { + Attributes attrs = new Attributes(); + Sequence seq = attrs.newSequence(Tag.ReferencedStudySequence, 0); + Dcm5DicomElement elem = new Dcm5DicomElement(Tag.ReferencedStudySequence, attrs, seq); + assertNull(elem.getValueAsString(0)); + } + + @Test + public void testSequenceModeGetBytesNull() { + Attributes attrs = new Attributes(); + Sequence seq = attrs.newSequence(Tag.ReferencedStudySequence, 0); + Dcm5DicomElement elem = new Dcm5DicomElement(Tag.ReferencedStudySequence, attrs, seq); + assertNull(elem.getBytes()); + } + + @Test(expected = UnsupportedOperationException.class) + public void testSequenceModeGetFragmentThrows() { + Attributes attrs = new Attributes(); + Sequence seq = attrs.newSequence(Tag.ReferencedStudySequence, 0); + Dcm5DicomElement elem = new Dcm5DicomElement(Tag.ReferencedStudySequence, attrs, seq); + elem.getFragment(0); + } + + @Test(expected = UnsupportedOperationException.class) + public void testSequenceModeAddFragmentThrows() { + Attributes attrs = new Attributes(); + Sequence seq = attrs.newSequence(Tag.ReferencedStudySequence, 0); + Dcm5DicomElement elem = new Dcm5DicomElement(Tag.ReferencedStudySequence, attrs, seq); + elem.addFragment(new byte[] { 1 }); + } + + @Test + public void testFragmentsModeAddAndGetFragment() { + Attributes attrs = new Attributes(); + Fragments frags = attrs.newFragments(Tag.PixelData, VR.OB, 2); + Dcm5DicomElement elem = new Dcm5DicomElement(Tag.PixelData, attrs, frags, "OB"); + + byte[] fragment = new byte[] { 0x10, 0x20, 0x30 }; + elem.addFragment(fragment); + + assertTrue(elem.hasItems()); + assertEquals(1, elem.countItems()); + assertArrayEquals(fragment, elem.getFragment(0)); + } + + @Test + public void testFragmentsModeVr() { + Attributes attrs = new Attributes(); + Fragments frags = attrs.newFragments(Tag.PixelData, VR.OB, 0); + Dcm5DicomElement elem = new Dcm5DicomElement(Tag.PixelData, attrs, frags, "OB"); + assertEquals("OB", elem.vr().toString()); + } + + @Test + public void testFragmentsModeLength() { + Attributes attrs = new Attributes(); + Fragments frags = attrs.newFragments(Tag.PixelData, VR.OB, 0); + Dcm5DicomElement elem = new Dcm5DicomElement(Tag.PixelData, attrs, frags, "OB"); + assertEquals(-1, elem.length()); + } + + @Test(expected = UnsupportedOperationException.class) + public void testFragmentsModeAddDicomObjectThrows() { + Attributes attrs = new Attributes(); + Fragments frags = attrs.newFragments(Tag.PixelData, VR.OB, 0); + Dcm5DicomElement elem = new Dcm5DicomElement(Tag.PixelData, attrs, frags, "OB"); + elem.addDicomObject(new Dcm5DicomObject()); + } + + @Test + public void testFragmentsModeGetDicomObjectNull() { + Attributes attrs = new Attributes(); + Fragments frags = attrs.newFragments(Tag.PixelData, VR.OB, 0); + Dcm5DicomElement elem = new Dcm5DicomElement(Tag.PixelData, attrs, frags, "OB"); + assertNull(elem.getDicomObject()); + } + + @Test(expected = UnsupportedOperationException.class) + public void testValueModeGetFragmentThrows() { + Attributes attrs = new Attributes(); + attrs.setString(Tag.PatientName, VR.PN, "Test"); + Dcm5DicomElement elem = new Dcm5DicomElement(Tag.PatientName, attrs); + elem.getFragment(0); + } + + @Test(expected = UnsupportedOperationException.class) + public void testValueModeAddFragmentThrows() { + Attributes attrs = new Attributes(); + attrs.setString(Tag.PatientName, VR.PN, "Test"); + Dcm5DicomElement elem = new Dcm5DicomElement(Tag.PatientName, attrs); + elem.addFragment(new byte[] { 1 }); + } + + @Test(expected = UnsupportedOperationException.class) + public void testValueModeAddDicomObjectThrows() { + Attributes attrs = new Attributes(); + attrs.setString(Tag.PatientName, VR.PN, "Test"); + Dcm5DicomElement elem = new Dcm5DicomElement(Tag.PatientName, attrs); + elem.addDicomObject(new Dcm5DicomObject()); + } + + @Test + public void testValueModeUnwrapReturnsParent() { + Attributes attrs = new Attributes(); + attrs.setString(Tag.PatientName, VR.PN, "Test"); + Dcm5DicomElement elem = new Dcm5DicomElement(Tag.PatientName, attrs); + assertTrue(elem.unwrap() == attrs); + } + + @Test + public void testSequenceModeUnwrapReturnsSequence() { + Attributes attrs = new Attributes(); + Sequence seq = attrs.newSequence(Tag.ReferencedStudySequence, 0); + Dcm5DicomElement elem = new Dcm5DicomElement(Tag.ReferencedStudySequence, attrs, seq); + assertTrue(elem.unwrap() == seq); + } + + @Test + public void testFragmentsModeUnwrapReturnsFragments() { + Attributes attrs = new Attributes(); + Fragments frags = attrs.newFragments(Tag.PixelData, VR.OB, 0); + Dcm5DicomElement elem = new Dcm5DicomElement(Tag.PixelData, attrs, frags, "OB"); + assertTrue(elem.unwrap() == frags); + } +} diff --git a/server/test/com/mirth/connect/connectors/dimse/dicom/dcm5/Dcm5DicomObjectTest.java b/server/test/com/mirth/connect/connectors/dimse/dicom/dcm5/Dcm5DicomObjectTest.java new file mode 100644 index 0000000000..8996256f54 --- /dev/null +++ b/server/test/com/mirth/connect/connectors/dimse/dicom/dcm5/Dcm5DicomObjectTest.java @@ -0,0 +1,178 @@ +package com.mirth.connect.connectors.dimse.dicom.dcm5; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; + +import java.util.Iterator; + +import org.dcm4che3.data.Attributes; +import org.dcm4che3.data.Tag; +import org.junit.Test; + +import com.mirth.connect.connectors.dimse.dicom.OieDicomElement; + +public class Dcm5DicomObjectTest { + + @Test + public void testCreateEmpty() { + Dcm5DicomObject obj = new Dcm5DicomObject(); + assertNotNull(obj.unwrap()); + assertFalse(obj.hasFileMetaInfo()); + assertFalse(obj.bigEndian()); + } + + @Test + public void testPutAndGetString() { + Dcm5DicomObject obj = new Dcm5DicomObject(); + obj.putString(Tag.PatientName, "PN", "Doe^John"); + assertEquals("Doe^John", obj.getString(Tag.PatientName)); + } + + @Test + public void testPutAndGetInt() { + Dcm5DicomObject obj = new Dcm5DicomObject(); + obj.putInt(Tag.Rows, "US", 512); + assertEquals(512, obj.getInt(Tag.Rows)); + } + + @Test + public void testPutAndGetBytes() { + Dcm5DicomObject obj = new Dcm5DicomObject(); + byte[] data = new byte[] { 1, 2, 3, 4 }; + obj.putBytes(Tag.PixelData, "OB", data); + OieDicomElement elem = obj.get(Tag.PixelData); + assertNotNull(elem); + assertNotNull(elem.getBytes()); + assertEquals(4, elem.getBytes().length); + } + + @Test + public void testGetReturnsNullForMissingTag() { + Dcm5DicomObject obj = new Dcm5DicomObject(); + assertNull(obj.get(Tag.PatientName)); + assertNull(obj.getString(Tag.PatientName)); + assertEquals(0, obj.getInt(Tag.Rows)); + } + + @Test + public void testPutSequence() { + Dcm5DicomObject obj = new Dcm5DicomObject(); + OieDicomElement seq = obj.putSequence(Tag.ReferencedStudySequence); + assertNotNull(seq); + assertEquals("SQ", seq.vr().toString()); + assertFalse(seq.hasItems()); + assertEquals(0, seq.countItems()); + } + + @Test + public void testSequenceAddAndGet() { + Dcm5DicomObject obj = new Dcm5DicomObject(); + OieDicomElement seq = obj.putSequence(Tag.ReferencedStudySequence); + + Dcm5DicomObject item = new Dcm5DicomObject(); + item.putString(Tag.StudyInstanceUID, "UI", "1.2.3.4"); + seq.addDicomObject(item); + + assertTrue(seq.hasItems()); + assertEquals(1, seq.countItems()); + assertNotNull(seq.getDicomObject()); + assertEquals("1.2.3.4", seq.getDicomObject().getString(Tag.StudyInstanceUID)); + } + + @Test + public void testPutFragments() { + Dcm5DicomObject obj = new Dcm5DicomObject(); + OieDicomElement frags = obj.putFragments(Tag.PixelData, "OB", false, 2); + assertNotNull(frags); + assertEquals("OB", frags.vr().toString()); + } + + @Test + public void testRemove() { + Dcm5DicomObject obj = new Dcm5DicomObject(); + obj.putString(Tag.PatientName, "PN", "Test"); + assertNotNull(obj.get(Tag.PatientName)); + + OieDicomElement removed = obj.remove(Tag.PatientName); + assertNotNull(removed); + assertNull(obj.get(Tag.PatientName)); + } + + @Test + public void testRemoveNonexistent() { + Dcm5DicomObject obj = new Dcm5DicomObject(); + assertNull(obj.remove(Tag.PatientName)); + } + + @Test + public void testClear() { + Dcm5DicomObject obj = new Dcm5DicomObject(); + obj.putString(Tag.PatientName, "PN", "Test"); + obj.putString(Tag.PatientID, "LO", "12345"); + obj.clear(); + assertNull(obj.get(Tag.PatientName)); + assertNull(obj.get(Tag.PatientID)); + } + + @Test + public void testInitFileMetaInformation() { + Dcm5DicomObject obj = new Dcm5DicomObject(); + assertFalse(obj.hasFileMetaInfo()); + + obj.initFileMetaInformation("1.2.840.10008.5.1.4.1.1.2", "1.2.3.4.5", "1.2.840.10008.1.2"); + assertTrue(obj.hasFileMetaInfo()); + assertNotNull(obj.getFmi()); + } + + @Test + public void testCommandIterator() { + Dcm5DicomObject obj = new Dcm5DicomObject(); + // Command group tags have group 0x0000 + obj.putString(0x00000002, "UI", "1.2.840.10008.1.1"); + obj.putInt(0x00000100, "US", 0x0001); + // Non-command tag should not appear + obj.putString(Tag.PatientName, "PN", "Test"); + + Iterator it = obj.commandIterator(); + int count = 0; + while (it.hasNext()) { + OieDicomElement elem = it.next(); + assertTrue((elem.tag() >>> 16) == 0x0000); + count++; + } + assertEquals(2, count); + } + + @Test + public void testWrapExistingAttributes() { + Attributes attrs = new Attributes(); + attrs.setString(Tag.PatientName, org.dcm4che3.data.VR.PN, "Wrapped"); + Dcm5DicomObject obj = new Dcm5DicomObject(attrs); + assertEquals("Wrapped", obj.getString(Tag.PatientName)); + assertTrue(obj.unwrap() == attrs); + } + + @Test + public void testWrapWithFmi() { + Attributes fmi = Attributes.createFileMetaInformation("1.2.3", "1.2.840.10008.5.1.4.1.1.2", "1.2.840.10008.1.2"); + Attributes dataset = new Attributes(); + Dcm5DicomObject obj = new Dcm5DicomObject(fmi, dataset); + assertTrue(obj.hasFileMetaInfo()); + assertTrue(obj.getFmi() == fmi); + } + + @Test + public void testDefaultGetStringReturnsDefault() { + Dcm5DicomObject obj = new Dcm5DicomObject(); + assertEquals("FALLBACK", obj.getString(Tag.PatientName, "FALLBACK")); + } + + @Test + public void testDefaultGetIntReturnsDefault() { + Dcm5DicomObject obj = new Dcm5DicomObject(); + assertEquals(42, obj.getInt(Tag.Rows, 42)); + } +} diff --git a/server/test/com/mirth/connect/connectors/dimse/dicom/dcm5/Dcm5DicomReceiverTest.java b/server/test/com/mirth/connect/connectors/dimse/dicom/dcm5/Dcm5DicomReceiverTest.java new file mode 100644 index 0000000000..e1d968404c --- /dev/null +++ b/server/test/com/mirth/connect/connectors/dimse/dicom/dcm5/Dcm5DicomReceiverTest.java @@ -0,0 +1,143 @@ +package com.mirth.connect.connectors.dimse.dicom.dcm5; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +import java.net.InetAddress; +import java.net.InetSocketAddress; +import java.net.Socket; +import java.util.Map; + +import org.dcm4che3.net.Association; +import org.dcm4che3.net.Device; +import org.dcm4che3.net.pdu.AAssociateAC; +import org.dcm4che3.net.pdu.AAssociateRQ; +import org.dcm4che3.net.pdu.PresentationContext; +import org.dcm4che3.net.pdu.UserIdentityRQ; +import org.junit.Test; + +import com.mirth.connect.connectors.dimse.DICOMConfiguration; +import com.mirth.connect.connectors.dimse.DICOMDispatcher; +import com.mirth.connect.connectors.dimse.DICOMDispatcherProperties; +import com.mirth.connect.connectors.dimse.DICOMReceiver; +import com.mirth.connect.connectors.dimse.DICOMReceiverProperties; +import com.mirth.connect.connectors.dimse.dicom.OieDicomReceiver; +import com.mirth.connect.connectors.dimse.dicom.OieDicomSender; +import com.mirth.connect.donkey.server.channel.Connector; +import com.mirth.connect.donkey.server.channel.SourceConnector; + +public class Dcm5DicomReceiverTest { + + @Test + public void testConstructionCreatesDevice() { + Dcm5DicomReceiver receiver = createReceiver(); + assertNotNull(receiver); + assertNotNull(receiver.unwrap()); + assertTrue(receiver.unwrap() instanceof Device); + } + + @Test + public void testImplementsOieDicomReceiver() { + Dcm5DicomReceiver receiver = createReceiver(); + assertTrue(receiver instanceof OieDicomReceiver); + } + + /** + * Verifies that buildSourceMap produces the exact same keys as MirthDcmRcv.onCStoreRQ. + * This is the most critical parity test for the dcm5 receiver. + */ + @Test + public void testSourceMapKeysMatchMirthDcmRcv() throws Exception { + Dcm5DicomReceiver receiver = createReceiver(); + + // Mock Association with full metadata + Association as = mock(Association.class); + when(as.getLocalAET()).thenReturn("LOCAL_AE"); + when(as.getRemoteAET()).thenReturn("REMOTE_AE"); + + // Mock Socket + Socket socket = mock(Socket.class); + InetAddress localAddr = InetAddress.getByName("127.0.0.1"); + InetAddress remoteAddr = InetAddress.getByName("192.168.1.100"); + when(socket.getLocalAddress()).thenReturn(localAddr); + when(socket.getLocalPort()).thenReturn(11112); + when(socket.getRemoteSocketAddress()).thenReturn(new InetSocketAddress(remoteAddr, 50000)); + when(as.getSocket()).thenReturn(socket); + + // Mock AAssociateAC + AAssociateAC ac = mock(AAssociateAC.class); + when(ac.getProtocolVersion()).thenReturn(1); + when(ac.getImplClassUID()).thenReturn("1.2.3.4"); + when(ac.getImplVersionName()).thenReturn("DCM5TEST"); + when(ac.getApplicationContext()).thenReturn("1.2.840.10008.3.1.1.1"); + when(ac.getNumberOfPresentationContexts()).thenReturn(0); + when(as.getAAssociateAC()).thenReturn(ac); + + // Mock AAssociateRQ with UserIdentity + AAssociateRQ rq = mock(AAssociateRQ.class); + when(rq.getProtocolVersion()).thenReturn(1); + when(rq.getImplClassUID()).thenReturn("1.2.3.5"); + when(rq.getImplVersionName()).thenReturn("DCM5REQ"); + when(rq.getApplicationContext()).thenReturn("1.2.840.10008.3.1.1.1"); + when(rq.getNumberOfPresentationContexts()).thenReturn(0); + + UserIdentityRQ uid = mock(UserIdentityRQ.class); + when(uid.getUsername()).thenReturn("testuser"); + when(uid.getPasscode()).thenReturn("testpass".toCharArray()); + when(uid.getType()).thenReturn(2); // USERNAME_PASSCODE + when(rq.getUserIdentityRQ()).thenReturn(uid); + when(as.getAAssociateRQ()).thenReturn(rq); + + Map sourceMap = receiver.buildSourceMap(as); + + // Verify ALL keys that MirthDcmRcv.onCStoreRQ populates + assertEquals("LOCAL_AE", sourceMap.get("localApplicationEntityTitle")); + assertEquals("REMOTE_AE", sourceMap.get("remoteApplicationEntityTitle")); + assertEquals("127.0.0.1", sourceMap.get("localAddress")); + assertEquals(11112, sourceMap.get("localPort")); + assertEquals("192.168.1.100", sourceMap.get("remoteAddress")); + assertEquals(50000, sourceMap.get("remotePort")); + assertEquals(1, sourceMap.get("associateACProtocolVersion")); + assertEquals("1.2.3.4", sourceMap.get("associateACImplClassUID")); + assertEquals("DCM5TEST", sourceMap.get("associateACImplVersionName")); + assertEquals("1.2.840.10008.3.1.1.1", sourceMap.get("associateACApplicationContext")); + assertEquals(1, sourceMap.get("associateRQProtocolVersion")); + assertEquals("1.2.3.5", sourceMap.get("associateRQImplClassUID")); + assertEquals("DCM5REQ", sourceMap.get("associateRQImplVersionName")); + assertEquals("1.2.840.10008.3.1.1.1", sourceMap.get("associateRQApplicationContext")); + assertEquals("testuser", sourceMap.get("username")); + assertEquals("testpass", sourceMap.get("passcode")); + assertEquals("USERNAME_PASSCODE", sourceMap.get("userIdentityType")); + } + + @Test + public void testSourceMapWithNullSocket() { + Dcm5DicomReceiver receiver = createReceiver(); + Association as = mock(Association.class); + when(as.getLocalAET()).thenReturn("AE"); + when(as.getRemoteAET()).thenReturn("REMOTE"); + when(as.getSocket()).thenReturn(null); + when(as.getAAssociateAC()).thenReturn(null); + when(as.getAAssociateRQ()).thenReturn(null); + + Map sourceMap = receiver.buildSourceMap(as); + assertEquals("AE", sourceMap.get("localApplicationEntityTitle")); + assertEquals("REMOTE", sourceMap.get("remoteApplicationEntityTitle")); + // No socket keys should be present + assertTrue(!sourceMap.containsKey("localAddress")); + } + + private Dcm5DicomReceiver createReceiver() { + return new Dcm5DicomReceiver(mock(SourceConnector.class), new TestConfig()); + } + + private static class TestConfig implements DICOMConfiguration { + @Override public void configureConnectorDeploy(Connector connector) {} + @Override public void configureReceiver(OieDicomReceiver r, DICOMReceiver c, DICOMReceiverProperties p) {} + @Override public void configureSender(OieDicomSender s, DICOMDispatcher c, DICOMDispatcherProperties p) {} + @Override public Map getCStoreRequestInformation(Object association) { return new java.util.HashMap<>(); } + } +} diff --git a/server/test/com/mirth/connect/connectors/dimse/dicom/dcm5/Dcm5DicomSenderTest.java b/server/test/com/mirth/connect/connectors/dimse/dicom/dcm5/Dcm5DicomSenderTest.java new file mode 100644 index 0000000000..b054cfc1f8 --- /dev/null +++ b/server/test/com/mirth/connect/connectors/dimse/dicom/dcm5/Dcm5DicomSenderTest.java @@ -0,0 +1,55 @@ +package com.mirth.connect.connectors.dimse.dicom.dcm5; + +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +import java.util.Map; + +import org.dcm4che3.net.Device; +import org.junit.Test; + +import com.mirth.connect.connectors.dimse.DICOMConfiguration; +import com.mirth.connect.connectors.dimse.DICOMDispatcher; +import com.mirth.connect.connectors.dimse.DICOMDispatcherProperties; +import com.mirth.connect.connectors.dimse.DICOMReceiver; +import com.mirth.connect.connectors.dimse.DICOMReceiverProperties; +import com.mirth.connect.connectors.dimse.dicom.OieDicomReceiver; +import com.mirth.connect.connectors.dimse.dicom.OieDicomSender; +import com.mirth.connect.donkey.server.channel.Connector; + +public class Dcm5DicomSenderTest { + + @Test + public void testConstructionCreatesDevice() { + Dcm5DicomSender sender = new Dcm5DicomSender(new TestConfig()); + assertNotNull(sender); + assertNotNull(sender.unwrap()); + assertTrue(sender.unwrap() instanceof Device); + } + + @Test + public void testImplementsOieDicomSender() { + Dcm5DicomSender sender = new Dcm5DicomSender(new TestConfig()); + assertTrue(sender instanceof OieDicomSender); + } + + @Test + public void testStorageCommitmentDefault() { + Dcm5DicomSender sender = new Dcm5DicomSender(new TestConfig()); + assertTrue(!sender.isStorageCommitment()); + } + + @Test + public void testSetStorageCommitment() { + Dcm5DicomSender sender = new Dcm5DicomSender(new TestConfig()); + sender.setStorageCommitment(true); + assertTrue(sender.isStorageCommitment()); + } + + private static class TestConfig implements DICOMConfiguration { + @Override public void configureConnectorDeploy(Connector connector) {} + @Override public void configureReceiver(OieDicomReceiver r, DICOMReceiver c, DICOMReceiverProperties p) {} + @Override public void configureSender(OieDicomSender s, DICOMDispatcher c, DICOMDispatcherProperties p) {} + @Override public Map getCStoreRequestInformation(Object association) { return new java.util.HashMap<>(); } + } +} diff --git a/server/test/com/mirth/connect/connectors/dimse/dicom/integration/ConverterParityIntegrationTest.java b/server/test/com/mirth/connect/connectors/dimse/dicom/integration/ConverterParityIntegrationTest.java new file mode 100644 index 0000000000..ab87bdc173 --- /dev/null +++ b/server/test/com/mirth/connect/connectors/dimse/dicom/integration/ConverterParityIntegrationTest.java @@ -0,0 +1,139 @@ +package com.mirth.connect.connectors.dimse.dicom.integration; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotEquals; +import static org.junit.Assert.assertNotNull; + +import org.dcm4che3.data.Tag; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +import com.mirth.connect.connectors.dimse.dicom.DicomLibraryFactory; +import com.mirth.connect.connectors.dimse.dicom.DicomLibraryFactory.DicomLibrary; +import com.mirth.connect.connectors.dimse.dicom.OieDicomConverter; +import com.mirth.connect.connectors.dimse.dicom.OieDicomObject; +import com.mirth.connect.connectors.dimse.dicom.dcm2.Dcm2DicomConverter; +import com.mirth.connect.connectors.dimse.dicom.dcm5.Dcm5DicomConverter; + +/** + * Verifies semantic equivalence between dcm2 and dcm5 converters. Both converters + * must produce DICOM data that is correctly parseable by the other. + * + *

Note: Byte-level equivalence is NOT expected because: + *

    + *
  • FMI implementation version names differ
  • + *
  • dcm2 uses two-pass write (ByteCounterOutputStream), dcm5 uses single-pass
  • + *
  • Internal padding/alignment may differ
  • + *
+ */ +public class ConverterParityIntegrationTest { + + private Dcm2DicomConverter dcm2Converter; + private Dcm5DicomConverter dcm5Converter; + + @Before + public void setUp() { + dcm2Converter = new Dcm2DicomConverter(); + dcm5Converter = new Dcm5DicomConverter(); + DicomLibraryFactory.resetForTesting(DicomLibrary.DCM4CHE5); + } + + @After + public void tearDown() { + DicomLibraryFactory.resetForTesting(null); + } + + @Test + public void testDcm5BytesParsedByDcm2() throws Exception { + // Create DICOM data using dcm5 + OieDicomObject dcm5Obj = dcm5Converter.createDicomObject(); + dcm5Obj.putString(Tag.PatientName, "PN", "Cross^Library"); + dcm5Obj.putString(Tag.PatientID, "LO", "XLIB001"); + dcm5Obj.putString(Tag.Modality, "CS", "MR"); + dcm5Obj.initFileMetaInformation( + "1.2.840.10008.5.1.4.1.1.4", // MR Image Storage + "1.2.3.4.5.6.7.8.9", + "1.2.840.10008.1.2"); // Implicit VR LE + byte[] dcm5Bytes = dcm5Converter.dicomObjectToByteArray(dcm5Obj); + + // Parse dcm5 bytes using dcm2 + DicomLibraryFactory.resetForTesting(DicomLibrary.DCM4CHE2); + OieDicomObject parsedByDcm2 = dcm2Converter.byteArrayToDicomObject(dcm5Bytes, false); + assertEquals("Cross^Library", parsedByDcm2.getString(Tag.PatientName)); + assertEquals("XLIB001", parsedByDcm2.getString(Tag.PatientID)); + assertEquals("MR", parsedByDcm2.getString(Tag.Modality)); + } + + @Test + public void testDcm2BytesParsedByDcm5() throws Exception { + // Create DICOM data using dcm2 + DicomLibraryFactory.resetForTesting(DicomLibrary.DCM4CHE2); + OieDicomObject dcm2Obj = dcm2Converter.createDicomObject(); + dcm2Obj.putString(Tag.PatientName, "PN", "Reverse^Test"); + dcm2Obj.putString(Tag.PatientID, "LO", "REV001"); + dcm2Obj.putString(Tag.Modality, "CS", "CT"); + dcm2Obj.initFileMetaInformation( + "1.2.840.10008.5.1.4.1.1.2", // CT Image Storage + "1.2.3.4.5.6.7.8.10", + "1.2.840.10008.1.2"); + byte[] dcm2Bytes = dcm2Converter.dicomObjectToByteArray(dcm2Obj); + + // Parse dcm2 bytes using dcm5 + DicomLibraryFactory.resetForTesting(DicomLibrary.DCM4CHE5); + OieDicomObject parsedByDcm5 = dcm5Converter.byteArrayToDicomObject(dcm2Bytes, false); + assertEquals("Reverse^Test", parsedByDcm5.getString(Tag.PatientName)); + assertEquals("REV001", parsedByDcm5.getString(Tag.PatientID)); + assertEquals("CT", parsedByDcm5.getString(Tag.Modality)); + } + + @Test + public void testBidirectionalRoundTrip() throws Exception { + // dcm5 -> bytes -> dcm2 parse -> dcm2 bytes -> dcm5 parse + OieDicomObject original = dcm5Converter.createDicomObject(); + original.putString(Tag.PatientName, "PN", "RoundTrip^Full"); + original.putString(Tag.PatientID, "LO", "RT001"); + original.putString(Tag.StudyDescription, "LO", "Integration Test"); + original.initFileMetaInformation( + "1.2.840.10008.5.1.4.1.1.2", + "1.2.3.4.5.6.7.8.11", + "1.2.840.10008.1.2"); + byte[] dcm5Bytes = dcm5Converter.dicomObjectToByteArray(original); + + // dcm2 parses dcm5 bytes + DicomLibraryFactory.resetForTesting(DicomLibrary.DCM4CHE2); + OieDicomObject intermediate = dcm2Converter.byteArrayToDicomObject(dcm5Bytes, false); + assertEquals("RoundTrip^Full", intermediate.getString(Tag.PatientName)); + + // dcm2 re-serializes + byte[] dcm2Bytes = dcm2Converter.dicomObjectToByteArray(intermediate); + + // dcm5 parses dcm2 bytes + DicomLibraryFactory.resetForTesting(DicomLibrary.DCM4CHE5); + OieDicomObject final5 = dcm5Converter.byteArrayToDicomObject(dcm2Bytes, false); + assertEquals("RoundTrip^Full", final5.getString(Tag.PatientName)); + assertEquals("RT001", final5.getString(Tag.PatientID)); + assertEquals("Integration Test", final5.getString(Tag.StudyDescription)); + } + + @Test + public void testElementNameParity() { + // Both converters should return equivalent element names for standard tags. + // Note: dcm2 returns "Patient's Name", dcm5 returns "PatientName" — both are valid. + String dcm2Name = dcm2Converter.getElementName(Tag.PatientName); + String dcm5Name = dcm5Converter.getElementName(Tag.PatientName); + assertNotNull(dcm2Name); + assertNotNull(dcm5Name); + // Both should be non-empty for a well-known tag + assertNotEquals("dcm2 element name should not be empty", "", dcm2Name); + assertNotEquals("dcm5 element name should not be empty", "", dcm5Name); + + // PatientID should also be recognized by both + assertNotEquals("", dcm2Converter.getElementName(Tag.PatientID)); + assertNotEquals("", dcm5Converter.getElementName(Tag.PatientID)); + + // Modality + assertNotEquals("", dcm2Converter.getElementName(Tag.Modality)); + assertNotEquals("", dcm5Converter.getElementName(Tag.Modality)); + } +} diff --git a/server/test/com/mirth/connect/connectors/dimse/dicom/integration/CrossLibraryIntegrationTest.java b/server/test/com/mirth/connect/connectors/dimse/dicom/integration/CrossLibraryIntegrationTest.java new file mode 100644 index 0000000000..1b56f50066 --- /dev/null +++ b/server/test/com/mirth/connect/connectors/dimse/dicom/integration/CrossLibraryIntegrationTest.java @@ -0,0 +1,158 @@ +package com.mirth.connect.connectors.dimse.dicom.integration; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +import java.io.File; +import java.nio.file.Files; + +import org.dcm4che3.data.Tag; +import org.junit.Test; +import org.mockito.ArgumentCaptor; + +import com.mirth.connect.connectors.dimse.dicom.DicomLibraryFactory; +import com.mirth.connect.connectors.dimse.dicom.DicomLibraryFactory.DicomLibrary; +import com.mirth.connect.connectors.dimse.dicom.OieDicomObject; +import com.mirth.connect.connectors.dimse.dicom.dcm2.Dcm2DicomConverter; +import com.mirth.connect.connectors.dimse.dicom.dcm2.Dcm2DicomReceiver; +import com.mirth.connect.connectors.dimse.dicom.dcm2.Dcm2DicomSender; +import com.mirth.connect.connectors.dimse.dicom.dcm5.Dcm5DicomConverter; +import com.mirth.connect.donkey.model.message.RawMessage; +import com.mirth.connect.donkey.server.channel.SourceConnector; + +/** + * Cross-library integration tests proving that dcm4che2 and dcm4che5 can + * interoperate at the DICOM protocol level. Both libraries use different + * Java packages (org.dcm4che2 vs org.dcm4che3), so they coexist on the classpath. + */ +public class CrossLibraryIntegrationTest extends DicomIntegrationTestBase { + + private Dcm2DicomReceiver dcm2Receiver; + private Dcm2DicomSender dcm2Sender; + + @Override + public void tearDown() { + if (dcm2Sender != null) { + try { dcm2Sender.close(); } catch (Exception e) { /* ignore */ } + try { dcm2Sender.stop(); } catch (Exception e) { /* ignore */ } + dcm2Sender = null; + } + if (dcm2Receiver != null) { + try { dcm2Receiver.stop(); } catch (Exception e) { /* ignore */ } + dcm2Receiver = null; + } + super.tearDown(); + } + + @Test + public void testDcm2SenderToDcm5Receiver() throws Exception { + int port = allocatePort(); + ArgumentCaptor captor = ArgumentCaptor.forClass(RawMessage.class); + SourceConnector mockConnector = createMockSourceConnector(captor); + + // Start dcm5 receiver + receiver = startDcm5Receiver(port, mockConnector); + + // Create DICOM file using dcm2 converter + DicomLibraryFactory.resetForTesting(DicomLibrary.DCM4CHE2); + File dcm2File = createDcm2TempFile("Dcm2^Sender", "DCM2TO5"); + + // Configure dcm2 sender + DicomLibraryFactory.resetForTesting(DicomLibrary.DCM4CHE5); + dcm2Sender = new Dcm2DicomSender(new TestConfig()); + dcm2Sender.setRemoteHost("127.0.0.1"); + dcm2Sender.setRemotePort(port); + dcm2Sender.setCalledAET("TEST_SCP"); + dcm2Sender.setCalling("DCM2_SCU"); + dcm2Sender.addFile(dcm2File); + dcm2Sender.configureTransferCapability(); + dcm2Sender.start(); + + dcm2Sender.open(); + dcm2Sender.send((cmd, data) -> {}); + // dcm2 sender's send() is synchronous + dcm2Sender.close(); + + // Give the receiver time to finish processing + Thread.sleep(500); + + RawMessage received = captor.getValue(); + assertNotNull("Receiver should have dispatched a message", received); + assertNotNull(received.getRawBytes()); + + // Parse with dcm5 converter + Dcm5DicomConverter dcm5Converter = new Dcm5DicomConverter(); + OieDicomObject parsed = dcm5Converter.byteArrayToDicomObject(received.getRawBytes(), false); + assertEquals("Dcm2^Sender", parsed.getString(Tag.PatientName)); + assertEquals("DCM2TO5", parsed.getString(Tag.PatientID)); + } + + @Test + public void testDcm5SenderToDcm2Receiver() throws Exception { + int port = allocatePort(); + ArgumentCaptor captor = ArgumentCaptor.forClass(RawMessage.class); + SourceConnector mockConnector = createMockSourceConnector(captor); + + // Start dcm2 receiver + DicomLibraryFactory.resetForTesting(DicomLibrary.DCM4CHE2); + dcm2Receiver = new Dcm2DicomReceiver(mockConnector, new TestConfig()); + dcm2Receiver.setHostname("127.0.0.1"); + dcm2Receiver.setPort(port); + dcm2Receiver.setAEtitle("DCM2_SCP"); + dcm2Receiver.setDestination(tempFolder.getRoot().getAbsolutePath()); + dcm2Receiver.setTransferSyntax(new String[] { "1.2.840.10008.1.2", "1.2.840.10008.1.2.1" }); + dcm2Receiver.initTransferCapability(); + dcm2Receiver.start(); + waitForPort(port, 2000); + + // Create dcm5 DICOM file and send with dcm5 sender + DicomLibraryFactory.resetForTesting(DicomLibrary.DCM4CHE5); + File dcm5File = createDicomTempFile("Dcm5^Sender", "DCM5TO2"); + sender = configureDcm5Sender(port, dcm5File); + sender.setCalledAET("DCM2_SCP"); + + CapturingDimseRspHandler handler = new CapturingDimseRspHandler(1); + sender.open(); + sender.send(handler); + assertTrue("DIMSE response not received", handler.awaitResponses(5000)); + sender.close(); + + // Give dcm2 receiver time to process + Thread.sleep(500); + + RawMessage received = captor.getValue(); + assertNotNull("dcm2 receiver should have dispatched a message", received); + assertNotNull(received.getRawBytes()); + + // Parse with dcm2 converter + DicomLibraryFactory.resetForTesting(DicomLibrary.DCM4CHE2); + Dcm2DicomConverter dcm2Converter = new Dcm2DicomConverter(); + OieDicomObject parsed = dcm2Converter.byteArrayToDicomObject(received.getRawBytes(), false); + assertEquals("Dcm5^Sender", parsed.getString(Tag.PatientName)); + assertEquals("DCM5TO2", parsed.getString(Tag.PatientID)); + } + + /** + * Creates a temp DICOM file using the dcm2 converter. + */ + private File createDcm2TempFile(String patientName, String patientId) throws Exception { + Dcm2DicomConverter converter = new Dcm2DicomConverter(); + OieDicomObject obj = converter.createDicomObject(); + obj.putString(Tag.PatientName, "PN", patientName); + obj.putString(Tag.PatientID, "LO", patientId); + // Use dcm4che2's UID generation for a pure dcm2 test artifact + obj.putString(Tag.StudyInstanceUID, "UI", org.dcm4che2.util.UIDUtils.createUID()); + obj.putString(Tag.SeriesInstanceUID, "UI", org.dcm4che2.util.UIDUtils.createUID()); + obj.putString(Tag.SOPInstanceUID, "UI", org.dcm4che2.util.UIDUtils.createUID()); + obj.putString(Tag.Modality, "CS", "CT"); + obj.initFileMetaInformation( + "1.2.840.10008.5.1.4.1.1.2", + org.dcm4che2.util.UIDUtils.createUID(), + "1.2.840.10008.1.2"); + byte[] bytes = converter.dicomObjectToByteArray(obj); + File tempFile = tempFolder.newFile(patientId + ".dcm"); + Files.write(tempFile.toPath(), bytes); + return tempFile; + } +} diff --git a/server/test/com/mirth/connect/connectors/dimse/dicom/integration/Dcm5CEchoIntegrationTest.java b/server/test/com/mirth/connect/connectors/dimse/dicom/integration/Dcm5CEchoIntegrationTest.java new file mode 100644 index 0000000000..bd469de2a6 --- /dev/null +++ b/server/test/com/mirth/connect/connectors/dimse/dicom/integration/Dcm5CEchoIntegrationTest.java @@ -0,0 +1,76 @@ +package com.mirth.connect.connectors.dimse.dicom.integration; + +import static org.junit.Assert.assertEquals; + +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.ScheduledExecutorService; + +import org.dcm4che3.data.Tag; +import org.dcm4che3.data.UID; +import org.dcm4che3.net.ApplicationEntity; +import org.dcm4che3.net.Connection; +import org.dcm4che3.net.Device; +import org.dcm4che3.net.DimseRSP; +import org.dcm4che3.net.Association; +import org.dcm4che3.net.pdu.AAssociateRQ; +import org.dcm4che3.net.pdu.PresentationContext; +import org.junit.Test; +import org.mockito.ArgumentCaptor; + +import com.mirth.connect.donkey.model.message.RawMessage; +import com.mirth.connect.donkey.server.channel.SourceConnector; + +/** + * Integration test verifying that the dcm5 receiver responds to C-ECHO requests. + * Uses raw dcm4che5 API to send C-ECHO because OieDicomSender only supports C-STORE. + */ +public class Dcm5CEchoIntegrationTest extends DicomIntegrationTestBase { + + @Test + public void testCEchoSuccess() throws Exception { + int port = allocatePort(); + ArgumentCaptor captor = ArgumentCaptor.forClass(RawMessage.class); + SourceConnector mockConnector = createMockSourceConnector(captor); + + receiver = startDcm5Receiver(port, mockConnector); + + // Build a raw dcm4che5 SCU to send C-ECHO + Device echoDevice = new Device("ECHO_SCU"); + Connection echoConn = new Connection(); + echoDevice.addConnection(echoConn); + ApplicationEntity echoAE = new ApplicationEntity("ECHO_SCU"); + echoAE.addConnection(echoConn); + echoDevice.addApplicationEntity(echoAE); + ExecutorService executor = Executors.newCachedThreadPool(); + ScheduledExecutorService scheduled = Executors.newSingleThreadScheduledExecutor(); + echoDevice.setExecutor(executor); + echoDevice.setScheduledExecutor(scheduled); + + Connection remoteConn = new Connection(); + remoteConn.setHostname("127.0.0.1"); + remoteConn.setPort(port); + + AAssociateRQ aarq = new AAssociateRQ(); + aarq.setCalledAET("TEST_SCP"); + aarq.setCallingAET("ECHO_SCU"); + aarq.addPresentationContext( + new PresentationContext(1, UID.Verification, UID.ImplicitVRLittleEndian)); + + Association as = null; + try { + as = echoAE.connect(echoConn, remoteConn, aarq); + DimseRSP rsp = as.cecho(); + rsp.next(); + int status = rsp.getCommand().getInt(Tag.Status, -1); + assertEquals("C-ECHO should return success status", 0, status); + } finally { + if (as != null) { + try { as.release(); } catch (Exception e) { /* ignore */ } + } + echoDevice.unbindConnections(); + executor.shutdownNow(); + scheduled.shutdownNow(); + } + } +} diff --git a/server/test/com/mirth/connect/connectors/dimse/dicom/integration/Dcm5ErrorHandlingIntegrationTest.java b/server/test/com/mirth/connect/connectors/dimse/dicom/integration/Dcm5ErrorHandlingIntegrationTest.java new file mode 100644 index 0000000000..8cadc2a9b2 --- /dev/null +++ b/server/test/com/mirth/connect/connectors/dimse/dicom/integration/Dcm5ErrorHandlingIntegrationTest.java @@ -0,0 +1,134 @@ +package com.mirth.connect.connectors.dimse.dicom.integration; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +import java.io.File; +import java.io.IOException; + +import org.dcm4che3.data.Tag; +import org.junit.Test; +import org.mockito.ArgumentCaptor; + +import com.mirth.connect.donkey.model.message.RawMessage; +import com.mirth.connect.donkey.model.message.Response; +import com.mirth.connect.donkey.server.channel.Channel; +import com.mirth.connect.donkey.server.channel.DispatchResult; +import com.mirth.connect.donkey.server.channel.SourceConnector; + +/** + * Integration tests for error handling scenarios: connection refused, + * receiver stop/restart, and dispatch errors. + */ +public class Dcm5ErrorHandlingIntegrationTest extends DicomIntegrationTestBase { + + @Test + public void testConnectionRefused() throws Exception { + int port = allocatePort(); + // No receiver started — port is unbound + File dicomFile = createDicomTempFile("NoReceiver^Test", "ERR001"); + sender = configureDcm5Sender(port, dicomFile); + + try { + sender.open(); + fail("open() should throw when no receiver is listening"); + } catch (Exception e) { + // Expected: connection refused or similar + assertNotNull(e); + } + + // Verify clean shutdown after connection failure + sender.close(); + sender.stop(); + sender = null; + } + + @Test + public void testReceiverStopAndRestart() throws Exception { + int port = allocatePort(); + ArgumentCaptor captor = ArgumentCaptor.forClass(RawMessage.class); + SourceConnector mockConnector = createMockSourceConnector(captor); + + // Start receiver, send successfully + receiver = startDcm5Receiver(port, mockConnector); + File dicomFile = createDicomTempFile("StopRestart^Test", "SR001"); + sender = configureDcm5Sender(port, dicomFile); + + CapturingDimseRspHandler handler1 = new CapturingDimseRspHandler(1); + sender.open(); + sender.send(handler1); + assertTrue("First send should succeed", handler1.awaitResponses(5000)); + sender.close(); + sender.stop(); + sender = null; + + // Stop receiver + receiver.stop(); + receiver = null; + + // Verify send fails when receiver is stopped + File dicomFile2 = createDicomTempFile("StopRestart^Fail", "SR002"); + sender = configureDcm5Sender(port, dicomFile2); + try { + sender.open(); + fail("open() should throw when receiver is stopped"); + } catch (Exception e) { + // Expected + } + sender.close(); + sender.stop(); + sender = null; + + // Restart receiver on same port + receiver = startDcm5Receiver(port, mockConnector); + File dicomFile3 = createDicomTempFile("StopRestart^Restart", "SR003"); + sender = configureDcm5Sender(port, dicomFile3); + + CapturingDimseRspHandler handler3 = new CapturingDimseRspHandler(1); + sender.open(); + sender.send(handler3); + assertTrue("Send after restart should succeed", handler3.awaitResponses(5000)); + assertEquals(Integer.valueOf(0), handler3.getStatuses().get(0)); + } + + @Test + public void testReceiverRejectsOnDispatchError() throws Exception { + int port = allocatePort(); + + // Create a mock SourceConnector where dispatchRawMessage returns an error response + Channel mockChannel = mock(Channel.class); + when(mockChannel.getName()).thenReturn("errorChannel"); + + SourceConnector mockConnector = mock(SourceConnector.class); + when(mockConnector.getChannel()).thenReturn(mockChannel); + when(mockConnector.getChannelId()).thenReturn("errorChannelId"); + + Response errorResponse = new Response( + com.mirth.connect.donkey.model.message.Status.ERROR, + "Simulated dispatch failure"); + DispatchResult errorResult = mock(DispatchResult.class); + when(errorResult.getSelectedResponse()).thenReturn(errorResponse); + when(mockConnector.dispatchRawMessage(any(RawMessage.class))).thenReturn(errorResult); + + receiver = startDcm5Receiver(port, mockConnector); + File dicomFile = createDicomTempFile("Error^Test", "DISP001"); + sender = configureDcm5Sender(port, dicomFile); + + CapturingDimseRspHandler handler = new CapturingDimseRspHandler(1); + sender.open(); + sender.send(handler); + assertTrue("DIMSE response should be received", handler.awaitResponses(5000)); + sender.close(); + + // Receiver should have sent a non-success status back to the sender + assertEquals(1, handler.getStatuses().size()); + int status = handler.getStatuses().get(0); + assertTrue("Status should indicate failure (non-zero), got: 0x" + Integer.toHexString(status), + status != 0); + } +} diff --git a/server/test/com/mirth/connect/connectors/dimse/dicom/integration/Dcm5LoopbackIntegrationTest.java b/server/test/com/mirth/connect/connectors/dimse/dicom/integration/Dcm5LoopbackIntegrationTest.java new file mode 100644 index 0000000000..3be0e081d6 --- /dev/null +++ b/server/test/com/mirth/connect/connectors/dimse/dicom/integration/Dcm5LoopbackIntegrationTest.java @@ -0,0 +1,231 @@ +package com.mirth.connect.connectors.dimse.dicom.integration; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +import java.io.File; +import java.nio.file.Files; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +import org.dcm4che3.data.Tag; +import org.dcm4che3.util.UIDUtils; +import org.junit.Test; +import org.mockito.ArgumentCaptor; + +import com.mirth.connect.connectors.dimse.dicom.OieDicomElement; +import com.mirth.connect.connectors.dimse.dicom.OieDicomObject; +import com.mirth.connect.connectors.dimse.dicom.dcm5.Dcm5DicomConverter; +import com.mirth.connect.connectors.dimse.dicom.dcm5.Dcm5DicomObject; +import com.mirth.connect.donkey.model.message.RawMessage; +import com.mirth.connect.donkey.server.channel.SourceConnector; + +/** + * Integration tests verifying dcm5 sender -> dcm5 receiver over real TCP sockets. + * These are the highest-value tests for the dcm4che5 backend — they prove the + * full DICOM C-STORE lifecycle works end-to-end. + */ +public class Dcm5LoopbackIntegrationTest extends DicomIntegrationTestBase { + + @Test + public void testSendSingleFile() throws Exception { + int port = allocatePort(); + ArgumentCaptor captor = ArgumentCaptor.forClass(RawMessage.class); + SourceConnector mockConnector = createMockSourceConnector(captor); + + receiver = startDcm5Receiver(port, mockConnector); + File dicomFile = createDicomTempFile("Doe^John", "PAT001"); + sender = configureDcm5Sender(port, dicomFile); + + CapturingDimseRspHandler handler = new CapturingDimseRspHandler(1); + sender.open(); + sender.send(handler); + assertTrue("DIMSE response not received within timeout", handler.awaitResponses(5000)); + sender.close(); + + // Verify receiver got the message + RawMessage received = captor.getValue(); + assertNotNull(received); + assertNotNull(received.getRawBytes()); + assertTrue(received.getRawBytes().length > 0); + + // Parse received bytes and verify DICOM data integrity + Dcm5DicomConverter converter = new Dcm5DicomConverter(); + OieDicomObject parsed = converter.byteArrayToDicomObject(received.getRawBytes(), false); + assertEquals("Doe^John", parsed.getString(Tag.PatientName)); + assertEquals("PAT001", parsed.getString(Tag.PatientID)); + + // Verify sender got a success response + assertEquals(1, handler.getStatuses().size()); + assertEquals(Integer.valueOf(0), handler.getStatuses().get(0)); + } + + @Test + public void testSourceMapFromRealAssociation() throws Exception { + int port = allocatePort(); + ArgumentCaptor captor = ArgumentCaptor.forClass(RawMessage.class); + SourceConnector mockConnector = createMockSourceConnector(captor); + + receiver = startDcm5Receiver(port, mockConnector); + File dicomFile = createDicomTempFile("Smith^Jane", "PAT002"); + sender = configureDcm5Sender(port, dicomFile); + + CapturingDimseRspHandler handler = new CapturingDimseRspHandler(1); + sender.open(); + sender.send(handler); + assertTrue("DIMSE response not received within timeout", handler.awaitResponses(5000)); + sender.close(); + + RawMessage received = captor.getValue(); + Map sourceMap = received.getSourceMap(); + assertNotNull(sourceMap); + + // Verify key sourceMap entries from a real association (not mocked) + assertNotNull("localApplicationEntityTitle", sourceMap.get("localApplicationEntityTitle")); + assertEquals("TEST_SCU", sourceMap.get("remoteApplicationEntityTitle")); + assertNotNull("localAddress should be set", sourceMap.get("localAddress")); + assertEquals(port, sourceMap.get("localPort")); + assertNotNull("remoteAddress should be set", sourceMap.get("remoteAddress")); + assertNotNull("remotePort should be set", sourceMap.get("remotePort")); + + // Association metadata from a real DICOM handshake + assertNotNull("associateRQImplClassUID should be set", sourceMap.get("associateRQImplClassUID")); + } + + @Test + public void testSendMultipleFiles() throws Exception { + int port = allocatePort(); + ArgumentCaptor captor = ArgumentCaptor.forClass(RawMessage.class); + SourceConnector mockConnector = createMockSourceConnector(captor); + + receiver = startDcm5Receiver(port, mockConnector); + + File file1 = createDicomTempFile("Alpha^Patient", "MULTI001"); + File file2 = createDicomTempFile("Beta^Patient", "MULTI002"); + File file3 = createDicomTempFile("Gamma^Patient", "MULTI003"); + + sender = configureDcm5Sender(port, file1, file2, file3); + + CapturingDimseRspHandler handler = new CapturingDimseRspHandler(3); + sender.open(); + sender.send(handler); + assertTrue("All DIMSE responses not received within timeout", handler.awaitResponses(10000)); + sender.close(); + + // Verify all 3 messages were dispatched + List allMessages = captor.getAllValues(); + assertEquals(3, allMessages.size()); + + // Verify each message has valid DICOM data + Dcm5DicomConverter converter = new Dcm5DicomConverter(); + List receivedNames = new ArrayList<>(); + for (RawMessage msg : allMessages) { + assertNotNull(msg.getRawBytes()); + OieDicomObject parsed = converter.byteArrayToDicomObject(msg.getRawBytes(), false); + receivedNames.add(parsed.getString(Tag.PatientName)); + } + + assertTrue("Should contain Alpha^Patient", receivedNames.contains("Alpha^Patient")); + assertTrue("Should contain Beta^Patient", receivedNames.contains("Beta^Patient")); + assertTrue("Should contain Gamma^Patient", receivedNames.contains("Gamma^Patient")); + + // All 3 should have success status + assertEquals(3, handler.getStatuses().size()); + for (int status : handler.getStatuses()) { + assertEquals(0, status); + } + } + + @Test + public void testFullLifecycleNoExceptions() throws Exception { + int port = allocatePort(); + ArgumentCaptor captor = ArgumentCaptor.forClass(RawMessage.class); + SourceConnector mockConnector = createMockSourceConnector(captor); + + receiver = startDcm5Receiver(port, mockConnector); + File dicomFile = createDicomTempFile("Lifecycle^Test", "LIFE001"); + sender = configureDcm5Sender(port, dicomFile); + + CapturingDimseRspHandler handler = new CapturingDimseRspHandler(1); + sender.open(); + sender.send(handler); + assertTrue("DIMSE response not received", handler.awaitResponses(5000)); + sender.close(); + sender.stop(); + sender = null; + + receiver.stop(); + receiver = null; + } + + @Test + public void testSendWithSequenceAndFragmentData() throws Exception { + int port = allocatePort(); + ArgumentCaptor captor = ArgumentCaptor.forClass(RawMessage.class); + SourceConnector mockConnector = createMockSourceConnector(captor); + + receiver = startDcm5Receiver(port, mockConnector); + + // Build a DICOM object with a nested sequence and encapsulated pixel data fragments + Dcm5DicomConverter converter = new Dcm5DicomConverter(); + Dcm5DicomObject obj = (Dcm5DicomObject) converter.createDicomObject(); + obj.putString(Tag.PatientName, "PN", "Complex^Data"); + obj.putString(Tag.PatientID, "LO", "SEQ001"); + obj.putString(Tag.Modality, "CS", "CT"); + obj.putString(Tag.StudyInstanceUID, "UI", UIDUtils.createUID()); + obj.putString(Tag.SeriesInstanceUID, "UI", UIDUtils.createUID()); + obj.putString(Tag.SOPInstanceUID, "UI", UIDUtils.createUID()); + + // Add a Referenced Study Sequence with a nested item + OieDicomElement seq = obj.putSequence(Tag.ReferencedStudySequence); + OieDicomObject seqItem = converter.createDicomObject(); + seqItem.putString(Tag.ReferencedSOPClassUID, "UI", "1.2.840.10008.3.1.2.3.1"); + seqItem.putString(Tag.ReferencedSOPInstanceUID, "UI", UIDUtils.createUID()); + seq.addDicomObject(seqItem); + + // Add encapsulated pixel data (OB fragments with small synthetic frames) + OieDicomElement frags = obj.putFragments(Tag.PixelData, "OB", false, 3); + frags.addFragment(new byte[0]); // offset table (empty) + frags.addFragment(new byte[] { (byte) 0xFF, (byte) 0xD8, 0x01, 0x02 }); // frame 1 + frags.addFragment(new byte[] { (byte) 0xFF, (byte) 0xD8, 0x03, 0x04 }); // frame 2 + + obj.initFileMetaInformation( + "1.2.840.10008.5.1.4.1.1.2", + UIDUtils.createUID(), + "1.2.840.10008.1.2"); + byte[] bytes = converter.dicomObjectToByteArray(obj); + File tempFile = tempFolder.newFile("complex.dcm"); + Files.write(tempFile.toPath(), bytes); + + sender = configureDcm5Sender(port, tempFile); + + CapturingDimseRspHandler handler = new CapturingDimseRspHandler(1); + sender.open(); + sender.send(handler); + assertTrue("DIMSE response not received", handler.awaitResponses(5000)); + sender.close(); + + // Verify complex data survived the network round-trip + RawMessage received = captor.getValue(); + assertNotNull(received); + Dcm5DicomConverter parseConverter = new Dcm5DicomConverter(); + OieDicomObject parsed = parseConverter.byteArrayToDicomObject(received.getRawBytes(), false); + assertEquals("Complex^Data", parsed.getString(Tag.PatientName)); + + // Verify sequence survived + OieDicomElement parsedSeq = parsed.get(Tag.ReferencedStudySequence); + assertNotNull("Sequence should survive network transfer", parsedSeq); + assertTrue("Sequence should have items", parsedSeq.hasItems()); + assertEquals(1, parsedSeq.countItems()); + assertEquals("1.2.840.10008.3.1.2.3.1", + parsedSeq.getDicomObject().getString(Tag.ReferencedSOPClassUID)); + + // Verify pixel data fragments survived + OieDicomElement parsedFrags = parsed.get(Tag.PixelData); + assertNotNull("Pixel data should survive network transfer", parsedFrags); + + assertEquals(Integer.valueOf(0), handler.getStatuses().get(0)); + } +} diff --git a/server/test/com/mirth/connect/connectors/dimse/dicom/integration/Dcm5StorageCommitmentIntegrationTest.java b/server/test/com/mirth/connect/connectors/dimse/dicom/integration/Dcm5StorageCommitmentIntegrationTest.java new file mode 100644 index 0000000000..d72478f7b9 --- /dev/null +++ b/server/test/com/mirth/connect/connectors/dimse/dicom/integration/Dcm5StorageCommitmentIntegrationTest.java @@ -0,0 +1,186 @@ +package com.mirth.connect.connectors.dimse.dicom.integration; + +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +import java.io.File; +import java.io.IOException; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.ScheduledExecutorService; + +import org.dcm4che3.data.Attributes; +import org.dcm4che3.data.Tag; +import org.dcm4che3.data.UID; +import org.dcm4che3.data.VR; +import org.dcm4che3.net.ApplicationEntity; +import org.dcm4che3.net.Association; +import org.dcm4che3.net.Commands; +import org.dcm4che3.net.Connection; +import org.dcm4che3.net.Device; +import org.dcm4che3.net.Dimse; +import org.dcm4che3.net.PDVInputStream; +import org.dcm4che3.net.Status; +import org.dcm4che3.net.TransferCapability; +import org.dcm4che3.net.pdu.PresentationContext; +import org.dcm4che3.net.service.AbstractDicomService; +import org.dcm4che3.net.service.BasicCEchoSCP; +import org.dcm4che3.net.service.BasicCStoreSCP; +import org.dcm4che3.net.service.DicomServiceRegistry; +import org.junit.Test; + +import com.mirth.connect.connectors.dimse.dicom.OieDicomObject; + +/** + * Integration test for the dcm5 sender's storage commitment protocol flow. + * + *

Uses a custom test SCP (not Dcm5DicomReceiver) that handles both C-STORE + * and N-ACTION (Storage Commitment), then responds with N-EVENT-REPORT. This + * tests the sender's commit() and waitForStgCmtResult() methods end-to-end. + */ +public class Dcm5StorageCommitmentIntegrationTest extends DicomIntegrationTestBase { + + private Device scpDevice; + private ExecutorService scpExecutor; + private ScheduledExecutorService scpScheduled; + + @Override + public void tearDown() { + if (scpDevice != null) { + scpDevice.unbindConnections(); + } + if (scpExecutor != null) { + scpExecutor.shutdownNow(); + } + if (scpScheduled != null) { + scpScheduled.shutdownNow(); + } + super.tearDown(); + } + + @Test + public void testStorageCommitmentEndToEnd() throws Exception { + int port = allocatePort(); + + // Build a test SCP that accepts C-STORE and handles storage commitment N-ACTION + startStgCmtScp(port); + + File dicomFile = createDicomTempFile("StgCmt^Test", "STGCMT001"); + + // Build sender manually (not via helper) so we can enable storage commitment before start() + sender = new com.mirth.connect.connectors.dimse.dicom.dcm5.Dcm5DicomSender(new TestConfig()); + sender.setRemoteHost("127.0.0.1"); + sender.setRemotePort(port); + sender.setCalledAET("STGCMT_SCP"); + sender.setCalling("TEST_SCU"); + sender.setStorageCommitment(true); + sender.addFile(dicomFile); + sender.configureTransferCapability(); + sender.start(); + + CapturingDimseRspHandler handler = new CapturingDimseRspHandler(1); + sender.open(); + sender.send(handler); + assertTrue("C-STORE response not received", handler.awaitResponses(5000)); + + // Request storage commitment + boolean commitResult = sender.commit(); + assertTrue("commit() should return true", commitResult); + + // Wait for the N-EVENT-REPORT from the SCP + OieDicomObject stgCmtResult = sender.waitForStgCmtResult(); + assertNotNull("Storage commitment result should not be null", stgCmtResult); + + sender.close(); + } + + /** + * Starts a raw dcm4che5 SCP that accepts C-STORE and responds to + * Storage Commitment N-ACTION by sending back an N-EVENT-REPORT with success. + */ + private void startStgCmtScp(int port) throws Exception { + scpDevice = new Device("STGCMT_SCP"); + Connection conn = new Connection(); + conn.setHostname("127.0.0.1"); + conn.setPort(port); + scpDevice.addConnection(conn); + + ApplicationEntity ae = new ApplicationEntity("STGCMT_SCP"); + ae.setAssociationAcceptor(true); + ae.addConnection(conn); + scpDevice.addApplicationEntity(ae); + + // Accept any SOP class for C-STORE, plus Verification and Storage Commitment + ae.addTransferCapability(new TransferCapability(null, "*", + TransferCapability.Role.SCP, "1.2.840.10008.1.2", "1.2.840.10008.1.2.1")); + ae.addTransferCapability(new TransferCapability(null, UID.Verification, + TransferCapability.Role.SCP, UID.ImplicitVRLittleEndian)); + ae.addTransferCapability(new TransferCapability(null, UID.StorageCommitmentPushModel, + TransferCapability.Role.SCP, UID.ImplicitVRLittleEndian)); + + DicomServiceRegistry services = new DicomServiceRegistry(); + services.addDicomService(new BasicCEchoSCP()); + + // C-STORE handler — just accept everything + services.addDicomService(new BasicCStoreSCP("*") { + @Override + protected void store(Association as, PresentationContext pc, Attributes rq, + PDVInputStream data, Attributes rsp) throws IOException { + // Read and discard the data stream to complete the transfer + data.skipAll(); + } + }); + + // Storage Commitment N-ACTION handler — respond with success N-EVENT-REPORT + services.addDicomService(new AbstractDicomService(UID.StorageCommitmentPushModel) { + @Override + public void onDimseRQ(Association as, PresentationContext pc, + Dimse dimse, Attributes rq, Attributes data) throws IOException { + if (dimse == Dimse.N_ACTION_RQ) { + // Send N-ACTION response (success) + Attributes actionRsp = Commands.mkNActionRSP(rq, Status.Success); + as.tryWriteDimseRSP(pc, actionRsp); + + // Now send N-EVENT-REPORT back to the sender with the committed references + try { + Attributes eventInfo = new Attributes(); + eventInfo.setString(Tag.TransactionUID, VR.UI, + data.getString(Tag.TransactionUID)); + + // Copy the ReferencedSOPSequence from the action data + org.dcm4che3.data.Sequence srcSeq = data.getSequence(Tag.ReferencedSOPSequence); + if (srcSeq != null) { + org.dcm4che3.data.Sequence destSeq = + eventInfo.newSequence(Tag.ReferencedSOPSequence, srcSeq.size()); + for (Attributes item : srcSeq) { + destSeq.add(new Attributes(item)); + } + } + + // Open a reverse association to deliver N-EVENT-REPORT + // In dcm4che5, the SCP typically sends N-EVENT-REPORT on a new association + // to the SCU. But some implementations send it on the same association. + // For simplicity, send on the existing association using the same PC. + as.neventReport( + UID.StorageCommitmentPushModel, + UID.StorageCommitmentPushModelInstance, + 1, // eventTypeID = 1 (Storage Commitment Request Successful) + eventInfo, UID.ImplicitVRLittleEndian, + new org.dcm4che3.net.DimseRSPHandler(as.nextMessageID())); + } catch (Exception e) { + throw new IOException("Failed to send N-EVENT-REPORT", e); + } + } + } + }); + + scpDevice.setDimseRQHandler(services); + + scpExecutor = Executors.newCachedThreadPool(); + scpScheduled = Executors.newSingleThreadScheduledExecutor(); + scpDevice.setExecutor(scpExecutor); + scpDevice.setScheduledExecutor(scpScheduled); + scpDevice.bindConnections(); + waitForPort(port, 2000); + } +} diff --git a/server/test/com/mirth/connect/connectors/dimse/dicom/integration/Dcm5TlsIntegrationTest.java b/server/test/com/mirth/connect/connectors/dimse/dicom/integration/Dcm5TlsIntegrationTest.java new file mode 100644 index 0000000000..5a078db23a --- /dev/null +++ b/server/test/com/mirth/connect/connectors/dimse/dicom/integration/Dcm5TlsIntegrationTest.java @@ -0,0 +1,164 @@ +package com.mirth.connect.connectors.dimse.dicom.integration; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +import java.io.File; +import java.io.FileOutputStream; +import java.math.BigInteger; +import java.security.KeyPair; +import java.security.KeyPairGenerator; +import java.security.KeyStore; +import java.security.SecureRandom; +import java.security.Security; +import java.security.cert.Certificate; +import java.security.cert.X509Certificate; +import java.util.Date; + +import javax.security.auth.x500.X500Principal; + +import org.bouncycastle.cert.X509v3CertificateBuilder; +import org.bouncycastle.cert.jcajce.JcaX509CertificateConverter; +import org.bouncycastle.cert.jcajce.JcaX509v3CertificateBuilder; +import org.bouncycastle.jce.provider.BouncyCastleProvider; +import org.bouncycastle.operator.ContentSigner; +import org.bouncycastle.operator.jcajce.JcaContentSignerBuilder; +import org.dcm4che3.data.Tag; +import org.junit.Test; +import org.mockito.ArgumentCaptor; + +import com.mirth.connect.connectors.dimse.dicom.OieDicomObject; +import com.mirth.connect.connectors.dimse.dicom.dcm5.Dcm5DicomConverter; +import com.mirth.connect.connectors.dimse.dicom.dcm5.Dcm5DicomReceiver; +import com.mirth.connect.connectors.dimse.dicom.dcm5.Dcm5DicomSender; +import com.mirth.connect.donkey.model.message.RawMessage; +import com.mirth.connect.donkey.server.channel.SourceConnector; + +/** + * Integration test verifying TLS-encrypted DICOM communication through the + * production Dcm5DicomReceiver and Dcm5DicomSender code paths. Generates + * ephemeral self-signed keystores at test time. + * + *

Uses the new setTlsCipherSuites() and setKeyStoreType() interface methods + * to configure modern cipher suites (the legacy preset methods use suites + * disabled in Java 21). + */ +public class Dcm5TlsIntegrationTest extends DicomIntegrationTestBase { + + // Cipher suite supported in Java 21 with RSA keys + private static final String[] CIPHER_SUITES = { "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256" }; + private static final String[] PROTOCOLS = { "TLSv1.2" }; + + @Test + public void testTlsEncryptedCStore() throws Exception { + // Generate ephemeral keystore and truststore + KeyStore ks = generateSelfSignedKeyStore("CN=DICOM-Test", "changeit"); + File keyStoreFile = tempFolder.newFile("test-keystore.jks"); + File trustStoreFile = tempFolder.newFile("test-truststore.jks"); + + try (FileOutputStream fos = new FileOutputStream(keyStoreFile)) { + ks.store(fos, "changeit".toCharArray()); + } + KeyStore ts = KeyStore.getInstance("JKS"); + ts.load(null, "changeit".toCharArray()); + ts.setCertificateEntry("test", ks.getCertificate("key")); + try (FileOutputStream fos = new FileOutputStream(trustStoreFile)) { + ts.store(fos, "changeit".toCharArray()); + } + + String ksUrl = keyStoreFile.toURI().toString(); + String tsUrl = trustStoreFile.toURI().toString(); + int port = allocatePort(); + + ArgumentCaptor captor = ArgumentCaptor.forClass(RawMessage.class); + SourceConnector mockConnector = createMockSourceConnector(captor); + + // Configure TLS receiver through the production code path + Dcm5DicomReceiver rcv = new Dcm5DicomReceiver(mockConnector, new TestConfig()); + rcv.setHostname("127.0.0.1"); + rcv.setPort(port); + rcv.setAEtitle("TLS_SCP"); + rcv.setTransferSyntax(new String[] { "1.2.840.10008.1.2", "1.2.840.10008.1.2.1" }); + rcv.setTlsCipherSuites(CIPHER_SUITES); + rcv.setTlsProtocol(PROTOCOLS); + rcv.setTlsNeedClientAuth(true); + rcv.setKeyStoreURL(ksUrl); + rcv.setKeyStorePassword("changeit"); + rcv.setKeyPassword("changeit"); + rcv.setKeyStoreType("JKS"); + rcv.setTrustStoreURL(tsUrl); + rcv.setTrustStorePassword("changeit"); + rcv.setTrustStoreType("JKS"); + rcv.initTLS(); + rcv.initTransferCapability(); + rcv.start(); + receiver = rcv; + waitForPort(port, 3000); + + // Configure TLS sender through the production code path + File dicomFile = createDicomTempFile("Tls^Test", "TLS001"); + Dcm5DicomSender snd = new Dcm5DicomSender(new TestConfig()); + snd.setRemoteHost("127.0.0.1"); + snd.setRemotePort(port); + snd.setCalledAET("TLS_SCP"); + snd.setCalling("TLS_SCU"); + snd.setTlsCipherSuites(CIPHER_SUITES); + snd.setTlsProtocol(PROTOCOLS); + snd.setKeyStoreURL(ksUrl); + snd.setKeyStorePassword("changeit"); + snd.setKeyPassword("changeit"); + snd.setKeyStoreType("JKS"); + snd.setTrustStoreURL(tsUrl); + snd.setTrustStorePassword("changeit"); + snd.setTrustStoreType("JKS"); + snd.initTLS(); + snd.addFile(dicomFile); + snd.configureTransferCapability(); + snd.start(); + sender = snd; + + CapturingDimseRspHandler handler = new CapturingDimseRspHandler(1); + sender.open(); + sender.send(handler); + assertTrue("TLS DIMSE response not received", handler.awaitResponses(5000)); + sender.close(); + + // Verify data integrity over TLS + RawMessage received = captor.getValue(); + assertNotNull("Message should be received over TLS", received); + Dcm5DicomConverter converter = new Dcm5DicomConverter(); + OieDicomObject parsed = converter.byteArrayToDicomObject(received.getRawBytes(), false); + assertEquals("Tls^Test", parsed.getString(Tag.PatientName)); + assertEquals("TLS001", parsed.getString(Tag.PatientID)); + assertEquals(Integer.valueOf(0), handler.getStatuses().get(0)); + } + + private KeyStore generateSelfSignedKeyStore(String dn, String password) throws Exception { + if (Security.getProvider("BC") == null) { + Security.addProvider(new BouncyCastleProvider()); + } + + KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA"); + kpg.initialize(2048, new SecureRandom()); + KeyPair kp = kpg.generateKeyPair(); + + X500Principal subject = new X500Principal(dn); + long now = System.currentTimeMillis(); + Date notBefore = new Date(now); + Date notAfter = new Date(now + 365L * 24 * 60 * 60 * 1000); + + X509v3CertificateBuilder builder = new JcaX509v3CertificateBuilder( + subject, BigInteger.valueOf(now), notBefore, notAfter, subject, kp.getPublic()); + + ContentSigner signer = new JcaContentSignerBuilder("SHA256WithRSA") + .setProvider("BC").build(kp.getPrivate()); + X509Certificate cert = new JcaX509CertificateConverter() + .setProvider("BC").getCertificate(builder.build(signer)); + + KeyStore keyStore = KeyStore.getInstance("JKS"); + keyStore.load(null, password.toCharArray()); + keyStore.setKeyEntry("key", kp.getPrivate(), password.toCharArray(), new Certificate[] { cert }); + return keyStore; + } +} diff --git a/server/test/com/mirth/connect/connectors/dimse/dicom/integration/DicomIntegrationTestBase.java b/server/test/com/mirth/connect/connectors/dimse/dicom/integration/DicomIntegrationTestBase.java new file mode 100644 index 0000000000..7474e68b0c --- /dev/null +++ b/server/test/com/mirth/connect/connectors/dimse/dicom/integration/DicomIntegrationTestBase.java @@ -0,0 +1,230 @@ +package com.mirth.connect.connectors.dimse.dicom.integration; + +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +import java.io.File; +import java.io.IOException; +import java.net.ServerSocket; +import java.nio.file.Files; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; + +import org.dcm4che3.data.Tag; +import org.dcm4che3.util.UIDUtils; +import org.junit.After; +import org.junit.Before; +import org.junit.Rule; +import org.junit.rules.TemporaryFolder; +import org.mockito.ArgumentCaptor; + +import com.mirth.connect.connectors.dimse.DICOMConfiguration; +import com.mirth.connect.connectors.dimse.DICOMDispatcher; +import com.mirth.connect.connectors.dimse.DICOMDispatcherProperties; +import com.mirth.connect.connectors.dimse.DICOMReceiver; +import com.mirth.connect.connectors.dimse.DICOMReceiverProperties; +import com.mirth.connect.connectors.dimse.dicom.DicomLibraryFactory; +import com.mirth.connect.connectors.dimse.dicom.DicomLibraryFactory.DicomLibrary; +import com.mirth.connect.connectors.dimse.dicom.OieDicomObject; +import com.mirth.connect.connectors.dimse.dicom.OieDicomReceiver; +import com.mirth.connect.connectors.dimse.dicom.OieDicomSender; +import com.mirth.connect.connectors.dimse.dicom.OieDimseRspHandler; +import com.mirth.connect.connectors.dimse.dicom.dcm5.Dcm5DicomConverter; +import com.mirth.connect.connectors.dimse.dicom.dcm5.Dcm5DicomObject; +import com.mirth.connect.connectors.dimse.dicom.dcm5.Dcm5DicomReceiver; +import com.mirth.connect.connectors.dimse.dicom.dcm5.Dcm5DicomSender; +import com.mirth.connect.donkey.model.message.RawMessage; +import com.mirth.connect.donkey.server.channel.Channel; +import com.mirth.connect.donkey.server.channel.Connector; +import com.mirth.connect.donkey.server.channel.DispatchResult; +import com.mirth.connect.donkey.server.channel.SourceConnector; + +/** + * Shared base class for DICOM integration tests. Provides port allocation, + * temp DICOM file creation, mock setup, and receiver/sender lifecycle helpers. + */ +public abstract class DicomIntegrationTestBase { + + @Rule + public TemporaryFolder tempFolder = new TemporaryFolder(); + + protected Dcm5DicomReceiver receiver; + protected Dcm5DicomSender sender; + + @Before + public void setUpFactory() { + DicomLibraryFactory.resetForTesting(DicomLibrary.DCM4CHE5); + } + + @After + public void tearDown() { + if (sender != null) { + try { sender.close(); } catch (Exception e) { /* ignore */ } + try { sender.stop(); } catch (Exception e) { /* ignore */ } + sender = null; + } + if (receiver != null) { + try { receiver.stop(); } catch (Exception e) { /* ignore */ } + receiver = null; + } + DicomLibraryFactory.resetForTesting(null); + } + + /** + * Allocate a free port using ServerSocket(0). The tiny TOCTOU race + * between close and re-bind is acceptable for localhost integration tests. + */ + protected int allocatePort() throws IOException { + try (ServerSocket ss = new ServerSocket(0)) { + ss.setReuseAddress(true); + return ss.getLocalPort(); + } + } + + /** + * Creates a temp DICOM file with the given patient data, FMI (CT Image Storage, + * Implicit VR Little Endian), and a generated SOP Instance UID. + */ + protected File createDicomTempFile(String patientName, String patientId) throws IOException { + Dcm5DicomConverter converter = new Dcm5DicomConverter(); + Dcm5DicomObject obj = (Dcm5DicomObject) converter.createDicomObject(); + obj.putString(Tag.PatientName, "PN", patientName); + obj.putString(Tag.PatientID, "LO", patientId); + obj.putString(Tag.StudyInstanceUID, "UI", UIDUtils.createUID()); + obj.putString(Tag.SeriesInstanceUID, "UI", UIDUtils.createUID()); + obj.putString(Tag.SOPInstanceUID, "UI", UIDUtils.createUID()); + obj.putString(Tag.Modality, "CS", "CT"); + // CT Image Storage SOP Class, Implicit VR Little Endian + obj.initFileMetaInformation( + "1.2.840.10008.5.1.4.1.1.2", + UIDUtils.createUID(), + "1.2.840.10008.1.2"); + byte[] bytes = converter.dicomObjectToByteArray(obj); + File tempFile = tempFolder.newFile(patientId + ".dcm"); + Files.write(tempFile.toPath(), bytes); + return tempFile; + } + + /** + * Creates a Mockito mock of SourceConnector wired for DICOM receiver integration tests. + * The captor captures RawMessage objects passed to dispatchRawMessage(). + */ + protected SourceConnector createMockSourceConnector(ArgumentCaptor captor) throws Exception { + Channel mockChannel = mock(Channel.class); + when(mockChannel.getName()).thenReturn("testChannel"); + + SourceConnector mockConnector = mock(SourceConnector.class); + when(mockConnector.getChannel()).thenReturn(mockChannel); + when(mockConnector.getChannelId()).thenReturn("testChannelId"); + + DispatchResult mockResult = mock(DispatchResult.class); + when(mockResult.getSelectedResponse()).thenReturn(null); + when(mockConnector.dispatchRawMessage(captor.capture())).thenReturn(mockResult); + + return mockConnector; + } + + /** + * Creates and starts a Dcm5DicomReceiver on the given port with standard config. + */ + protected Dcm5DicomReceiver startDcm5Receiver(int port, SourceConnector mockConnector) throws Exception { + Dcm5DicomReceiver rcv = new Dcm5DicomReceiver(mockConnector, new TestConfig()); + rcv.setHostname("127.0.0.1"); + rcv.setPort(port); + rcv.setAEtitle("TEST_SCP"); + rcv.setTransferSyntax(new String[] { "1.2.840.10008.1.2", "1.2.840.10008.1.2.1" }); + rcv.initTransferCapability(); + rcv.start(); + waitForPort(port, 2000); + return rcv; + } + + /** + * Creates and starts a Dcm5DicomSender configured to connect to localhost:port. + */ + protected Dcm5DicomSender configureDcm5Sender(int port, File... dicomFiles) throws Exception { + Dcm5DicomSender snd = new Dcm5DicomSender(new TestConfig()); + snd.setRemoteHost("127.0.0.1"); + snd.setRemotePort(port); + snd.setCalledAET("TEST_SCP"); + snd.setCalling("TEST_SCU"); + for (File f : dicomFiles) { + snd.addFile(f); + } + snd.configureTransferCapability(); + snd.start(); + return snd; + } + + /** + * Polls until a TCP connection to localhost:port succeeds, or timeout expires. + */ + protected void waitForPort(int port, long timeoutMs) throws Exception { + long deadline = System.currentTimeMillis() + timeoutMs; + while (System.currentTimeMillis() < deadline) { + try { + new java.net.Socket("127.0.0.1", port).close(); + return; + } catch (IOException e) { + Thread.sleep(50); + } + } + throw new IOException("Port " + port + " not ready after " + timeoutMs + "ms"); + } + + /** + * DIMSE response handler that captures responses and provides a latch for synchronization. + * dcm4che5's cstore() is async — the response handler fires on a worker thread after + * send() returns. Use awaitResponses() to block until all expected responses arrive. + */ + protected static class CapturingDimseRspHandler implements OieDimseRspHandler { + private final CountDownLatch latch; + private final List statuses = Collections.synchronizedList(new ArrayList<>()); + + public CapturingDimseRspHandler(int expectedResponses) { + this.latch = new CountDownLatch(expectedResponses); + } + + @Override + public void onDimseRSP(OieDicomObject cmd, OieDicomObject data) { + if (cmd != null) { + statuses.add(cmd.getInt(Tag.Status)); + } + latch.countDown(); + } + + public boolean awaitResponses(long timeoutMs) throws InterruptedException { + return latch.await(timeoutMs, TimeUnit.MILLISECONDS); + } + + public List getStatuses() { + return statuses; + } + } + + /** + * Minimal DICOMConfiguration for testing — no ControllerFactory dependencies. + */ + protected static class TestConfig implements DICOMConfiguration { + @Override + public void configureConnectorDeploy(Connector connector) {} + + @Override + public void configureReceiver(OieDicomReceiver receiver, DICOMReceiver connector, + DICOMReceiverProperties connectorProperties) {} + + @Override + public void configureSender(OieDicomSender sender, DICOMDispatcher connector, + DICOMDispatcherProperties connectorProperties) {} + + @Override + public Map getCStoreRequestInformation(Object association) { + return new HashMap<>(); + } + } +} diff --git a/server/test/com/mirth/connect/connectors/dimse/dicom/integration/DicomPerformanceBenchmark.java b/server/test/com/mirth/connect/connectors/dimse/dicom/integration/DicomPerformanceBenchmark.java new file mode 100644 index 0000000000..7efd74c5ba --- /dev/null +++ b/server/test/com/mirth/connect/connectors/dimse/dicom/integration/DicomPerformanceBenchmark.java @@ -0,0 +1,494 @@ +package com.mirth.connect.connectors.dimse.dicom.integration; + +import java.io.File; +import java.io.IOException; +import java.nio.file.Files; +import java.util.ArrayList; +import java.util.List; + +import org.dcm4che3.data.Tag; +import org.dcm4che3.util.UIDUtils; +import org.junit.After; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.TemporaryFolder; +import org.mockito.ArgumentCaptor; + +import com.mirth.connect.connectors.dimse.dicom.DicomLibraryFactory; +import com.mirth.connect.connectors.dimse.dicom.DicomLibraryFactory.DicomLibrary; +import com.mirth.connect.connectors.dimse.dicom.OieDicomConverter; +import com.mirth.connect.connectors.dimse.dicom.OieDicomObject; +import com.mirth.connect.connectors.dimse.dicom.dcm2.Dcm2DicomConverter; +import com.mirth.connect.connectors.dimse.dicom.dcm2.Dcm2DicomReceiver; +import com.mirth.connect.connectors.dimse.dicom.dcm2.Dcm2DicomSender; +import com.mirth.connect.connectors.dimse.dicom.dcm5.Dcm5DicomConverter; +import com.mirth.connect.connectors.dimse.dicom.dcm5.Dcm5DicomObject; +import com.mirth.connect.connectors.dimse.dicom.dcm5.Dcm5DicomReceiver; +import com.mirth.connect.connectors.dimse.dicom.dcm5.Dcm5DicomSender; +import com.mirth.connect.donkey.model.message.RawMessage; +import com.mirth.connect.donkey.server.channel.SourceConnector; + +/** + * Performance benchmark comparing dcm4che2 and dcm4che5 backends. + * + *

Measures converter throughput (serialize/deserialize/XML), network C-STORE + * throughput, and memory usage. Results are printed as formatted comparison tables. + * + *

This is not a regression gate — it produces data for human review. Run with: + *

+ * ./gradlew :server:test --tests "*.DicomPerformanceBenchmark" --info
+ * 
+ */ +public class DicomPerformanceBenchmark extends DicomIntegrationTestBase { + + // Benchmark parameters + private static final int WARMUP_ITERATIONS = 50; + private static final int MEASURE_ITERATIONS = 200; + private static final int NETWORK_WARMUP = 5; + private static final int NETWORK_MEASURE = 50; + + private Dcm2DicomReceiver dcm2Receiver; + private Dcm2DicomSender dcm2Sender; + + @Override + public void tearDown() { + if (dcm2Sender != null) { + try { dcm2Sender.close(); } catch (Exception e) { /* ignore */ } + try { dcm2Sender.stop(); } catch (Exception e) { /* ignore */ } + dcm2Sender = null; + } + if (dcm2Receiver != null) { + try { dcm2Receiver.stop(); } catch (Exception e) { /* ignore */ } + dcm2Receiver = null; + } + super.tearDown(); + } + + @Test + public void benchmarkConverterSerialization() throws Exception { + System.out.println("\n========== CONVERTER: dicomObjectToByteArray =========="); + System.out.printf("%-12s %12s %12s %12s%n", "Backend", "Ops/sec", "Avg (ms)", "Mem (KB)"); + System.out.println("----------------------------------------------------"); + + // dcm4che2 + BenchmarkResult dcm2Result = benchmarkSerialization(new Dcm2DicomConverter(), "dcm2"); + printRow("dcm4che2", dcm2Result); + + // dcm4che5 + BenchmarkResult dcm5Result = benchmarkSerialization(new Dcm5DicomConverter(), "dcm5"); + printRow("dcm4che5", dcm5Result); + + printSpeedup(dcm2Result, dcm5Result); + } + + @Test + public void benchmarkConverterDeserialization() throws Exception { + System.out.println("\n========== CONVERTER: byteArrayToDicomObject =========="); + System.out.printf("%-12s %12s %12s %12s%n", "Backend", "Ops/sec", "Avg (ms)", "Mem (KB)"); + System.out.println("----------------------------------------------------"); + + // Prepare test data + Dcm2DicomConverter dcm2Conv = new Dcm2DicomConverter(); + byte[] dcm2Bytes = createTestBytes(dcm2Conv); + + Dcm5DicomConverter dcm5Conv = new Dcm5DicomConverter(); + byte[] dcm5Bytes = createTestBytes(dcm5Conv); + + // dcm4che2 + BenchmarkResult dcm2Result = benchmarkDeserialization(dcm2Conv, dcm2Bytes); + printRow("dcm4che2", dcm2Result); + + // dcm4che5 + BenchmarkResult dcm5Result = benchmarkDeserialization(dcm5Conv, dcm5Bytes); + printRow("dcm4che5", dcm5Result); + + printSpeedup(dcm2Result, dcm5Result); + } + + @Test + public void benchmarkConverterXml() throws Exception { + System.out.println("\n========== CONVERTER: dicomBytesToXml =========="); + System.out.printf("%-12s %12s %12s %12s%n", "Backend", "Ops/sec", "Avg (ms)", "Mem (KB)"); + System.out.println("----------------------------------------------------"); + + // Prepare base64-encoded test data + Dcm2DicomConverter dcm2Conv = new Dcm2DicomConverter(); + byte[] dcm2Raw = createTestBytes(dcm2Conv); + byte[] dcm2B64 = java.util.Base64.getEncoder().encode(dcm2Raw); + + Dcm5DicomConverter dcm5Conv = new Dcm5DicomConverter(); + byte[] dcm5Raw = createTestBytes(dcm5Conv); + byte[] dcm5B64 = java.util.Base64.getEncoder().encode(dcm5Raw); + + // dcm4che2 + BenchmarkResult dcm2Result = benchmarkXmlConversion(dcm2Conv, dcm2B64); + printRow("dcm4che2", dcm2Result); + + // dcm4che5 + BenchmarkResult dcm5Result = benchmarkXmlConversion(dcm5Conv, dcm5B64); + printRow("dcm4che5", dcm5Result); + + printSpeedup(dcm2Result, dcm5Result); + } + + @Test + public void benchmarkNetworkCStoreDcm5() throws Exception { + System.out.println("\n========== NETWORK: dcm5 sender → dcm5 receiver (C-STORE) =========="); + System.out.printf("%-12s %12s %12s %12s%n", "Phase", "Ops/sec", "Avg (ms)", "Total (ms)"); + System.out.println("----------------------------------------------------"); + + int port = allocatePort(); + ArgumentCaptor captor = ArgumentCaptor.forClass(RawMessage.class); + SourceConnector mockConnector = createMockSourceConnector(captor); + receiver = startDcm5Receiver(port, mockConnector); + + // Create test files + List files = new ArrayList<>(); + for (int i = 0; i < NETWORK_WARMUP + NETWORK_MEASURE; i++) { + files.add(createDicomTempFile("Bench^Patient" + i, "BENCH" + String.format("%04d", i))); + } + + // Warmup + for (int i = 0; i < NETWORK_WARMUP; i++) { + sendOneDcm5File(port, files.get(i)); + } + + // Measure + long[] latencies = new long[NETWORK_MEASURE]; + long start = System.nanoTime(); + for (int i = 0; i < NETWORK_MEASURE; i++) { + long opStart = System.nanoTime(); + sendOneDcm5File(port, files.get(NETWORK_WARMUP + i)); + latencies[i] = System.nanoTime() - opStart; + } + long totalNs = System.nanoTime() - start; + + printNetworkRow("Measured", latencies, totalNs); + printLatencyPercentiles("dcm5→dcm5", latencies); + } + + @Test + public void benchmarkNetworkCStoreDcm2() throws Exception { + System.out.println("\n========== NETWORK: dcm2 sender → dcm2 receiver (C-STORE) =========="); + System.out.printf("%-12s %12s %12s %12s%n", "Phase", "Ops/sec", "Avg (ms)", "Total (ms)"); + System.out.println("----------------------------------------------------"); + + int port = allocatePort(); + ArgumentCaptor captor = ArgumentCaptor.forClass(RawMessage.class); + SourceConnector mockConnector = createMockSourceConnector(captor); + + // Start dcm2 receiver + DicomLibraryFactory.resetForTesting(DicomLibrary.DCM4CHE2); + dcm2Receiver = new Dcm2DicomReceiver(mockConnector, new TestConfig()); + dcm2Receiver.setHostname("127.0.0.1"); + dcm2Receiver.setPort(port); + dcm2Receiver.setAEtitle("BENCH_SCP"); + dcm2Receiver.setDestination(tempFolder.getRoot().getAbsolutePath()); + dcm2Receiver.setTransferSyntax(new String[] { "1.2.840.10008.1.2", "1.2.840.10008.1.2.1" }); + dcm2Receiver.initTransferCapability(); + dcm2Receiver.start(); + waitForPort(port, 2000); + + // Create test files using dcm2 converter + List files = new ArrayList<>(); + for (int i = 0; i < NETWORK_WARMUP + NETWORK_MEASURE; i++) { + files.add(createDcm2TempFile("Bench^Patient" + i, "BENCH" + String.format("%04d", i))); + } + + // Warmup + for (int i = 0; i < NETWORK_WARMUP; i++) { + sendOneDcm2File(port, files.get(i)); + } + + // Measure + long[] latencies = new long[NETWORK_MEASURE]; + long start = System.nanoTime(); + for (int i = 0; i < NETWORK_MEASURE; i++) { + long opStart = System.nanoTime(); + sendOneDcm2File(port, files.get(NETWORK_WARMUP + i)); + latencies[i] = System.nanoTime() - opStart; + } + long totalNs = System.nanoTime() - start; + + printNetworkRow("Measured", latencies, totalNs); + printLatencyPercentiles("dcm2→dcm2", latencies); + } + + @Test + public void benchmarkMemoryFootprint() throws Exception { + System.out.println("\n========== MEMORY: converter object creation =========="); + System.out.printf("%-12s %12s %12s%n", "Backend", "Per-obj (B)", "100-obj (KB)"); + System.out.println("--------------------------------------------"); + + // dcm4che2 + long dcm2Single = measureObjectMemory(() -> { + Dcm2DicomConverter c = new Dcm2DicomConverter(); + OieDicomObject obj = c.createDicomObject(); + obj.putString(Tag.PatientName, "PN", "Test^Patient"); + obj.putString(Tag.PatientID, "LO", "ID001"); + return obj; + }); + long dcm2Bulk = measureBulkMemory(() -> { + Dcm2DicomConverter c = new Dcm2DicomConverter(); + OieDicomObject obj = c.createDicomObject(); + obj.putString(Tag.PatientName, "PN", "Test^Patient"); + obj.putString(Tag.PatientID, "LO", "ID001"); + return obj; + }, 100); + System.out.printf("%-12s %12d %12.1f%n", "dcm4che2", dcm2Single, dcm2Bulk / 1024.0); + + // dcm4che5 + long dcm5Single = measureObjectMemory(() -> { + Dcm5DicomConverter c = new Dcm5DicomConverter(); + OieDicomObject obj = c.createDicomObject(); + obj.putString(Tag.PatientName, "PN", "Test^Patient"); + obj.putString(Tag.PatientID, "LO", "ID001"); + return obj; + }); + long dcm5Bulk = measureBulkMemory(() -> { + Dcm5DicomConverter c = new Dcm5DicomConverter(); + OieDicomObject obj = c.createDicomObject(); + obj.putString(Tag.PatientName, "PN", "Test^Patient"); + obj.putString(Tag.PatientID, "LO", "ID001"); + return obj; + }, 100); + System.out.printf("%-12s %12d %12.1f%n", "dcm4che5", dcm5Single, dcm5Bulk / 1024.0); + } + + private BenchmarkResult benchmarkSerialization(OieDicomConverter converter, String label) throws IOException { + // Warmup + for (int i = 0; i < WARMUP_ITERATIONS; i++) { + OieDicomObject obj = createTestObject(converter); + converter.dicomObjectToByteArray(obj); + } + + // Measure + forceGc(); + long memBefore = usedMemory(); + long start = System.nanoTime(); + for (int i = 0; i < MEASURE_ITERATIONS; i++) { + OieDicomObject obj = createTestObject(converter); + converter.dicomObjectToByteArray(obj); + } + long elapsed = System.nanoTime() - start; + long memAfter = usedMemory(); + + return new BenchmarkResult(MEASURE_ITERATIONS, elapsed, memAfter - memBefore); + } + + private BenchmarkResult benchmarkDeserialization(OieDicomConverter converter, byte[] bytes) throws IOException { + // Warmup + for (int i = 0; i < WARMUP_ITERATIONS; i++) { + converter.byteArrayToDicomObject(bytes, false); + } + + // Measure + forceGc(); + long memBefore = usedMemory(); + long start = System.nanoTime(); + for (int i = 0; i < MEASURE_ITERATIONS; i++) { + converter.byteArrayToDicomObject(bytes, false); + } + long elapsed = System.nanoTime() - start; + long memAfter = usedMemory(); + + return new BenchmarkResult(MEASURE_ITERATIONS, elapsed, memAfter - memBefore); + } + + private BenchmarkResult benchmarkXmlConversion(OieDicomConverter converter, byte[] b64Bytes) throws Exception { + // Warmup + for (int i = 0; i < WARMUP_ITERATIONS; i++) { + converter.dicomBytesToXml(b64Bytes); + } + + // Measure + forceGc(); + long memBefore = usedMemory(); + long start = System.nanoTime(); + for (int i = 0; i < MEASURE_ITERATIONS; i++) { + converter.dicomBytesToXml(b64Bytes); + } + long elapsed = System.nanoTime() - start; + long memAfter = usedMemory(); + + return new BenchmarkResult(MEASURE_ITERATIONS, elapsed, memAfter - memBefore); + } + + private void sendOneDcm5File(int port, File file) throws Exception { + Dcm5DicomSender snd = new Dcm5DicomSender(new TestConfig()); + snd.setRemoteHost("127.0.0.1"); + snd.setRemotePort(port); + snd.setCalledAET("TEST_SCP"); + snd.setCalling("BENCH_SCU"); + snd.addFile(file); + snd.configureTransferCapability(); + snd.start(); + try { + CapturingDimseRspHandler handler = new CapturingDimseRspHandler(1); + snd.open(); + snd.send(handler); + handler.awaitResponses(10000); + snd.close(); + } finally { + try { snd.stop(); } catch (Exception e) { /* ignore */ } + } + } + + private void sendOneDcm2File(int port, File file) throws Exception { + DicomLibraryFactory.resetForTesting(DicomLibrary.DCM4CHE2); + Dcm2DicomSender snd = new Dcm2DicomSender(new TestConfig()); + snd.setRemoteHost("127.0.0.1"); + snd.setRemotePort(port); + snd.setCalledAET("BENCH_SCP"); + snd.setCalling("BENCH_SCU"); + snd.addFile(file); + snd.configureTransferCapability(); + snd.start(); + try { + snd.open(); + snd.send((cmd, data) -> {}); + snd.close(); + } finally { + try { snd.stop(); } catch (Exception e) { /* ignore */ } + } + } + + private File createDcm2TempFile(String patientName, String patientId) throws Exception { + Dcm2DicomConverter converter = new Dcm2DicomConverter(); + OieDicomObject obj = converter.createDicomObject(); + obj.putString(Tag.PatientName, "PN", patientName); + obj.putString(Tag.PatientID, "LO", patientId); + obj.putString(Tag.StudyInstanceUID, "UI", org.dcm4che2.util.UIDUtils.createUID()); + obj.putString(Tag.SeriesInstanceUID, "UI", org.dcm4che2.util.UIDUtils.createUID()); + obj.putString(Tag.SOPInstanceUID, "UI", org.dcm4che2.util.UIDUtils.createUID()); + obj.putString(Tag.Modality, "CS", "CT"); + obj.initFileMetaInformation( + "1.2.840.10008.5.1.4.1.1.2", + org.dcm4che2.util.UIDUtils.createUID(), + "1.2.840.10008.1.2"); + byte[] bytes = converter.dicomObjectToByteArray(obj); + File tempFile = tempFolder.newFile(patientId + ".dcm"); + Files.write(tempFile.toPath(), bytes); + return tempFile; + } + + private OieDicomObject createTestObject(OieDicomConverter converter) { + OieDicomObject obj = converter.createDicomObject(); + obj.putString(Tag.PatientName, "PN", "Benchmark^Patient"); + obj.putString(Tag.PatientID, "LO", "BENCH001"); + obj.putString(Tag.StudyInstanceUID, "UI", "1.2.3.4.5.6.7.8.9"); + obj.putString(Tag.SeriesInstanceUID, "UI", "1.2.3.4.5.6.7.8.10"); + obj.putString(Tag.SOPInstanceUID, "UI", "1.2.3.4.5.6.7.8.11"); + obj.putString(Tag.Modality, "CS", "CT"); + obj.putString(Tag.StudyDate, "DA", "20260326"); + obj.putString(Tag.StudyDescription, "LO", "Performance benchmark test study"); + obj.putString(Tag.InstitutionName, "LO", "Test Hospital"); + obj.putString(Tag.ReferringPhysicianName, "PN", "Doctor^Test"); + obj.initFileMetaInformation("1.2.840.10008.5.1.4.1.1.2", + "1.2.3.4.5.6.7.8.11", "1.2.840.10008.1.2"); + return obj; + } + + private byte[] createTestBytes(OieDicomConverter converter) throws IOException { + OieDicomObject obj = createTestObject(converter); + return converter.dicomObjectToByteArray(obj); + } + + @FunctionalInterface + private interface ObjectFactory { + Object create() throws Exception; + } + + private long measureObjectMemory(ObjectFactory factory) throws Exception { + forceGc(); + long before = usedMemory(); + Object obj = factory.create(); + long after = usedMemory(); + // Keep reference alive past measurement + if (obj.hashCode() == Integer.MIN_VALUE) System.out.print(""); + return Math.max(0, after - before); + } + + private long measureBulkMemory(ObjectFactory factory, int count) throws Exception { + forceGc(); + long before = usedMemory(); + Object[] objects = new Object[count]; + for (int i = 0; i < count; i++) { + objects[i] = factory.create(); + } + long after = usedMemory(); + // Keep references alive past measurement + if (objects[0].hashCode() == Integer.MIN_VALUE) System.out.print(""); + return Math.max(0, after - before); + } + + private static void forceGc() { + System.gc(); + System.gc(); + try { Thread.sleep(50); } catch (InterruptedException e) { Thread.currentThread().interrupt(); } + System.gc(); + } + + private static long usedMemory() { + Runtime rt = Runtime.getRuntime(); + return rt.totalMemory() - rt.freeMemory(); + } + + private static class BenchmarkResult { + final int iterations; + final long elapsedNs; + final long memoryDeltaBytes; + + BenchmarkResult(int iterations, long elapsedNs, long memoryDeltaBytes) { + this.iterations = iterations; + this.elapsedNs = elapsedNs; + this.memoryDeltaBytes = memoryDeltaBytes; + } + + double opsPerSec() { + return iterations / (elapsedNs / 1_000_000_000.0); + } + + double avgMs() { + return (elapsedNs / 1_000_000.0) / iterations; + } + + double memoryKB() { + return Math.max(0, memoryDeltaBytes) / 1024.0; + } + } + + private static void printRow(String label, BenchmarkResult result) { + System.out.printf("%-12s %12.1f %12.3f %12.1f%n", + label, result.opsPerSec(), result.avgMs(), result.memoryKB()); + } + + private static void printSpeedup(BenchmarkResult dcm2, BenchmarkResult dcm5) { + double speedup = dcm5.opsPerSec() / dcm2.opsPerSec(); + System.out.printf("%n dcm5 vs dcm2: %.2fx %s%n", + Math.abs(speedup), + speedup >= 1.0 ? "faster" : "slower"); + } + + private static void printNetworkRow(String label, long[] latenciesNs, long totalNs) { + double avgMs = 0; + for (long l : latenciesNs) avgMs += l; + avgMs = (avgMs / latenciesNs.length) / 1_000_000.0; + double opsPerSec = latenciesNs.length / (totalNs / 1_000_000_000.0); + double totalMs = totalNs / 1_000_000.0; + System.out.printf("%-12s %12.1f %12.1f %12.0f%n", label, opsPerSec, avgMs, totalMs); + } + + private static void printLatencyPercentiles(String label, long[] latenciesNs) { + long[] sorted = latenciesNs.clone(); + java.util.Arrays.sort(sorted); + System.out.printf("%n %s latency percentiles (ms):%n", label); + System.out.printf(" p50: %.1f p90: %.1f p99: %.1f min: %.1f max: %.1f%n", + sorted[(int)(sorted.length * 0.50)] / 1_000_000.0, + sorted[(int)(sorted.length * 0.90)] / 1_000_000.0, + sorted[(int)(sorted.length * 0.99)] / 1_000_000.0, + sorted[0] / 1_000_000.0, + sorted[sorted.length - 1] / 1_000_000.0); + } +} diff --git a/server/test/com/mirth/connect/server/launcher/MirthLauncherVariantTest.java b/server/test/com/mirth/connect/server/launcher/MirthLauncherVariantTest.java new file mode 100644 index 0000000000..9362210b99 --- /dev/null +++ b/server/test/com/mirth/connect/server/launcher/MirthLauncherVariantTest.java @@ -0,0 +1,65 @@ +package com.mirth.connect.server.launcher; + +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +import java.util.Properties; + +import org.junit.Test; + +public class MirthLauncherVariantTest { + + @Test + public void testNullVariantAlwaysLoads() { + assertTrue(MirthLauncher.shouldLoadLibrary(null, new Properties())); + } + + @Test + public void testEmptyVariantAlwaysLoads() { + assertTrue(MirthLauncher.shouldLoadLibrary("", new Properties())); + } + + @Test + public void testMatchingVariantLoads() { + Properties props = new Properties(); + props.setProperty("dicom.library", "dcm4che2"); + assertTrue(MirthLauncher.shouldLoadLibrary("dicom.library:dcm4che2", props)); + } + + @Test + public void testMismatchedVariantSkips() { + Properties props = new Properties(); + props.setProperty("dicom.library", "dcm4che5"); + assertFalse(MirthLauncher.shouldLoadLibrary("dicom.library:dcm4che2", props)); + } + + @Test + public void testMissingPropertyUsesDefault() { + Properties props = new Properties(); + // dicom.library not set, default is dcm4che2 + assertTrue(MirthLauncher.shouldLoadLibrary("dicom.library:dcm4che2", props)); + assertFalse(MirthLauncher.shouldLoadLibrary("dicom.library:dcm4che5", props)); + } + + @Test + public void testWhitespaceInPropertyValueTrimmed() { + Properties props = new Properties(); + props.setProperty("dicom.library", " dcm4che2 "); + assertTrue(MirthLauncher.shouldLoadLibrary("dicom.library:dcm4che2", props)); + } + + @Test + public void testMalformedVariantNoColonAlwaysLoads() { + Properties props = new Properties(); + assertTrue(MirthLauncher.shouldLoadLibrary("noColonHere", props)); + } + + @Test + public void testUnknownPropertyWithNoDefaultAlwaysLoads() { + Properties props = new Properties(); + // "unknown.prop" has no entry in VARIANT_DEFAULTS, so default is "" + // "somevalue" != "" → false. But wait, empty default doesn't match, so it should skip. + // Actually, let's test: unknown property with no default and no value = empty default + assertFalse(MirthLauncher.shouldLoadLibrary("unknown.prop:somevalue", props)); + } +} diff --git a/server/tests/dicom-channels/DICOM_Forward.xml b/server/tests/dicom-channels/DICOM_Forward.xml new file mode 100644 index 0000000000..4271f3da6f --- /dev/null +++ b/server/tests/dicom-channels/DICOM_Forward.xml @@ -0,0 +1,221 @@ + + 5ba097b6-56f6-4802-82d6-c7a830a3aaf3 + 2 + DICOM Forward + + 3 + + 0 + sourceConnector + + + + 0.0.0.0 + 11112 + + + None + true + false + false + 1 + + + Default Resource + [Default Resource] + + + 1000 + + + + + + 50 + 5 + 5 + 60 + 10 + 0 + false + 16 + 16 + 0 + false + 1 + false + + false + 0 + 0 + true + + + + true + true + notls + + + + + + DICOM + DICOM + + + + + + + DICOM Listener + SOURCE + true + true + + + + 1 + Destination 1 + + + + false + false + 10000 + false + 0 + false + false + 1 + + false + + + Default Resource + [Default Resource] + + + 1000 + true + + 127.0.0.1 + 11113 + + + + + + 5000 + 0 + 1 + 0 + med + + false + 16 + 10 + 5 + 60 + 1000 + 16 + 50 + 0 + 0 + false + true + false + false + + + + + true + true + notls + + + + + + DICOM + DICOM + + + + + + DICOM + DICOM + + + + + + + DICOM Sender + DESTINATION + true + true + + + // Modify the message variable below to pre process data +return message; + // This script executes once after a message has been processed +// Responses returned from here will be stored as "Postprocessor" in the response map +return; + // This script executes once when the channel is deployed +// You only have access to the globalMap and globalChannelMap here to persist data +return; + // This script executes once when the channel is undeployed +// You only have access to the globalMap and globalChannelMap here to persist data +return; + + true + DEVELOPMENT + false + false + false + false + false + false + STARTED + true + + + SOURCE + STRING + mirth_source + + + TYPE + STRING + mirth_type + + + + None + + + + + Default Resource + [Default Resource] + + + + + + true + + + America/Denver + + + true + false + + 1 + + + \ No newline at end of file diff --git a/server/tests/dicom-channels/DICOM_Receiver.xml b/server/tests/dicom-channels/DICOM_Receiver.xml new file mode 100644 index 0000000000..c963fbb36e --- /dev/null +++ b/server/tests/dicom-channels/DICOM_Receiver.xml @@ -0,0 +1,327 @@ + + + c7bbd2f4-bad8-414c-ab78-b527531ba984 + 2 + Dicom Receiver + + 2 + + 0 + sourceConnector + + + + 0.0.0.0 + 11113 + + + None + true + false + false + 1 + + + Default Resource + [Default Resource] + + + 1000 + + + + + + 50 + 5 + 5 + 60 + 10 + 0 + false + 16 + 16 + 0 + false + 1 + false + + false + 0 + 0 + true + + + + true + true + notls + + + + + + + excercise api + 0 + true + + + + + + DICOM + DICOM + + + + + + + DICOM Listener + SOURCE + true + true + + + + 1 + Destination 1 + + + + false + false + 10000 + false + 0 + false + false + 1 + + false + + + Default Resource + [Default Resource] + + + 1000 + true + + none + ${message.encodedData} + + + + + DICOM + DICOM + + + + + + DICOM + DICOM + + + + + + + Channel Writer + DESTINATION + true + true + + + // Modify the message variable below to pre process data +return message; + // This script executes once after a message has been processed +// Responses returned from here will be stored as "Postprocessor" in the response map +return; + // This script executes once when the channel is deployed +// You only have access to the globalMap and globalChannelMap here to persist data +return; + // This script executes once when the channel is undeployed +// You only have access to the globalMap and globalChannelMap here to persist data +return; + + true + DEVELOPMENT + false + false + false + false + false + false + STARTED + true + + + SOURCE + STRING + mirth_source + + + TYPE + STRING + mirth_type + + + + None + + + + + Default Resource + [Default Resource] + + + + + + true + + + America/Denver + + + true + false + + 1 + + + \ No newline at end of file diff --git a/server/tests/dicom-channels/README.md b/server/tests/dicom-channels/README.md new file mode 100644 index 0000000000..28273344a9 --- /dev/null +++ b/server/tests/dicom-channels/README.md @@ -0,0 +1,51 @@ +# DICOM Manual Test Channels + +Channels and transformer script for validating the DICOM connector end-to-end +against a running Open Integration Engine server. Used to confirm the +`dicom.library` toggle (dcm4che2 vs dcm4che5) produces identical behaviour. + +## Files + +| File | Purpose | +|---|---| +| `DICOM_Forward.xml` | DICOM Listener on `:11112` that forwards to `:11113` | +| `DICOM_Receiver.xml` | DICOM Listener on `:11113` with a JavaScript transformer that exercises the DICOM user API | +| `dicom-api-test.js` | Transformer script that asserts every `OieDicomObject`, `OieDicomElement`, and `DICOMUtil` method. Emits `[DICOM_TEST]` log lines | + +Both channels are configured with `DICOM` / +`DICOM`. The admin UI defaults new +channels to HL7v2; importing these XMLs avoids having to set the data type +manually. + +## Usage + +Start the server, then import via REST API: + + curl -sk -u admin:admin -H 'X-Requested-With: XMLHttpRequest' \ + -H 'Content-Type: application/xml' \ + -X POST --data-binary @DICOM_Forward.xml \ + https://localhost:8443/api/channels + curl -sk -u admin:admin -H 'X-Requested-With: XMLHttpRequest' \ + -H 'Content-Type: application/xml' \ + -X POST --data-binary @DICOM_Receiver.xml \ + https://localhost:8443/api/channels + curl -sk -u admin:admin -H 'X-Requested-With: XMLHttpRequest' \ + -X POST https://localhost:8443/api/channels/_redeployAll + +Send the DICOM fixtures through the pipeline with DCMTK: + + storescu localhost 11112 ../test-dicom-input-1.dcm + storescu localhost 11112 ../test-dicom-input-2.dcm + storescu localhost 11112 ../test-dicom-input-3.dcm + +Watch the server log for `[DICOM_TEST]` lines. Each message produces: + + [DICOM_TEST] === START message=N === + [DICOM_TEST] PASS ... (one per assertion) + [DICOM_TEST] backend=dcm4che2 (impl=org.dcm4che2.data.BasicDicomObject) + [DICOM_TEST] === END message=N backend=dcm4che2 failures=0 result=ALL_PASS === + +To validate the dcm4che5 backend, set `dicom.library = dcm4che5` in +`server/conf/mirth.properties`, restart the server, redeploy the channels, +and rerun `storescu`. The `backend=` field in the END line should report +`dcm4che5` and every assertion should still PASS. diff --git a/server/tests/dicom-channels/dicom-api-test.js b/server/tests/dicom-channels/dicom-api-test.js new file mode 100644 index 0000000000..b636462340 --- /dev/null +++ b/server/tests/dicom-channels/dicom-api-test.js @@ -0,0 +1,129 @@ +// === OIE DICOM API Regression Script (v2: Rhino-safe) === +var results = {}; +var failures = []; +var LOG_PREFIX = '[DICOM_TEST] '; + +function nonEmpty(x) { return x != null && String(x) !== ''; } + +function check(name, cond, info) { + var status = cond ? 'PASS' : 'FAIL'; + var line = status + ' ' + name + (info != null ? ' (' + info + ')' : ''); + results[name] = line; + if (cond) { logger.info(LOG_PREFIX + line); } + else { failures.push(line); logger.warn(LOG_PREFIX + line); } +} + +logger.info(LOG_PREFIX + '=== START message=' + connectorMessage.getMessageId() + ' ==='); + +var dicomBytes = DICOMUtil.getDICOMMessage(connectorMessage); +check('rawBytesNonEmpty', dicomBytes != null && dicomBytes.length > 0, 'len=' + (dicomBytes ? dicomBytes.length : 'null')); + +var rawBytes = DICOMUtil.getDICOMRawBytes(connectorMessage); +check('rawBytesDirectAccess', rawBytes != null && rawBytes.length > 0, 'len=' + (rawBytes ? rawBytes.length : 'null')); + +var rawB64 = DICOMUtil.getDICOMRawData(connectorMessage); +check('rawDataBase64', nonEmpty(rawB64), 'b64len=' + (rawB64 ? String(rawB64).length : 'null')); + +var dicomObj = DICOMUtil.byteArrayToDicomObject(dicomBytes, false); +check('parseObject', dicomObj != null); + +var patientName = dicomObj.getString(0x00100010); +var patientID = dicomObj.getString(0x00100020); +var modality = dicomObj.getString(0x00080060); +var sopClassUID = dicomObj.getString(0x00080016); +var sopInstUID = dicomObj.getString(0x00080018); + +check('getString_patientName', nonEmpty(patientName), patientName); +check('getString_patientID', nonEmpty(patientID), patientID); +check('getString_modality', nonEmpty(modality), modality); +check('getString_sopClassUID', nonEmpty(sopClassUID), sopClassUID); +check('getString_sopInstUID', nonEmpty(sopInstUID), sopInstUID); + +var studyDate = dicomObj.getString(0x00080020, 'UNKNOWN'); +var numFrames = dicomObj.getInt(0x00280008, 1); +var bogusTag = dicomObj.getString(0x00190099, 'DEFAULT'); +var bogusInt = dicomObj.getInt(0x00190099, 42); + +check('getString_default_absent_uses_default', String(bogusTag) == 'DEFAULT', String(bogusTag)); +check('getInt_default_absent_uses_default', bogusInt == 42, String(bogusInt)); +check('getInt_numFrames_fallback', numFrames >= 1, String(numFrames)); + +var sopClassElem = dicomObj.get(0x00080016); +if (sopClassElem != null) { + check('element_tag_matches', sopClassElem.tag() == 0x00080016, '0x' + sopClassElem.tag().toString(16)); + check('element_vr_nonempty', nonEmpty(sopClassElem.vr()), String(sopClassElem.vr())); + check('element_length_gt_zero', sopClassElem.length() > 0, 'len=' + sopClassElem.length()); + check('element_valueAsString', String(sopClassElem.getValueAsString(0)) == String(sopClassUID)); +} else { + check('element_sopClass_present', false, 'null'); +} + +check('absent_element_null', dicomObj.get(0x00190099) == null); + +var pixelElem = dicomObj.get(0x7FE00010); +if (pixelElem != null) { + var pixBytes = pixelElem.getBytes(); + check('pixelData_bytes_readable', pixBytes != null, 'len=' + (pixBytes ? pixBytes.length : 'null')); + check('pixelData_hasItems_queryable', typeof pixelElem.hasItems() == 'boolean'); +} else { + results['pixelData_present'] = 'ABSENT (expected on minimal fixtures)'; + logger.info(LOG_PREFIX + 'SKIP pixelData_present (absent on fixture)'); +} + +try { + var slices = DICOMUtil.getSliceCount(connectorMessage); + check('getSliceCount_noThrow', true, String(slices)); +} catch (e) { + check('getSliceCount_noThrow', false, String(e)); +} + +check('hasFileMetaInfo', dicomObj.hasFileMetaInfo() === true); +check('bigEndian_boolean', typeof dicomObj.bigEndian() == 'boolean'); + +try { + dicomObj.putString(0x00189004, 'CS', 'OIE_TEST_VALUE'); + check('putString_roundtrip', String(dicomObj.getString(0x00189004)) == 'OIE_TEST_VALUE'); + check('remove_returnsElement', dicomObj.remove(0x00189004) != null); + check('remove_actuallyRemoves', dicomObj.getString(0x00189004) == null); +} catch (e) { + check('mutation_supported', false, String(e)); +} + +try { + var roundTripBytes = DICOMUtil.dicomObjectToByteArray(dicomObj); + check('roundtrip_nonEmpty', roundTripBytes != null && roundTripBytes.length > 0, 'len=' + (roundTripBytes ? roundTripBytes.length : 'null')); + var reparsed = DICOMUtil.byteArrayToDicomObject(roundTripBytes, false); + check('roundtrip_reparse_patientName_stable', String(reparsed.getString(0x00100010)) == String(patientName)); + check('roundtrip_reparse_modality_stable', String(reparsed.getString(0x00080060)) == String(modality)); +} catch (e) { + check('roundtrip_noThrow', false, String(e)); +} + +var backend = 'UNKNOWN'; +try { + var implClass = String(dicomObj.unwrap().getClass().getName()); + backend = implClass.indexOf('dcm4che3') >= 0 ? 'dcm4che5' + : implClass.indexOf('dcm4che2') >= 0 ? 'dcm4che2' : 'UNKNOWN'; + channelMap.put('dicomTest.backendImplClass', implClass); + logger.info(LOG_PREFIX + 'backend=' + backend + ' (impl=' + implClass + ')'); +} catch (e) { + logger.warn(LOG_PREFIX + 'backend detection failed: ' + e); +} +channelMap.put('dicomTest.backend', backend); + +for (var key in results) { + channelMap.put('dicomTest.' + key, String(results[key])); +} +channelMap.put('dicomTest.failureCount', String(failures.length)); +channelMap.put('dicomTest.summary', failures.length == 0 ? 'ALL PASS' : ('FAILURES: ' + failures.join('; '))); + +channelMap.put('patientName', String(patientName)); +channelMap.put('patientID', String(patientID)); +channelMap.put('modality', String(modality)); +channelMap.put('studyDate', String(studyDate)); +channelMap.put('numberOfFrames', String(numFrames)); + +logger.info(LOG_PREFIX + '=== END message=' + connectorMessage.getMessageId() + + ' backend=' + backend + + ' failures=' + failures.length + + (failures.length == 0 ? ' result=ALL_PASS' : (' result=FAIL fails=[' + failures.join(' | ') + ']')) + ' ==='); diff --git a/server/tests/test-dicom-input-1.dcm b/server/tests/test-dicom-input-1.dcm new file mode 100644 index 0000000000000000000000000000000000000000..0c1526c7d3b3220019fd9d66582d6a9d9be1a00f GIT binary patch literal 620 zcmc&w%}Rqo3{2|}AA;qhf=Ew&09}&oZZ>;U+k+KF(e|oBE%c&&F(1Y*TbcG)Fl zGn1Kw=zq_2Ho5P^!s2e9z7YG=qlfD*;`I86i`j@IXz;{AnAt-P5)vMMQQrgNoHS_0 z6|dP@)jR_4UUGHO!WBuetg6{_pIUH+zqy8Lp> zyC09~c<0I8IA%|33ZO?gsfw-Em<)oNYEIG7d9dTC6|6d1t~r;e)ilMLib$#nvs6PT GGx-KyV@;6& literal 0 HcmV?d00001 diff --git a/server/tests/test-dicom-input-2.dcm b/server/tests/test-dicom-input-2.dcm new file mode 100644 index 0000000000000000000000000000000000000000..d58a9dc401d17d2f03e8424ae5b9fdc9f2a99499 GIT binary patch literal 592 zcmc(bO-lno42IMC!6I0e3L-u252!;jNoIC#ej!#YmDXPUpcd+(p8Q$Y zcgZ38-?*Az-gdCCyxFI3yphI5H$0SKpb56p{E#)N1@g$Wb*x19)lr$*@ z>{hrqtB6>rSgV@3)T*4TYb%o7YezjWqhGvG0ow?Zemj96Bn>)-{s}FvhxD>~_to3$ zc~0iZ4(XJ}F#4CjLpq}=cDDXZImD`jdA7z`EyNXPc?64u3kzrPK0y(`vgqOT2-WO! z{q^xUTR%^Fn$Q6{_ZJV$HlgDkyMx`dWG}^hbAR>bRjbz`1(!#)92xlG4x=Tc`o>h@ SC{eOBZ2@PBCg2v{!sG}0m_}9r literal 0 HcmV?d00001 diff --git a/server/tests/test-dicom-output-1.xml b/server/tests/test-dicom-output-1.xml new file mode 100644 index 0000000000..851ce249cf --- /dev/null +++ b/server/tests/test-dicom-output-1.xml @@ -0,0 +1,33 @@ + + + 146 + + 00\01 + + 1.2.840.10008.5.1.4.1.1.2 + + 1.2.3.4.5.6.7.8.9.1 + + 1.2.840.10008.1.2 + + 1.2.40.0.13.1.1 + + dcm4che-2.0 + + ISO_IR 100 + + 20230101 + + 120000 + + CT + + Doe^John + + PAT001 + + 19800101 + + M + + diff --git a/server/tests/test-dicom-output-2.xml b/server/tests/test-dicom-output-2.xml new file mode 100644 index 0000000000..c3767e55b1 --- /dev/null +++ b/server/tests/test-dicom-output-2.xml @@ -0,0 +1,29 @@ + + + 146 + + 00\01 + + 1.2.840.10008.5.1.4.1.1.4 + + 1.2.3.4.5.6.7.8.9.2 + + 1.2.840.10008.1.2 + + 1.2.40.0.13.1.1 + + dcm4che-2.0 + + ISO_IR 100 + + 20230215 + + MR + + Smith^Jane + + PAT002 + + F + + diff --git a/server/tests/test-dicom-output-3.xml b/server/tests/test-dicom-output-3.xml new file mode 100644 index 0000000000..a12ef94838 --- /dev/null +++ b/server/tests/test-dicom-output-3.xml @@ -0,0 +1,9 @@ + + + US + + Brown^Bob + + PAT003 + + From 865d1f1b9bdd1ed2e84c52ecc7e8f3ca1c75a46e Mon Sep 17 00:00:00 2001 From: Jesse Dowell Date: Wed, 15 Apr 2026 17:29:24 -0600 Subject: [PATCH 2/4] fix: apply extension library variant filter to WebStart JNLP MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit MirthLauncher already filters extension libraries by their `variant` attribute (e.g., `dicom.library:dcm4che5`) when building the server classpath, but WebStartServlet served all CLIENT/SHARED libraries to the Administrator regardless of variant. That left the Administrator downloading both dcm4che2 and dcm4che5 library JARs whenever both were declared — harmless (different package namespaces), but wasteful and inconsistent with server-side selection. Mirror MirthLauncher.shouldLoadLibrary in WebStartServlet so the Administrator receives only the libraries matching the server's current configuration. Signed-off-by: Jesse Dowell --- .../server/servlets/WebStartServlet.java | 48 +++++++++++++++++-- 1 file changed, 44 insertions(+), 4 deletions(-) diff --git a/server/src/com/mirth/connect/server/servlets/WebStartServlet.java b/server/src/com/mirth/connect/server/servlets/WebStartServlet.java index ecc077b7ab..81493f3e17 100644 --- a/server/src/com/mirth/connect/server/servlets/WebStartServlet.java +++ b/server/src/com/mirth/connect/server/servlets/WebStartServlet.java @@ -22,6 +22,7 @@ import java.util.Enumeration; import java.util.HashSet; import java.util.List; +import java.util.Map; import java.util.Set; import javax.servlet.ServletException; @@ -55,6 +56,11 @@ import com.mirth.connect.util.MirthSSLUtil; public class WebStartServlet extends HttpServlet { + // Default values for variant-filtered libraries when the corresponding + // property is absent from mirth.properties. Must stay in sync with + // MirthLauncher.VARIANT_DEFAULTS so client and server select the same variant. + private static final Map LIBRARY_VARIANT_DEFAULTS = Map.of("dicom.library", "dcm4che2"); + private Logger logger = LogManager.getLogger(this.getClass()); private ConfigurationController configurationController = ControllerFactory.getFactory().createConfigurationController(); private ExtensionController extensionController = ControllerFactory.getFactory().createExtensionController(); @@ -258,7 +264,7 @@ protected Document getAdministratorJnlp(HttpServletRequest request) throws Excep Set extensionPathsToAddToJnlp = new HashSet(); for (MetaData extension : allExtensions) { - if (extensionController.isExtensionEnabled(extension.getName()) && doesExtensionHaveClientOrSharedLibraries(extension)) { + if (extensionController.isExtensionEnabled(extension.getName()) && doesExtensionHaveClientOrSharedLibraries(extension, mirthProperties)) { extensionPathsToAddToJnlp.add(extension.getPath()); } } @@ -306,9 +312,10 @@ public static String getClientLibPath() { } } - private boolean doesExtensionHaveClientOrSharedLibraries(MetaData extension) { + private boolean doesExtensionHaveClientOrSharedLibraries(MetaData extension, PropertiesConfiguration mirthProperties) { for (ExtensionLibrary lib : extension.getLibraries()) { - if (lib.getType().equals(ExtensionLibrary.Type.CLIENT) || lib.getType().equals(ExtensionLibrary.Type.SHARED)) { + if ((lib.getType().equals(ExtensionLibrary.Type.CLIENT) || lib.getType().equals(ExtensionLibrary.Type.SHARED)) + && shouldServeLibrary(lib.getVariant(), mirthProperties)) { return true; } } @@ -316,6 +323,36 @@ private boolean doesExtensionHaveClientOrSharedLibraries(MetaData extension) { return false; } + /** + * Determines whether an extension library should be served to the Administrator + * based on its {@code variant} attribute and the current mirth.properties values. + * Mirrors {@code MirthLauncher.shouldLoadLibrary} so the client receives the same + * variant the server is running. + * + *

Variant format: {@code "propertyKey:requiredValue"} (e.g., {@code "dicom.library:dcm4che2"}). + * Libraries without a variant attribute are always served. + */ + static boolean shouldServeLibrary(String variant, PropertiesConfiguration mirthProperties) { + if (variant == null || variant.isEmpty()) { + return true; + } + + int colonIdx = variant.indexOf(':'); + if (colonIdx <= 0) { + return true; + } + + String propName = variant.substring(0, colonIdx); + String requiredValue = variant.substring(colonIdx + 1); + String actual = mirthProperties != null ? mirthProperties.getString(propName) : null; + + if (actual == null || actual.trim().isEmpty()) { + actual = LIBRARY_VARIANT_DEFAULTS.getOrDefault(propName, ""); + } + + return requiredValue.equalsIgnoreCase(actual.trim()); + } + protected Document getExtensionJnlp(String extensionPath) throws Exception { List allExtensions = new ArrayList(); allExtensions.addAll(ControllerFactory.getFactory().createExtensionController().getConnectorMetaData().values()); @@ -323,12 +360,15 @@ protected Document getExtensionJnlp(String extensionPath) throws Exception { Set librariesToAddToJnlp = new HashSet(); List extensionsWithThePath = new ArrayList(); + PropertiesConfiguration mirthProperties = getMirthProperties(); + for (MetaData metaData : allExtensions) { if (metaData.getPath().equals(extensionPath)) { extensionsWithThePath.add(metaData.getName()); for (ExtensionLibrary library : metaData.getLibraries()) { - if (library.getType().equals(ExtensionLibrary.Type.CLIENT) || library.getType().equals(ExtensionLibrary.Type.SHARED)) { + if ((library.getType().equals(ExtensionLibrary.Type.CLIENT) || library.getType().equals(ExtensionLibrary.Type.SHARED)) + && shouldServeLibrary(library.getVariant(), mirthProperties)) { librariesToAddToJnlp.add(library.getPath()); } } From c9de11f40fa4e021048d5a50899bd78869e1e655 Mon Sep 17 00:00:00 2001 From: Jesse Dowell Date: Thu, 16 Apr 2026 15:01:05 -0600 Subject: [PATCH 3/4] refactor: polish dcm4che5 backend after pre-PR audit Followups from a pre-PR audit of the dcm4che5 backend: - Add Object-VR overloads on OieDicomObject for putString / putInt / putBytes / putFragments, delegating via toString(). Preserves backward compatibility for transformer scripts passing a library-specific VR constant (e.g., dcm4che2's VR.PN) when the method surface is the version-neutral wrapper. - Simplify OieDicomObject.getInt(int, int) default from a two-step get(tag) + getInt(tag) lookup to a single contains(tag) + getInt(tag). - Upgrade trace->warn for Dcm5 no-op setters (setFileBufferSize, setTranscoderBufferSize, setDestination). These paths are only reached when the user explicitly set a non-default value, so the warn has zero noise on default configs and surfaces an otherwise-silent ignored setting. Also documents the long-standing upstream behavior of DICOMReceiver 'dest' being ignored on both backends (MirthDcmRcv's onCStoreRQ override streams directly to the channel and never consults DcmRcv.setDestination). - Document no-op settings and DICOMUtil API migration in docs/dcm4che5-migration-guide.md. Signed-off-by: Jesse Dowell --- docs/dcm4che5-migration-guide.md | 42 ++++++++++++++++++- .../dimse/dicom/OieDicomObject.java | 30 ++++++++++++- .../dimse/dicom/dcm5/Dcm5DicomReceiver.java | 17 +++++--- .../dimse/dicom/dcm5/Dcm5DicomSender.java | 7 +++- .../dimse/dicom/dcm5/Dcm5DicomObjectTest.java | 22 ++++++++++ 5 files changed, 108 insertions(+), 10 deletions(-) diff --git a/docs/dcm4che5-migration-guide.md b/docs/dcm4che5-migration-guide.md index 7de102b78e..fadcdbb376 100644 --- a/docs/dcm4che5-migration-guide.md +++ b/docs/dcm4che5-migration-guide.md @@ -34,7 +34,7 @@ To revert, change the value back to `dcm4che2` (or remove the line) and restart. | Area | Behavior | |------|----------| -| Channel properties | All DICOM Listener and Sender properties work identically | +| Channel properties | Listener and Sender UI properties work identically (see [Settings with no effect on dcm4che5](#settings-with-no-effect-on-dcm4che5) for two pure-tuning flags that are ignored) | | Source map keys | Same keys populated: `localApplicationEntityTitle`, `remoteApplicationEntityTitle`, `localAddress`, `localPort`, `remoteAddress`, `remotePort` | | DICOM object serialization | Byte-level output differs (different FMI implementation version UIDs), but all tag values are semantically equivalent | | C-STORE, C-ECHO | Both work through the standard channel lifecycle | @@ -63,6 +63,46 @@ If your channel logic inspects DICOM element names (not tag numbers), be aware t dicomObject.getString(Tag.PatientName) // works on both ``` +### Settings with no effect + +A few Listener and Sender UI fields have no corresponding implementation on the dcm4che5 backend. The dcm4che2 backend behavior is preserved unchanged. A `WARN`-level log is emitted on channel start when any of these are set to a non-default value on dcm4che5: + +| UI setting | Connector | Note | +|---|---|---| +| `bufSize` | Listener | File buffer size. dcm4che3 manages buffers internally; no equivalent API | +| `bufSize` | Sender | Transcoder buffer size. dcm4che3 manages buffers internally via `DataWriterAdapter` | +| `dest` (Store Received Objects in Directory) | Listener | Silently ignored on **both backends** — a long-standing upstream behavior. `MirthDcmRcv` streams DIMSE data directly to the channel and never consults this setting on either backend | + +None of these affect data integrity. Messages still arrive and dispatch through the channel correctly. The `bufSize` flags are pure performance tuning; revert `dicom.library` to `dcm4che2` if the throughput difference matters for your deployment. + +All other UI settings — TLS options, AE titles, timeouts, PDU lengths, transfer syntax selection, storage commitment, user identity, and priority — work identically on both backends. + +### DICOMUtil API (user transformer scripts) + +`DICOMUtil.byteArrayToDicomObject()` and `dicomObjectToByteArray()` now return / accept the version-neutral `OieDicomObject` type. For the vast majority of transformer scripts this change is invisible — Rhino's duck typing plus Object-type overloads on `OieDicomObject` mean existing calls keep working unchanged: + +```javascript +// Existing scripts continue to work on default (dcm4che2) without changes: +var dcm = DICOMUtil.byteArrayToDicomObject(bytes, false); +dcm.getString(Tag.PatientName); // same method exists on OieDicomObject +dcm.putString(Tag.PatientName, VR.PN, "SMITH"); // Object-overload routes via VR.toString() +``` + +Only these specific patterns require a one-line change: + +| Pattern | Change | +|---|---| +| `(DicomObject) DICOMUtil.byteArrayToDicomObject(...)` explicit cast | `(DicomObject) DICOMUtil.byteArrayToDicomObject(...).unwrap()` | +| `dcm instanceof DicomObject` | `dcm.unwrap() instanceof DicomObject` | +| Passing the result to a Java API that expects `org.dcm4che2.data.DicomObject` | Pass `dcm.unwrap()` instead | + +The recommended version-neutral pattern for new scripts is to use string VR codes instead of library-specific constants: + +```javascript +// Works identically on both backends — no dependency on VR class: +dcm.putString(Tag.PatientName, "PN", "SMITH"); +``` + ## TLS Configuration ### Standard UI TLS Options diff --git a/server/src/com/mirth/connect/connectors/dimse/dicom/OieDicomObject.java b/server/src/com/mirth/connect/connectors/dimse/dicom/OieDicomObject.java index bab4499156..f385671385 100644 --- a/server/src/com/mirth/connect/connectors/dimse/dicom/OieDicomObject.java +++ b/server/src/com/mirth/connect/connectors/dimse/dicom/OieDicomObject.java @@ -36,8 +36,7 @@ default String getString(int tag, String defaultValue) { * if the tag is not present. */ default int getInt(int tag, int defaultValue) { - OieDicomElement elem = get(tag); - return elem != null ? getInt(tag) : defaultValue; + return contains(tag) ? getInt(tag) : defaultValue; } OieDicomElement get(int tag); @@ -79,14 +78,41 @@ default int getInt(int tag, int defaultValue) { void putString(int tag, String vr, String value); + /** + * Overload accepting any {@code Object} as the VR argument. Delegates to + * {@link #putString(int, String, String)} using {@code vr.toString()}. + * + *

Preserves backward compatibility for transformer scripts that pass a + * library-specific VR constant (e.g., dcm4che2's {@code VR.PN}), whose + * {@code toString()} returns the two-letter VR code. + */ + default void putString(int tag, Object vr, String value) { + putString(tag, vr != null ? vr.toString() : null, value); + } + void putInt(int tag, String vr, int value); + /** Object-VR overload of {@link #putInt(int, String, int)}; see {@link #putString(int, Object, String)}. */ + default void putInt(int tag, Object vr, int value) { + putInt(tag, vr != null ? vr.toString() : null, value); + } + void putBytes(int tag, String vr, byte[] value); + /** Object-VR overload of {@link #putBytes(int, String, byte[])}; see {@link #putString(int, Object, String)}. */ + default void putBytes(int tag, Object vr, byte[] value) { + putBytes(tag, vr != null ? vr.toString() : null, value); + } + OieDicomElement putSequence(int tag); OieDicomElement putFragments(int tag, String vr, boolean bigEndian, int capacity); + /** Object-VR overload of {@link #putFragments(int, String, boolean, int)}; see {@link #putString(int, Object, String)}. */ + default OieDicomElement putFragments(int tag, Object vr, boolean bigEndian, int capacity) { + return putFragments(tag, vr != null ? vr.toString() : null, bigEndian, capacity); + } + void add(OieDicomElement element); OieDicomElement remove(int tag); diff --git a/server/src/com/mirth/connect/connectors/dimse/dicom/dcm5/Dcm5DicomReceiver.java b/server/src/com/mirth/connect/connectors/dimse/dicom/dcm5/Dcm5DicomReceiver.java index 93660769fd..cb850c063a 100644 --- a/server/src/com/mirth/connect/connectors/dimse/dicom/dcm5/Dcm5DicomReceiver.java +++ b/server/src/com/mirth/connect/connectors/dimse/dicom/dcm5/Dcm5DicomReceiver.java @@ -273,8 +273,13 @@ public void setHostname(String hostname) { @Override public void setDestination(String destination) { - // Not used — dcm5 receiver dispatches directly to the channel, not to filesystem - logger.trace("setDestination ignored in dcm5 receiver (no filesystem storage): " + destination); + // Matches dcm4che2's de facto behavior: MirthDcmRcv streams DIMSE data directly + // to the channel and never consults DcmRcv.setDestination, so the UI flag has + // been a no-op on both backends. Only reached when the user explicitly set a + // non-blank value in the Listener's "Store Received Objects in Directory" field. + logger.warn("destination={} has no effect on either DICOM backend (the flag has been " + + "silently ignored upstream for years). Remove this setting to clear the warning.", + destination); } @Override @@ -345,9 +350,11 @@ public void setReceiveBufferSize(int size) { @Override public void setFileBufferSize(int size) { - // dcm5 receiver writes directly to ByteArrayOutputStream, not filesystem. - // No file buffer applicable. - logger.trace("setFileBufferSize ignored in dcm5 receiver: " + size); + // dcm5 receiver streams directly to memory, with no file buffer concept. + // Only reached when the user explicitly changed bufSize from default, + // so warn instead of trace to surface the ignored setting. + logger.warn("bufSize={} has no effect on dcm4che5 receiver (dcm4che3 manages buffers internally). " + + "Revert dicom.library=dcm4che2 if this tuning is load-bearing.", size); } @Override diff --git a/server/src/com/mirth/connect/connectors/dimse/dicom/dcm5/Dcm5DicomSender.java b/server/src/com/mirth/connect/connectors/dimse/dicom/dcm5/Dcm5DicomSender.java index 609a5aa9b9..53d74160ef 100644 --- a/server/src/com/mirth/connect/connectors/dimse/dicom/dcm5/Dcm5DicomSender.java +++ b/server/src/com/mirth/connect/connectors/dimse/dicom/dcm5/Dcm5DicomSender.java @@ -197,8 +197,11 @@ public void setMaxOpsInvoked(int maxOps) { @Override public void setTranscoderBufferSize(int size) { - // dcm4che5 does not have a transcoder buffer — transcoding is handled internally. - logger.trace("setTranscoderBufferSize ignored in dcm5 sender: " + size); + // dcm4che5 has no transcoder buffer — transcoding is handled internally via DataWriterAdapter. + // Only reached when the user explicitly changed bufSize from default, so warn instead of + // trace to surface the ignored setting. + logger.warn("bufSize={} has no effect on dcm4che5 sender (dcm4che3 manages transcoder buffers internally). " + + "Revert dicom.library=dcm4che2 if this tuning is load-bearing.", size); } @Override diff --git a/server/test/com/mirth/connect/connectors/dimse/dicom/dcm5/Dcm5DicomObjectTest.java b/server/test/com/mirth/connect/connectors/dimse/dicom/dcm5/Dcm5DicomObjectTest.java index 8996256f54..0276b52dee 100644 --- a/server/test/com/mirth/connect/connectors/dimse/dicom/dcm5/Dcm5DicomObjectTest.java +++ b/server/test/com/mirth/connect/connectors/dimse/dicom/dcm5/Dcm5DicomObjectTest.java @@ -57,6 +57,28 @@ public void testGetReturnsNullForMissingTag() { assertEquals(0, obj.getInt(Tag.Rows)); } + @Test + public void testPutStringAcceptsObjectVrViaToString() { + // Simulates a user transformer script passing a library-specific VR constant + // (e.g., dcm4che2 VR.PN) — the Object overload delegates via toString(). + Object libraryVr = new Object() { + @Override public String toString() { return "PN"; } + }; + Dcm5DicomObject obj = new Dcm5DicomObject(); + obj.putString(Tag.PatientName, libraryVr, "Doe^John"); + assertEquals("Doe^John", obj.getString(Tag.PatientName)); + } + + @Test + public void testPutIntAcceptsObjectVrViaToString() { + Object libraryVr = new Object() { + @Override public String toString() { return "US"; } + }; + Dcm5DicomObject obj = new Dcm5DicomObject(); + obj.putInt(Tag.Rows, libraryVr, 512); + assertEquals(512, obj.getInt(Tag.Rows)); + } + @Test public void testPutSequence() { Dcm5DicomObject obj = new Dcm5DicomObject(); From 179b530287bcb6a3cd1273bd7a4ffc0ed3561ff2 Mon Sep 17 00:00:00 2001 From: Jesse Dowell Date: Tue, 21 Apr 2026 13:48:01 -0600 Subject: [PATCH 4/4] style: convert DICOM file headers to SPDX format MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Per PR review feedback from jonbartels: convert all touched files in this PR to the project's SPDX header style (matching the format already in use in LoginStatus.java, DelimitedReader.java, EDIReader.java, etc.). Three patterns applied based on file provenance: * New files contributed by this PR (45 files, mostly under server/src/com/mirth/connect/connectors/dimse/dicom/ and the corresponding test tree): a single Saga IT, LLC copyright line. Replaces the legacy Mirth Corporation block header that was copy-pasted from existing files when these were created. * Existing Mirth files modified by this PR (15 files, including DICOMReceiver, DICOMDispatcher, DICOMUtil, MirthLauncher, etc.): Mirth Corporation copyright preserved, Saga IT, LLC added as a contributor copyright line. * Vendored dcm4che2 tool files modified by this PR (MirthDcmRcv.java, MirthDcmSnd.java): dcm4che project + Mirth Corporation + Saga IT, LLC. Note: the upstream dcm4che2 source carries an MPL-1.1 OR GPL-2.0-only OR LGPL-2.1-only tri-license; we use MPL-2.0 here to match the rest of the project. Surfacing the actual upstream license is a separate concern. Header format matches existing project examples: // SPDX-License-Identifier: MPL-2.0 // SPDX-FileCopyrightText: CRLF line endings preserved on files that originally used CRLF; LF files unchanged. Per-file diffs are header-only — no source code changed. Signed-off-by: Jesse Dowell --- .../connect/connectors/dimse/DICOMConfiguration.java | 11 +++-------- .../connectors/dimse/DICOMConfigurationUtil.java | 11 +++-------- .../connect/connectors/dimse/DICOMDispatcher.java | 11 +++-------- .../mirth/connect/connectors/dimse/DICOMReceiver.java | 11 +++-------- .../connectors/dimse/DefaultDICOMConfiguration.java | 11 +++-------- .../dimse/DefaultDcm5DICOMConfiguration.java | 10 ++-------- .../connectors/dimse/dicom/DicomConstants.java | 10 ++-------- .../connectors/dimse/dicom/DicomLibraryFactory.java | 10 ++-------- .../connectors/dimse/dicom/OieDicomConverter.java | 10 ++-------- .../connectors/dimse/dicom/OieDicomElement.java | 10 ++-------- .../connectors/dimse/dicom/OieDicomObject.java | 10 ++-------- .../connectors/dimse/dicom/OieDicomReceiver.java | 10 ++-------- .../connectors/dimse/dicom/OieDicomSender.java | 10 ++-------- .../connectors/dimse/dicom/OieDimseRspHandler.java | 10 ++-------- .../mirth/connect/connectors/dimse/dicom/OieVR.java | 10 ++-------- .../dimse/dicom/dcm2/Dcm2DICOMConfiguration.java | 10 ++-------- .../dimse/dicom/dcm2/Dcm2DicomConverter.java | 10 ++-------- .../connectors/dimse/dicom/dcm2/Dcm2DicomElement.java | 10 ++-------- .../connectors/dimse/dicom/dcm2/Dcm2DicomObject.java | 10 ++-------- .../dimse/dicom/dcm2/Dcm2DicomReceiver.java | 10 ++-------- .../connectors/dimse/dicom/dcm2/Dcm2DicomSender.java | 10 ++-------- .../connect/connectors/dimse/dicom/dcm2/Dcm2VR.java | 10 ++-------- .../dimse/dicom/dcm5/Dcm5DICOMConfiguration.java | 10 ++-------- .../dimse/dicom/dcm5/Dcm5DicomConverter.java | 10 ++-------- .../connectors/dimse/dicom/dcm5/Dcm5DicomElement.java | 10 ++-------- .../connectors/dimse/dicom/dcm5/Dcm5DicomObject.java | 10 ++-------- .../dimse/dicom/dcm5/Dcm5DicomReceiver.java | 10 ++-------- .../connectors/dimse/dicom/dcm5/Dcm5DicomSender.java | 10 ++-------- .../connectors/dimse/dicom/dcm5/Dcm5TlsUtil.java | 10 ++-------- .../connect/connectors/dimse/dicom/dcm5/Dcm5VR.java | 10 ++-------- .../src/com/mirth/connect/model/ExtensionLibrary.java | 11 +++-------- .../connect/model/converters/DICOMConverter.java | 11 +++-------- .../plugins/datatypes/dicom/DICOMReference.java | 11 +++-------- .../plugins/datatypes/dicom/DICOMSerializer.java | 11 +++-------- .../attachments/dicom/DICOMAttachmentHandler.java | 11 +++-------- .../mirth/connect/server/launcher/MirthLauncher.java | 11 +++-------- .../connect/server/servlets/WebStartServlet.java | 11 +++-------- .../com/mirth/connect/server/userutil/DICOMUtil.java | 11 +++-------- .../mirth/connect/server/util/DICOMMessageUtil.java | 11 +++-------- server/src/org/dcm4che2/tool/dcmrcv/MirthDcmRcv.java | 5 +++++ server/src/org/dcm4che2/tool/dcmsnd/MirthDcmSnd.java | 5 +++++ .../connect/connectors/dimse/DICOMDispatcherTest.java | 4 ++++ .../connect/connectors/dimse/DICOMReceiverTest.java | 3 +++ .../dimse/dicom/DicomLibraryFactoryTest.java | 3 +++ .../dimse/dicom/GenerateDicomTestFiles.java | 3 +++ .../dimse/dicom/dcm2/Dcm2DICOMConfigurationTest.java | 3 +++ .../dimse/dicom/dcm5/Dcm5DICOMConfigurationTest.java | 3 +++ .../dimse/dicom/dcm5/Dcm5DicomConverterTest.java | 3 +++ .../dimse/dicom/dcm5/Dcm5DicomElementTest.java | 3 +++ .../dimse/dicom/dcm5/Dcm5DicomObjectTest.java | 3 +++ .../dimse/dicom/dcm5/Dcm5DicomReceiverTest.java | 3 +++ .../dimse/dicom/dcm5/Dcm5DicomSenderTest.java | 3 +++ .../integration/ConverterParityIntegrationTest.java | 3 +++ .../integration/CrossLibraryIntegrationTest.java | 3 +++ .../dicom/integration/Dcm5CEchoIntegrationTest.java | 3 +++ .../integration/Dcm5ErrorHandlingIntegrationTest.java | 3 +++ .../integration/Dcm5LoopbackIntegrationTest.java | 3 +++ .../Dcm5StorageCommitmentIntegrationTest.java | 3 +++ .../dicom/integration/Dcm5TlsIntegrationTest.java | 3 +++ .../dicom/integration/DicomIntegrationTestBase.java | 3 +++ .../dicom/integration/DicomPerformanceBenchmark.java | 3 +++ .../server/launcher/MirthLauncherVariantTest.java | 3 +++ 62 files changed, 166 insertions(+), 312 deletions(-) diff --git a/server/src/com/mirth/connect/connectors/dimse/DICOMConfiguration.java b/server/src/com/mirth/connect/connectors/dimse/DICOMConfiguration.java index d595f8cd7e..01040b95a0 100644 --- a/server/src/com/mirth/connect/connectors/dimse/DICOMConfiguration.java +++ b/server/src/com/mirth/connect/connectors/dimse/DICOMConfiguration.java @@ -1,11 +1,6 @@ -/* - * Copyright (c) Mirth Corporation. All rights reserved. - * - * http://www.mirthcorp.com - * - * The software in this package is published under the terms of the MPL license a copy of which has - * been included with this distribution in the LICENSE.txt file. - */ +// SPDX-License-Identifier: MPL-2.0 +// SPDX-FileCopyrightText: Mirth Corporation +// SPDX-FileCopyrightText: Saga IT, LLC package com.mirth.connect.connectors.dimse; diff --git a/server/src/com/mirth/connect/connectors/dimse/DICOMConfigurationUtil.java b/server/src/com/mirth/connect/connectors/dimse/DICOMConfigurationUtil.java index ba10c3b241..3de7cb3f0a 100644 --- a/server/src/com/mirth/connect/connectors/dimse/DICOMConfigurationUtil.java +++ b/server/src/com/mirth/connect/connectors/dimse/DICOMConfigurationUtil.java @@ -1,11 +1,6 @@ -/* - * Copyright (c) Mirth Corporation. All rights reserved. - * - * http://www.mirthcorp.com - * - * The software in this package is published under the terms of the MPL license a copy of which has - * been included with this distribution in the LICENSE.txt file. - */ +// SPDX-License-Identifier: MPL-2.0 +// SPDX-FileCopyrightText: Mirth Corporation +// SPDX-FileCopyrightText: Saga IT, LLC package com.mirth.connect.connectors.dimse; diff --git a/server/src/com/mirth/connect/connectors/dimse/DICOMDispatcher.java b/server/src/com/mirth/connect/connectors/dimse/DICOMDispatcher.java index 1fffc973d3..90d2a79f2f 100644 --- a/server/src/com/mirth/connect/connectors/dimse/DICOMDispatcher.java +++ b/server/src/com/mirth/connect/connectors/dimse/DICOMDispatcher.java @@ -1,11 +1,6 @@ -/* - * Copyright (c) Mirth Corporation. All rights reserved. - * - * http://www.mirthcorp.com - * - * The software in this package is published under the terms of the MPL license a copy of which has - * been included with this distribution in the LICENSE.txt file. - */ +// SPDX-License-Identifier: MPL-2.0 +// SPDX-FileCopyrightText: Mirth Corporation +// SPDX-FileCopyrightText: Saga IT, LLC package com.mirth.connect.connectors.dimse; diff --git a/server/src/com/mirth/connect/connectors/dimse/DICOMReceiver.java b/server/src/com/mirth/connect/connectors/dimse/DICOMReceiver.java index 60e13bc8f8..b1e691dd59 100644 --- a/server/src/com/mirth/connect/connectors/dimse/DICOMReceiver.java +++ b/server/src/com/mirth/connect/connectors/dimse/DICOMReceiver.java @@ -1,11 +1,6 @@ -/* - * Copyright (c) Mirth Corporation. All rights reserved. - * - * http://www.mirthcorp.com - * - * The software in this package is published under the terms of the MPL license a copy of which has - * been included with this distribution in the LICENSE.txt file. - */ +// SPDX-License-Identifier: MPL-2.0 +// SPDX-FileCopyrightText: Mirth Corporation +// SPDX-FileCopyrightText: Saga IT, LLC package com.mirth.connect.connectors.dimse; diff --git a/server/src/com/mirth/connect/connectors/dimse/DefaultDICOMConfiguration.java b/server/src/com/mirth/connect/connectors/dimse/DefaultDICOMConfiguration.java index 521a06fbaf..b38d5a8d55 100644 --- a/server/src/com/mirth/connect/connectors/dimse/DefaultDICOMConfiguration.java +++ b/server/src/com/mirth/connect/connectors/dimse/DefaultDICOMConfiguration.java @@ -1,11 +1,6 @@ -/* - * Copyright (c) Mirth Corporation. All rights reserved. - * - * http://www.mirthcorp.com - * - * The software in this package is published under the terms of the MPL license a copy of which has - * been included with this distribution in the LICENSE.txt file. - */ +// SPDX-License-Identifier: MPL-2.0 +// SPDX-FileCopyrightText: Mirth Corporation +// SPDX-FileCopyrightText: Saga IT, LLC package com.mirth.connect.connectors.dimse; diff --git a/server/src/com/mirth/connect/connectors/dimse/DefaultDcm5DICOMConfiguration.java b/server/src/com/mirth/connect/connectors/dimse/DefaultDcm5DICOMConfiguration.java index 4a088e20e1..9ca9b6e5fd 100644 --- a/server/src/com/mirth/connect/connectors/dimse/DefaultDcm5DICOMConfiguration.java +++ b/server/src/com/mirth/connect/connectors/dimse/DefaultDcm5DICOMConfiguration.java @@ -1,11 +1,5 @@ -/* - * Copyright (c) Mirth Corporation. All rights reserved. - * - * http://www.mirthcorp.com - * - * The software in this package is published under the terms of the MPL license a copy of which has - * been included with this distribution in the LICENSE.txt file. - */ +// SPDX-License-Identifier: MPL-2.0 +// SPDX-FileCopyrightText: Saga IT, LLC package com.mirth.connect.connectors.dimse; diff --git a/server/src/com/mirth/connect/connectors/dimse/dicom/DicomConstants.java b/server/src/com/mirth/connect/connectors/dimse/dicom/DicomConstants.java index 9e373ec59f..a0dd84f6c2 100644 --- a/server/src/com/mirth/connect/connectors/dimse/dicom/DicomConstants.java +++ b/server/src/com/mirth/connect/connectors/dimse/dicom/DicomConstants.java @@ -1,11 +1,5 @@ -/* - * Copyright (c) Mirth Corporation. All rights reserved. - * - * http://www.mirthcorp.com - * - * The software in this package is published under the terms of the MPL license a copy of which has - * been included with this distribution in the LICENSE.txt file. - */ +// SPDX-License-Identifier: MPL-2.0 +// SPDX-FileCopyrightText: Saga IT, LLC package com.mirth.connect.connectors.dimse.dicom; diff --git a/server/src/com/mirth/connect/connectors/dimse/dicom/DicomLibraryFactory.java b/server/src/com/mirth/connect/connectors/dimse/dicom/DicomLibraryFactory.java index e6f43f8906..1830a6fbee 100644 --- a/server/src/com/mirth/connect/connectors/dimse/dicom/DicomLibraryFactory.java +++ b/server/src/com/mirth/connect/connectors/dimse/dicom/DicomLibraryFactory.java @@ -1,11 +1,5 @@ -/* - * Copyright (c) Mirth Corporation. All rights reserved. - * - * http://www.mirthcorp.com - * - * The software in this package is published under the terms of the MPL license a copy of which has - * been included with this distribution in the LICENSE.txt file. - */ +// SPDX-License-Identifier: MPL-2.0 +// SPDX-FileCopyrightText: Saga IT, LLC package com.mirth.connect.connectors.dimse.dicom; diff --git a/server/src/com/mirth/connect/connectors/dimse/dicom/OieDicomConverter.java b/server/src/com/mirth/connect/connectors/dimse/dicom/OieDicomConverter.java index f17c6b566c..079cba6744 100644 --- a/server/src/com/mirth/connect/connectors/dimse/dicom/OieDicomConverter.java +++ b/server/src/com/mirth/connect/connectors/dimse/dicom/OieDicomConverter.java @@ -1,11 +1,5 @@ -/* - * Copyright (c) Mirth Corporation. All rights reserved. - * - * http://www.mirthcorp.com - * - * The software in this package is published under the terms of the MPL license a copy of which has - * been included with this distribution in the LICENSE.txt file. - */ +// SPDX-License-Identifier: MPL-2.0 +// SPDX-FileCopyrightText: Saga IT, LLC package com.mirth.connect.connectors.dimse.dicom; diff --git a/server/src/com/mirth/connect/connectors/dimse/dicom/OieDicomElement.java b/server/src/com/mirth/connect/connectors/dimse/dicom/OieDicomElement.java index 5b7c728ad1..be1ae201a6 100644 --- a/server/src/com/mirth/connect/connectors/dimse/dicom/OieDicomElement.java +++ b/server/src/com/mirth/connect/connectors/dimse/dicom/OieDicomElement.java @@ -1,11 +1,5 @@ -/* - * Copyright (c) Mirth Corporation. All rights reserved. - * - * http://www.mirthcorp.com - * - * The software in this package is published under the terms of the MPL license a copy of which has - * been included with this distribution in the LICENSE.txt file. - */ +// SPDX-License-Identifier: MPL-2.0 +// SPDX-FileCopyrightText: Saga IT, LLC package com.mirth.connect.connectors.dimse.dicom; diff --git a/server/src/com/mirth/connect/connectors/dimse/dicom/OieDicomObject.java b/server/src/com/mirth/connect/connectors/dimse/dicom/OieDicomObject.java index f385671385..46dee46c96 100644 --- a/server/src/com/mirth/connect/connectors/dimse/dicom/OieDicomObject.java +++ b/server/src/com/mirth/connect/connectors/dimse/dicom/OieDicomObject.java @@ -1,11 +1,5 @@ -/* - * Copyright (c) Mirth Corporation. All rights reserved. - * - * http://www.mirthcorp.com - * - * The software in this package is published under the terms of the MPL license a copy of which has - * been included with this distribution in the LICENSE.txt file. - */ +// SPDX-License-Identifier: MPL-2.0 +// SPDX-FileCopyrightText: Saga IT, LLC package com.mirth.connect.connectors.dimse.dicom; diff --git a/server/src/com/mirth/connect/connectors/dimse/dicom/OieDicomReceiver.java b/server/src/com/mirth/connect/connectors/dimse/dicom/OieDicomReceiver.java index b8c55c9921..7ac21c3210 100644 --- a/server/src/com/mirth/connect/connectors/dimse/dicom/OieDicomReceiver.java +++ b/server/src/com/mirth/connect/connectors/dimse/dicom/OieDicomReceiver.java @@ -1,11 +1,5 @@ -/* - * Copyright (c) Mirth Corporation. All rights reserved. - * - * http://www.mirthcorp.com - * - * The software in this package is published under the terms of the MPL license a copy of which has - * been included with this distribution in the LICENSE.txt file. - */ +// SPDX-License-Identifier: MPL-2.0 +// SPDX-FileCopyrightText: Saga IT, LLC package com.mirth.connect.connectors.dimse.dicom; diff --git a/server/src/com/mirth/connect/connectors/dimse/dicom/OieDicomSender.java b/server/src/com/mirth/connect/connectors/dimse/dicom/OieDicomSender.java index 5a785bed5f..fa60d31485 100644 --- a/server/src/com/mirth/connect/connectors/dimse/dicom/OieDicomSender.java +++ b/server/src/com/mirth/connect/connectors/dimse/dicom/OieDicomSender.java @@ -1,11 +1,5 @@ -/* - * Copyright (c) Mirth Corporation. All rights reserved. - * - * http://www.mirthcorp.com - * - * The software in this package is published under the terms of the MPL license a copy of which has - * been included with this distribution in the LICENSE.txt file. - */ +// SPDX-License-Identifier: MPL-2.0 +// SPDX-FileCopyrightText: Saga IT, LLC package com.mirth.connect.connectors.dimse.dicom; diff --git a/server/src/com/mirth/connect/connectors/dimse/dicom/OieDimseRspHandler.java b/server/src/com/mirth/connect/connectors/dimse/dicom/OieDimseRspHandler.java index 814923bdb2..d2b21a2df3 100644 --- a/server/src/com/mirth/connect/connectors/dimse/dicom/OieDimseRspHandler.java +++ b/server/src/com/mirth/connect/connectors/dimse/dicom/OieDimseRspHandler.java @@ -1,11 +1,5 @@ -/* - * Copyright (c) Mirth Corporation. All rights reserved. - * - * http://www.mirthcorp.com - * - * The software in this package is published under the terms of the MPL license a copy of which has - * been included with this distribution in the LICENSE.txt file. - */ +// SPDX-License-Identifier: MPL-2.0 +// SPDX-FileCopyrightText: Saga IT, LLC package com.mirth.connect.connectors.dimse.dicom; diff --git a/server/src/com/mirth/connect/connectors/dimse/dicom/OieVR.java b/server/src/com/mirth/connect/connectors/dimse/dicom/OieVR.java index 6d7e874ee3..25b15ecf3a 100644 --- a/server/src/com/mirth/connect/connectors/dimse/dicom/OieVR.java +++ b/server/src/com/mirth/connect/connectors/dimse/dicom/OieVR.java @@ -1,11 +1,5 @@ -/* - * Copyright (c) Mirth Corporation. All rights reserved. - * - * http://www.mirthcorp.com - * - * The software in this package is published under the terms of the MPL license a copy of which has - * been included with this distribution in the LICENSE.txt file. - */ +// SPDX-License-Identifier: MPL-2.0 +// SPDX-FileCopyrightText: Saga IT, LLC package com.mirth.connect.connectors.dimse.dicom; diff --git a/server/src/com/mirth/connect/connectors/dimse/dicom/dcm2/Dcm2DICOMConfiguration.java b/server/src/com/mirth/connect/connectors/dimse/dicom/dcm2/Dcm2DICOMConfiguration.java index 0b8f922ea2..668e6ccf8a 100644 --- a/server/src/com/mirth/connect/connectors/dimse/dicom/dcm2/Dcm2DICOMConfiguration.java +++ b/server/src/com/mirth/connect/connectors/dimse/dicom/dcm2/Dcm2DICOMConfiguration.java @@ -1,11 +1,5 @@ -/* - * Copyright (c) Mirth Corporation. All rights reserved. - * - * http://www.mirthcorp.com - * - * The software in this package is published under the terms of the MPL license a copy of which has - * been included with this distribution in the LICENSE.txt file. - */ +// SPDX-License-Identifier: MPL-2.0 +// SPDX-FileCopyrightText: Saga IT, LLC package com.mirth.connect.connectors.dimse.dicom.dcm2; diff --git a/server/src/com/mirth/connect/connectors/dimse/dicom/dcm2/Dcm2DicomConverter.java b/server/src/com/mirth/connect/connectors/dimse/dicom/dcm2/Dcm2DicomConverter.java index 50257d8e51..0965ee5e3e 100644 --- a/server/src/com/mirth/connect/connectors/dimse/dicom/dcm2/Dcm2DicomConverter.java +++ b/server/src/com/mirth/connect/connectors/dimse/dicom/dcm2/Dcm2DicomConverter.java @@ -1,11 +1,5 @@ -/* - * Copyright (c) Mirth Corporation. All rights reserved. - * - * http://www.mirthcorp.com - * - * The software in this package is published under the terms of the MPL license a copy of which has - * been included with this distribution in the LICENSE.txt file. - */ +// SPDX-License-Identifier: MPL-2.0 +// SPDX-FileCopyrightText: Saga IT, LLC package com.mirth.connect.connectors.dimse.dicom.dcm2; diff --git a/server/src/com/mirth/connect/connectors/dimse/dicom/dcm2/Dcm2DicomElement.java b/server/src/com/mirth/connect/connectors/dimse/dicom/dcm2/Dcm2DicomElement.java index b8a6b25d17..b619ff93b0 100644 --- a/server/src/com/mirth/connect/connectors/dimse/dicom/dcm2/Dcm2DicomElement.java +++ b/server/src/com/mirth/connect/connectors/dimse/dicom/dcm2/Dcm2DicomElement.java @@ -1,11 +1,5 @@ -/* - * Copyright (c) Mirth Corporation. All rights reserved. - * - * http://www.mirthcorp.com - * - * The software in this package is published under the terms of the MPL license a copy of which has - * been included with this distribution in the LICENSE.txt file. - */ +// SPDX-License-Identifier: MPL-2.0 +// SPDX-FileCopyrightText: Saga IT, LLC package com.mirth.connect.connectors.dimse.dicom.dcm2; diff --git a/server/src/com/mirth/connect/connectors/dimse/dicom/dcm2/Dcm2DicomObject.java b/server/src/com/mirth/connect/connectors/dimse/dicom/dcm2/Dcm2DicomObject.java index 02280b9bde..3dc5b9c95d 100644 --- a/server/src/com/mirth/connect/connectors/dimse/dicom/dcm2/Dcm2DicomObject.java +++ b/server/src/com/mirth/connect/connectors/dimse/dicom/dcm2/Dcm2DicomObject.java @@ -1,11 +1,5 @@ -/* - * Copyright (c) Mirth Corporation. All rights reserved. - * - * http://www.mirthcorp.com - * - * The software in this package is published under the terms of the MPL license a copy of which has - * been included with this distribution in the LICENSE.txt file. - */ +// SPDX-License-Identifier: MPL-2.0 +// SPDX-FileCopyrightText: Saga IT, LLC package com.mirth.connect.connectors.dimse.dicom.dcm2; diff --git a/server/src/com/mirth/connect/connectors/dimse/dicom/dcm2/Dcm2DicomReceiver.java b/server/src/com/mirth/connect/connectors/dimse/dicom/dcm2/Dcm2DicomReceiver.java index 98788e7bb3..bb2d3128b3 100644 --- a/server/src/com/mirth/connect/connectors/dimse/dicom/dcm2/Dcm2DicomReceiver.java +++ b/server/src/com/mirth/connect/connectors/dimse/dicom/dcm2/Dcm2DicomReceiver.java @@ -1,11 +1,5 @@ -/* - * Copyright (c) Mirth Corporation. All rights reserved. - * - * http://www.mirthcorp.com - * - * The software in this package is published under the terms of the MPL license a copy of which has - * been included with this distribution in the LICENSE.txt file. - */ +// SPDX-License-Identifier: MPL-2.0 +// SPDX-FileCopyrightText: Saga IT, LLC package com.mirth.connect.connectors.dimse.dicom.dcm2; diff --git a/server/src/com/mirth/connect/connectors/dimse/dicom/dcm2/Dcm2DicomSender.java b/server/src/com/mirth/connect/connectors/dimse/dicom/dcm2/Dcm2DicomSender.java index f619029379..24db0d2245 100644 --- a/server/src/com/mirth/connect/connectors/dimse/dicom/dcm2/Dcm2DicomSender.java +++ b/server/src/com/mirth/connect/connectors/dimse/dicom/dcm2/Dcm2DicomSender.java @@ -1,11 +1,5 @@ -/* - * Copyright (c) Mirth Corporation. All rights reserved. - * - * http://www.mirthcorp.com - * - * The software in this package is published under the terms of the MPL license a copy of which has - * been included with this distribution in the LICENSE.txt file. - */ +// SPDX-License-Identifier: MPL-2.0 +// SPDX-FileCopyrightText: Saga IT, LLC package com.mirth.connect.connectors.dimse.dicom.dcm2; diff --git a/server/src/com/mirth/connect/connectors/dimse/dicom/dcm2/Dcm2VR.java b/server/src/com/mirth/connect/connectors/dimse/dicom/dcm2/Dcm2VR.java index 3f500e5d41..9c1929d05e 100644 --- a/server/src/com/mirth/connect/connectors/dimse/dicom/dcm2/Dcm2VR.java +++ b/server/src/com/mirth/connect/connectors/dimse/dicom/dcm2/Dcm2VR.java @@ -1,11 +1,5 @@ -/* - * Copyright (c) Mirth Corporation. All rights reserved. - * - * http://www.mirthcorp.com - * - * The software in this package is published under the terms of the MPL license a copy of which has - * been included with this distribution in the LICENSE.txt file. - */ +// SPDX-License-Identifier: MPL-2.0 +// SPDX-FileCopyrightText: Saga IT, LLC package com.mirth.connect.connectors.dimse.dicom.dcm2; diff --git a/server/src/com/mirth/connect/connectors/dimse/dicom/dcm5/Dcm5DICOMConfiguration.java b/server/src/com/mirth/connect/connectors/dimse/dicom/dcm5/Dcm5DICOMConfiguration.java index 1dbfec9ba7..de19dea6ce 100644 --- a/server/src/com/mirth/connect/connectors/dimse/dicom/dcm5/Dcm5DICOMConfiguration.java +++ b/server/src/com/mirth/connect/connectors/dimse/dicom/dcm5/Dcm5DICOMConfiguration.java @@ -1,11 +1,5 @@ -/* - * Copyright (c) Mirth Corporation. All rights reserved. - * - * http://www.mirthcorp.com - * - * The software in this package is published under the terms of the MPL license a copy of which has - * been included with this distribution in the LICENSE.txt file. - */ +// SPDX-License-Identifier: MPL-2.0 +// SPDX-FileCopyrightText: Saga IT, LLC package com.mirth.connect.connectors.dimse.dicom.dcm5; diff --git a/server/src/com/mirth/connect/connectors/dimse/dicom/dcm5/Dcm5DicomConverter.java b/server/src/com/mirth/connect/connectors/dimse/dicom/dcm5/Dcm5DicomConverter.java index fde390a345..4d5e52f02f 100644 --- a/server/src/com/mirth/connect/connectors/dimse/dicom/dcm5/Dcm5DicomConverter.java +++ b/server/src/com/mirth/connect/connectors/dimse/dicom/dcm5/Dcm5DicomConverter.java @@ -1,11 +1,5 @@ -/* - * Copyright (c) Mirth Corporation. All rights reserved. - * - * http://www.mirthcorp.com - * - * The software in this package is published under the terms of the MPL license a copy of which has - * been included with this distribution in the LICENSE.txt file. - */ +// SPDX-License-Identifier: MPL-2.0 +// SPDX-FileCopyrightText: Saga IT, LLC package com.mirth.connect.connectors.dimse.dicom.dcm5; diff --git a/server/src/com/mirth/connect/connectors/dimse/dicom/dcm5/Dcm5DicomElement.java b/server/src/com/mirth/connect/connectors/dimse/dicom/dcm5/Dcm5DicomElement.java index 2c8d2be79f..33608a93b4 100644 --- a/server/src/com/mirth/connect/connectors/dimse/dicom/dcm5/Dcm5DicomElement.java +++ b/server/src/com/mirth/connect/connectors/dimse/dicom/dcm5/Dcm5DicomElement.java @@ -1,11 +1,5 @@ -/* - * Copyright (c) Mirth Corporation. All rights reserved. - * - * http://www.mirthcorp.com - * - * The software in this package is published under the terms of the MPL license a copy of which has - * been included with this distribution in the LICENSE.txt file. - */ +// SPDX-License-Identifier: MPL-2.0 +// SPDX-FileCopyrightText: Saga IT, LLC package com.mirth.connect.connectors.dimse.dicom.dcm5; diff --git a/server/src/com/mirth/connect/connectors/dimse/dicom/dcm5/Dcm5DicomObject.java b/server/src/com/mirth/connect/connectors/dimse/dicom/dcm5/Dcm5DicomObject.java index f6c1a262db..b9cca88c39 100644 --- a/server/src/com/mirth/connect/connectors/dimse/dicom/dcm5/Dcm5DicomObject.java +++ b/server/src/com/mirth/connect/connectors/dimse/dicom/dcm5/Dcm5DicomObject.java @@ -1,11 +1,5 @@ -/* - * Copyright (c) Mirth Corporation. All rights reserved. - * - * http://www.mirthcorp.com - * - * The software in this package is published under the terms of the MPL license a copy of which has - * been included with this distribution in the LICENSE.txt file. - */ +// SPDX-License-Identifier: MPL-2.0 +// SPDX-FileCopyrightText: Saga IT, LLC package com.mirth.connect.connectors.dimse.dicom.dcm5; diff --git a/server/src/com/mirth/connect/connectors/dimse/dicom/dcm5/Dcm5DicomReceiver.java b/server/src/com/mirth/connect/connectors/dimse/dicom/dcm5/Dcm5DicomReceiver.java index cb850c063a..bed9f3568b 100644 --- a/server/src/com/mirth/connect/connectors/dimse/dicom/dcm5/Dcm5DicomReceiver.java +++ b/server/src/com/mirth/connect/connectors/dimse/dicom/dcm5/Dcm5DicomReceiver.java @@ -1,11 +1,5 @@ -/* - * Copyright (c) Mirth Corporation. All rights reserved. - * - * http://www.mirthcorp.com - * - * The software in this package is published under the terms of the MPL license a copy of which has - * been included with this distribution in the LICENSE.txt file. - */ +// SPDX-License-Identifier: MPL-2.0 +// SPDX-FileCopyrightText: Saga IT, LLC package com.mirth.connect.connectors.dimse.dicom.dcm5; diff --git a/server/src/com/mirth/connect/connectors/dimse/dicom/dcm5/Dcm5DicomSender.java b/server/src/com/mirth/connect/connectors/dimse/dicom/dcm5/Dcm5DicomSender.java index 53d74160ef..3b71cbd630 100644 --- a/server/src/com/mirth/connect/connectors/dimse/dicom/dcm5/Dcm5DicomSender.java +++ b/server/src/com/mirth/connect/connectors/dimse/dicom/dcm5/Dcm5DicomSender.java @@ -1,11 +1,5 @@ -/* - * Copyright (c) Mirth Corporation. All rights reserved. - * - * http://www.mirthcorp.com - * - * The software in this package is published under the terms of the MPL license a copy of which has - * been included with this distribution in the LICENSE.txt file. - */ +// SPDX-License-Identifier: MPL-2.0 +// SPDX-FileCopyrightText: Saga IT, LLC package com.mirth.connect.connectors.dimse.dicom.dcm5; diff --git a/server/src/com/mirth/connect/connectors/dimse/dicom/dcm5/Dcm5TlsUtil.java b/server/src/com/mirth/connect/connectors/dimse/dicom/dcm5/Dcm5TlsUtil.java index c00fad7ac2..06192ad2b0 100644 --- a/server/src/com/mirth/connect/connectors/dimse/dicom/dcm5/Dcm5TlsUtil.java +++ b/server/src/com/mirth/connect/connectors/dimse/dicom/dcm5/Dcm5TlsUtil.java @@ -1,11 +1,5 @@ -/* - * Copyright (c) Mirth Corporation. All rights reserved. - * - * http://www.mirthcorp.com - * - * The software in this package is published under the terms of the MPL license a copy of which has - * been included with this distribution in the LICENSE.txt file. - */ +// SPDX-License-Identifier: MPL-2.0 +// SPDX-FileCopyrightText: Saga IT, LLC package com.mirth.connect.connectors.dimse.dicom.dcm5; diff --git a/server/src/com/mirth/connect/connectors/dimse/dicom/dcm5/Dcm5VR.java b/server/src/com/mirth/connect/connectors/dimse/dicom/dcm5/Dcm5VR.java index 0df3cbfb4d..d0635167de 100644 --- a/server/src/com/mirth/connect/connectors/dimse/dicom/dcm5/Dcm5VR.java +++ b/server/src/com/mirth/connect/connectors/dimse/dicom/dcm5/Dcm5VR.java @@ -1,11 +1,5 @@ -/* - * Copyright (c) Mirth Corporation. All rights reserved. - * - * http://www.mirthcorp.com - * - * The software in this package is published under the terms of the MPL license a copy of which has - * been included with this distribution in the LICENSE.txt file. - */ +// SPDX-License-Identifier: MPL-2.0 +// SPDX-FileCopyrightText: Saga IT, LLC package com.mirth.connect.connectors.dimse.dicom.dcm5; diff --git a/server/src/com/mirth/connect/model/ExtensionLibrary.java b/server/src/com/mirth/connect/model/ExtensionLibrary.java index 85a3ff87b0..acb4895658 100644 --- a/server/src/com/mirth/connect/model/ExtensionLibrary.java +++ b/server/src/com/mirth/connect/model/ExtensionLibrary.java @@ -1,11 +1,6 @@ -/* - * Copyright (c) Mirth Corporation. All rights reserved. - * - * http://www.mirthcorp.com - * - * The software in this package is published under the terms of the MPL license a copy of which has - * been included with this distribution in the LICENSE.txt file. - */ +// SPDX-License-Identifier: MPL-2.0 +// SPDX-FileCopyrightText: Mirth Corporation +// SPDX-FileCopyrightText: Saga IT, LLC package com.mirth.connect.model; diff --git a/server/src/com/mirth/connect/model/converters/DICOMConverter.java b/server/src/com/mirth/connect/model/converters/DICOMConverter.java index 3c83d4a303..ff95d815a8 100644 --- a/server/src/com/mirth/connect/model/converters/DICOMConverter.java +++ b/server/src/com/mirth/connect/model/converters/DICOMConverter.java @@ -1,11 +1,6 @@ -/* - * Copyright (c) Mirth Corporation. All rights reserved. - * - * http://www.mirthcorp.com - * - * The software in this package is published under the terms of the MPL license a copy of which has - * been included with this distribution in the LICENSE.txt file. - */ +// SPDX-License-Identifier: MPL-2.0 +// SPDX-FileCopyrightText: Mirth Corporation +// SPDX-FileCopyrightText: Saga IT, LLC package com.mirth.connect.model.converters; diff --git a/server/src/com/mirth/connect/plugins/datatypes/dicom/DICOMReference.java b/server/src/com/mirth/connect/plugins/datatypes/dicom/DICOMReference.java index 56678404c4..af78d8e545 100644 --- a/server/src/com/mirth/connect/plugins/datatypes/dicom/DICOMReference.java +++ b/server/src/com/mirth/connect/plugins/datatypes/dicom/DICOMReference.java @@ -1,11 +1,6 @@ -/* - * Copyright (c) Mirth Corporation. All rights reserved. - * - * http://www.mirthcorp.com - * - * The software in this package is published under the terms of the MPL license a copy of which has - * been included with this distribution in the LICENSE.txt file. - */ +// SPDX-License-Identifier: MPL-2.0 +// SPDX-FileCopyrightText: Mirth Corporation +// SPDX-FileCopyrightText: Saga IT, LLC package com.mirth.connect.plugins.datatypes.dicom; diff --git a/server/src/com/mirth/connect/plugins/datatypes/dicom/DICOMSerializer.java b/server/src/com/mirth/connect/plugins/datatypes/dicom/DICOMSerializer.java index 42ebf882e7..ff0e5c7447 100644 --- a/server/src/com/mirth/connect/plugins/datatypes/dicom/DICOMSerializer.java +++ b/server/src/com/mirth/connect/plugins/datatypes/dicom/DICOMSerializer.java @@ -1,11 +1,6 @@ -/* - * Copyright (c) Mirth Corporation. All rights reserved. - * - * http://www.mirthcorp.com - * - * The software in this package is published under the terms of the MPL license a copy of which has - * been included with this distribution in the LICENSE.txt file. - */ +// SPDX-License-Identifier: MPL-2.0 +// SPDX-FileCopyrightText: Mirth Corporation +// SPDX-FileCopyrightText: Saga IT, LLC package com.mirth.connect.plugins.datatypes.dicom; diff --git a/server/src/com/mirth/connect/server/attachments/dicom/DICOMAttachmentHandler.java b/server/src/com/mirth/connect/server/attachments/dicom/DICOMAttachmentHandler.java index eddf7bf6af..ee64b7a591 100644 --- a/server/src/com/mirth/connect/server/attachments/dicom/DICOMAttachmentHandler.java +++ b/server/src/com/mirth/connect/server/attachments/dicom/DICOMAttachmentHandler.java @@ -1,11 +1,6 @@ -/* - * Copyright (c) Mirth Corporation. All rights reserved. - * - * http://www.mirthcorp.com - * - * The software in this package is published under the terms of the MPL license a copy of which has - * been included with this distribution in the LICENSE.txt file. - */ +// SPDX-License-Identifier: MPL-2.0 +// SPDX-FileCopyrightText: Mirth Corporation +// SPDX-FileCopyrightText: Saga IT, LLC package com.mirth.connect.server.attachments.dicom; diff --git a/server/src/com/mirth/connect/server/launcher/MirthLauncher.java b/server/src/com/mirth/connect/server/launcher/MirthLauncher.java index 5e53c50599..db8e0b528b 100644 --- a/server/src/com/mirth/connect/server/launcher/MirthLauncher.java +++ b/server/src/com/mirth/connect/server/launcher/MirthLauncher.java @@ -1,11 +1,6 @@ -/* - * Copyright (c) Mirth Corporation. All rights reserved. - * - * http://www.mirthcorp.com - * - * The software in this package is published under the terms of the MPL license a copy of which has - * been included with this distribution in the LICENSE.txt file. - */ +// SPDX-License-Identifier: MPL-2.0 +// SPDX-FileCopyrightText: Mirth Corporation +// SPDX-FileCopyrightText: Saga IT, LLC package com.mirth.connect.server.launcher; diff --git a/server/src/com/mirth/connect/server/servlets/WebStartServlet.java b/server/src/com/mirth/connect/server/servlets/WebStartServlet.java index 81493f3e17..2a938fd97a 100644 --- a/server/src/com/mirth/connect/server/servlets/WebStartServlet.java +++ b/server/src/com/mirth/connect/server/servlets/WebStartServlet.java @@ -1,11 +1,6 @@ -/* - * Copyright (c) Mirth Corporation. All rights reserved. - * - * http://www.mirthcorp.com - * - * The software in this package is published under the terms of the MPL license a copy of which has - * been included with this distribution in the LICENSE.txt file. - */ +// SPDX-License-Identifier: MPL-2.0 +// SPDX-FileCopyrightText: Mirth Corporation +// SPDX-FileCopyrightText: Saga IT, LLC package com.mirth.connect.server.servlets; diff --git a/server/src/com/mirth/connect/server/userutil/DICOMUtil.java b/server/src/com/mirth/connect/server/userutil/DICOMUtil.java index 2eb087a010..ce09289490 100644 --- a/server/src/com/mirth/connect/server/userutil/DICOMUtil.java +++ b/server/src/com/mirth/connect/server/userutil/DICOMUtil.java @@ -1,11 +1,6 @@ -/* - * Copyright (c) Mirth Corporation. All rights reserved. - * - * http://www.mirthcorp.com - * - * The software in this package is published under the terms of the MPL license a copy of which has - * been included with this distribution in the LICENSE.txt file. - */ +// SPDX-License-Identifier: MPL-2.0 +// SPDX-FileCopyrightText: Mirth Corporation +// SPDX-FileCopyrightText: Saga IT, LLC package com.mirth.connect.server.userutil; diff --git a/server/src/com/mirth/connect/server/util/DICOMMessageUtil.java b/server/src/com/mirth/connect/server/util/DICOMMessageUtil.java index d1778743af..52e02dc9ba 100644 --- a/server/src/com/mirth/connect/server/util/DICOMMessageUtil.java +++ b/server/src/com/mirth/connect/server/util/DICOMMessageUtil.java @@ -1,11 +1,6 @@ -/* - * Copyright (c) Mirth Corporation. All rights reserved. - * - * http://www.mirthcorp.com - * - * The software in this package is published under the terms of the MPL license a copy of which has - * been included with this distribution in the LICENSE.txt file. - */ +// SPDX-License-Identifier: MPL-2.0 +// SPDX-FileCopyrightText: Mirth Corporation +// SPDX-FileCopyrightText: Saga IT, LLC package com.mirth.connect.server.util; diff --git a/server/src/org/dcm4che2/tool/dcmrcv/MirthDcmRcv.java b/server/src/org/dcm4che2/tool/dcmrcv/MirthDcmRcv.java index 649b65d10e..98b73ddc39 100644 --- a/server/src/org/dcm4che2/tool/dcmrcv/MirthDcmRcv.java +++ b/server/src/org/dcm4che2/tool/dcmrcv/MirthDcmRcv.java @@ -1,3 +1,8 @@ +// SPDX-License-Identifier: MPL-2.0 +// SPDX-FileCopyrightText: dcm4che project +// SPDX-FileCopyrightText: Mirth Corporation +// SPDX-FileCopyrightText: Saga IT, LLC + package org.dcm4che2.tool.dcmrcv; import java.io.BufferedOutputStream; diff --git a/server/src/org/dcm4che2/tool/dcmsnd/MirthDcmSnd.java b/server/src/org/dcm4che2/tool/dcmsnd/MirthDcmSnd.java index cd6908186a..9fa6c6b7f3 100644 --- a/server/src/org/dcm4che2/tool/dcmsnd/MirthDcmSnd.java +++ b/server/src/org/dcm4che2/tool/dcmsnd/MirthDcmSnd.java @@ -1,3 +1,8 @@ +// SPDX-License-Identifier: MPL-2.0 +// SPDX-FileCopyrightText: dcm4che project +// SPDX-FileCopyrightText: Mirth Corporation +// SPDX-FileCopyrightText: Saga IT, LLC + package org.dcm4che2.tool.dcmsnd; import java.io.IOException; diff --git a/server/test/com/mirth/connect/connectors/dimse/DICOMDispatcherTest.java b/server/test/com/mirth/connect/connectors/dimse/DICOMDispatcherTest.java index 17a3fbd587..969fb280fc 100644 --- a/server/test/com/mirth/connect/connectors/dimse/DICOMDispatcherTest.java +++ b/server/test/com/mirth/connect/connectors/dimse/DICOMDispatcherTest.java @@ -1,3 +1,7 @@ +// SPDX-License-Identifier: MPL-2.0 +// SPDX-FileCopyrightText: Mirth Corporation +// SPDX-FileCopyrightText: Saga IT, LLC + package com.mirth.connect.connectors.dimse; import static org.junit.Assert.assertEquals; diff --git a/server/test/com/mirth/connect/connectors/dimse/DICOMReceiverTest.java b/server/test/com/mirth/connect/connectors/dimse/DICOMReceiverTest.java index 359239d59f..b84a04d78a 100644 --- a/server/test/com/mirth/connect/connectors/dimse/DICOMReceiverTest.java +++ b/server/test/com/mirth/connect/connectors/dimse/DICOMReceiverTest.java @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: MPL-2.0 +// SPDX-FileCopyrightText: Saga IT, LLC + package com.mirth.connect.connectors.dimse; import static org.junit.Assert.assertArrayEquals; diff --git a/server/test/com/mirth/connect/connectors/dimse/dicom/DicomLibraryFactoryTest.java b/server/test/com/mirth/connect/connectors/dimse/dicom/DicomLibraryFactoryTest.java index 8d3983ea08..02fae3d2ea 100644 --- a/server/test/com/mirth/connect/connectors/dimse/dicom/DicomLibraryFactoryTest.java +++ b/server/test/com/mirth/connect/connectors/dimse/dicom/DicomLibraryFactoryTest.java @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: MPL-2.0 +// SPDX-FileCopyrightText: Saga IT, LLC + package com.mirth.connect.connectors.dimse.dicom; import static org.junit.Assert.assertEquals; diff --git a/server/test/com/mirth/connect/connectors/dimse/dicom/GenerateDicomTestFiles.java b/server/test/com/mirth/connect/connectors/dimse/dicom/GenerateDicomTestFiles.java index 9b4150789b..85245508bf 100644 --- a/server/test/com/mirth/connect/connectors/dimse/dicom/GenerateDicomTestFiles.java +++ b/server/test/com/mirth/connect/connectors/dimse/dicom/GenerateDicomTestFiles.java @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: MPL-2.0 +// SPDX-FileCopyrightText: Saga IT, LLC + package com.mirth.connect.connectors.dimse.dicom; import java.io.File; diff --git a/server/test/com/mirth/connect/connectors/dimse/dicom/dcm2/Dcm2DICOMConfigurationTest.java b/server/test/com/mirth/connect/connectors/dimse/dicom/dcm2/Dcm2DICOMConfigurationTest.java index 453a14306f..dd1f6daaa0 100644 --- a/server/test/com/mirth/connect/connectors/dimse/dicom/dcm2/Dcm2DICOMConfigurationTest.java +++ b/server/test/com/mirth/connect/connectors/dimse/dicom/dcm2/Dcm2DICOMConfigurationTest.java @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: MPL-2.0 +// SPDX-FileCopyrightText: Saga IT, LLC + package com.mirth.connect.connectors.dimse.dicom.dcm2; import static org.junit.Assert.assertEquals; diff --git a/server/test/com/mirth/connect/connectors/dimse/dicom/dcm5/Dcm5DICOMConfigurationTest.java b/server/test/com/mirth/connect/connectors/dimse/dicom/dcm5/Dcm5DICOMConfigurationTest.java index 2ef9efa60a..90933bc848 100644 --- a/server/test/com/mirth/connect/connectors/dimse/dicom/dcm5/Dcm5DICOMConfigurationTest.java +++ b/server/test/com/mirth/connect/connectors/dimse/dicom/dcm5/Dcm5DICOMConfigurationTest.java @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: MPL-2.0 +// SPDX-FileCopyrightText: Saga IT, LLC + package com.mirth.connect.connectors.dimse.dicom.dcm5; import static org.junit.Assert.assertEquals; diff --git a/server/test/com/mirth/connect/connectors/dimse/dicom/dcm5/Dcm5DicomConverterTest.java b/server/test/com/mirth/connect/connectors/dimse/dicom/dcm5/Dcm5DicomConverterTest.java index baf81920da..9755343c70 100644 --- a/server/test/com/mirth/connect/connectors/dimse/dicom/dcm5/Dcm5DicomConverterTest.java +++ b/server/test/com/mirth/connect/connectors/dimse/dicom/dcm5/Dcm5DicomConverterTest.java @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: MPL-2.0 +// SPDX-FileCopyrightText: Saga IT, LLC + package com.mirth.connect.connectors.dimse.dicom.dcm5; import static org.junit.Assert.assertEquals; diff --git a/server/test/com/mirth/connect/connectors/dimse/dicom/dcm5/Dcm5DicomElementTest.java b/server/test/com/mirth/connect/connectors/dimse/dicom/dcm5/Dcm5DicomElementTest.java index f6cbd4202d..7ea28883e2 100644 --- a/server/test/com/mirth/connect/connectors/dimse/dicom/dcm5/Dcm5DicomElementTest.java +++ b/server/test/com/mirth/connect/connectors/dimse/dicom/dcm5/Dcm5DicomElementTest.java @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: MPL-2.0 +// SPDX-FileCopyrightText: Saga IT, LLC + package com.mirth.connect.connectors.dimse.dicom.dcm5; import static org.junit.Assert.assertArrayEquals; diff --git a/server/test/com/mirth/connect/connectors/dimse/dicom/dcm5/Dcm5DicomObjectTest.java b/server/test/com/mirth/connect/connectors/dimse/dicom/dcm5/Dcm5DicomObjectTest.java index 0276b52dee..a033254481 100644 --- a/server/test/com/mirth/connect/connectors/dimse/dicom/dcm5/Dcm5DicomObjectTest.java +++ b/server/test/com/mirth/connect/connectors/dimse/dicom/dcm5/Dcm5DicomObjectTest.java @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: MPL-2.0 +// SPDX-FileCopyrightText: Saga IT, LLC + package com.mirth.connect.connectors.dimse.dicom.dcm5; import static org.junit.Assert.assertEquals; diff --git a/server/test/com/mirth/connect/connectors/dimse/dicom/dcm5/Dcm5DicomReceiverTest.java b/server/test/com/mirth/connect/connectors/dimse/dicom/dcm5/Dcm5DicomReceiverTest.java index e1d968404c..c00ffc5d32 100644 --- a/server/test/com/mirth/connect/connectors/dimse/dicom/dcm5/Dcm5DicomReceiverTest.java +++ b/server/test/com/mirth/connect/connectors/dimse/dicom/dcm5/Dcm5DicomReceiverTest.java @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: MPL-2.0 +// SPDX-FileCopyrightText: Saga IT, LLC + package com.mirth.connect.connectors.dimse.dicom.dcm5; import static org.junit.Assert.assertEquals; diff --git a/server/test/com/mirth/connect/connectors/dimse/dicom/dcm5/Dcm5DicomSenderTest.java b/server/test/com/mirth/connect/connectors/dimse/dicom/dcm5/Dcm5DicomSenderTest.java index b054cfc1f8..97f0fe8580 100644 --- a/server/test/com/mirth/connect/connectors/dimse/dicom/dcm5/Dcm5DicomSenderTest.java +++ b/server/test/com/mirth/connect/connectors/dimse/dicom/dcm5/Dcm5DicomSenderTest.java @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: MPL-2.0 +// SPDX-FileCopyrightText: Saga IT, LLC + package com.mirth.connect.connectors.dimse.dicom.dcm5; import static org.junit.Assert.assertNotNull; diff --git a/server/test/com/mirth/connect/connectors/dimse/dicom/integration/ConverterParityIntegrationTest.java b/server/test/com/mirth/connect/connectors/dimse/dicom/integration/ConverterParityIntegrationTest.java index ab87bdc173..dc84f1e6e8 100644 --- a/server/test/com/mirth/connect/connectors/dimse/dicom/integration/ConverterParityIntegrationTest.java +++ b/server/test/com/mirth/connect/connectors/dimse/dicom/integration/ConverterParityIntegrationTest.java @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: MPL-2.0 +// SPDX-FileCopyrightText: Saga IT, LLC + package com.mirth.connect.connectors.dimse.dicom.integration; import static org.junit.Assert.assertEquals; diff --git a/server/test/com/mirth/connect/connectors/dimse/dicom/integration/CrossLibraryIntegrationTest.java b/server/test/com/mirth/connect/connectors/dimse/dicom/integration/CrossLibraryIntegrationTest.java index 1b56f50066..842ff3b921 100644 --- a/server/test/com/mirth/connect/connectors/dimse/dicom/integration/CrossLibraryIntegrationTest.java +++ b/server/test/com/mirth/connect/connectors/dimse/dicom/integration/CrossLibraryIntegrationTest.java @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: MPL-2.0 +// SPDX-FileCopyrightText: Saga IT, LLC + package com.mirth.connect.connectors.dimse.dicom.integration; import static org.junit.Assert.assertEquals; diff --git a/server/test/com/mirth/connect/connectors/dimse/dicom/integration/Dcm5CEchoIntegrationTest.java b/server/test/com/mirth/connect/connectors/dimse/dicom/integration/Dcm5CEchoIntegrationTest.java index bd469de2a6..ef121b1627 100644 --- a/server/test/com/mirth/connect/connectors/dimse/dicom/integration/Dcm5CEchoIntegrationTest.java +++ b/server/test/com/mirth/connect/connectors/dimse/dicom/integration/Dcm5CEchoIntegrationTest.java @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: MPL-2.0 +// SPDX-FileCopyrightText: Saga IT, LLC + package com.mirth.connect.connectors.dimse.dicom.integration; import static org.junit.Assert.assertEquals; diff --git a/server/test/com/mirth/connect/connectors/dimse/dicom/integration/Dcm5ErrorHandlingIntegrationTest.java b/server/test/com/mirth/connect/connectors/dimse/dicom/integration/Dcm5ErrorHandlingIntegrationTest.java index 8cadc2a9b2..afc0659c56 100644 --- a/server/test/com/mirth/connect/connectors/dimse/dicom/integration/Dcm5ErrorHandlingIntegrationTest.java +++ b/server/test/com/mirth/connect/connectors/dimse/dicom/integration/Dcm5ErrorHandlingIntegrationTest.java @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: MPL-2.0 +// SPDX-FileCopyrightText: Saga IT, LLC + package com.mirth.connect.connectors.dimse.dicom.integration; import static org.junit.Assert.assertEquals; diff --git a/server/test/com/mirth/connect/connectors/dimse/dicom/integration/Dcm5LoopbackIntegrationTest.java b/server/test/com/mirth/connect/connectors/dimse/dicom/integration/Dcm5LoopbackIntegrationTest.java index 3be0e081d6..ea4f96fad7 100644 --- a/server/test/com/mirth/connect/connectors/dimse/dicom/integration/Dcm5LoopbackIntegrationTest.java +++ b/server/test/com/mirth/connect/connectors/dimse/dicom/integration/Dcm5LoopbackIntegrationTest.java @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: MPL-2.0 +// SPDX-FileCopyrightText: Saga IT, LLC + package com.mirth.connect.connectors.dimse.dicom.integration; import static org.junit.Assert.assertEquals; diff --git a/server/test/com/mirth/connect/connectors/dimse/dicom/integration/Dcm5StorageCommitmentIntegrationTest.java b/server/test/com/mirth/connect/connectors/dimse/dicom/integration/Dcm5StorageCommitmentIntegrationTest.java index d72478f7b9..0db42cd3bc 100644 --- a/server/test/com/mirth/connect/connectors/dimse/dicom/integration/Dcm5StorageCommitmentIntegrationTest.java +++ b/server/test/com/mirth/connect/connectors/dimse/dicom/integration/Dcm5StorageCommitmentIntegrationTest.java @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: MPL-2.0 +// SPDX-FileCopyrightText: Saga IT, LLC + package com.mirth.connect.connectors.dimse.dicom.integration; import static org.junit.Assert.assertNotNull; diff --git a/server/test/com/mirth/connect/connectors/dimse/dicom/integration/Dcm5TlsIntegrationTest.java b/server/test/com/mirth/connect/connectors/dimse/dicom/integration/Dcm5TlsIntegrationTest.java index 5a078db23a..b56a86230f 100644 --- a/server/test/com/mirth/connect/connectors/dimse/dicom/integration/Dcm5TlsIntegrationTest.java +++ b/server/test/com/mirth/connect/connectors/dimse/dicom/integration/Dcm5TlsIntegrationTest.java @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: MPL-2.0 +// SPDX-FileCopyrightText: Saga IT, LLC + package com.mirth.connect.connectors.dimse.dicom.integration; import static org.junit.Assert.assertEquals; diff --git a/server/test/com/mirth/connect/connectors/dimse/dicom/integration/DicomIntegrationTestBase.java b/server/test/com/mirth/connect/connectors/dimse/dicom/integration/DicomIntegrationTestBase.java index 7474e68b0c..d8f32bc3f4 100644 --- a/server/test/com/mirth/connect/connectors/dimse/dicom/integration/DicomIntegrationTestBase.java +++ b/server/test/com/mirth/connect/connectors/dimse/dicom/integration/DicomIntegrationTestBase.java @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: MPL-2.0 +// SPDX-FileCopyrightText: Saga IT, LLC + package com.mirth.connect.connectors.dimse.dicom.integration; import static org.mockito.Mockito.mock; diff --git a/server/test/com/mirth/connect/connectors/dimse/dicom/integration/DicomPerformanceBenchmark.java b/server/test/com/mirth/connect/connectors/dimse/dicom/integration/DicomPerformanceBenchmark.java index 7efd74c5ba..364dd6a9e3 100644 --- a/server/test/com/mirth/connect/connectors/dimse/dicom/integration/DicomPerformanceBenchmark.java +++ b/server/test/com/mirth/connect/connectors/dimse/dicom/integration/DicomPerformanceBenchmark.java @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: MPL-2.0 +// SPDX-FileCopyrightText: Saga IT, LLC + package com.mirth.connect.connectors.dimse.dicom.integration; import java.io.File; diff --git a/server/test/com/mirth/connect/server/launcher/MirthLauncherVariantTest.java b/server/test/com/mirth/connect/server/launcher/MirthLauncherVariantTest.java index 9362210b99..b5933dc8ef 100644 --- a/server/test/com/mirth/connect/server/launcher/MirthLauncherVariantTest.java +++ b/server/test/com/mirth/connect/server/launcher/MirthLauncherVariantTest.java @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: MPL-2.0 +// SPDX-FileCopyrightText: Saga IT, LLC + package com.mirth.connect.server.launcher; import static org.junit.Assert.assertFalse;

%sXy9&9QiEvAH@HbwK=#N#EJK{QmmRDF``ysw= zhM~IgRT*$=ZgYLH0|=!|!8h45wy@C`Pbi1mbCHJpF;mhM5rdyBLxw9ndyW9Ya{;s~ zLP-vZ$8~;I4n6cA#WiH5a*9SQ3~i&d!+zoNb-D&=5e#JW z)F&1$%;gH!;6-KY;XKPW-OMbc>2bn5>K}>~;>;4mPXH&CBE3q6hTqX_1M- z6i+cqaJC<83VYhJqwLJnsXD1HVIN$UrH>kZHlSnapGdilo#+ZoVw*72Mz zf4H@4tWEY{>}CmPe78B9^{*Y?!Z)ani0+_MOv4><%EVV`-@iIc-99iclnk~Wuuzx} zTGH{7zN&L{6;{_I3`X(QXXxpc3J>BJeL&eOQwK;g`?`1t@FN-pH2W#4P7$`5d5D(b z*NQiZZ&SDJ-o^&9_@vZ|NvY#8E(y&b5)lnVCIfsMA22J@UKe_(mfYSekZQ_a^U8_b zt0U}2=@P+SU}Q!C))>W`KiiaW`RRthGA3~<z`2-58=fk?HU1cxbu^yP*jB| zeS7X$JV-`IDsXjiaA@&-Q=gWoCt8k(9iz;FRmVqa3J0O&(kmwD+ zXy|=Uko2`71H(HK!1AWj`n4WdwA%+Pr+23KcRC!eAT#gOY2JPYx71SaBr~_DHqT6T z&nPo@><4z1{XbNFiLD^A`s^dh*eed5(6WqNGjVd+L(15!_M7AOSlJW$1D2Ju?z2_t zi$f}Ikb7K#5-=U(D6nD>@sO&>XVN zZP?P+ew@1;ei;0wz1lm4!56LUxi}->hjBlIS09^`?{EX^CsUQaiSXa3>ih2Z<1KRm zH+mQ+6?X#1JY|L^8>cCkI+o~EKUG7vqtfGQjP)`Y(H8V8*dd&ZdsOOqWyAs2(K`0y zlNmWAQSM#iJM5K)A%D(J(Fw?S+|Lvur}<0SMt4EM%06u zy3_-P7|J_D0=G1T-;Rnq2HFzUTF@Ro}mDc1vK&#sRXNH&$ov*Z5T#DO^&Y5MPaH>J+g5R^E9@AKDFHJJawDuXxfl zErplY(Tr`X=o#B9w`Oj1$DUCfqd#_~H9k=RT|&HvHY$f*#UxFSYP!^fshaAeF^b4A z6Yg@QwIx<53`x3?(HZZCg2-TKDXFupS{-K%78sN8hnnfNaGh`l;&Ua>M}Z_}-GKE*ZOn+e7>@dY zj)sb&t~iv#WS&j8%E=tpsQxxgGnz0_9c&Lrd15hMTPsZz0Y#_P)-R-nPgG;8Y@7YQ z=4Sx~y2x~oeT*F*q98wE*96Xi<@Um>Y5A~{EWQ7PXD7w(>NI(8#0_D+T#rxC}tReCNV|~-WpcpApV@@V7z4~<_fSKOSU!P8!|F6%GJ3y zU{NaUx%VSM#N`e@QAgb|e_nLxV+`=MdsD=2;4LipT!=x_XXb(>a0VAmJy`aO=#@tV>qB3^_m=vh7j zx)r5^V@SAj!6D&t$xoq9qo;)T98O#&4it`iAhR~o`u0uU87&HEGQ9lz5tJP;X-A)D zt|<%aKVZ8ZMOhX;)MMooA=b-Mg&L)l`I+jHwWbe+TMGi)c8ZG=2Wbu?RUlZ)Fj|vs zkz4G)?U^Ib(xW|>u(6FxULZ8XP1g!}W-bnx10LYYQ=GL#S63>?DJm&euP0Ta%SEW= zBo_smB&Zcs;W@R>4VomWRRp!Xd2_tOc7IAWOmc1TGNM-K{&}iCc)O!qX$VR>DaTfc z94Lr!uaq{OGt}=mpwv}2!S3G)JF`PMU_FU0ayZB&o)+T9li)nXx3;#X;<}P&|jBa>pXZ{PKm;Ha#*; z{#5J_1pRzrn=@KIrhAeIR}GmE&k#MQn7r8b`yY&bV|1m_wq+$1+qP}nwr$%+#kOtd z#I|kQMuinu(z*Bbd!xJGyLa?A&W|(3Ip43n_gZVuxz?QSAzU>diJMoOm4aV1_Uuvh z>HCljGN>?$sXWxopxPORX;Q>8pd*=rx!L&BbAxbEcpt~_OY5DAD%xE#6GwaNs}GQY zAH(r!<*u9{`?F^c=8vz=5JFyoMl+kR_$yVgX6AyaOG_#7y_X&;qxS^Z%y9?U(A;UO zD(GEb(Ek8tjv5#-gb{!InECc6{nuDK{=WidTun(B{{xSSQP#Cb5=7zsX^kGgAteo1 zv9}IcL96RBI3iaxs51hh@K{REq@1p76reNp8m22e=Cl819K@wE&EnC z#qhl2Jj>~RvU-Eh4@9#s2aG5piy?{AhcI|XeF;dh*0SSm?RkydOfrq*nJGK&ap`OQ(Q^IyvMBMno=>#1V@$^b$|J zb$SlIZjP+E<{SXjwwBy(!3~J(9N+_5hDM7RR2|L&>#8p&okn>>qLrE&7R}Jx!OV$Ksf{KZa)r zX1wfdfk_FO#(&kq*4}Gq%XUtpdT&#u+3ZvB2_6<|198B>I+m~3$rD7$rB(CPEtXW_ zTw%LEqkrtqT=KUqtrj*{#4V;HJ}Ftu#_TCn?n~-PZsCaNwQwERoqZz))(>L|O|7L!2nI zT=V}MB^fs%iKBZY)AD$8@hrEDP+UeAgQaH1Fs=3E89>-Wc_F%rm};eX*U>Y518piQ z1n(j!xcG;FIZH1re^Q5yCycQDq+?6pRx1bYW{;)xjFl-nzszz$oIde0r%*RmtyIpe zH^{d{HaM|hu#aeF&b}e-S0jfwH7`vzd?Y>CFyi4u%|w-NN1(F3ix-YzrQk9*=Ot#TE|gt~i<(0AI8dm{ zQfe%WuS=bIT)F2!LvXPZodw5IN8%&!aL_^1w^Sk87y;>yGSlKRQZ_7X60>G`87`X? zxZz@9#`7Gbk*4&jHZ+$U_^!Cpk)Er>hy2+O3yV+JEeI*-CaQ`NwuMgXNnbS#LVjUq zLoavbho}V&6;r&)HT+Xs~~GnsER1Y5I?|>+NUVd1!BA3a?e7LNy8yXgbi#Wf!iY1QVsih)LrJ^uR#)J>dv)$99CQ zEdLXl-Ms9i=eRWXADtSl@rLQ}LaV=_{MB_PaXTkrTeY{Mj?GFSLUka2jxiruOHntD z#&1)#f+_aphZsQ$Q!q|F5h^^7haAR-ES42o83r3(h3-0S9&R*e@vew z=x6;V#kWr{=z@FKQS-2fCG4}AQ;3-Tj zMO+HRkD0A|EjvTOsrRkduwB$G(0d?ZgLM_=-B-hvHn3*F?%}e#@|v#;Om-lJj5ci> z->QJD>t_BGjXVazy1Z(-by9Dhc^%7S)KI8Hnv+9C!N zX7R$3c>Lrnc@`1g_{TX183nWCJkB|as2RgMIg@yf|+1F+qPrWwAGQ-Q9j`i$c7k=Pyi#;g|dMdmw;wLYNC~Tpk@l%JzEJlLkFgy zr0?!5zsA2nz8Chl{WYpZRW+uYWi`vaOU*XVe3(Cj1wA0mXV%|0cX!^o-*0CpclCd8 z1mv+aLEt!aE464)zo2f773`Ayb;Gy<0? ziTSN$vp2S!CpQ!w9V9y?y{0&X(od@EPTrNINyiN%h=zq?4B8^BbuRc#HC4sT0iUZt zoIpi#1{JUq)fgfRyF&9d)t>jSZD=skj=dAP2c!`prC? z2VBIen`j)#6YN393)HP#6s_zoSAB8=tXY&$I6CTN(GAk0c2|hu)6R@AWfbTj!Tm97 zWybs+l<2!O712v}aj`)hB1@+{);o{K`Q);w&el}j4YF4W3khb~;k2hE)7;%$a7FS4 zLCtH70l$+I^opvkvX>oE>=k!VQ^a}WtxEdlthF`9Lm()FSyqqRlA$QX98;nR#M4X5?4C0fsb$6PrQD&+998?gxTg#Rb-t+f z9q1=p*)Ea5z7>B=9;m1e;hA1Q19WxHm(O)kEY5p|;nG|%wyw^qK#E>|Y5Dh4wH=FT z8e@!vhf;IZ9BedfDm)kPZJG_MZ*(xx&Y_NITUx7(x^5xNC1b2Vxmd(rBC;R)79Sc% zL!Y@;M3*Z;+du=cE`)|k2GB;43qyl)o@&<=?W0vV-}TkmYBF5|)vC}+kJ_&dJ0QDz zkZtLbO0p)=Id(&FMf#8zGMky2&CyEXQC<`m8-t-WXOIP1s%OUQ#RNmbKA%lg{G6PQ zm6~O;y$s+qU8Fs$E}vyQR}Ei=4dSAsgSNqO$%(Y*>QT}g^0_MBvw1M5k+SfIxNT6BStT}FCQs-w5sJU;X_kQ0 z(J%(7wgyH3%B@6koV}bcmlx%fy{hOc>d|atx0wN5&($e&$x=o?+Dw5@Ak0H7inW}j z1rO?2&dJo}%K;9U6To+^(i7BcQsGVoyff3qc?Cq;T-a~zm07vv)KNNvQaxxBGk+H291@N!vU-R zmpLCtVVEah?Va+MLRAn-p(uc_pj)k3tFKH%{uUVzq+6KHXC=iGig)oHChIHMBk(#y zS3X_`CYykrK)m(%kcw4XV440KDWQQ1%7g3t5igWh$VU5Gzrt*p2F!Ykiu*-!E-@s?x^)jwL6 zW3WWe6-xHzIN?a0yT>u1E82*+k&bCnn$uCt(iAG&$c^&tR!UI`Wnt;>dQ?c=X{xd5( zH_*1*eKX=rF#j%q6aMS0tm5hLzlraXWNrIJ29(jb(G@#W?863E1`PL92hCq8QQOyQ8C{|G|1&^leg2 zA+90ajbVZvia88DWfP_>y~+$GU+2kbpq@Zh<1Qj!1hZgqb_W@wNdQyxoKL2U6RRM# z8LaaKcxBdo27`XYgX70q$ow2X;8T9XlJAnRx}%bRTK6C_!ZNci7f6of7Za8%I;k*$ z-0%cREy0KpN{vG(*9t1NhtIr_hNAVccm0x`xkh_7mYNW)5~aM4LGUoYz3*nO*E!o5 zMhGaWh?A-`XUgQPI?w@zRw}CEcOouD;MF4v2mREvw=aDvLW?8Y@{R?K9PI)?u zaGP_E z-4?HLbOBJ5s?4ZN=}gwPaGg-pBPt!CntszG)V9bju*)&na$@#A9zIg{jsGXP5bpH$kSz+vn=kcxYMVZ^zrnD@aw zpU=OpRA|3{|9{^XGIX{y7IL+*7BO@&6ft!+cCvK%uZjhr3F)D;?8&R%$Yc3vbDb*Q zU?ZuAAxS)r4J_SKM~clXsuv%OvyQ-&inq{bA(kOpF9ggXkhNqIuq0WRBrtV=gkx0> z07c&~g(NYtPI8gdMhdswD3(sF2_90L?Y^;O$%^>!edSB{KBfEe`gH!P*Xw>9fcX{k zT|eTiv8=gr?4eL}4f3DZ!+rM_O?$)b7{UyJWM};>5UAGeJE^!_jHgy8gc~*vFnDN@ z7~e?cG6>q4y8zj zt2OX5x5hJ#E9ldr2~Z=y(XJAPjmm?-A|zbDZ*k)=6b=^_6oh-|yZu;CEo_+8)gmK~ zn)G?4?WfDApT-AkP|R|h%mh4ap%WZQOe5jL-k zI?YuSCb9QmfWlOKv-$<+UX^q$zvafXl3CtR9KEu|8)(Im?%8Uc{wUCvkaPp5tgGk9 zn1#)jh*UkfaDAvdw2Emc|F{{tov1e52XKvUfJO3(%H$hSCG?(|?0 zaTSLawv~Ib6uUE&LnU_Wt?liY zIzgNu3&uR+1OcLy{U=C3AA(zeeLURfgSx)LWZfNDhBd$8Wof0~Z`H0)ZSc?59s;8` z(q&Q1aSTXtf^f;5B0j=_HO!OA5f1^{~B~t-@T0@WpQ#aq-iDox-9u z@~ZcIc!I-NeUwJ=CHZuco#OgWIbriAJfzO@pvCVnapU$dtXWauD48^pj*rhK+BV3V z{nUg`oPk%(_S-@GMc*FEV@Hem&^P_5< zoco*xnY(^>CXPpjOiw>XYiqdGbCtSw{c=8m-zDCuI%AH8dZ1kL8WI7H-Q$t8y-iY?*vP7>McFI^hntZu#lg^ z$9fb8JI#H3B{R)^^Kq@De<_W%-`|AETF1u>dZ^3h&$4Xl&jmG-K0IXv|j*3s4uadih9FHE}AHr%@@TbD3&`Zl6C2Z_2-O0a12>2!YMk8V| zlt=I)L+|N(&@wY`wfqT;14_89<@%Iek)^|j8ivRE463yjb58-_UPHo!eAIgc|8bMm zYGbD_$G5OYwwSdcY}6&oY&a5zs&fwow-gjqCos8+jl*Ff>i!H86n4wl2lB6*#fKcb zSt;aY!!ZCu+u>)@F3y~ST^~&qr*BmrTBYfZu)WoZSW#MsEfJU5Bby!YYNu9A!Illz z?CU9CrZI_86z!}yF69c{sGiT2DLeEh;Wk{eR`IpmY`>9YlND*UK+MO^ecs^nr3_$&2c zgFIstz4nb*UPpUl4zqSTSJZ z&-8gr#wokc?Q>v%?`^$|k(^#+P$eZlBt^-YcB6JFsep`hk{-uD!G{Szhi|`pC{uMq z6*G&O5=-b&n20XIg8ON>QA896(P+bPCwm8H>Y*lqVp+?NHE6ytW4!s*t$X*}*{P6r z{UelSa2@U+_}dqRAp?z7|B{IO<+S*lG{y~$UKa9qcsPlIH|qX$Y57ZO;QC{0YF1Wd zA<{Jai(TDC8R8TCYf_PF&6u)HHv?j+Cn@kPw6Q#UwITR9;E9BGb-o=SwTPsgSt2=8 z{0_qL37?cYWA+EvVJT1W_&ivnOzTR9X)S@_1rXeS%|olou^8=Cv7FQ8ESyL<6a0@) zuMkBPA+=lyrjxOnu+?pgt0zFJo@IzHAm!ZdO0wfxrlWhK!#C$RR88L#jru~q>~&r^ zrCZX^0+OF4gg9XEh1Jg(l6!zzE>;${vy1t<1OKrFdHaOIjLji$$fRr>Z-W{AV zo~x2AV7@xFHabCplQWnY{T;D^(7MGm4jq%6aG>Q5u8n38NviJic#tX*}8lUu4e+r+gECp|b1 znQgVaCD&RiC%Y&8ex#zSd*O!WMSiQZfG0VuJ$y{-v|bRse-ASAn4SIC1F5G&)2VN8 z=r=iLPtnj&*<7G}5VSDf%j~}J3s3G)kq27bd=~wlYIfiA9fw~e zd3p@FWTqzGME7T$=TR;z@I#w8w* zesnA0Rq0*ccfXA4a4vdghgyYh#d6tMJ&>?2%KMYG^WrxNzVOP5Jpo4Bkz2#)ik16> zu+O?fYOvxgIKI%LX>}@zc@LysjIyjEqjIPJ#Tyn(#tlMdF+H=$adLdfsipMSz3I8Pv^9*J z(@ox@z*W0QxnQH91M>niY|L^T*2z{3-=IRl&P>*EawbFySLI}_vlRpS@&?=H4p&Fk zVISz-mX8d%`!L+mXJrfv(ZGN%09cQ1y`35R$4S474wZN{ALeJ_s`z0Nl07UzA1_di_D(6JPFWN>Jt7Jjih&dAjOhRl0^&Bg@7F4pQCWKl5$xa zH86;U31Oos=9~YRTiSSvfhPH$Tf!sycR163BMQE+@Bex87Irc<{I6@bZmcZSfB;O0 z{zsL6c)oXQha+0YrC1XbXaTf5Lu`=RX6#ah2OBzGpKwHlf#6R<&!b7{+}ih_eJHlz zqyv4$-u23ND!7j#!D3U5XGfCM=oP6e#c))?zZLaL!c7{``=82FNL^I;R`oL(uxq{m zT?!d%@-rFR8l}eWk5N}1^=+p}nUh%y=Gd7>2l;|$zB3I8_$bJwY-G|YdLap9k6$~u zr_`*#1<^d=y|slS8-}X;TBkNn`a+km|3D+6F>iRfzOe@Af2+zu^*^Bz{|$)vPnJ1F zdD0G<5rtQ70WznQG+4+JbpvSwghUM0R9Fg4Rxpx|_Is-?9k^Fd0gYcqQ7Mv^* zX60i|#%)mTaPqa7YSul|>`Y8gJ{g%}ou577sG%3xx7lW{t>H|AE5j0@Le!Ao#H2pe zofpd)r0s&)gEJlwk2~!YMy4}-|V5; zZ93s>^>aBg-_ZRoFzAMjq&0Yu2gP)b>UwXPpxVdRu*c>$fo^HXqD^C%WJCA+=cE&u zPe%dhH`WF7ZwE^LKQ|ZCf6%TeO0xFIj0nDREs)!#wpbRE>IF>&O*k4r-L?@3loAOo zC<#>Ha1t{k8*STHVtV9AVIb~Vcc0p@@IA%h7_!cBIRCFjWQ-0A(%Gz3(2Pz z^A3x)u{3dVW<1Zmfxh+oo*U3Bn!*`R3yeRY%jd=&Fx4SU6Zz*f8NyR09>q~|oqj8a za;rUImDFfgMRuwMdtQUlrtQ_xM(zG1epTvV@7W`CzY!t z(i6xD%bCp0V4j*(bt1$R z7l!huuLN`PBoRX8z+9&W*91{eHQ2TQKTPQBZWNRyENv^rJP%jh)dJ=GvM9HMDh=o0`l{A3K9cP)_j>^ZN}Aeno=HZ-X)i5N zGipmX(@prVn~@x{G}zX2Ws%yj`p1`8iR`-@Vr?l5Oc-v6wypbZiUUMjjvzy>cs!J( zl0;RR(hLzLm?DfKZH${wd4z^=me-^sdS#M?dGNXV8QuX)B{_9o!?uPpB7`d0F1CyAgjj4#K z%m2aWhp5PEYm1`zg>9J#wau~kq-fDJsUblWgKcQ#H<6&kfQ6I5hUD|GkE7Itdfy~% z{Q%H)DtrmL^K93h3$aW1zSTSL!{4#D%^hT5TLcY_PETb!?>yY)ax(Y!zWzb|#aR71 z2ZA0}H~&N>wj#yEeZ7h~TX zP00uGHWA}cpS96a7-2AHsA@F9z?^@fqKd7Imjv03Ss!(@k*Q=FOHlt}%86W+5VfAq z&>TQhO_JW?euqe{-AN|_y@&<>&q$78nG$}@KG!HLD*hy-t-S*|%x|IbYKYi7<6lXf zjf!lo$EI%%$VpUo0ii9b)M$&UlT=Ysq9~Sbmy`aNjEEBxcDo6*8D?iTeT+>)l>9O*ymUAHSj zc`^Q;d8maF}ktv?ELsG&JE+$ zVc{w1TdHmV{KBNv-r!>cH-Zel!7XH0K$W)zoXB&2oulas`|ZAO^dAa-PN7ber~KGX z?_|7ZJ~FT5RTXvWNQUzal{HaAS+WN=uNSad)6-l-8L|jeGvaDa3=0vh9QO&*+(!yd;eS zj6?IPjRB5ZJjE>?m(9h_FnU`>8c?FM2jZ`BxVlU5C}K}u1{QQ5Ruite=PF)#2R?1e z5wV@%ra$fY1GGJ#Gz`7N{M&L7o5Z@K=paQ3f+ByHG|(@+LZQ-7J|UI{X*uU<5i0)F zC`Ha*gmOyOLb49Jgzdtqigx`g$q`DQBlvppPie!NkxCS;?;6J+{NIHu>i;2J3ESJb znA*8W7}}ZGm^ulX7&^H8r*dSDHl&Zr@-qLaX(D?D&sZ=5L2z9NX$HtZ4KSDx1O|*X z0Rn<+Vi(EJqzne;h+mOv724Y+8yc4@R$Chlrix8;w(}iLs+V@URjQXtY4TO3ub-zq zY2zf(={J*c;u@Pw`m1OKr5wDXnNww8*q;V;^NxYy`HjFH=@0vBMH*ID!cg9 zZT26}6gnrR201!SB2Z?Nj}`bV^V249b?(eB9$OBpO7isfJ;uKn80r^(ZB?=hIdKnydHS`b^;PFlT4 zQEJ1AMx|FrYlIdiv|~G&MJzj=5D5Wd;W96QMT~_V#o2D^nKEFKEqG`N46)pQ0@XTv4oTw z3AKG|@qc)S3QI3$EO@s7itCbDrj-_Gg5>g%9fN80{2L)@O_N74`NWgCHuE`I(93QB zfZ?{Sbk#IX zYV#w`-iv63Du~L0HMqw5kuip+Cn@4L6|9!@WqS4>Gm`{*lu%!onHb{WsFg*q964qS z;+&bI-`;h5b9=Dt$spFUB@ImEIT5tq5@*-aVa&A>JAxL(+@Q=&U!dHz|$=QKF)M*2~f%%St-DOmw; z5DUNHqh8dB-!;1mB!bCIxe&EkT(zP zYYQc!_}R_LK0?2^aU8&kdg1dc+u5zx>l}vbofm884+=ONHxH$5p1I}tS5_Ff;kx?s*7>E3W7xWv|DwEV9`c?9#7WOU11iy-X z1*OEjRnXhSuJYoVanfW%{N2@xy*z>I;LUD!%`r;2|D^O~yyT{wv%w-w@Okm41B~^& z>C;EV9n%FP3<=>?5jZTAQrME8`5f8>LQ5RRWBJu^$r@EB()|tWTM$K`(uS2Ywagm< zPfPo{`eiY>LH#sg9*oaIe%YBNj;Q;F3elg-I#Rg5>-oJBI17eL$2$%rA*qXviNkru zROje`EVjgQ%5KgLopGMW&PNz{CV3EpV7gkM)u5W{?0&XqitF7dIP zfxU%WD)5khrt{68D+lov`4em5ccx9K&J{^zOgmv9-aiVvL105 zhQWwDc`%OXZ|_(Vr5UW7UD#-N`$Mu>a}<-hZ?1J)=0wHqGTZEyK<M=%UYp7 zI(ealT1`EtKHtjKGUP`ms79RGB~P&B%QN-#FlIK<<}65u2~chOB@lfGOf*+mW5&qG zk5YAlXz}rn`9L|;kvuY;vhlaWgTjVfh?4`H5E#$G{`PF}`7Gc&Lb+KS*QHl5bP0@= zEMO{#4i6^u3!dS<3Lbzun$ATG3qc|48*l@^hGIsP`K?TjIi?SA-Wv9k4K#63Ur=|T zsCA(1=384PZ1%)KeDZUul2)Wk&LUN^eg zY}JydAA6yg`TG3=fYmICqhhA7bI?0jV;Lv>1#8-(H!8}r00&BFqizkh+71GA_FnB> z7Paufv%bH~0Tbk&jWq*^;95~C-`G)%eN0?yPZ^d@9TJ84El@Bf4YNzf%k^;sGD97! zOUj~xsmPt{WEreBp$F(JsvhRCn$;uckz>9nQJtyw6qf5}9ovH#LGdBkXrh5JGC|>9 z7`{Z&e1es`Iff4z@ggjWXX>!S_zgR@iHU@k@ehByph1O@onxoV{oit#shhzjdc3U-DX{Y0oONS1&8?ElHU27j5Y?tN= zJRL2#&ZF%`tw;8B6ZVtztJ2$@SKX)mSR`mQT>I#r_bcB~=>2gNXi7xvz-I?$mVD8#NIdF1a+1JS#VbcUT7U8IqlIQUm1ig`|? zHAfb37{7S@Z&}!ZC?7xP3e3AyP?~PTc-N^5AX3ffYs4V@6mpbpbUIs`$T87y$8Wbi zo18BQveAyd%!Uv-Kb&>TizCY<`D{kh`z1={(rgY*twonl__o$89YoB~s zBD~b#dWqg%JFoUsEqg3)wLjQkAPa)WH*3GWmX#$xI+rEiR+$17Eis=2?L~q~0 zzLNNVt&17N`!&AzOV4iC8So~GGx-mFExZ~B@$bt6@yEtMuTZ&JFwp2|)_bY0GrdT7 zZE0}DeA(Wfet@b)fTR%IQy|R3AI`aas&IV7_3Kw{s>JL*5(R#Q^)A112YpS3rH4Mb zHj1{jfga})tt?)99vZ_I4&A_pT~|rb=Z$1TaWt|o;0SqTp+2X${k~H+MNFSMdmcK2 z6)im;_P)vXu2wR=f)~1x@~HpAmIj3=L;X^N=1^9s8MCT?4*Obci;SB9h7adzWZ$#< z+yIXVrXteCnw932)zL0B^7}my?>XTho!lkCE!-?}ZH0x2d**&! z>rS$)@7FLe6KRXaT)c1j`!w1j{R;^JA@q<{&Z6t|qOa|_@43K9p7vpDFP)PrNR}{b zDF(<7DIMf&8lHGFbdaC~2a+S(z+)B=>p?p&y5$O4SIfnw^A5J3m`Yig&!wFNZ+0o0 zv(KdyOC;AIX>NsXi8a$~O`ID#rS-grJ^`tFW{q`Qn;N>8sN6M|aH5nk^?)+tv_^8x z0c~!WIBIw>c4<70T$OIJnw=Gs&o3?jX&gWM&Dsu9?XEr$bZ!ye)lV}CP}P7-uccSy z>$Hg@i;)G^z3{ug8(lTDL#AIZ!pFmUu%(Q@;N*xV^7jKb6&8=Ac~#ZstW?pIDJKN) zS!1b~EjbwRQ~CG;-P~l}DK-u*1F_P?@mRlLy_B2F=2X6^WOBE-RTDY7(~5S`rGgRt z$`R}Pnz9MCH?sPR5!#3&@l(KBOII$bQS|VYvQzxj_R%@WAov)86?yCF57?TEV!~^d zrn1bCi!rL_4>_!DIZnL4{X=e<5L!KjvQ}l|7BYitnAa@KUj(pES7imSxGoD?@P2t) za-_M4*G&>fvI_Szg+MReKu9P>YEpw1h{t;rr3#oRo>a8OPFiwh`*myw&*v)A=817# zR`x}-6-C~gCO5FGuIZVjMZd|iwE#YnF=h#m4JS*9*WL8Ne#I<2uevHv5VWH+?^cbe zN@LOUrHHzUzQQycOFCWCCmQ8V(#hd~+AUnul;UvM$QVP|y7jtLq#T~b+-xGR%Y4>2 z1x08!8KSvLu5$EG$cEDQL z{fIW&RVV6W>&@0K zE*RIc3#Ig~mi~b)`pvtpQtvn4w&U-ft(mth5VDcC>DtpAKZGO@pW2p_y#>N41^~ZJ z2%7@u3L(_nb%okMf&r0rgE>UOjRI>m5HWVb5UvE-MG$4};1Gte5ZoyHD$fFhG$8vv zqUqOir~@ttbPB;dt=bUAf@>8JgIktD5eeN!TQ9LT|_h3>bnPhtFR0%lxbx=#GMq0s4_Q8hgv)0e8qDR~uAR`W3-6EBJtSVwd(O4&4G?Np;KGh2;%wmzXEE zzdGJ=b_;y@SQSx)nq4kB%a?sapq3&`Ow)fPV$7gcCcn?Y2atu2of2&;aH;g`O< zXw6n!jN(2p@AWo0e)EQsL5WF8VI;oNn3*_jKlzqwoW>U2NH~91P5y4=g&_U?0Zg6G z6Z9*P!-xOxasbAc&#uHXb@@eX`dTJ#jLW*q91>nLdGc+h51|!(3li-)_Jw29V$}U5 zs=N?)cdV#0*BKz!G&Ef9jP9ccTY5*h!iC=Ac{sSK;3+ZFXWOEYzHz-w`wBVuuU}^N zoZ!t<9iGU*QL8~WcJ*_9H+!h9SMv4u^(pIGFggVhnn&~cv8OCQhwoN~OQJ?n_pz4E z$qdzH{`C40HucSn-q)QxMu4_TJPuUTP8}RK^=QS|hM4q;Xr6okOqXGm(1qUuUV#o* zAkL69Jjv;hn;GVE|F~xC#wMjKmba$?IK1Ab+hb5JFD!Y& zgW=T`;@WW0FaEfBmp9(0hp_Z&jLtl56MiW-a7*OSqOY3r;CEX&4v&*&KMCPPDcP{{$6;Lt`LCx>5SJ&ChI3^WaJ>5X z+z3SN@jqwxvK^oDqw=Ywr9o^aK{gt_3OeLXYm030F$%#!im~8u6Z&c@aVrjt-BGGO6Vm zkv5EggQF`LalqQez7I6o=bN6Z}gyr5Ne7f@e8_4%~hy;?-YUPUUJ zK=_z~q-H}75b$q1@lrOOj6+<-=A8o5ei6-OF@x+<0ijbExJLvuSzib0l4Tw8z*z2z} zBH{qFz@k+e5OH}eh*&lJ z=?_Kp#<^+@$!m?#^F}Crz~J||@W%MuoRP~M(-%Ft;ZK}BA#RQed>GB|Q+NVv53h0! zMmswIQSPpT@N+gV0a{iplhLJwVHGXtXFtqR@Cjm$?Ds$GSJ!{>${J5%C5-_y*LMetCH1#e*>B1AXV$-W+J z#5(B{GDswIBY}ciQpMb%71zVXUL}~qAKX{pTQLV4?)+rbnxIt_KOHqQls>uMX4|YIC{E&P zf7s`pTY~GztT{Z;h@Ms+8&Ig!g_tTS!yQh4_p)Wue^p24)ad$w|zh&Z@sw%{I zXT_?D3Bct3;pYQUWo*dBea1r@#;;2F7=8_`e2#e;AdmwHdo(-`qfjp^%r26cetQ2k zqmP7B`@)bDyL%h@6EuWbs<}sZ?lYG(Bky*rtd{ITP*1jnuB&n#S!J9K-?}qlbFxwQ3KLPY zZ*6-5FEGvIQ3HNUeJQrE_)6b-EL)zGryB_hj^@Gj!ufm!=Vxdur0BMCeMIMgE@^EJ z+=}}b2kgUXHkVu?`h?5Li5K&#sJ{#Hq$$IxErAE;7bfch254e1Zq+ag&=lV4`YRnZ++j=APnu6VZv^j8F z$6zoA=3wiHd1bL@QsGYyQnHo#oJ4J^UMrpROZQHhO+qP}nww;_fIl+l-+qP{d zovOP1aJ#E(jQzNu_E`JpT=QFTIyndyb-$0l5)HoB*Hnl@{BwN-&;8mc{yO0VedwRs z<6WUk?V&Non-KQ=Yl9#z)|JMj2rt4JS{b@@l8Nyb0=IUhh3B4$&pX9ng?cqfSRUHB zJm@$A;5c5B2e1lMIv}xa7*fjy)hc8I%}*A@jBeDam0gHRO0vX1v3NK(zxPUcI5D>x z(u!1*%KR^#hUE!Fvl=Df3wTw5U7f>@ZC4^U_c zrmHTz$`=@0xCb%z)@fC$v;$YmI0IJ*ABqXr-eDnUZC~4{z`)$7G%YAJkWp`r{l3>2 zK2GDdpc6*EmQtrp1*o7^L>AX!EYMKPL+kyr>-#7U;)|xqglb%f)^}CF;W4K**>>4Kq#o5z62Q=;8*|=n&-o#2k_yCQnWxMB=ZFf--4Z#!NxU=;9Il zIR@8IQ3o5X(6kKb%!-Andk)R$SFqd^3K}*~PzVgtr7?mB;SKPKmA~oi`0vo~`s-3FnIIuaepeHm-p_01S55Zje%|i~^Z;UxGw|@8 zR4A}~ED$&yHTI{56EtD=nV`fvbeVgaP-h>c#C9BF%arRtum`24T*yG%1{B3biUr0$ zO)6t`N~9w+T7IvN5}~Dg40*^L4Lfo|>7aRyF&&UqDvoJ58?!5*zf{Cm7<79hny%b; zcDhBm*I+U)hax|ah2mW09z-0}BifY@N4hTlR4rzr!w@6%UgaKYREcAT6J2v*HmGlt z0mLK7MG>9+FBK7jf90X~t5A@0fqc9fIF4=2q^+HJ&HGa`M?-(w?0n3^j6ouGS_yJC zH%pD^ku^$FOJZJfFAD3cbjCcvoH-5oc7tkc?PeRW&=`!YyMLG}VH1a5d=LzNRdGsg80X^HaI>OEHy(70u0 zq+6X#bc?_71j!tK37gm>C#M%rXZABBbzK(vjZp~nVY zXmTZ{{thB9RB#3^^M;xeXR7gy+sLEWFgYKZ9IAqG=uSFX%Vni8>TBw=Ub?v2X(bO; z>y4f^Q}$R(4QVoKHUu8}!$IkSO1U{M74V0@rP{{})LkbdREn!;@*-oJ9;a#g4bfqw z1xVa(l+3ERmsqOLn}XxkoP-oMvNyONKPF+vKe^m2ojRk566D|zZawN1PLPq=X5#V)S+whs( zlD)LN9u;njXU_1fv{XPkqi^~K^9%T#Wa%8O?@|?O99OEs{vvI?FubxLGgbUIrv#F|I~#ZKS*UGS$x6(57>^Qt>YCZL%&3?+p7JBFv%jMDT@FG9@qA zM4m5;w++~CO_*j|b$e1wmsSQ;JpKfHW5Y@Og;*8zo`Q+A45wTDqoIOo?k+{<(DeKQ z1?pQaxli8sh3?SkUU z7O|SZ(hqQ?@b)2w%J=OynQJ|>#33yMrkgDjukJvS?8dCaIwxc#H=(pNv6Q*v$d9g6 zN!MkwUS9m+>%wVWhu=?t{knGA^v+#kFDsb6uwGhy5HGoOMP<74#vLW%inWP&fd@%; z=E^Fo!BNsbG%2<)1LWBfb<}iy1ENEN%{levTK1~cS!72(cCEplFZTa2f-4t&m)ZVG z4jLf;rYJ8~8Kq<|R_au=JeS1M8aI=}_#j}7d3e~|!!$GTbX zEEwx?JEcbCyA7UKK);mVgQHnAK`e|UPi9a1`}?P_J4gUu4(S5I-T81GEZyfP=xxc1 zqfsk;xlN||WT(>J1Oa6M`@-!Mnv{tnmu>-BATGev%nG8Sfbffx9#5wIX{Wk1LljC* z5-2x3$f~|68G-lLT1Uy{4ywSofCsIVHnIg*(Ow7s8W??IuGpseFF%}vf_o&~uegmG z2~aG@LZRn_bNrkq>bcCPKP(T77C0M0x}B?c-)=_&+5rK;8Z~JCqR{I(ud@ZH%!M>5NEK)7{c_mCLQodOz9e`37^qtqP_nuqZq%h!GAs zW3XD`ZE@b(N?JMh)6jp~s%xxmkF-0Nh?<@R+Dq8JKgguM+&Vq!wlD?=MzaA&g>U!7*=-@KY6Y!CNEMpU_OprNG*gG(fw4ny9N`kK*m`# zZ)4r4Xb=69+9@we;;95Jah%RuJG#a^*F8Hj?E#CW(&x@DkQZ5Y!>+cTJU)&DhLzRc z^(OjO9@fV;w7Odpe&uR^O9-(iC;lP34AO*oh%)$6Xx*o4`!dnowZtE0&7-nTQ$l2L zuPnF~qWLNx9O>@_n~KgYS!Nj`_1ZVF-8p&ZRvQ$jrW;Cj2xI-GMkr1VHvMTyF$*Vu zdeA;|u5nFuDKYB62xCm+q>~YVR#btd%1lBYwaK2K2OsCanvPC1kERpr8^H(vUayf3 zATwoopz>JG<`E|P$zre)HO{V{QMb%3znXh9taPtBdj%74gU)9_;m{q!2d_igFb_=a zTG_8iM`2|d%i$PuTjKyX1|i&-q%wOqgnw?q|T5Zf^6OSQfcWQj(mR9cOB)vgRus`V)BYmZoBuy4#-IN~ zioy2Z5ODw3FDPkeY~yNT`oFtv{=acf*;al*0mbjSy+)gsiJU&DAc6v$;>h%s%}78m zi4-{|l{7kE${ly8mQ{Dc+&?KsBtmS!+&|@R(>iuE25h}Ve&)FSIxR;f6Z=jcZTTYDhpLhlYzvwB*9F= z#*T4PeTG^Q4GR-jv#@Y+MHW$izHq|h!&G!I-Sv@Zq(E*_t#adnY@q+*f!lKQpfV~a zj_;AV#AfA%Ls-91W2^C*cA%-Vw7#iv3AM+jdU$4hWg>MjvQQwMTH^w1x|BCq|2#$HVlhHD&EpT6rj14Q}2)LkAD( z2T33!RuMe|8|@??gK`|5LGqJG^dMw^p6m22f|`8PzaYXeD$nxGHuQBMLrmyiI)td| zXl;=ZOs*G%{|@{IkM}8`W^)9lkkE(nPEX;iS18fQIRvVZi;JToqAkZR=lKhMHuLkz-CMU7Sv$+?jP1@f z-q`mPudFWI(m0{MisC*fMyhgz34-ON?Q2`Nw=L8>xcGcP>i94Zi8`SoD9MD$f?FAa zk#u*qmY096(cbGVDea$hU`5^4zadspKYxi&5REFRO6EH6@@CW1l;8aqDTPC2Fop=) zn+BAZ*Ba(8geTJ%vgfE`0KtJT%+$@LJ36xaS{HWfWiCj_@v8bcFyfKf&zRE);{51^ zM)80OIsQS%NDI51&w>-;FS{B7GdBMe6DF}052ZL|<9v|FNM+0fGXcOYfu=Ki9?NzGz*(YVIKYRyq=05YX$@JO-lqEamnvMLGhSXf!Os&#R-uQ)q9 zzjyoCqJ_B+N34mc0kKPks*3a(v*oqRr$^DG-W@gr6GNMTb!^EX&@hAzMkGsg&(>Qn zgj=3VI>#gdn=8_D>SHZo??zwM5UOdn5pV36xVdvfT4S%Ag~(0-pgz4(vG=Az_8r*&??gp#WSLxTZnzIH)j|x zc$MqXzW0JqZRwLMI`@oFnSM7C@%5}LWlWame6w2~o<=k44uL-kWm_{+o zTw$?d{R{hj2QATh{*DAI^8{$|wc;LKU0t)Odn>wY%m0>u{b&)a-&g^`;2;;5mye%# z^2VN%i>EJMk9qdS+}gt2;kDSo6@>s_EB-UG+(h*)L-1UmWTn^ohHI{kj6rz#F2K`u zvPnugTsecqavN*84-fb06d@|y0HO(`kMjAM8+-BI>KFl?N}s|^F%?emhyp}5%v7Eh zVqes5?KhU6aVWXUD=p55Tpu5)9*Gn)p=8m)_38ZtV)+N~JkCFIHVk3vHTzI=B8?eB zKVYOYOOLd)FPvaVPIDI)1vwjrxaB8sR6T+bL4vD_Z}FthP&W@uz54zts!lNfsB&n@ z+(kpcbR+xzhQG_&+mY7wMOc*fqqO82_T{%^nflu3Q;}JT7_YXd+kx(i3&|)*q|{q} z>YnCREgb`*{{-`C$zL9UB=2*mR71Yka4zwJWdRbIhAkz2S^UM;?T z^By*n{13Ul|MZKO$c5}Ii9PvO-9q|A4Vz$7o&AGQuF<4*{LDG@LP`BD?oSsvq6n!| zB7XE&ea-3w?eG>??QUSyVIApk5ApDRyyixgo9ifHkVjArPOT5PW2qR} z$CLMt?%0?HfZNT=EMkHd9$EiAxUFe(vLx(OuWgx$He^GyHFZlJN=TE$S{L<7>85&t z<9~`()x?PwA9pnpZuPCS<3fM)%S$C?8pV>Txi7E|&1f)5{Zpq>l3Gr-6nID|Jl)Zdi^Bc;vNfVv`%FnHANy z2Vxq-=$K%#LD66I{x`dOk0UiU9V~Kl^nM!c1ulp^aW_{OI)=g6fWtNq9W4S)}bARXln(=X}#y6#gn3C;5eGp-|T8M z*$xd;Q4%^eD*?|!IZ`TW($+LPb}eBm&7y`sB;8P!NLCahV9h!!f=6v8^qQPqeyEMNBfu$CzXP?;Gx=y;I zaJgMM6~H4>C|T#(Xq?{4&gVqiaBl#7M2=2TSrcB_kUqtJx8^oAuu*SRGr@DS7oZ#+ zrY22@fWJ+r;lwu3H@c;|*2y(gX1)Jii2~DLmG8Ahig{)yBE$r4`rj@5v9nB~Pkv{uLA;2Er4?lnFxyvS85){E`9UQxN(yIbhv`svBSjLMC+N-b##y0+5zB z*Pp%om_5Dda2@>n@6{oyj*u&{B*ZG3fgee}24^|`gw{(_x6E-m@&z1*?vneuH>gzI zF+Z8Sw&hMU*4m^D_?H;nDL*4qe$_SBOD&bT#7VU4KoUDwYDZ5`67HDhsp(qd740=x zs*c1joHZAVvIaNyHs98Tkj`kIN<~{c6GwIP=&BCV{tIU!tS>^`qfKvBH)LADwPoEc ztN}a27Ogc~k#FBX4|9z5P|(RhU0VXjR$)_jrpIJa(I+LS5lBpZ?~6xga&?c5b%ma_ zRbCjfCD)?#Q`-v>@WP>bv!>wv=(f0)Zoa9VtZPe>S#5kU*IOG1aH+5&O?b4QOd6*V&F3P7u zlt~-tE&sUS+Uj3Kdn4n9V=U^EL!=n;gptCT@i_4qm_*y5ikofF_lLAtUSi4^Jj7a{ zGwEfebT@lyM0cF;o(w2j-hXaI403nX<9WtCBTor&Y&OJqiwahvP?)xt@EAr}$F86T zB6$nrdL|5J5_Q3wSMJ#?>(V5-fdHO>n4jvSyFF5sJ%%2^_QwBM-{K1NBaHO}zEHAe z3XZz}G_2MD1s6GRJfOBcEfO=M1v;`YJ)B(ux`yxTWzW1m+BYtGGE-a}vH;pXmZFQxH$SW5e znHT!=6MiOap&#W~%9=-zubx~&Q-8#dcb5Rre8jw|qDbZMEM2Ww25C<);MLXr9qVNq z4H=+&jvbdv8ZjR6Wy5!4WA`-(KGXI*($6|6qob6 zT&Q?^En`4;MUNL80-dlJM;c5Rso=>YKgFBHLed8#HAhUzi*&W+ft;FWa5R>y1%QK; z;K-}IXW;`nNhcF$emXf!$&X#&n;Blfq=B3zN$7X6;FK}mQigI?oa^xE&Vy?ymO)ox z0!PK`!LKMA^FgBENxqyPk!)=_(dN_&ObM7#SL+%~`L{ZROEpv4x*8?%_u1($X((+?j<{S6H=d{K2HD6znAcz1#;0)V4x*Yn#m7HF;*MOE#&z z1edWCFqA5v2s~x)qChZVcG&!S%O zy%v&mYPBputOWhC0Y%@6)gCA$!(VkzVEuTCf(WHrDPk=VC{ckB0Xu~^vF(Us0Vdy; zs@P6KmAS?lf$}{wP2;25TLX=57PwS_@0Tg|ISLu zFca;(wQh?_eXzMWF^*v|ah=Dyow`T3IKH^pO0w#B&|$6PWU6X z_|9RC)c+!;=3_w85$zC(%@&CaEOHJI|1>A6ZOUCHc64X3JjkWykMzW6U))I^X%(9L zOR}>U0FU?=+~eOrBrbfOf;M*mXSzX=VMBl+T?nP>57IA3h*EOmo05kSF2CpmH9ON)OjV22X)O3%e82GVo02-w zRxPd3sGXX7ZwggeNGz#~J8#5^JtY>mZRiV&#V;yw>&V*}plE^FQ}QQ!7@xq*ev zsW(-h^dvJFvo0PjZBuUshk>T;vP!+fjAhJ%`fS*u%`($V9oW^IcuBX@G{M;f_{e&^aEAr+tk&Yw1 zwve#x%$bR;O0Ua2MqT&v2UP?mTciBB3Y4WdB@l&)v?YS-;uzt8u?U3))qFoT3jwzX;*nq{thjMy0 z63tSP^h57sG5T*a{J;nEyKt&53P#lgYO(wbLtAP{>EcOEp<#}}Bqe4nmd9Gd4*BR- zj!_HM_%ueH^ksW%@7{$d)P@Lqstr$hZIDC7pD9*EQZ73q0IF|y?7A1j#}N+B>F{^g z<6NIK5pcBbiFVl%<_JiU5j=j01ca`Q?!8~supzb z$D|&69V$C%z%b_$Pm};axD7QivbqMxD2>`UmLl3liT1Jv0tOi=JpE*A#25SzV&p6N zc(Oh+6mds3pT#^(mPU*&?$OSQ&{R~Uo=Qq$Zpi3!LqSomx(%95F)W(GRhqqENKs2q zN%w5_d8B?TSf#8MZmVgRJ*ciR^AjRXgtLCv2`sdXIa^p>(8NtmrMxIipDg7eE$piOr%LaVA=c?heXjU~NnAsi_r=b$KdQKpMoD6Nr4 zDA}!1aIvaRiv`2H1(xlO7fkZBol}PpMYv4WMn#mEv!()1AA}yUOKnd{G?^!jkkks9 z7ULyHaM8sJ3>b!wSWytaJn*$zOksMsV6OxaL?*WYZ988jv^X}3{tj&dMNIARS>e07$!MMS#^D@ zon&1H@Lfc$pqay)cYETya{uQ18)8c5SZ+oO!i$Gci8c0v@R##>SqgzO5gKZqTuT~T z)e;D6MgPX7mHt7$1^R_ovCucJSH5|(Fa`@I6{`3kD4jS+KmRdYTOrzFPl$3=jDV5# z=P8g%d;8gi`9wO7*e(UiJ>)&?heTe6j-0uB9jI`dao1-dW@E>^F;eT{%wvq;Nf8_QNe zQe*YE8yS$RYA9ab9DVF1k@p_=eELZ;r=hy2d3-s_j_ua{5EJNt%Q4K}qQU}*>Lo-* ziFBuOF#*~k(QOdD=$O5n!iZ4}d^n&FteVV+3D0%k>!^PVzkshOk4eGk{V>^?fIEfQ z?TMc!Z(nDTW}DrzltkaB>SS=3KQ}@cbR=zI+5pi62@%N<<&eno?9zc>+9FFsRAF-y znp(sGl1;SA5+SkqKf^%nyrfwhrk3Q$VN&RqQ!usuHb;1pBzeBDvAe}z%uRU-lpK2S zA|<4I$~18xv3t5p*-Jdm;zlU=$=|(>hi}FRN#Hqaa38~v0U2ZKBd@O-4q$p7P1pdq zxq-&?Cf%}(WnL+kWOKEXL3SMy!z;VEjv)x{*@`aFGKdYer=eC;rb}(jpV^g>Fh0zM zzF={oKY4e^gzpy1`>%%XEn0F<@;82yxY2TdG45yz79Oo~Z+=g0r%|bgYx7Ie+_|~5 zo|$Z2vF<+@WO!9n<-oZSue$iVvl}cvKIAp!`WSVYf-rFRhPfWYOd8bXLn3W4Z zv|)DFJ|`L+sDF;jJ6j>SzNg_5$b7{$wtkB^0dsHSP}OL&(w{gbI6+F zowa7ofB|bO3Th)FcXldRbb|(_I=c9qVROlHv6*TG70X0}0yp=fjh-7R?o)-bv@dk= z&JwHjgyG*#+uSR)NFe_*o$Y6QYX^69Xp6 z(l?2WdTf$yd>*@fL34Y@wv=_O)!_P-gb}kxwj$7~)vsK*&Q&JWP*FCp#aSJwl4>rKDP7^HN+z+k^OkU^k_t)=YVj>WsgTNb zXUjARsVbV1Y5|`GX23aLX*vf9;Fr*f zI4AfVP3i{ z0moMbs+|f-xT7O-9+gz;8fH@m1U}7oqRRlwbSj2B{EFER{ijz1J&n^F>q1-h>7;%e zxB4Mb<0bQ)t@w7*p@z9Ix>*MZ+ zZs`ku?>l_3YsB#TTj>kB!IzNo7g4poO{IPigSJ5wPL&ZiFQmWMb{YT9;!Y2|eiFlio+qWUbOs91muk+; z$r07!tl`N?QSrSfN&xSl@IPjHL^_Osdjc-ExBW7MVCzE^OD%EZC=1&thF)ry-uSac zt*c4wkfT1C5oalMEd7rX%2 z;N5Zlr zA&C$ul71?Zeyvu>k)1FEyD+j=P#ySUYxzg^-O;jUQZWyJi7_agp;A}2DGTn3aytV@-Sp@U2#6CycOMQHD3_+GFqVDw$cOtNaSbtK)x}QcInWiQ+S~JC~`yz!l={@JdS6Qb%Zm1u#RL&tH0__9AOg8z=X&g%GPG> zmw=@;Xhsnv9nAs1U{cm3e*#9;rf;mVqs~+7L7G31SC6K(a2|=Z90=>VPt%O!0Gqho zp+8KvhB5V_jO%Db*_(h{Tygvg2ieO@jN{B^B zdc+^a1V~765+M;Q-2T3X@_BT{Nhob64+6k1!S@o6KvbkSI2{G`=M*&XNSM5l9VWpX zCY7|9CP)uOUL(JV_cGDrOpGDc`v~x0MCy3%9cG0cX7Rzajmi@{eKGBKqlOYQQ4NJl&te&I)rb~3z~FCikHoy5Zlf`t0&aS*XaNL>BC zVJ{Z})9bkPSv`v=DIkK!3&-Yli61f&?8O$RLZ%I^)(mG_)EA;11h$p{v{ivW2niP@ z%+-MHVwxIcgf4BA{&)z$Lkdbyt#iv(w96`lvk}rhZmJ~|RUd+anTHXC9n>5xM&p5q_Fp&!Vh&j~Y) zB9-Y_y7BK_1r-HMft+0F`;8~iUmqtV-K}HR9#;IzDrcWOu?#_c?yV@7ceq8|pnhe* z^J^V~W_Zx}6u`oUQ5)Yz9QkuuE97?jo593RfURQ=WT=)|c(#N*Y6RAseJj8nzzjE} zhY7;`Jv*#li2GhqB>K(pb$5dZt5E*+h6v`HBL~f04Cm9?_*h7XK6&2_fUkqc=Nw$7 zxEMz28>=|5cX2c0y%Br>>_s%?aYqE_)8}E&_yyzo@~RF~_ebmgDszBDe<%|Ih6Dpt<}$9C0)MZ^p9cbDm`W%(CTigZG$TRNTMX%pszY*_ zYjer7alkaT(fN-xjAFj#d|8bR?{m%?@zQ5ETR;8@LNYZHzT&wR&}XLARceN~E-2g5YtQ7azlFz!gUS|;yfgIX?@?^$^8HtMZO5bk|re{V!!ZJe(P#z??`FaFFf#1 z?FjM3nn^bxv(w6NPLib?SZ01@bEMReoI#g_qcG?VZnE|Yz@mkbZ>}x2Q;``5JOh-2 zUE^^_C2Sih{_H&*1LuJtrDt@Jv%lp5KVTJ?z!K&^3{we+R)tEk>y+7k>H^|EZM8QC zIhnvV-HU_1Hi`;HEXc2jQj;SH6W_K;SscPv`-2Zj32TqaAn!(KXMr*_`?@g(Yefix zi@knvV298wQa_khDU;(Velr5#7yYgahZPXbHh#yl5IuN`&Baq5d=G#SP4fE0%j5~H zJ%R_0^C6yLfr5tOQ_Z4TJb4Pet?4Oojq~(CbMEu#`x=q!7Ad7#?5IxxAq3 zWaUdDJBz<;L^EdZPe&zLY~K+IRI9bX+vW6~lbk03swmQ|r%F@Jz?TX(CGfx%dGL@t zf+$xEpfCsV|ER_G*VGo(t>$bN#Sc8b$!K{e)W9sP^MKOuur@3&?}iKLhTDk|j9^G* zvF-(k2gR1*$|r&+(m;NldjvB8i*Yj&pmFiySV z%Av91HT{EUdXWhYsh2FFN}G~^raFn0QZ2a|YBsQ32&z{3V`_L)Q5L*zMm0|60A6xu zGkT0n5H24=$pdb7t3z=tSAOhSmv|z~Odl}igJiRp3~NUp7P)V_Z`8kCAkg6<+DSz@ zYo}14TNW^UC6&eN7Z-_@W0!X!RfYD%7mMqi;pw=gO&iao-!;2v=Ox>fH0fmpw)PD8 z99#gmjNwYf8^xdo82i*y_z3X~w-VMih@I==2(AH;?AH6b|A25G{ zKLJy-*1OQL;yQ&7uSi}Pl=OF}w{-Hfd>8M$`5X3;;rD9F^;)}VL@N^02Y;2x?M29C z_!`CS@)MkpL~x|X+z9@@(%98GhHO$VjNw$8FL%doC3W%B(3COXMGJFMD8rwn7W5Fp_;B%5~UW zC+hT`EkmZg*c9x@934HAsoCG9^`34UlNp$|Lc{xT14AR2x#6IDY`7x?ob+!UN5 zRy%$1&)zft7^r8MPz-C>#i)$Sq;13UW+2@tg5R0L26^aL&cYAs!=#5? zxUnnCae#bOh1a*;NTt)5;9lZq;e}caWE>nHomDYRY&H!5q-OP!{LHm~hDX2aAGzck z83-?Im1S@JHj!wSbMPM!Gy)Aa49-DDgRiPPqnfufl>)R;=$@IAKi2LzNvH>{jwyuh zz_|HA4?busqSyyVmh<1gURj9UFtkB7!d9CTUx`cFm`i_x3XLUPmSw0hY1fLttfAZT z`a^Hwzb6WQQOs2}4hB2`WCBBP$hX1K!ar~Sk{=Wq`l<4fFZ6I5458a3m)V&P>*J2J5q~ZTTzX%wWVKIXM2r)V(Ar&wKrjk9*8 zr^iGU=a;D*^Fu}=y-PsyTDt$?X<@UBRFfD<-45PHvoi9dZ!hc-Sa9NxIe;%H^+p)` zkj@zRHU1m(dr`p)!un$@-vZYKz6fI9fYaj#;PFAAKM3C{`+?M+i0`TS!Cddg_XU4C zvhel@E(iCC+KHzbcCTMihH{<1fF8v}s5XL6FtTjnVfjH%6IQy6Y zT?X7C*Hj_U3ysIfWROc7hEdc_4cabv9|33~edQ>MbD_a=pLO!M6h$jnpjGqHqmwC~ zIN+I*E7j#H6M8Y5b%eC%?b&M!a!5JRUWSW0+Lfm8!`N6IzJbNXUTeN*Y+RSgb`yA3 ztHhqsS8%sz*z!K2cnc#+&(0W#X9Rq-@61yET2E!N{$dw1AYYl~{J8JT+TKcyK1^R@ zPi3?D@2!I*Uzs%d(SKzZ^DWmO+}hvoscfhgZ#PsZ?u4pFMo1p&i}K?)py%KpBD)Zt z7-mwZb=wv=dmmmD9!%DFRN3T7(eDR%DCK>I3G!qHto8&f$Zug_`pWJ)n|x=|o0eZTmeau9ALYzDfNN+m{ar7!cVdVnObv)&qzuGS zR)X9rkBr9js=wnAWTzZy;)bM2Yc0(}iudj{G#mEoZb#=!#aWrT@Y=J-y15EH^f5BU zG{1GV_TJ;nMZf6_2!0=30d`QO=Rpbyua_`b1o+XT|J3Q;mwkmopU}oTx#ne9KRqaE z9%=OsXnA^|kK zwxVV1BFNtZ08T3Do~s{JABddo20m~a%K#J|d8$oPm?S4gCL1_M1nV>;kwGqM;k6KKQma| z-R|RmWT>H^&)@r(i;Ppaul!o-p+1vh&{a;5G0O^Ln!@w%39)6#J}fdCJs;W+-0|*s z^`}&0MTtJ@JfcP=xx|5^wqLt=!@`W0{1>@|fhFw_jZPpZQ#?B(?e7ID;qG7dUj5<` z*XSS|Hc5A9A&l2WaX_$TxA!pLvh7pR87+I5BIY!dgpBaK2Otq3W8Hd)22sRocg9H+ zX@f!yGa=_h$SDd1BPHc(!ie`)ee}i=L^{ppmoue)M~X#{ui-9+JBA$*y=-~*f_%gQ zxLe*-!N?8yu_JOr&fMsQM3!7I`1|b0F??U7V4`+3w%(VgzT(B8Pwx+{L!+y2^qvXN zjF)9}m|OkFdLVNb{GRwENl*}<1b&H=Ht#;nQ9b6%1?Ws?)EeIH&AeKi1qIOraD*t# zC9kf&(A|fZ13z65b>OY^F6iq-c|;kq2q_5^Rf$=v3_7(wo_Z|eek~2!bAw=IIz7bdaYMG+*LAkyRN{apZe+ zK;W1MLLo$WOJ!sz#ZNYus$?6;=!YM;fuO@j{FDA$Gyc(8?W7j;IAL896Y%xOi}u}S z%e&KBWcjk zgyTrPe{8IZ)C)jqH8#QeXd3b`BVh>pWDKGt8IWD3ySsw09BQM_1bOr%+na{nKTcWc|bLSzIf$&Awd*(RCna(aPYoGi=Cl z)ZZuRG-p$_*y8;>DmjC(oRgEs8+!|lqQ5r8Vun}7B!AILs7^r=r5_Q{kT1VJ--c9rEhm#$lOFJj~{Y|YR7w1XoBU7UwTLte_^UgF)(cSdS0<@W!$ zZPhU7mA<`!Yh~pJ9ey~B49}8TYJM9t3Es-Tg=N9t`%^N(2ev*H9xoy<7{8Zfjya)O z+(EBGY-al&;2~Ul4A#gwGl91O3?tpb_6+iu7}71vf~> z0BPX}c|Ky$A&cu}-B)at#}Vytg26+M??cw`7yHEeCh!CP8$rHnd#C-XfD?|qFX=Lv zXOuj+P_4l;kQT914|PXVg*a31y8lwG`Wa}8xUTu(c}k=cPB*}g5jcY6jv=S(O&}UV zT0v%dCg!=FG^Qp=Y8B{Mt&<~C8y!?(Q~Qc`fJ03)m`OQZFGx9oxMP@&o7Pw#)NL9e znEfFi3U~Ow2s_8%%=%{CPmDVg+qRudY}>Z&31^brv2EM7ZQGjIcFw%}*{5oss&~Jq zYJFPY)~fDaef59!?^28j_?J>ttcQpL?j+T^(BB-j!7 zdSJ@BRox?TL;Y%2oy+HoXBNUS^VtEjxJP$CxXtvwY}HW9a2l+dIfPXwo<(P&MS)IB zL4?3&Cua3-gkE>w%vfdmishEDfPz{y%{_s9ddE@^`8*o%jvCx(SW0lix7OXAk|14{ ztE2RXokf$IDiM%$ysb=VD%Fi!B(GkUJutu9OKZLZA2;U|<8m4E@)NcN_7uEFF0sh69VclFr^PoHz}WnE(R3K&dh~4+C%_y%E^Kqnx!22Ls z&zwWb!_fA0_5L<<-(&i0=^CQm{E^qNK@^L45+mRZyxjGZwd@VCI6zBxM+`NLmQWN#^5h5Q^|IC*d)E=0ilpT+9jgo3E5W|vEPHCpWO9@V%$J2OFe8^g4`{HT(_&zegFN&=C%oAtcu-WiklS7BR4}N4(<-BCREqR! zC0xr&HN>iq{t8usQd}D|rCs`a6*}nh=-lGafWXv9ag)IYb&ZpyYmr`{2)@8GSG;qc zM4>PeF|ksHAFaCvq(sk)#d=ZbZoi~*7_0CS&P7Y=esibCY=mlKahEO){_!S?o)%uz z&qFg30)Nmr;mb~>8S&j%G851pL(8RCeym_JKR}pF9*$cfq31fc;O2`%8Yu*pDVZpE zDE23=mGLY@HVb0Mqluj64n8He@I1v*vT*~n$wX10aH5@%+PR2KSF#ZPKgAoIH~U&qq1$kT}9RA>dd)B0|Ziw`xGJBMzD* zfpkPU&agEO^oY9D0muw$ry$mMA;rB>YSPmwMSiX>CYT)u5u7mVAcF-aPYLfKHX3x4 zPrRcN@O%@!flmS_eD^!GBfZ(|Q6>=_u;eHiZ z7$$mJ?3IhTY7Kk&6wF9>U5S8GS+9bM6B>chlDr>y9FG_+_J=2_h-^!tdrlT_9Y&(q zB~2z^w3AtPboM>vjzs=%3ruwF%scp!Omc>FG zzjjrC{lh^uW>P~5Y++M2s9;8eO|)cGPmMz61cPBiA#*@)pmg2=HT^A_tZOl{30$M# ziIc!GSS>k%ZuH)RkED%qOeJ!sl!62EPV|jallUZfS#+7;Debe&?a$j$L}PwHB=alP`37fwFoRFUnQX06Dida5*ze z^{kP;#2H-<_7U^x#scjF5HMzGd|fudCrz6*sQgUL-slsFzB-APnY&M^USG|C>$!=N zg_3ju*_uKzTWnX1$YCVzlQgmu1!PN7Q8H#erp?0gylSt+Ndsk`n4Am%Ng`cLZbLtp z6qJl2_pH-T!>l==Q$5;Z7{cN@f?=i;AM%6HN{LRONGEt(!sblA4(t(CG8Q%LvN@t{ zveB}=$wgcNan&YSHw$_R&%0E_eF;jA?iw3_cG%;WPA{e89B7R%0Bd5bYRTzYMtXrH z6pIZ~g!z(`+hRhZn%UkzlW%ePqk)-MJ{xg_8a_Vyi~4{iFgyM3#xWerKY~Tz@C-(o zzONcAP5!Y3Szf@w1QZ*__CV_6nvV$~b`%r!GM(5s9}HGx?=~bx3fZJ*a_A+20+F_}=#gz6y;fav2N1H7ve7;bycZ{K`9|I-TN|H>eccXjy-A^2xq z{=au~H2@wurm4PP6Qt(MT(7?{uO6FrER6q=cj9EGyn;5i`<4&e>FGVYhS_euquqDO;txa-P5;B=R*@S=HEQG z30z+fZ{1Jr9bZpJ8#MZy-wpEDu0%m}us6726$>0*c6VY8j5(KDe&9-C?!U!{)|%we zFxi2NqlGmA^LGc}fn%pp_iYns+SZ=oyMncl)ltaDur$W|{gDB=vyr(-#sReUfMBEi zRV7~ITf7iVScqV)FeU;3Yr-jIfV`os9>~S4f(;`s-WGon^l+XdL}jJVQ&m=!9k3D4 zd9_ycUZ)^mXKE(GB4pnYOS@v9S#g6c2KTnkuQiIAR#5}Bn=1o4(j^)y|Axr8Z3b#%x*Jf>@ zE@G}zgBo9Ze7-&h9ulQ@C`%w6Y7rKYj|6Gi)GF?6T?uEI3l353bJI1>B+1f4Rk! z78xFh(#b(t;+uLpGfSmB2)4WXcx=Ea0k~AxV5c+JXGU(NM~`Ag!K3l2MVPGnfW*@^ z7-%;d4HOdf_4Aw!2g8OxJr?F)oM;ZAw8KZB2oWmhTR?^m8P>0^@eUepNA3;WrQGYq zL6s^pOr7$I*WjZ}y2{?X#ScWiZ$pE(v*Qia#SXe1a&dQ92}cTK!(DPDAx_|Po~;6p z#*`q3tNU%&x5|Pq9pyTVx}IPJM9jLj<0jb^=s_guJU_AI$Z^&pdOWm=ZgJrf8%A{YsWqH_gN_^+Dm>RU zF98lVo4fLCp&%n~G&xH;3^}0{t48hCt~7vGx^GWvBONr@gJ-rk_Pl-S5goxGBNo~=-a;j*$5wQ-UA+In+})FbKpLTFEjRU? zbFdUV!dwkfu77L~?ta1F`xU&sX#$S$LW+0-s=CHqmN;pONno(R~n| zHVkH@h#%mD`t9MYy5&GmHTp>9$Xyk?`mQ{o#Tsmr z34(KVqNu=q15K;>0N8=tfd?KXZN_tiIik*Ap$1dt(q1J7dcD2fPld8=cP2I0^8Qh}@P0 z{3_gUezsT2hB?BX=Z(l&ZGtdSXF$$-zH)ij>riAy$3kkxXL-yrb(cYInu&e+x^(fQ3}Xdc{wr-7`Ft3RaVuZw5BHO zz>#Fe)96Q;in?i7VP~+1j2O%Ok=AZa^05S)yfPZ;O#>O&8_QTZ)S_uy8S9x!Qnoii zDYY(LY!|ARBV=`ZBIKUv5>gcQTUclR^5QAez2z`o(hdcfs?M2cgZC;Z4y z5#lU3gs=iEcP5tU*|^&cVZ&HH{N$JLxUD^PjD!up5*0)Orj;$*KtH=(2vb8 z^sVy~9`mdVA-ypGwyHFocubZ$IyTHqBm#~j6AO%z#%_6%Z&NElUz`J8{uqzHyRGS~ z-5n+~`1tzVwsE}CvOnvJL>+jgaCIeg7QEB_-CO-!qoVY~vh$l@ftmbbJd`!c?N&*) z19sB`$AU#dw1&3F6$iG@sERU0FB^GE0ub(TYG8G(xXjfwh!o&zj2e9{TAL5_Vo1ss!b7k=P8W)|7lu_|$dWUZhFvdmctH7F zL)DtfNo0?`(>;9QllqozkKciBeGSRF7m4M`%H_$LO0QI=<>r5yP>Q`_SUwAFnpQCL z1^t-eQiGNn09M4asbw%uqx{*C{&Z-EKi1x=w)khY*az4~jg_~>Zl3gpGwo>6?Ey3RB6?(vIMcFPTyzVOym1F4VV&!rD< zQD%m<$e(U)XSOnb+?k;-d%kS}880V#TvmErG;Ez1+4^;TVa^nDdh>6PPH%HEzF1jx zklokv?aWos%zqwBHLkMvu;8NTVO9CWO$>B&Eb5=N%NAa%#i78Q;`!h4RV0-7f?sh* z4XT}OqNJENZh7Gr7BkMNQ_vJ&|CaMQ0hcnh$Te-~{-JOrze_TIyquTPeYJaYWqRgg zGJ|07kJ7g~_pKMmBF>9Y}W*pDTtL)Vj0g~0bPd+0qF5tABQNkuv z0Zk;-8|;R%M~feFyz=uqshnKCjwm-6rs6XuTPx0@_Zr7OzD}rDZTj>ZqW>D!p?UIuEH)@dukTK}^r#gFY07whP~btsb#d*xgiIvuSOdb+v-@2?&hR;lDK z>nh>RP3EK8!>s*`ip9B2rD^ir-m_BSpShDvNrF{Ir=Zz+MHDF$*+te@6#0ITIF86a zZZyyT#J?jFJobA)bL=B^fW^1OC!gzj&xhw${TAzID=#162Kp~Ctui$x8jso7_SY8) zMr)oA%x~E{C8yUNYI@1e(+9p0vs+nohBTgnmeCvi9t+FPF1>Kev{g4pZ&6#f8a7hjieXn16NlVe$%Hei}E!s-fH-jyyf z?ncsQC$ejpO6|JFHIRj`A#W7EV6D%S)U9;uwe4G-f@=v>LY4Bc;4Cghmu(!?*Pgf} z`yIpkN6vjVO_%=~&l;>d{WL`A^L74moxK&}^u*~YUCBd{M<=`QE1~_W*ZYLg<&y)* zf1tFX{Qd!ZRbI`UFpYG(tPoJllJkmJ;tN%_{rgnC{e^+{$w3C03pn`kBY0nKwXve?4OHs^;~To?-LqhXsdmYnzxt zh#UN6z(1E&Gwe0$8?5$n%HYm&Stt8a@dZt%_^q$LYG?d|S{s9x1{zE2+2qF3Da-uN zF10I@^SIX&6ZVf&>cx8GWzbh#qW2J_M`N+8pGhgxckr)N` zoY$TcfwVaZXA^-9JF%$@M!d!|=|IOW9S8Cu9MgzxtFt0BKRrK4gn|TmFsjC$x1~K} z6f;$pQ>oI3veLeY0DYztUs-|=$nhIupZoO)&x$oA7F~wQaV5jhe4&i+K|0mX1g(Ly zya01qKFcK7c&f$~{z7`ck%Xh5p~|I`aS!_IA5kB_E4Smn>GgrW$7+3qwmK3ChnK<8 z@i<%{VcjvS+?2qV8R?qh$lN(aKc*BeGsf^h+yM*FzH0q`-<)7|BFmL1GOU<_>-9@Zw_6qt5LXtiQtfbJTz9q2A*78Xz?08?4&r{6MCH@Cm&=|ODvMd7ImbWLs@{vI#+A?u5Xo=ELKU#C;>4@*G> zo>#%D=ui}J=rzjj{q7||4#SbfIS$X!wj9ibZEHkgG7aG|JRx_S13akDo{WQgn&g1y z@(4PMPYlxT7Q(kDvP^G3de&LVdFAk2I4i(@4b_?xV^PoAk2CH)SnmH4Ab_5K;|?)G z8nB%ukT@EiF7NK%`g)NYIX`2Oq-0ekYXJOjNVm$;&d7p@pX9V~ zf{cNr{c_VTew!aYy!HBB-EYta`0m1(zoLa<`=h`01B=J1h;h=W_-9>+nrUUbUv=^UaJ!^(jv4U#5kEd+`93h;%j}xKhYuKjRbhT_ookrnO}2nG zcjSuzv`8Q)c>2`aYBpIkiez5?Q4q2hW7i~;8vo-&)ZL~tnjE&ixVQG`S*78b!N4*Q zb$|#pX<<@&TV~mSJLpgrwpFw%QErwwp&-a2QroGF;#T;hQKMG{t+Q+;&5O@PN=`W+ zMxXwDxTi#Op>8rQCn|~&_vwO(^p!8vgue_dt(S4>=`ti#^e0^YM;TKMcA{OrasKS&_I%r$_HjcFToojPf(7EiBO_i|fe7b7ch7+xp zoY73LvLHd6^t;TfRNUVUGWZTZTN>oz#mUDfOfC?Z5cR(N^a8LGGfd)9_SpQj>NCEDtB8A}e8b7xGAWA23~SNfE>*MXWUpk>PO7JoRh8nfU5N|Y>$DN1`25p#HzfR*w~k>RC701==fmA9w)dg;NU_X_i` z()(onB!~Jp&E)?h&+Okh*D48${SR>F|KnU6sjMxJB8bUbPe*I3E=vD*H?_oq%A#{y z09By@9Hdn6_kf8dl!j&dq?`5qEELLDD8s7(ag0TtecE&W0!zJgr3eba*o1GgbJtbI z?pyRBqzrw;j8B>C#8Xm1H~Z4EMPTuAc~D++{Y$EV+Zm za^m@zm0O!0^<O8=nr_C%;Xnb`Yt}GtUI?QNBJPVCH3Ye(qZgiAnu@I@Kkn>X4Fz7mZ5TnSMPvJ zv7+15>8hFGx=QDASO8R(0GunO2GN6VMs_-}L|(^)%G5uy$O>H!<^bn8`)jR~s>)Bu z-;N+W=f2b={^al5#Uh`lI#D~d>FFhH343XV&N2N#KcDNk;5z*QC-!&dQJ3NIfSiwG)L-?ggzHMM0 zd^G0IcKy2(miogRvo<2wcFZ%lvmv0CA@%q7foBGQ+E{M-%()VAp;EgOxY=K@7|Gl)|m+qw?*Exd5iL_7jKZh+e5Gs zy_+J2C&MO0B7$PW&}#=2>wq&)m8;j&F+!ei2HdK!Kq zo;dD(7f}7l1|sfjj|DIj(7oW~_sg65|H{d?N15y&e{*v4KjtLuzxn+A&B^~cp8tQ7 zQfX5TTM_XS5`9^>MC%J}wrsH?Wkj?R!$^gdjEE?%Bo{*uFDV}%tldP@M!!6CtpLO4 z7oW<021G2TYzLS5;lvY5ef`(x*9*V^=ZxJbB%M)7!XSk4CyAY?+)Jwzg^g=pJ!4Fs zB<7lO7VHy@qj|oSA!ZWH4GeVa#+$kGU){aC0#9n&6Gru9=s2jKxV6jpApZ&t;!6?1-oKp@#DDCJ2>wlI zC<|&RnHrk>Uvu$7l~tv`?J;j=AY9?Mf=EA!BL* zIm)2?wf!{&W$EoAHUHS{BO(bAkzi)dRNb}J6%v8mh+nsmDz3utTKFoWk3())Egmy~;`tTeepA&4r)l zsXqu&ps`SND-!5GOs=;J=TF2Zl0D5z?DSb0$Y`rNw+~aj({(CM3+PZfv1UB) zAQloKysa-=L&m@fP?IJii=X#m5iI+m*D#z2T znTo++F)K3;L9AOR3i+jV;E*`NCR7za@?GjPZO$%kq!Kok#^Z&b*qAJKo>e+|lgRD& z>^zR^N~;=_`)IONm3m`K*2aO9ii7TG^?{K_Ba?Oaf00{Rv;>kb|B_n;q5hM|Wc&B2 zqvB*}=WJ&0WNYd~s%+}w>hM2q{G&I0{w`YeDZl~c-z^)}5H~WpkBuNVGei)VKU@KIQC$gF-#1tPn}n8i)k< z8tEX*D3uTwj3}F%)(n|@446Y%Pz1{tgS%WF3gtgQJ|G%(!=*LL%jJEJqfbxyScFG- zO=lm;jwVv;yFV`Muj-Eurn`MVzW1nhAnpEE|0VBF020(+e#^oY8~gBQAYf2cwH6aJ zAgxN1fXO4jlZ99d5tUHN0yyBnZB9!uC-qoXm!~Ib(JEr)VYe3J>P%&Bq8cEmrADWf z&c+(f?~9Rn0KbHCwkp%NwwaQmR{s)VQ)=c^2ggXK?PRo42WMNW@X<7;D=*au`w|B< zv8MwB%P92_1+g?9r!)w?;g^{a8N+Z+I8-4Yy2&-GY+}bhxQMX@%{yfgiZ<+0V%%ba zh~otJ6~g6aUhz%MT$~@Ww%j@07m&P3R{c!bT`$63^1J}QyQ0P z=P{R9xWBT}0_8o$Bo%cbA>N4ybazbJ?dz(*T61-+G}&DI3+Q7>^*p<+2$H@9&)A3I zoW2&eJ>X9I(q`uzq%2+;uhB~1^V@I2am;Gx3;I0n60sHKM+T*rY6%>NtM#)RLu6GQ zhZ*MM{hoJ`x$9dc)e`iC1+OSfeWqZ3=0G3WjYeQ3(Bldt38w_SQs#&39!WIL$=mYX9hNS>Q9xK>8ULssg8~W*;sOA_G0Mn&^bcKBVRg(lX#({oZdBN#2(rc zNIVBN8+~CfM=qZT!%)f0tA{>CZ02AES(%e1(qM*Z70aJnk{dzRgC3Gj82{e&jt9rU zQKyN;T$YtyLQ4$m{)u(TE`z+|MlZ{58=qFS#bAP=YOJLleVI3{ zHA^`r5x;R0u@s(X{(U(I*t^ouC<{_q&T_~$wN31w8-c4 z%(U+U9*!(gwDiLeyCNtjJ1YtyhBV%oOgy0Cp5Kc%@sEaBvK4~K$?U=45+p79+`9;%itwFwXAvr`+3Y1qYyxQ*>Q7C6wQah{2 zOS!}jBM^u6S{2zX^z?Hh?hr;Iubooo;$&EWm5`F26IVyOwpnQrSFl=*4oKxf5ztZ5 zeU_ehQqi87I3#YYfbnXO+hZwPP!iwSK!$BKQL3b2aa9+c+L^tjwy8z0>LtI zo;h)k*Lp-a1qL1X&$o@|1U-73g}iz>NbqfpVsZO zR0T)RwB1C|9y5?Eeqt|;N^`llRkv&~w7V|sC7h}hN^K{oC;^y!6xAf@p37E*rq;c_ zIRdgjqb~JlZkFsgaitqlw@9ZsEFR|`Z^HHt>@jr%w6D1l-*NucFb4e?q7MA4Blr>j zQ&lJW_f=ip$hZqiV&SDO*g(E;Yxn*rdmUU_uJ&l}UuvXlhZdsPVAE8Odox1Y{+< z{~KyV!k^QD%exRLF!JOTE$Sm<#} z6Nj;Z0w9$M7IS;Yur&RXR^f1@?yktdLDap8OEOUw!@_*ZkR^&a?Zggk|3s}3=G=y( zh(zA9#N*pL;$|WU>Y4obVs~qT{94#<9KaRD8Sb%$u$^8Q>xDF*E8^vgc)-BsO}3X& zF)_=n=-Fy+gnJ6+dm^Au52`E zINwfyGBgW$^x9ws?=5mWbh`LDPJoL{Dc55_8?K@c@k|k?7|NIudE>$=Q+($b{-VQm zK#$aifmLwX;#6J6FF4Q2m&0Lzw^WN|%f7b^wkYY+BkC-8&Kl39zmH9)Sgb=)5RI24 z{LA7OH(~kSPvRA~pO~=3&f$i38t?%>J%A2bkSt)>J_9URY@6RIS&KajqoI7{jqYU( z@f~SnT(h^nYt;`H`qb>*@=ffG@ri|JGuZ%@Ww@L zj)b=i_b%^LQn16Li>upV@2e;Jql_ooX|5xHyx(I!6v%{w=7~e^Mewjc2A`mvS3_$> zX|1i8v9yJ!W=m&<@6<_o-mV8F^~gq90N0HN>&6Tg0!$tRTlnjRJ?v0`DNV8}?Hc9= zGOhJ@v9xh?4jVYOAsVIg@+)YzAdWzsaxMQ^0}`%1a`b`}Gi){(Xs-9lAxpT};87{@9_VsiGOn+zajXd|6OU6oIC1ZI%f@+z9jn zQGeT94e^@T<#D+-F<#RUR`qAcK!dokmdeUTTJ#OIC1k4$Xi;NHrKJYfh9YCQxdgi` zpyLRJhyRU-4CBw)qwLBVXK}5RU!fhc!bd^h%et!_VChgx?ScpQdM&)|yo}9pMo*Z1ZvAKz+Nmzr?RsuFZTqGM1By4RK#RJG zJh!7|YxsQ%QKPr0h*U&Nn~~G(OPK{o1EwK8Qrj;|Ql2mvro zPLOt2;w(I*8S%@)g8U;`Bj>{Dya!VP1y~&xfz?_qsL8Qzb^LMaqlii-aeh9LmSY}C z!u`=SFuqh0;MzZgsh1bgt9l#ZGJ_nPT??piBT^Qc#R}Wx>R%uH-&KAYQ6dVLEaTjK z=kKyK3`WLIl+u&Uu1%A$=0q-o6ZfCJ7<<)*-TWfsWFvbqMH3z}O?)r|H1DVtLC5Pv zI4o@63di8<7*=3Wvp`g>v*xOu4t5*w!f%X@L^gA9GzWRI9W!v|JIUtSIqtTjU-ms& zyojtxD}jE*yd~`L(gNa)8XMUbaBVVCY}r%kVcfpbhj1-k#-<#sl|$@Y80J7*qTyS~ zwD<(|{VaBU&zB}8yfaA}f0} zWXNE5Kmhzh0pLVpf{Ai0V5p??Oz}Z?{b7dDGug08MhlxBDkw6HVCp-L0Qr)$m;Tz* zrl@B(eqV0JAe2Wq+eJ<&y&E)|nqy!vxCIrFHeL@t4YmpEkR)@4y-p zoo07Y2a~dzQ(bn2H|kHbUAm4*fmP&1VnS6$7R32lf~)5n1i;l^wm%G*GCU~YC`bzMPpgB}y51B(W#1__l;>^Z&vntg%_YspL zY#BNGxwPDKi6tMQluELmbkm^1-;!UCCaIKrpw1-4LG5udsl2^mT} zqU`n5WiT7#f3xU>&jS$(%p>_kKa7@Y2`(GSULSF7sl7E}==eDK3d|!sRXD2AByBHUTw9Dd zPNvx;Xy_LOI^U0i)2z}{Gi#Qk@Sj$HhjQ}s2c%R_(m=9$R`);O>FpQD-F)H|b=yr| zPV1@F8LF$y3CC@u<&YjR?3T#Etmd{vYQ&yom$g+jnbmn0V26>hHM%-U3IKPssSE&% z$gSJ>4D{k0wtJq8F>$*DU{VHoI4ew3X|Hmac0SHoihkgQ=uc{*phGh3HfcIdGa+}$ zO#P(dbK&F~N&D!9($qpdHD=pU>Phwhn7TCB5v!yJA92t=b}}D1YjNosB2)y9qERi) zqvU$psp@8aa@?>@6XoJZUv|!Sdb+%V-Z-(`Sh|2G>C^MOa-~0c{jognWs?e5QUKEh zR^VECes5ILz#lEzsVamKG5^81q(_OXLTx%Z$E?M~mvSqDXS0F&YT+)r(wUdlvB+|`Q z^zi_fvc^<-`K^fT#{szfYtTL+ULU<0x{WqnjJX4|)n?wM!{c>Mn$%B! zaIDaH(aK%k1IiCWgM&QZ@}Wda)0MS#yG`U&*`({s9wlh;BL*(&%uN1dyq>1AOqFTX zdP%8Vsq?3Hmg^qa8!GycJ@djWH?VpE*=lIJbsuA=DO3GLoPn|x( z@(H-saRMr70%mKv*5k80q*J;Q-BS<@ilnQsu0`3x2YY+Ctm*0S{b|H}v zXZD9bx61kOZ8lVJ&TB+5x5cR+es?%*Tm983)lB@^f=ON-W6%BS{;VbQ1&+Ct&rLmH0l>IJcyp5C)Lr>0Tg-ZdYe(v#FE^|lr za^CSy$51N2%ZxoM;cXcn>?C>Wp^o%!!+`8hzL|U?lEQc#3c5IXYXFZ2!IN9%42L#C z{88Qmb+}v7u()F(!9N(~O|O`xZ8~_d3v%%ZB%^XZWHN^fLF`g%n+^5`axNS$cGqW5 zZvp|zy~T6E%9+YA=_F#~T^?Q=8-wc^5?d#)nw;qA-siQ$uvI)8;wN8E-9y(?>rso@ zmaonkpEAqYSg+1JqSf|S5$r*SK(;&<+&{f73Vvf%V2HoEY(R^?N4b#qYj9*=2QQP5UVbEg#t$e)>0kMd zy1Yi5aHIQtkG>gg_{4eOW9C#!WK71sVp4ZN^>dAnCmk*USWOvS_XLw{XQtj0o+#=6 zj4S9ZrcFIEjVpNQ6n%>&Cn#nn--_ZZkHKSyHkwH~cS;%?L;*cEt;*99lv#%Aw=02B zSBRsS&PekA6B@bp2iu3WkDymo7CrrdQH?9 zvLYuT&81aZ7Rwp`yghtWXN9HW6q_{w^lkHRHR}OJRx+k37fkc9>H|%sPc~#rPxxhN zJo;!w3@LLdM~$(<;j+s{ZI@nF1Q)~Kwb5M)kd`B)4U zqst6RhB4`lN+}$`lVF@{c^Ts-1B38;it>rLs@B}5h%ZI;iu-(w!q{qAFFjoOW-zc^ z+OsC)3DMaf+~!3*9>;?3737DPHhmeC$juTOR-O*Qf7i^EXo6-re*Mb!;l#^jgGTDTSnlyQB1U9t(o zxL#Ig9ZoTZY4&P>E7<0RRNI;=>)>L-ep)%@g7?6^5eUfTs(9?GxLA* z1WciInyF`%$%0h2Xhb$*C|1{Mad1P0Is6dY`_V9mC;2PpC?qBsF_)m7Ja`jyiY#Wz zuo+{W2eV}9YEI4_5A+0bUO!-xJ#I;vm)baKEGs9wvm+3mBc_)(aNG+odD&!koN#>B zFsZ|Eg@*bC86)P5YtGxveG5Os2W9T1#Q=)u>5u1K+sz-R!{j&}eFS={v963I8Xs`= zbAu#WA58TF&vr*ugsv^1Eb4JkI%AL-dwi>&+{QwHy}Kcd{P~99VhRusQ?D=o2k&M} zC%_l)F{d0b(dJ&g73`Jzvpf4E!0vqS0If(3oVDc-dp$fr^rd0b;o?n4dRd9-0w7tS}hpKDQ4?J zWnc6)OPnm?J;PFUS}DK!AQwim7djD89lRpj#hm5itmHkn!Sm@Sd<35-!~NX6fvnUm z(B3-k&2DojfOk)N8@>=A5B*|WuGXt5qg-c*Jl*u3)sJr-aD+eXf?OI(4SxH?#1$m>bd5L{{V18F))jEil}zUSbw4a zxcRXmsjyE~!W{41{`oTam=TFe z9yxnyxOw}u`u?Kc3cvlMH$5Br%^T%W&5?=ZDuBLYXi(nG;N9Yi(%bDr)&~%c5&h@} zXuB4W?AiehpH8@TNWcTz+uK z`$!DGhFrfh$-cn|zJ8k;DsDl{u07x!$-y|3!{}nrJ4YkH&mGK)`<4~Y+R<}E6DR0i zcg>!CHR900u=*?@_V?HL7SjU91{TZW^qP$prC%F%90Ge3%Pz_T&x>K5@B^__MiUab z;AT%8Ix3M5J2v>Jm9dv%?B)ON3@csP#v9NquJxIU7QiP6S4)A+4JXO}P+h^c0 zv)AMem~mQxyT{v;Bq zBt;lv`GK>z)00c%!> zM>1`=t?y@L6#aZ4;p(M_?3$D$Q!>a&y2U%vlxJK(jM=xX7_8xT9h~b@a-%h@Tt<<# zry5px2aSjmVs9rKNhXd+Ho_$-l#68DqPJxGK;jC$~DEVtJlwpO}^Y9=0D!9@XjQokTg{wFwjQ z^eD(8lT!sWmR^WaiuCodH;a|vH zqj^0IFU0>L?45!{3EDQncAvIw+qP}nwyo3d)3$Bfwr$(CvHkrsv4fqM&8W!8i>kb; zta{^pWHyGqJhEgSM`@kd7B<0MP`1{&>Wyt+I2IA*3Q~sV%E@`*?7VD|t4UNk@GC%? zbS?o#Kce9H%K$O>qzZd~uVr6RHTmG4&K{AqC|I;#2BhAiyiyLeIQiIa_U`D-vAtoB zpyud3Ptz16Pb!mR)>SsL5#cr#&&A-Dvxrp9%~PMx&2Pq+H9J0%zS&F5(I6Ip9qPQ9 zi5}|GNx{IoW$uA3W)nW*8xnu4ZXq|xtbLhK9eDCAB7;+*H!3JPWl<@DW)Qhp&sQe& zkJ@yQy05GrIl>s@yeKXkvIZh!0WQ*)C#2Q33VHIknKz0t|8 zH6q_|>7Gw5-r;{=)gPqahI%iI9~;ZgoO?rZ_zC;IDxv2(TaFrr$B;Orv5)0JPC83B zzpeq62T6q1NgEpP&hoocB~qX zYS+#-a9L>J=_j5+Ef3Pua4}z5kx$(3GbC}9LvK+}PEOocYO;0quahsVOKvgs^xL@P zHK2VtatL+#Tf1Y!+rv=b8L5UMe%;9B_|-DJ+WbOn9t?t-Vy?#Rlb!N3jxpaAPJ)Op z;DDw23@m-NTN-zkFwboNRrna2<++d)ZQV!Vu=C{Y#obrM&+FV@*|t@QT_0ZPynD7h zc-D0L?s#;`>G_>@UN5iUel+!DAp$s306AiWj2%fA>lL(U%Pw{UiA^L;im1tBsNMCe zJus@}X;rFQCnNWTN^l=I0+dTnVbAKa3LyjLur8@dAO%3nE#KwE#)Xqa5KIF zR9JGpy1sp}w&{2-H!Vq`e!BC#u*ahu5Z&%*U&4VqYgtkA()+B;^W&vm&&}nS z@6X#C)L)Fs@z#*PLAe27%#1t*yBw8YX7=Q*Q^sdA`fnKU>(_pW?+)NUL zD1b(4QiP1Iy30&|#w^&p^U(9lNUvYS^*Yz6+U^J!l`hXbjehF($PXIE>E7hoh8wvn-#3Re)%)^SvY7_fa5<>h%cK6a%>@rDH!A_Y=GA!GG>?&eM+K9 zJ1dlnrB@Kd`MYCw4StjqGcS?M#God{!is=%UX3_fUw8Z&hi7U!iS(+jB&{sq?CfY^=<=U4XJ_JQWMOCf-;Q0Dn$0f_3EtOs)tG>~ z1~R-fOk@hGwkfxHH~_h>P*fQ)Fl5Zjh@uG#Qkt>~#5?go{c>>{Ea@RhszJYI9LdqD>XE z)-1IOT`IIqb21$!T0_A}pm*U1 za&5~+IVxz#J!mwPm9OH9F~f^iVOb|YEUpY7#OxFI%q1EQrjnuZq)CQHh@qVxWzoLE zpY^-+O*mG)5JlP5XHZkAj>5@EG6lm};|q@r%Q1DQ4B4|vcd8C2t8A!5<6S5jY-tGz z!WBY%K-7Ew8ZbUi=k7VfAH<4u((N(x=9V&x?T#sZ8NPBXGNTxF9IBE&Tz|8&ksHS6 z)i_8C$OLbN3k zdQP%-9i~SQaVz_4AJWn{L*nhvRakt_D`qQqqsl%dKmqiSrxR{vCzCD&(GX1iwwN?4 zW0RMuH&=N~yE8{}A7}l z;wi9MJ(+_(g=cAUsTPNd{&jEVM7EIoK*aS4F!n71nop-Qe(Go!6@Xkm>=Yn{G8sRa z;FOCLuyY&XU=BoPlbK3qNmP`e`uCbG;5z~^m(3z8u>qASd#2hhpir&wa(hS2?mCQ>57B#Z0geKzl1|p(W#-*CymUlp5?AN zBKc%2g4PG7npjJAu5l!8_C!KFDUSPKKIBMY3dpB5O`f-L{X3Oz^-tuIqAnM#FiwK{!dRc(Xg^K%MMO zNb?Q=={4lqc1Q8cSFG*x4+VGe)=!+}Ia%l~w*qGXt~X3Xc^6zL#0cpo1f)n>EeKh& z$~%W(GtLKx^=w8=Em1XC%`5`Qw!ZdYn;+HBo#t7RuRbAdj{sMf>xb7U6+A7`kIx|v z+?UXOtQ!uV2S>CRpzj@LC>|~BC-{Fp{5S4~qdC9a4c1=)=>OoI7HcVL|B{ma-+}bI zvU4<}Gd8ke{w=DQ=xj`kEez;@|BKrDpSyk;ApbS~#}-BZ+ZO*HN2C9?g|LN@osF=C zUOnWlckpp$OTgvMp*fF1l#8y=srD#&M3h7Fmg^hMN6(yMAh- z){!7J`Sgve>HhFJ`JDOT?tbuLCEM}120^GgCK^)i9dw{;E1MM(!SpCiEh9k1v%rCj zse!#=Q*DaI5<=)|qC$+0aueD23E?#!ObcKBb%ZkJT5$AxVR;AaVnMXp!p2})PTLuN zJQcSh$A}RYTV{cEACoG=ofr1SP#U^SwE3uJ=$9Z(>2c^4f=Wf5nd3=|jBElc7^Cqt z^o!x$D{`cy0aVWsRZ*T&Mqg%#v9NHfHn}h!6O2Ng!;ro<$TgwW3>6%=@E}Kc~nEWq} zcKN8`gOj0j>7>~YCsKC@jk0P8e zJ<STttS zno^=v>cFSd*EVkDcpY)i>gCUY3Ft9r!Y_!dh(>XiL4lDxA)rhNz}c9Vk0mbE#I%lH zRlLZ@mW@A8H_L?f4+rT}6i>tj@WlPH7L{TWg#rfmLoYre?WuW{@ffSKnDY$=4^ht% z*zAHadz_Y^=239Z7s!Rbq+QY|5a&aqrt8%EW2G7WXfvbGpG0@eKvig9!g3kWP+}*f z0vi{EI+)jG)QZS#FioUMh(zawhn%DNPXDqvi7zVuEgfflJB1JaV1`_PPgp@sf$!`a z)=8Tv%7?LH7W~*NHnwgUe>?IGO^Z4U-o+%PaT%3Dz+5oT%r7SC^4ts~j4l6yt(Btp z5G=5QAgQM|kUn+5nZDSpIpA{hq>xC!<;-X4>Hj{&(A}h4%2ML z>75IgWbE|^*FikjzuSfI6E=!h6fg8Ph@=yAZkOFljed#KDMenkOR7LlJbwu&$DPcW zn9FERm^e;Y5qq24)D#V3+l!@Lt{2t%Cbe{0pF`H`Ku7aA%=g3+^Tn>j0LmI zjAkRd{755NPWDS*@d-00E%`J&vaErkG#$N%C)aymM)Pw=X}~#&TzB3aUK#hz>(Da8nIPNI<`$ zxtB9zhOa*+42@-UtrWye6Guxs=8r_26sBKUuZJwfD$`u*+oP{uc}FGEUJt^1H`cYv zZ+@{br!KDmA_}f4=d27Lcr5Q^Caz}Uq+b!DJ-L2E(dnsIFtpRnScli>ms$3?{@DwkEYxHnAWeQ7ssf8kCIBXMVWu!9ddz+p)ddd0nn2%= zw`m`MYWs_N2y5PB_AJ=yg*E4F5BZ()v}qn->i!8w3}K+mb4lYoy~V&>8F#1XFJ(&( z69=X_aKWTYc9N{SH0dj3pw&#V^hR9~qMBwt%PK8eanzkIxvEFO=P#m4<3BAV~%$QXU{ zoLRE{)TT4n4GTFxeH{gy+swoYvIf;oq+oP$_{vMPZD;xHGSdIP`WH85)Xi!(YZDKl zhYR$5lM1->VciUy+Mu%f%$5B|Ki^B+;MN2&f*6YA>6ZMm0p7h*6rTEH!PDb0e|aKO z$#Tm2gWast+SS_&zDkp&`(@tn(C2%fYw-CcBC& z7N?LoW(~b6qEN^Tedf5u0s|vcRlV+5Zk%egX?)3*wcP)TM|p( zXxRJ&C_{n zi?kk3XH(=WVgY1)M1s` zqT>}X(GuxzXskLKD)BGze_kM$Z%bscD#Ol60a5~|={08oWjJtb|J!as^dygGQ&eGr zwH#Dio-%w2DXH%q|DN;&SczSL*d0p;WK=tGy!Ur35L0X7LjT8;n~rd$1OE6vc0&jO z?&BY;r@52_q)w7ILrWmPgAkRdurPsismJ)UKpf^~9=!Q6h?E_Pp5O^5H7}jd9qq^v z7B*T-3ElQVZR*kUW_b2P)zDD?C$f!POg25CA-PBh3J(P_y_@`EKt0&xc%@?9KuciB z>9{jL5kg*#U3R{*tGOqhMy9lwIWwCkV8Tn9l(I7JpYM*H$9WjRuZXqJ4 zaFH`kmc)t@k4{Q_4~*+3>n-Uvw8}*i9i-&0L^m@O6rQu;9vB(wq3VXhV5qjz;~v?9 z@a8^#|CH9Li zQwxb_0ZO|`DTx~{LCgn)V@Gyl8uQ&&T0qTYxXvC_G{qMF1>U&f)t2n?_JO&L9IDj~ zujI>N?X!UThq$fPQSvsz)|c!l?^&3w6{_>giRcUatPgDrT{Fk~zQ0(*>;7-Qy042| zDpMhuvgCBn*;y}yLT`*(O5F!^$~v-wUTHfC1Z0t!Cmr`&PYOYPUw-91Q^aRoU~z6U z|8NB(nS9N72nc55$!svfsW7Rc$^tWyJ0i-RGuUtHSnmKn-~VLvC!pYS#x(8+=r9Mr zEifm?o9$)e{-)pB0xB6Kz4+9LXKE)oAJsfNpA4)ef4u3D`|i3X-Rxp54L|HOpnu0UE`eB5Ev#VLQ z#v*DwO${Z9k+onUqb#9jzv7CVlFd+dUqPN`ljMRHAUt?2}VWDKsnp(XZ!q$ZFT+Ao3#&bhFVVja?$XhW{W4H71W7( z2U$mxo?Oc_T8Y7xgP0Xx#=<(A!4=)z=kbU2l}u-fZo}-O<_5n@FUl>?4VOcru624b zpX>w@(u|h5psx(dqpD=L@`ii4h8m1GWrdeVPLbKV@l;$IB z_Kxho1LTUU%{zzGQ0a;*_Ggp9I~nWS+F%1T;)%+1{sbHA29wJ=W_0b}{4GH%o!I@$ zMH{=p0EL3d>;vo4O}jE~5YGtYE}8M`W7JieYu8!z$ap0|6z$CYYh_O}X4MS{?J9En zvJwn8HLg~!_}~D(r>`}I_XiBf?rhjnY-DNx&?66uR?@%#aaPE0#^3u!H_fIAeW8v@RI`rPQA%TXIpWRwV@%G z&GPVF*O8@fn^3a>FJw!wv2*~`zn3i<4x%WsG$f&nh{SCS20d4>FUYJf$f|5=6f4md z{Njf`QWO!QBTc+5!q1YL_a(I)iflap`xSV0w^>}`#s1QTHAqcCWg|`X22i7vs;WpPn-6MviN94`Tce!Opj}@L(9MD`5)CsnSW*fB z4i@~*0`+7tnZV+7V+IC3xAIe2vi6cg4lfhX$boYT@3_>9;RW*6oHO0O%qFFK{uL=d zJi5vVT7-X8T+IK?IT~ZDDkuG*`OQN-O^q#A&g2{+|QE0XGm~;&O31% zaJdSoX-M$gw%jnAPzS$98p;Yv&O4pba!c@F#tJHFWJ`tyvfV3rwn$#`&yrzpxj$M8 z5HkPl+uynAm6Ft1gN)g{zYU&@T>Xaa;(%^|?hQcKA%{offWgasaXWbrJl;G3y#siI z=_RKYR06)GwA}<%*MFM8&+QF$wUo6UsnM|Wjv`{@%ec{aBqKC+Lj*+1-E#KhiGn2L zmQd5cQ=jBIKM-fqo1kOE>;#QGnf4Efkax9u@2eWa`6MsiSlff_)QWBV_Z2x)_&`R_ zM19qD8b%kS=gw*~zF@gtxGFcO^hceLHCSk$&_6=;L7id!XVFYcV;+8a-pycQpiDRkr0Q2`IJ?y~4#XptK` z=8|>-xx3Lu-abyPyYc#70jl=E4W0*FgLMQaUctKO7|FJ*@tPM0UDS>9qp*eX)ocH8JSWj8;*?uUk%wZXH%8rHq^mVfR=KPHdlN;W%P@3O zsMCID-Dx(v|8!hG zOm{yr8#w9&OWMKDC!J>pQW#saYh(%~)1wXPth@xU)R5h@bl2_%^_pQ3pM|DOCqMk4asj~+oi0eVPNqH#L7VW3h%`@tD3e|Gh;~Pr2%UeWM zXyWx~*{qWzhX0$+Q}td=ajkd?7bK z%Qj4ss``Pl6V}26Oz27$XO%9R$ukHS9E@hqmVAL4s7~1L$K)7Odf$VKa-R zZOG^42$13stj37MF6j#ualmhJg#JvK;jKLF{rZQ?CCuWPx33x2peQE39&F{4GuO@j z)F(j42xJ=10PBXbn&e3`)rf8gqoFn0W4fnr4tkzXp^*`;taeOT(z_SFZDvDMt-ARh zN2$VkWE3Y#ApuK;8cVuZncooAmQ(^tU3!^hGvFWXLr3~7*|qWgC)j^lybLL~a?HOC zS~!sZ+pGBh)1UpHrFuo05Z=m5OME9�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%0A>B?buND9U3_^~7?;j;mYNYvIx4_Dp&z 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 literal 0 HcmV?d00001 diff --git a/server/lib/extensions/dimse/dcm4che-net-5.34.3.jar b/server/lib/extensions/dimse/dcm4che-net-5.34.3.jar new file mode 100644 index 0000000000000000000000000000000000000000..ca38f5775b0ad1a8b686cdfd90f45cf748e02dff GIT binary patch literal 205771 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⩔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