001/* ***** BEGIN LICENSE BLOCK ***** 002 * Version: MPL 1.1/GPL 2.0/LGPL 2.1 003 * 004 * The contents of this file are subject to the Mozilla Public License Version 005 * 1.1 (the "License"); you may not use this file except in compliance with 006 * the License. You may obtain a copy of the License at 007 * http://www.mozilla.org/MPL/ 008 * 009 * Software distributed under the License is distributed on an "AS IS" basis, 010 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License 011 * for the specific language governing rights and limitations under the 012 * License. 013 * 014 * The Original Code is part of dcm4che, an implementation of DICOM(TM) in 015 * Java(TM), hosted at https://github.com/gunterze/dcm4che. 016 * 017 * The Initial Developer of the Original Code is 018 * Agfa Healthcare. 019 * Portions created by the Initial Developer are Copyright (C) 2011 020 * the Initial Developer. All Rights Reserved. 021 * 022 * Contributor(s): 023 * See @authors listed below 024 * 025 * Alternatively, the contents of this file may be used under the terms of 026 * either the GNU General Public License Version 2 or later (the "GPL"), or 027 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), 028 * in which case the provisions of the GPL or the LGPL are applicable instead 029 * of those above. If you wish to allow use of your version of this file only 030 * under the terms of either the GPL or the LGPL, and not to allow others to 031 * use your version of this file under the terms of the MPL, indicate your 032 * decision by deleting the provisions above and replace them with the notice 033 * and other provisions required by the GPL or the LGPL. If you do not delete 034 * the provisions above, a recipient may use your version of this file under 035 * the terms of any one of the MPL, the GPL or the LGPL. 036 * 037 * ***** END LICENSE BLOCK ***** */ 038 039package org.dcm4che3.tool.mppsscu.test; 040 041import static org.junit.Assert.assertTrue; 042 043import java.io.File; 044import java.io.IOException; 045import java.security.GeneralSecurityException; 046import java.text.MessageFormat; 047import java.util.ArrayList; 048import java.util.Arrays; 049import java.util.concurrent.ExecutorService; 050import java.util.concurrent.Executors; 051import java.util.concurrent.ScheduledExecutorService; 052 053import org.dcm4che3.data.Attributes; 054import org.dcm4che3.data.Tag; 055import org.dcm4che3.data.UID; 056import org.dcm4che3.net.ApplicationEntity; 057import org.dcm4che3.net.Association; 058import org.dcm4che3.net.Connection; 059import org.dcm4che3.net.Device; 060import org.dcm4che3.net.DimseRSPHandler; 061import org.dcm4che3.net.IncompatibleConnectionException; 062import org.dcm4che3.net.Status; 063import org.dcm4che3.tool.common.test.TestResult; 064import org.dcm4che3.tool.common.test.TestTool; 065import org.dcm4che3.tool.mppsscu.MppsSCU; 066import org.dcm4che3.util.TagUtils; 067 068/** 069 * @author Umberto Cappellini <umberto.cappellini@agfa.com> 070 * @author Hesham Elbadawi <bsdreko@gmail.com> 071 */ 072public class MppsTool implements TestTool{ 073 074 private String host; 075 private int port; 076 private String aeTitle; 077 private Device device; 078 private Connection conn; 079 private String sourceAETitle; 080 private File baseDirectory; 081 082 private int nCreateSent; 083 private int nCreateWarnings; 084 private int nCreateFailures; 085 private int nSetSent; 086 private int nSetFailures; 087 private ArrayList<Attributes> nSetcmdRSP = new ArrayList<Attributes>(); 088 private ArrayList<Attributes> nCreatecmdRSP = new ArrayList<Attributes>(); 089 private TestResult result; 090 091 /** 092 * @param host 093 * @param port 094 * @param aeTitle 095 * @param baseDirectory 096 * @param conn 097 */ 098 public MppsTool(String host, int port, String aeTitle, File baseDirectory, Device device, String sourceAETitle, Connection conn) { 099 super(); 100 this.host = host; 101 this.port = port; 102 this.aeTitle = aeTitle; 103 this.baseDirectory = baseDirectory; 104 this.sourceAETitle = sourceAETitle; 105 this.device = device; 106 this.conn = conn; 107 } 108 109 public void mppsscu(String testDescription, String fileName) throws IOException, InterruptedException, 110 IncompatibleConnectionException, GeneralSecurityException { 111 112 long t1, t2, t3; 113 114 File file = new File(baseDirectory, fileName); 115 116 assertTrue( 117 "file or directory does not exists: " + file.getAbsolutePath(), 118 file.exists()); 119 120 device.setInstalled(true); 121 ApplicationEntity ae = new ApplicationEntity(sourceAETitle); 122 device.addApplicationEntity(ae); 123 ae.addConnection(conn); 124 125 final MppsSCU main = new MppsSCU(ae); 126 127 main.setRspHandlerFactory(new MppsSCU.RSPHandlerFactory() { 128 129 @Override 130 public DimseRSPHandler createDimseRSPHandlerForNCreate(final MppsSCU.MppsWithIUID mppsWithUID) { 131 return new DimseRSPHandler(0) { 132 @Override 133 public void onDimseRSP(Association as, Attributes cmd, 134 Attributes data) { 135 136 switch(cmd.getInt(Tag.Status, -1)) { 137 case Status.Success: 138 case Status.AttributeListError: 139 case Status.AttributeValueOutOfRange: 140 mppsWithUID.iuid = cmd.getString( 141 Tag.AffectedSOPInstanceUID, mppsWithUID.iuid); 142 main.addCreatedMpps(mppsWithUID); 143 } 144 145 super.onDimseRSP(as, cmd, data); 146 MppsTool.this.onNCreateRSP(cmd); 147 } 148 }; 149 } 150 151 @Override 152 public DimseRSPHandler createDimseRSPHandlerForNSet() { 153 154 return new DimseRSPHandler(0) { 155 156 @Override 157 public void onDimseRSP(Association as, Attributes cmd, Attributes data) { 158 159 super.onDimseRSP(as, cmd, data); 160 MppsTool.this.onNSetRSP(cmd); 161 } 162 }; 163 } 164 165 }); 166 167 // configure 168 main.getAAssociateRQ().setCalledAET(aeTitle); 169 main.getRemoteConnection().setHostname(host); 170 main.getRemoteConnection().setPort(port); 171 main.setTransferSyntaxes(new String[]{UID.ImplicitVRLittleEndian, UID.ExplicitVRLittleEndian, UID.ExplicitVRBigEndianRetired}); 172 //ensure secure connection 173 main.getRemoteConnection().setTlsCipherSuites(conn.getTlsCipherSuites()); 174 main.getRemoteConnection().setTlsProtocols(conn.tlsProtocols()); 175 main.setAttributes(new Attributes()); 176 177 // scan 178 t1 = System.currentTimeMillis(); 179 main.scanFiles(Arrays.asList(file.getAbsolutePath()), false); //do not printout 180 t2 = System.currentTimeMillis(); 181 182 // create executor 183 ExecutorService executorService = Executors.newSingleThreadExecutor(); 184 ScheduledExecutorService scheduledExecutorService = Executors 185 .newSingleThreadScheduledExecutor(); 186 device.setExecutor(executorService); 187 device.setScheduledExecutor(scheduledExecutorService); 188 189 // open and send 190 try { 191 main.open(); 192 193 t1 = System.currentTimeMillis(); 194 main.createMpps(); 195 t2 = System.currentTimeMillis(); 196 main.updateMpps(); 197 t3 = System.currentTimeMillis(); 198 } finally { 199 main.close(); 200 executorService.shutdown(); 201 scheduledExecutorService.shutdown(); 202 } 203 204 init(new MppsResult(testDescription, fileName, 205 nCreateSent, nCreateWarnings, nCreateFailures, 206 nSetSent, nSetFailures, (t2-t1), (t3-t2), nCreatecmdRSP, nSetcmdRSP)); 207 } 208 209 private void onNCreateRSP(Attributes cmd) { 210 nCreatecmdRSP.add(cmd); 211 int status = cmd.getInt(Tag.Status, -1); 212 switch (status) { 213 case Status.Success: 214 ++nCreateSent; 215 break; 216 case Status.CoercionOfDataElements: 217 case Status.AttributeListError: 218 case Status.AttributeValueOutOfRange: 219 ++nCreateSent; 220 ++nCreateWarnings; 221 break; 222 default: 223 ++nCreateFailures; 224 System.err.println(MessageFormat.format("error", 225 TagUtils.shortToHexString(status))); 226 System.err.println(cmd); 227 } 228 } 229 230 private void onNSetRSP(Attributes cmd) { 231 nSetcmdRSP.add(cmd); 232 int status = cmd.getInt(Tag.Status, -1); 233 switch (status) { 234 case Status.Success: 235 ++nSetSent; 236 break; 237 default: 238 ++nSetFailures; 239 System.err.println(MessageFormat.format("error", 240 TagUtils.shortToHexString(status))); 241 System.err.println(cmd); 242 } 243 } 244 245 @Override 246 public void init(TestResult result) { 247 this.result = result; 248 } 249 250 @Override 251 public TestResult getResult() { 252 return this.result; 253 } 254 255}