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.web.servlets; 020 021import java.io.File; 022import java.io.FileFilter; 023import java.io.IOException; 024import java.net.URI; 025import java.util.List; 026import java.util.Map; 027import java.util.HashMap; 028import java.util.Enumeration; 029import javax.servlet.http.HttpServlet; 030import javax.servlet.http.HttpServletRequest; 031import javax.servlet.http.HttpServletResponse; 032import javax.servlet.ServletOutputStream; 033 034import pt.ua.dicoogle.sdk.datastructs.Report; 035import pt.ua.dicoogle.sdk.settings.types.ServerDirectoryPath; 036import pt.ua.dicoogle.sdk.task.Task; 037import pt.ua.dicoogle.server.web.management.Services; 038import pt.ua.dicoogle.server.web.auth.Session; 039import static org.apache.commons.lang3.StringEscapeUtils.escapeHtml4; 040import pt.ua.dicoogle.plugins.PluginController; 041import pt.ua.dicoogle.server.web.management.Dicoogle; 042 043/** 044 * Provides indexing start and stop requests (scan path). Also handles requests 045 * for both indexing progress/status and server path contents. 046 * 047 * @author António Novo <antonio.novo@ua.pt> 048 */ 049@Deprecated 050public class IndexerServlet extends HttpServlet { 051 052 /** 053 * 054 */ 055 private static final long serialVersionUID = 1L; 056 057 public static final String PARAM_ACTION = "action"; 058 059 public static final String ACTION_START_INDEXING = "start"; 060 public static final String ACTION_STOP_INDEXING = "stop"; 061 public static final String ACTION_GET_STATUS = "status"; 062 public static final String ACTION_SET_INDEXING_PATH = "setpath"; 063 public static final String ACTION_SET_ADVANCED_SETTINGS = "setadvancedsettings"; 064 public static final String ACTION_GET_PATH_CONTENTS = "pathcontents"; 065 public static final String ACTION_PARAM_PATH = "path"; 066 067 /* 068 * Action codes for internal use. 069 */ 070 private static final int ACTION_CODE_INVALID = 0; 071 private static final int ACTION_CODE_START_INDEXING = 1; 072 private static final int ACTION_CODE_STOP_INDEXING = 2; 073 private static final int ACTION_CODE_GET_STATUS = 3; 074 private static final int ACTION_CODE_SET_INDEXING_PATH = 4; 075 private static final int ACTION_CODE_SET_ADVANCED_SETTINGS = 5; 076 private static final int ACTION_CODE_GET_PATH_CONTENTS = 6; 077 078 /** 079 * A file filter to allow the listing of directories only. 080 */ 081 private static FileFilter onlyDirectories = new FileFilter() { 082 @Override 083 public boolean accept(File pathname) { 084 return pathname.isDirectory(); 085 } 086 }; 087 088 private List<Task<Report>> ongoingTasks; 089 090 public IndexerServlet() { 091 this.ongoingTasks = null; 092 } 093 094 /** 095 * Returns a XML document in String form containing the list of child 096 * directories of the specified path. 097 * 098 * @param path 099 * the path of the directory to retrieve the child directories 100 * of. 101 * @return a XML document in String form containing the list of child 102 * directories of the specified path. 103 */ 104 public static String getPathContents(String path) { 105 File dir = null; 106 if (path != null) 107 dir = new File(path); 108 109 // check if the specified path is a valid one, if not revert to "roots" 110 if ((path == null) || path.trim().isEmpty() || (dir == null) 111 || (!dir.exists()) || (!dir.isDirectory())) 112 path = ""; 113 else 114 path = dir.getAbsolutePath(); 115 116 // guarantee that the parent path is always a valid one (never null) 117 String parentPath = ""; 118 File[] childs = null; 119 if (path.isEmpty()) { 120 // return "roots" 121 childs = File.listRoots(); 122 } else { 123 if (dir.getParent() != null) { 124 File parent = new File(dir.getParent()); 125 parentPath = parent.getAbsolutePath(); 126 } 127 // list the dir children 128 childs = dir.listFiles(onlyDirectories); 129 } 130 131 // create the XML string builder and open the xml document 132 StringBuilder xml = new StringBuilder( 133 "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>"); 134 xml.append("<contents path=\""); 135 xml.append(escapeHtml4(path)); 136 xml.append("\" parent=\""); 137 xml.append(escapeHtml4(parentPath)); 138 xml.append("\">"); 139 140 // loop through all the cildren and add their path name to the XML tree 141 if (childs != null) { 142 for (File child : childs) { 143 String cName = child.getName(); 144 String cPath = child.getAbsolutePath(); 145 if ((cName == null) || cName.isEmpty()) 146 cName = cPath; 147 148 xml.append("<directory name=\""); 149 xml.append(escapeHtml4(cName)); 150 xml.append("\" path=\""); 151 xml.append(escapeHtml4(cPath)); 152 xml.append("\" />"); 153 } 154 } 155 156 // close the document 157 xml.append("</contents>"); 158 159 // return the formed XML string 160 return xml.toString(); 161 } 162 163 /** 164 * Returns a XML document in String form containing the status of the 165 * indexing. 166 * 167 * @return a XML document in String form containing the status of the 168 * indexing. TODO: fix 169 */ 170 public String getIndexingStatus() { 171 boolean isIndexing = false; 172 int percentCompleted = 0; 173 174 if (this.ongoingTasks != null) { 175 System.out.println("### Status ###"); 176 System.out.println("### Number of Tasks : " 177 + this.ongoingTasks.size()); 178 float tempProgess = 0; 179 for (Task<Report> task : this.ongoingTasks) { 180 if (!task.isDone()) 181 isIndexing = true; 182 System.out.println("##### $ Progress: " + task.getProgress()); 183 System.out.println("##### $ Completed: " + task.isDone()); 184 tempProgess += task.getProgress(); 185 } 186 percentCompleted = (int) (tempProgess / this.ongoingTasks.size() * 100); 187 if (isIndexing == false) 188 this.ongoingTasks = null; 189 } 190 191 // create the XML string builder and open the xml document 192 StringBuilder xml = new StringBuilder( 193 "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>"); 194 xml.append("<status running=\""); 195 xml.append(Boolean.toString(isIndexing)); 196 xml.append("\">"); 197 198 // add percentage information 199 xml.append("<percent completed=\""); 200 xml.append(percentCompleted); 201 xml.append("\" />"); 202 203 // close the document 204 xml.append("</status>"); 205 206 // return the formed XML string 207 return xml.toString(); 208 } 209 210 /** 211 * Writes the specified XML document in String form to a HttpServletResponse 212 * object. 213 * 214 * @param xml 215 * a XML document in String form. 216 * @param response 217 * a HttpServletResponse. 218 * @throws IOException 219 * if a error has occurred while writing the response. 220 */ 221 private static void writeXMLToResponse(String xml, 222 HttpServletResponse response, boolean allowCache) 223 throws IOException { 224 // get the returned xml as a UTF-8 byte array 225 byte[] data = xml.getBytes("UTF-8"); 226 if (data == null) { 227 response.sendError(500, 228 "Could generate the resulting XML document!"); 229 return; 230 } 231 232 if (!allowCache) { 233 response.addHeader("Cache-Control", "no-cache, must-revalidate"); 234 response.addHeader("Pragma", "no-cache"); 235 } 236 237 response.setContentType("application/xml"); // set the appropriate type 238 // for the XML file 239 response.setContentLength(data.length); // set the document size 240 // response.setCharacterEncoding("UTF-8"); // set the apropriate 241 // encoding type 242 243 // write the XML data to the response output 244 ServletOutputStream out = response.getOutputStream(); 245 out.write(data); 246 out.close(); 247 } 248 249 @Override 250 protected void doGet(HttpServletRequest request, 251 HttpServletResponse response) throws IOException { 252 // TODO validate user session credentials 253 254 // get which action to take 255 String actionStr = request.getParameter(PARAM_ACTION); 256 257 // translate each action string to a action identification 258 int action = ACTION_CODE_INVALID; 259 if (actionStr != null) { 260 if (actionStr.equalsIgnoreCase(ACTION_START_INDEXING)) 261 action = ACTION_CODE_START_INDEXING; 262 else if (actionStr.equalsIgnoreCase(ACTION_STOP_INDEXING)) 263 action = ACTION_CODE_STOP_INDEXING; 264 else if (actionStr.equalsIgnoreCase(ACTION_GET_STATUS)) 265 action = ACTION_CODE_GET_STATUS; 266 else if (actionStr.equalsIgnoreCase(ACTION_SET_INDEXING_PATH)) 267 action = ACTION_CODE_SET_INDEXING_PATH; 268 else if (actionStr.equalsIgnoreCase(ACTION_SET_ADVANCED_SETTINGS)) 269 action = ACTION_CODE_SET_ADVANCED_SETTINGS; 270 else if (actionStr.equalsIgnoreCase(ACTION_GET_PATH_CONTENTS)) 271 action = ACTION_CODE_GET_PATH_CONTENTS; 272 } 273 274 // response to each action accordingly 275 // fix this! 276 switch (action) { 277 case ACTION_CODE_START_INDEXING: 278 System.err.println("Started Indexing!!"); 279 280 Dicoogle dic = Dicoogle.getInstance(); 281 282 ServerDirectoryPath thepath = (ServerDirectoryPath) dic 283 .getIndexingSettings().get( 284 "Dicoogle Directory Monitorization"); 285 286 System.out.println("Indexing Home: " + thepath.getPath()); 287 File f = new File(thepath.getPath()); 288 URI uri = f.toURI(); 289 290 if (uri != null) { 291 System.out.println("URI: " + uri.toString()); 292 List<Task<Report>> report = PluginController.getInstance().index(uri); 293 System.out.println("Report Length: " + report.size()); 294 if (this.ongoingTasks == null) 295 this.ongoingTasks = report; 296 else 297 System.out.println("More than one task in queue"); 298 } else 299 System.out.println("Faulty"); 300 // send the client back the to previous page 301 response.sendRedirect(Session.getLastVisitedURL(request)); 302 break; 303 304 case ACTION_CODE_STOP_INDEXING: 305 // idx.stopIndexing(); 306 // send the client back the to previous page 307 308 // Cancelling all Tasks 309 if (this.ongoingTasks != null) { 310 for (Task<Report> t : this.ongoingTasks) 311 t.cancel(true); 312 } 313 314 response.sendRedirect(Session.getLastVisitedURL(request)); 315 break; 316 317 case ACTION_CODE_GET_STATUS: 318 // get the XML document containing contents of the requested 319 // directory path 320 writeXMLToResponse(getIndexingStatus(), response, false); 321 break; 322 323 case ACTION_CODE_SET_INDEXING_PATH: 324 String path = request.getParameter(ACTION_PARAM_PATH); 325 if ((path == null) || (path.isEmpty())) { 326 response.sendError(HttpServletResponse.SC_NOT_ACCEPTABLE, 327 "Invalid path parameter specified!"); 328 return; 329 } 330 331 // send the client back the to previous page 332 response.sendRedirect(Session.getLastVisitedURL(request)); 333 break; 334 335 case ACTION_CODE_SET_ADVANCED_SETTINGS: 336 HashMap<String, String[]> advSettings = new HashMap<String, String[]>(); 337 338 // get all the settings and their values 339 Enumeration<String> params = request.getParameterNames(); 340 while (params.hasMoreElements()) { 341 String name = params.nextElement(); 342 // ignore the main params (the ones that go us here) 343 if (name.equalsIgnoreCase(PARAM_ACTION)) 344 continue; 345 String[] value = request.getParameterValues(name); 346 advSettings.put(name, value); 347 } 348 349 // HashMap<String, Object> settings = idx.getSettings(); 350 // Services svcs = Services.getInstance(); 351 // svcs.processAdvancedSettings(settings, advSettings); 352 353 // try to apply the settings 354 /* 355 * if (idx.trySettings(settings)){ idx.setSettings(settings); 356 * svcs.saveSettings(); // send the client back the to previous page 357 * response.sendRedirect(Session.getLastVisitedURL(request)); } else 358 */ 359 response.sendError(HttpServletResponse.SC_BAD_REQUEST, 360 "Invalid parameters!"); 361 break; 362 363 case ACTION_CODE_GET_PATH_CONTENTS: 364 path = request.getParameter(ACTION_PARAM_PATH); 365 366 // get the XML document containing contents of the requested 367 // directory path 368 writeXMLToResponse(getPathContents(path), response, false); 369 break; 370 371 default: 372 response.sendError(HttpServletResponse.SC_BAD_REQUEST, 373 "Invalid action!"); 374 return; 375 } 376 } 377 378 /** 379 * Based on the request, returns a String containing a form with all the 380 * settings inputs boxes. These boxes are rendered/specified in accordance 381 * with the each setting value type reported by the plugin/service. 382 * 383 * @param request 384 * the servlet request object. 385 * @param brokerURL 386 * the URL of the broker that will apply the settings after 387 * receiving this forms post. 388 * @param elementID 389 * the ID of this HTML form, can be null. 390 * @return a String containing the HTML structure for the form with all the 391 * plugin advanced setting. 392 */ 393 public static String getHTMLServiceAdvancedSettingsForm( 394 HttpServletRequest request, String brokerURL, String elementID) 395 throws IOException { 396 String result = ""; 397 398 if ((elementID == null) || elementID.trim().isEmpty()) 399 result += "<form "; 400 else 401 result += "<form id=\"" + elementID + "\" "; 402 result += "action=\"" + brokerURL + "\" method=\"get\">"; 403 404 result += "<input type=\"hidden\" name=\"" + PARAM_ACTION 405 + "\" value=\"" + ACTION_SET_ADVANCED_SETTINGS + "\" />"; 406 407 result += "<table class=\"table table-hover\"><tbody>"; 408 409 // HashMap<String, Object> settings = idx.getSettings(); 410 // HashMap<String, String> settingsHelp = idx.getSettingsHelp(); 411 412 HashMap<String, Object> settings = new HashMap<>(); 413 HashMap<String, String> settingsHelp = new HashMap<>(); 414 415 Services svcs = Services.getInstance(); 416 417 // create a table row for each setting (includes name, value/type and 418 // help, if available) 419 for (Map.Entry<String, Object> setting : settings.entrySet()) { 420 String key = setting.getKey(); 421 Object value = setting.getValue(); 422 String help = settingsHelp.get(key); 423 424 result += svcs.getHTMLAdvancedSettingsFormRow(key, value, help); 425 } 426 427 result += "</tbody></table><br />"; 428 result += "<input type=\"submit\" value=\"Apply Settings\" class=\"btn btn-primary\"/>"; 429 result += "</form>"; 430 431 return result; 432 } 433 434 @Override 435 protected void doPost(HttpServletRequest request, 436 HttpServletResponse response) throws IOException { 437 doGet(request, response); 438 } 439}