001 /* 002 * $RCSfile: JDLHandler.java,v $ 003 * 004 * Created on August 28, 2003, 13:28 AM 005 * 006 * This file is part of the STAR Scheduler. 007 * Copyright (c) 2002-2006 STAR Collaboration - Brookhaven National Laboratory 008 * 009 * STAR Scheduler is free software; you can redistribute it and/or modify 010 * it under the terms of the GNU General Public License as published by 011 * the Free Software Foundation; either version 2 of the License, or 012 * (at your option) any later version. 013 * 014 * STAR Scheduler is distributed in the hope that it will be useful, 015 * but WITHOUT ANY WARRANTY; without even the implied warranty of 016 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 017 * GNU General Public License for more details. 018 * 019 * You should have received a copy of the GNU General Public License 020 * along with STAR Scheduler; if not, write to the Free Software 021 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 022 */ 023 package gov.bnl.star.offline.scheduler.request; 024 025 import gov.bnl.star.offline.scheduler.*; 026 import gov.bnl.star.offline.scheduler.util.FilesystemToolkit; 027 import gov.bnl.star.offline.scheduler.util.sandbox.*; 028 import org.xml.sax.Attributes; 029 030 import java.net.URL; 031 import java.net.URI; 032 import java.util.Arrays; 033 import java.util.List; 034 //import java.util.logging.Level; 035 import org.apache.log4j.Logger; 036 037 038 /** 039 * Reads a STAR scheduler XML request and creates a Request 040 * with the specified information. 041 * 042 * @author Gabriele Carcassi & Pavel Jakl & Levente Hajdu 043 * @version $Revision: 1.15 $ $Date: 2006/11/21 00:41:31 $ 044 */ 045 public class JDLHandler extends RequestHandler { 046 047 static public Logger log = Logger.getLogger(RequestHandler.class.getName()); 048 boolean readingCommand; 049 boolean readingFile; 050 private boolean startLimitDeprecationMessage = false; 051 private OutputFile currentOutput; 052 private SandboxPackage currentPackage; 053 054 /** 055 * Parses an XML file according the STAR scheduler specification. More information 056 * about the specifications can be found in the STAR scheduler website. 057 * 058 * @param fileName the XML request file name 059 */ 060 public JDLHandler(String fileName) { 061 super(fileName); 062 } 063 064 String command = ""; 065 066 /** 067 * Parsing method. This method parses the XML file according to SAX specifications. 068 */ 069 public void characters(char[] ch, int start, int length) { 070 071 if (readingCommand) { 072 command += new String(ch, start, length); 073 } 074 075 if(readingFile) packageFileElement(new String(ch, start, length)); 076 077 } 078 079 private void flushCommandBuffer() { 080 081 if (readingCommand) { 082 ((Request) requests.get(requests.size() - 1)).setCommand(command); 083 readingCommand = false; 084 } 085 } 086 087 private void displayStartLimitDeprecationMessage() { 088 if (!startLimitDeprecationMessage) { 089 System.out.print("\nWARNING: The use of \"start\" and \"limit\" for catalog queries is deprecated."); 090 System.out.print("\nUse \"nFiles\" which will return only one copy per file."); 091 startLimitDeprecationMessage = true; 092 } 093 } 094 095 private void catalogElement(Attributes attrs) { 096 Request req = ((Request) requests.get(requests.size() - 1)); 097 List input = req.getInputList(); 098 CatalogQuery query = new CatalogQuery(attrs.getValue("URL")); 099 100 String nFiles = attrs.getValue("nFiles"); 101 102 if (nFiles != null) { 103 try { 104 if (nFiles.equals("all")) { 105 query.setNFiles(new Integer(-1)); 106 } else { 107 query.setNFiles(new Integer(nFiles)); 108 } 109 } catch (NumberFormatException e) { 110 log.fatal("Wrong argument for nFile attibute"); 111 112 throw new RuntimeException("Wrong argument for nFile attibute. Must be an integer and was: " + 113 nFiles); 114 } 115 } 116 117 if (attrs.getValue("limit") != null) { 118 try { 119 displayStartLimitDeprecationMessage(); 120 query.setLimit(new Integer(attrs.getValue("limit"))); 121 } catch (NumberFormatException e) { 122 log.fatal("Wrong argument for a limit attibute"); 123 124 throw new RuntimeException("Wrong argument for a limit attibute. Must be an integer and was: " + 125 attrs.getValue("limit")); 126 } 127 } 128 129 if (attrs.getValue("start") != null) { 130 try { 131 displayStartLimitDeprecationMessage(); 132 query.setStart(new Integer(attrs.getValue("start"))); 133 } catch (NumberFormatException e) { 134 log.fatal("Wrong argument for a start attibute"); 135 throw new RuntimeException("Wrong argument for a start attibute. Must be an integer and was: " + 136 attrs.getValue("limit")); 137 } 138 } 139 140 if ((attrs.getValue("singleCopy") == null) || 141 (attrs.getValue("singleCopy").equals("true"))) { 142 query.setSingleCopy(true); 143 } else { 144 query.setSingleCopy(false); 145 } 146 147 String preferStorage = attrs.getValue("preferStorage"); 148 149 if (preferStorage != null) { 150 List preferStorageAllowedValues = Arrays.asList(new String[]{ 151 "NFS", "local", "HPSS" 152 }); 153 154 if (preferStorageAllowedValues.contains(preferStorage)) { 155 query.setPreferStorage(preferStorage); 156 } else { 157 log.fatal("Wrong argument for a preferStorage attibute"); 158 throw new RuntimeException("Wrong argument for a preferStorage attibute.\n Allowed values are: " + 159 preferStorageAllowedValues + "\n Specified value was: " + 160 preferStorage); 161 } 162 // go through the requests and check if preferStorage is HPSS and fileListSyntax is xrootd 163 String fileListSyntax = req.getFileListType(); 164 if ("HPSS".equals(preferStorage) && !"xrootd".equals(fileListSyntax)) { 165 throw new RuntimeException("You have specified preferStorage as HPSS, but files from HPSS are accessible only with attribute fileListSyntax=\"xrootd\" !! \n" 166 + "You have specified fileListSyntax as: " + fileListSyntax); 167 } 168 } 169 input.add(query); 170 } 171 172 private void jobElement(String namespaceURI, String sName, String qName, 173 Attributes attrs) { 174 // New process found in the job description 175 log.debug("Reading job"); 176 177 Request req = new Request(attrs.getValue("username"), null, 178 attrs.getValue("name"), attrs.getValue("description"), 179 xmlFileName); 180 181 // Process maxFilesPerProcess 182 String maxFilesPerProcess = attrs.getValue("maxFilesPerProcess"); 183 184 if (maxFilesPerProcess != null) { 185 try {//this try is not really needed because it should have been validated before getting to this point. 186 req.setResourceMax("FilesPerProcess", Integer.parseInt(maxFilesPerProcess)); 187 //System.out.println("MaxFilesPerProcess is set to = " + req.getMaxFilesPerProcess());////////////////////////// 188 } catch (NumberFormatException e) { 189 log.fatal("maxFilesPerProcess must be an integer: " + maxFilesPerProcess, e); 190 throw new RuntimeException("Illegal value for maxFilesPerProcess. Must be an integer and was: " + 191 maxFilesPerProcess); 192 } 193 } 194 195 // Process maxDiskSpace 196 String maxStorageSpace = attrs.getValue("maxStorageSpace"); 197 if (maxStorageSpace != null) { 198 req.setResourceMax("StorageSpace", 199 Integer.parseInt(maxStorageSpace)); 200 //System.out.println("maxStorageSpace = " + maxStorageSpace); //just for testing 201 } 202 // Process minDiskSpace 203 String minStorageSpace = attrs.getValue("minStorageSpace"); 204 if (minStorageSpace != null) { 205 req.setResourceMin("StorageSpace", 206 Integer.parseInt(minStorageSpace)); 207 //System.out.println("minStorageSpace = " + minStorageSpace); //just for testing 208 } 209 210 // Process maxMemory 211 String maxMemory = attrs.getValue("maxMemory"); 212 if (maxMemory != null) { 213 214 req.setResourceMax("Memory", Integer.parseInt(maxMemory)); 215 //System.out.println("maxStorageSpace = " + maxStorageSpace); //just for testing 216 } 217 218 // Process minMemory 219 String minMemory = attrs.getValue("minMemory"); 220 if (minMemory != null) { 221 222 req.setResourceMin("Memory", Integer.parseInt(minMemory)); 223 //System.out.println("maxStorageSpace = " + maxStorageSpace); //just for testing 224 } 225 226 227 //minWallTime 228 String minWallTime = attrs.getValue("minWallTime"); 229 if (minWallTime != null) { 230 req.setResourceMin("WallTime", Integer.parseInt(minWallTime)); 231 //System.out.println(req.getMinWallTime()); 232 } 233 234 //maxWallTime 235 String maxWallTime = attrs.getValue("maxWallTime"); 236 if (maxWallTime != null) { 237 req.setResourceMax("WallTime", Integer.parseInt(maxWallTime)); 238 //System.out.println(req.getMaxWallTime()); 239 } 240 241 242 // Process minFilesPerProcess 243 String minFilesPerProcess = attrs.getValue("minFilesPerProcess"); 244 if (minFilesPerProcess != null) { 245 try { 246 req.setResourceMin("FilesPerProcess", Integer.parseInt(minFilesPerProcess)); 247 } catch (NumberFormatException e) { 248 log.fatal("minFilesPerProcess must be an integer: " + minFilesPerProcess, e); 249 throw new RuntimeException("Illegal value for minFilesPerProcess. Must be an integer and was: " + minFilesPerProcess); 250 } 251 } else 252 req.setResourceMin("FilesPerProcess", -1); 253 254 // Process nProcesses 255 String nProcesses = attrs.getValue("nProcesses"); 256 if (nProcesses != null) { 257 try { 258 req.setNProcesses(Integer.parseInt(nProcesses)); 259 } catch (NumberFormatException e) { 260 log.fatal("nProcesses must be an integer: " + nProcesses, e); 261 throw new RuntimeException("Illegal value for nProcesses. Must be an integer and was: " + nProcesses); 262 } 263 } 264 265 if ("true".equals(attrs.getValue("simulation"))) { 266 System.out.println("\nThe \"simulation\" attribute is deprecated. It was confusiong since in STAR simulation has a specific meaning. "); 267 System.out.print("Use \"simulateSubmission\" instead. For this time, scheduling will continue anyway in simulation mode."); 268 req.setSimulation(true); 269 } 270 271 if ("true".equals(attrs.getValue("simulateSubmission"))) { 272 req.setSimulation(true); 273 } 274 275 if ("true".equals(attrs.getValue("mail"))) { 276 req.setMail(true); 277 } 278 279 if (attrs.getValue("fileListSyntax") != null) { 280 req.setFileListType(attrs.getValue("fileListSyntax")); 281 } 282 283 if (attrs.getValue("filesPerHour") != null) { 284 try { 285 req.setFilesPerHour(Double.parseDouble(attrs.getValue("filesPerHour"))); 286 } catch (Exception ex) { 287 log.fatal("filesPerHour not formatted correctly: " + attrs.getValue("filesPerHour"), ex); 288 throw new RuntimeException("filesPerHour must be a number (ex. 23.5)"); 289 } 290 } 291 292 if (attrs.getValue("inputOrder") != null) { 293 req.prepareInputOrder(attrs.getValue("inputOrder")); 294 System.out.println("TEST: Input order " + req.getInputOrder()); 295 } 296 297 requests.add(req); 298 } 299 300 private void fileElement(String namespaceURI, String sName, String qName, Attributes attrs) { 301 List input = ((Request) requests.get(requests.size() - 1)).getInputList(); 302 303 304 if ((attrs.getValue("URL").indexOf('*') != -1) || (attrs.getValue("URL").indexOf('?') != -1)) { 305 // The URL contains a wildcard 306 if ((attrs.getValue("URL").startsWith("file:/")) && (!attrs.getValue("URL").startsWith("file://"))) { 307 308 log.debug("Identified as individual file input: " + attrs.getValue("URL").substring(5)); 309 String[] files = FilesystemToolkit.resolveWildcard(attrs.getValue("URL").substring(5)); 310 311 try { 312 for (int nFile = 0; nFile < files.length; nFile++) { 313 URL file = new URL("file", null, files[nFile]); 314 log.debug("Adding from wildcard: " + file); 315 input.add(file); 316 } 317 } catch (Exception e) { 318 log.debug( "Error while resolving wildcard: " + attrs.getValue("URL"), e); 319 throw new RuntimeException("Error while resolving wildcard: " + attrs.getValue("URL")); 320 } 321 } else { 322 throw new RuntimeException("Can resolve wildcards only on local files: " + attrs.getValue("URL")); 323 } 324 } else { 325 // The URL doesn't contain a wildcard 326 try { 327 input.add(new URL(attrs.getValue("URL"))); 328 } catch (Exception e) { 329 throw new RuntimeException("input URL isn't well specified."); 330 } 331 } 332 } 333 334 private void fileListElement(String namespaceURI, String sName, String qName, Attributes attrs) { 335 List input = ((Request) requests.get(requests.size() - 1)).getInputList(); 336 337 //Only true if fileListSyntax="xrootd" 338 boolean alowXRootd = ((Request) requests.get(requests.size() - 1)).getFileListType().matches("xrootd"); 339 340 // The URL contains a wildcard 341 if ((attrs.getValue("URL").startsWith("filelist:/")) && (!attrs.getValue("URL").startsWith("filelist://"))) { 342 log.debug("Getting filelist: " + attrs.getValue("URL").substring(9)); 343 344 /////////////////////// nfiles bug fix /////////////////////////// 345 String nFiles = attrs.getValue("nFiles"); 346 int nFilesInt = -1; 347 if (nFiles != null) { 348 try { 349 if (!nFiles.equals("all")) nFilesInt = new Integer(nFiles).intValue(); 350 } catch (NumberFormatException e) { 351 log.fatal("Wrong argument for nFile attibute"); 352 throw new RuntimeException("Wrong argument for nFile attibute. Must be an integer and was: " + nFiles); 353 } 354 } 355 ///////////////////////////////////////////////////////////////////////// 356 357 List files = FilesystemToolkit.retrieveFileListContents(attrs.getValue("URL").substring(9), nFilesInt); 358 359 try { 360 for (int nFile = 0; nFile < files.size(); nFile++) { 361 362 //Give the user some kind of error here look for the :/ 363 if (((String) files.get(nFile)).indexOf(":/") == -1){ 364 System.out.println("\nAll the files in the filelist must start with [Identifier]:/ \n example: file:/mydir/myfile.root "); 365 } 366 367 368 369 //Moved to request hendler 370 //This line is needed to alow files with the "root:" protcal to be passed 371 System.setProperty("java.protocol.handler.pkgs", "gov.bnl.star.offline.scheduler.util.protocol" ); 372 373 374 URL file = new URL((String) files.get(nFile)); 375 376 377 //Halt is the user is trying to input files in xrootd from and output it in paths or rootd 378 if((file.getProtocol().matches("root")) && (! alowXRootd) ){ 379 String falt = "\n\nYou are trying to input a filelist with xrootd file(s) in it (example:"+ file +" ) , and then convent the syntax of the output filelist to \"" +((Request) requests.get(requests.size() - 1)).getFileListType() + "\" syntax. This is not possible because node information will be lost (SUMS can't convert LFN to PFN ). Please change your fileListSyntax in the job tag to xrootd or change your file lists syntax.\n\n"; 380 System.out.println(falt); 381 throw new RuntimeException(falt); 382 } 383 384 385 log.debug("Adding from filelist: " + file); 386 input.add(file); 387 } 388 } catch (Exception e) { 389 log.fatal( "Error while processing filelist : " + attrs.getValue("URL"), e); 390 throw new RuntimeException("Error while processing filelist: " + attrs.getValue("URL")); 391 } 392 } else { 393 throw new RuntimeException("Can resolve wildcards only on local files: " + attrs.getValue("URL")); 394 } 395 } 396 397 398 private void stdinElement(String namespaceURI, String sName, String qName, 399 Attributes attrs) { 400 // Standard input for the current process 401 log.debug("Reading stdin"); 402 403 if (attrs.getValue("URL") != null) { 404 try { 405 ((Request) requests.get(requests.size() - 1)).setStdIn(new URL(attrs.getValue("URL"))); 406 } catch (Exception e) { 407 throw new RuntimeException("Stdin URL isn't well specified."); 408 } 409 } else { 410 throw new RuntimeException("Stdin syntax not understood or not implemented."); 411 } 412 } 413 414 private void stdoutElement(String namespaceURI, String sName, String qName, 415 Attributes attrs) { 416 // Standard output for the current process 417 log.debug("Reading stdout"); 418 boolean urlNotSet = true; 419 420 if (attrs.getValue("URL") != null) { 421 try { 422 ((Request) requests.get(requests.size() - 1)).setStdOut(new URL(attrs.getValue("URL"))); 423 urlNotSet = false; 424 } catch (Exception e) { 425 throw new RuntimeException("Stdout URL isn't well specified."); 426 } 427 } 428 if (attrs.getValue("discard") != null){ 429 if (attrs.getValue("discard").equals("true")) { 430 ((Request) requests.get(requests.size() - 1)).setStdOut(Request.discard); 431 } else if( attrs.getValue("discard").equals("false")) { 432 if(urlNotSet) throw new RuntimeException("If discard=\"false\" then the URL must be set for the stdout element."); 433 }else{ 434 throw new RuntimeException("Stdout syntax not understood or not implemented."); 435 } 436 } 437 } 438 439 private void stderrElement(String namespaceURI, String sName, String qName, Attributes attrs) { 440 // Standard error for the current process 441 log.debug("Reading stderr"); 442 boolean urlNotSet = true; 443 444 if (attrs.getValue("URL") != null) { 445 try { 446 ((Request) requests.get(requests.size() - 1)).setStdErr(new URL(attrs.getValue("URL"))); 447 urlNotSet = false; 448 } catch (Exception e) { 449 throw new RuntimeException("Stderr URL isn't well specified."); 450 } 451 } 452 453 454 if (attrs.getValue("discard") != null){ 455 456 if (attrs.getValue("discard").equals("true")) { 457 ((Request) requests.get(requests.size() - 1)).setStdErr(Request.discard); 458 }else if( attrs.getValue("discard").equals("false")) { 459 if(urlNotSet) throw new RuntimeException("If discard=\"false\" then the URL must be set for the stderr element."); 460 }else{ 461 throw new RuntimeException("Stderr syntax not understood or not implemented."); 462 } 463 } 464 465 } 466 467 private void inputElement(String namespaceURI, String sName, String qName, 468 Attributes attrs) { 469 // Input file for the current process 470 log.debug("Reading input"); 471 472 if (attrs.getValue("URL") != null) { 473 if (attrs.getValue("URL").startsWith("catalog:")) { 474 log.debug("Identified as catalog input "); 475 catalogElement(attrs); 476 } else if (attrs.getValue("URL").startsWith("filelist:")) { 477 log.debug("Identified as filelist input"); 478 fileListElement(namespaceURI, sName, qName, attrs); 479 } else { 480 log.debug("Identified as individual file input"); 481 fileElement(namespaceURI, sName, qName, attrs); 482 } 483 } else { 484 log.fatal("Could not identified input"); 485 throw new RuntimeException("input syntax not understood or not implemented."); 486 } 487 } 488 489 private void outputElement(String namespaceURI, String sName, String qName, 490 Attributes attrs) { 491 // Output file for the current process 492 log.debug("Reading output"); 493 494 List output = ((Request) requests.get(requests.size() - 1)).getOutputList(); 495 496 if ((attrs.getValue("fromScratch") != null)) { 497 OutputFile file = new OutputFile(attrs.getValue("fromScratch"), 498 attrs.getValue("toURL")); 499 currentOutput = file; 500 output.add(file); 501 } else { 502 throw new RuntimeException("output syntax not understood or not implemented."); 503 } 504 } 505 506 private void outputCopyActionElement(String namespaceURI, String sName, String qName, 507 Attributes attrs) { 508 if ((attrs.getValue("to") != null)) { 509 510 int sleep = -1; 511 int retries = -1; 512 513 if ((attrs.getValue("retries") != null)) { 514 try { //try to recover the int from the retries attribute 515 retries = java.lang.Integer.parseInt(attrs.getValue("retries")); 516 } catch (Exception e) { 517 throw new RuntimeException("The value of \"retries\" in the copy tag must be an integer\n", e); 518 } 519 if ((attrs.getValue("sleep") != null)) { 520 try { //try to recover the int from the sleep attribute 521 sleep = java.lang.Integer.parseInt(attrs.getValue("sleep")); 522 } catch (Exception e) { 523 throw new RuntimeException("The value of \"sleep\" in the copy tag must be an integer\n", e); 524 } 525 } 526 } 527 528 OutputCopyAction action = new OutputCopyAction(currentOutput.getActionList(), 529 attrs.getValue("id"), 530 attrs.getValue("referto"), 531 attrs.getValue("to"), 532 retries, 533 sleep, 534 attrs.getValue("Type")); 535 currentOutput.getActionList().add(action); 536 } else 537 throw new RuntimeException("copy must have a \"to\" attribute."); 538 } 539 540 private void outputCopyRegisterElement(String namespaceURI, String sName, String qName, 541 Attributes attrs) { 542 if ((attrs.getValue("to") != null)) { 543 544 int sleep = -1; 545 int retries = -1; 546 547 if ((attrs.getValue("retries") != null)) { 548 try { //try to recover the int from the retries attribute 549 retries = java.lang.Integer.parseInt(attrs.getValue("retries")); 550 } catch (Exception e) { 551 throw new RuntimeException("The value of \"retries\" must be an integer\n", e); 552 } 553 if ((attrs.getValue("sleep") != null)) { 554 try { //try to recover the int from the sleep attribute 555 sleep = java.lang.Integer.parseInt(attrs.getValue("sleep")); 556 } catch (Exception e) { 557 throw new RuntimeException("The value of \"sleep\" must be an integer\n", e); 558 } 559 } 560 } 561 562 563 OutputRegisterAction action = new OutputRegisterAction(currentOutput.getActionList(), 564 attrs.getValue("id"), 565 attrs.getValue("referto"), 566 attrs.getValue("to"), 567 retries, 568 sleep); 569 currentOutput.getActionList().add(action); 570 } else { 571 throw new RuntimeException("register tag must have a \"to\" attribute."); 572 } 573 } 574 575 576 private void outputLinkAction(String namespaceURI, String sName, String qName, Attributes attrs) { 577 578 if ((attrs.getValue("to") != null)) { 579 580 int sleep = -1; 581 int retries = -1; 582 583 if ((attrs.getValue("retries") != null)) { 584 try { //try to recover the int from the retries attribute 585 retries = java.lang.Integer.parseInt(attrs.getValue("retries")); 586 } catch (Exception e) { 587 throw new RuntimeException("The value of \"retries\" must be an integer\n", e); 588 } 589 if ((attrs.getValue("sleep") != null)) { 590 try { //try to recover the int from the sleep attribute 591 sleep = java.lang.Integer.parseInt(attrs.getValue("sleep")); 592 } catch (Exception e) { 593 throw new RuntimeException("The value of \"sleep\" must be an integer\n", e); 594 } 595 } 596 } 597 598 OutputLinkAction action = new OutputLinkAction(currentOutput.getActionList(), 599 attrs.getValue("id"), 600 attrs.getValue("referto"), 601 attrs.getValue("to"), 602 retries, 603 sleep, 604 attrs.getValue("kind")); 605 606 607 currentOutput.getActionList().add(action); 608 } else { 609 throw new RuntimeException("link must have a \"to\" attribute."); 610 } 611 612 } 613 614 615 private void SandboxElement(String namespaceURI, String sName, String qName, Attributes attrs) { 616 Request request = (Request) requests.get(requests.size() - 1); 617 if(request.getSandbox()!= null){ 618 throw new RuntimeException("You can only have one sand box element."); 619 } 620 if ((attrs.getValue("installer") == null)){ 621 request.setSandbox(new LocalSandbox() ); 622 } 623 else if( attrs.getValue("installer").compareTo("ZIP") == 0 ){ 624 request.setSandbox(new ZipSandbox() ); 625 } 626 else if( attrs.getValue("installer").compareTo("PACMAN") == 0 ){ 627 request.setSandbox(new PackmanSandbox() ); 628 } 629 else { 630 throw new RuntimeException("The sandox installer is unkown !!"); 631 } 632 } 633 634 635 private void PackageElement(String namespaceURI, String sName, String qName, Attributes attrs) { 636 currentPackage = new SandboxPackage(); 637 638 Sandbox sandbox = ((Request) requests.get(requests.size() - 1)).getSandbox(); 639 640 if(sandbox == null){ 641 throw new RuntimeException("Could not make sandbox for Package"); 642 } 643 644 if ((attrs.getValue("name") != null)) { 645 currentPackage.setPackageName(attrs.getValue("name")); 646 } 647 if ((attrs.getValue("repository") != null)) { 648 currentPackage.setRepository(attrs.getValue("repository")); 649 } 650 if ((attrs.getValue("installdir") != null)) { 651 currentPackage.setInstalldir(attrs.getValue("installdir")); 652 } 653 if ((attrs.getValue("version") != null)) { 654 currentPackage.setVersion(attrs.getValue("version")); 655 } 656 657 sandbox.addPackage(currentPackage); 658 } 659 660 661 private void packageFileElement(String file) { 662 663 664 665 if(file.matches("^file\\:((\\.{2,2}/)|(\\./.*/\\.\\./)|(\\./\\.\\./)).*$")){ 666 throw new RuntimeException("Sorry, you are not allowed to have a relative path in your sandbox that has a reference to a parent director, item \"" + file +"\"."); 667 } 668 669 670 if(!file.matches("^file\\:.*$")){ 671 throw new RuntimeException("Files in the sandbox must be in the format of file:[path]\\[fileName]\n" + 672 "Examples:\n" + 673 "file:/bla/bla/myfile.root\n" + 674 "file:./bla/bla/myfile.root\n" + 675 "file:./*.root\n"); 676 } 677 678 679 680 681 682 try{ 683 currentPackage.addFile(new URL(file)); 684 } catch (Exception e) { 685 throw new RuntimeException("the <File> </File> tag is not a URI. \n\n" + 686 "Examples of valid sandbox file formats are:\n" + 687 "file:/bla/bla/myfile.root\n" + 688 "file:./bla/bla/myfile.root\n" + 689 "file:./*.root\n", e); 690 691 } 692 readingFile = false; 693 } 694 /** 695 * Parsing method. This method parses the XML file according to SAX specifications. 696 */ 697 public void startElement(String namespaceURI, String sName, String qName, Attributes attrs) { 698 if (qName.equals("job")) { 699 jobElement(namespaceURI, sName, qName, attrs); 700 } else if (qName.equals("command")) { 701 readingCommand = true; 702 } else if (qName.equals("stdin")) { 703 stdinElement(namespaceURI, sName, qName, attrs); 704 } else if (qName.equals("stdout")) { 705 stdoutElement(namespaceURI, sName, qName, attrs); 706 } else if (qName.equals("stderr")) { 707 stderrElement(namespaceURI, sName, qName, attrs); 708 } else if (qName.equals("input")) { 709 inputElement(namespaceURI, sName, qName, attrs); 710 } else if (qName.equals("output")) { 711 outputElement(namespaceURI, sName, qName, attrs); 712 } else if ((currentOutput != null) && ("copy".equals(qName))) { 713 outputCopyActionElement(namespaceURI, sName, qName, attrs); 714 } else if ((currentOutput != null) && ("register".equals(qName))) { 715 outputCopyRegisterElement(namespaceURI, sName, qName, attrs); 716 } else if ((currentOutput != null) && ("link".equals(qName))) { 717 outputLinkAction(namespaceURI, sName, qName, attrs); 718 } else if (qName.equals("SandBox")) { 719 SandboxElement(namespaceURI, sName, qName, attrs); 720 } else if (qName.equals("Package")) { 721 PackageElement(namespaceURI, sName, qName, attrs); 722 } else if (qName.equals("File")) { 723 readingFile = true; 724 725 726 727 728 } else { 729 throw new RuntimeException("Found element out of the specifications : " + qName); 730 } 731 } 732 733 public void endElement(String uri, String localName, String qName) throws org.xml.sax.SAXException { 734 if ("command".equals(qName)) { 735 flushCommandBuffer(); 736 } 737 if ("output".equals(qName)) { 738 currentOutput = null; 739 } 740 } 741 742 }