1 /* 2 * Copyright (C) 2014 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 //================================================================================================== 18 // 19 // Module Name: DMTValidator 20 // 21 // General Description: The classes contained here provide a depth first recursive traversal of the 22 // Dmt.zip directory heirarchy, and have numerous sanity checks built in which 23 // validate the contents of the parm.txt files that make up the DMT. 24 // 25 //================================================================================================== 26 27 package com.mot.dm.core; 28 29 import java.io.BufferedReader; 30 import java.util.HashMap; 31 import java.util.ArrayList; 32 import java.util.StringTokenizer; 33 import java.util.ListIterator; 34 35 // Joda is an Open Source date/time parsing library (used to parse ISO8601 date/time formats) 36 import org.joda.time.format.DateTimeFormatter; 37 import org.joda.time.format.ISODateTimeFormat; 38 import org.joda.time.DateTime; 39 40 // Jakarta regexp is an Open Source regular expression parsing library. 41 import org.apache.regexp.RE; 42 import org.apache.regexp.RESyntaxException; 43 44 import java.io.Reader; 45 import com.mot.dm.io.Node; 46 import com.mot.dm.io.NodeLoader; 47 48 // Main DMTValidator class 49 public class DMTValidator 50 { 51 private final String[] illegalCharsForNodeName = {"#", "$", "\\", "/", "?", "<", ">", "%", "\"", "|", ":"}; //"&", "!" 52 private int depth = 1; 53 final static private String parm = "parm.txt"; 54 static private String initDir = "D:\\Dmt"; 55 static private ArrayList problemsList = new ArrayList(); 56 private String [] path = new String [20]; 57 58 private static void usage() 59 { 60 System.err.println("Usage: java DMTValidator -d dirName \n" + 61 "\t\t -d : dirName points to the directory where Dmt is located\n"); 62 } 63 64 public static void main(String [] args) throws Exception 65 { 66 if (args.length != 2) 67 { 68 System.err.println("Error: Incorrect number of arguments!"); 69 usage(); 70 System.exit(1); 71 } 72 else 73 { 74 if (args[0].equals("-d")) 75 { 76 initDir = args[1]; 77 } 78 else 79 { 80 System.err.println("Error: No directory specified!"); 81 usage(); 82 System.exit(1); 83 } 84 } 85 86 // Check to make sure the directory we are passed is valid 87 if (!NodeLoader.getInstance(initDir).exists()) 88 { 89 System.err.println("Error: Invalid directory specified!"); 90 usage(); 91 System.exit(1); 92 } 93 94 // Run the validator on our dir structure 95 96 DMTValidator validator = new DMTValidator(); 97 validator.analyzeDir(initDir); 98 99 // Exit with the proper return code, and print out any problems 100 101 if (problemsList.isEmpty()) 102 { 103 //System.out.println("DMT validation passed..."); 104 System.exit(0); 105 } 106 else 107 { 108 ListIterator iterator = problemsList.listIterator(); 109 110 //System.out.println("DM Tree cannot be generated: validation failed!"); 111 112 while (iterator.hasNext()) 113 { 114 System.err.println("Error: " + iterator.next()); 115 } 116 117 System.exit(1); 118 } 119 } 120 121 // Starting point for our tree traversal - called recursively to process the tree 122 public void analyzeDir(String dirName) throws Exception 123 { 124 boolean isLeaf=false; 125 boolean isMultiNode = false; 126 127 // Increment our depth 128 129 depth += 1; 130 131 // Remove leading (leaf) and trailing (reserved name) "#" 132 133 String nodeName; 134 135 if (depth <= 2) 136 { 137 nodeName = "."; 138 } 139 else 140 { 141 nodeName = dirName.substring(dirName.lastIndexOf(System.getProperty("file.separator")) + 1); 142 143 if (nodeName.startsWith("#")) 144 { 145 isLeaf=true; 146 } 147 148 nodeName = nodeName.replace('#', ' '); 149 150 if (nodeName.startsWith("@")) 151 { 152 nodeName = nodeName.substring(1); 153 } 154 155 nodeName = nodeName.trim(); 156 157 if (nodeName.charAt(0) == '[') 158 { 159 nodeName = "*"; 160 isMultiNode = true; 161 } 162 path [depth - 2] = nodeName; 163 } 164 165 // Get the current node path 166 167 String nodepath="."; 168 169 for (int i=1; i<depth-1; i++) 170 { 171 nodepath=nodepath+"/"+path[i]; 172 } 173 174 // Process the directory 175 176 Node directory = NodeLoader.getInstance(dirName); 177 Node[] children = directory.listNodes(); 178 179 // Create our parameters HashMap and access ArrayList 180 181 HashMap parameters = new HashMap(); 182 ArrayList access = new ArrayList(); 183 184 String filename = dirName+"/"+parm; 185 186 // Does the parm file exist? If not, flag it, and continue 187 188 if (NodeLoader.getInstance(filename).exists()) 189 { 190 // Get parameters from the current branch 191 192 try 193 { 194 getParms(filename, parameters, access); 195 } 196 catch (Exception e) 197 { 198 e.printStackTrace(); 199 problemsList.add("Malformed parm.txt file for node: " + nodepath); 200 } 201 202 // DMT VALIDATIONS GO HERE 203 // ======================= 204 205 // ----------------------------------------------------- 206 // Check to see if a valid type is defined for this node 207 // ----------------------------------------------------- 208 209 String nodeType = (String) parameters.get("Type"); 210 211 if (nodeType == null) 212 { 213 problemsList.add("No type defined for node: " + nodepath); 214 } 215 else if (!nodeType.equalsIgnoreCase("int") && !nodeType.equalsIgnoreCase("bool") && 216 !nodeType.equalsIgnoreCase("bin") && !nodeType.equalsIgnoreCase("node") && 217 !nodeType.equalsIgnoreCase("chr") && !nodeType.equalsIgnoreCase("null") && 218 !nodeType.equalsIgnoreCase("test") && !nodeType.equalsIgnoreCase("date") && 219 !nodeType.equalsIgnoreCase("time") && !nodeType.equalsIgnoreCase("float")) 220 221 { 222 problemsList.add("Invalid node type '" + nodeType + "' for the node: " + nodepath + 223 ". The valid types are: 'node', 'int', 'bin', 'chr', 'bool', 'float', 'time', 'date'."); 224 225 } 226 227 // ------------------------------------------------------- 228 // Sanity checks for 'default' MA (format,constraints, etc) 229 // ------------------------------------------------------- 230 231 String defValue = (String) parameters.get("Default"); 232 233 if (defValue != null) 234 { 235 // ----------------------------------------------------- 236 // Do not allow default values for node types: 237 // 'test', 'null', 'node' 238 // ----------------------------------------------------- 239 240 if (nodeType != null && (nodeType.equalsIgnoreCase("test") || nodeType.equalsIgnoreCase("null") || 241 nodeType.equalsIgnoreCase("node"))) 242 { 243 problemsList.add("Default values are not allowed for nodes with type '" + nodeType + "' for the node: " + nodepath + 244 ". The attribute 'default' should be removed"); 245 } 246 247 // Check these values for min/max and other constraints 248 249 checkValues(defValue,parameters,nodepath,nodeType,"Default"); 250 } 251 252 // ------------------------------------------------------- 253 // Make sure that only multi-nodes have storesPD parameter 254 // ------------------------------------------------------- 255 256 if (!isMultiNode && (parameters.get("storesPD") != null)) 257 { 258 problemsList.add("The 'storesPD' attribute is not allowed for the non-multinode: " + nodepath + 259 ". This attribute should be removed."); 260 } 261 262 // -------------------------------------------------------------- 263 // Make sure that 'auto' MA is only used on interior & test nodes 264 // -------------------------------------------------------------- 265 266 if ((parameters.get("auto") != null) && (nodeType != null && !nodeType.equalsIgnoreCase("node")) && 267 (nodeType != null && !nodeType.equalsIgnoreCase("test"))) 268 { 269 problemsList.add("The 'auto' attribute is not allowed for the non-interior node: " + nodepath + 270 ". This attribute should be removed."); 271 } 272 273 // ------------------------------------------------------ 274 // Sanity checks for 'fk' MA (format,constraints, etc) 275 // ------------------------------------------------------ 276 277 String fkStr = (String) parameters.get("fk"); 278 279 if (fkStr != null && (nodeType != null && nodeType.equalsIgnoreCase("node"))) 280 { 281 problemsList.add("The 'fk' attribute is not allowed for the interior node: " + nodepath + 282 ". This attribute should be removed."); 283 } 284 285 if (fkStr != null && fkStr.length() == 0) 286 { 287 problemsList.add("The 'fk' attribute can not be an empty string for the node: " + nodepath + 288 ". This attribute should be removed or value for 'fk' should be set."); 289 } 290 291 // ------------------------------------------------------- 292 // Sanity checks for 'value' MA (format,constraints, etc) 293 // ------------------------------------------------------- 294 295 String value = (String) parameters.get("Value"); 296 297 if (value != null) 298 { 299 if (nodeType != null && nodeType.equalsIgnoreCase("node")) 300 { 301 problemsList.add("The 'value' attribute is not allowed for the interior node: " + nodepath + 302 ". This attribute should be removed."); 303 } 304 305 // Check these values for min/max and other constraints 306 307 checkValues(value,parameters,nodepath,nodeType,"Value"); 308 } 309 310 // -------------------------------------------------------- 311 // Sanity checks for 'values' MA (format,constraints, etc) 312 // -------------------------------------------------------- 313 314 String values = (String) parameters.get("values"); 315 316 if (values != null) 317 { 318 if (nodeType != null && nodeType.equalsIgnoreCase("node")) 319 { 320 problemsList.add("The 'values' attribute is not allowed for the interior node: " + nodepath + 321 ". This attribute should be removed."); 322 } 323 324 // Check these values for min/max and other constraints 325 326 checkValues(values,parameters,nodepath,nodeType,"Values"); 327 328 // Check values and default values against possible values 329 330 if (value != null) 331 { 332 if (values.indexOf(value) == -1) 333 { 334 problemsList.add("Initial value '" + value + 335 "' is not one of the valid values in 'values' constraint '" + 336 values + "' for the node: " + nodepath + 337 ". The attribute 'value' should be set to one of the valid values."); 338 } 339 } 340 341 if (defValue != null) 342 { 343 if (values.indexOf(defValue) == -1) 344 { 345 problemsList.add("Default value '" + defValue + 346 "' is not one of the valid values in 'values' constraint '" + 347 values + "' for node: " + nodepath + 348 ". The attribute 'default' should be set to one of the valid values."); 349 } 350 } 351 } 352 353 // ---------------------------------------------------------------------- 354 // Make sure that 'min' MA is only used on int/float/date/time/test nodes 355 // ---------------------------------------------------------------------- 356 357 if ((parameters.get("min") != null) && (nodeType != null && !nodeType.equalsIgnoreCase("int")) && 358 (nodeType != null && !nodeType.equalsIgnoreCase("test")) && 359 (nodeType != null && !nodeType.equalsIgnoreCase("float")) && 360 (nodeType != null && !nodeType.equalsIgnoreCase("date")) && 361 (nodeType != null && !nodeType.equalsIgnoreCase("time"))) 362 { 363 problemsList.add("The 'min' attribute is not allowed for nodes with type '" + nodeType + "' at the node: " + nodepath + 364 ". This attribute should be removed."); 365 } 366 367 // ---------------------------------------------------------------------- 368 // Make sure that 'max' MA is only used on int/float/date/time/test nodes 369 // ---------------------------------------------------------------------- 370 371 if ((parameters.get("max") != null) && (nodeType != null && !nodeType.equalsIgnoreCase("int")) && 372 (nodeType != null && !nodeType.equalsIgnoreCase("test")) && 373 (nodeType != null && !nodeType.equalsIgnoreCase("float")) && 374 (nodeType != null && !nodeType.equalsIgnoreCase("date")) && 375 (nodeType != null && !nodeType.equalsIgnoreCase("time"))) 376 { 377 problemsList.add("The 'max' attribute is not allowed for nodes with type '" + nodeType + "' at the node: " + nodepath + 378 ". This attribute should be removed."); 379 } 380 381 // --------------------------------------------------------- 382 // Make sure that 'minLen' MA is only used on chr/bin/test nodes 383 // --------------------------------------------------------- 384 385 if ((parameters.get("minLen") != null) && (nodeType != null && !nodeType.equalsIgnoreCase("chr")) && 386 (nodeType != null && !nodeType.equalsIgnoreCase("bin")) && (nodeType != null && !nodeType.equalsIgnoreCase("test"))) 387 { 388 problemsList.add("The 'minLen' attribute not allowed for nodes with type '" + nodeType + "' at the node: " + nodepath + 389 ". This attribute should be removed."); 390 } 391 392 // --------------------------------------------------------- 393 // Make sure that 'maxLen' MA is only used on chr/bin/test nodes 394 // --------------------------------------------------------- 395 396 if ((parameters.get("maxLen") != null) && (nodeType != null && !nodeType.equalsIgnoreCase("chr")) && 397 (nodeType != null && !nodeType.equalsIgnoreCase("bin")) && (nodeType != null && !nodeType.equalsIgnoreCase("test"))) 398 { 399 problemsList.add("The 'maxLen' attribute not allowed for nodes with type '" + nodeType + "' at the node: " + nodepath + 400 ". This attribute should be removed."); 401 } 402 403 // --------------------------------------------------------- 404 // Sanity checks for 'regexp' MA (format,constraints, etc) 405 // --------------------------------------------------------- 406 407 String regexpStr = (String) parameters.get("regexp"); 408 409 if (regexpStr != null && (nodeType != null && !nodeType.equalsIgnoreCase("chr")) && 410 (nodeType != null && !nodeType.equalsIgnoreCase("test"))) 411 { 412 problemsList.add("The 'regexp' attribute not allowed for the non-character node: " + nodepath+ 413 ". This attribute should be removed."); 414 } 415 else if (regexpStr != null && regexpStr.length() == 0) 416 { 417 problemsList.add("The 'regexp' attribute may not be an empty string for the node: " + nodepath + 418 ". This attribute should be removed or value for 'regexp' should be set."); 419 } 420 else if (regexpStr != null) 421 { 422 try 423 { 424 RE regexpValue = new RE(regexpStr); 425 426 // Check default and value MA's against this regular expression 427 428 if (value != null) 429 { 430 if (!regexpValue.match(value)) 431 { 432 problemsList.add("Value attribute '" + value + "' does not match regular expression '" + regexpStr + "' for node: " + nodepath); 433 } 434 } 435 436 if (defValue != null) 437 { 438 if (!regexpValue.match(defValue)) 439 { 440 problemsList.add("Default attribute '" + defValue + "' does not match regular expression '" + regexpStr + "' for node: " + nodepath); 441 } 442 } 443 } 444 catch (RESyntaxException e) 445 { 446 problemsList.add("Invalid regular expression string '" + regexpStr + "' for the node: " + nodepath); 447 } 448 } 449 450 // ---------------------------------------------------- 451 // Checks for 'nMaxLen' MA (format,current nodename) 452 // ---------------------------------------------------- 453 454 String nMaxLenStr = (String) parameters.get("nMaxLen"); 455 456 if (nMaxLenStr != null) 457 { 458 if (nMaxLenStr.length() != 0) 459 { 460 try 461 { 462 int maxIntValue = Integer.parseInt(nMaxLenStr); 463 464 if (nodeName.length() > maxIntValue) 465 { 466 problemsList.add("Node name '" + nodeName + 467 "' is longer than the maximum node name length constraint '" + 468 maxIntValue + "' for the node: " + nodepath); 469 } 470 } 471 catch (NumberFormatException e) 472 { 473 problemsList.add("The attribute nMaxLen has invalid value '" + nMaxLenStr + "' for the node: " + nodepath + 474 ". This attribute should be valid integer from 1 to 2147483647."); 475 } 476 } 477 else 478 { 479 problemsList.add("The attribute nMaxLen may not be an empty string for the node: " + nodepath); 480 } 481 } 482 483 // ---------------------------------------------------- 484 // Checks for 'nValues' MA (format,current nodename) 485 // ---------------------------------------------------- 486 487 String nValuesStr = (String) parameters.get("nValues"); 488 489 if (nValuesStr != null) 490 { 491 if (nValuesStr.length() != 0) 492 { 493 if (nValuesStr.indexOf(nodeName) == -1 && !nodeName.equals("*")) 494 { 495 problemsList.add("Node name '" + nodeName + 496 "' is not one of the valid values in the attribute nValues constraint '" + 497 nValuesStr + "' for the node: " + nodepath); 498 } 499 } 500 else 501 { 502 problemsList.add("The attribute nValues may not be an empty string for node: " + nodepath); 503 } 504 } 505 506 // ---------------------------------------------------- 507 // Checks that file name (current nodename) doesn't contain illegal chars 508 // ---------------------------------------------------- 509 for(int i=0; i<illegalCharsForNodeName.length; i++){ 510 if(nodeName.indexOf(illegalCharsForNodeName[i]) > -1){ 511 problemsList.add("The node name contains illegal char '" + illegalCharsForNodeName[i] + "' for the " + nodepath); 512 } 513 } 514 515 // ---------------------------------------------------- 516 // Checks for 'nRegexp' MA (format,current nodename) 517 // ---------------------------------------------------- 518 519 String nRegexpStr = (String) parameters.get("nRegexp"); 520 521 /* 522 if (nRegexpStr != null && nodeName != "*") 523 { 524 if (nRegexpStr.length() != 0) 525 { 526 try 527 { 528 RE nRegexpValue = new RE(nRegexpStr); 529 530 // Check the nodename against this regular expression 531 532 if (!nRegexpValue.match(nodeName)) 533 { 534 problemsList.add("Node name '" + nodeName + "' does not match regular expression '" + nRegexpStr + "' for node: " + nodepath); 535 } 536 } 537 catch (RESyntaxException e) 538 { 539 problemsList.add("Invalid regular expression string '" + nRegexpStr + "' for node: " + nodepath); 540 } 541 } 542 else 543 { 544 problemsList.add("nRegexp attribute may not be an empty string for node: " + nodepath); 545 } 546 }*/ 547 548 // --------------------------------------------------------- 549 // Make sure that 'access' MA has valid values 550 // --------------------------------------------------------- 551 552 ArrayList accessType = (ArrayList) parameters.get("AccessType"); 553 554 if (accessType == null || accessType.isEmpty()) 555 { 556 problemsList.add("The attribute 'access' is not present for the node: " + nodepath 557 + ". This attribute is required"); 558 } 559 else 560 { 561 Object accessTokens[] = accessType.toArray(); 562 563 for (int i=0;i<accessTokens.length;i++) 564 { 565 if (!((String)accessTokens[i]).equalsIgnoreCase("Add") && 566 !((String)accessTokens[i]).equalsIgnoreCase("Delete") && 567 !((String)accessTokens[i]).equalsIgnoreCase("Get") && 568 !((String)accessTokens[i]).equalsIgnoreCase("Exec")&& 569 !((String)accessTokens[i]).equalsIgnoreCase("Replace")&& 570 !((String)accessTokens[i]).equalsIgnoreCase("Local")) 571 { 572 problemsList.add("Invalid access type '" + accessTokens[i] + "' for node: " + nodepath 573 + ". The valid types are: 'Add', 'Delete', 'Get', 'Replace', 'Exec', 'Local'"); 574 } 575 } 576 } 577 578 //---------------------------------------------------- 579 // Checks for 'store' values (true,false,1,0) and that parms 'default' and 'value' hasn't been set 580 // ---------------------------------------------------- 581 String storeStr = (String) parameters.get("store"); 582 583 if (storeStr != null) 584 { 585 //validate that parms 'default' and 'value' hasn't been set 586 if(parameters.get("Default") != null){ 587 problemsList.add("Attribute 'default' cannot be set with attribute 'store' for the node: " + nodepath); 588 } 589 if(parameters.get("Value") != null){ 590 problemsList.add("Attribute 'value' cannot be set with attribute 'store' for the node: " + nodepath); 591 } 592 593 if (storeStr.length() != 0) 594 { 595 if (!storeStr.equalsIgnoreCase("true") && !storeStr.equalsIgnoreCase("false") && 596 !storeStr.equalsIgnoreCase("1") && !storeStr.equalsIgnoreCase("0")) 597 { 598 problemsList.add("The value '" + storeStr + "' for parm 'store' is not one of the valid values for node: " + nodepath 599 + ". The valid values are: 'true', 'false'"); 600 } 601 } 602 else 603 { 604 problemsList.add("The 'store' attribute may not be an empty string for the node: " + nodepath); 605 } 606 } 607 608 //---------------------------------------------------- 609 // Checks for 'LOBProgressBAR' values (true,false,1,0) and that parm "store" is presented 610 // ---------------------------------------------------- 611 String LOBProgressBARStr = (String) parameters.get("LOBProgressBAR"); 612 613 if (LOBProgressBARStr != null) 614 { 615 //parm 'store' is required and should be true or false 616 if(parameters.get("store") == null){ 617 problemsList.add("The attribute 'LOBProgressBAR' cannot be specified without attribute 'store' for the node: " + nodepath); 618 } 619 else if(!((String) parameters.get("store")).trim().equalsIgnoreCase("true") && 620 !((String) parameters.get("store")).trim().equalsIgnoreCase("1")){ 621 problemsList.add("The attribute 'LOBProgressBAR' can be specified only if attribute 'store' equals 'true' or '1' for the node: " + nodepath); 622 } 623 624 if (LOBProgressBARStr.length() != 0) 625 { 626 if (!LOBProgressBARStr.equalsIgnoreCase("true") && !LOBProgressBARStr.equalsIgnoreCase("false") && 627 !LOBProgressBARStr.equalsIgnoreCase("1") && !LOBProgressBARStr.equalsIgnoreCase("0")) 628 { 629 problemsList.add("The value '" + LOBProgressBARStr + "' for parm 'LOBProgressBAR' is not one of the valid values for the node: " + nodepath 630 + ". The valid values are: 'true', 'false'"); 631 } 632 } 633 else 634 { 635 problemsList.add("The LOBProgressBAR attribute may not be an empty string for node: " + nodepath); 636 } 637 } 638 639 // --------------------------------------------------------- 640 // Make sure that parameter 'event' has valid values 641 // --------------------------------------------------------- 642 ArrayList arrEvents = (ArrayList) parameters.get("Event"); 643 644 if (arrEvents != null && !arrEvents.isEmpty()) 645 { 646 String event; 647 HashMap mapNotifyAndIgnoreVals = new HashMap(); //keeps values for "Notify" and " Ignore" 648 for (int i=0;i<arrEvents.size();i++) 649 { 650 event = (String)arrEvents.get(i); 651 if (!validateEventValues(event, arrEvents, isLeaf, mapNotifyAndIgnoreVals)) 652 { 653 problemsList.add("The attribute 'event' contains invalid value for the node: " + nodepath 654 + ". The valid operations are: 'Add', 'Delete', 'Replace', 'Indirect'. " 655 + " The valid format can be 'Node' or 'Detail' or 'Cumulative' (for interior nodes only)." 656 + " The keys in key=value(s) pairs can be 'Topic' (single), 'Ignore' (list), 'Notify' (list)." 657 + "Sample: Topic=AAA&Notify=BBB&CCC. 'Ignore' and 'Notify' cannot have the same values."); 658 break; 659 } 660 } 661 } 662 663 664 665 666 // --- END OF DMT VALIDATIONS --- 667 } 668 else 669 { 670 problemsList.add("Missing parm.txt file for node: " + nodepath); 671 } 672 673 // Process child directories 674 675 if (children == null) 676 { 677 // Either dir does not exist or is not a directory 678 } 679 else 680 { 681 // process any directories 682 683 for (int ii=0; ii<children.length; ii++) 684 { 685 if (children[ii].isDirectory()) 686 { 687 analyzeDir(children[ii].getAbsolutePath()); 688 } 689 } 690 } 691 692 depth -= 1; 693 } 694 695 // Validate passed in value against empty string criteria, as well as violation of any constraints 696 private void checkValues(String value,HashMap parameters,String nodepath,String nodeType,String type) 697 { 698 if (value.length() != 0) 699 { 700 StringTokenizer valueTokens = new StringTokenizer(value,","); 701 String valueToken; 702 703 while (valueTokens.hasMoreTokens()) 704 { 705 valueToken = valueTokens.nextToken(); 706 707 if (nodeType != null && nodeType.equalsIgnoreCase("int")) 708 { 709 // Attempt to parse this value into an int - if we get a NumberFormat Exception, flag this 710 // as an invalid value. 711 712 boolean validValue = true; 713 int intValue = 0; 714 715 try 716 { 717 intValue = Integer.parseInt(valueToken); 718 } 719 catch (NumberFormatException e) 720 { 721 problemsList.add(" The '" + valueToken + "' is an invalid integer value for the attribute '"+ type 722 + "' for node: " + nodepath + ". The valid value should be an integer from -2147483648 to 2147483647"); 723 validValue = false; 724 } 725 726 // Check this value against any min/max constraints specified for this node 727 728 String minStrValue = (String) parameters.get("min"); 729 730 if (minStrValue != null) 731 { 732 try 733 { 734 int minIntValue = Integer.parseInt(minStrValue); 735 736 if (validValue && intValue < minIntValue) 737 { 738 problemsList.add(type + " attribute '" + valueToken + 739 "' is less than minimum value constraint '" + 740 minStrValue + "' for node: " + nodepath); 741 } 742 } 743 catch (NumberFormatException e) 744 { 745 problemsList.add("Invalid min value '" + minStrValue + "' for node: " + nodepath 746 + ". The valid value should be an integer from -2147483648 to 2147483647"); 747 } 748 } 749 750 String maxStrValue = (String) parameters.get("max"); 751 752 if (maxStrValue != null) 753 { 754 try 755 { 756 int maxIntValue = Integer.parseInt(maxStrValue); 757 758 if (validValue && intValue > maxIntValue) 759 { 760 problemsList.add(type + " attribute '" + valueToken + 761 "' is greater than maximum value constraint '" + 762 maxStrValue + "' for node: " + nodepath); 763 } 764 } 765 catch (NumberFormatException e) 766 { 767 problemsList.add("Invalid max value '" + maxStrValue + "' for node: " + nodepath 768 + ". The valid value should be an integer from -2147483648 to 2147483647"); 769 } 770 } 771 } 772 else if (nodeType != null && nodeType.equalsIgnoreCase("float")) 773 { 774 // Attempt to parse this value into a float - if we get a NumberFormat Exception, flag this 775 // as an invalid value. 776 777 boolean validValue = true; 778 float floatValue = 0; 779 780 try 781 { 782 floatValue = Float.parseFloat(valueToken); 783 } 784 catch (NumberFormatException e) 785 { 786 problemsList.add(type + " attribute '" + valueToken + "' is an invalid float value for node: " + nodepath); 787 validValue = false; 788 } 789 790 // Check this value against any min/max constraints specified for this node 791 792 String minStrValue = (String) parameters.get("min"); 793 794 if (minStrValue != null) 795 { 796 try 797 { 798 float minFloatValue = Float.parseFloat(minStrValue); 799 800 if (validValue && floatValue < minFloatValue) 801 { 802 problemsList.add(type + " attribute '" + valueToken + 803 "' is less than minimum value constraint '" + 804 minStrValue + "' for node: " + nodepath); 805 } 806 } 807 catch (NumberFormatException e) 808 { 809 problemsList.add("The attribute 'min' contains invalid float value '" + minStrValue + "' for the node: " + nodepath); 810 } 811 } 812 813 String maxStrValue = (String) parameters.get("max"); 814 815 if (maxStrValue != null) 816 { 817 try 818 { 819 float maxFloatValue = Float.parseFloat(maxStrValue); 820 821 if (validValue && floatValue > maxFloatValue) 822 { 823 problemsList.add(type + " attribute '" + valueToken + 824 "' is greater than maximum value constraint '" + 825 maxStrValue + "' for node: " + nodepath); 826 } 827 } 828 catch (NumberFormatException e) 829 { 830 problemsList.add("The attribute 'max' contains invalid float value '" + maxStrValue + "' for the node: " + nodepath); 831 } 832 } 833 } 834 else if (nodeType != null && nodeType.equalsIgnoreCase("date")) 835 { 836 // Attempt to parse this value into a date - if we get an IllegalArgument Exception, flag this 837 // as an invalid value. 838 839 boolean validValue = true; 840 DateTimeFormatter fmt = ISODateTimeFormat.dateParser(); 841 DateTime dateValue = null; 842 843 try 844 { 845 dateValue = fmt.parseDateTime(valueToken); 846 } 847 catch (IllegalArgumentException e) 848 { 849 problemsList.add(type + " attribute '" + valueToken + "' is an invalid date value for node: " + nodepath 850 + ". The valid value type 'date' should be in the one of valid ISO8601 formats, for example 'YYYY-MM-DD', 'YYYY-MM', 'YYY-DDD', 'YYYY-Wxx-d', 'YYYYMMDD', etc."); 851 validValue = false; 852 } 853 854 // Check this value against any min/max constraints specified for this node 855 856 String minStrValue = (String) parameters.get("min"); 857 858 if (minStrValue != null) 859 { 860 try 861 { 862 DateTime minDateValue = fmt.parseDateTime(minStrValue); 863 864 if (validValue && dateValue.isBefore(minDateValue)) 865 { 866 problemsList.add(type + " attribute '" + valueToken + 867 "' is less than minimum value constraint '" + 868 minStrValue + "' for node: " + nodepath); 869 } 870 } 871 catch (IllegalArgumentException e) 872 { 873 problemsList.add("The attribute 'min' contains invalid value '" + minStrValue + "' for the node: " + nodepath 874 + ". The valid value type 'date' should be in the one of valid ISO8601 formats, for example 'YYYY-MM-DD', 'YYYY-MM', 'YYY-DDD', 'YYYY-Wxx-d', 'YYYYMMDD', etc."); 875 } 876 } 877 878 String maxStrValue = (String) parameters.get("max"); 879 880 if (maxStrValue != null) 881 { 882 try 883 { 884 DateTime maxDateValue = fmt.parseDateTime(maxStrValue); 885 886 if (validValue && dateValue.isAfter(maxDateValue)) 887 { 888 problemsList.add(type + " attribute '" + valueToken + 889 "' is greater than maximum value constraint '" + 890 maxStrValue + "' for node: " + nodepath); 891 } 892 } 893 catch (IllegalArgumentException e) 894 { 895 problemsList.add("The attribute 'max' contains invalid value '" + maxStrValue + "' for the node: " + nodepath 896 + ". The valid value type 'date' should be in the one of valid ISO8601 formats, for example 'YYYY-MM-DD', 'YYYY-MM', 'YYY-DDD', 'YYYY-Wxx-d', 'YYYYMMDD', etc."); 897 } 898 } 899 } 900 else if (nodeType != null && nodeType.equalsIgnoreCase("time")) 901 { 902 // Attempt to parse this value into a time - if we get an IllegalArgument Exception, flag this 903 // as an invalid value. 904 905 boolean validValue = true; 906 DateTimeFormatter fmt = ISODateTimeFormat.timeParser(); 907 DateTime timeValue = null; 908 909 try 910 { 911 timeValue = fmt.parseDateTime(valueToken); 912 } 913 catch (IllegalArgumentException e) 914 { 915 problemsList.add(type + " attribute '" + valueToken + "' is an invalid time value for node: " + nodepath 916 + ". The valid value type 'time' should be in the one of valid ISO8601 formats, for example 'hh:mm:ss', 'hh:mm', 'hhmmss', 'hhmm', 'hh', etc."); 917 validValue = false; 918 } 919 920 // Check this value against any min/max constraints specified for this node 921 922 String minStrValue = (String) parameters.get("min"); 923 924 if (minStrValue != null) 925 { 926 try 927 { 928 DateTime minTimeValue = fmt.parseDateTime(minStrValue); 929 930 if (validValue && timeValue.isBefore(minTimeValue)) 931 { 932 problemsList.add(type + " attribute '" + valueToken + 933 "' is less than minimum value constraint '" + 934 minStrValue + "' for node: " + nodepath); 935 } 936 } 937 catch (IllegalArgumentException e) 938 { 939 problemsList.add("The attribute 'min' contains invalid value '" + minStrValue + "' for the node: " + nodepath 940 + ". The valid value type 'time' should be in the one of valid ISO8601 formats, for example 'hh:mm:ss', 'hh:mm', 'hhmmss', 'hhmm', 'hh', etc."); 941 } 942 } 943 944 String maxStrValue = (String) parameters.get("max"); 945 946 if (maxStrValue != null) 947 { 948 try 949 { 950 DateTime maxTimeValue = fmt.parseDateTime(maxStrValue); 951 952 if (validValue && timeValue.isAfter(maxTimeValue)) 953 { 954 problemsList.add(type + " attribute '" + valueToken + 955 "' is greater than maximum value constraint '" + 956 maxStrValue + "' for node: " + nodepath); 957 } 958 } 959 catch (IllegalArgumentException e) 960 { 961 problemsList.add("The attribute 'min' contains invalid value '" + maxStrValue + "' for the node: " + nodepath 962 + ". The valid value type 'time' should be in the one of valid ISO8601 formats, for example 'hh:mm:ss', 'hh:mm', 'hhmmss', 'hhmm', 'hh', etc."); 963 } 964 } 965 } 966 else if (nodeType != null && nodeType.equalsIgnoreCase("chr")) 967 { 968 // Checks for min/maxLength violations 969 970 String minLenValue = (String) parameters.get("minLen"); 971 972 if (minLenValue != null) 973 { 974 try 975 { 976 int minLenIntValue = Integer.parseInt(minLenValue); 977 978 if (valueToken.length() < minLenIntValue) 979 { 980 problemsList.add(type + " attribute '" + valueToken + 981 "' is less than minimum length value constraint '" + 982 minLenValue + "' for node: " + nodepath); 983 } 984 } 985 catch (NumberFormatException e) 986 { 987 problemsList.add("Invalid minLen value '" + minLenValue + "' for node: " + nodepath); 988 } 989 } 990 991 String maxLenValue = (String) parameters.get("maxLen"); 992 993 if (maxLenValue != null) 994 { 995 try 996 { 997 int maxLenIntValue = Integer.parseInt(maxLenValue); 998 999 if (valueToken.length() > maxLenIntValue) 1000 { 1001 problemsList.add(type + " attribute '" + valueToken + 1002 "' is greater than maximum length value constraint: '" + 1003 maxLenValue + "' for node: " + nodepath); 1004 } 1005 } 1006 catch (NumberFormatException e) 1007 { 1008 problemsList.add("Invalid maxLen value '" + maxLenValue + "' for node: " + nodepath); 1009 } 1010 } 1011 } 1012 else if (nodeType != null && nodeType.equalsIgnoreCase("bin")) 1013 { 1014 //Check for the correct binary value 1015 1016 if (valueToken.length() % 2 > 0) { 1017 problemsList.add("The attribute '" + type.toLowerCase() + "' for the node " + nodepath 1018 + " contains invalid binary value '" + valueToken + "'. \n" 1019 + "The valid value should be a string with the following constrains: \n" 1020 + " - No empty spaces and leadings '0x' and '%'; \n" 1021 + " - The length of the value should be even number; \n" 1022 + " - Value may contain only digits form '0' to '9' and letters from 'A' to 'F' ('a' to 'f'); \n" 1023 + "Sample: 0130AB0fc33d"); 1024 }else{ 1025 try 1026 { 1027 String tmp; 1028 for (int i = 0; i < valueToken.length() - 1; i++) { 1029 tmp = valueToken.substring(i, i+2); 1030 Integer.parseInt(tmp, 16); 1031 i++; 1032 } 1033 }catch(NumberFormatException e){ 1034 problemsList.add("The attribute '" + type.toLowerCase() + "' for the node " + nodepath 1035 + " contains invalid binary value '" + valueToken + "'. \n" 1036 + "The valid value should be a string with the following constrains: \n" 1037 + " - No empty spaces and leadings '0x' and '%'; \n" 1038 + " - The length of the value should be even number; \n" 1039 + " - Value may contain only digits form '0' to '9' and letters from 'A' to 'F' ('a' to 'f'); \n" 1040 + "Sample: 0130AB0fc33d"); 1041 } 1042 } 1043 // Checks for min/maxLength violations. Compare with 1/2 length of the string representation 1044 1045 String minLenValue = (String) parameters.get("minLen"); 1046 1047 if (minLenValue != null) 1048 { 1049 try 1050 { 1051 int minLenIntValue = Integer.parseInt(minLenValue); 1052 1053 if ((valueToken.length())/2 < minLenIntValue) 1054 { 1055 problemsList.add(type + " attribute '" + valueToken + 1056 "' is less than minimum length value constraint '" + 1057 minLenValue + "' for node: " + nodepath); 1058 } 1059 } 1060 catch (NumberFormatException e) 1061 { 1062 problemsList.add("Invalid minLen value '" + minLenValue + "' for node: " + nodepath); 1063 } 1064 } 1065 1066 String maxLenValue = (String) parameters.get("maxLen"); 1067 1068 if (maxLenValue != null) 1069 { 1070 try 1071 { 1072 int maxLenIntValue = Integer.parseInt(maxLenValue); 1073 1074 if ((valueToken.length())/2 > maxLenIntValue) 1075 { 1076 problemsList.add(type + " attribute '" + valueToken + 1077 "' is greater than maximum length value constraint: '" + 1078 maxLenValue + "' for node: " + nodepath); 1079 } 1080 } 1081 catch (NumberFormatException e) 1082 { 1083 problemsList.add("Invalid maxLen value '" + maxLenValue + "' for node: " + nodepath); 1084 } 1085 } 1086 } 1087 } 1088 } 1089 else 1090 { 1091 if(!"Value".equalsIgnoreCase(type)){ 1092 problemsList.add(type + " attribute may not be an empty string for the node: " + nodepath); 1093 } 1094 } 1095 } 1096 1097 // Utility function to remove spaces in a comma-seperated list (for values MA) 1098 private String removeSpaces(String line) 1099 { 1100 int i = 0; 1101 1102 if ((i = line.indexOf(' ', i)) >= 0) 1103 { 1104 char [] line2 = line.toCharArray(); 1105 StringBuffer buf = new StringBuffer(line2.length); 1106 buf.append(line2, 0, i).append(""); 1107 1108 i++; 1109 int j = i; 1110 1111 while ((i = line.indexOf(' ', i)) > 0) 1112 { 1113 buf.append(line2, j, i - j).append(""); 1114 i++; 1115 j = i; 1116 } 1117 1118 buf.append(line2, j, line2.length - j); 1119 return buf.toString(); 1120 } 1121 1122 return line; 1123 } 1124 1125 // Utility function to parse the contents of parm.txt files in each DMT directory 1126 private void getParms(String fileName,HashMap parameters,ArrayList access) throws Exception 1127 { 1128 Reader reader = NodeLoader.getReader(fileName); 1129 BufferedReader in = new BufferedReader(reader); 1130 String line; 1131 1132 try 1133 { 1134 while ((line = in.readLine()) != null) 1135 { 1136 if(line.trim().length() == 0 || line.trim().startsWith("#")){ 1137 continue; 1138 } 1139 1140 int nameBoundary = line.indexOf(":"); 1141 if(nameBoundary <= 0){ 1142 problemsList.add("The line '"+line+"' doesn't contain ':' simbol in the file " + fileName 1143 + ". The valid attribute/value pair should be separated by ':'."); 1144 continue; 1145 } 1146 1147 String parmName = line.substring(0,nameBoundary); 1148 String parmValue = line.substring(nameBoundary + 1); 1149 1150 // if(parmValue == null || parmValue.trim().length() == 0){ 1151 // problemsList.add("The line '"+line+"' doesn't contain any value after simbol ':' in the file " + fileName + ". Please add value or remove unused parameter."); 1152 // } 1153 if (parmName.equalsIgnoreCase("type")) 1154 { 1155 if (parmValue.equalsIgnoreCase("boolean")) 1156 { 1157 parmValue="bool"; 1158 } 1159 1160 parameters.put("Type", parmValue.trim()); 1161 } 1162 1163 else if (parmName.equalsIgnoreCase("storesPD")) 1164 { 1165 parameters.put("storesPD",parmValue.trim()); 1166 } 1167 1168 else if (parmName.equalsIgnoreCase("HandledByPlugin")) 1169 { 1170 parameters.put("HandledByPlugin",parmValue.trim()); 1171 } 1172 1173 else if (parmName.equalsIgnoreCase("ID")) 1174 { 1175 parameters.put("ID",parmValue.trim()); 1176 } 1177 1178 else if (parmName.equalsIgnoreCase("minLen")) 1179 { 1180 parameters.put("minLen",parmValue.trim()); 1181 } 1182 1183 else if (parmName.equalsIgnoreCase("maxLen")) 1184 { 1185 parameters.put("maxLen",parmValue.trim()); 1186 } 1187 1188 else if (parmName.equalsIgnoreCase("maxChild")) 1189 { 1190 parameters.put("maxChild",parmValue.trim()); 1191 } 1192 1193 else if (parmName.equalsIgnoreCase("min")) 1194 { 1195 parameters.put("min",parmValue.trim()); 1196 } 1197 1198 else if (parmName.equalsIgnoreCase("max")) 1199 { 1200 parameters.put("max",parmValue.trim()); 1201 } 1202 1203 else if (parmName.equalsIgnoreCase("values")) 1204 { 1205 parameters.put("values",trimSepSpaces(parmValue)); 1206 } 1207 1208 else if (parmName.equalsIgnoreCase("regexp")) 1209 { 1210 parameters.put("regexp",parmValue.trim()); 1211 } 1212 1213 else if (parmName.equalsIgnoreCase("nMaxLen")) 1214 { 1215 parameters.put("nMaxLen",parmValue.trim()); 1216 } 1217 1218 else if (parmName.equalsIgnoreCase("nValues")) 1219 { 1220 parameters.put("nValues",removeSpaces(parmValue.trim())); 1221 } 1222 1223 else if (parmName.equalsIgnoreCase("nRegexp")) 1224 { 1225 parameters.put("nRegexp",parmValue.trim()); 1226 } 1227 1228 else if (parmName.equalsIgnoreCase("auto")) 1229 { 1230 parameters.put("auto",parmValue.trim()); 1231 } 1232 1233 else if (parmName.equalsIgnoreCase("fk")) 1234 { 1235 parameters.put("fk",parmValue.trim()); 1236 } 1237 1238 else if (parmName.equalsIgnoreCase("child")) 1239 { 1240 parameters.put("child",removeSpaces(parmValue.trim())); 1241 } 1242 1243 else if (parmName.equalsIgnoreCase("depend")) 1244 { 1245 parameters.put("depend",parmValue.trim()); 1246 } 1247 1248 else if (parmName.equalsIgnoreCase("recur-after-segment")) 1249 { 1250 parameters.put("recur-after-segment",parmValue.trim()); 1251 } 1252 1253 else if (parmName.equalsIgnoreCase("max-recurrence")) 1254 { 1255 parameters.put("max-recurrence",parmValue.trim()); 1256 } 1257 1258 else if (parmName.equalsIgnoreCase("acl")) 1259 { 1260 parameters.put("Acl", parmValue.trim()); 1261 } 1262 1263 else if (parmName.equalsIgnoreCase("event")) 1264 { 1265 ArrayList arrEvents = new ArrayList(); 1266 if(parmValue.trim().indexOf(' ') > -1){ 1267 arrEvents.add(parmValue.trim()); //error... cannot contain empty space... will be handled later 1268 } 1269 else{ 1270 StringTokenizer tok = new StringTokenizer(parmValue.trim(), "&"); 1271 while (tok.hasMoreTokens()) 1272 { 1273 String event = tok.nextToken().trim(); 1274 arrEvents.add(event); 1275 } 1276 } 1277 parameters.put("Event", arrEvents); 1278 } 1279 1280 else if (parmName.equalsIgnoreCase("default")) 1281 { 1282 parameters.put("Default", parmValue.trim()); 1283 } 1284 1285 else if (parmName.equalsIgnoreCase("value")) 1286 { 1287 parameters.put("Value", parmValue.trim()); 1288 } 1289 1290 else if (parmName.equalsIgnoreCase("mime")) 1291 { 1292 parameters.put("Mime", parmValue.trim()); 1293 } 1294 1295 else if (parmName.equalsIgnoreCase("access")) 1296 { 1297 StringTokenizer tok = new StringTokenizer(parmValue, ","); 1298 ArrayList tmpAccess = new ArrayList(); 1299 1300 while (tok.hasMoreTokens()) 1301 { 1302 String accessType = tok.nextToken().trim(); 1303 tmpAccess.add(accessType); 1304 } 1305 parameters.put("AccessType", tmpAccess); 1306 } 1307 1308 else if (parmName.equalsIgnoreCase("nodatagen")) 1309 { 1310 parameters.put("DataGen", new Boolean(false)); 1311 } 1312 1313 else if (parmName.equalsIgnoreCase("nometagen")) 1314 { 1315 parameters.put("MetaGen", new Boolean(false)); 1316 } 1317 1318 else if (parmName.equalsIgnoreCase("store")) 1319 { 1320 parameters.put("store",parmValue.trim()); 1321 } 1322 1323 else if (parmName.equalsIgnoreCase("LOBProgressBAR")) 1324 { 1325 parameters.put("LOBProgressBAR",parmValue.trim()); 1326 } 1327 1328 else if (parmName.equalsIgnoreCase("description")) 1329 { 1330 String docstr = parmValue; 1331 while ((line = in.readLine()) != null) 1332 docstr += line; 1333 parameters.put("Description", docstr); 1334 continue; 1335 } 1336 else{ 1337 problemsList.add("The attribute name '" + parmName + "' is not supported in the file: " + fileName); 1338 } 1339 }// while loop 1340 }finally{ 1341 try 1342 { 1343 in.close(); 1344 }catch(Exception e){} 1345 try 1346 { 1347 reader.close(); 1348 }catch(Exception e){} 1349 1350 in = null; 1351 reader = null; 1352 } 1353 } 1354 1355 private String trimSepSpaces(String parmValue) throws Exception { 1356 String sep = ","; 1357 StringTokenizer tok = new StringTokenizer(parmValue, sep); 1358 StringBuffer sb = new StringBuffer(); 1359 String tmp; 1360 while (tok.hasMoreTokens()) 1361 { 1362 tmp = tok.nextToken().trim(); 1363 if(sb.length() > 0){ 1364 tmp = sep + tmp; 1365 } 1366 sb.append(tmp); 1367 1368 } 1369 return sb.toString(); 1370 } 1371 1372 //validate values from attribute event 1373 private boolean validateEventValues(String event, ArrayList arrEvents, 1374 boolean isLeaf, HashMap mapNotifyAndIgnoreVals){ 1375 1376 if(event.indexOf(' ') > -1){ 1377 return false; //not allow empty spaces... 1378 } 1379 else if("Add".equals(event) || "Delete".equals(event) || 1380 "Replace".equals(event) || "Indirect".equals(event) ){ 1381 return true; 1382 } 1383 else if("Node".equals(event)){ 1384 if(arrEvents.contains("Detail") || arrEvents.contains("Cumulative")){ // cannot be together with "Node" 1385 return false; 1386 } 1387 else{ 1388 return true; 1389 } 1390 } 1391 else if("Detail".equals(event)){ 1392 if(arrEvents.contains("Node") || arrEvents.contains("Cumulative")){ // cannot be together with "Detail" 1393 return false; 1394 } 1395 else{ 1396 return true; 1397 } 1398 } 1399 else if("Cumulative".equals(event)){ 1400 if(arrEvents.contains("Detail") || arrEvents.contains("Node") || isLeaf){ // cannot be together with "Cumulative" and interior nodes only 1401 return false; 1402 } 1403 else{ 1404 return true; 1405 } 1406 } 1407 else if(event.startsWith("Topic=")){ 1408 if (event.length() > "Topic=".length()){ 1409 return true; // check if has value like Topic=ABC 1410 }else{ 1411 return false; 1412 } 1413 } 1414 else if(event.startsWith("Ignore=") || event.startsWith("Notify=")){ 1415 // !!! length of "Ignore=" and "Notify=" is the same and equals 7 !!!! 1416 if (event.length() == 7){ 1417 return false; // check that value is not empty like Ignore= 1418 }else{ 1419 String vals = event.substring(7); 1420 StringTokenizer tok = new StringTokenizer(vals, "+"); 1421 String tmp; 1422 while (tok.hasMoreTokens()){ 1423 tmp = tok.nextToken(); 1424 if(mapNotifyAndIgnoreVals.containsKey(tmp.toUpperCase())){ 1425 return false; // This value for key "Ignore" or "Notify" already has been used 1426 } 1427 else{ 1428 mapNotifyAndIgnoreVals.put(tmp.toUpperCase(), tmp.toUpperCase()); 1429 } 1430 } 1431 return true; 1432 } 1433 } 1434 else { 1435 return false; // unsupported parameter for attribute 'event' 1436 } 1437 } 1438 } 1439