001/** 002 * Copyright (C) 2014 Universidade de Aveiro, DETI/IEETA, Bioinformatics Group - http://bioinformatics.ua.pt/ 003 * 004 * This file is part of Dicoogle/dicoogle. 005 * 006 * Dicoogle/dicoogle is free software: you can redistribute it and/or modify 007 * it under the terms of the GNU General Public License as published by 008 * the Free Software Foundation, either version 3 of the License, or 009 * (at your option) any later version. 010 * 011 * Dicoogle/dicoogle is distributed in the hope that it will be useful, 012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 014 * GNU General Public License for more details. 015 * 016 * You should have received a copy of the GNU General Public License 017 * along with Dicoogle. If not, see <http://www.gnu.org/licenses/>. 018 */ 019package pt.ua.dicoogle.server.queryretrieve; 020 021import aclmanager.core.LuceneQueryACLManager; 022import aclmanager.models.Principal; 023import java.net.InetAddress; 024import java.net.URI; 025import java.net.URISyntaxException; 026import java.util.ArrayList; 027import java.util.concurrent.Executor; 028 029import org.dcm4che2.data.Tag; 030import org.slf4j.Logger; 031import org.slf4j.LoggerFactory; 032import org.slf4j.Logger; 033import org.slf4j.LoggerFactory; 034import javax.xml.transform.TransformerConfigurationException; 035import org.dcm4che2.data.DicomElement; 036import org.dcm4che2.data.DicomObject; 037import org.dcm4che2.net.Association; 038import org.dcm4che2.net.DicomServiceException; 039import org.dcm4che2.net.DimseRSP; 040import org.dcm4che2.net.Status; 041import pt.ua.dicoogle.core.exceptions.CFindNotSupportedException; 042 043import pt.ua.dicoogle.DicomLog.LogDICOM; 044import pt.ua.dicoogle.DicomLog.LogLine; 045import pt.ua.dicoogle.DicomLog.LogXML; 046import pt.ua.dicoogle.sdk.datastructs.MoveDestination; 047import pt.ua.dicoogle.server.DicomNetwork; 048import pt.ua.dicoogle.server.SearchDicomResult; 049import pt.ua.dicoogle.core.ServerSettings; 050import pt.ua.dicoogle.rGUI.server.controllers.Logs; 051 052/** 053 * 054 * @author Luís A. Bastião Silva <bastiao@ua.pt> 055 */ 056public class CMoveServiceSCP extends CMoveService { 057 058 private DicomNetwork service = null; 059 private LuceneQueryACLManager luke; 060 061 public CMoveServiceSCP(String[] sopClasses, Executor executor, LuceneQueryACLManager luke) { 062 super(sopClasses, executor); 063 this.luke = luke; 064 } 065 066 public CMoveServiceSCP(String sopClass, Executor executor) { 067 super(sopClass, executor); 068 this.luke = null; 069 } 070 071 072 @Override 073 protected DimseRSP doCMove(Association as, int pcid, DicomObject cmd, 074 DicomObject data, DicomObject rsp) throws DicomServiceException { 075 //DebugManager.getInstance().debug("doCMove"); 076 //DebugManager.getInstance().debug("DoCmove"); 077 078 DimseRSP replay = null; 079 080 /** 081 * Verify Permited AETs 082 */ 083 //DebugManager.getInstance().debug(":: Verify Permited AETs @??C-MOVE Action "); 084 085 boolean permited = false; 086 087 if (ServerSettings.getInstance().getPermitAllAETitles()) { 088 permited = true; 089 } else 090 { 091 String permitedAETs[] = ServerSettings.getInstance().getCAET(); 092 093 for (int i = 0; i < permitedAETs.length; i++) { 094 if (permitedAETs[i].equals(as.getCallingAET())) { 095 permited = true; 096 break; 097 } 098 } 099 } 100 101 if (!permited) { 102 //DebugManager.getInstance().debug("Client association NOT permited: " + as.getCallingAET() + "!"); 103 as.abort(); 104 105 return new MoveRSP(data, rsp); 106 } else { 107 //DebugManager.getInstance().debug("Client association permited: " + as.getCallingAET() + "!"); 108 } 109 110 /** FIXME: Write wait by rspreplay */ 111 try { 112 Thread.sleep(ServerSettings.getInstance().getRspDelay()); 113 } catch (Exception e) { 114 e.printStackTrace(); 115 } 116 117 118 119 /** 120 * 121 * Now it is the code to move 122 * In this sense it have a fork, besides we can open the store request 123 * in the source direction, or it can make a store to a third party 124 * 125 */ 126 /** Get the real IP to move */ 127 InetAddress ip = as.getSocket().getInetAddress(); 128 /** Get the port to move */ 129 int portAddr = as.getSocket().getPort(); 130 131 String destination = cmd.getString(org.dcm4che2.data.Tag.MoveDestination); 132 //DebugManager.getInstance().debug("A Move was required to <ip:port> : <" 133 // + ip.getHostAddress() + ":" + portAddr + ">" + " to --> " + destination); 134 135 136 137 /** Verify if it have the field destination */ 138 if (destination == null) { 139 throw new DicomServiceException(cmd, Status.UnrecognizedOperation, 140 "Missing Move Destination"); 141 } 142 143 /*DebugManager.getInstance().debug("-- Objects containing the data requested by C-MOVE"); 144 DebugManager.getInstance().debug(data.toString()); 145 DebugManager.getInstance().debug(cmd.toString()); 146 DebugManager.getInstance().debug(rsp.toString());*/ 147 String SOPUID = new String(data.get(Integer.parseInt("0020000D", 16)).getBytes()); 148 String CMoveID = cmd.getString(org.dcm4che2.data.Tag.MessageID); 149 System.out.println("C-MOVE ID REQUEST: " + CMoveID); 150 151 /** 152 * Get object to search 153 */ 154 ArrayList<String> extrafields = null; 155 extrafields = new ArrayList<String>(); 156 157 extrafields.add("PatientName"); 158 extrafields.add("PatientID"); 159 extrafields.add("Modality"); 160 extrafields.add("StudyDate"); 161 extrafields.add("Thumbnail"); 162 extrafields.add("StudyInstanceUID"); 163 164 SearchDicomResult.QUERYLEVEL level = null; 165 if (CFindBuilder.isPatientRoot(rsp)) { 166 level = SearchDicomResult.QUERYLEVEL.PATIENT; 167 } else if (CFindBuilder.isStudyRoot(rsp)) { 168 level = SearchDicomResult.QUERYLEVEL.STUDY; 169 } 170 171 CFindBuilder cfind = null; 172 try { 173 cfind = new CFindBuilder(data, rsp); 174 } catch (CFindNotSupportedException ex) { 175 ex.printStackTrace(); 176 } 177 String query = cfind.getQueryString(); 178 179 if(luke != null){ 180 String filterQuery = luke.produceQueryFilter(new Principal("AETitle", as.getCallingAET())); 181 if(query.length() > 0 ) 182 query += filterQuery; 183 } 184 //TODO: FIlter Query; 185 SearchDicomResult search = new SearchDicomResult(query, 186 true, extrafields, SearchDicomResult.QUERYLEVEL.IMAGE); 187 ArrayList<URI> files = new ArrayList<URI>(); 188 189 190 191 192 if (search == null) { 193 //DebugManager.getInstance().debug(">> Search is null, so" 194 // + " somethig is wrong "); 195 } else { 196 197 while (search.hasNext()) { 198 DicomObject obj = search.next(); 199 DicomElement e = obj.get(Integer.parseInt("0020000D", 16)); 200 String tmp = null; 201 if (e != null) { 202 tmp = new String(e.getBytes()); 203 } 204 if (SOPUID != null && tmp != null) { 205 //files.add(new File(search.getCurrentFile())); 206 String uriString = search.getCurrentFile(); 207 208 try { 209 URI nURI = new URI(uriString); 210 211 files.add(nURI); 212 } catch (URISyntaxException ex) { 213 LoggerFactory.getLogger(CMoveServiceSCP.class).error(ex.getMessage(), ex); 214 } 215 } 216 217 } 218 } 219 220 221 222 223 224 if (files.size() != 0) { 225 226 /** 227 * What is the destination? 228 * 229 */ 230 String hostDest = ip.getHostAddress(); 231 ServerSettings ob = ServerSettings.getInstance(); 232 for (MoveDestination m : ob.getMoves()) { 233 if (m.getAETitle().equals(destination)) { 234 hostDest = m.getIpAddrs(); 235 portAddr = m.getPort(); 236 } 237 } 238 239 240 241 LogLine ll = new LogLine("cmove", LogLine.getDateTime(), destination, 242 "Files: " + files.size() + " -- (" + hostDest + ":" + portAddr + ")","studyUID="+data.getString(Tag.StudyInstanceUID)); 243 LogDICOM.getInstance().addLine(ll); 244 245 synchronized (LogDICOM.getInstance()) { 246 try { 247 LogXML l = new LogXML(); 248 l.printXML(); 249 } catch (TransformerConfigurationException ex) { 250 LoggerFactory.getLogger(CMoveServiceSCP.class).error(ex.getMessage(), ex); 251 } 252 } 253 254 //Logs.getInstance().addLog(ll); 255 if (CMoveID==null||CMoveID.equals("")) 256 { 257 //DebugManager.getInstance().debug("No originator message ID"); 258 return null; 259 } 260 try 261 { 262 System.out.println("Destination: " + destination); 263 new CallDCMSend(files, portAddr, hostDest, destination, CMoveID); 264 } catch (Exception ex) 265 { 266 ex.printStackTrace(); 267 //DebugManager.getInstance().debug("Error Sending files to Storage Server!"); 268 } 269 } 270 271 /** UnNecessary now 272 273 // put a BufferedReader on the ls output 274 275 InputStream inputstream = 276 proc.getInputStream(); 277 InputStreamReader inputstreamreader = 278 new InputStreamReader(inputstream); 279 BufferedReader bufferedreader = 280 new BufferedReader(inputstreamreader); 281 282 // read the ls output 283 284 String line; 285 try 286 { 287 while ((line = bufferedreader.readLine()) != null) 288 { 289 System.out.println(">>>"+line); 290 } 291 //replay = new MoveRSP(keys, rsp, this.core); // Third Party Move 292 } catch (IOException ex) 293 { 294 LoggerFactory.getLogger(CMoveServiceSCP.class).error(ex.getMessage(), ex); 295 } 296 try 297 { 298 Thread.sleep(100); 299 //replay = new MoveRSP(keys, rsp, this.core); // Third Party Move 300 } catch (InterruptedException ex) 301 { 302 LoggerFactory.getLogger(CMoveServiceSCP.class).error(ex.getMessage(), ex); 303 } 304 */ 305 replay = new MoveRSP(data, rsp); // Third Party Move 306 return replay; 307 308 } 309 310 /** 311 * @return the service 312 */ 313 public DicomNetwork getService() { 314 return service; 315 } 316 317 /** 318 * @param service the service to set 319 */ 320 public void setService(DicomNetwork service) { 321 this.service = service; 322 } 323}