Changeset 11682 in josm for trunk/tools
- Timestamp:
- 2017-03-05T01:25:59+01:00 (8 years ago)
- Location:
- trunk/tools/japicc
- Files:
-
- 22 added
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/tools/japicc/japi-compliance-checker.pl
r10845 r11682 1 1 #!/usr/bin/perl 2 2 ########################################################################### 3 # Java API Compliance Checker (JAPICC) 1.83 # Java API Compliance Checker (JAPICC) 2.1 4 4 # A tool for checking backward compatibility of a Java library API 5 5 # 6 6 # Written by Andrey Ponomarenko 7 7 # 8 # Copyright (C) 2011 Institute for System Programming, RAS 9 # Copyright (C) 2011-2016 Andrey Ponomarenko's ABI Laboratory 8 # Copyright (C) 2011-2017 Andrey Ponomarenko's ABI Laboratory 10 9 # 11 10 # PLATFORMS … … 40 39 use File::Path qw(mkpath rmtree); 41 40 use File::Temp qw(tempdir); 42 use File::Copy qw(copy); 43 use File::Spec::Functions qw(abs2rel); 41 use File::Basename qw(dirname); 44 42 use Cwd qw(abs_path cwd); 45 43 use Data::Dumper; 46 use Digest::MD5 qw(md5_hex); 47 use Config; 48 49 my $TOOL_VERSION = "1.8"; 50 my $API_DUMP_VERSION = "2.0"; 51 my $API_DUMP_MAJOR = majorVersion($API_DUMP_VERSION); 52 53 my ($Help, $ShowVersion, %Descriptor, $TargetLibraryName, $CheckSeparately, 54 $TestSystem, $DumpAPI, $ClassListPath, $ClientPath, $StrictCompat, 55 $DumpVersion, $BinaryOnly, $TargetTitle, %TargetVersion, $SourceOnly, 56 $ShortMode, $KeepInternal, $OutputReportPath, $BinaryReportPath, 57 $SourceReportPath, $Debug, $Quick, $SortDump, $SkipDeprecated, $SkipClassesList, 58 $ShowAccess, $AffectLimit, $JdkPath, $SkipInternalPackages, $HideTemplates, 59 $HidePackages, $ShowPackages, $Minimal, $AnnotationsListPath, 60 $SkipPackagesList, $OutputDumpPath, $AllAffected, $Compact, 61 $SkipAnnotationsListPath, $ExternCss, $ExternJs, $SkipInternalTypes, 62 $AddedAnnotations, $RemovedAnnotations, $CountMethods, %DepDump, $OldStyle); 63 64 my $CmdName = get_filename($0); 65 my $OSgroup = get_OSgroup(); 66 my $ORIG_DIR = cwd(); 67 my $TMP_DIR = tempdir(CLEANUP=>1); 68 my $ARG_MAX = get_ARG_MAX(); 69 my $REPRODUCIBLE = 1; 70 my $MD5_LEN = 8; 71 72 my %OS_Archive = ( 73 "windows"=>"zip", 74 "default"=>"tar.gz" 75 ); 76 77 my %ERROR_CODE = ( 78 # Compatible verdict 79 "Compatible"=>0, 80 "Success"=>0, 81 # Incompatible verdict 82 "Incompatible"=>1, 83 # Undifferentiated error code 84 "Error"=>2, 85 # System command is not found 86 "Not_Found"=>3, 87 # Cannot access input files 88 "Access_Error"=>4, 89 # Invalid input API dump 90 "Invalid_Dump"=>7, 91 # Incompatible version of API dump 92 "Dump_Version"=>8, 93 # Cannot find a module 94 "Module_Error"=>9 95 ); 44 45 my $TOOL_VERSION = "2.1"; 46 my $API_DUMP_VERSION = "2.1"; 47 my $API_DUMP_VERSION_MIN = "2.0"; 48 49 # Internal modules 50 my $MODULES_DIR = getModules(); 51 push(@INC, dirname($MODULES_DIR)); 52 53 # Basic modules 54 my %LoadedModules = (); 55 loadModule("Basic"); 56 loadModule("Input"); 57 loadModule("Path"); 58 loadModule("Logging"); 59 loadModule("Utils"); 60 loadModule("TypeAttr"); 61 loadModule("Filter"); 62 loadModule("SysFiles"); 63 loadModule("Descriptor"); 64 loadModule("Mangling"); 65 66 # Rules DB 67 my %RULES_PATH = ( 68 "Binary" => $MODULES_DIR."/RulesBin.xml", 69 "Source" => $MODULES_DIR."/RulesSrc.xml"); 70 71 my $CmdName = getFilename($0); 96 72 97 73 my %HomePage = ( 98 74 "Dev"=>"https://github.com/lvc/japi-compliance-checker", 99 " Wiki"=>"http://ispras.linuxbase.org/index.php/Java_API_Compliance_Checker"75 "Doc"=>"https://lvc.github.io/japi-compliance-checker/" 100 76 ); 101 77 102 78 my $ShortUsage = "Java API Compliance Checker (JAPICC) $TOOL_VERSION 103 79 A tool for checking backward compatibility of a Java library API 104 Copyright (C) 201 6Andrey Ponomarenko's ABI Laboratory80 Copyright (C) 2017 Andrey Ponomarenko's ABI Laboratory 105 81 License: GNU LGPL or GNU GPL 106 82 … … 116 92 } 117 93 118 GetOptions("h|help!" => \$ Help,119 "v|version!" => \$ ShowVersion,120 "dumpversion!" => \$ DumpVersion,94 GetOptions("h|help!" => \$In::Opt{"Help"}, 95 "v|version!" => \$In::Opt{"ShowVersion"}, 96 "dumpversion!" => \$In::Opt{"DumpVersion"}, 121 97 # general options 122 "l|lib|library=s" => \$ TargetLibraryName,123 "d1|old|o=s" => \$ Descriptor{1}{"Path"},124 "d2|new|n=s" => \$ Descriptor{2}{"Path"},98 "l|lib|library=s" => \$In::Opt{"TargetLib"}, 99 "d1|old|o=s" => \$In::Desc{1}{"Path"}, 100 "d2|new|n=s" => \$In::Desc{2}{"Path"}, 125 101 # extra options 126 "client|app=s" => \$ ClientPath,127 "binary|bin!" => \$ BinaryOnly,128 "source|src!" => \$ SourceOnly,129 "v1|version1|vnum=s" => \$ TargetVersion{1},130 "v2|version2=s" => \$ TargetVersion{2},131 "s|strict!" => \$ StrictCompat,132 "keep-internal!" => \$ KeepInternal,133 "skip-internal-packages|skip-internal=s" => \$ SkipInternalPackages,134 "skip-internal-types=s" => \$ SkipInternalTypes,135 "dump|dump-api=s" => \$ DumpAPI,136 "classes-list=s" => \$ ClassListPath,137 "annotations-list=s" => \$ AnnotationsListPath,138 "skip-annotations-list=s" => \$ SkipAnnotationsListPath,139 "skip-deprecated!" => \$ SkipDeprecated,140 "skip-classes=s" => \$ SkipClassesList,141 "skip-packages=s" => \$ SkipPackagesList,142 "short" => \$ ShortMode,143 "dump-path=s" => \$ OutputDumpPath,144 "report-path=s" => \$ OutputReportPath,145 "bin-report-path=s" => \$ BinaryReportPath,146 "src-report-path=s" => \$ SourceReportPath,147 "quick!" => \$ Quick,148 "sort!" => \$ SortDump,149 "show-access!" => \$ ShowAccess,150 "limit-affected=s" => \$ AffectLimit,151 "hide-templates!" => \$ HideTemplates,152 "show-packages!" => \$ ShowPackages,153 "compact!" => \$ Compact,154 "added-annotations!" => \$ AddedAnnotations,155 "removed-annotations!" => \$ RemovedAnnotations,156 "count-methods=s" => \$ CountMethods,157 "dep1=s" => \$ DepDump{1},158 "dep2=s" => \$ DepDump{2},159 "old-style!" => \$ OldStyle,102 "client|app=s" => \$In::Opt{"ClientPath"}, 103 "binary|bin!" => \$In::Opt{"BinaryOnly"}, 104 "source|src!" => \$In::Opt{"SourceOnly"}, 105 "v1|version1|vnum=s" => \$In::Desc{1}{"TargetVersion"}, 106 "v2|version2=s" => \$In::Desc{2}{"TargetVersion"}, 107 "s|strict!" => \$In::Opt{"StrictCompat"}, 108 "keep-internal!" => \$In::Opt{"KeepInternal"}, 109 "skip-internal-packages|skip-internal=s" => \$In::Opt{"SkipInternalPackages"}, 110 "skip-internal-types=s" => \$In::Opt{"SkipInternalTypes"}, 111 "dump|dump-api=s" => \$In::Opt{"DumpAPI"}, 112 "classes-list=s" => \$In::Opt{"ClassListPath"}, 113 "annotations-list=s" => \$In::Opt{"AnnotationsListPath"}, 114 "skip-annotations-list=s" => \$In::Opt{"SkipAnnotationsListPath"}, 115 "skip-deprecated!" => \$In::Opt{"SkipDeprecated"}, 116 "skip-classes=s" => \$In::Opt{"SkipClassesList"}, 117 "skip-packages=s" => \$In::Opt{"SkipPackagesList"}, 118 "short" => \$In::Opt{"ShortMode"}, 119 "dump-path=s" => \$In::Opt{"OutputDumpPath"}, 120 "report-path=s" => \$In::Opt{"OutputReportPath"}, 121 "bin-report-path=s" => \$In::Opt{"BinaryReportPath"}, 122 "src-report-path=s" => \$In::Opt{"SourceReportPath"}, 123 "quick!" => \$In::Opt{"Quick"}, 124 "sort!" => \$In::Opt{"SortDump"}, 125 "show-access!" => \$In::Opt{"ShowAccess"}, 126 "limit-affected=s" => \$In::Opt{"AffectLimit"}, 127 "hide-templates!" => \$In::Opt{"HideTemplates"}, 128 "show-packages!" => \$In::Opt{"ShowPackages"}, 129 "compact!" => \$In::Opt{"Compact"}, 130 "added-annotations!" => \$In::Opt{"AddedAnnotations"}, 131 "removed-annotations!" => \$In::Opt{"RemovedAnnotations"}, 132 "count-methods=s" => \$In::Opt{"CountMethods"}, 133 "dep1=s" => \$In::Desc{1}{"DepDump"}, 134 "dep2=s" => \$In::Desc{2}{"DepDump"}, 135 "old-style!" => \$In::Opt{"OldStyle"}, 160 136 # other options 161 "test!" => \$ TestSystem,162 "debug!" => \$ Debug,163 "title=s" => \$ TargetTitle,164 "jdk-path=s" => \$ JdkPath,165 "external-css=s" => \$ ExternCss,166 "external-js=s" => \$ ExternJs,137 "test!" => \$In::Opt{"TestTool"}, 138 "debug!" => \$In::Opt{"Debug"}, 139 "title=s" => \$In::Opt{"TargetTitle"}, 140 "jdk-path=s" => \$In::Opt{"JdkPath"}, 141 "external-css=s" => \$In::Opt{"ExternCss"}, 142 "external-js=s" => \$In::Opt{"ExternJs"}, 167 143 # deprecated 168 "minimal!" => \$ Minimal,169 "hide-packages!" => \$ HidePackages,144 "minimal!" => \$In::Opt{"Minimal"}, 145 "hide-packages!" => \$In::Opt{"HidePackages"}, 170 146 # private 171 "all-affected!" => \$ AllAffected172 ) or ERR_MESSAGE();147 "all-affected!" => \$In::Opt{"AllAffected"} 148 ) or errMsg(); 173 149 174 150 if(@ARGV) … … 176 152 if($#ARGV==1) 177 153 { # japi-compliance-checker OLD.jar NEW.jar 178 $ Descriptor{1}{"Path"} = $ARGV[0];179 $ Descriptor{2}{"Path"} = $ARGV[1];154 $In::Desc{1}{"Path"} = $ARGV[0]; 155 $In::Desc{2}{"Path"} = $ARGV[1]; 180 156 } 181 157 else { 182 ERR_MESSAGE();183 } 184 } 185 186 sub ERR_MESSAGE()158 errMsg(); 159 } 160 } 161 162 sub errMsg() 187 163 { 188 164 printMsg("INFO", "\n".$ShortUsage); 189 exit($ERROR_CODE{"Error"}); 190 } 191 192 my $AR_EXT = getAR_EXT($OSgroup); 193 194 my $HelpMessage=" 165 exit(getErrorCode("Error")); 166 } 167 168 my $HelpMessage = " 195 169 NAME: 196 170 Java API Compliance Checker ($CmdName) … … 199 173 DESCRIPTION: 200 174 Java API Compliance Checker (JAPICC) is a tool for checking backward 201 binary/source compatibility of a Java library API. The tool checks class es175 binary/source compatibility of a Java library API. The tool checks class 202 176 declarations of old and new versions and analyzes changes that may break 203 compatibility: removed class members, added abstract methods, etc. Breakage 204 of the binary compatibility may result in crashing or incorrect behavior of 205 existing clients built with an old version of a library if they run with a 206 new one. Breakage of the source compatibility may result in recompilation 177 compatibility: removed class members, added abstract methods, etc. 178 179 Break of the binary compatibility may result in crash or incorrect behavior 180 of existing clients built with an old library version if they run with a 181 new one. Break of the source compatibility may result in recompilation 207 182 errors with a new library version. 208 183 209 JAPICC is intended for library developers and operating system maintainers 210 who are interested in ensuring backward compatibility (i.e. allow old clients 211 to run or to be recompiled with a new version of a library). 184 The tool is intended for developers of software libraries and maintainers 185 of operating systems who are interested in ensuring backward compatibility, 186 i.e. allow old clients to run or to be recompiled with newer library 187 versions. 212 188 213 189 This tool is free software: you can redistribute it and/or modify it … … 217 193 $CmdName [options] 218 194 219 EXAMPLE :195 EXAMPLE 1: 220 196 $CmdName OLD.jar NEW.jar 221 OR 197 198 EXAMPLE 2: 222 199 $CmdName -lib NAME -old OLD.xml -new NEW.xml 223 200 OLD.xml and NEW.xml are XML-descriptors: … … 244 221 245 222 GENERAL OPTIONS: 246 -l|-lib |-library NAME223 -l|-library NAME 247 224 Library name (without version). 248 225 249 - d1|-old|-oPATH250 Descriptor of 1st (old) library version.226 -old|-d1 PATH 227 Descriptor of the 1st (old) library version. 251 228 It may be one of the following: 252 229 253 1. Java ARchive (*.jar)230 1. Java archive (*.jar) 254 231 2. XML-descriptor (VERSION.xml file): 255 232 … … 268 245 3. API dump generated by -dump option 269 246 270 If you are using 1, 4-6 descriptor typesthen you should247 If you are using *.jar as a descriptor then you should 271 248 specify version numbers with -v1 and -v2 options too. 272 273 If you are using *.jar as a descriptor then the tool will try to 274 get implementation version from MANIFEST.MF file. 275 276 -d2|-new|-n PATH 277 Descriptor of 2nd (new) library version. 249 If version numbers are not specified then the tool will 250 try to detect them automatically. 251 252 -new|-d2 PATH 253 Descriptor of the 2nd (new) library version. 278 254 279 255 EXTRA OPTIONS: 280 256 -client|-app PATH 281 This option allows to specify the client Java ARchive that should be257 This option allows to specify the client Java archive that should be 282 258 checked for portability to the new library version. 283 259 284 260 -binary|-bin 285 261 Show \"Binary\" compatibility problems only. 286 262 Generate report to \"bin_compat_report.html\". 287 263 288 264 -source|-src 289 265 Show \"Source\" compatibility problems only. 290 266 Generate report to \"src_compat_report.html\". 291 267 292 268 -v1|-version1 NUM 293 269 Specify 1st API version outside the descriptor. This option is needed … … 323 299 Dump library API to gzipped TXT format file. You can transfer it 324 300 anywhere and pass instead of the descriptor. Also it may be used 325 for debugging the tool. Compatible dump versions: $API_DUMP_MAJOR.0<=V<=$API_DUMP_VERSION301 for debugging the tool. 326 302 327 303 -classes-list PATH … … 352 328 353 329 -dump-path PATH 354 Specify a *. api.$AR_EXT or *.apifile path where to generate an API dump.330 Specify a *.dump file path where to generate an API dump. 355 331 Default: 356 a bi_dumps/LIB_NAME/LIB_NAME_VERSION.api.$AR_EXT332 api_dumps/LIB_NAME/VERSION/API.dump 357 333 358 334 -report-path PATH … … 455 431 non-zero - Incompatible or the tool has run with errors. 456 432 457 MORE INFORMATION: 458 ".$HomePage{"Wiki"}." 459 ".$HomePage{"Dev"}."\n\n"; 460 461 sub HELP_MESSAGE() 462 { # -help 433 MORE INFO: 434 ".$HomePage{"Doc"}." 435 ".$HomePage{"Dev"}; 436 437 sub helpMsg() { 463 438 printMsg("INFO", $HelpMessage."\n"); 464 439 } 465 440 466 my %TypeProblems_Kind=( 467 "Binary"=>{ 468 "NonAbstract_Class_Added_Abstract_Method"=>"High", 469 "Abstract_Class_Added_Abstract_Method"=>"Safe", 470 "Abstract_Class_Added_Abstract_Method_Invoked_By_Others"=>"Medium", 471 "Class_Removed_Abstract_Method"=>"High", 472 "Interface_Added_Abstract_Method"=>"Safe", 473 "Interface_Added_Abstract_Method_Invoked_By_Others"=>"Medium", 474 "Interface_Removed_Abstract_Method"=>"High", 475 "Removed_Class"=>"High", 476 "Removed_Interface"=>"High", 477 "Class_Method_Became_Abstract"=>"High", 478 "Class_Method_Became_NonAbstract"=>"Low", 479 "Interface_Method_Became_NonDefault"=>"High", 480 "Interface_Method_Became_Default"=>"Safe", 481 "Added_Super_Class"=>"Low", 482 "Abstract_Class_Added_Super_Abstract_Class"=>"Safe", 483 "Abstract_Class_Added_Super_Abstract_Class_Invoked_By_Others"=>"Medium", 484 "Removed_Super_Class"=>"Medium", 485 "Changed_Super_Class"=>"Medium", 486 "Abstract_Class_Added_Super_Interface"=>"Safe", 487 "Abstract_Class_Added_Super_Interface_Invoked_By_Others"=>"Medium", 488 "Abstract_Class_Added_Super_Interface_With_Implemented_Methods"=>"Safe", 489 "Class_Removed_Super_Interface"=>"High", 490 "Interface_Added_Super_Interface"=>"Safe", 491 "Interface_Added_Super_Interface_Used_By_Others"=>"Medium", 492 "Interface_Added_Super_Constant_Interface"=>"Low", 493 "Interface_Added_Super_Interface_With_Implemented_Methods"=>"Safe", 494 "Interface_Removed_Super_Interface"=>"High", 495 "Interface_Removed_Super_Constant_Interface"=>"Safe", 496 "Class_Became_Interface"=>"High", 497 "Interface_Became_Class"=>"High", 498 "Class_Became_Final"=>"High", 499 "Class_Became_Abstract"=>"High", 500 "Class_Added_Field"=>"Safe", 501 "Interface_Added_Field"=>"Safe", 502 "Removed_NonConstant_Field"=>"High", 503 "Removed_Constant_Field"=>"Low", 504 "Renamed_Field"=>"High", 505 "Renamed_Constant_Field"=>"Low", 506 "Changed_Field_Type"=>"High", 507 "Changed_Field_Access"=>"High", 508 "Changed_Final_Field_Value"=>"Medium", 509 "Changed_Final_Version_Field_Value"=>"Low", 510 "Field_Became_Final"=>"Medium", 511 "Field_Became_NonFinal"=>"Low", 512 "NonConstant_Field_Became_Static"=>"High", 513 "NonConstant_Field_Became_NonStatic"=>"High", 514 "Class_Overridden_Method"=>"Low", 515 "Class_Method_Moved_Up_Hierarchy"=>"Low" 516 }, 517 "Source"=>{ 518 "NonAbstract_Class_Added_Abstract_Method"=>"High", 519 "Abstract_Class_Added_Abstract_Method"=>"High", 520 "Abstract_Class_Added_Abstract_Method_Invoked_By_Others"=>"High", 521 "Interface_Added_Abstract_Method"=>"High", 522 "Interface_Added_Abstract_Method_Invoked_By_Others"=>"High", 523 "Class_Removed_Abstract_Method"=>"High", 524 "Interface_Removed_Abstract_Method"=>"High", 525 "Removed_Class"=>"High", 526 "Removed_Interface"=>"High", 527 "Class_Method_Became_Abstract"=>"High", 528 "Class_Method_Became_NonAbstract"=>"Safe", 529 "Interface_Method_Became_NonDefault"=>"High", 530 "Interface_Method_Became_Default"=>"Safe", 531 "Added_Super_Class"=>"Low", 532 "Abstract_Class_Added_Super_Abstract_Class"=>"High", 533 "Abstract_Class_Added_Super_Abstract_Class_Invoked_By_Others"=>"High", 534 "Removed_Super_Class"=>"Medium", 535 "Changed_Super_Class"=>"Medium", 536 "Abstract_Class_Added_Super_Interface"=>"High", 537 "Abstract_Class_Added_Super_Interface_Invoked_By_Others"=>"High", 538 "Abstract_Class_Added_Super_Interface_With_Implemented_Methods"=>"Safe", 539 "Class_Removed_Super_Interface"=>"High", 540 "Interface_Added_Super_Interface"=>"High", 541 "Interface_Added_Super_Interface_Used_By_Others"=>"High", 542 "Interface_Added_Super_Constant_Interface"=>"Low", 543 "Interface_Added_Super_Interface_With_Implemented_Methods"=>"Safe", 544 "Interface_Removed_Super_Interface"=>"High", 545 "Interface_Removed_Super_Constant_Interface"=>"High", 546 "Class_Became_Interface"=>"High", 547 "Interface_Became_Class"=>"High", 548 "Class_Became_Final"=>"High", 549 "Class_Became_Abstract"=>"High", 550 "Class_Added_Field"=>"Safe", 551 "Interface_Added_Field"=>"Safe", 552 "Removed_NonConstant_Field"=>"High", 553 "Removed_Constant_Field"=>"High", 554 "Renamed_Field"=>"High", 555 "Renamed_Constant_Field"=>"High", 556 "Changed_Field_Type"=>"High", 557 "Changed_Field_Access"=>"High", 558 "Field_Became_Final"=>"Medium", 559 "Constant_Field_Became_NonStatic"=>"High", 560 "NonConstant_Field_Became_NonStatic"=>"High", 561 "Removed_Annotation"=>"High" 562 } 563 ); 564 565 my %MethodProblems_Kind=( 566 "Binary"=>{ 567 "Added_Method"=>"Safe", 568 "Removed_Method"=>"High", 569 "Method_Became_Static"=>"High", 570 "Method_Became_NonStatic"=>"High", 571 "NonStatic_Method_Became_Final"=>"Medium", 572 "Changed_Method_Access"=>"High", 573 "Method_Became_Synchronized"=>"Low", 574 "Method_Became_NonSynchronized"=>"Low", 575 "Method_Became_Abstract"=>"High", 576 "Method_Became_NonAbstract"=>"Low", 577 "Method_Became_NonDefault"=>"High", 578 "Method_Became_Default"=>"Safe", 579 "NonAbstract_Method_Added_Checked_Exception"=>"Low", 580 "NonAbstract_Method_Removed_Checked_Exception"=>"Low", 581 "Added_Unchecked_Exception"=>"Low", 582 "Removed_Unchecked_Exception"=>"Low", 583 "Variable_Arity_To_Array"=>"Low",# not implemented yet 584 "Changed_Method_Return_From_Void"=>"High" 585 }, 586 "Source"=>{ 587 "Added_Method"=>"Safe", 588 "Removed_Method"=>"High", 589 "Method_Became_Static"=>"Low", 590 "Method_Became_NonStatic"=>"High", 591 "Static_Method_Became_Final"=>"Medium", 592 "NonStatic_Method_Became_Final"=>"Medium", 593 "Changed_Method_Access"=>"High", 594 "Method_Became_Abstract"=>"High", 595 "Method_Became_NonAbstract"=>"Safe", 596 "Method_Became_NonDefault"=>"High", 597 "Method_Became_Default"=>"Safe", 598 "Abstract_Method_Added_Checked_Exception"=>"Medium", 599 "NonAbstract_Method_Added_Checked_Exception"=>"Medium", 600 "Abstract_Method_Removed_Checked_Exception"=>"Medium", 601 "NonAbstract_Method_Removed_Checked_Exception"=>"Medium" 602 } 603 ); 604 441 #Aliases 442 my (%MethodInfo, %TypeInfo, %TName_Tid) = (); 443 444 #Separate checked and unchecked exceptions 605 445 my %KnownRuntimeExceptions= map {$_=>1} ( 606 # To separate checked- and unchecked- exceptions607 446 "java.lang.AnnotationTypeMismatchException", 608 447 "java.lang.ArithmeticException", … … 656 495 ); 657 496 658 my %Slash_Type=(659 "default"=>"/",660 "windows"=>"\\"661 );662 663 my $SLASH = $Slash_Type{$OSgroup}?$Slash_Type{$OSgroup}:$Slash_Type{"default"};664 665 my %OS_AddPath=(666 # this data needed if tool can't detect it automatically667 "macos"=>{668 "bin"=>{"/Developer/usr/bin"=>1}},669 "beos"=>{670 "bin"=>{"/boot/common/bin"=>1,"/boot/system/bin"=>1,"/boot/develop/abi"=>1}}671 );672 673 #Global variables674 my %RESULT;675 my $ExtractCounter = 0;676 my %Cache;677 my $TOP_REF = "<a class='top_ref' href='#Top'>to the top</a>";678 my %DEBUG_PATH;679 680 #Types681 my %TypeInfo;682 my $TYPE_ID = 0;683 my %CheckedTypes;684 my %TName_Tid;685 my %Class_Constructed;686 687 #Classes688 my %ClassList_User;689 my %UsedMethods_Client;690 my %UsedFields_Client;691 my %UsedClasses_Client;692 my %LibArchives;693 my %Class_Methods;694 my %Class_AbstractMethods;695 my %Class_Fields;696 my %MethodUsed;697 my %ClassMethod_AddedUsed;698 # my %FieldUsed;699 700 497 #java.lang.Object 701 498 my %JavaObjectMethod = ( … … 714 511 ); 715 512 716 #Annotations 717 my %AnnotationList_User; 718 my %SkipAnnotationList_User; 513 #Global variables 514 my %Cache; 515 my %RESULT; 516 my $TOP_REF = "<a class='top_ref' href='#Top'>to the top</a>"; 517 518 #Types 519 my %CheckedTypes; 520 521 #Classes 522 my %LibArchives; 523 my %Class_Methods; 524 my %Class_AbstractMethods; 525 my %Class_Fields; 526 my %ClassMethod_AddedUsed; 527 my %Class_Constructed; 719 528 720 529 #Methods 721 530 my %CheckedMethods; 722 my % tr_name;531 my %MethodUsed; 723 532 724 533 #Merging 725 my %MethodInfo;726 my $Version;727 534 my %AddedMethod_Abstract; 728 535 my %RemovedMethod_Abstract; 729 536 my %ChangedReturnFromVoid; 730 my %SkipClasses; 731 my %SkipPackages; 732 my %KeepPackages; 733 my %SkippedPackage; 537 my %CompatRules; 538 my %IncompleteRules; 734 539 735 540 #Report … … 737 542 738 543 #Recursion locks 739 my @RecurSymlink;740 544 my @RecurTypes; 741 742 #System743 my %SystemPaths;744 my %DefaultBinPaths;745 545 746 546 #Problem descriptions … … 760 560 my $Content_Counter = 0; 761 561 762 #Modes 763 my $JoinReport = 1; 764 my $DoubleReport = 0; 765 766 sub get_CmdPath($) 562 sub getModules() 563 { 564 my $TOOL_DIR = dirname($0); 565 if(not $TOOL_DIR) 566 { # patch for MS Windows 567 $TOOL_DIR = "."; 568 } 569 my @SEARCH_DIRS = ( 570 # tool's directory 571 abs_path($TOOL_DIR), 572 # relative path to modules 573 abs_path($TOOL_DIR)."/../share/japi-compliance-checker", 574 # install path 575 'MODULES_INSTALL_PATH' 576 ); 577 foreach my $DIR (@SEARCH_DIRS) 578 { 579 if($DIR!~/\A(\/|\w+:[\/\\])/) 580 { # relative path 581 $DIR = abs_path($TOOL_DIR)."/".$DIR; 582 } 583 if(-d $DIR."/modules") { 584 return $DIR."/modules"; 585 } 586 } 587 588 print STDERR "ERROR: can't find modules (Did you installed the tool by 'make install' command?)\n"; 589 exit(9); # Module_Error 590 } 591 592 sub loadModule($) 767 593 { 768 594 my $Name = $_[0]; 769 return "" if(not $Name); 770 if(defined $Cache{"get_CmdPath"}{$Name}) { 771 return $Cache{"get_CmdPath"}{$Name}; 772 } 773 my $Path = search_Cmd($Name); 774 if(not $Path and $OSgroup eq "windows") 775 { # search for *.exe file 776 $Path=search_Cmd($Name.".exe"); 777 } 778 if (not $Path) { 779 $Path=search_Cmd_Path($Name); 780 } 781 if($Path=~/\s/) { 782 $Path = "\"".$Path."\""; 783 } 784 return ($Cache{"get_CmdPath"}{$Name} = $Path); 785 } 786 787 sub search_Cmd($) 788 { 789 my $Name = $_[0]; 790 return "" if(not $Name); 791 if(defined $Cache{"search_Cmd"}{$Name}) { 792 return $Cache{"search_Cmd"}{$Name}; 793 } 794 if(defined $JdkPath) 795 { 796 if(-x $JdkPath."/".$Name) { 797 return ($Cache{"search_Cmd"}{$Name} = $JdkPath."/".$Name); 798 } 799 800 if(-x $JdkPath."/bin/".$Name) { 801 return ($Cache{"search_Cmd"}{$Name} = $JdkPath."/bin/".$Name); 802 } 803 } 804 if(my $DefaultPath = get_CmdPath_Default($Name)) { 805 return ($Cache{"search_Cmd"}{$Name} = $DefaultPath); 806 } 807 return ($Cache{"search_Cmd"}{$Name} = ""); 808 } 809 810 sub search_Cmd_Path($) 811 { 812 my $Name = $_[0]; 813 return "" if(not $Name); 814 815 if(defined $Cache{"search_Cmd_Path"}{$Name}) { 816 return $Cache{"search_Cmd_Path"}{$Name}; 817 } 818 819 if(defined $SystemPaths{"bin"}) 820 { 821 foreach my $Path (sort {length($a)<=>length($b)} keys(%{$SystemPaths{"bin"}})) 822 { 823 if(-f $Path."/".$Name or -f $Path."/".$Name.".exe") { 824 return ($Cache{"search_Cmd_Path"}{$Name} = joinPath($Path,$Name)); 825 } 826 } 827 } 828 829 return ($Cache{"search_Cmd_Path"}{$Name} = ""); 830 } 831 832 sub get_CmdPath_Default($) 833 { # search in PATH 834 return "" if(not $_[0]); 835 if(defined $Cache{"get_CmdPath_Default"}{$_[0]}) { 836 return $Cache{"get_CmdPath_Default"}{$_[0]}; 837 } 838 return ($Cache{"get_CmdPath_Default"}{$_[0]} = get_CmdPath_Default_I($_[0])); 839 } 840 841 sub get_CmdPath_Default_I($) 842 { # search in PATH 843 my $Name = $_[0]; 844 if($Name=~/find/) 845 { # special case: search for "find" utility 846 if(`find \"$TMP_DIR\" -maxdepth 0 2>\"$TMP_DIR/null\"`) { 847 return "find"; 848 } 849 } 850 if(get_version($Name)) { 851 return $Name; 852 } 853 if($OSgroup eq "windows") 854 { 855 if(`$Name /? 2>\"$TMP_DIR/null\"`) { 856 return $Name; 857 } 858 } 859 if($Name!~/which/) 860 { 861 if(my $WhichCmd = get_CmdPath("which")) 862 { 863 if(`$WhichCmd $Name 2>\"$TMP_DIR/null\"`) { 864 return $Name; 865 } 866 } 867 } 868 foreach my $Path (sort {length($a)<=>length($b)} keys(%DefaultBinPaths)) 869 { 870 if(-f $Path."/".$Name) { 871 return joinPath($Path,$Name); 872 } 873 } 874 return ""; 875 } 876 877 sub showPos($) 878 { 879 my $Number = $_[0]; 880 if(not $Number) { 881 $Number = 1; 882 } 883 else { 884 $Number = int($Number)+1; 885 } 886 if($Number>3) { 887 return $Number."th"; 888 } 889 elsif($Number==1) { 890 return "1st"; 891 } 892 elsif($Number==2) { 893 return "2nd"; 894 } 895 elsif($Number==3) { 896 return "3rd"; 897 } 898 else { 899 return $Number; 900 } 901 } 902 903 sub getAR_EXT($) 904 { 905 my $Target = $_[0]; 906 if(my $Ext = $OS_Archive{$Target}) { 907 return $Ext; 908 } 909 return $OS_Archive{"default"}; 910 } 911 912 sub readDescriptor($$) 913 { 914 my ($LibVersion, $Content) = @_; 915 return if(not $LibVersion); 916 my $DName = $DumpAPI?"descriptor":"descriptor \"d$LibVersion\""; 917 if(not $Content) { 918 exitStatus("Error", "$DName is empty"); 919 } 920 if($Content!~/\</) { 921 exitStatus("Error", "descriptor should be one of the following:\n Java ARchive, XML descriptor, gzipped API dump or directory with Java ARchives."); 922 } 923 $Content=~s/\/\*(.|\n)+?\*\///g; 924 $Content=~s/<\!--(.|\n)+?-->//g; 925 $Descriptor{$LibVersion}{"Version"} = parseTag(\$Content, "version"); 926 $Descriptor{$LibVersion}{"Version"} = $TargetVersion{$LibVersion} if($TargetVersion{$LibVersion}); 927 if($Descriptor{$LibVersion}{"Version"} eq "") { 928 exitStatus("Error", "version in the $DName is not specified (<version> section)"); 929 } 930 931 my $DArchives = parseTag(\$Content, "archives"); 932 if(not $DArchives){ 933 exitStatus("Error", "Java ARchives in the $DName are not specified (<archive> section)"); 934 } 935 else 936 {# append the descriptor Java ARchives list 937 if($Descriptor{$LibVersion}{"Archives"}) { 938 $Descriptor{$LibVersion}{"Archives"} .= "\n".$DArchives; 939 } 940 else { 941 $Descriptor{$LibVersion}{"Archives"} = $DArchives; 942 } 943 foreach my $Path (split(/\s*\n\s*/, $DArchives)) 944 { 945 if(not -e $Path) { 946 exitStatus("Access_Error", "can't access \'$Path\'"); 947 } 948 } 949 } 950 foreach my $Package (split(/\s*\n\s*/, parseTag(\$Content, "skip_packages"))) { 951 $SkipPackages{$LibVersion}{$Package} = 1; 952 } 953 foreach my $Package (split(/\s*\n\s*/, parseTag(\$Content, "packages"))) { 954 $KeepPackages{$LibVersion}{$Package} = 1; 955 } 956 } 957 958 sub parseTag($$) 959 { 960 my ($CodeRef, $Tag) = @_; 961 return "" if(not $CodeRef or not ${$CodeRef} or not $Tag); 962 if(${$CodeRef}=~s/\<\Q$Tag\E\>((.|\n)+?)\<\/\Q$Tag\E\>//) 963 { 964 my $Content = $1; 965 $Content=~s/(\A\s+|\s+\Z)//g; 966 return $Content; 967 } 968 else { 969 return ""; 970 } 971 } 972 973 sub ignore_path($$) 974 { 975 my ($Path, $Prefix) = @_; 976 return 1 if(not $Path or not -e $Path 977 or not $Prefix or not -e $Prefix); 978 return 1 if($Path=~/\~\Z/);# skipping system backup files 979 # skipping hidden .svn, .git, .bzr, .hg and CVS directories 980 return 1 if(cut_path_prefix($Path, $Prefix)=~/(\A|[\/\\]+)(\.(svn|git|bzr|hg)|CVS)([\/\\]+|\Z)/); 981 return 0; 982 } 983 984 sub cut_path_prefix($$) 985 { 986 my ($Path, $Prefix) = @_; 987 $Prefix=~s/[\/\\]+\Z//; 988 $Path=~s/\A\Q$Prefix\E([\/\\]+|\Z)//; 989 return $Path; 990 } 991 992 sub get_filename($) 993 { # much faster than basename() from File::Basename module 994 if(defined $Cache{"get_filename"}{$_[0]}) { 995 return $Cache{"get_filename"}{$_[0]}; 996 } 997 if($_[0] and $_[0]=~/([^\/\\]+)[\/\\]*\Z/) { 998 return ($Cache{"get_filename"}{$_[0]}=$1); 999 } 1000 return ($Cache{"get_filename"}{$_[0]}=""); 1001 } 1002 1003 sub get_dirname($) 1004 { # much faster than dirname() from File::Basename module 1005 if(defined $Cache{"get_dirname"}{$_[0]}) { 1006 return $Cache{"get_dirname"}{$_[0]}; 1007 } 1008 if($_[0] and $_[0]=~/\A(.*?)[\/\\]+[^\/\\]*[\/\\]*\Z/) { 1009 return ($Cache{"get_dirname"}{$_[0]}=$1); 1010 } 1011 return ($Cache{"get_dirname"}{$_[0]}=""); 1012 } 1013 1014 sub separate_path($) { 1015 return (get_dirname($_[0]), get_filename($_[0])); 1016 } 1017 1018 sub joinPath($$) 1019 { 1020 return join($SLASH, @_); 1021 } 1022 1023 sub get_abs_path($) 1024 { # abs_path() should NOT be called for absolute inputs 1025 # because it can change them 1026 my $Path = $_[0]; 1027 if(not is_abs($Path)) { 1028 $Path = abs_path($Path); 1029 } 1030 return $Path; 1031 } 1032 1033 sub is_abs($) { 1034 return ($_[0]=~/\A(\/|\w+:[\/\\])/); 1035 } 1036 1037 sub cmd_find($$$$) 1038 { 1039 my ($Path, $Type, $Name, $MaxDepth) = @_; 1040 return () if(not $Path or not -e $Path); 1041 if($OSgroup eq "windows") 1042 { 1043 my $DirCmd = get_CmdPath("dir"); 1044 if(not $DirCmd) { 1045 exitStatus("Not_Found", "can't find \"dir\" command"); 1046 } 1047 $Path=~s/[\\]+\Z//; 1048 $Path = get_abs_path($Path); 1049 my $Cmd = $DirCmd." \"$Path\" /B /O"; 1050 if($MaxDepth!=1) { 1051 $Cmd .= " /S"; 1052 } 1053 if($Type eq "d") { 1054 $Cmd .= " /AD"; 1055 } 1056 my @Files = (); 1057 if($Name) 1058 { # FIXME: how to search file names in MS shell? 1059 $Name=~s/\*/.*/g if($Name!~/\]/); 1060 foreach my $File (split(/\n/, `$Cmd`)) 1061 { 1062 if($File=~/$Name\Z/i) { 1063 push(@Files, $File); 1064 } 1065 } 1066 } 1067 else { 1068 @Files = split(/\n/, `$Cmd 2>\"$TMP_DIR/null\"`); 1069 } 1070 my @AbsPaths = (); 1071 foreach my $File (@Files) 1072 { 1073 if(not is_abs($File)) { 1074 $File = joinPath($Path, $File); 1075 } 1076 if($Type eq "f" and not -f $File) 1077 { # skip dirs 1078 next; 1079 } 1080 push(@AbsPaths, $File); 1081 } 1082 if($Type eq "d") { 1083 push(@AbsPaths, $Path); 1084 } 1085 return @AbsPaths; 1086 } 1087 else 1088 { 1089 my $FindCmd = get_CmdPath("find"); 1090 if(not $FindCmd) { 1091 exitStatus("Not_Found", "can't find a \"find\" command"); 1092 } 1093 $Path = get_abs_path($Path); 1094 if(-d $Path and -l $Path 1095 and $Path!~/\/\Z/) 1096 { # for directories that are symlinks 1097 $Path.="/"; 1098 } 1099 my $Cmd = $FindCmd." \"$Path\""; 1100 if($MaxDepth) { 1101 $Cmd .= " -maxdepth $MaxDepth"; 1102 } 1103 if($Type) { 1104 $Cmd .= " -type $Type"; 1105 } 1106 if($Name) 1107 { 1108 if($Name=~/\]/) { 1109 $Cmd .= " -regex \"$Name\""; 1110 } 1111 else { 1112 $Cmd .= " -name \"$Name\""; 1113 } 1114 } 1115 return split(/\n/, `$Cmd 2>\"$TMP_DIR/null\"`); 1116 } 1117 } 1118 1119 sub path_format($$) 1120 { # forward slash to pass into MinGW GCC 1121 my ($Path, $Fmt) = @_; 1122 if($Fmt eq "windows") 1123 { 1124 $Path=~s/\//\\/g; 1125 $Path=lc($Path); 1126 } 1127 else { 1128 $Path=~s/\\/\//g; 1129 } 1130 return $Path; 1131 } 1132 1133 sub unpackDump($) 1134 { 1135 my $Path = $_[0]; 1136 return "" if(not $Path or not -e $Path); 1137 1138 if(isDumpFile($Path)) { 1139 return $Path; 1140 } 1141 1142 $Path = get_abs_path($Path); 1143 $Path = path_format($Path, $OSgroup); 1144 my ($Dir, $FileName) = separate_path($Path); 1145 my $UnpackDir = $TMP_DIR."/unpack"; 1146 if(-d $UnpackDir) { 1147 rmtree($UnpackDir); 1148 } 1149 mkpath($UnpackDir); 1150 if($FileName=~s/\Q.zip\E\Z//g) 1151 { # *.zip 1152 my $UnzipCmd = get_CmdPath("unzip"); 1153 if(not $UnzipCmd) { 1154 exitStatus("Not_Found", "can't find \"unzip\" command"); 1155 } 1156 chdir($UnpackDir); 1157 system("$UnzipCmd \"$Path\" >contents.txt"); 1158 if($?) { 1159 exitStatus("Error", "can't extract \'$Path\'"); 1160 } 1161 chdir($ORIG_DIR); 1162 my @Contents = (); 1163 foreach (split("\n", readFile("$UnpackDir/contents.txt"))) 1164 { 1165 if(/inflating:\s*([^\s]+)/) { 1166 push(@Contents, $1); 1167 } 1168 } 1169 if(not @Contents) { 1170 exitStatus("Error", "can't extract \'$Path\'"); 1171 } 1172 return joinPath($UnpackDir, $Contents[0]); 1173 } 1174 elsif($FileName=~s/\Q.tar.gz\E\Z//g) 1175 { # *.tar.gz 1176 if($OSgroup eq "windows") 1177 { # -xvzf option is not implemented in tar.exe (2003) 1178 # use "gzip.exe -k -d -f" + "tar.exe -xvf" instead 1179 my $TarCmd = get_CmdPath("tar"); 1180 if(not $TarCmd) { 1181 exitStatus("Not_Found", "can't find \"tar\" command"); 1182 } 1183 my $GzipCmd = get_CmdPath("gzip"); 1184 if(not $GzipCmd) { 1185 exitStatus("Not_Found", "can't find \"gzip\" command"); 1186 } 1187 chdir($UnpackDir); 1188 qx/$GzipCmd -k -d -f "$Path"/; # keep input files (-k) 1189 if($?) { 1190 exitStatus("Error", "can't extract \'$Path\'"); 1191 } 1192 my @Contents = qx/$TarCmd -xvf "$Dir\\$FileName.tar"/; 1193 if($? or not @Contents) { 1194 exitStatus("Error", "can't extract \'$Path\'"); 1195 } 1196 chdir($ORIG_DIR); 1197 unlink($Dir."/".$FileName.".tar"); 1198 chomp $Contents[0]; 1199 return joinPath($UnpackDir, $Contents[0]); 1200 } 1201 else 1202 { # Linux, Unix, OS X 1203 my $TarCmd = get_CmdPath("tar"); 1204 if(not $TarCmd) { 1205 exitStatus("Not_Found", "can't find \"tar\" command"); 1206 } 1207 chdir($UnpackDir); 1208 my @Contents = qx/$TarCmd -xvzf "$Path" 2>&1/; 1209 if($? or not @Contents) { 1210 exitStatus("Error", "can't extract \'$Path\'"); 1211 } 1212 chdir($ORIG_DIR); 1213 $Contents[0]=~s/^x //; # OS X 1214 chomp $Contents[0]; 1215 return joinPath($UnpackDir, $Contents[0]); 1216 } 1217 } 595 if(defined $LoadedModules{$Name}) { 596 return; 597 } 598 my $Path = $MODULES_DIR."/Internals/$Name.pm"; 599 if(not -f $Path) 600 { 601 print STDERR "can't access \'$Path\'\n"; 602 exit(2); 603 } 604 require $Path; 605 $LoadedModules{$Name} = 1; 606 } 607 608 sub readModule($$) 609 { 610 my ($Module, $Name) = @_; 611 my $Path = $MODULES_DIR."/Internals/$Module/".$Name; 612 if(not -f $Path) { 613 exitStatus("Module_Error", "can't access \'$Path\'"); 614 } 615 return readFile($Path); 1218 616 } 1219 617 … … 1225 623 { 1226 624 next if(not $ClassName); 1227 my $Type1_Id = $TName_Tid{1}{$ClassName}; 1228 my %Type1 = get_Type($Type1_Id, 1); 1229 1230 if($Type1{"Type"}!~/class|interface/) { 625 my $Type1 = getType($TName_Tid{1}{$ClassName}, 1); 626 627 if($Type1->{"Type"}!~/class|interface/) { 1231 628 next; 1232 629 } 1233 630 1234 if(defined $Type1 {"Access"}1235 and $Type1 {"Access"}=~/private/) {631 if(defined $Type1->{"Access"} 632 and $Type1->{"Access"}=~/private/) { 1236 633 next; 1237 634 } 1238 635 1239 if(not classFilter( \%Type1, 1, 0)) {636 if(not classFilter($Type1, 1, 0)) { 1240 637 next; 1241 638 } … … 1253 650 $CheckedMethods{$Method} = 1; 1254 651 1255 if($Type1 {"Type"} eq "class")652 if($Type1->{"Type"} eq "class") 1256 653 { 1257 654 %{$CompatProblems{$Method}{"Removed_Class"}{"this"}} = ( 1258 655 "Type_Name"=>$ClassName, 1259 "Target"=>$ClassName 656 "Target"=>$ClassName); 1260 657 } 1261 658 else … … 1263 660 %{$CompatProblems{$Method}{"Removed_Interface"}{"this"}} = ( 1264 661 "Type_Name"=>$ClassName, 1265 "Target"=>$ClassName 662 "Target"=>$ClassName); 1266 663 } 1267 664 … … 1273 670 foreach my $Class_Id (keys(%{$TypeInfo{1}})) 1274 671 { 1275 my %Class1 = get_Type($Class_Id, 1);1276 1277 if($Class1 {"Type"}!~/class|interface/) {672 my $Class1 = getType($Class_Id, 1); 673 674 if($Class1->{"Type"}!~/class|interface/) { 1278 675 next; 1279 676 } 1280 677 1281 if(defined $Class1 {"Access"}1282 and $Class1 {"Access"}=~/private/) {678 if(defined $Class1->{"Access"} 679 and $Class1->{"Access"}=~/private/) { 1283 680 next; 1284 681 } 1285 682 1286 if(not classFilter( \%Class1, 1, 1)) {683 if(not classFilter($Class1, 1, 1)) { 1287 684 next; 1288 685 } 1289 686 1290 my $ClassName = $Class1 {"Name"};687 my $ClassName = $Class1->{"Name"}; 1291 688 1292 689 if(my $Class2_Id = $TName_Tid{2}{$ClassName}) … … 1294 691 if(not defined $Class_Methods{1}{$ClassName}) 1295 692 { 1296 my %Class2 = get_Type($Class2_Id, 2);693 my $Class2 = getType($Class2_Id, 2); 1297 694 1298 foreach my $Field (keys(%{$Class1 {"Fields"}}))695 foreach my $Field (keys(%{$Class1->{"Fields"}})) 1299 696 { 1300 my $FieldInfo = $Class1 {"Fields"}{$Field};697 my $FieldInfo = $Class1->{"Fields"}{$Field}; 1301 698 1302 699 my $FAccess = $FieldInfo->{"Access"}; … … 1309 706 $CheckedTypes{$ClassName} = 1; 1310 707 1311 if(not defined $Class2 {"Fields"}{$Field})708 if(not defined $Class2->{"Fields"}{$Field}) 1312 709 { 1313 710 %{$CompatProblems{".client_method"}{"Removed_NonConstant_Field"}{$Field}}=( 1314 711 "Target"=>$Field, 1315 712 "Type_Name"=>$ClassName, 1316 "Type_Type"=>$Class1 {"Type"},1317 "Field_Type"=>get _TypeName($FieldInfo->{"Type"}, 1));713 "Type_Type"=>$Class1->{"Type"}, 714 "Field_Type"=>getTypeName($FieldInfo->{"Type"}, 1)); 1318 715 } 1319 716 } … … 1323 720 else 1324 721 { # removed 1325 if(defined $Class1 {"Annotation"})722 if(defined $Class1->{"Annotation"}) 1326 723 { 1327 724 %{$CompatProblems{".client_method"}{"Removed_Annotation"}{"this"}} = ( 1328 725 "Type_Name"=>$ClassName, 1329 "Target"=>$ClassName 726 "Target"=>$ClassName); 1330 727 } 1331 728 … … 1335 732 if(not defined $ReportedRemoved{$ClassName}) 1336 733 { 1337 foreach my $Field (keys(%{$Class1 {"Fields"}}))734 foreach my $Field (keys(%{$Class1->{"Fields"}})) 1338 735 { 1339 my $FieldInfo = $Class1 {"Fields"}{$Field};736 my $FieldInfo = $Class1->{"Fields"}{$Field}; 1340 737 1341 738 my $FAccess = $FieldInfo->{"Access"}; … … 1348 745 $CheckedTypes{$ClassName} = 1; 1349 746 1350 if($Class1 {"Type"} eq "class")747 if($Class1->{"Type"} eq "class") 1351 748 { 1352 749 %{$CompatProblems{".client_method"}{"Removed_Class"}{"this"}} = ( 1353 750 "Type_Name"=>$ClassName, 1354 "Target"=>$ClassName 751 "Target"=>$ClassName); 1355 752 } 1356 753 else … … 1358 755 %{$CompatProblems{".client_method"}{"Removed_Interface"}{"this"}} = ( 1359 756 "Type_Name"=>$ClassName, 1360 "Target"=>$ClassName 757 "Target"=>$ClassName); 1361 758 } 1362 759 } … … 1405 802 sub pushType($$) 1406 803 { 1407 my %TypeDescriptor =(804 my %TypeDescriptor = ( 1408 805 "Tid1" => $_[0], 1409 "Tid2" => $_[1] 806 "Tid2" => $_[1]); 1410 807 push(@RecurTypes, \%TypeDescriptor); 1411 808 } 1412 809 1413 sub get _SFormat($)810 sub getSFormat($) 1414 811 { 1415 812 my $Name = $_[0]; … … 1418 815 } 1419 816 1420 sub get_PFormat($) 1421 { 1422 my $Name = $_[0]; 1423 $Name=~s/\//./g; 1424 return $Name; 1425 } 1426 1427 sub get_ConstantValue($$) 817 sub getConstantValue($$) 1428 818 { 1429 819 my ($Value, $ValueType) = @_; 1430 return "" if(not $Value); 820 821 if(not defined $Value) { 822 return undef; 823 } 824 1431 825 if($Value eq "\@EMPTY_STRING\@") { 1432 826 return "\"\""; … … 1435 829 return "\"".$Value."\""; 1436 830 } 1437 else { 1438 return $Value; 1439 } 831 832 return $Value; 1440 833 } 1441 834 … … 1466 859 } 1467 860 1468 my %Type1 = get_Type($Type1_Id, 1);1469 my %Type2 = get_Type($Type2_Id, 2);1470 861 if(isRecurType($Type1_Id, $Type2_Id)) 1471 862 { # do not follow to recursive declarations 1472 863 return {}; 1473 864 } 865 866 my %Type1 = %{getType($Type1_Id, 1)}; 867 my %Type2 = %{getType($Type2_Id, 2)}; 868 1474 869 return {} if(not $Type1{"Name"} or not $Type2{"Name"}); 1475 870 return {} if(not $Type1{"Archive"} or not $Type2{"Archive"}); … … 1502 897 { 1503 898 %{$SubProblems{"Class_Became_Interface"}{""}}=( 1504 "Type_Name"=>$Type1{"Name"} 899 "Type_Name"=>$Type1{"Name"}); 1505 900 1506 901 return ($Cache{"mergeTypes"}{$Type1_Id}{$Type2_Id} = \%SubProblems); … … 1510 905 { 1511 906 %{$SubProblems{"Interface_Became_Class"}{""}}=( 1512 "Type_Name"=>$Type1{"Name"} 907 "Type_Name"=>$Type1{"Name"}); 1513 908 1514 909 return ($Cache{"mergeTypes"}{$Type1_Id}{$Type2_Id} = \%SubProblems); … … 1519 914 %{$SubProblems{"Class_Became_Final"}{""}}=( 1520 915 "Type_Name"=>$Type1{"Name"}, 1521 "Target"=>$Type1{"Name"} 916 "Target"=>$Type1{"Name"}); 1522 917 } 1523 918 if(not $Type1{"Abstract"} … … 1525 920 { 1526 921 %{$SubProblems{"Class_Became_Abstract"}{""}}=( 1527 "Type_Name"=>$Type1{"Name"} 922 "Type_Name"=>$Type1{"Name"}); 1528 923 } 1529 924 … … 1538 933 if(my @InvokedBy = sort keys(%{$MethodUsed{2}{$AddedMethod}})) 1539 934 { 1540 %{$SubProblems{"Abstract_Class_Added_Abstract_Method_Invoked_By_Others"}{get _SFormat($AddedMethod)}} = (935 %{$SubProblems{"Abstract_Class_Added_Abstract_Method_Invoked_By_Others"}{getSFormat($AddedMethod)}} = ( 1541 936 "Type_Name"=>$Type1{"Name"}, 1542 937 "Type_Type"=>$Type1{"Type"}, 1543 938 "Target"=>$AddedMethod, 1544 "Invoked By"=>$InvokedBy[0]);939 "Invoked_By"=>$InvokedBy[0]); 1545 940 } 1546 941 else 1547 942 { 1548 %{$SubProblems{"Abstract_Class_Added_Abstract_Method"}{get _SFormat($AddedMethod)}} = (943 %{$SubProblems{"Abstract_Class_Added_Abstract_Method"}{getSFormat($AddedMethod)}} = ( 1549 944 "Type_Name"=>$Type1{"Name"}, 1550 945 "Type_Type"=>$Type1{"Type"}, 1551 "Target"=>$AddedMethod 946 "Target"=>$AddedMethod); 1552 947 } 1553 948 } 1554 949 else 1555 950 { 1556 %{$SubProblems{"NonAbstract_Class_Added_Abstract_Method"}{get _SFormat($AddedMethod)}} = (951 %{$SubProblems{"NonAbstract_Class_Added_Abstract_Method"}{getSFormat($AddedMethod)}} = ( 1557 952 "Type_Name"=>$Type1{"Name"}, 1558 953 "Type_Type"=>$Type1{"Type"}, 1559 "Target"=>$AddedMethod 954 "Target"=>$AddedMethod); 1560 955 } 1561 956 } … … 1564 959 if(my @InvokedBy = sort keys(%{$MethodUsed{2}{$AddedMethod}})) 1565 960 { 1566 %{$SubProblems{"Interface_Added_Abstract_Method_Invoked_By_Others"}{get _SFormat($AddedMethod)}} = (961 %{$SubProblems{"Interface_Added_Abstract_Method_Invoked_By_Others"}{getSFormat($AddedMethod)}} = ( 1567 962 "Type_Name"=>$Type1{"Name"}, 1568 963 "Type_Type"=>$Type1{"Type"}, 1569 964 "Target"=>$AddedMethod, 1570 "Invoked By"=>$InvokedBy[0]);965 "Invoked_By"=>$InvokedBy[0]); 1571 966 } 1572 967 else 1573 968 { 1574 %{$SubProblems{"Interface_Added_Abstract_Method"}{get _SFormat($AddedMethod)}} = (969 %{$SubProblems{"Interface_Added_Abstract_Method"}{getSFormat($AddedMethod)}} = ( 1575 970 "Type_Name"=>$Type1{"Name"}, 1576 971 "Type_Type"=>$Type1{"Type"}, 1577 "Target"=>$AddedMethod 972 "Target"=>$AddedMethod); 1578 973 } 1579 974 } … … 1583 978 if($Type1{"Type"} eq "class") 1584 979 { 1585 %{$SubProblems{"Class_Removed_Abstract_Method"}{get _SFormat($RemovedMethod)}} = (980 %{$SubProblems{"Class_Removed_Abstract_Method"}{getSFormat($RemovedMethod)}} = ( 1586 981 "Type_Name"=>$Type1{"Name"}, 1587 982 "Type_Type"=>$Type1{"Type"}, 1588 "Target"=>$RemovedMethod 983 "Target"=>$RemovedMethod); 1589 984 } 1590 985 else 1591 986 { 1592 %{$SubProblems{"Interface_Removed_Abstract_Method"}{get _SFormat($RemovedMethod)}} = (987 %{$SubProblems{"Interface_Removed_Abstract_Method"}{getSFormat($RemovedMethod)}} = ( 1593 988 "Type_Name"=>$Type1{"Name"}, 1594 989 "Type_Type"=>$Type1{"Type"}, 1595 "Target"=>$RemovedMethod 990 "Target"=>$RemovedMethod); 1596 991 } 1597 992 } … … 1599 994 and $Type2{"Type"} eq "class") 1600 995 { 1601 my %SuperClass1 = get_Type($Type1{"SuperClass"}, 1); 1602 my %SuperClass2 = get_Type($Type2{"SuperClass"}, 2); 1603 if($SuperClass2{"Name"} ne $SuperClass1{"Name"}) 1604 { 1605 if($SuperClass1{"Name"} eq "java.lang.Object" 1606 or not $SuperClass1{"Name"}) 996 my $SuperClass1 = getType($Type1{"SuperClass"}, 1); 997 my $SuperClass2 = getType($Type2{"SuperClass"}, 2); 998 999 my $SuperClassName1 = $SuperClass1->{"Name"}; 1000 my $SuperClassName2 = $SuperClass2->{"Name"}; 1001 1002 if($SuperClassName2 ne $SuperClassName1) 1003 { 1004 if($SuperClassName1 eq "java.lang.Object" 1005 or not $SuperClassName1) 1607 1006 { 1608 1007 # Java 6: java.lang.Object 1609 1008 # Java 7: none 1610 if($SuperClass 2{"Name"}ne "java.lang.Object")1009 if($SuperClassName2 ne "java.lang.Object") 1611 1010 { 1612 if($SuperClass2 {"Abstract"}1011 if($SuperClass2->{"Abstract"} 1613 1012 and $Type1{"Abstract"} and $Type2{"Abstract"} 1614 and keys(%{$Class_AbstractMethods{2}{$SuperClass 2{"Name"}}}))1013 and keys(%{$Class_AbstractMethods{2}{$SuperClassName2}})) 1615 1014 { 1616 1015 if(my ($Invoked, $InvokedBy) = getInvoked($Type1{"Name"})) … … 1618 1017 %{$SubProblems{"Abstract_Class_Added_Super_Abstract_Class_Invoked_By_Others"}{""}} = ( 1619 1018 "Type_Name"=>$Type1{"Name"}, 1620 "Target"=>$SuperClass 2{"Name"},1019 "Target"=>$SuperClassName2, 1621 1020 "Invoked"=>$Invoked, 1622 "Invoked By"=>$InvokedBy);1021 "Invoked_By"=>$InvokedBy); 1623 1022 } 1624 1023 else … … 1626 1025 %{$SubProblems{"Abstract_Class_Added_Super_Abstract_Class"}{""}} = ( 1627 1026 "Type_Name"=>$Type1{"Name"}, 1628 "Target"=>$SuperClass 2{"Name"});1027 "Target"=>$SuperClassName2); 1629 1028 } 1630 1029 } … … 1633 1032 %{$SubProblems{"Added_Super_Class"}{""}} = ( 1634 1033 "Type_Name"=>$Type1{"Name"}, 1635 "Target"=>$SuperClass 2{"Name"});1636 } 1637 } 1638 } 1639 elsif($SuperClass 2{"Name"}eq "java.lang.Object"1640 or not $SuperClass 2{"Name"})1034 "Target"=>$SuperClassName2); 1035 } 1036 } 1037 } 1038 elsif($SuperClassName2 eq "java.lang.Object" 1039 or not $SuperClassName2) 1641 1040 { 1642 1041 # Java 6: java.lang.Object 1643 1042 # Java 7: none 1644 if($SuperClass 1{"Name"}ne "java.lang.Object")1043 if($SuperClassName1 ne "java.lang.Object") 1645 1044 { 1646 1045 %{$SubProblems{"Removed_Super_Class"}{""}} = ( 1647 1046 "Type_Name"=>$Type1{"Name"}, 1648 "Target"=>$SuperClass 1{"Name"});1047 "Target"=>$SuperClassName1); 1649 1048 } 1650 1049 } … … 1653 1052 %{$SubProblems{"Changed_Super_Class"}{""}} = ( 1654 1053 "Type_Name"=>$Type1{"Name"}, 1655 "Target"=>$SuperClass 1{"Name"},1656 "Old_Value"=>$SuperClass 1{"Name"},1657 "New_Value"=>$SuperClass 2{"Name"});1658 } 1659 } 1660 } 1661 my %SuperInterfaces_Old = map {get _TypeName($_, 1) => 1} keys(%{$Type1{"SuperInterface"}});1662 my %SuperInterfaces_New = map {get _TypeName($_, 2) => 1} keys(%{$Type2{"SuperInterface"}});1054 "Target"=>$SuperClassName1, 1055 "Old_Value"=>$SuperClassName1, 1056 "New_Value"=>$SuperClassName2); 1057 } 1058 } 1059 } 1060 my %SuperInterfaces_Old = map {getTypeName($_, 1) => 1} keys(%{$Type1{"SuperInterface"}}); 1061 my %SuperInterfaces_New = map {getTypeName($_, 2) => 1} keys(%{$Type2{"SuperInterface"}}); 1663 1062 foreach my $SuperInterface (keys(%SuperInterfaces_New)) 1664 1063 { … … 1675 1074 if($HaveMethods and checkDefaultImpl(2, $SuperInterface, $Type2{"Name"})) 1676 1075 { 1677 %{$SubProblems{"Interface_Added_Super_Interface_With_Implemented_Methods"}{get _SFormat($SuperInterface)}} = (1076 %{$SubProblems{"Interface_Added_Super_Interface_With_Implemented_Methods"}{getSFormat($SuperInterface)}} = ( 1678 1077 "Type_Name"=>$Type1{"Name"}, 1679 "Target"=>$SuperInterface 1078 "Target"=>$SuperInterface); 1680 1079 } 1681 1080 else … … 1683 1082 if(my ($Invoked, $InvokedBy) = getInvoked($Type1{"Name"})) 1684 1083 { 1685 %{$SubProblems{"Interface_Added_Super_Interface_Used_By_Others"}{get _SFormat($SuperInterface)}} = (1084 %{$SubProblems{"Interface_Added_Super_Interface_Used_By_Others"}{getSFormat($SuperInterface)}} = ( 1686 1085 "Type_Name"=>$Type1{"Name"}, 1687 1086 "Target"=>$SuperInterface, 1688 1087 "Invoked"=>$Invoked, 1689 "Invoked By"=>$InvokedBy);1088 "Invoked_By"=>$InvokedBy); 1690 1089 } 1691 1090 else 1692 1091 { 1693 %{$SubProblems{"Interface_Added_Super_Interface"}{get _SFormat($SuperInterface)}} = (1092 %{$SubProblems{"Interface_Added_Super_Interface"}{getSFormat($SuperInterface)}} = ( 1694 1093 "Type_Name"=>$Type1{"Name"}, 1695 "Target"=>$SuperInterface 1094 "Target"=>$SuperInterface); 1696 1095 } 1697 1096 } … … 1699 1098 elsif($HaveFields) 1700 1099 { 1701 %{$SubProblems{"Interface_Added_Super_Constant_Interface"}{get _SFormat($SuperInterface)}} = (1100 %{$SubProblems{"Interface_Added_Super_Constant_Interface"}{getSFormat($SuperInterface)}} = ( 1702 1101 "Type_Name"=>$Type2{"Name"}, 1703 "Target"=>$SuperInterface 1102 "Target"=>$SuperInterface); 1704 1103 } 1705 1104 else … … 1714 1113 if($HaveMethods and checkDefaultImpl(2, $SuperInterface, $Type2{"Name"})) 1715 1114 { 1716 %{$SubProblems{"Abstract_Class_Added_Super_Interface_With_Implemented_Methods"}{get _SFormat($SuperInterface)}} = (1115 %{$SubProblems{"Abstract_Class_Added_Super_Interface_With_Implemented_Methods"}{getSFormat($SuperInterface)}} = ( 1717 1116 "Type_Name"=>$Type1{"Name"}, 1718 "Target"=>$SuperInterface 1117 "Target"=>$SuperInterface); 1719 1118 } 1720 1119 else … … 1722 1121 if(my ($Invoked, $InvokedBy) = getInvoked($Type1{"Name"})) 1723 1122 { 1724 %{$SubProblems{"Abstract_Class_Added_Super_Interface_Invoked_By_Others"}{get _SFormat($SuperInterface)}} = (1123 %{$SubProblems{"Abstract_Class_Added_Super_Interface_Invoked_By_Others"}{getSFormat($SuperInterface)}} = ( 1725 1124 "Type_Name"=>$Type1{"Name"}, 1726 1125 "Target"=>$SuperInterface, 1727 1126 "Invoked"=>$Invoked, 1728 "Invoked By"=>$InvokedBy);1127 "Invoked_By"=>$InvokedBy); 1729 1128 } 1730 1129 else 1731 1130 { 1732 %{$SubProblems{"Abstract_Class_Added_Super_Interface"}{get _SFormat($SuperInterface)}} = (1131 %{$SubProblems{"Abstract_Class_Added_Super_Interface"}{getSFormat($SuperInterface)}} = ( 1733 1132 "Type_Name"=>$Type1{"Name"}, 1734 "Target"=>$SuperInterface 1133 "Target"=>$SuperInterface); 1735 1134 } 1736 1135 } … … 1751 1150 or $SuperInterface=~/\Ajava\./) 1752 1151 { 1753 %{$SubProblems{"Interface_Removed_Super_Interface"}{get _SFormat($SuperInterface)}} = (1152 %{$SubProblems{"Interface_Removed_Super_Interface"}{getSFormat($SuperInterface)}} = ( 1754 1153 "Type_Name"=>$Type1{"Name"}, 1755 1154 "Type_Type"=>"interface", 1756 "Target"=>$SuperInterface 1155 "Target"=>$SuperInterface); 1757 1156 } 1758 1157 elsif($HaveFields) 1759 1158 { 1760 %{$SubProblems{"Interface_Removed_Super_Constant_Interface"}{get _SFormat($SuperInterface)}} = (1159 %{$SubProblems{"Interface_Removed_Super_Constant_Interface"}{getSFormat($SuperInterface)}} = ( 1761 1160 "Type_Name"=>$Type1{"Name"}, 1762 "Target"=>$SuperInterface 1161 "Target"=>$SuperInterface); 1763 1162 } 1764 1163 else { … … 1768 1167 else 1769 1168 { 1770 %{$SubProblems{"Class_Removed_Super_Interface"}{get _SFormat($SuperInterface)}} = (1169 %{$SubProblems{"Class_Removed_Super_Interface"}{getSFormat($SuperInterface)}} = ( 1771 1170 "Type_Name"=>$Type1{"Name"}, 1772 1171 "Type_Type"=>"class", 1773 "Target"=>$SuperInterface 1172 "Target"=>$SuperInterface); 1774 1173 } 1775 1174 } … … 1785 1184 my $Field_Pos1 = $Type1{"Fields"}{$Field_Name}{"Pos"}; 1786 1185 my $FieldType1_Id = $Type1{"Fields"}{$Field_Name}{"Type"}; 1787 my %FieldType1 = get_Type($FieldType1_Id, 1);1186 my $FieldType1_Name = getTypeName($FieldType1_Id, 1); 1788 1187 1789 1188 if(not $Type2{"Fields"}{$Field_Name}) … … 1791 1190 my $StraightPair_Name = findFieldPair($Field_Pos1, \%Type2); 1792 1191 if($StraightPair_Name ne "lost" and not $Type1{"Fields"}{$StraightPair_Name} 1793 and $FieldType1 {"Name"} eq get_TypeName($Type2{"Fields"}{$StraightPair_Name}{"Type"}, 2))1794 { 1795 if(my $Constant = get _ConstantValue($Type1{"Fields"}{$Field_Name}{"Value"}, $FieldType1{"Name"}))1192 and $FieldType1_Name eq getTypeName($Type2{"Fields"}{$StraightPair_Name}{"Type"}, 2)) 1193 { 1194 if(my $Constant = getConstantValue($Type1{"Fields"}{$Field_Name}{"Value"}, $FieldType1_Name)) 1796 1195 { 1797 1196 %{$SubProblems{"Renamed_Constant_Field"}{$Field_Name}}=( … … 1800 1199 "Old_Value"=>$Field_Name, 1801 1200 "New_Value"=>$StraightPair_Name, 1802 "Field_Type"=>$FieldType1 {"Name"},1803 "Field_Value"=>$Constant 1201 "Field_Type"=>$FieldType1_Name, 1202 "Field_Value"=>$Constant); 1804 1203 } 1805 1204 else … … 1810 1209 "Old_Value"=>$Field_Name, 1811 1210 "New_Value"=>$StraightPair_Name, 1812 "Field_Type"=>$FieldType1 {"Name"});1211 "Field_Type"=>$FieldType1_Name); 1813 1212 } 1814 1213 } 1815 1214 else 1816 1215 { 1817 if(my $Constant = get _ConstantValue($Type1{"Fields"}{$Field_Name}{"Value"}, $FieldType1{"Name"}))1216 if(my $Constant = getConstantValue($Type1{"Fields"}{$Field_Name}{"Value"}, $FieldType1_Name)) 1818 1217 { # has a compile-time constant value 1819 1218 %{$SubProblems{"Removed_Constant_Field"}{$Field_Name}}=( … … 1821 1220 "Type_Name"=>$Type1{"Name"}, 1822 1221 "Field_Value"=>$Constant, 1823 "Field_Type"=>$FieldType1 {"Name"},1824 "Type_Type"=>$Type1{"Type"} 1222 "Field_Type"=>$FieldType1_Name, 1223 "Type_Type"=>$Type1{"Type"}); 1825 1224 } 1826 1225 else … … 1830 1229 "Type_Name"=>$Type1{"Name"}, 1831 1230 "Type_Type"=>$Type1{"Type"}, 1832 "Field_Type"=>$FieldType1 {"Name"});1231 "Field_Type"=>$FieldType1_Name); 1833 1232 } 1834 1233 } 1835 1234 next; 1836 1235 } 1236 1837 1237 my $FieldType2_Id = $Type2{"Fields"}{$Field_Name}{"Type"}; 1838 my %FieldType2 = get_Type($FieldType2_Id, 2);1238 my $FieldType2_Name = getTypeName($FieldType2_Id, 2); 1839 1239 1840 1240 if(not $Type1{"Fields"}{$Field_Name}{"Static"} … … 1845 1245 %{$SubProblems{"NonConstant_Field_Became_Static"}{$Field_Name}}=( 1846 1246 "Target"=>$Field_Name, 1847 "Field_Type"=>$FieldType1 {"Name"},1848 "Type_Name"=>$Type1{"Name"} 1247 "Field_Type"=>$FieldType1_Name, 1248 "Type_Name"=>$Type1{"Name"}); 1849 1249 } 1850 1250 } … … 1856 1256 %{$SubProblems{"Constant_Field_Became_NonStatic"}{$Field_Name}}=( 1857 1257 "Target"=>$Field_Name, 1858 "Field_Type"=>$FieldType1 {"Name"},1859 "Type_Name"=>$Type1{"Name"} 1258 "Field_Type"=>$FieldType1_Name, 1259 "Type_Name"=>$Type1{"Name"}); 1860 1260 } 1861 1261 else … … 1863 1263 %{$SubProblems{"NonConstant_Field_Became_NonStatic"}{$Field_Name}}=( 1864 1264 "Target"=>$Field_Name, 1865 "Field_Type"=>$FieldType1 {"Name"},1866 "Type_Name"=>$Type1{"Name"} 1265 "Field_Type"=>$FieldType1_Name, 1266 "Type_Name"=>$Type1{"Name"}); 1867 1267 } 1868 1268 } … … 1872 1272 %{$SubProblems{"Field_Became_Final"}{$Field_Name}}=( 1873 1273 "Target"=>$Field_Name, 1874 "Field_Type"=>$FieldType1 {"Name"},1875 "Type_Name"=>$Type1{"Name"} 1274 "Field_Type"=>$FieldType1_Name, 1275 "Type_Name"=>$Type1{"Name"}); 1876 1276 } 1877 1277 elsif($Type1{"Fields"}{$Field_Name}{"Final"} … … 1880 1280 %{$SubProblems{"Field_Became_NonFinal"}{$Field_Name}}=( 1881 1281 "Target"=>$Field_Name, 1882 "Field_Type"=>$FieldType1 {"Name"},1883 "Type_Name"=>$Type1{"Name"} 1282 "Field_Type"=>$FieldType1_Name, 1283 "Type_Name"=>$Type1{"Name"}); 1884 1284 } 1885 1285 my $Access2 = $Type2{"Fields"}{$Field_Name}{"Access"}; … … 1887 1287 or $Access1 eq "protected" and $Access2=~/private/) 1888 1288 { 1889 %{$SubProblems{"Changed_Field_Access"}{$Field_Name}}=( 1890 "Target"=>$Field_Name, 1891 "Type_Name"=>$Type1{"Name"}, 1892 "Old_Value"=>$Access1, 1893 "New_Value"=>$Access2 ); 1894 } 1895 1896 my $Value1 = get_ConstantValue($Type1{"Fields"}{$Field_Name}{"Value"}, $FieldType1{"Name"}); 1897 my $Value2 = get_ConstantValue($Type2{"Fields"}{$Field_Name}{"Value"}, $FieldType2{"Name"}); 1289 if($Access2 eq "package-private") 1290 { 1291 %{$SubProblems{"Changed_Field_Access_To_Package_Private"}{$Field_Name}}=( 1292 "Target"=>$Field_Name, 1293 "Type_Name"=>$Type1{"Name"}, 1294 "Old_Value"=>$Access1, 1295 "New_Value"=>$Access2); 1296 } 1297 else 1298 { 1299 %{$SubProblems{"Changed_Field_Access"}{$Field_Name}}=( 1300 "Target"=>$Field_Name, 1301 "Type_Name"=>$Type1{"Name"}, 1302 "Old_Value"=>$Access1, 1303 "New_Value"=>$Access2); 1304 } 1305 } 1306 1307 my $Value1 = getConstantValue($Type1{"Fields"}{$Field_Name}{"Value"}, $FieldType1_Name); 1308 my $Value2 = getConstantValue($Type2{"Fields"}{$Field_Name}{"Value"}, $FieldType2_Name); 1898 1309 1899 1310 if($Value1 ne $Value2) … … 1908 1319 %{$SubProblems{"Changed_Final_Version_Field_Value"}{$Field_Name}}=( 1909 1320 "Target"=>$Field_Name, 1910 "Field_Type"=>$FieldType1 {"Name"},1321 "Field_Type"=>$FieldType1_Name, 1911 1322 "Type_Name"=>$Type1{"Name"}, 1912 1323 "Old_Value"=>$Value1, 1913 "New_Value"=>$Value2 1324 "New_Value"=>$Value2); 1914 1325 } 1915 1326 else … … 1917 1328 %{$SubProblems{"Changed_Final_Field_Value"}{$Field_Name}}=( 1918 1329 "Target"=>$Field_Name, 1919 "Field_Type"=>$FieldType1 {"Name"},1330 "Field_Type"=>$FieldType1_Name, 1920 1331 "Type_Name"=>$Type1{"Name"}, 1921 1332 "Old_Value"=>$Value1, 1922 "New_Value"=>$Value2 1333 "New_Value"=>$Value2); 1923 1334 } 1924 1335 } … … 1948 1359 foreach my $Sub_SubLocation (sort {length($a)<=>length($b)} sort keys(%{$Sub_SubProblems->{$Sub_SubProblemType}})) 1949 1360 { 1950 if(not defined $ AllAffected)1361 if(not defined $In::Opt{"AllAffected"}) 1951 1362 { 1952 1363 if(defined $DupProblems{$Sub_SubProblems->{$Sub_SubProblemType}{$Sub_SubLocation}}) { … … 1958 1369 $SubProblems{$Sub_SubProblemType}{$NewLocation} = $Sub_SubProblems->{$Sub_SubProblemType}{$Sub_SubLocation}; 1959 1370 1960 if(not defined $ AllAffected)1371 if(not defined $In::Opt{"AllAffected"}) 1961 1372 { 1962 1373 $DupProblems{$Sub_SubProblems->{$Sub_SubProblemType}{$Sub_SubLocation}} = 1; … … 1975 1386 my $FieldPos2 = $Type2{"Fields"}{$Field_Name}{"Pos"}; 1976 1387 my $FieldType2_Id = $Type2{"Fields"}{$Field_Name}{"Type"}; 1977 my %FieldType2 = get_Type($FieldType2_Id, 2);1388 my $FieldType2_Name = getTypeName($FieldType2_Id, 2); 1978 1389 1979 1390 if(not $Type1{"Fields"}{$Field_Name}) … … 1981 1392 my $StraightPair_Name = findFieldPair($FieldPos2, \%Type1); 1982 1393 if($StraightPair_Name ne "lost" and not $Type2{"Fields"}{$StraightPair_Name} 1983 and get _TypeName($Type1{"Fields"}{$StraightPair_Name}{"Type"}, 1) eq $FieldType2{"Name"})1394 and getTypeName($Type1{"Fields"}{$StraightPair_Name}{"Type"}, 1) eq $FieldType2_Name) 1984 1395 { 1985 1396 # Already reported as "Renamed_Field" or "Renamed_Constant_Field" … … 1991 1402 %{$SubProblems{"Interface_Added_Field"}{$Field_Name}}=( 1992 1403 "Target"=>$Field_Name, 1993 "Type_Name"=>$Type1{"Name"} 1404 "Type_Name"=>$Type1{"Name"}); 1994 1405 } 1995 1406 else … … 1997 1408 %{$SubProblems{"Class_Added_Field"}{$Field_Name}}=( 1998 1409 "Target"=>$Field_Name, 1999 "Type_Name"=>$Type1{"Name"} 1410 "Type_Name"=>$Type1{"Name"}); 2000 1411 } 2001 1412 } … … 2010 1421 { # Check if all abstract methods of the super class have 2011 1422 # default implementations in the class 2012 my ($L ibVersion, $SuperClassName, $ClassName) = @_;2013 2014 foreach my $Method (keys(%{$Class_AbstractMethods{$L ibVersion}{$SuperClassName}}))2015 { 2016 if(my $Overridden = findMethod_Class($Method, $ClassName, $L ibVersion))2017 { 2018 if($MethodInfo{$L ibVersion}{$Overridden}{"Abstract"}) {1423 my ($LVer, $SuperClassName, $ClassName) = @_; 1424 1425 foreach my $Method (keys(%{$Class_AbstractMethods{$LVer}{$SuperClassName}})) 1426 { 1427 if(my $Overridden = findMethod_Class($Method, $ClassName, $LVer)) 1428 { 1429 if($MethodInfo{$LVer}{$Overridden}{"Abstract"}) { 2019 1430 return 0; 2020 1431 } … … 2028 1439 } 2029 1440 2030 sub unmangle($) 2031 { 2032 my $Name = $_[0]; 2033 $Name=~s!/!.!g; 2034 $Name=~s!:\(!(!g; 2035 $Name=~s!\).+\Z!)!g; 2036 if($Name=~/\A(.+)\((.+)\)/) 2037 { 2038 my ($ShortName, $MangledParams) = ($1, $2); 2039 my @UnmangledParams = (); 2040 my ($IsArray, $Shift, $Pos, $CurParam) = (0, 0, 0, ""); 2041 while($Pos<length($MangledParams)) 2042 { 2043 my $Symbol = substr($MangledParams, $Pos, 1); 2044 if($Symbol eq "[") 2045 { # array 2046 $IsArray = 1; 2047 $Pos+=1; 2048 } 2049 elsif($Symbol eq "L") 2050 { # class 2051 if(substr($MangledParams, $Pos+1)=~/\A(.+?);/) { 2052 $CurParam = $1; 2053 $Shift = length($CurParam)+2; 2054 } 2055 if($IsArray) { 2056 $CurParam .= "[]"; 2057 } 2058 $Pos+=$Shift; 2059 push(@UnmangledParams, $CurParam); 2060 ($IsArray, $Shift, $CurParam) = (0, 0, "") 2061 } 2062 else 2063 { 2064 if($Symbol eq "C") { 2065 $CurParam = "char"; 2066 } 2067 elsif($Symbol eq "B") { 2068 $CurParam = "byte"; 2069 } 2070 elsif($Symbol eq "S") { 2071 $CurParam = "short"; 2072 } 2073 elsif($Symbol eq "S") { 2074 $CurParam = "short"; 2075 } 2076 elsif($Symbol eq "I") { 2077 $CurParam = "int"; 2078 } 2079 elsif($Symbol eq "F") { 2080 $CurParam = "float"; 2081 } 2082 elsif($Symbol eq "J") { 2083 $CurParam = "long"; 2084 } 2085 elsif($Symbol eq "D") { 2086 $CurParam = "double"; 2087 } 2088 else { 2089 printMsg("INFO", "WARNING: unmangling error"); 2090 } 2091 if($IsArray) { 2092 $CurParam .= "[]"; 2093 } 2094 $Pos+=1; 2095 push(@UnmangledParams, $CurParam); 2096 ($IsArray, $Shift, $CurParam) = (0, 0, "") 2097 } 2098 } 2099 return $ShortName."(".join(", ", @UnmangledParams).")"; 2100 } 2101 else { 2102 return $Name; 2103 } 2104 } 2105 2106 sub get_TypeName($$) 2107 { 2108 my ($TypeId, $LibVersion) = @_; 2109 return $TypeInfo{$LibVersion}{$TypeId}{"Name"}; 2110 } 2111 2112 sub get_ShortName($$) 2113 { 2114 my ($TypeId, $LibVersion) = @_; 2115 my $TypeName = $TypeInfo{$LibVersion}{$TypeId}{"Name"}; 2116 $TypeName=~s/\A.*\.//g; 2117 return $TypeName; 2118 } 2119 2120 sub get_TypeType($$) 2121 { 2122 my ($TypeId, $LibVersion) = @_; 2123 return $TypeInfo{$LibVersion}{$TypeId}{"Type"}; 2124 } 2125 2126 sub get_TypeHeader($$) 2127 { 2128 my ($TypeId, $LibVersion) = @_; 2129 return $TypeInfo{$LibVersion}{$TypeId}{"Header"}; 2130 } 2131 2132 sub get_BaseType($$) 2133 { 2134 my ($TypeId, $LibVersion) = @_; 2135 return "" if(not $TypeId); 2136 if(defined $Cache{"get_BaseType"}{$TypeId}{$LibVersion}) { 2137 return %{$Cache{"get_BaseType"}{$TypeId}{$LibVersion}}; 2138 } 2139 return "" if(not $TypeInfo{$LibVersion}{$TypeId}); 2140 my %Type = %{$TypeInfo{$LibVersion}{$TypeId}}; 2141 return %Type if(not $Type{"BaseType"}); 2142 %Type = get_BaseType($Type{"BaseType"}, $LibVersion); 2143 $Cache{"get_BaseType"}{$TypeId}{$LibVersion} = \%Type; 2144 return %Type; 2145 } 2146 2147 sub get_OneStep_BaseType($$) 2148 { 2149 my ($TypeId, $LibVersion) = @_; 2150 return "" if(not $TypeId); 2151 return "" if(not $TypeInfo{$LibVersion}{$TypeId}); 2152 my %Type = %{$TypeInfo{$LibVersion}{$TypeId}}; 2153 return %Type if(not $Type{"BaseType"}); 2154 return get_Type($Type{"BaseType"}, $LibVersion); 2155 } 2156 2157 sub get_Type($$) 2158 { 2159 my ($TypeId, $LibVersion) = @_; 2160 return "" if(not $TypeId); 2161 return "" if(not $TypeInfo{$LibVersion}{$TypeId}); 2162 return %{$TypeInfo{$LibVersion}{$TypeId}}; 2163 } 2164 2165 sub classFilter($$$) 2166 { 2167 my ($Class, $LibVersion, $ClassContext) = @_; 2168 2169 if(defined $Class->{"Dep"}) { 2170 return 0; 2171 } 2172 2173 my $CName = $Class->{"Name"}; 2174 my $Package = $Class->{"Package"}; 2175 2176 if(defined $ClassListPath 2177 and not defined $ClassList_User{$CName}) 2178 { # user defined classes 2179 return 0; 2180 } 2181 2182 if(defined $SkipClassesList 2183 and defined $SkipClasses{$CName}) 2184 { # user defined classes 2185 return 0; 2186 } 2187 2188 if(skipPackage($Package, $LibVersion)) 2189 { # internal packages 2190 return 0; 2191 } 2192 2193 if(skipType($CName)) 2194 { # internal types 2195 return 0; 2196 } 2197 2198 if($ClassContext) 2199 { 2200 my @Ann = (); 2201 2202 if(defined $Class->{"Annotations"}) { 2203 @Ann = keys(%{$Class->{"Annotations"}}); 2204 } 2205 2206 if(not annotationFilter(\@Ann, $LibVersion)) { 2207 return 0; 2208 } 2209 2210 if($ClientPath) 2211 { 2212 if(not defined $UsedClasses_Client{$CName}) { 2213 return 0; 2214 } 2215 } 2216 } 2217 2218 return 1; 2219 } 2220 2221 sub annotationFilter($$) 2222 { 2223 my ($Ann, $LibVersion) = @_; 2224 2225 if(not defined $CountMethods) 2226 { 2227 if(defined $AddedAnnotations and $LibVersion==1) { 2228 return 1; 2229 } 2230 2231 if(defined $RemovedAnnotations and $LibVersion==2) { 2232 return 1; 2233 } 2234 } 2235 2236 if($SkipAnnotationsListPath) 2237 { 2238 foreach my $Aid (@{$Ann}) 2239 { 2240 my $AName = $TypeInfo{$LibVersion}{$Aid}{"Name"}; 2241 2242 if(defined $SkipAnnotationList_User{$AName}) { 2243 return 0; 2244 } 2245 } 2246 } 2247 2248 if($AnnotationsListPath) 2249 { 2250 my $Annotated = 0; 2251 2252 foreach my $Aid (@{$Ann}) 2253 { 2254 my $AName = $TypeInfo{$LibVersion}{$Aid}{"Name"}; 2255 2256 if(defined $AnnotationList_User{$AName}) 2257 { 2258 $Annotated = 1; 2259 last; 2260 } 2261 } 2262 2263 if(not $Annotated) { 2264 return 0; 2265 } 2266 } 2267 2268 return 1; 2269 } 2270 2271 sub methodFilter($$) 2272 { 2273 my ($Method, $LibVersion) = @_; 2274 2275 if(defined $MethodInfo{$LibVersion}{$Method}{"Dep"}) { 2276 return 0; 2277 } 2278 2279 if($MethodInfo{$LibVersion}{$Method}{"Access"}=~/private/) 2280 { # non-public 2281 return 0; 2282 } 2283 2284 my $ClassId = $MethodInfo{$LibVersion}{$Method}{"Class"}; 2285 my %Class = get_Type($ClassId, $LibVersion); 2286 2287 if($Class{"Access"}=~/private/) 2288 { # skip private classes 2289 return 0; 2290 } 2291 2292 my $Package = $MethodInfo{$LibVersion}{$Method}{"Package"}; 2293 2294 my @Ann = (); 2295 2296 if(defined $Class{"Annotations"}) { 2297 @Ann = (@Ann, keys(%{$Class{"Annotations"}})); 2298 } 2299 2300 if(defined $MethodInfo{$LibVersion}{$Method}{"Annotations"}) { 2301 @Ann = (@Ann, keys(%{$MethodInfo{$LibVersion}{$Method}{"Annotations"}})); 2302 } 2303 2304 if(not annotationFilter(\@Ann, $LibVersion)) { 2305 return 0; 2306 } 2307 2308 if($ClientPath) 2309 { # user defined application 2310 if(not defined $UsedMethods_Client{$Method} 2311 and not defined $UsedClasses_Client{$Class{"Name"}}) { 2312 return 0; 2313 } 2314 } 2315 2316 if(skipPackage($Package, $LibVersion)) 2317 { # internal packages 2318 return 0; 2319 } 2320 2321 if(not classFilter(\%Class, $LibVersion, 0)) { 2322 return 0; 2323 } 2324 2325 if(defined $SkipDeprecated) 2326 { 2327 if($Class{"Deprecated"}) 2328 { # deprecated class 2329 return 0; 2330 } 2331 if($MethodInfo{$LibVersion}{$Method}{"Deprecated"}) 2332 { # deprecated method 2333 return 0; 2334 } 2335 } 2336 2337 return 1; 2338 } 2339 2340 sub skipType($) 2341 { 2342 my $TName = $_[0]; 2343 2344 if(defined $SkipInternalTypes) 2345 { 2346 if($TName=~/($SkipInternalTypes)/) { 2347 return 1; 2348 } 2349 } 2350 2351 return 0; 2352 } 2353 2354 sub skipPackage($$) 2355 { 2356 my ($Package, $LibVersion) = @_; 2357 return 0 if(not $Package); 2358 2359 if(defined $SkipInternalPackages) 2360 { 2361 if($Package=~/($SkipInternalPackages)/) { 2362 return 1; 2363 } 2364 } 2365 2366 if(defined $SkipPackages{$LibVersion}) 2367 { 2368 foreach my $SkipPackage (keys(%{$SkipPackages{$LibVersion}})) 2369 { 2370 if($Package=~/\A\Q$SkipPackage\E(\.|\Z)/) 2371 { # user skipped packages 2372 return 1; 2373 } 2374 } 2375 } 2376 2377 if(not defined $KeepInternal) 2378 { 2379 my $Note = (not keys %SkippedPackage)?" (use --keep-internal option to check them)":""; 2380 2381 if($Package=~/(\A|\.)(internal|impl|examples)(\.|\Z)/) 2382 { # internal packages 2383 if(not $SkippedPackage{$LibVersion}{$2}) 2384 { 2385 $SkippedPackage{$LibVersion}{$2} = 1; 2386 printMsg("WARNING", "skip \"$2\" packages".$Note); 2387 } 2388 return 1; 2389 } 2390 } 2391 2392 if(defined $KeepPackages{$LibVersion} 2393 and my @Keeped = keys(%{$KeepPackages{$LibVersion}})) 2394 { 2395 my $UserKeeped = 0; 2396 foreach my $KeepPackage (@Keeped) 2397 { 2398 if($Package=~/\A\Q$KeepPackage\E(\.|\Z)/) 2399 { # user keeped packages 2400 $UserKeeped = 1; 2401 last; 2402 } 2403 } 2404 if(not $UserKeeped) { 2405 return 1; 2406 } 2407 } 2408 2409 return 0; 2410 } 2411 2412 sub get_MSuffix($) 1441 sub getMSuffix($) 2413 1442 { 2414 1443 my $Method = $_[0]; … … 2419 1448 } 2420 1449 2421 sub get _MShort($)1450 sub getMShort($) 2422 1451 { 2423 1452 my $Method = $_[0]; … … 2436 1465 { 2437 1466 my @Search = (); 2438 if(get _TypeType($ClassId, $ClassVersion) eq "class")1467 if(getTypeType($ClassId, $ClassVersion) eq "class") 2439 1468 { 2440 1469 if(my $SuperClassId = $TypeInfo{$ClassVersion}{$ClassId}{"SuperClass"}) { … … 2457 1486 } 2458 1487 2459 my $SuperName = get _TypeName($SuperId, $ClassVersion);1488 my $SuperName = getTypeName($SuperId, $ClassVersion); 2460 1489 2461 1490 if(my $MethodInClass = findMethod_Class($Method, $SuperName, $ClassVersion)) { … … 2468 1497 } 2469 1498 2470 my $TargetSuffix = get _MSuffix($Method);2471 my $TargetShortName = get _MShort($Method);1499 my $TargetSuffix = getMSuffix($Method); 1500 my $TargetShortName = getMShort($Method); 2472 1501 2473 1502 # search in java.lang.Object 2474 1503 foreach my $C (keys(%JavaObjectMethod)) 2475 1504 { 2476 if($TargetSuffix eq get _MSuffix($C))2477 { 2478 if($TargetShortName eq get _MShort($C)) {1505 if($TargetSuffix eq getMSuffix($C)) 1506 { 1507 if($TargetShortName eq getMShort($C)) { 2479 1508 return $C; 2480 1509 } … … 2488 1517 { 2489 1518 my ($Method, $ClassName, $ClassVersion) = @_; 2490 my $TargetSuffix = get _MSuffix($Method);2491 my $TargetShortName = get _MShort($Method);1519 my $TargetSuffix = getMSuffix($Method); 1520 my $TargetShortName = getMShort($Method); 2492 1521 2493 1522 if(not defined $Class_Methods{$ClassVersion}{$ClassName}) { … … 2498 1527 { # search for method with the same parameters suffix 2499 1528 next if($MethodInfo{$ClassVersion}{$Candidate}{"Constructor"}); 2500 if($TargetSuffix eq get _MSuffix($Candidate))2501 { 2502 if($TargetShortName eq get _MShort($Candidate)) {1529 if($TargetSuffix eq getMSuffix($Candidate)) 1530 { 1531 if($TargetShortName eq getMShort($Candidate)) { 2503 1532 return $Candidate; 2504 1533 } … … 2509 1538 } 2510 1539 2511 sub prepareMethods($) 2512 { 2513 my $LibVersion = $_[0]; 2514 foreach my $Method (keys(%{$MethodInfo{$LibVersion}})) 2515 { 2516 if($MethodInfo{$LibVersion}{$Method}{"Access"}!~/private/) 2517 { 2518 if($MethodInfo{$LibVersion}{$Method}{"Constructor"}) { 2519 registerUsage($MethodInfo{$LibVersion}{$Method}{"Class"}, $LibVersion); 1540 sub prepareData($) 1541 { 1542 my $LVer = $_[0]; 1543 1544 if(my $MUsed = $In::API{$LVer}{"MethodUsed"}) 1545 { 1546 foreach my $M_Id (keys(%{$MUsed})) 1547 { 1548 my $Name = $MUsed->{$M_Id}{"Name"}; 1549 $MethodUsed{$LVer}{$Name} = $MUsed->{$M_Id}{"Used"}; 1550 } 1551 } 1552 1553 foreach my $TypeId (keys(%{$TypeInfo{$LVer}})) 1554 { 1555 my $TypeAttr = $TypeInfo{$LVer}{$TypeId}; 1556 my $TName = $TypeAttr->{"Name"}; 1557 1558 $TName_Tid{$LVer}{$TName} = $TypeId; 1559 1560 if(not $TypeAttr->{"Dep"}) 1561 { 1562 if(my $Archive = $TypeAttr->{"Archive"}) { 1563 $LibArchives{$LVer}{$Archive} = 1; 1564 } 1565 } 1566 1567 foreach my $FieldName (keys(%{$TypeAttr->{"Fields"}})) 1568 { 1569 if($TypeAttr->{"Fields"}{$FieldName}{"Access"}=~/public|protected/) { 1570 $Class_Fields{$LVer}{$TName}{$FieldName} = $TypeAttr->{"Fields"}{$FieldName}{"Type"}; 1571 } 1572 } 1573 } 1574 1575 foreach my $Method (keys(%{$MethodInfo{$LVer}})) 1576 { 1577 my $Name = $MethodInfo{$LVer}{$Method}{"Name"}; 1578 $MethodInfo{$LVer}{$Name} = delete($MethodInfo{$LVer}{$Method}); 1579 } 1580 1581 foreach my $Method (keys(%{$MethodInfo{$LVer}})) 1582 { 1583 my $MAttr = $MethodInfo{$LVer}{$Method}; 1584 1585 $MAttr->{"Signature"} = getSignature($Method, $LVer, "Full"); 1586 1587 if(my $ClassId = $MAttr->{"Class"} 1588 and $MAttr->{"Access"}=~/public|protected/) 1589 { 1590 my $CName = getTypeName($ClassId, $LVer); 1591 $Class_Methods{$LVer}{$CName}{$Method} = 1; 1592 if($MAttr->{"Abstract"}) { 1593 $Class_AbstractMethods{$LVer}{$CName}{$Method} = 1; 1594 } 1595 } 1596 1597 if($MAttr->{"Access"}!~/private/) 1598 { 1599 if($MAttr->{"Constructor"}) { 1600 registerUsage($MAttr->{"Class"}, $LVer); 2520 1601 } 2521 1602 else { 2522 registerUsage($M ethodInfo{$LibVersion}{$Method}{"Return"}, $LibVersion);1603 registerUsage($MAttr->{"Return"}, $LVer); 2523 1604 } 2524 1605 } … … 2542 1623 2543 1624 my $ClassId1 = $MethodInfo{1}{$Method}{"Class"}; 2544 my %Class1 = get_Type($ClassId1, 1); 2545 2546 $CheckedTypes{$Class1{"Name"}} = 1; 1625 my $Class1_Name = getTypeName($ClassId1, 1); 1626 my $Class1_Type = getTypeType($ClassId1, 1); 1627 1628 $CheckedTypes{$Class1_Name} = 1; 2547 1629 $CheckedMethods{$Method} = 1; 2548 1630 2549 my %Class2 = get_Type($MethodInfo{2}{$Method}{"Class"}, 2);2550 1631 if(not $MethodInfo{1}{$Method}{"Static"} 2551 and $Class1 {"Type"}eq "class" and not $Class_Constructed{1}{$ClassId1})1632 and $Class1_Type eq "class" and not $Class_Constructed{1}{$ClassId1}) 2552 1633 { # class cannot be constructed or inherited by clients 2553 1634 # non-static method cannot be called 2554 1635 next; 2555 1636 } 1637 2556 1638 # checking attributes 2557 1639 if(not $MethodInfo{1}{$Method}{"Static"} … … 2563 1645 %{$CompatProblems{$Method}{"Method_Became_NonStatic"}{""}} = (); 2564 1646 } 1647 2565 1648 if(not $MethodInfo{1}{$Method}{"Synchronized"} 2566 1649 and $MethodInfo{2}{$Method}{"Synchronized"}) { … … 2571 1654 %{$CompatProblems{$Method}{"Method_Became_NonSynchronized"}{""}} = (); 2572 1655 } 1656 2573 1657 if(not $MethodInfo{1}{$Method}{"Final"} 2574 1658 and $MethodInfo{2}{$Method}{"Final"}) … … 2581 1665 } 2582 1666 } 1667 2583 1668 my $Access1 = $MethodInfo{1}{$Method}{"Access"}; 2584 1669 my $Access2 = $MethodInfo{2}{$Method}{"Access"}; 1670 2585 1671 if($Access1 eq "public" and $Access2=~/protected|private/ 2586 1672 or $Access1 eq "protected" and $Access2=~/private/) … … 2588 1674 %{$CompatProblems{$Method}{"Changed_Method_Access"}{""}} = ( 2589 1675 "Old_Value"=>$Access1, 2590 "New_Value"=>$Access2 ); 2591 } 2592 if($Class1{"Type"} eq "class" 2593 and $Class2{"Type"} eq "class") 1676 "New_Value"=>$Access2); 1677 } 1678 1679 my $Class2_Type = getTypeType($MethodInfo{2}{$Method}{"Class"}, 2); 1680 1681 if($Class1_Type eq "class" 1682 and $Class2_Type eq "class") 2594 1683 { 2595 1684 if(not $MethodInfo{1}{$Method}{"Abstract"} … … 2597 1686 { 2598 1687 %{$CompatProblems{$Method}{"Method_Became_Abstract"}{""}} = (); 2599 %{$CompatProblems{$Method}{"Class_Method_Became_Abstract"}{"this.".get _SFormat($Method)}} = (2600 "Type_Name"=>$Class1 {"Name"},2601 "Target"=>$Method 1688 %{$CompatProblems{$Method}{"Class_Method_Became_Abstract"}{"this.".getSFormat($Method)}} = ( 1689 "Type_Name"=>$Class1_Name, 1690 "Target"=>$Method); 2602 1691 } 2603 1692 elsif($MethodInfo{1}{$Method}{"Abstract"} … … 2605 1694 { 2606 1695 %{$CompatProblems{$Method}{"Method_Became_NonAbstract"}{""}} = (); 2607 %{$CompatProblems{$Method}{"Class_Method_Became_NonAbstract"}{"this.".get _SFormat($Method)}} = (2608 "Type_Name"=>$Class1 {"Name"},2609 "Target"=>$Method 2610 } 2611 } 2612 elsif($Class1 {"Type"}eq "interface"2613 and $Class2 {"Type"}eq "interface")1696 %{$CompatProblems{$Method}{"Class_Method_Became_NonAbstract"}{"this.".getSFormat($Method)}} = ( 1697 "Type_Name"=>$Class1_Name, 1698 "Target"=>$Method); 1699 } 1700 } 1701 elsif($Class1_Type eq "interface" 1702 and $Class2_Type eq "interface") 2614 1703 { 2615 1704 if(not $MethodInfo{1}{$Method}{"Abstract"} … … 2617 1706 { 2618 1707 %{$CompatProblems{$Method}{"Method_Became_NonDefault"}{""}} = (); 2619 %{$CompatProblems{$Method}{"Interface_Method_Became_NonDefault"}{"this.".get _SFormat($Method)}} = (2620 "Type_Name"=>$Class1 {"Name"},2621 "Target"=>$Method 1708 %{$CompatProblems{$Method}{"Interface_Method_Became_NonDefault"}{"this.".getSFormat($Method)}} = ( 1709 "Type_Name"=>$Class1_Name, 1710 "Target"=>$Method); 2622 1711 } 2623 1712 elsif($MethodInfo{1}{$Method}{"Abstract"} … … 2625 1714 { 2626 1715 %{$CompatProblems{$Method}{"Method_Became_Default"}{""}} = (); 2627 %{$CompatProblems{$Method}{"Interface_Method_Became_Default"}{"this.".get _SFormat($Method)}} = (2628 "Type_Name"=>$Class1 {"Name"},2629 "Target"=>$Method 2630 } 2631 } 2632 2633 my %Exceptions_Old = map {get _TypeName($_, 1) => $_} keys(%{$MethodInfo{1}{$Method}{"Exceptions"}});2634 my %Exceptions_New = map {get _TypeName($_, 2) => $_} keys(%{$MethodInfo{2}{$Method}{"Exceptions"}});1716 %{$CompatProblems{$Method}{"Interface_Method_Became_Default"}{"this.".getSFormat($Method)}} = ( 1717 "Type_Name"=>$Class1_Name, 1718 "Target"=>$Method); 1719 } 1720 } 1721 1722 my %Exceptions_Old = map {getTypeName($_, 1) => $_} keys(%{$MethodInfo{1}{$Method}{"Exceptions"}}); 1723 my %Exceptions_New = map {getTypeName($_, 2) => $_} keys(%{$MethodInfo{2}{$Method}{"Exceptions"}}); 2635 1724 foreach my $Exception (keys(%Exceptions_Old)) 2636 1725 { 2637 1726 if(not $Exceptions_New{$Exception}) 2638 1727 { 2639 my %ExceptionType = get_Type($Exceptions_Old{$Exception}, 1); 2640 my $SuperClass = $ExceptionType{"SuperClass"}; 1728 my $EType = getType($Exceptions_Old{$Exception}, 1); 1729 my $SuperClass = $EType->{"SuperClass"}; 1730 2641 1731 if($KnownRuntimeExceptions{$Exception} 2642 or defined $SuperClass and get _TypeName($SuperClass, 1) eq "java.lang.RuntimeException")1732 or defined $SuperClass and getTypeName($SuperClass, 1) eq "java.lang.RuntimeException") 2643 1733 { 2644 1734 if(not $MethodInfo{1}{$Method}{"Abstract"} 2645 1735 and not $MethodInfo{2}{$Method}{"Abstract"}) 2646 1736 { 2647 %{$CompatProblems{$Method}{"Removed_Unchecked_Exception"}{"this.".get _SFormat($Exception)}} = (2648 "Type_Name"=>$Class1 {"Name"},2649 "Target"=>$Exception 1737 %{$CompatProblems{$Method}{"Removed_Unchecked_Exception"}{"this.".getSFormat($Exception)}} = ( 1738 "Type_Name"=>$Class1_Name, 1739 "Target"=>$Exception); 2650 1740 } 2651 1741 } … … 2655 1745 and $MethodInfo{2}{$Method}{"Abstract"}) 2656 1746 { 2657 %{$CompatProblems{$Method}{"Abstract_Method_Removed_Checked_Exception"}{"this.".get _SFormat($Exception)}} = (2658 "Type_Name"=>$Class1 {"Name"},2659 "Target"=>$Exception 1747 %{$CompatProblems{$Method}{"Abstract_Method_Removed_Checked_Exception"}{"this.".getSFormat($Exception)}} = ( 1748 "Type_Name"=>$Class1_Name, 1749 "Target"=>$Exception); 2660 1750 } 2661 1751 else 2662 1752 { 2663 %{$CompatProblems{$Method}{"NonAbstract_Method_Removed_Checked_Exception"}{"this.".get_SFormat($Exception)}} = ( 2664 "Type_Name"=>$Class1{"Name"}, 2665 "Target"=>$Exception ); 2666 } 2667 } 2668 } 2669 } 1753 %{$CompatProblems{$Method}{"NonAbstract_Method_Removed_Checked_Exception"}{"this.".getSFormat($Exception)}} = ( 1754 "Type_Name"=>$Class1_Name, 1755 "Target"=>$Exception); 1756 } 1757 } 1758 } 1759 } 1760 2670 1761 foreach my $Exception (keys(%Exceptions_New)) 2671 1762 { 2672 1763 if(not $Exceptions_Old{$Exception}) 2673 1764 { 2674 my %ExceptionType = get_Type($Exceptions_New{$Exception}, 2); 2675 my $SuperClass = $ExceptionType{"SuperClass"}; 1765 my $EType = getType($Exceptions_New{$Exception}, 2); 1766 my $SuperClass = $EType->{"SuperClass"}; 1767 2676 1768 if($KnownRuntimeExceptions{$Exception} 2677 or defined $SuperClass and get _TypeName($SuperClass, 2) eq "java.lang.RuntimeException")1769 or defined $SuperClass and getTypeName($SuperClass, 2) eq "java.lang.RuntimeException") 2678 1770 { 2679 1771 if(not $MethodInfo{1}{$Method}{"Abstract"} 2680 1772 and not $MethodInfo{2}{$Method}{"Abstract"}) 2681 1773 { 2682 %{$CompatProblems{$Method}{"Added_Unchecked_Exception"}{"this.".get _SFormat($Exception)}} = (2683 "Type_Name"=>$Class1 {"Name"},2684 "Target"=>$Exception 1774 %{$CompatProblems{$Method}{"Added_Unchecked_Exception"}{"this.".getSFormat($Exception)}} = ( 1775 "Type_Name"=>$Class1_Name, 1776 "Target"=>$Exception); 2685 1777 } 2686 1778 } … … 2690 1782 and $MethodInfo{2}{$Method}{"Abstract"}) 2691 1783 { 2692 %{$CompatProblems{$Method}{"Abstract_Method_Added_Checked_Exception"}{"this.".get _SFormat($Exception)}} = (2693 "Type_Name"=>$Class1 {"Name"},2694 "Target"=>$Exception 1784 %{$CompatProblems{$Method}{"Abstract_Method_Added_Checked_Exception"}{"this.".getSFormat($Exception)}} = ( 1785 "Type_Name"=>$Class1_Name, 1786 "Target"=>$Exception); 2695 1787 } 2696 1788 else 2697 1789 { 2698 %{$CompatProblems{$Method}{"NonAbstract_Method_Added_Checked_Exception"}{"this.".get _SFormat($Exception)}} = (2699 "Type_Name"=>$Class1 {"Name"},2700 "Target"=>$Exception 1790 %{$CompatProblems{$Method}{"NonAbstract_Method_Added_Checked_Exception"}{"this.".getSFormat($Exception)}} = ( 1791 "Type_Name"=>$Class1_Name, 1792 "Target"=>$Exception); 2701 1793 } 2702 1794 } … … 2779 1871 my ($Type1_Id, $Type2_Id, $Prefix) = @_; 2780 1872 my %LocalProblems = (); 2781 my %Type1 = get_Type($Type1_Id, 1); 2782 my %Type2 = get_Type($Type2_Id, 2); 2783 my %Type1_Base = ($Type1{"Type"} eq "array")?get_OneStep_BaseType($Type1_Id, 1):get_BaseType($Type1_Id, 1); 2784 my %Type2_Base = ($Type2{"Type"} eq "array")?get_OneStep_BaseType($Type2_Id, 2):get_BaseType($Type2_Id, 2); 2785 return () if(not $Type1{"Name"} or not $Type2{"Name"}); 2786 return () if(not $Type1_Base{"Name"} or not $Type2_Base{"Name"}); 2787 if($Type1_Base{"Name"} ne $Type2_Base{"Name"} and $Type1{"Name"} eq $Type2{"Name"}) 1873 1874 my $Type1 = getType($Type1_Id, 1); 1875 my $Type2 = getType($Type2_Id, 2); 1876 1877 my $Type1_Name = $Type1->{"Name"}; 1878 my $Type2_Name = $Type2->{"Name"}; 1879 1880 my $Type1_Base = undef; 1881 my $Type2_Base = undef; 1882 1883 if($Type1->{"Type"} eq "array") { 1884 $Type1_Base = getOneStepBaseType($Type1_Id, 1); 1885 } 1886 else { 1887 $Type1_Base = getBaseType($Type1_Id, 1); 1888 } 1889 1890 if($Type2->{"Type"} eq "array") { 1891 $Type2_Base = getOneStepBaseType($Type2_Id, 2); 1892 } 1893 else { 1894 $Type2_Base = getBaseType($Type2_Id, 2); 1895 } 1896 1897 return () if(not $Type1_Name or not $Type2_Name); 1898 return () if(not $Type1_Base->{"Name"} or not $Type2_Base->{"Name"}); 1899 if($Type1_Base->{"Name"} ne $Type2_Base->{"Name"} and $Type1_Name eq $Type2_Name) 2788 1900 {# base type change 2789 1901 %{$LocalProblems{"Changed_".$Prefix."_BaseType"}}=( 2790 "Old_Value"=>$Type1_Base {"Name"},2791 "New_Value"=>$Type2_Base {"Name"});2792 } 2793 elsif($Type1 {"Name"} ne $Type2{"Name"})1902 "Old_Value"=>$Type1_Base->{"Name"}, 1903 "New_Value"=>$Type2_Base->{"Name"}); 1904 } 1905 elsif($Type1_Name ne $Type2_Name) 2794 1906 {# type change 2795 1907 %{$LocalProblems{"Changed_".$Prefix."_Type"}}=( 2796 "Old_Value"=>$Type1 {"Name"},2797 "New_Value"=>$Type2 {"Name"});1908 "Old_Value"=>$Type1_Name, 1909 "New_Value"=>$Type2_Name); 2798 1910 } 2799 1911 return %LocalProblems; 2800 1912 } 2801 1913 2802 sub htmlSpecChars($)1914 sub specChars($) 2803 1915 { 2804 1916 my $Str = $_[0]; … … 2820 1932 } 2821 1933 2822 sub black_Name($$) 1934 sub blackName($) 1935 { 1936 my $N = $_[0]; 1937 return "<span class='iname_b'>".$N."</span>"; 1938 } 1939 1940 sub highLight_ItalicColor($$) 2823 1941 { 2824 1942 my ($M, $V) = @_; 2825 return "<span class='iname_b'>".highLight_Signature($M, $V)."</span>"; 2826 } 2827 2828 sub black_Name_S($) 2829 { 2830 my $Name = $_[0]; 2831 $Name=~s!\A(\w+)!<span class='iname_b'>$1</span> !g; 2832 return $Name; 2833 } 2834 2835 sub highLight_Signature($$) 2836 { 2837 my ($M, $V) = @_; 2838 return get_Signature($M, $V, "Class|HTML|Italic"); 2839 } 2840 2841 sub highLight_Signature_Italic_Color($$) 2842 { 2843 my ($M, $V) = @_; 2844 return get_Signature($M, $V, "Full|HTML|Italic|Color"); 2845 } 2846 2847 sub get_Signature($$$) 2848 { 2849 my ($Method, $LibVersion, $Kind) = @_; 2850 if(defined $Cache{"get_Signature"}{$LibVersion}{$Method}{$Kind}) { 2851 return $Cache{"get_Signature"}{$LibVersion}{$Method}{$Kind}; 1943 return getSignature($M, $V, "Full|HTML|Italic|Color"); 1944 } 1945 1946 sub getSignature($$$) 1947 { 1948 my ($Method, $LVer, $Kind) = @_; 1949 if(defined $Cache{"getSignature"}{$LVer}{$Method}{$Kind}) { 1950 return $Cache{"getSignature"}{$LVer}{$Method}{$Kind}; 2852 1951 } 2853 1952 2854 1953 # settings 2855 1954 my ($Full, $Html, $Simple, $Italic, $Color, 2856 $ShowParams, $ShowClass, $ShowAttr, $ Target) = (0, 0, 0, 0, 0, 0, 0, 0, undef);1955 $ShowParams, $ShowClass, $ShowAttr, $Desc, $Target) = (0, 0, 0, 0, 0, 0, 0, 0, 0, undef); 2857 1956 2858 1957 if($Kind=~/Full/) { … … 2883 1982 $ShowAttr = 1; 2884 1983 } 2885 2886 if(not defined $MethodInfo{$LibVersion}{$Method}{"ShortName"}) 1984 if($Kind=~/Desc/) { 1985 $Desc = 1; 1986 } 1987 1988 if(not defined $MethodInfo{$LVer}{$Method}{"ShortName"}) 2887 1989 { # from java.lang.Object 2888 1990 if($Html or $Simple) { 2889 return htmlSpecChars($Method); 2890 } 2891 else 2892 { 1991 return specChars($Method); 1992 } 1993 else { 2893 1994 return $Method; 2894 1995 } 2895 1996 } 2896 1997 2897 my $Signature = $MethodInfo{$L ibVersion}{$Method}{"ShortName"};1998 my $Signature = $MethodInfo{$LVer}{$Method}{"ShortName"}; 2898 1999 if($Full or $ShowClass) 2899 2000 { 2900 my $Class = get _TypeName($MethodInfo{$LibVersion}{$Method}{"Class"}, $LibVersion);2901 2902 if($ HideTemplates) {2001 my $Class = getTypeName($MethodInfo{$LVer}{$Method}{"Class"}, $LVer); 2002 2003 if($In::Opt{"HideTemplates"}) { 2903 2004 $Class=~s/<.*>//g; 2904 2005 } 2905 2006 2906 2007 if($Html) { 2907 $Class = htmlSpecChars($Class);2008 $Class = specChars($Class); 2908 2009 } 2909 2010 … … 2912 2013 my @Params = (); 2913 2014 2914 if(defined $MethodInfo{$L ibVersion}{$Method}{"Param"})2015 if(defined $MethodInfo{$LVer}{$Method}{"Param"}) 2915 2016 { 2916 2017 foreach my $PPos (sort {int($a)<=>int($b)} 2917 keys(%{$MethodInfo{$L ibVersion}{$Method}{"Param"}}))2918 { 2919 my $PTid = $MethodInfo{$L ibVersion}{$Method}{"Param"}{$PPos}{"Type"};2920 if(my $PTName = get _TypeName($PTid, $LibVersion))2921 { 2922 if($ HideTemplates) {2018 keys(%{$MethodInfo{$LVer}{$Method}{"Param"}})) 2019 { 2020 my $PTid = $MethodInfo{$LVer}{$Method}{"Param"}{$PPos}{"Type"}; 2021 if(my $PTName = getTypeName($PTid, $LVer)) 2022 { 2023 if($In::Opt{"HideTemplates"}) { 2923 2024 $PTName=~s/<.*>//g; 2924 2025 } 2925 2026 2926 if(not $ ShowPackages) {2027 if(not $In::Opt{"ShowPackages"}) { 2927 2028 $PTName=~s/(\A|\<\s*|\,\s*)[a-z0-9\.]+\./$1/g; 2928 2029 } 2929 2030 2930 2031 if($Html) { 2931 $PTName = htmlSpecChars($PTName);2032 $PTName = specChars($PTName); 2932 2033 } 2933 2034 2934 2035 if($Full or $ShowParams) 2935 2036 { 2936 my $PName = $MethodInfo{$L ibVersion}{$Method}{"Param"}{$PPos}{"Name"};2037 my $PName = $MethodInfo{$LVer}{$Method}{"Param"}{$PPos}{"Name"}; 2937 2038 2938 2039 if($Simple) { … … 2971 2072 { 2972 2073 $Signature .= " "; 2973 $Signature .= "<span class='sym_p'>"; 2074 if($Desc) { 2075 $Signature .= "<span class='sym_pd'>"; 2076 } 2077 else { 2078 $Signature .= "<span class='sym_p'>"; 2079 } 2974 2080 if(@Params) 2975 2081 { … … 3013 2119 if($Full or $ShowAttr) 3014 2120 { 3015 if($MethodInfo{$L ibVersion}{$Method}{"Static"}) {2121 if($MethodInfo{$LVer}{$Method}{"Static"}) { 3016 2122 $Signature .= " [static]"; 3017 2123 } 3018 elsif($MethodInfo{$L ibVersion}{$Method}{"Abstract"}) {2124 elsif($MethodInfo{$LVer}{$Method}{"Abstract"}) { 3019 2125 $Signature .= " [abstract]"; 3020 2126 } … … 3023 2129 if($Full) 3024 2130 { 3025 if($ ShowAccess)3026 { 3027 if(my $Access = $MethodInfo{$L ibVersion}{$Method}{"Access"})2131 if($In::Opt{"ShowAccess"}) 2132 { 2133 if(my $Access = $MethodInfo{$LVer}{$Method}{"Access"}) 3028 2134 { 3029 2135 if($Access ne "public") { … … 3033 2139 } 3034 2140 3035 if(my $ReturnId = $MethodInfo{$L ibVersion}{$Method}{"Return"})3036 { 3037 my $RName = get _TypeName($ReturnId, $LibVersion);2141 if(my $ReturnId = $MethodInfo{$LVer}{$Method}{"Return"}) 2142 { 2143 my $RName = getTypeName($ReturnId, $LVer); 3038 2144 3039 if($ HideTemplates) {2145 if($In::Opt{"HideTemplates"}) { 3040 2146 $RName=~s/<.*>//g; 3041 2147 } 3042 2148 3043 if(not $ ShowPackages) {2149 if(not $In::Opt{"ShowPackages"}) { 3044 2150 $RName=~s/(\A|\<\s*|\,\s*)[a-z0-9\.]+\./$1/g; 3045 2151 } 3046 2152 3047 2153 if($Simple) { 3048 $Signature .= " <b>:</b> ". htmlSpecChars($RName);2154 $Signature .= " <b>:</b> ".specChars($RName); 3049 2155 } 3050 2156 elsif($Html) { 3051 $Signature .= "<span class='sym_p nowrap'>  <b>:</b>  ". htmlSpecChars($RName)."</span>";2157 $Signature .= "<span class='sym_p nowrap'>  <b>:</b>  ".specChars($RName)."</span>"; 3052 2158 } 3053 2159 else { … … 3056 2162 } 3057 2163 3058 if(not $ SkipDeprecated)3059 { 3060 if($MethodInfo{$L ibVersion}{$Method}{"Deprecated"}) {2164 if(not $In::Opt{"SkipDeprecated"}) 2165 { 2166 if($MethodInfo{$LVer}{$Method}{"Deprecated"}) { 3061 2167 $Signature .= " *DEPRECATED*"; 3062 2168 } … … 3068 2174 if($Html) 3069 2175 { 3070 if(not $ SkipDeprecated) {2176 if(not $In::Opt{"SkipDeprecated"}) { 3071 2177 $Signature=~s!(\*deprecated\*)!<span class='deprecated'>$1</span>!ig; 3072 2178 } … … 3084 2190 } 3085 2191 3086 return ($Cache{"get_Signature"}{$LibVersion}{$Method}{$Kind} = $Signature); 3087 } 3088 3089 sub checkJavaCompiler($) 3090 { # check javac: compile simple program 3091 my $Cmd = $_[0]; 3092 3093 if(not $Cmd) { 3094 return; 3095 } 3096 3097 writeFile($TMP_DIR."/test_javac/Simple.java", 3098 "public class Simple { 3099 public Integer f; 3100 public void method(Integer p) { }; 3101 }"); 3102 chdir($TMP_DIR."/test_javac"); 3103 system("$Cmd Simple.java 2>errors.txt"); 3104 chdir($ORIG_DIR); 3105 if($?) 3106 { 3107 my $Msg = "something is going wrong with the Java compiler (javac):\n"; 3108 my $Err = readFile($TMP_DIR."/test_javac/errors.txt"); 3109 $Msg .= $Err; 3110 if($Err=~/elf\/start\.S/ and $Err=~/undefined\s+reference\s+to/) 3111 { # /usr/lib/gcc/i586-suse-linux/4.5/../../../crt1.o: In function _start: 3112 # /usr/src/packages/BUILD/glibc-2.11.3/csu/../sysdeps/i386/elf/start.S:115: undefined reference to main 3113 $Msg .= "\nDid you install a JDK-devel package?"; 3114 } 3115 exitStatus("Error", $Msg); 3116 } 3117 } 3118 3119 sub runTests($$$$) 3120 { 3121 my ($TestsPath, $PackageName, $Path_v1, $Path_v2) = @_; 3122 # compile with old version of package 3123 my $JavacCmd = get_CmdPath("javac"); 3124 if(not $JavacCmd) { 3125 exitStatus("Not_Found", "can't find \"javac\" compiler"); 3126 } 3127 my $JavaCmd = get_CmdPath("java"); 3128 if(not $JavaCmd) { 3129 exitStatus("Not_Found", "can't find \"java\" command"); 3130 } 3131 mkpath($TestsPath."/$PackageName/"); 3132 foreach my $ClassPath (cmd_find($Path_v1,"","*\.class","")) 3133 {# create a compile-time package copy 3134 copy($ClassPath, $TestsPath."/$PackageName/"); 3135 } 3136 chdir($TestsPath); 3137 system($JavacCmd." -g *.java"); 3138 chdir($ORIG_DIR); 3139 foreach my $TestSrc (cmd_find($TestsPath,"","*\.java","")) 3140 { # remove test source 3141 unlink($TestSrc); 3142 } 3143 3144 my $PkgPath = $TestsPath."/".$PackageName; 3145 if(-d $PkgPath) { 3146 rmtree($PkgPath); 3147 } 3148 mkpath($PkgPath); 3149 foreach my $ClassPath (cmd_find($Path_v2,"","*\.class","")) 3150 {# create a run-time package copy 3151 copy($ClassPath, $PkgPath."/"); 3152 } 3153 my $TEST_REPORT = ""; 3154 foreach my $TestPath (cmd_find($TestsPath,"","*\.class",1)) 3155 {# run tests 3156 my $Name = get_filename($TestPath); 3157 $Name=~s/\.class\Z//g; 3158 chdir($TestsPath); 3159 system($JavaCmd." $Name >result.txt 2>&1"); 3160 chdir($ORIG_DIR); 3161 my $Result = readFile($TestsPath."/result.txt"); 3162 unlink($TestsPath."/result.txt"); 3163 $TEST_REPORT .= "TEST CASE: $Name\n"; 3164 if($Result) { 3165 $TEST_REPORT .= "RESULT: FAILED\n"; 3166 $TEST_REPORT .= "OUTPUT:\n$Result\n"; 3167 } 3168 else { 3169 $TEST_REPORT .= "RESULT: SUCCESS\n"; 3170 } 3171 $TEST_REPORT .= "\n"; 3172 } 3173 writeFile("$TestsPath/Journal.txt", $TEST_REPORT); 3174 3175 if(-d $PkgPath) { 3176 rmtree($PkgPath); 3177 } 3178 } 3179 3180 sub compileJavaLib($$$) 3181 { 3182 my ($LibName, $BuildRoot1, $BuildRoot2) = @_; 3183 my $JavacCmd = get_CmdPath("javac"); 3184 if(not $JavacCmd) { 3185 exitStatus("Not_Found", "can't find \"javac\" compiler"); 3186 } 3187 checkJavaCompiler($JavacCmd); 3188 my $JarCmd = get_CmdPath("jar"); 3189 if(not $JarCmd) { 3190 exitStatus("Not_Found", "can't find \"jar\" command"); 3191 } 3192 writeFile("$BuildRoot1/MANIFEST.MF", "Implementation-Version: 1.0\n"); 3193 # space before value, new line 3194 writeFile("$BuildRoot2/MANIFEST.MF", "Implementation-Version: 2.0\n"); 3195 my (%SrcDir1, %SrcDir2) = (); 3196 foreach my $Path (cmd_find($BuildRoot1,"f","*.java","")) { 3197 $SrcDir1{get_dirname($Path)} = 1; 3198 } 3199 foreach my $Path (cmd_find($BuildRoot2,"f","*.java","")) { 3200 $SrcDir2{get_dirname($Path)} = 1; 3201 } 3202 # build classes v.1 3203 foreach my $Dir (keys(%SrcDir1)) 3204 { 3205 chdir($Dir); 3206 system("$JavacCmd -g *.java"); 3207 chdir($ORIG_DIR); 3208 if($?) { 3209 exitStatus("Error", "can't compile classes v.1"); 3210 } 3211 } 3212 # create java archive v.1 3213 chdir($BuildRoot1); 3214 system("$JarCmd -cmf MANIFEST.MF $LibName.jar TestPackage"); 3215 chdir($ORIG_DIR); 3216 3217 # build classes v.2 3218 foreach my $Dir (keys(%SrcDir2)) 3219 { 3220 chdir($Dir); 3221 system("$JavacCmd -g *.java"); 3222 chdir($ORIG_DIR); 3223 if($?) { 3224 exitStatus("Error", "can't compile classes v.2"); 3225 } 3226 } 3227 # create java archive v.2 3228 chdir($BuildRoot2); 3229 system("$JarCmd -cmf MANIFEST.MF $LibName.jar TestPackage"); 3230 chdir($ORIG_DIR); 3231 3232 foreach my $SrcPath (cmd_find($BuildRoot1,"","*\.java","")) { 3233 unlink($SrcPath); 3234 } 3235 foreach my $SrcPath (cmd_find($BuildRoot2,"","*\.java","")) { 3236 unlink($SrcPath); 3237 } 3238 return 1; 3239 } 3240 3241 sub readLineNum($$) 3242 { 3243 my ($Path, $Num) = @_; 3244 return "" if(not $Path or not -f $Path); 3245 open (FILE, $Path); 3246 foreach (1 ... $Num) { 3247 <FILE>; 3248 } 3249 my $Line = <FILE>; 3250 close(FILE); 3251 return $Line; 3252 } 3253 3254 sub readAttributes($$) 3255 { 3256 my ($Path, $Num) = @_; 3257 return () if(not $Path or not -f $Path); 3258 my %Attributes = (); 3259 if(readLineNum($Path, $Num)=~/<!--\s+(.+)\s+-->/) 3260 { 3261 foreach my $AttrVal (split(/;/, $1)) 3262 { 3263 if($AttrVal=~/(.+):(.+)/) 3264 { 3265 my ($Name, $Value) = ($1, $2); 3266 $Attributes{$Name} = $Value; 3267 } 3268 } 3269 } 3270 return \%Attributes; 3271 } 3272 3273 sub runChecker($$$) 3274 { 3275 my ($LibName, $Path1, $Path2) = @_; 3276 writeFile("$LibName/v1.xml", " 3277 <version> 3278 1.0 3279 </version> 3280 <archives> 3281 ".get_abs_path($Path1)." 3282 </archives>"); 3283 writeFile("$LibName/v2.xml", " 3284 <version> 3285 2.0 3286 </version> 3287 <archives> 3288 ".get_abs_path($Path2)." 3289 </archives>"); 3290 my $Cmd = "perl $0 -l $LibName $LibName/v1.xml $LibName/v2.xml"; 3291 if($Quick) { 3292 $Cmd .= " -quick"; 3293 } 3294 if(defined $SkipDeprecated) { 3295 $Cmd .= " -skip-deprecated"; 3296 } 3297 if(defined $OldStyle) { 3298 $Cmd .= " -old-style"; 3299 } 3300 writeFile($TMP_DIR."/skip-annotations.list", "TestPackage.Beta"); 3301 $Cmd .= " -skip-annotations-list ".$TMP_DIR."/skip-annotations.list"; 3302 if($Debug) 3303 { 3304 $Cmd .= " -debug"; 3305 printMsg("INFO", "running $Cmd"); 3306 } 3307 system($Cmd); 3308 my $Report = "compat_reports/$LibName/1.0_to_2.0/compat_report.html"; 3309 # Binary 3310 my $BReport = readAttributes($Report, 0); 3311 my $NProblems = $BReport->{"type_problems_high"}+$BReport->{"type_problems_medium"}; 3312 $NProblems += $BReport->{"method_problems_high"}+$BReport->{"method_problems_medium"}; 3313 $NProblems += $BReport->{"removed"}; 3314 # Source 3315 my $SReport = readAttributes($Report, 1); 3316 $NProblems += $SReport->{"type_problems_high"}+$SReport->{"type_problems_medium"}; 3317 $NProblems += $SReport->{"method_problems_high"}+$SReport->{"method_problems_medium"}; 3318 $NProblems += $SReport->{"removed"}; 3319 if($NProblems>=100) { 3320 printMsg("INFO", "test result: SUCCESS ($NProblems breaks found)\n"); 3321 } 3322 else { 3323 printMsg("ERROR", "test result: FAILED ($NProblems breaks found)\n"); 3324 } 3325 } 3326 3327 sub writeFile($$) 3328 { 3329 my ($Path, $Content) = @_; 3330 return if(not $Path); 3331 if(my $Dir = get_dirname($Path)) { 3332 mkpath($Dir); 3333 } 3334 open (FILE, ">".$Path) || die ("can't open file \'$Path\': $!\n"); 3335 print FILE $Content; 3336 close(FILE); 3337 } 3338 3339 sub readFile($) 3340 { 3341 my $Path = $_[0]; 3342 return "" if(not $Path or not -f $Path); 3343 open (FILE, $Path); 3344 my $Content = join("", <FILE>); 3345 close(FILE); 3346 $Content=~s/\r//g; 3347 return $Content; 3348 } 3349 3350 sub appendFile($$) 3351 { 3352 my ($Path, $Content) = @_; 3353 return if(not $Path); 3354 if(my $Dir = get_dirname($Path)) { 3355 mkpath($Dir); 3356 } 3357 open(FILE, ">>".$Path) || die ("can't open file \'$Path\': $!\n"); 3358 print FILE $Content; 3359 close(FILE); 3360 } 3361 3362 sub get_Report_Header($) 2192 return ($Cache{"getSignature"}{$LVer}{$Method}{$Kind} = $Signature); 2193 } 2194 2195 sub getReportHeader($) 3363 2196 { 3364 2197 my $Level = $_[0]; … … 3373 2206 $Report_Header .= "API compatibility"; 3374 2207 } 3375 $Report_Header .= " report for the <span style='color:Blue;'> $TargetTitle</span> library between <span style='color:Red;'>".$Descriptor{1}{"Version"}."</span> and <span style='color:Red;'>".$Descriptor{2}{"Version"}."</span> versions";3376 if($ ClientPath) {3377 $Report_Header .= " (concerning portability of the client: <span style='color:Blue;'>".get _filename($ClientPath)."</span>)";2208 $Report_Header .= " report for the <span style='color:Blue;'>".$In::Opt{"TargetTitle"}."</span> library between <span style='color:Red;'>".$In::Desc{1}{"Version"}."</span> and <span style='color:Red;'>".$In::Desc{2}{"Version"}."</span> versions"; 2209 if($In::Opt{"ClientPath"}) { 2210 $Report_Header .= " (concerning portability of the client: <span style='color:Blue;'>".getFilename($In::Opt{"ClientPath"})."</span>)"; 3378 2211 } 3379 2212 $Report_Header .= "</h1>\n"; … … 3381 2214 } 3382 2215 3383 sub get _SourceInfo()2216 sub getSourceInfo() 3384 2217 { 3385 2218 my $CheckedArchives = "<a name='Checked_Archives'></a>"; 3386 if($ OldStyle) {3387 $CheckedArchives .= "<h2>Java A Rchives (".keys(%{$LibArchives{1}}).")</h2>";2219 if($In::Opt{"OldStyle"}) { 2220 $CheckedArchives .= "<h2>Java Archives (".keys(%{$LibArchives{1}}).")</h2>"; 3388 2221 } 3389 2222 else { 3390 $CheckedArchives .= "<h2>Java A Rchives <span class='gray'> ".keys(%{$LibArchives{1}})." </span></h2>";2223 $CheckedArchives .= "<h2>Java Archives <span class='gray'> ".keys(%{$LibArchives{1}})." </span></h2>"; 3391 2224 } 3392 2225 $CheckedArchives .= "\n<hr/><div class='jar_list'>\n"; 3393 2226 foreach my $ArchivePath (sort {lc($a) cmp lc($b)} keys(%{$LibArchives{1}})) { 3394 $CheckedArchives .= get _filename($ArchivePath)."<br/>\n";2227 $CheckedArchives .= getFilename($ArchivePath)."<br/>\n"; 3395 2228 } 3396 2229 $CheckedArchives .= "</div><br/>$TOP_REF<br/>\n"; … … 3398 2231 } 3399 2232 3400 sub get _TypeProblems_Count($$)2233 sub getTypeProblemsCount($$) 3401 2234 { 3402 2235 my ($TargetSeverity, $Level) = @_; … … 3408 2241 foreach my $Kind (sort keys(%{$TypeChanges{$Level}{$Type_Name}})) 3409 2242 { 3410 if($ TypeProblems_Kind{$Level}{$Kind} ne $TargetSeverity) {2243 if($CompatRules{$Level}{$Kind}{"Severity"} ne $TargetSeverity) { 3411 2244 next; 3412 2245 } 2246 3413 2247 foreach my $Location (sort keys(%{$TypeChanges{$Level}{$Type_Name}{$Kind}})) 3414 2248 { … … 3428 2262 } 3429 2263 3430 sub show _number($)2264 sub showNum($) 3431 2265 { 3432 2266 if($_[0]) 3433 2267 { 3434 my $Num = cut _off_number($_[0], 2, 0);2268 my $Num = cutNum($_[0], 2, 0); 3435 2269 if($Num eq "0") 3436 2270 { 3437 2271 foreach my $P (3 .. 7) 3438 2272 { 3439 $Num = cut _off_number($_[0], $P, 1);2273 $Num = cutNum($_[0], $P, 1); 3440 2274 if($Num ne "0") { 3441 2275 last; … … 3451 2285 } 3452 2286 3453 sub cut _off_number($$$)2287 sub cutNum($$$) 3454 2288 { 3455 2289 my ($num, $digs_to_cut, $z) = @_; … … 3477 2311 } 3478 2312 3479 sub get _Summary($)2313 sub getSummary($) 3480 2314 { 3481 2315 my $Level = $_[0]; 3482 2316 my ($Added, $Removed, $M_Problems_High, $M_Problems_Medium, $M_Problems_Low, 3483 $T_Problems_High, $T_Problems_Medium, $T_Problems_Low, $M_Other, $T_Other) = (0, 0,0,0,0,0,0,0,0,0);2317 $T_Problems_High, $T_Problems_Medium, $T_Problems_Low, $M_Other, $T_Other) = (0, 0, 0, 0, 0, 0, 0, 0, 0, 0); 3484 2318 3485 2319 %{$RESULT{$Level}} = ( 3486 2320 "Problems"=>0, 3487 2321 "Warnings"=>0, 3488 "Affected"=>0 2322 "Affected"=>0); 3489 2323 3490 2324 foreach my $Method (sort keys(%CompatProblems)) … … 3492 2326 foreach my $Kind (sort keys(%{$CompatProblems{$Method}})) 3493 2327 { 3494 if(my $Severity = $MethodProblems_Kind{$Level}{$Kind}) 3495 { 3496 foreach my $Location (sort keys(%{$CompatProblems{$Method}{$Kind}})) 2328 if($CompatRules{$Level}{$Kind}{"Kind"} eq "Methods") 2329 { 2330 my $Severity = $CompatRules{$Level}{$Kind}{"Severity"}; 2331 foreach my $Loc (sort keys(%{$CompatProblems{$Method}{$Kind}})) 3497 2332 { 3498 2333 if($Kind eq "Added_Method") … … 3531 2366 $M_Problems_Low+=1; 3532 2367 } 3533 if(($Severity ne "Low" or $ StrictCompat)2368 if(($Severity ne "Low" or $In::Opt{"StrictCompat"}) 3534 2369 and $Severity ne "Safe") { 3535 2370 $TotalAffected{$Level}{$Method} = $Severity; … … 3545 2380 foreach my $Method (sort keys(%CompatProblems)) 3546 2381 { 3547 my @Kinds = sort keys(%{$CompatProblems{$Method}});3548 foreach my $Kind (@Kinds)3549 {3550 if(my $Severity = $TypeProblems_Kind{$Level}{$Kind})3551 {3552 my @Locs = sort {length($a)<=>length($b)} sort keys(%{$CompatProblems{$Method}{$Kind}});3553 foreach my $Location (@Locs)2382 foreach my $Kind (sort keys(%{$CompatProblems{$Method}})) 2383 { 2384 if($CompatRules{$Level}{$Kind}{"Kind"} eq "Types") 2385 { 2386 my $Severity = $CompatRules{$Level}{$Kind}{"Severity"}; 2387 if(($Severity ne "Low" or $In::Opt{"StrictCompat"}) 2388 and $Severity ne "Safe") 3554 2389 { 3555 my $Type_Name = $CompatProblems{$Method}{$Kind}{$Location}{"Type_Name"}; 3556 my $Target = $CompatProblems{$Method}{$Kind}{$Location}{"Target"}; 2390 if(my $Sev = $TotalAffected{$Level}{$Method}) 2391 { 2392 if($Severity_Val{$Severity}>$Severity_Val{$Sev}) { 2393 $TotalAffected{$Level}{$Method} = $Severity; 2394 } 2395 } 2396 else { 2397 $TotalAffected{$Level}{$Method} = $Severity; 2398 } 2399 } 2400 2401 my $MK = $CompatProblems{$Method}{$Kind}; 2402 my (@Locs1, @Locs2) = (); 2403 foreach my $Loc (sort {length($a)<=>length($b)} sort keys(%{$MK})) 2404 { 2405 if(index($Loc, "retval")==0 or index($Loc, "this")==0) { 2406 push(@Locs2, $Loc); 2407 } 2408 else { 2409 push(@Locs1, $Loc); 2410 } 2411 } 2412 foreach my $Loc (@Locs1, @Locs2) 2413 { 2414 my $Type = $MK->{$Loc}{"Type_Name"}; 2415 my $Target = $MK->{$Loc}{"Target"}; 3557 2416 3558 if(defined $MethodTypeIndex{$Method}{$Type _Name}{$Kind}{$Target})2417 if(defined $MethodTypeIndex{$Method}{$Type}{$Kind}{$Target}) 3559 2418 { # one location for one type and target 3560 2419 next; 3561 2420 } 3562 $MethodTypeIndex{$Method}{$Type_Name}{$Kind}{$Target} = 1; 3563 $TypeChanges{$Level}{$Type_Name}{$Kind}{$Location} = $CompatProblems{$Method}{$Kind}{$Location}; 2421 $MethodTypeIndex{$Method}{$Type}{$Kind}{$Target} = 1; 3564 2422 3565 if(($Severity ne "Low" or $StrictCompat) 3566 and $Severity ne "Safe") 3567 { 3568 if(my $Sev = $TotalAffected{$Level}{$Method}) 3569 { 3570 if($Severity_Val{$Severity}>$Severity_Val{$Sev}) { 3571 $TotalAffected{$Level}{$Method} = $Severity; 3572 } 3573 } 3574 else { 3575 $TotalAffected{$Level}{$Method} = $Severity; 3576 } 3577 } 2423 $TypeChanges{$Level}{$Type}{$Kind}{$Loc} = $MK->{$Loc}; 2424 $TypeProblemsIndex{$Level}{$Type}{$Kind}{$Loc}{$Method} = 1; 3578 2425 } 3579 2426 } … … 3583 2430 %MethodTypeIndex = (); # clear memory 3584 2431 3585 3586 $T_Problems_High = get_TypeProblems_Count("High", $Level); 3587 $T_Problems_Medium = get_TypeProblems_Count("Medium", $Level); 3588 $T_Problems_Low = get_TypeProblems_Count("Low", $Level); 3589 $T_Other = get_TypeProblems_Count("Safe", $Level); 2432 $T_Problems_High = getTypeProblemsCount("High", $Level); 2433 $T_Problems_Medium = getTypeProblemsCount("Medium", $Level); 2434 $T_Problems_Low = getTypeProblemsCount("Low", $Level); 2435 $T_Other = getTypeProblemsCount("Safe", $Level); 3590 2436 3591 2437 my $SCount = keys(%CheckedMethods)-$Added; … … 3605 2451 $RESULT{$Level}{"Affected"} = 0; 3606 2452 } 3607 $RESULT{$Level}{"Affected"} = show _number($RESULT{$Level}{"Affected"});2453 $RESULT{$Level}{"Affected"} = showNum($RESULT{$Level}{"Affected"}); 3608 2454 if($RESULT{$Level}{"Affected"}>=100) { 3609 2455 $RESULT{$Level}{"Affected"} = 100; … … 3615 2461 $TestInfo .= "<h2>Test Info</h2><hr/>\n"; 3616 2462 $TestInfo .= "<table class='summary'>\n"; 3617 $TestInfo .= "<tr><th>Library Name</th><td> $TargetTitle</td></tr>\n";3618 $TestInfo .= "<tr><th>Version #1</th><td>".$ Descriptor{1}{"Version"}."</td></tr>\n";3619 $TestInfo .= "<tr><th>Version #2</th><td>".$ Descriptor{2}{"Version"}."</td></tr>\n";3620 3621 if($ JoinReport)2463 $TestInfo .= "<tr><th>Library Name</th><td>".$In::Opt{"TargetTitle"}."</td></tr>\n"; 2464 $TestInfo .= "<tr><th>Version #1</th><td>".$In::Desc{1}{"Version"}."</td></tr>\n"; 2465 $TestInfo .= "<tr><th>Version #2</th><td>".$In::Desc{2}{"Version"}."</td></tr>\n"; 2466 2467 if($In::Opt{"JoinReport"}) 3622 2468 { 3623 2469 if($Level eq "Binary") { … … 3631 2477 3632 2478 # test results 3633 $TestResults .= "<h2>Test Results</h2><hr/> ";3634 $TestResults .= "<table class='summary'> ";2479 $TestResults .= "<h2>Test Results</h2><hr/>\n"; 2480 $TestResults .= "<table class='summary'>\n"; 3635 2481 3636 2482 my $Checked_Archives_Link = "0"; … … 3641 2487 3642 2488 $RESULT{$Level}{"Problems"} += $Removed+$M_Problems_High+$T_Problems_High+$T_Problems_Medium+$M_Problems_Medium; 3643 if($ StrictCompat) {2489 if($In::Opt{"StrictCompat"}) { 3644 2490 $RESULT{$Level}{"Problems"}+=$T_Problems_Low+$M_Problems_Low; 3645 2491 } … … 3652 2498 $TestResults .= "<tr><th>Compatibility</th>\n"; 3653 2499 3654 my $BC_Rate = show _number(100 - $RESULT{$Level}{"Affected"});2500 my $BC_Rate = showNum(100 - $RESULT{$Level}{"Affected"}); 3655 2501 3656 2502 if($RESULT{$Level}{"Problems"}) … … 3677 2523 3678 2524 # Problem Summary 3679 $Problem_Summary .= "<h2>Problem Summary</h2><hr/> ";3680 $Problem_Summary .= "<table class='summary'> ";3681 $Problem_Summary .= "<tr><th></th><th style='text-align:center;'>Severity</th><th style='text-align:center;'>Count</th></tr> ";2525 $Problem_Summary .= "<h2>Problem Summary</h2><hr/>\n"; 2526 $Problem_Summary .= "<table class='summary'>\n"; 2527 $Problem_Summary .= "<tr><th></th><th style='text-align:center;'>Severity</th><th style='text-align:center;'>Count</th></tr>\n"; 3682 2528 3683 2529 my $Added_Link = "0"; 3684 2530 if($Added>0) 3685 2531 { 3686 if($ ShortMode) {2532 if($In::Opt{"ShortMode"}) { 3687 2533 $Added_Link = $Added; 3688 2534 } 3689 2535 else 3690 2536 { 3691 if($ JoinReport) {2537 if($In::Opt{"JoinReport"}) { 3692 2538 $Added_Link = "<a href='#".$Level."_Added' style='color:Blue;'>$Added</a>"; 3693 2539 } … … 3698 2544 } 3699 2545 $META_DATA .= "added:$Added;"; 3700 $Problem_Summary .= "<tr><th>Added Methods</th><td>-</td><td".getStyle("M", "Added", $Added).">$Added_Link</td></tr> ";2546 $Problem_Summary .= "<tr><th>Added Methods</th><td>-</td><td".getStyle("M", "Added", $Added).">$Added_Link</td></tr>\n"; 3701 2547 3702 2548 my $Removed_Link = "0"; 3703 2549 if($Removed>0) 3704 2550 { 3705 if($ ShortMode) {2551 if($In::Opt{"ShortMode"}) { 3706 2552 $Removed_Link = $Removed; 3707 2553 } 3708 2554 else 3709 2555 { 3710 if($ JoinReport) {2556 if($In::Opt{"JoinReport"}) { 3711 2557 $Removed_Link = "<a href='#".$Level."_Removed' style='color:Blue;'>$Removed</a>" 3712 2558 } … … 3718 2564 $META_DATA .= "removed:$Removed;"; 3719 2565 $Problem_Summary .= "<tr><th>Removed Methods</th>"; 3720 $Problem_Summary .= "<td>High</td><td".getStyle("M", "Removed", $Removed).">$Removed_Link</td></tr> ";2566 $Problem_Summary .= "<td>High</td><td".getStyle("M", "Removed", $Removed).">$Removed_Link</td></tr>\n"; 3721 2567 3722 2568 my $TH_Link = "0"; 3723 $TH_Link = "<a href='#".get _Anchor("Type", $Level, "High")."' style='color:Blue;'>$T_Problems_High</a>" if($T_Problems_High>0);2569 $TH_Link = "<a href='#".getAnchor("Type", $Level, "High")."' style='color:Blue;'>$T_Problems_High</a>" if($T_Problems_High>0); 3724 2570 $META_DATA .= "type_problems_high:$T_Problems_High;"; 3725 2571 $Problem_Summary .= "<tr><th rowspan='3'>Problems with<br/>Data Types</th>"; 3726 $Problem_Summary .= "<td>High</td><td".getStyle("T", "High", $T_Problems_High).">$TH_Link</td></tr> ";2572 $Problem_Summary .= "<td>High</td><td".getStyle("T", "High", $T_Problems_High).">$TH_Link</td></tr>\n"; 3727 2573 3728 2574 my $TM_Link = "0"; 3729 $TM_Link = "<a href='#".get _Anchor("Type", $Level, "Medium")."' style='color:Blue;'>$T_Problems_Medium</a>" if($T_Problems_Medium>0);2575 $TM_Link = "<a href='#".getAnchor("Type", $Level, "Medium")."' style='color:Blue;'>$T_Problems_Medium</a>" if($T_Problems_Medium>0); 3730 2576 $META_DATA .= "type_problems_medium:$T_Problems_Medium;"; 3731 $Problem_Summary .= "<tr><td>Medium</td><td".getStyle("T", "Medium", $T_Problems_Medium).">$TM_Link</td></tr> ";2577 $Problem_Summary .= "<tr><td>Medium</td><td".getStyle("T", "Medium", $T_Problems_Medium).">$TM_Link</td></tr>\n"; 3732 2578 3733 2579 my $TL_Link = "0"; 3734 $TL_Link = "<a href='#".get _Anchor("Type", $Level, "Low")."' style='color:Blue;'>$T_Problems_Low</a>" if($T_Problems_Low>0);2580 $TL_Link = "<a href='#".getAnchor("Type", $Level, "Low")."' style='color:Blue;'>$T_Problems_Low</a>" if($T_Problems_Low>0); 3735 2581 $META_DATA .= "type_problems_low:$T_Problems_Low;"; 3736 $Problem_Summary .= "<tr><td>Low</td><td".getStyle("T", "Low", $T_Problems_Low).">$TL_Link</td></tr> ";2582 $Problem_Summary .= "<tr><td>Low</td><td".getStyle("T", "Low", $T_Problems_Low).">$TL_Link</td></tr>\n"; 3737 2583 3738 2584 my $MH_Link = "0"; 3739 $MH_Link = "<a href='#".get _Anchor("Method", $Level, "High")."' style='color:Blue;'>$M_Problems_High</a>" if($M_Problems_High>0);2585 $MH_Link = "<a href='#".getAnchor("Method", $Level, "High")."' style='color:Blue;'>$M_Problems_High</a>" if($M_Problems_High>0); 3740 2586 $META_DATA .= "method_problems_high:$M_Problems_High;"; 3741 2587 $Problem_Summary .= "<tr><th rowspan='3'>Problems with<br/>Methods</th>"; 3742 $Problem_Summary .= "<td>High</td><td".getStyle("M", "High", $M_Problems_High).">$MH_Link</td></tr> ";2588 $Problem_Summary .= "<td>High</td><td".getStyle("M", "High", $M_Problems_High).">$MH_Link</td></tr>\n"; 3743 2589 3744 2590 my $MM_Link = "0"; 3745 $MM_Link = "<a href='#".get _Anchor("Method", $Level, "Medium")."' style='color:Blue;'>$M_Problems_Medium</a>" if($M_Problems_Medium>0);2591 $MM_Link = "<a href='#".getAnchor("Method", $Level, "Medium")."' style='color:Blue;'>$M_Problems_Medium</a>" if($M_Problems_Medium>0); 3746 2592 $META_DATA .= "method_problems_medium:$M_Problems_Medium;"; 3747 $Problem_Summary .= "<tr><td>Medium</td><td".getStyle("M", "Medium", $M_Problems_Medium).">$MM_Link</td></tr> ";2593 $Problem_Summary .= "<tr><td>Medium</td><td".getStyle("M", "Medium", $M_Problems_Medium).">$MM_Link</td></tr>\n"; 3748 2594 3749 2595 my $ML_Link = "0"; 3750 $ML_Link = "<a href='#".get _Anchor("Method", $Level, "Low")."' style='color:Blue;'>$M_Problems_Low</a>" if($M_Problems_Low>0);2596 $ML_Link = "<a href='#".getAnchor("Method", $Level, "Low")."' style='color:Blue;'>$M_Problems_Low</a>" if($M_Problems_Low>0); 3751 2597 $META_DATA .= "method_problems_low:$M_Problems_Low;"; 3752 $Problem_Summary .= "<tr><td>Low</td><td".getStyle("M", "Low", $M_Problems_Low).">$ML_Link</td></tr> ";2598 $Problem_Summary .= "<tr><td>Low</td><td".getStyle("M", "Low", $M_Problems_Low).">$ML_Link</td></tr>\n"; 3753 2599 3754 2600 # Safe Changes 3755 2601 if($T_Other) 3756 2602 { 3757 my $TS_Link = "<a href='#".get _Anchor("Type", $Level, "Safe")."' style='color:Blue;'>$T_Other</a>";2603 my $TS_Link = "<a href='#".getAnchor("Type", $Level, "Safe")."' style='color:Blue;'>$T_Other</a>"; 3758 2604 $Problem_Summary .= "<tr><th>Other Changes<br/>in Data Types</th><td>-</td><td".getStyle("T", "Safe", $T_Other).">$TS_Link</td></tr>\n"; 3759 2605 } … … 3761 2607 if($M_Other) 3762 2608 { 3763 my $MS_Link = "<a href='#".get _Anchor("Method", $Level, "Safe")."' style='color:Blue;'>$M_Other</a>";2609 my $MS_Link = "<a href='#".getAnchor("Method", $Level, "Safe")."' style='color:Blue;'>$M_Other</a>"; 3764 2610 $Problem_Summary .= "<tr><th>Other Changes<br/>in Methods</th><td>-</td><td".getStyle("M", "Safe", $M_Other).">$MS_Link</td></tr>\n"; 3765 2611 } … … 3790 2636 } 3791 2637 3792 sub get _Anchor($$$)2638 sub getAnchor($$$) 3793 2639 { 3794 2640 my ($Kind, $Level, $Severity) = @_; 3795 if($ JoinReport)2641 if($In::Opt{"JoinReport"}) 3796 2642 { 3797 2643 if($Severity eq "Safe") { … … 3813 2659 } 3814 2660 3815 sub get _Report_Added($)3816 { 3817 if($ ShortMode) {2661 sub getReportAdded($) 2662 { 2663 if($In::Opt{"ShortMode"}) { 3818 2664 return ""; 3819 2665 } … … 3828 2674 { 3829 2675 my $ArchiveName = $MethodInfo{2}{$Method}{"Archive"}; 3830 my $ClassName = get _ShortName($MethodInfo{2}{$Method}{"Class"}, 2);2676 my $ClassName = getShortName($MethodInfo{2}{$Method}{"Class"}, 2); 3831 2677 if($Level eq "Source") 3832 2678 { … … 3854 2700 foreach my $NameSpace (sort keys(%NameSpace_Method)) 3855 2701 { 3856 $ADDED_METHODS .= "<span class='jar'>$ArchiveName</span>, <span class='cname'>". htmlSpecChars($ShowClass).".class</span><br/>\n";2702 $ADDED_METHODS .= "<span class='jar'>$ArchiveName</span>, <span class='cname'>".specChars($ShowClass).".class</span><br/>\n"; 3857 2703 3858 2704 if($NameSpace) { … … 3860 2706 } 3861 2707 3862 if($ Compact) {2708 if($In::Opt{"Compact"}) { 3863 2709 $ADDED_METHODS .= "<div class='symbols'>"; 3864 2710 } … … 3871 2717 my $Signature = undef; 3872 2718 3873 if($ Compact) {3874 $Signature = get _Signature($Method, 2, "Full|HTML|Simple");2719 if($In::Opt{"Compact"}) { 2720 $Signature = getSignature($Method, 2, "Full|HTML|Simple"); 3875 2721 } 3876 2722 else { 3877 $Signature = highLight_ Signature_Italic_Color($Method, 2);2723 $Signature = highLight_ItalicColor($Method, 2); 3878 2724 } 3879 2725 … … 3882 2728 } 3883 2729 3884 if($ Compact) {2730 if($In::Opt{"Compact"}) { 3885 2731 $ADDED_METHODS .= " ".$Signature."<br/>\n"; 3886 2732 } 3887 2733 else { 3888 $ADDED_METHODS .= insertIDs($ContentSpanStart.$Signature.$ContentSpanEnd."<br/>\n".$ContentDivStart."<span class='mngl'> [mangled: <b>".htmlSpecChars($Method)."</b>]</span><br/><br/>".$ContentDivEnd."\n");2734 $ADDED_METHODS .= insertIDs($ContentSpanStart.$Signature.$ContentSpanEnd."<br/>\n".$ContentDivStart."<span class='mngl'>".specChars($Method)."</span><br/><br/>".$ContentDivEnd."\n"); 3889 2735 } 3890 2736 } 3891 2737 3892 if($ Compact) {2738 if($In::Opt{"Compact"}) { 3893 2739 $ADDED_METHODS .= "</div>"; 3894 2740 } … … 3902 2748 { 3903 2749 my $Anchor = "<a name='Added'></a>"; 3904 if($ JoinReport) {2750 if($In::Opt{"JoinReport"}) { 3905 2751 $Anchor = "<a name='".$Level."_Added'></a>"; 3906 2752 } 3907 if($ OldStyle) {2753 if($In::Opt{"OldStyle"}) { 3908 2754 $ADDED_METHODS = "<h2>Added Methods ($Added_Number)</h2><hr/>\n".$ADDED_METHODS; 3909 2755 } … … 3916 2762 } 3917 2763 3918 sub get _Report_Removed($)3919 { 3920 if($ ShortMode) {2764 sub getReportRemoved($) 2765 { 2766 if($In::Opt{"ShortMode"}) { 3921 2767 return ""; 3922 2768 } … … 3937 2783 } 3938 2784 my $ArchiveName = $MethodInfo{1}{$Method}{"Archive"}; 3939 my $ClassName = get _ShortName($MethodInfo{1}{$Method}{"Class"}, 1);2785 my $ClassName = getShortName($MethodInfo{1}{$Method}{"Class"}, 1); 3940 2786 $MethodRemovedFromArchiveClass{$ArchiveName}{$ClassName}{$Method} = 1; 3941 2787 } … … 3958 2804 foreach my $NameSpace (sort keys(%NameSpace_Method)) 3959 2805 { 3960 $REMOVED_METHODS .= "<span class='jar'>$ArchiveName</span>, <span class='cname'>". htmlSpecChars($ShowClass).".class</span><br/>\n";2806 $REMOVED_METHODS .= "<span class='jar'>$ArchiveName</span>, <span class='cname'>".specChars($ShowClass).".class</span><br/>\n"; 3961 2807 3962 2808 if($NameSpace) { … … 3964 2810 } 3965 2811 3966 if($ Compact) {2812 if($In::Opt{"Compact"}) { 3967 2813 $REMOVED_METHODS .= "<div class='symbols'>"; 3968 2814 } … … 3975 2821 my $Signature = undef; 3976 2822 3977 if($ Compact) {3978 $Signature = get _Signature($Method, 1, "Full|HTML|Simple");2823 if($In::Opt{"Compact"}) { 2824 $Signature = getSignature($Method, 1, "Full|HTML|Simple"); 3979 2825 } 3980 2826 else { 3981 $Signature = highLight_ Signature_Italic_Color($Method, 1);2827 $Signature = highLight_ItalicColor($Method, 1); 3982 2828 } 3983 2829 … … 3986 2832 } 3987 2833 3988 if($ Compact) {2834 if($In::Opt{"Compact"}) { 3989 2835 $REMOVED_METHODS .= " ".$Signature."<br/>\n"; 3990 2836 } 3991 2837 else { 3992 $REMOVED_METHODS .= insertIDs($ContentSpanStart.$Signature.$ContentSpanEnd."<br/>\n".$ContentDivStart."<span class='mngl'> [mangled: <b>".htmlSpecChars($Method)."</b>]</span><br/><br/>".$ContentDivEnd."\n");2838 $REMOVED_METHODS .= insertIDs($ContentSpanStart.$Signature.$ContentSpanEnd."<br/>\n".$ContentDivStart."<span class='mngl'>".specChars($Method)."</span><br/><br/>".$ContentDivEnd."\n"); 3993 2839 } 3994 2840 } 3995 2841 3996 if($ Compact) {2842 if($In::Opt{"Compact"}) { 3997 2843 $REMOVED_METHODS .= "</div>"; 3998 2844 } … … 4005 2851 { 4006 2852 my $Anchor = "<a name='Removed'></a><a name='Withdrawn'></a>"; 4007 if($ JoinReport) {2853 if($In::Opt{"JoinReport"}) { 4008 2854 $Anchor = "<a name='".$Level."_Removed'></a><a name='".$Level."_Withdrawn'></a>"; 4009 2855 } 4010 if($ OldStyle) {2856 if($In::Opt{"OldStyle"}) { 4011 2857 $REMOVED_METHODS = "<h2>Removed Methods ($Removed_Number)</h2><hr/>\n".$REMOVED_METHODS; 4012 2858 } … … 4019 2865 } 4020 2866 4021 sub get_Report_MethodProblems($$) 2867 sub readRules($) 2868 { 2869 my $Kind = $_[0]; 2870 if(not -f $RULES_PATH{$Kind}) { 2871 exitStatus("Module_Error", "can't access \'".$RULES_PATH{$Kind}."\'"); 2872 } 2873 my $Content = readFile($RULES_PATH{$Kind}); 2874 while(my $Rule = parseTag(\$Content, "rule")) 2875 { 2876 my $RId = parseTag(\$Rule, "id"); 2877 my @Properties = ("Severity", "Change", "Effect", "Overcome", "Kind"); 2878 foreach my $Prop (@Properties) { 2879 if(my $Value = parseTag(\$Rule, lc($Prop))) 2880 { 2881 $Value=~s/\n[ ]*//; 2882 $CompatRules{$Kind}{$RId}{$Prop} = $Value; 2883 } 2884 } 2885 if($CompatRules{$Kind}{$RId}{"Kind"}=~/\A(Methods|Parameters)\Z/) { 2886 $CompatRules{$Kind}{$RId}{"Kind"} = "Methods"; 2887 } 2888 else { # Types, Fields 2889 $CompatRules{$Kind}{$RId}{"Kind"} = "Types"; 2890 } 2891 } 2892 } 2893 2894 sub addMarkup($) 2895 { 2896 my $Content = $_[0]; 2897 2898 # auto-markup 2899 $Content=~s/\n[ ]*//; # spaces 2900 $Content=~s!([2-9]\))!<br/>$1!g; # 1), 2), ... 2901 if($Content=~/\ANOTE:/) 2902 { # notes 2903 $Content=~s!(NOTE):!<b>$1</b>:!g; 2904 } 2905 else { 2906 $Content=~s!(NOTE):!<br/><br/><b>$1</b>:!g; 2907 } 2908 2909 my @Keywords = ( 2910 "static", 2911 "abstract", 2912 "default", 2913 "final", 2914 "synchronized" 2915 ); 2916 2917 my $MKeys = join("|", @Keywords); 2918 foreach (@Keywords) { 2919 $MKeys .= "|non-".$_; 2920 } 2921 2922 $Content=~s!(became\s*)($MKeys)([^\w-]|\Z)!$1<b>$2</b>$3!ig; # intrinsic types, modifiers 2923 2924 # Markdown 2925 $Content=~s!\*\*([\w\-\@]+)\*\*!<b>$1</b>!ig; 2926 $Content=~s!\*([\w\-]+)\*!<i>$1</i>!ig; 2927 2928 return $Content; 2929 } 2930 2931 sub applyMacroses($$$$$) 2932 { 2933 my ($Level, $Kind, $Content, $Problem, $AddAttr) = @_; 2934 2935 $Content = addMarkup($Content); 2936 2937 # macros 2938 foreach my $Attr (sort {$b cmp $a} (keys(%{$Problem}), keys(%{$AddAttr}))) 2939 { 2940 my $Macro = "\@".lc($Attr); 2941 my $Value = undef; 2942 2943 if(defined $Problem->{$Attr}) { 2944 $Value = $Problem->{$Attr}; 2945 } 2946 else { 2947 $Value = $AddAttr->{$Attr}; 2948 } 2949 2950 if(not defined $Value 2951 or $Value eq "") { 2952 next; 2953 } 2954 2955 if(index($Content, $Macro)==-1) { 2956 next; 2957 } 2958 2959 if($Attr eq "Param_Pos") { 2960 $Value = showPos($Value); 2961 } 2962 2963 if($Attr eq "Invoked") { 2964 $Value = blackName(specChars($Value)); 2965 } 2966 elsif($Value=~/\s/) { 2967 $Value = "<span class='value'>".specChars($Value)."</span>"; 2968 } 2969 else 2970 { 2971 my $Fmt = "Class|HTML|Desc"; 2972 2973 if($Attr ne "Invoked_By") 2974 { 2975 if($Attr eq "Method_Short" 2976 or $Kind!~/Overridden|Moved_Up/) { 2977 $Fmt = "HTML|Desc"; 2978 } 2979 } 2980 2981 if(defined $MethodInfo{1}{$Value} 2982 and defined $MethodInfo{1}{$Value}{"ShortName"}) { 2983 $Value = blackName(getSignature($Value, 1, $Fmt)); 2984 } 2985 elsif(defined $MethodInfo{2}{$Value} 2986 and defined $MethodInfo{2}{$Value}{"ShortName"}) { 2987 $Value = blackName(getSignature($Value, 2, $Fmt)); 2988 } 2989 else 2990 { 2991 $Value = specChars($Value); 2992 if($Attr ne "Type_Type") { 2993 $Value = "<b>".$Value."</b>"; 2994 } 2995 } 2996 } 2997 $Content=~s/\Q$Macro\E/$Value/g; 2998 } 2999 3000 if($Content=~/(\A|[^\@\w])(\@\w+)/) 3001 { 3002 if(not $IncompleteRules{$Level}{$Kind}) 3003 { # only one warning 3004 printMsg("WARNING", "incomplete $2 in the rule \"$Kind\" (\"$Level\")"); 3005 $IncompleteRules{$Level}{$Kind} = 1; 3006 } 3007 } 3008 3009 return $Content; 3010 } 3011 3012 sub getReportMethodProblems($$) 4022 3013 { 4023 3014 my ($TargetSeverity, $Level) = @_; … … 4028 3019 { 4029 3020 my $ArchiveName = $MethodInfo{1}{$Method}{"Archive"}; 4030 my $ClassName = get _ShortName($MethodInfo{1}{$Method}{"Class"}, 1);3021 my $ClassName = getShortName($MethodInfo{1}{$Method}{"Class"}, 1); 4031 3022 4032 3023 foreach my $Kind (sort keys(%{$CompatProblems{$Method}})) 4033 3024 { 4034 if($Kind eq "Added_Method" 4035 or $Kind eq "Removed_Method") { 4036 next; 4037 } 4038 4039 if(my $Severity = $MethodProblems_Kind{$Level}{$Kind}) 4040 { 4041 if($Severity ne $TargetSeverity) { 3025 if($CompatRules{$Level}{$Kind}{"Kind"} eq "Methods") 3026 { 3027 if($Kind eq "Added_Method" 3028 or $Kind eq "Removed_Method") { 4042 3029 next; 4043 3030 } 4044 3031 4045 $MethodChanges{$Method}{$Kind} = $CompatProblems{$Method}{$Kind}; 4046 $ReportMap{$ArchiveName}{$ClassName}{$Method} = 1; 3032 if(my $Severity = $CompatRules{$Level}{$Kind}{"Severity"}) 3033 { 3034 if($Severity ne $TargetSeverity) { 3035 next; 3036 } 3037 3038 $MethodChanges{$Method}{$Kind} = $CompatProblems{$Method}{$Kind}; 3039 $ReportMap{$ArchiveName}{$ClassName}{$Method} = 1; 3040 } 4047 3041 } 4048 3042 } … … 4063 3057 foreach my $NameSpace (sort keys(%NameSpace_Method)) 4064 3058 { 4065 $METHOD_PROBLEMS .= "<span class='jar'>$ArchiveName</span>, <span class='cname'>". htmlSpecChars($ShowClass).".class</span><br/>\n";3059 $METHOD_PROBLEMS .= "<span class='jar'>$ArchiveName</span>, <span class='cname'>".specChars($ShowClass).".class</span><br/>\n"; 4066 3060 if($NameSpace) { 4067 3061 $METHOD_PROBLEMS .= "<span class='pkg_t'>package</span> <span class='pkg'>$NameSpace</span><br/>\n"; … … 4071 3065 foreach my $Method (@SortedMethods) 4072 3066 { 4073 my $ShortSignature = get_Signature($Method, 1, "Short"); 4074 my $ClassName_Full = get_TypeName($MethodInfo{1}{$Method}{"Class"}, 1); 3067 my %AddAttr = (); 3068 3069 $AddAttr{"Method_Short"} = $Method; 3070 $AddAttr{"Class"} = getTypeName($MethodInfo{1}{$Method}{"Class"}, 1); 3071 4075 3072 my $METHOD_REPORT = ""; 4076 3073 my $ProblemNum = 1; 4077 3074 foreach my $Kind (sort keys(%{$MethodChanges{$Method}})) 4078 3075 { 4079 foreach my $Loc ation(sort keys(%{$MethodChanges{$Method}{$Kind}}))3076 foreach my $Loc (sort keys(%{$MethodChanges{$Method}{$Kind}})) 4080 3077 { 4081 my %Problems = %{$MethodChanges{$Method}{$Kind}{$Location}};3078 my $ProblemAttr = $MethodChanges{$Method}{$Kind}{$Loc}; 4082 3079 4083 my $Target = $Problems{"Target"}; 4084 4085 my ($Change, $Effect) = ("", ""); 4086 my $Old_Value = htmlSpecChars($Problems{"Old_Value"}); 4087 my $New_Value = htmlSpecChars($Problems{"New_Value"}); 4088 4089 if($Kind eq "Method_Became_Static") 3080 if(my $Change = applyMacroses($Level, $Kind, $CompatRules{$Level}{$Kind}{"Change"}, $ProblemAttr, \%AddAttr)) 4090 3081 { 4091 $Change = "Method became <b>static</b>.\n"; 4092 $Effect = "A client program may be interrupted by <b>NoSuchMethodError</b> exception."; 4093 } 4094 elsif($Kind eq "Method_Became_NonStatic") 4095 { 4096 $Change = "Method became <b>non-static</b>.\n"; 4097 if($Level eq "Binary") { 4098 $Effect = "A client program may be interrupted by <b>NoSuchMethodError</b> exception."; 4099 } 4100 else { 4101 $Effect = "Recompilation of a client program may be terminated with the message: non-static method ".htmlSpecChars($ShortSignature)." cannot be referenced from a static context."; 4102 } 4103 } 4104 elsif($Kind eq "Changed_Method_Return_From_Void") 4105 { 4106 $Change = "Return value type has been changed from <b>void</b> to <b>".htmlSpecChars($New_Value)."</b>.\n"; 4107 $Effect = "This method has been removed because the return type is part of the method signature."; 4108 } 4109 elsif($Kind eq "Static_Method_Became_Final") 4110 {# Source Only 4111 $Change = "Method became <b>final</b>.\n"; 4112 $Effect = "Recompilation of a client program may be terminated with the message: ".htmlSpecChars($ShortSignature)." in client class C cannot override ".htmlSpecChars($ShortSignature)." in ".htmlSpecChars($ClassName_Full)."; overridden method is final."; 4113 } 4114 elsif($Kind eq "NonStatic_Method_Became_Final") 4115 { 4116 $Change = "Method became <b>final</b>.\n"; 4117 if($Level eq "Binary") { 4118 $Effect = "A client program trying to reimplement this method may be interrupted by <b>VerifyError</b> exception."; 4119 } 4120 else { 4121 $Effect = "Recompilation of a client program may be terminated with the message: ".htmlSpecChars($ShortSignature)." in client class C cannot override ".htmlSpecChars($ShortSignature)." in ".htmlSpecChars($ClassName_Full)."; overridden method is final."; 4122 } 4123 } 4124 elsif($Kind eq "Method_Became_Abstract") 4125 { 4126 $Change = "Method became <b>abstract</b>.\n"; 4127 if($Level eq "Binary") { 4128 $Effect = "A client program trying to create an instance of the method's class may be interrupted by <b>InstantiationError</b> exception."; 4129 } 4130 else { 4131 $Effect = "Recompilation of a client program may be terminated with the message: A client class C is not abstract and does not override abstract method ".htmlSpecChars($ShortSignature)." in ".htmlSpecChars($ClassName_Full)."."; 4132 } 4133 } 4134 elsif($Kind eq "Method_Became_NonAbstract") 4135 { 4136 $Change = "Method became <b>non-abstract</b>.\n"; 4137 if($Level eq "Binary") { 4138 $Effect = "A client program may change behavior."; 4139 } 4140 else { 4141 $Effect = "No effect."; 4142 } 4143 } 4144 elsif($Kind eq "Method_Became_Default") 4145 { 4146 $Change = "Method became <b>default</b>.\n"; 4147 if($Level eq "Binary") { 4148 $Effect = "No effect."; 4149 } 4150 else { 4151 $Effect = "No effect."; 4152 } 4153 } 4154 elsif($Kind eq "Method_Became_NonDefault") 4155 { 4156 $Change = "Method became <b>non-default</b>.\n"; 4157 if($Level eq "Binary") { 4158 $Effect = "A client program trying to create an instance of a class may be interrupted by <b>AbstractMethodError</b> exception."; 4159 } 4160 else { 4161 $Effect = "Recompilation of a client program may be terminated with the message: A client class C is not abstract and does not override abstract method ".htmlSpecChars($ShortSignature)." in ".htmlSpecChars($ClassName_Full)."."; 4162 } 4163 } 4164 elsif($Kind eq "Method_Became_Synchronized") 4165 { 4166 $Change = "Method became <b>synchronized</b>.\n"; 4167 $Effect = "A multi-threaded client program may change behavior."; 4168 } 4169 elsif($Kind eq "Method_Became_NonSynchronized") 4170 { 4171 $Change = "Method became <b>non-synchronized</b>.\n"; 4172 $Effect = "A multi-threaded client program may change behavior."; 4173 } 4174 elsif($Kind eq "Changed_Method_Access") 4175 { 4176 $Change = "Access level has been changed from <span class='nowrap'><b>".htmlSpecChars($Old_Value)."</b></span> to <span class='nowrap'><b>".htmlSpecChars($New_Value)."</b></span>."; 4177 if($Level eq "Binary") { 4178 $Effect = "A client program may be interrupted by <b>IllegalAccessError</b> exception."; 4179 } 4180 else { 4181 $Effect = "Recompilation of a client program may be terminated with the message: ".htmlSpecChars($ShortSignature)." has $New_Value access in ".htmlSpecChars($ClassName_Full)."."; 4182 } 4183 } 4184 elsif($Kind eq "Abstract_Method_Added_Checked_Exception") 4185 {# Source Only 4186 $Change = "Added <b>".htmlSpecChars($Target)."</b> exception thrown.\n"; 4187 $Effect = "Recompilation of a client program may be terminated with the message: unreported exception ".htmlSpecChars($Target)." must be caught or declared to be thrown."; 4188 } 4189 elsif($Kind eq "NonAbstract_Method_Added_Checked_Exception") 4190 { 4191 $Change = "Added <b>".htmlSpecChars($Target)."</b> exception thrown.\n"; 4192 if($Level eq "Binary") { 4193 $Effect = "A client program may be interrupted by added exception."; 4194 } 4195 else { 4196 $Effect = "Recompilation of a client program may be terminated with the message: unreported exception ".htmlSpecChars($Target)." must be caught or declared to be thrown."; 4197 } 4198 } 4199 elsif($Kind eq "Abstract_Method_Removed_Checked_Exception") 4200 {# Source Only 4201 $Change = "Removed <b>".htmlSpecChars($Target)."</b> exception thrown.\n"; 4202 $Effect = "Recompilation of a client program may be terminated with the message: cannot override ".htmlSpecChars($ShortSignature)." in ".htmlSpecChars($ClassName_Full)."; overridden method does not throw ".htmlSpecChars($Target)."."; 4203 } 4204 elsif($Kind eq "NonAbstract_Method_Removed_Checked_Exception") 4205 { 4206 $Change = "Removed <b>".htmlSpecChars($Target)."</b> exception thrown.\n"; 4207 if($Level eq "Binary") { 4208 $Effect = "A client program may change behavior because the removed exception will not be thrown any more and client will not catch and handle it."; 4209 } 4210 else { 4211 $Effect = "Recompilation of a client program may be terminated with the message: cannot override ".htmlSpecChars($ShortSignature)." in ".htmlSpecChars($ClassName_Full)."; overridden method does not throw ".htmlSpecChars($Target)."."; 4212 } 4213 } 4214 elsif($Kind eq "Added_Unchecked_Exception") 4215 {# Binary Only 4216 $Change = "Added <b>".htmlSpecChars($Target)."</b> exception thrown.\n"; 4217 $Effect = "A client program may be interrupted by added exception."; 4218 } 4219 elsif($Kind eq "Removed_Unchecked_Exception") 4220 {# Binary Only 4221 $Change = "Removed <b>".htmlSpecChars($Target)."</b> exception thrown.\n"; 4222 $Effect = "A client program may change behavior because the removed exception will not be thrown any more and client will not catch and handle it."; 4223 } 4224 if($Change) 4225 { 4226 $METHOD_REPORT .= "<tr><th>$ProblemNum</th><td>".$Change."</td><td>".$Effect."</td></tr>\n"; 3082 my $Effect = applyMacroses($Level, $Kind, $CompatRules{$Level}{$Kind}{"Effect"}, $ProblemAttr, \%AddAttr); 3083 $METHOD_REPORT .= "<tr>\n<th>$ProblemNum</th>\n<td>".$Change."</td>\n<td>".$Effect."</td>\n</tr>\n"; 4227 3084 $ProblemNum += 1; 4228 3085 $ProblemsNum += 1; … … 4233 3090 if($METHOD_REPORT) 4234 3091 { 4235 my $ShowMethod = highLight_ Signature_Italic_Color($Method, 1);3092 my $ShowMethod = highLight_ItalicColor($Method, 1); 4236 3093 if($NameSpace) 4237 3094 { 4238 $METHOD_REPORT = cut _Namespace($METHOD_REPORT, $NameSpace);4239 $ShowMethod = cut _Namespace($ShowMethod, $NameSpace);3095 $METHOD_REPORT = cutNs($METHOD_REPORT, $NameSpace); 3096 $ShowMethod = cutNs($ShowMethod, $NameSpace); 4240 3097 } 4241 3098 4242 3099 $METHOD_PROBLEMS .= $ContentSpanStart."<span class='ext'>[+]</span> ".$ShowMethod; 4243 if($ OldStyle) {3100 if($In::Opt{"OldStyle"}) { 4244 3101 $METHOD_PROBLEMS .= " ($ProblemNum)"; 4245 3102 } … … 4250 3107 $METHOD_PROBLEMS .= $ContentDivStart; 4251 3108 4252 if(not $ Compact) {4253 $METHOD_PROBLEMS .= "<span class='mngl '>   [mangled: <b>".htmlSpecChars($Method)."</b>]</span><br/>\n";3109 if(not $In::Opt{"Compact"}) { 3110 $METHOD_PROBLEMS .= "<span class='mngl pleft'>".specChars($Method)."</span><br/>\n"; 4254 3111 } 4255 3112 … … 4272 3129 $Title = "Other Changes in Methods"; 4273 3130 } 4274 if($ OldStyle) {3131 if($In::Opt{"OldStyle"}) { 4275 3132 $METHOD_PROBLEMS = "<h2>$Title ($ProblemsNum)</h2><hr/>\n".$METHOD_PROBLEMS; 4276 3133 } … … 4278 3135 $METHOD_PROBLEMS = "<h2>$Title <span".getStyle("M", $TargetSeverity, $ProblemsNum)."> $ProblemsNum </span></h2><hr/>\n".$METHOD_PROBLEMS; 4279 3136 } 4280 $METHOD_PROBLEMS = "<a name='".get _Anchor("Method", $Level, $TargetSeverity)."'></a>\n".$METHOD_PROBLEMS;3137 $METHOD_PROBLEMS = "<a name='".getAnchor("Method", $Level, $TargetSeverity)."'></a>\n".$METHOD_PROBLEMS; 4281 3138 $METHOD_PROBLEMS .= $TOP_REF."<br/>\n"; 4282 3139 } … … 4284 3141 } 4285 3142 4286 sub get_Report_TypeProblems($$) 3143 sub showType($$$) 3144 { 3145 my ($Name, $Html, $LVer) = @_; 3146 my $TType = $TypeInfo{$LVer}{$TName_Tid{$LVer}{$Name}}{"Type"}; 3147 if($Html) { 3148 $Name = "<span class='ttype'>".$TType."</span> ".specChars($Name); 3149 } 3150 else { 3151 $Name = $TType." ".$Name; 3152 } 3153 return $Name; 3154 } 3155 3156 sub getReportTypeProblems($$) 4287 3157 { 4288 3158 my ($TargetSeverity, $Level) = @_; 4289 3159 my $TYPE_PROBLEMS = ""; 3160 4290 3161 my %ReportMap = (); 4291 3162 my %TypeChanges_Sev = (); … … 4297 3168 foreach my $Kind (keys(%{$TypeChanges{$Level}{$TypeName}})) 4298 3169 { 4299 my $Severity = $TypeProblems_Kind{$Level}{$Kind}; 3170 if($CompatRules{$Level}{$Kind}{"Severity"} ne $TargetSeverity) { 3171 next; 3172 } 4300 3173 4301 if($Severity ne $TargetSeverity) { 4302 next; 4303 } 4304 4305 foreach my $Location (keys(%{$TypeChanges{$Level}{$TypeName}{$Kind}})) 3174 foreach my $Loc (keys(%{$TypeChanges{$Level}{$TypeName}{$Kind}})) 4306 3175 { 4307 3176 $ReportMap{$ArchiveName}{$TypeName} = 1; 4308 $TypeChanges_Sev{$TypeName}{$Kind}{$Loc ation} = $TypeChanges{$Level}{$TypeName}{$Kind}{$Location};3177 $TypeChanges_Sev{$TypeName}{$Kind}{$Loc} = $TypeChanges{$Level}{$TypeName}{$Kind}{$Loc}; 4309 3178 } 4310 3179 } … … 4314 3183 foreach my $ArchiveName (sort {lc($a) cmp lc($b)} keys(%ReportMap)) 4315 3184 { 4316 my ($HEADER_REPORT, %NameSpace_Type) = (); 4317 foreach my $TypeName (keys(%{$ReportMap{$ArchiveName}})) 4318 { 3185 my %NameSpace_Type = (); 3186 foreach my $TypeName (keys(%{$ReportMap{$ArchiveName}})) { 4319 3187 $NameSpace_Type{$TypeInfo{1}{$TName_Tid{1}{$TypeName}}{"Package"}}{$TypeName} = 1; 4320 3188 } … … 4326 3194 } 4327 3195 4328 my @SortedTypes = sort {lc( $a) cmp lc($b)} keys(%{$NameSpace_Type{$NameSpace}});3196 my @SortedTypes = sort {lc(showType($a, 0, 1)) cmp lc(showType($b, 0, 1))} keys(%{$NameSpace_Type{$NameSpace}}); 4329 3197 foreach my $TypeName (@SortedTypes) 4330 3198 { 4331 3199 my $TypeId = $TName_Tid{1}{$TypeName}; 3200 4332 3201 my $ProblemNum = 1; 4333 3202 my $TYPE_REPORT = ""; 4334 3203 my (%Kinds_Locations, %Kinds_Target) = (); 3204 4335 3205 foreach my $Kind (sort keys(%{$TypeChanges_Sev{$TypeName}})) 4336 3206 { … … 4345 3215 $Kinds_Target{$Kind}{$Target} = 1; 4346 3216 4347 my ($Change, $Effect) = ("", ""); 4348 my %Problems = %{$TypeChanges_Sev{$TypeName}{$Kind}{$Location}}; 3217 my %AddAttr = (); 4349 3218 4350 my $Old_Value = $Problems{"Old_Value"}; 4351 my $New_Value = $Problems{"New_Value"}; 4352 my $Field_Type = $Problems{"Field_Type"}; 4353 my $Field_Value = $Problems{"Field_Value"}; 4354 my $Type_Type = $Problems{"Type_Type"}; 4355 4356 if($Kind eq "NonAbstract_Class_Added_Abstract_Method") 3219 if($Kind=~/Method/) 4357 3220 { 4358 $Change = "Abstract method ".black_Name($Target, 2)." has been added to this $Type_Type."; 4359 if($Level eq "Binary") { 4360 $Effect = "This class became <b>abstract</b> and a client program may be interrupted by <b>InstantiationError</b> exception."; 3221 if(defined $MethodInfo{1}{$Target} and $MethodInfo{1}{$Target}{"Name"}) 3222 { 3223 $AddAttr{"Method_Short"} = $Target; 3224 $AddAttr{"Class"} = getTypeName($MethodInfo{1}{$Target}{"Class"}, 1); 4361 3225 } 4362 else { 4363 $Effect = "Recompilation of a client program may be terminated with the message: a client class C is not abstract and does not override abstract method <b>".htmlSpecChars(get_Signature($Target, 2, "Short"))."</b> in <b>".htmlSpecChars(get_TypeName($MethodInfo{2}{$Target}{"Class"}, 2))."</b>."; 3226 elsif(defined $MethodInfo{2}{$Target} and $MethodInfo{2}{$Target}{"Name"}) 3227 { 3228 $AddAttr{"Method_Short"} = $Target; 3229 $AddAttr{"Class"} = getTypeName($MethodInfo{2}{$Target}{"Class"}, 2); 4364 3230 } 4365 3231 } 4366 elsif($Kind eq "Abstract_Class_Added_Abstract_Method") 3232 3233 my $ProblemAttr = $TypeChanges_Sev{$TypeName}{$Kind}{$Location}; 3234 3235 if(my $Change = applyMacroses($Level, $Kind, $CompatRules{$Level}{$Kind}{"Change"}, $ProblemAttr, \%AddAttr)) 4367 3236 { 4368 $Change = "Abstract method ".black_Name($Target, 2)." has been added to this $Type_Type."; 4369 if($Level eq "Binary") { 4370 $Effect = "No effect."; 4371 } 4372 else { 4373 $Effect = "Recompilation of a client program may be terminated with the message: a client class C is not abstract and does not override abstract method <b>".htmlSpecChars(get_Signature($Target, 2, "Short"))."</b> in <b>".htmlSpecChars(get_TypeName($MethodInfo{2}{$Target}{"Class"}, 2))."</b>."; 4374 } 4375 } 4376 elsif($Kind eq "Abstract_Class_Added_Abstract_Method_Invoked_By_Others") 4377 { 4378 $Change = "Abstract method ".black_Name($Target, 2)." has been added to this $Type_Type."; 4379 if($Level eq "Binary") { 4380 $Effect = "A client program may be interrupted by <b>AbstractMethodError</b> exception. Added abstract method is called in 2nd library version by the method ".black_Name($Problems{"InvokedBy"}, 1)." and may not be implemented by old clients."; 4381 } 4382 else { 4383 $Effect = "Recompilation of a client program may be terminated with the message: a client class C is not abstract and does not override abstract method <b>".htmlSpecChars(get_Signature($Target, 2, "Short"))."</b> in <b>".htmlSpecChars(get_TypeName($MethodInfo{2}{$Target}{"Class"}, 2))."</b>."; 4384 } 4385 } 4386 elsif($Kind eq "Class_Removed_Abstract_Method" 4387 or $Kind eq "Interface_Removed_Abstract_Method") 4388 { 4389 $Change = "Abstract method ".black_Name($Target, 1)." has been removed from this $Type_Type."; 4390 if($Level eq "Binary") { 4391 $Effect = "A client program may be interrupted by <b>NoSuchMethodError</b> exception."; 4392 } 4393 else { 4394 $Effect = "Recompilation of a client program may be terminated with the message: cannot find method <b>".htmlSpecChars(get_Signature($Target, 1, "Short"))."</b> in $Type_Type <b>".htmlSpecChars(get_TypeName($MethodInfo{1}{$Target}{"Class"}, 1))."</b>."; 4395 } 4396 } 4397 elsif($Kind eq "Interface_Added_Abstract_Method") 4398 { 4399 $Change = "Abstract method ".black_Name($Target, 2)." has been added to this $Type_Type."; 4400 if($Level eq "Binary") { 4401 $Effect = "No effect."; 4402 } 4403 else { 4404 $Effect = "Recompilation of a client program may be terminated with the message: a client class C is not abstract and does not override abstract method <b>".htmlSpecChars(get_Signature($Target, 2, "Short"))."</b> in <b>".htmlSpecChars(get_TypeName($MethodInfo{2}{$Target}{"Class"}, 2))."</b>."; 4405 } 4406 } 4407 elsif($Kind eq "Interface_Added_Abstract_Method_Invoked_By_Others") 4408 { 4409 $Change = "Abstract method ".black_Name($Target, 2)." has been added to this $Type_Type."; 4410 if($Level eq "Binary") { 4411 $Effect = "A client program may be interrupted by <b>AbstractMethodError</b> exception. Added abstract method is called in 2nd library version by the method ".black_Name($Problems{"InvokedBy"}, 1)." and may not be implemented by old clients."; 4412 } 4413 else { 4414 $Effect = "Recompilation of a client program may be terminated with the message: a client class C is not abstract and does not override abstract method <b>".htmlSpecChars(get_Signature($Target, 2, "Short"))."</b> in <b>".htmlSpecChars(get_TypeName($MethodInfo{2}{$Target}{"Class"}, 2))."</b>."; 4415 } 4416 } 4417 elsif($Kind eq "Class_Method_Became_Abstract") 4418 { 4419 $Change = "Method ".black_Name($Target, 1)." became <b>abstract</b>."; 4420 if($Level eq "Binary") { 4421 $Effect = "A client program may be interrupted by <b>InstantiationError</b> exception."; 4422 } 4423 else { 4424 $Effect = "Recompilation of a client program may be terminated with the message: a client class C is not abstract and does not override abstract method <b>".htmlSpecChars(get_Signature($Target, 1, "Short"))."</b> in <b>".htmlSpecChars(get_TypeName($MethodInfo{1}{$Target}{"Class"}, 1))."</b>."; 4425 } 4426 } 4427 elsif($Kind eq "Class_Method_Became_NonAbstract") 4428 { 4429 $Change = "Abstract method ".black_Name($Target, 1)." became <b>non-abstract</b>."; 4430 if($Level eq "Binary") { 4431 $Effect = "Some methods in this class may change behavior."; 4432 } 4433 else { 4434 $Effect = "No effect."; 4435 } 4436 } 4437 elsif($Kind eq "Interface_Method_Became_NonDefault") 4438 { 4439 $Change = "Method ".black_Name($Target, 1)." became <b>non-default</b>."; 4440 if($Level eq "Binary") { 4441 $Effect = "A client program may be interrupted by <b>AbstractMethodError</b> exception."; 4442 } 4443 else { 4444 $Effect = "Recompilation of a client program may be terminated with the message: a client class C is not abstract and does not override abstract method <b>".htmlSpecChars(get_Signature($Target, 1, "Short"))."</b> in <b>".htmlSpecChars(get_TypeName($MethodInfo{1}{$Target}{"Class"}, 1))."</b>."; 4445 } 4446 } 4447 elsif($Kind eq "Interface_Method_Became_Default") 4448 { 4449 $Change = "Method ".black_Name($Target, 1)." became <b>default</b>."; 4450 if($Level eq "Binary") { 4451 $Effect = "No effect."; 4452 } 4453 else { 4454 $Effect = "No effect."; 4455 } 4456 } 4457 elsif($Kind eq "Class_Overridden_Method") 4458 { 4459 $Change = "Method ".black_Name($Old_Value, 2)." has been overridden by ".black_Name($New_Value, 2); 4460 $Effect = "Method ".black_Name($New_Value, 2)." will be called instead of ".black_Name($Old_Value, 2)." in a client program."; 4461 } 4462 elsif($Kind eq "Class_Method_Moved_Up_Hierarchy") 4463 { 4464 $Change = "Method ".black_Name($Old_Value, 1)." has been moved up type hierarchy to ".black_Name($New_Value, 2); 4465 $Effect = "Method ".black_Name($New_Value, 2)." will be called instead of ".black_Name($Old_Value, 1)." in a client program."; 4466 } 4467 elsif($Kind eq "Abstract_Class_Added_Super_Interface") 4468 { 4469 $Change = "Added super-interface <b>".htmlSpecChars($Target)."</b>."; 4470 if($Level eq "Binary") 4471 { 4472 $Effect = "No effect."; 4473 } 4474 else { 4475 $Effect = "Recompilation of a client program may be terminated with the message: a client class C is not abstract and does not override abstract method in <b>".htmlSpecChars($Target)."</b>."; 4476 } 4477 } 4478 elsif($Kind eq "Abstract_Class_Added_Super_Interface_Invoked_By_Others") 4479 { 4480 $Change = "Added super-interface <b>".htmlSpecChars($Target)."</b>."; 4481 if($Level eq "Binary") { 4482 $Effect = "If abstract methods from an added super-interface must be implemented by client then it may be interrupted by <b>AbstractMethodError</b> exception.<br/><br/>Abstract method ".black_Name_S(htmlSpecChars($Problems{"Invoked"}))." from the added super-interface is called by the method ".black_Name($Problems{"InvokedBy"}, 2)." in 2nd library version and may not be implemented by old clients."; 4483 } 4484 else { 4485 $Effect = "Recompilation of a client program may be terminated with the message: a client class C is not abstract and does not override abstract method in <b>".htmlSpecChars($Target)."</b>."; 4486 } 4487 } 4488 elsif($Kind eq "Abstract_Class_Added_Super_Interface_With_Implemented_Methods") 4489 { 4490 $Change = "Added super-interface <b>".htmlSpecChars($Target)."</b>."; 4491 $Effect = "No effect."; 4492 } 4493 elsif($Kind eq "Interface_Added_Super_Interface") 4494 { 4495 $Change = "Added super-interface <b>".htmlSpecChars($Target)."</b>."; 4496 if($Level eq "Binary") { 4497 $Effect = "No effect."; 4498 } 4499 else { 4500 $Effect = "Recompilation of a client program may be terminated with the message: a client class C is not abstract and does not override abstract method in <b>".htmlSpecChars($Target)."</b>."; 4501 } 4502 } 4503 elsif($Kind eq "Interface_Added_Super_Interface_Used_By_Others") 4504 { 4505 $Change = "Added super-interface <b>".htmlSpecChars($Target)."</b>."; 4506 if($Level eq "Binary") 4507 { 4508 $Effect = "If abstract methods from an added super-interface must be implemented by client then it may be interrupted by <b>AbstractMethodError</b> exception.<br/><br/>Abstract method ".black_Name_S(htmlSpecChars($Problems{"Invoked"}))." from the added super-interface is called by the method ".black_Name($Problems{"InvokedBy"}, 2)." in 2nd library version and may not be implemented by old clients."; 4509 } 4510 else { 4511 $Effect = "Recompilation of a client program may be terminated with the message: a client class C is not abstract and does not override abstract method in <b>".htmlSpecChars($Target)."</b>."; 4512 } 4513 } 4514 elsif($Kind eq "Interface_Added_Super_Interface_With_Implemented_Methods") 4515 { 4516 $Change = "Added super-interface <b>".htmlSpecChars($Target)."</b>."; 4517 if($Level eq "Binary") { 4518 $Effect = "No effect."; 4519 } 4520 else { 4521 $Effect = "No effect."; 4522 } 4523 } 4524 elsif($Kind eq "Interface_Added_Super_Constant_Interface") 4525 { 4526 $Change = "Added super-interface <b>".htmlSpecChars($Target)."</b> containing constants only."; 4527 if($Level eq "Binary") { 4528 $Effect = "A static field from a super-interface of a client class may hide a field (with the same name) inherited from a super-class and cause <b>IncompatibleClassChangeError</b> exception."; 4529 } 4530 else { 4531 $Effect = "A static field from a super-interface of a client class may hide a field (with the same name) inherited from a super-class. Recompilation of a client class may be terminated with the message: reference to variable is ambiguous."; 4532 } 4533 } 4534 elsif($Kind eq "Interface_Removed_Super_Interface" 4535 or $Kind eq "Class_Removed_Super_Interface") 4536 { 4537 $Change = "Removed super-interface <b>".htmlSpecChars($Target)."</b>."; 4538 if($Level eq "Binary") { 4539 $Effect = "A client program may be interrupted by <b>NoSuchMethodError</b> exception."; 4540 } 4541 else { 4542 $Effect = "Recompilation of a client program may be terminated with the message: cannot find method in $Type_Type <b>".htmlSpecChars($TypeName)."</b>."; 4543 } 4544 } 4545 elsif($Kind eq "Interface_Removed_Super_Constant_Interface") 4546 { 4547 $Change = "Removed super-interface <b>".htmlSpecChars($Target)."</b> containing constants only."; 4548 if($Level eq "Binary") { 4549 $Effect = "No effect."; 4550 } 4551 else { 4552 $Effect = "Recompilation of a client program may be terminated with the message: cannot find variable in $Type_Type <b>".htmlSpecChars($TypeName)."</b>."; 4553 } 4554 } 4555 elsif($Kind eq "Added_Super_Class") 4556 { 4557 $Change = "Added super-class <b>".htmlSpecChars($Target)."</b>."; 4558 if($Level eq "Binary") { 4559 $Effect = "A static field from a super-interface of a client class may hide a field (with the same name) inherited from new super-class and cause <b>IncompatibleClassChangeError</b> exception."; 4560 } 4561 else { 4562 $Effect = "A static field from a super-interface of a client class may hide a field (with the same name) inherited from new super-class. Recompilation of a client class may be terminated with the message: reference to variable is ambiguous."; 4563 } 4564 } 4565 elsif($Kind eq "Abstract_Class_Added_Super_Abstract_Class") 4566 { 4567 $Change = "Added abstract super-class <b>".htmlSpecChars($Target)."</b>."; 4568 if($Level eq "Binary") { 4569 $Effect = "No effect."; 4570 } 4571 else { 4572 $Effect = "Recompilation of a client program may be terminated with the message: a client class C is not abstract and does not override abstract method in <b>".htmlSpecChars($Target)."</b>."; 4573 } 4574 } 4575 elsif($Kind eq "Abstract_Class_Added_Super_Abstract_Class_Invoked_By_Others") 4576 { 4577 $Change = "Added abstract super-class <b>".htmlSpecChars($Target)."</b>."; 4578 if($Level eq "Binary") { 4579 $Effect = "If abstract methods from an added super-class must be implemented by client then it may be interrupted by <b>AbstractMethodError</b> exception.<br/><br/>Abstract method ".black_Name_S(htmlSpecChars($Problems{"Invoked"}))." from the added abstract super-class is called by the method ".black_Name($Problems{"InvokedBy"}, 2)." in 2nd library version and may not be implemented by old clients."; 4580 } 4581 else { 4582 $Effect = "Recompilation of a client program may be terminated with the message: a client class C is not abstract and does not override abstract method in <b>".htmlSpecChars($Target)."</b>."; 4583 } 4584 } 4585 elsif($Kind eq "Removed_Super_Class") 4586 { 4587 $Change = "Removed super-class <b>".htmlSpecChars($Target)."</b>."; 4588 if($Level eq "Binary") { 4589 $Effect = "Access of a client program to the fields or methods of the old super-class may be interrupted by <b>NoSuchFieldError</b> or <b>NoSuchMethodError</b> exceptions."; 4590 } 4591 else { 4592 $Effect = "Recompilation of a client program may be terminated with the message: cannot find variable (or method) in <b>".htmlSpecChars($TypeName)."</b>."; 4593 } 4594 } 4595 elsif($Kind eq "Changed_Super_Class") 4596 { 4597 $Change = "Superclass has been changed from <b>".htmlSpecChars($Old_Value)."</b> to <b>".htmlSpecChars($New_Value)."</b>."; 4598 if($Level eq "Binary") { 4599 $Effect = "1) Access of a client program to the fields or methods of the old super-class may be interrupted by <b>NoSuchFieldError</b> or <b>NoSuchMethodError</b> exceptions.<br/>2) A static field from a super-interface of a client class may hide a field (with the same name) inherited from new super-class and cause <b>IncompatibleClassChangeError</b> exception."; 4600 } 4601 else { 4602 $Effect = "1) Recompilation of a client program may be terminated with the message: cannot find variable (or method) in <b>".htmlSpecChars($TypeName)."</b>.<br/>2) A static field from a super-interface of a client class may hide a field (with the same name) inherited from new super-class. Recompilation of a client class may be terminated with the message: reference to variable is ambiguous."; 4603 } 4604 } 4605 elsif($Kind eq "Class_Added_Field") 4606 { 4607 $Change = "Field <b>$Target</b> has been added to this class."; 4608 if($Level eq "Binary") 4609 { 4610 $Effect = "No effect."; 4611 # $Effect .= "<br/><b>NOTE</b>: A static field from a super-interface of a client class may hide an added field (with the same name) inherited from the super-class of a client class and cause <b>IncompatibleClassChangeError</b> exception."; 4612 } 4613 else 4614 { 4615 $Effect = "No effect."; 4616 # $Effect .= "<br/><b>NOTE</b>: A static field from a super-interface of a client class may hide an added field (with the same name) inherited from the super-class of a client class. Recompilation of a client class may be terminated with the message: reference to <b>$Target</b> is ambiguous."; 4617 } 4618 } 4619 elsif($Kind eq "Interface_Added_Field") 4620 { 4621 $Change = "Field <b>$Target</b> has been added to this interface."; 4622 if($Level eq "Binary") { 4623 $Effect = "No effect.<br/><b>NOTE</b>: An added static field from a super-interface of a client class may hide a field (with the same name) inherited from the super-class of a client class and cause <b>IncompatibleClassChangeError</b> exception."; 4624 } 4625 else { 4626 $Effect = "No effect.<br/><b>NOTE</b>: An added static field from a super-interface of a client class may hide a field (with the same name) inherited from the super-class of a client class. Recompilation of a client class may be terminated with the message: reference to <b>$Target</b> is ambiguous."; 4627 } 4628 } 4629 elsif($Kind eq "Renamed_Field") 4630 { 4631 $Change = "Field <b>$Target</b> has been renamed to <b>".htmlSpecChars($New_Value)."</b>."; 4632 if($Level eq "Binary") { 4633 $Effect = "A client program may be interrupted by <b>NoSuchFieldError</b> exception."; 4634 } 4635 else { 4636 $Effect = "Recompilation of a client program may be terminated with the message: cannot find variable <b>$Target</b> in <b>".htmlSpecChars($TypeName)."</b>."; 4637 } 4638 } 4639 elsif($Kind eq "Renamed_Constant_Field") 4640 { 4641 if($Level eq "Binary") { 4642 $Change = "Field <b>$Target</b> (".htmlSpecChars($Field_Type).") with the compile-time constant value <b>$Field_Value</b> has been renamed to <b>".htmlSpecChars($New_Value)."</b>."; 4643 $Effect = "A client program may change behavior."; 4644 } 4645 else { 4646 $Change = "Field <b>$Target</b> has been renamed to <b>".htmlSpecChars($New_Value)."</b>."; 4647 $Effect = "Recompilation of a client program may be terminated with the message: cannot find variable <b>$Target</b> in <b>".htmlSpecChars($TypeName)."</b>."; 4648 } 4649 } 4650 elsif($Kind eq "Removed_NonConstant_Field") 4651 { 4652 $Change = "Field <b>$Target</b> of type ".htmlSpecChars($Field_Type)." has been removed from this $Type_Type."; 4653 if($Level eq "Binary") { 4654 $Effect = "A client program may be interrupted by <b>NoSuchFieldError</b> exception."; 4655 } 4656 else { 4657 $Effect = "Recompilation of a client program may be terminated with the message: cannot find variable <b>$Target</b> in <b>".htmlSpecChars($TypeName)."</b>."; 4658 } 4659 } 4660 elsif($Kind eq "Removed_Constant_Field") 4661 { 4662 $Change = "Field <b>$Target</b> (".htmlSpecChars($Field_Type).") with the compile-time constant value <b>$Field_Value</b> has been removed from this $Type_Type."; 4663 if($Level eq "Binary") { 4664 $Effect = "A client program may change behavior."; 4665 } 4666 else { 4667 $Effect = "Recompilation of a client program may be terminated with the message: cannot find variable <b>$Target</b> in <b>".htmlSpecChars($TypeName)."</b>."; 4668 } 4669 } 4670 elsif($Kind eq "Changed_Field_Type") 4671 { 4672 $Change = "Type of field <b>$Target</b> has been changed from <span class='nowrap'><b>".htmlSpecChars($Old_Value)."</b></span> to <span class='nowrap'><b>".htmlSpecChars($New_Value)."</b></span>."; 4673 if($Level eq "Binary") { 4674 $Effect = "A client program may be interrupted by <b>NoSuchFieldError</b> exception."; 4675 } 4676 else { 4677 $Effect = "Recompilation of a client program may be terminated with the message: incompatible types, found: <b>".htmlSpecChars($Old_Value)."</b>, required: <b>".htmlSpecChars($New_Value)."</b>."; 4678 } 4679 } 4680 elsif($Kind eq "Changed_Field_Access") 4681 { 4682 $Change = "Access level of field <b>$Target</b> has been changed from <span class='nowrap'><b>$Old_Value</b></span> to <span class='nowrap'><b>$New_Value</b></span>."; 4683 if($Level eq "Binary") { 4684 $Effect = "A client program may be interrupted by <b>IllegalAccessError</b> exception."; 4685 } 4686 else 4687 { 4688 if($New_Value eq "package-private") { 4689 $Effect = "Recompilation of a client program may be terminated with the message: <b>$Target</b> is not public in <b>".htmlSpecChars($TypeName)."</b>; cannot be accessed from outside package."; 4690 } 4691 else { 4692 $Effect = "Recompilation of a client program may be terminated with the message: <b>$Target</b> has <b>$New_Value</b> access in <b>".htmlSpecChars($TypeName)."</b>."; 4693 } 4694 } 4695 } 4696 elsif($Kind eq "Changed_Final_Field_Value") 4697 { # Binary Only 4698 $Change = "Value of final field <b>$Target</b> (<b>$Field_Type</b>) has been changed from <span class='nowrap'><b>".htmlSpecChars($Old_Value)."</b></span> to <span class='nowrap'><b>".htmlSpecChars($New_Value)."</b></span>."; 4699 $Effect = "Old value of the field will be inlined to the client code at compile-time and will be used instead of a new one."; 4700 } 4701 elsif($Kind eq "Changed_Final_Version_Field_Value") 4702 { # Binary Only 4703 $Change = "Value of final field <b>$Target</b> (<b>$Field_Type</b>) has been changed from <span class='nowrap'><b>".htmlSpecChars($Old_Value)."</b></span> to <span class='nowrap'><b>".htmlSpecChars($New_Value)."</b></span>."; 4704 $Effect = "Old value of the field will be inlined to the client code at compile-time and will be used instead of a new one."; 4705 } 4706 elsif($Kind eq "Field_Became_Final") 4707 { 4708 $Change = "Field <b>$Target</b> became <b>final</b>."; 4709 if($Level eq "Binary") { 4710 $Effect = "A client program may be interrupted by <b>IllegalAccessError</b> exception when attempt to assign new values to the field."; 4711 } 4712 else { 4713 $Effect = "Recompilation of a client program may be terminated with the message: cannot assign a value to final variable $Target."; 4714 } 4715 } 4716 elsif($Kind eq "Field_Became_NonFinal") 4717 { # Binary Only 4718 $Change = "Field <b>$Target</b> became <b>non-final</b>."; 4719 $Effect = "Old value of the field will be inlined to the client code at compile-time and will be used instead of a new one."; 4720 } 4721 elsif($Kind eq "NonConstant_Field_Became_Static") 4722 { # Binary Only 4723 $Change = "Non-final field <b>$Target</b> became <b>static</b>."; 4724 $Effect = "A client program may be interrupted by <b>IncompatibleClassChangeError</b> exception."; 4725 } 4726 elsif($Kind eq "NonConstant_Field_Became_NonStatic") 4727 { 4728 if($Level eq "Binary") { 4729 $Change = "Non-constant field <b>$Target</b> became <b>non-static</b>."; 4730 $Effect = "A client program may be interrupted by <b>IncompatibleClassChangeError</b> exception."; 4731 } 4732 else { 4733 $Change = "Field <b>$Target</b> became <b>non-static</b>."; 4734 $Effect = "Recompilation of a client program may be terminated with the message: non-static variable <b>$Target</b> cannot be referenced from a static context."; 4735 } 4736 } 4737 elsif($Kind eq "Constant_Field_Became_NonStatic") 4738 { # Source Only 4739 $Change = "Field <b>$Target</b> became <b>non-static</b>."; 4740 $Effect = "Recompilation of a client program may be terminated with the message: non-static variable <b>$Target</b> cannot be referenced from a static context."; 4741 } 4742 elsif($Kind eq "Class_Became_Interface") 4743 { 4744 $Change = "This <b>class</b> became <b>interface</b>."; 4745 if($Level eq "Binary") { 4746 $Effect = "A client program may be interrupted by <b>IncompatibleClassChangeError</b> or <b>InstantiationError</b> exception dependent on the usage of this class."; 4747 } 4748 else { 4749 $Effect = "Recompilation of a client program may be terminated with the message: <b>".htmlSpecChars($TypeName)."</b> is abstract; cannot be instantiated."; 4750 } 4751 } 4752 elsif($Kind eq "Interface_Became_Class") 4753 { 4754 $Change = "This <b>interface</b> became <b>class</b>."; 4755 if($Level eq "Binary") { 4756 $Effect = "A client program may be interrupted by <b>IncompatibleClassChangeError</b> exception."; 4757 } 4758 else { 4759 $Effect = "Recompilation of a client program may be terminated with the message: interface expected."; 4760 } 4761 } 4762 elsif($Kind eq "Class_Became_Final") 4763 { 4764 $Change = "This class became <b>final</b>."; 4765 if($Level eq "Binary") { 4766 $Effect = "A client program may be interrupted by <b>VerifyError</b> exception."; 4767 } 4768 else { 4769 $Effect = "Recompilation of a client program may be terminated with the message: cannot inherit from final <b>".htmlSpecChars($TypeName)."</b>."; 4770 } 4771 } 4772 elsif($Kind eq "Class_Became_Abstract") 4773 { 4774 $Change = "This class became <b>abstract</b>."; 4775 if($Level eq "Binary") { 4776 $Effect = "A client program may be interrupted by <b>InstantiationError</b> exception."; 4777 } 4778 else { 4779 $Effect = "Recompilation of a client program may be terminated with the message: <b>".htmlSpecChars($TypeName)."</b> is abstract; cannot be instantiated."; 4780 } 4781 } 4782 elsif($Kind eq "Removed_Class") 4783 { 4784 $Change = "This class has been removed."; 4785 if($Level eq "Binary") { 4786 $Effect = "A client program may be interrupted by <b>NoClassDefFoundError</b> exception."; 4787 } 4788 else { 4789 $Effect = "Recompilation of a client program may be terminated with the message: cannot find class <b>".htmlSpecChars($TypeName)."</b>."; 4790 } 4791 } 4792 elsif($Kind eq "Removed_Interface") 4793 { 4794 $Change = "This interface has been removed."; 4795 if($Level eq "Binary") { 4796 $Effect = "A client program may be interrupted by <b>NoClassDefFoundError</b> exception."; 4797 } 4798 else { 4799 $Effect = "Recompilation of a client program may be terminated with the message: cannot find class <b>".htmlSpecChars($TypeName)."</b>."; 4800 } 4801 } 4802 elsif($Kind eq "Removed_Annotation") 4803 { 4804 $Change = "This annotation type has been removed."; 4805 if($Level eq "Binary") { 4806 $Effect = "No effect."; 4807 } 4808 else { 4809 $Effect = "Recompilation of a client program may be terminated with the error message: cannot find symbol <b>\@".htmlSpecChars($TypeName)."</b>."; 4810 } 4811 } 4812 if($Change) 4813 { 4814 $TYPE_REPORT .= "<tr><th>$ProblemNum</th><td>".$Change."</td><td>".$Effect."</td></tr>\n"; 3237 my $Effect = applyMacroses($Level, $Kind, $CompatRules{$Level}{$Kind}{"Effect"}, $ProblemAttr, \%AddAttr); 3238 3239 $TYPE_REPORT .= "<tr>\n<th>$ProblemNum</th>\n<td>".$Change."</td>\n<td>".$Effect."</td>\n</tr>\n"; 4815 3240 $ProblemNum += 1; 4816 3241 $ProblemsNum += 1; 4817 $Kinds_Locations{$Kind}{$Location} = 1;4818 3242 } 4819 3243 } … … 4827 3251 } 4828 3252 4829 my $ShowType = $TypeName;3253 my $ShowType = showType($TypeName, 1, 1); 4830 3254 if($NameSpace) 4831 3255 { 4832 $TYPE_REPORT = cut _Namespace($TYPE_REPORT, $NameSpace);4833 $ShowType = cut _Namespace($ShowType, $NameSpace);4834 $Affected = cut _Namespace($Affected, $NameSpace);3256 $TYPE_REPORT = cutNs($TYPE_REPORT, $NameSpace); 3257 $ShowType = cutNs($ShowType, $NameSpace); 3258 $Affected = cutNs($Affected, $NameSpace); 4835 3259 } 4836 3260 4837 $TYPE_PROBLEMS .= $ContentSpanStart."<span class='ext'>[+]</span> ". htmlSpecChars($ShowType);4838 if($ OldStyle) {3261 $TYPE_PROBLEMS .= $ContentSpanStart."<span class='ext'>[+]</span> ".$ShowType; 3262 if($In::Opt{"OldStyle"}) { 4839 3263 $TYPE_PROBLEMS .= " ($ProblemNum)"; 4840 3264 } … … 4861 3285 $Title = "Other Changes in Data Types"; 4862 3286 } 4863 if($ OldStyle) {3287 if($In::Opt{"OldStyle"}) { 4864 3288 $TYPE_PROBLEMS = "<h2>$Title ($ProblemsNum)</h2><hr/>\n".$TYPE_PROBLEMS; 4865 3289 } … … 4867 3291 $TYPE_PROBLEMS = "<h2>$Title <span".getStyle("T", $TargetSeverity, $ProblemsNum)."> $ProblemsNum </span></h2><hr/>\n".$TYPE_PROBLEMS; 4868 3292 } 4869 $TYPE_PROBLEMS = "<a name='".get _Anchor("Type", $Level, $TargetSeverity)."'></a>\n".$TYPE_PROBLEMS;3293 $TYPE_PROBLEMS = "<a name='".getAnchor("Type", $Level, $TargetSeverity)."'></a>\n".$TYPE_PROBLEMS; 4870 3294 $TYPE_PROBLEMS .= $TOP_REF."<br/>\n"; 4871 3295 } … … 4873 3297 } 4874 3298 4875 sub cut _Namespace($$)3299 sub cutNs($$) 4876 3300 { 4877 3301 my ($N, $Ns) = @_; … … 4885 3309 4886 3310 my $LIMIT = 10; 4887 if(defined $AffectLimit) { 4888 $LIMIT = $AffectLimit; 4889 } 4890 4891 my @Kinds = sort keys(%{$Kinds_Locations}); 4892 my %KLocs = (); 4893 foreach my $Kind (@Kinds) 4894 { 4895 my @Locs = sort {$a=~/retval/ cmp $b=~/retval/} sort {length($a)<=>length($b)} sort keys(%{$Kinds_Locations->{$Kind}}); 4896 $KLocs{$Kind} = \@Locs; 4897 } 4898 4899 my %SymLocKind = (); 4900 foreach my $Method (sort keys(%{$TypeProblemsIndex{$Target_TypeName}})) 4901 { 4902 if($Method eq ".client_method") { 4903 next; 4904 } 4905 4906 foreach my $Kind (@Kinds) 4907 { 4908 foreach my $Loc (@{$KLocs{$Kind}}) 4909 { 4910 if(not defined $CompatProblems{$Method}{$Kind}{$Loc}) { 3311 if(defined $In::Opt{"AffectLimit"}) { 3312 $LIMIT = $In::Opt{"AffectLimit"}; 3313 } 3314 3315 my %SymSel = (); 3316 3317 foreach my $Kind (sort keys(%{$Kinds_Locations})) 3318 { 3319 my @Locs = sort {(index($a, "retval")!=-1) cmp (index($b, "retval")!=-1)} sort {length($a)<=>length($b)} sort keys(%{$Kinds_Locations->{$Kind}}); 3320 3321 foreach my $Loc (@Locs) 3322 { 3323 foreach my $Method (keys(%{$TypeProblemsIndex{$Level}{$Target_TypeName}{$Kind}{$Loc}})) 3324 { 3325 if($Method eq ".client_method") { 4911 3326 next; 4912 3327 } 4913 3328 4914 my $Type_Name = $CompatProblems{$Method}{$Kind}{$Loc}{"Type_Name"}; 4915 if($Type_Name ne $Target_TypeName) { 4916 next; 4917 } 4918 4919 $SymLocKind{$Method}{$Loc}{$Kind} = 1; 4920 last; 4921 } 4922 } 4923 } 4924 4925 %KLocs = (); # clear 4926 4927 if(not keys(%SymLocKind)) { 3329 if(not defined $SymSel{$Method}) 3330 { 3331 $SymSel{$Method}{"Kind"} = $Kind; 3332 $SymSel{$Method}{"Loc"} = $Loc; 3333 } 3334 } 3335 } 3336 } 3337 3338 my $Total = keys(%SymSel); 3339 3340 if(not $Total) { 4928 3341 return ""; 4929 3342 } 4930 3343 4931 my %SymSel = ();4932 my $Num = 0;4933 foreach my $Method (sort keys(%SymLocKind))4934 {4935 LOOP: foreach my $Loc (sort {$a=~/retval/ cmp $b=~/retval/} sort {length($a)<=>length($b)} sort keys(%{$SymLocKind{$Method}}))4936 {4937 foreach my $Kind (sort keys(%{$SymLocKind{$Method}{$Loc}}))4938 {4939 $SymSel{$Method}{"Loc"} = $Loc;4940 $SymSel{$Method}{"Kind"} = $Kind;4941 last LOOP;4942 }4943 }4944 4945 $Num += 1;4946 4947 if($Num>=$LIMIT) {4948 last;4949 }4950 }4951 4952 3344 my $Affected = ""; 3345 my $SNum = 0; 4953 3346 4954 3347 foreach my $Method (sort {lc($a) cmp lc($b)} keys(%SymSel)) … … 4961 3354 my $Pos = getParamPos($PName, $Method, 1); 4962 3355 4963 $Affected .= "<span class='iname_a'>".get _Signature($Method, 1, "HTML|Italic|Param|Class|Target=".$Pos)."</span><br/>";3356 $Affected .= "<span class='iname_a'>".getSignature($Method, 1, "HTML|Italic|Param|Class|Target=".$Pos)."</span><br/>"; 4964 3357 $Affected .= "<div class='affect'>".$Desc."</div>\n"; 4965 } 4966 4967 if(keys(%SymLocKind)>$LIMIT) { 3358 3359 if(++$SNum>=$LIMIT) { 3360 last; 3361 } 3362 } 3363 3364 if($Total>$LIMIT) { 4968 3365 $Affected .= " <b>...</b>\n<br/>\n"; # and others ... 4969 3366 } … … 4972 3369 if($Affected) 4973 3370 { 4974 my $Num = keys(%SymLocKind); 4975 my $Per = show_number($Num*100/keys(%CheckedMethods)); 3371 my $Per = showNum($Total*100/keys(%CheckedMethods)); 4976 3372 $Affected = $ContentDivStart.$Affected.$ContentDivEnd; 4977 $Affected = $ContentSpanStart_Affected."[+] affected methods: $ Num($Per\%)".$ContentSpanEnd.$Affected;4978 } 4979 4980 return ($Affected);3373 $Affected = $ContentSpanStart_Affected."[+] affected methods: $Total ($Per\%)".$ContentSpanEnd.$Affected; 3374 } 3375 3376 return $Affected; 4981 3377 } 4982 3378 … … 4991 3387 $Location=~s/\.[^.]+?\Z//; 4992 3388 4993 my %TypeAttr = get_Type($MethodInfo{1}{$Method}{"Class"}, 1);4994 my $Type_Type = $TypeAttr {"Type"};3389 my $TypeAttr = getType($MethodInfo{1}{$Method}{"Class"}, 1); 3390 my $Type_Type = $TypeAttr->{"Type"}; 4995 3391 4996 3392 my $ABSTRACT_M = $MethodInfo{1}{$Method}{"Abstract"}?" abstract":""; 4997 my $ABSTRACT_C = $TypeAttr {"Abstract"}?" abstract":"";3393 my $ABSTRACT_C = $TypeAttr->{"Abstract"}?" abstract":""; 4998 3394 my $METHOD_TYPE = $MethodInfo{1}{$Method}{"Constructor"}?"constructor":"method"; 4999 3395 5000 3396 if($Kind eq "Class_Overridden_Method" or $Kind eq "Class_Method_Moved_Up_Hierarchy") { 5001 return "Method '". highLight_Signature($New_Value, 2)."' will be called instead of this method in a client program.";5002 } 5003 elsif($ TypeProblems_Kind{$Level}{$Kind})3397 return "Method '".getSignature($New_Value, 2, "Class|HTML|Italic")."' will be called instead of this method in a client program."; 3398 } 3399 elsif($CompatRules{$Level}{$Kind}{"Kind"} eq "Types") 5004 3400 { 5005 3401 my %MInfo = %{$MethodInfo{1}{$Method}}; 5006 3402 5007 3403 if($Location eq "this") { 5008 return "This$ABSTRACT_M $METHOD_TYPE is from \'". htmlSpecChars($Type_Name)."\'$ABSTRACT_C $Type_Type.";3404 return "This$ABSTRACT_M $METHOD_TYPE is from \'".specChars($Type_Name)."\'$ABSTRACT_C $Type_Type."; 5009 3405 } 5010 3406 … … 5014 3410 { # return value 5015 3411 if($Location=~/\./) { 5016 push(@Sentence_Parts, "Field \'". htmlSpecChars($Location)."\' inreturn value");3412 push(@Sentence_Parts, "Field \'".specChars($Location)."\' in the return value"); 5017 3413 } 5018 3414 else { … … 5024 3420 elsif($Location=~/this/) 5025 3421 { # "this" reference 5026 push(@Sentence_Parts, "Field \'". htmlSpecChars($Location)."\' in the object");3422 push(@Sentence_Parts, "Field \'".specChars($Location)."\' in the object"); 5027 3423 5028 3424 $TypeID = $MInfo{"Class"}; … … 5034 3430 5035 3431 if($Location=~/\./) { 5036 push(@Sentence_Parts, "Field \'". htmlSpecChars($Location)."\' in ".showPos($PPos)." parameter");3432 push(@Sentence_Parts, "Field \'".specChars($Location)."\' in ".showPos($PPos)." parameter"); 5037 3433 } 5038 3434 else { … … 5058 3454 5059 3455 if($TypeInfo{1}{$TypeID_Problem}{"Name"} eq $Type_Name) { 5060 push(@Sentence_Parts, " has type \'".htmlSpecChars($Type_Name)."\'.");3456 push(@Sentence_Parts, "is of type \'".specChars($Type_Name)."\'."); 5061 3457 } 5062 3458 else { 5063 push(@Sentence_Parts, "has base type \'". htmlSpecChars($Type_Name)."\'.");3459 push(@Sentence_Parts, "has base type \'".specChars($Type_Name)."\'."); 5064 3460 } 5065 3461 } … … 5069 3465 sub getParamPos($$$) 5070 3466 { 5071 my ($Name, $Method, $L ibVersion) = @_;5072 5073 if(defined $MethodInfo{$L ibVersion}{$Method}5074 and defined $MethodInfo{$L ibVersion}{$Method}{"Param"})5075 { 5076 my $Info = $MethodInfo{$L ibVersion}{$Method};3467 my ($Name, $Method, $LVer) = @_; 3468 3469 if(defined $MethodInfo{$LVer}{$Method} 3470 and defined $MethodInfo{$LVer}{$Method}{"Param"}) 3471 { 3472 my $Info = $MethodInfo{$LVer}{$Method}; 5077 3473 foreach (keys(%{$Info->{"Param"}})) 5078 3474 { … … 5096 3492 sub getFieldType($$$) 5097 3493 { 5098 my ($Location, $TypeId, $L ibVersion) = @_;3494 my ($Location, $TypeId, $LVer) = @_; 5099 3495 5100 3496 my @Fields = split(/\./, $Location); … … 5102 3498 foreach my $Name (@Fields) 5103 3499 { 5104 my %Info = get_BaseType($TypeId, $LibVersion);5105 5106 foreach my $N (keys(%{$ Info{"Fields"}}))3500 my $TInfo = getBaseType($TypeId, $LVer); 3501 3502 foreach my $N (keys(%{$TInfo->{"Fields"}})) 5107 3503 { 5108 3504 if($N eq $Name) 5109 3505 { 5110 $TypeId = $ Info{"Fields"}{$N}{"Type"};3506 $TypeId = $TInfo->{"Fields"}{$N}{"Type"}; 5111 3507 last; 5112 3508 } … … 5124 3520 } 5125 3521 5126 sub getRelPath($$)5127 {5128 my ($A, $B) = @_;5129 return abs2rel($A, get_dirname($B));5130 }5131 5132 3522 sub createReport() 5133 3523 { 5134 if($JoinReport) 5135 { # --stdout 3524 if($In::Opt{"JoinReport"}) { 5136 3525 writeReport("Join", getReport("Join")); 5137 3526 } 5138 elsif($ DoubleReport)3527 elsif($In::Opt{"DoubleReport"}) 5139 3528 { # default 5140 3529 writeReport("Binary", getReport("Binary")); 5141 3530 writeReport("Source", getReport("Source")); 5142 3531 } 5143 elsif($ BinaryOnly)3532 elsif($In::Opt{"BinaryOnly"}) 5144 3533 { # --binary 5145 3534 writeReport("Binary", getReport("Binary")); 5146 3535 } 5147 elsif($ SourceOnly)3536 elsif($In::Opt{"SourceOnly"}) 5148 3537 { # --source 5149 3538 writeReport("Source", getReport("Source")); … … 5151 3540 } 5152 3541 5153 sub getCssStyles() 5154 { 5155 my $CssStyles = " 5156 body { 5157 font-family:Arial, sans-serif; 5158 background-color:White; 5159 color:Black; 5160 } 5161 hr { 5162 color:Black; 5163 background-color:Black; 5164 height:1px; 5165 border:0; 5166 } 5167 h1 { 5168 margin-bottom:0px; 5169 padding-bottom:0px; 5170 font-size:1.625em; 5171 } 5172 h2 { 5173 margin-bottom:0px; 5174 padding-bottom:0px; 5175 font-size:1.25em; 5176 white-space:nowrap; 5177 } 5178 div.symbols { 5179 color:#003E69; 5180 } 5181 div.symbols i { 5182 color:Brown; 5183 } 5184 span.section { 5185 font-weight:bold; 5186 cursor:pointer; 5187 color:#003E69; 5188 white-space:nowrap; 5189 margin-left:5px; 5190 } 5191 span:hover.section { 5192 color:#336699; 5193 } 5194 span.sect_aff { 5195 cursor:pointer; 5196 margin-left:7px; 5197 padding-left:15px; 5198 font-size:0.875em; 5199 color:#cc3300; 5200 } 5201 span.ext { 5202 font-weight:100; 5203 } 5204 span.jar { 5205 color:#cc3300; 5206 font-size:0.875em; 5207 font-weight:bold; 5208 } 5209 div.jar_list { 5210 padding-left:5px; 5211 font-size:0.94em; 5212 } 5213 span.pkg_t { 5214 color:#408080; 5215 font-size:0.875em; 5216 } 5217 span.pkg { 5218 color:#408080; 5219 font-size:0.875em; 5220 font-weight:bold; 5221 } 5222 span.cname { 5223 color:Green; 5224 font-size:0.875em; 5225 font-weight:bold; 5226 } 5227 span.iname_b { 5228 font-weight:bold; 5229 font-size:1.1em; 5230 } 5231 span.iname_a { 5232 color:#333333; 5233 font-weight:bold; 5234 font-size:0.94em; 5235 } 5236 span.sym_p { 5237 font-weight:normal; 5238 white-space:normal; 5239 } 5240 span.sym_p span { 5241 white-space:nowrap; 5242 } 5243 span.attr { 5244 color:Black; 5245 font-weight:100; 5246 } 5247 span.deprecated { 5248 color:Red; 5249 font-weight:bold; 5250 font-family:Monaco, monospace; 5251 } 5252 div.affect { 5253 padding-left:15px; 5254 padding-bottom:10px; 5255 font-size:0.87em; 5256 font-style:italic; 5257 line-height:0.75em; 5258 } 5259 div.affected { 5260 padding-left:30px; 5261 padding-top:10px; 5262 } 5263 table.ptable { 5264 border-collapse:collapse; 5265 border:1px outset black; 5266 line-height:1em; 5267 margin-left:15px; 5268 margin-top:3px; 5269 margin-bottom:3px; 5270 width:900px; 5271 } 5272 table.ptable td { 5273 border:1px solid Gray; 5274 padding: 3px; 5275 font-size:0.875em; 5276 text-align:left; 5277 vertical-align:top; 5278 } 5279 table.ptable th { 5280 background-color:#eeeeee; 5281 font-weight:bold; 5282 color:#333333; 5283 font-family:Verdana, Arial; 5284 font-size:0.875em; 5285 border:1px solid Gray; 5286 text-align:center; 5287 vertical-align:top; 5288 white-space:nowrap; 5289 padding: 3px; 5290 } 5291 table.summary { 5292 border-collapse:collapse; 5293 border:1px outset black; 5294 } 5295 table.summary th { 5296 background-color:#eeeeee; 5297 font-weight:100; 5298 text-align:left; 5299 font-size:0.94em; 5300 white-space:nowrap; 5301 border:1px inset Gray; 5302 padding: 3px; 5303 } 5304 table.summary td { 5305 text-align:right; 5306 white-space:nowrap; 5307 border:1px inset Gray; 5308 padding: 3px 5px 3px 10px; 5309 } 5310 span.mngl { 5311 padding-left:15px; 5312 font-size:0.875em; 5313 cursor:text; 5314 color:#444444; 5315 } 5316 span.color_p { 5317 font-style:italic; 5318 color:Brown; 5319 } 5320 span.param { 5321 font-style:italic; 5322 } 5323 span.focus_p { 5324 font-style:italic; 5325 background-color:#DCDCDC; 5326 } 5327 span.nowrap { 5328 white-space:nowrap; 5329 } 5330 .passed { 5331 background-color:#CCFFCC; 5332 font-weight:100; 5333 } 5334 .warning { 5335 background-color:#F4F4AF; 5336 font-weight:100; 5337 } 5338 .failed { 5339 background-color:#FFCCCC; 5340 font-weight:100; 5341 } 5342 .new { 5343 background-color:#C6DEFF; 5344 font-weight:100; 5345 } 5346 5347 .compatible { 5348 background-color:#CCFFCC; 5349 font-weight:100; 5350 } 5351 .almost_compatible { 5352 background-color:#FFDAA3; 5353 font-weight:100; 5354 } 5355 .incompatible { 5356 background-color:#FFCCCC; 5357 font-weight:100; 5358 } 5359 .gray { 5360 background-color:#DCDCDC; 5361 font-weight:100; 5362 } 5363 5364 .top_ref { 5365 font-size:0.69em; 5366 } 5367 .footer { 5368 font-size:0.75em; 5369 }"; 5370 5371 if($JoinReport or $ExternCss) 5372 { 5373 $CssStyles .= " 5374 .tabset { 5375 float:left; 5376 } 5377 a.tab { 5378 border:1px solid Black; 5379 float:left; 5380 margin:0px 5px -1px 0px; 5381 padding:3px 5px 3px 5px; 5382 position:relative; 5383 font-size:0.875em; 5384 background-color:#DDD; 5385 text-decoration:none; 5386 color:Black; 5387 } 5388 a.disabled:hover 5389 { 5390 color:Black; 5391 background:#EEE; 5392 } 5393 a.active:hover 5394 { 5395 color:Black; 5396 background:White; 5397 } 5398 a.active { 5399 border-bottom-color:White; 5400 background-color:White; 5401 } 5402 div.tab { 5403 border-top:1px solid Black; 5404 padding:0px; 5405 width:100%; 5406 clear:both; 5407 }"; 3542 sub getCssStyles($) 3543 { 3544 my $Level = $_[0]; 3545 3546 my $CssStyles = readModule("Css", "Report.css"); 3547 3548 if($Level eq "Join" or $In::Opt{"ExternCss"}) { 3549 $CssStyles .= readModule("Css", "Tabs.css"); 5408 3550 } 5409 3551 … … 5411 3553 } 5412 3554 5413 sub getJsScript() 5414 { 5415 my $JScripts = " 5416 function sC(header, id) 5417 { 5418 e = document.getElementById(id); 5419 if(e.style.display == 'none') 5420 { 5421 e.style.display = 'block'; 5422 e.style.visibility = 'visible'; 5423 header.innerHTML = header.innerHTML.replace(/\\\[[^0-9 ]\\\]/gi,\"[−]\"); 5424 } 5425 else 5426 { 5427 e.style.display = 'none'; 5428 e.style.visibility = 'hidden'; 5429 header.innerHTML = header.innerHTML.replace(/\\\[[^0-9 ]\\\]/gi,\"[+]\"); 5430 } 5431 }"; 5432 5433 if($JoinReport or $ExternJs) 5434 { 5435 $JScripts .= " 5436 function initTabs() 5437 { 5438 var url = window.location.href; 5439 if(url.indexOf('_Source_')!=-1 || url.indexOf('#Source')!=-1) 5440 { 5441 var tab1 = document.getElementById('BinaryID'); 5442 var tab2 = document.getElementById('SourceID'); 5443 tab1.className='tab disabled'; 5444 tab2.className='tab active'; 5445 } 5446 var sets = document.getElementsByTagName('div'); 5447 for (var i = 0; i < sets.length; i++) 5448 { 5449 if (sets[i].className.indexOf('tabset') != -1) 5450 { 5451 var tabs = []; 5452 var links = sets[i].getElementsByTagName('a'); 5453 for (var j = 0; j < links.length; j++) 5454 { 5455 if (links[j].className.indexOf('tab') != -1) 5456 { 5457 tabs.push(links[j]); 5458 links[j].tabs = tabs; 5459 var tab = document.getElementById(links[j].href.substr(links[j].href.indexOf('#') + 1)); 5460 //reset all tabs on start 5461 if (tab) 5462 { 5463 if (links[j].className.indexOf('active')!=-1) { 5464 tab.style.display = 'block'; 5465 } 5466 else { 5467 tab.style.display = 'none'; 5468 } 5469 } 5470 links[j].onclick = function() 5471 { 5472 var tab = document.getElementById(this.href.substr(this.href.indexOf('#') + 1)); 5473 if (tab) 5474 { 5475 //reset all tabs before change 5476 for (var k = 0; k < this.tabs.length; k++) 5477 { 5478 document.getElementById(this.tabs[k].href.substr(this.tabs[k].href.indexOf('#') + 1)).style.display = 'none'; 5479 this.tabs[k].className = this.tabs[k].className.replace('active', 'disabled'); 5480 } 5481 this.className = 'tab active'; 5482 tab.style.display = 'block'; 5483 // window.location.hash = this.id.replace('ID', ''); 5484 return false; 5485 } 5486 } 5487 } 5488 } 5489 } 5490 } 5491 if(url.indexOf('#')!=-1) { 5492 location.href=location.href; 5493 } 5494 } 5495 if (window.addEventListener) window.addEventListener('load', initTabs, false); 5496 else if (window.attachEvent) window.attachEvent('onload', initTabs);"; 3555 sub getJsScript($) 3556 { 3557 my $Level = $_[0]; 3558 3559 my $JScripts = readModule("Js", "Sections.js"); 3560 3561 if($Level eq "Join" or $In::Opt{"ExternJs"}) { 3562 $JScripts .= readModule("Js", "Tabs.js"); 5497 3563 } 5498 3564 … … 5504 3570 my $Level = $_[0]; 5505 3571 5506 my $CssStyles = getCssStyles(); 5507 my $JScripts = getJsScript(); 5508 5509 if(defined $ExternCss) 5510 { 5511 $CssStyles=~s/\n /\n/g; 5512 writeFile($ExternCss, $CssStyles); 5513 } 5514 5515 if(defined $ExternJs) 5516 { 5517 $JScripts=~s/\n /\n/g; 5518 writeFile($ExternJs, $JScripts); 3572 my $CssStyles = getCssStyles($Level); 3573 my $JScripts = getJsScript($Level); 3574 3575 if(defined $In::Opt{"ExternCss"}) { 3576 writeFile($In::Opt{"ExternCss"}, $CssStyles); 3577 } 3578 3579 if(defined $In::Opt{"ExternJs"}) { 3580 writeFile($In::Opt{"ExternJs"}, $JScripts); 5519 3581 } 5520 3582 5521 3583 if($Level eq "Join") 5522 3584 { 5523 my $Title = "$TargetTitle: ".$Descriptor{1}{"Version"}." to ".$Descriptor{2}{"Version"}." compatibility report"; 5524 my $Keywords = "$TargetTitle, compatibility"; 5525 my $Description = "Compatibility report for the $TargetTitle library between ".$Descriptor{1}{"Version"}." and ".$Descriptor{2}{"Version"}." versions"; 5526 my ($BSummary, $BMetaData) = get_Summary("Binary"); 5527 my ($SSummary, $SMetaData) = get_Summary("Source"); 3585 my $Title = $In::Opt{"TargetTitle"}.": ".$In::Desc{1}{"Version"}." to ".$In::Desc{2}{"Version"}." compatibility report"; 3586 my $Keywords = $In::Opt{"TargetTitle"}.", compatibility"; 3587 my $Description = "Compatibility report for the ".$In::Opt{"TargetTitle"}." library between ".$In::Desc{1}{"Version"}." and ".$In::Desc{2}{"Version"}." versions"; 3588 3589 my ($BSummary, $BMetaData) = getSummary("Binary"); 3590 my ($SSummary, $SMetaData) = getSummary("Source"); 3591 5528 3592 my $Report = "<!-\- $BMetaData -\->\n<!-\- $SMetaData -\->\n".composeHTML_Head($Level, $Title, $Keywords, $Description, $CssStyles, $JScripts)."<body><a name='Source'></a><a name='Binary'></a><a name='Top'></a>"; 5529 $Report .= get_Report_Header("Join")." 5530 <br/><div class='tabset'> 5531 <a id='BinaryID' href='#BinaryTab' class='tab active'>Binary<br/>Compatibility</a> 5532 <a id='SourceID' href='#SourceTab' style='margin-left:3px' class='tab disabled'>Source<br/>Compatibility</a> 5533 </div>"; 5534 $Report .= "<div id='BinaryTab' class='tab'>\n$BSummary\n".get_Report_Added("Binary").get_Report_Removed("Binary").get_Report_Problems("High", "Binary").get_Report_Problems("Medium", "Binary").get_Report_Problems("Low", "Binary").get_Report_Problems("Safe", "Binary").get_SourceInfo()."<br/><br/><br/></div>"; 5535 $Report .= "<div id='SourceTab' class='tab'>\n$SSummary\n".get_Report_Added("Source").get_Report_Removed("Source").get_Report_Problems("High", "Source").get_Report_Problems("Medium", "Source").get_Report_Problems("Low", "Source").get_Report_Problems("Safe", "Source").get_SourceInfo()."<br/><br/><br/></div>"; 3593 3594 $Report .= getReportHeader("Join"); 3595 $Report .= "<br/><div class='tabset'>\n"; 3596 $Report .= "<a id='BinaryID' href='#BinaryTab' class='tab active'>Binary<br/>Compatibility</a>\n"; 3597 $Report .= "<a id='SourceID' href='#SourceTab' style='margin-left:3px' class='tab disabled'>Source<br/>Compatibility</a>\n"; 3598 $Report .= "</div>\n"; 3599 3600 $Report .= "<div id='BinaryTab' class='tab'>\n$BSummary\n".getReportAdded("Binary").getReportRemoved("Binary").getReportProblems("High", "Binary").getReportProblems("Medium", "Binary").getReportProblems("Low", "Binary").getReportProblems("Safe", "Binary").getSourceInfo()."<br/><br/><br/></div>"; 3601 3602 $Report .= "<div id='SourceTab' class='tab'>\n$SSummary\n".getReportAdded("Source").getReportRemoved("Source").getReportProblems("High", "Source").getReportProblems("Medium", "Source").getReportProblems("Low", "Source").getReportProblems("Safe", "Source").getSourceInfo()."<br/><br/><br/></div>"; 3603 5536 3604 $Report .= getReportFooter(); 5537 3605 $Report .= "\n</body></html>"; … … 5540 3608 else 5541 3609 { 5542 my ($Summary, $MetaData) = get_Summary($Level); 5543 my $Title = "$TargetTitle: ".$Descriptor{1}{"Version"}." to ".$Descriptor{2}{"Version"}." ".lc($Level)." compatibility report"; 5544 my $Keywords = "$TargetTitle, ".lc($Level).", compatibility"; 5545 my $Description = "$Level compatibility report for the $TargetTitle library between ".$Descriptor{1}{"Version"}." and ".$Descriptor{2}{"Version"}." versions"; 3610 my ($Summary, $MetaData) = getSummary($Level); 3611 3612 my $Title = $In::Opt{"TargetTitle"}.": ".$In::Desc{1}{"Version"}." to ".$In::Desc{2}{"Version"}." ".lc($Level)." compatibility report"; 3613 my $Keywords = $In::Opt{"TargetTitle"}.", ".lc($Level).", compatibility"; 3614 my $Description = "$Level compatibility report for the ".$In::Opt{"TargetTitle"}." library between ".$In::Desc{1}{"Version"}." and ".$In::Desc{2}{"Version"}." versions"; 5546 3615 5547 3616 my $Report = "<!-\- $MetaData -\->\n".composeHTML_Head($Level, $Title, $Keywords, $Description, $CssStyles, $JScripts)."<body><a name='Top'></a>"; 5548 $Report .= get _Report_Header($Level)."\n".$Summary."\n";5549 $Report .= get _Report_Added($Level).get_Report_Removed($Level);5550 $Report .= get _Report_Problems("High", $Level).get_Report_Problems("Medium", $Level).get_Report_Problems("Low", $Level).get_Report_Problems("Safe", $Level);5551 $Report .= get _SourceInfo()."<br/><br/><br/>\n";3617 $Report .= getReportHeader($Level)."\n".$Summary."\n"; 3618 $Report .= getReportAdded($Level).getReportRemoved($Level); 3619 $Report .= getReportProblems("High", $Level).getReportProblems("Medium", $Level).getReportProblems("Low", $Level).getReportProblems("Safe", $Level); 3620 $Report .= getSourceInfo()."<br/><br/><br/>\n"; 5552 3621 $Report .= getReportFooter(); 5553 3622 $Report .= "\n</body></html>"; … … 5567 3636 } 5568 3637 5569 sub get _Report_Problems($$)3638 sub getReportProblems($$) 5570 3639 { 5571 3640 my ($Priority, $Level) = @_; 5572 my $Report = get _Report_TypeProblems($Priority, $Level);5573 if(my $MProblems = get _Report_MethodProblems($Priority, $Level)) {3641 my $Report = getReportTypeProblems($Priority, $Level); 3642 if(my $MProblems = getReportMethodProblems($Priority, $Level)) { 5574 3643 $Report .= $MProblems; 5575 3644 } 5576 3645 if($Report) 5577 3646 { 5578 if($ JoinReport)3647 if($In::Opt{"JoinReport"}) 5579 3648 { 5580 3649 if($Priority eq "Safe") { … … 5611 3680 my $RPath = getReportPath($Level); 5612 3681 5613 if(defined $ ExternCss) {5614 $Head .= "<link rel=\"stylesheet\" type=\"text/css\" href=\"".getRelPath($ ExternCss, $RPath)."\" />\n";5615 } 5616 5617 if(defined $ ExternJs) {5618 $Head .= "<script type=\"text/javascript\" src=\"".getRelPath($ ExternJs, $RPath)."\"></script>\n";3682 if(defined $In::Opt{"ExternCss"}) { 3683 $Head .= "<link rel=\"stylesheet\" type=\"text/css\" href=\"".getRelPath($In::Opt{"ExternCss"}, $RPath)."\" />\n"; 3684 } 3685 3686 if(defined $In::Opt{"ExternJs"}) { 3687 $Head .= "<script type=\"text/javascript\" src=\"".getRelPath($In::Opt{"ExternJs"}, $RPath)."\"></script>\n"; 5619 3688 } 5620 3689 5621 3690 $Head .= "<title>$Title</title>\n"; 5622 3691 5623 if(not defined $ ExternCss) {3692 if(not defined $In::Opt{"ExternCss"}) { 5624 3693 $Head .= "<style type=\"text/css\">\n$Styles\n</style>\n"; 5625 3694 } 5626 3695 5627 if(not defined $ ExternJs) {3696 if(not defined $In::Opt{"ExternJs"}) { 5628 3697 $Head .= "<script type=\"text/javascript\" language=\"JavaScript\">\n<!--\n$Scripts\n-->\n</script>\n"; 5629 3698 } 5630 3699 5631 3700 $Head .= "</head>\n"; 5632 5633 $Head=~s/\n /\n/g;5634 3701 5635 3702 return $Head; … … 5652 3719 } 5653 3720 5654 sub readArchives($)5655 {5656 my $LibVersion = $_[0];5657 my @ArchivePaths = getArchives($LibVersion);5658 if($#ArchivePaths==-1) {5659 exitStatus("Error", "Java ARchives are not found in ".$Descriptor{$LibVersion}{"Version"});5660 }5661 printMsg("INFO", "reading classes ".$Descriptor{$LibVersion}{"Version"}." ...");5662 $TYPE_ID = 0;5663 5664 foreach my $ArchivePath (sort {length($a)<=>length($b)} @ArchivePaths) {5665 readArchive($LibVersion, $ArchivePath);5666 }5667 foreach my $TName (keys(%{$TName_Tid{$LibVersion}}))5668 {5669 my $Tid = $TName_Tid{$LibVersion}{$TName};5670 if(not $TypeInfo{$LibVersion}{$Tid}{"Type"})5671 {5672 if($TName=~/\A(void|boolean|char|byte|short|int|float|long|double)\Z/) {5673 $TypeInfo{$LibVersion}{$Tid}{"Type"} = "primitive";5674 }5675 else {5676 $TypeInfo{$LibVersion}{$Tid}{"Type"} = "class";5677 }5678 }5679 }5680 5681 foreach my $Method (keys(%{$MethodInfo{$LibVersion}}))5682 {5683 $MethodInfo{$LibVersion}{$Method}{"Signature"} = get_Signature($Method, $LibVersion, "Full");5684 $tr_name{$Method} = get_TypeName($MethodInfo{$LibVersion}{$Method}{"Class"}, $LibVersion).".".get_Signature($Method, $LibVersion, "Short");5685 }5686 }5687 5688 sub testSystem()5689 {5690 printMsg("INFO", "\nverifying detectable Java library changes");5691 5692 my $LibName = "libsample_java";5693 if(-d $LibName) {5694 rmtree($LibName);5695 }5696 5697 my $PackageName = "TestPackage";5698 my $Path_v1 = "$LibName/$PackageName.v1/$PackageName";5699 mkpath($Path_v1);5700 5701 my $Path_v2 = "$LibName/$PackageName.v2/$PackageName";5702 mkpath($Path_v2);5703 5704 my $TestsPath = "$LibName/Tests";5705 mkpath($TestsPath);5706 5707 # FirstCheckedException5708 my $FirstCheckedException = "package $PackageName;5709 public class FirstCheckedException extends Exception {5710 }";5711 writeFile($Path_v1."/FirstCheckedException.java", $FirstCheckedException);5712 writeFile($Path_v2."/FirstCheckedException.java", $FirstCheckedException);5713 5714 # SecondCheckedException5715 my $SecondCheckedException = "package $PackageName;5716 public class SecondCheckedException extends Exception {5717 }";5718 writeFile($Path_v1."/SecondCheckedException.java", $SecondCheckedException);5719 writeFile($Path_v2."/SecondCheckedException.java", $SecondCheckedException);5720 5721 # FirstUncheckedException5722 my $FirstUncheckedException = "package $PackageName;5723 public class FirstUncheckedException extends RuntimeException {5724 }";5725 writeFile($Path_v1."/FirstUncheckedException.java", $FirstUncheckedException);5726 writeFile($Path_v2."/FirstUncheckedException.java", $FirstUncheckedException);5727 5728 # SecondUncheckedException5729 my $SecondUncheckedException = "package $PackageName;5730 public class SecondUncheckedException extends RuntimeException {5731 }";5732 writeFile($Path_v1."/SecondUncheckedException.java", $SecondUncheckedException);5733 writeFile($Path_v2."/SecondUncheckedException.java", $SecondUncheckedException);5734 5735 # BaseAbstractClass5736 my $BaseAbstractClass = "package $PackageName;5737 public abstract class BaseAbstractClass {5738 public Integer field;5739 public Integer someMethod(Integer param) { return param; }5740 public abstract Integer abstractMethod(Integer param);5741 }";5742 writeFile($Path_v1."/BaseAbstractClass.java", $BaseAbstractClass);5743 writeFile($Path_v2."/BaseAbstractClass.java", $BaseAbstractClass);5744 5745 # Removed_Annotation5746 writeFile($Path_v1."/RemovedAnnotation.java",5747 "package $PackageName;5748 public \@interface RemovedAnnotation {5749 }");5750 5751 # Beta Annotation5752 writeFile($Path_v1."/Beta.java",5753 "package $PackageName;5754 public \@interface Beta {5755 }");5756 5757 writeFile($Path_v2."/Beta.java",5758 "package $PackageName;5759 public \@interface Beta {5760 }");5761 5762 # BaseClass5763 my $BaseClass = "package $PackageName;5764 public class BaseClass {5765 public Integer field;5766 public Integer method(Integer param) { return param; }5767 }";5768 writeFile($Path_v1."/BaseClass.java", $BaseClass);5769 writeFile($Path_v2."/BaseClass.java", $BaseClass);5770 5771 # BaseClass25772 my $BaseClass2 = "package $PackageName;5773 public class BaseClass2 {5774 public Integer field2;5775 public Integer method2(Integer param) { return param; }5776 }";5777 writeFile($Path_v1."/BaseClass2.java", $BaseClass2);5778 writeFile($Path_v2."/BaseClass2.java", $BaseClass2);5779 5780 # BaseInterface5781 my $BaseInterface = "package $PackageName;5782 public interface BaseInterface {5783 public Integer field = 100;5784 public Integer method(Integer param);5785 }";5786 writeFile($Path_v1."/BaseInterface.java", $BaseInterface);5787 writeFile($Path_v2."/BaseInterface.java", $BaseInterface);5788 5789 # BaseInterface25790 my $BaseInterface2 = "package $PackageName;5791 public interface BaseInterface2 {5792 public Integer field2 = 100;5793 public Integer method2(Integer param);5794 }";5795 writeFile($Path_v1."/BaseInterface2.java", $BaseInterface2);5796 writeFile($Path_v2."/BaseInterface2.java", $BaseInterface2);5797 5798 # BaseConstantInterface5799 my $BaseConstantInterface = "package $PackageName;5800 public interface BaseConstantInterface {5801 public Integer CONSTANT = 10;5802 public Integer CONSTANT2 = 100;5803 }";5804 writeFile($Path_v1."/BaseConstantInterface.java", $BaseConstantInterface);5805 writeFile($Path_v2."/BaseConstantInterface.java", $BaseConstantInterface);5806 5807 # Removed_Method (Beta method)5808 writeFile($Path_v1."/RemovedBetaMethod.java",5809 "package $PackageName;5810 public class RemovedBetaMethod5811 {5812 \@Beta5813 public Integer someMethod() {5814 return 0;5815 }5816 }");5817 writeFile($Path_v2."/RemovedBetaMethod.java",5818 "package $PackageName;5819 public class RemovedBetaMethod {5820 }");5821 5822 # Removed_Method (from Beta class)5823 writeFile($Path_v1."/RemovedMethodFromBetaClass.java",5824 "package $PackageName;5825 \@Beta5826 public class RemovedMethodFromBetaClass5827 {5828 public Integer someMethod() {5829 return 0;5830 }5831 }");5832 writeFile($Path_v2."/RemovedMethodFromBetaClass.java",5833 "package $PackageName;5834 \@Beta5835 public class RemovedMethodFromBetaClass {5836 }");5837 5838 # Removed_Class (Beta)5839 writeFile($Path_v1."/RemovedBetaClass.java",5840 "package $PackageName;5841 \@Beta5842 public class RemovedBetaClass5843 {5844 public Integer someMethod() {5845 return 0;5846 }5847 }");5848 5849 # Abstract_Method_Added_Checked_Exception5850 writeFile($Path_v1."/AbstractMethodAddedCheckedException.java",5851 "package $PackageName;5852 public abstract class AbstractMethodAddedCheckedException {5853 public abstract Integer someMethod() throws FirstCheckedException;5854 }");5855 writeFile($Path_v2."/AbstractMethodAddedCheckedException.java",5856 "package $PackageName;5857 public abstract class AbstractMethodAddedCheckedException {5858 public abstract Integer someMethod() throws FirstCheckedException, SecondCheckedException;5859 }");5860 5861 # Abstract_Method_Removed_Checked_Exception5862 writeFile($Path_v1."/AbstractMethodRemovedCheckedException.java",5863 "package $PackageName;5864 public abstract class AbstractMethodRemovedCheckedException {5865 public abstract Integer someMethod() throws FirstCheckedException, SecondCheckedException;5866 }");5867 writeFile($Path_v2."/AbstractMethodRemovedCheckedException.java",5868 "package $PackageName;5869 public abstract class AbstractMethodRemovedCheckedException {5870 public abstract Integer someMethod() throws FirstCheckedException;5871 }");5872 5873 # NonAbstract_Method_Added_Checked_Exception5874 writeFile($Path_v1."/NonAbstractMethodAddedCheckedException.java",5875 "package $PackageName;5876 public class NonAbstractMethodAddedCheckedException {5877 public Integer someMethod() throws FirstCheckedException {5878 return 10;5879 }5880 }");5881 writeFile($Path_v2."/NonAbstractMethodAddedCheckedException.java",5882 "package $PackageName;5883 public class NonAbstractMethodAddedCheckedException {5884 public Integer someMethod() throws FirstCheckedException, SecondCheckedException {5885 return 10;5886 }5887 }");5888 5889 # NonAbstract_Method_Removed_Checked_Exception5890 writeFile($Path_v1."/NonAbstractMethodRemovedCheckedException.java",5891 "package $PackageName;5892 public class NonAbstractMethodRemovedCheckedException {5893 public Integer someMethod() throws FirstCheckedException, SecondCheckedException {5894 return 10;5895 }5896 }");5897 writeFile($Path_v2."/NonAbstractMethodRemovedCheckedException.java",5898 "package $PackageName;5899 public class NonAbstractMethodRemovedCheckedException {5900 public Integer someMethod() throws FirstCheckedException {5901 return 10;5902 }5903 }");5904 5905 # Added_Unchecked_Exception5906 writeFile($Path_v1."/AddedUncheckedException.java",5907 "package $PackageName;5908 public class AddedUncheckedException {5909 public Integer someMethod() throws FirstUncheckedException {5910 return 10;5911 }5912 }");5913 writeFile($Path_v2."/AddedUncheckedException.java",5914 "package $PackageName;5915 public class AddedUncheckedException {5916 public Integer someMethod() throws FirstUncheckedException, SecondUncheckedException, NullPointerException {5917 return 10;5918 }5919 }");5920 5921 # Removed_Unchecked_Exception5922 writeFile($Path_v1."/RemovedUncheckedException.java",5923 "package $PackageName;5924 public class RemovedUncheckedException {5925 public Integer someMethod() throws FirstUncheckedException, SecondUncheckedException, NullPointerException {5926 return 10;5927 }5928 }");5929 writeFile($Path_v2."/RemovedUncheckedException.java",5930 "package $PackageName;5931 public class RemovedUncheckedException {5932 public Integer someMethod() throws FirstUncheckedException {5933 return 10;5934 }5935 }");5936 5937 # Changed_Method_Return_From_Void5938 writeFile($Path_v1."/ChangedMethodReturnFromVoid.java",5939 "package $PackageName;5940 public class ChangedMethodReturnFromVoid {5941 public void changedMethod(Integer param1, String[] param2) { }5942 }");5943 writeFile($Path_v2."/ChangedMethodReturnFromVoid.java",5944 "package $PackageName;5945 public class ChangedMethodReturnFromVoid {5946 public Integer changedMethod(Integer param1, String[] param2){5947 return param1;5948 }5949 }");5950 5951 # Added_Method5952 writeFile($Path_v1."/AddedMethod.java",5953 "package $PackageName;5954 public class AddedMethod {5955 public Integer field = 100;5956 }");5957 writeFile($Path_v2."/AddedMethod.java",5958 "package $PackageName;5959 public class AddedMethod {5960 public Integer field = 100;5961 public Integer addedMethod(Integer param1, String[] param2) { return param1; }5962 public static String[] addedStaticMethod(String[] param) { return param; }5963 }");5964 5965 # Added_Method (Constructor)5966 writeFile($Path_v1."/AddedConstructor.java",5967 "package $PackageName;5968 public class AddedConstructor {5969 public Integer field = 100;5970 }");5971 writeFile($Path_v2."/AddedConstructor.java",5972 "package $PackageName;5973 public class AddedConstructor {5974 public Integer field = 100;5975 public AddedConstructor() { }5976 public AddedConstructor(Integer x, String y) { }5977 }");5978 5979 # Class_Added_Field5980 writeFile($Path_v1."/ClassAddedField.java",5981 "package $PackageName;5982 public class ClassAddedField {5983 public Integer otherField;5984 }");5985 writeFile($Path_v2."/ClassAddedField.java",5986 "package $PackageName;5987 public class ClassAddedField {5988 public Integer addedField;5989 public Integer otherField;5990 }");5991 5992 # Interface_Added_Field5993 writeFile($Path_v1."/InterfaceAddedField.java",5994 "package $PackageName;5995 public interface InterfaceAddedField {5996 public Integer method();5997 }");5998 writeFile($Path_v2."/InterfaceAddedField.java",5999 "package $PackageName;6000 public interface InterfaceAddedField {6001 public Integer addedField = 100;6002 public Integer method();6003 }");6004 6005 # Removed_NonConstant_Field (Class)6006 writeFile($Path_v1."/ClassRemovedField.java",6007 "package $PackageName;6008 public class ClassRemovedField {6009 public Integer removedField;6010 public Integer otherField;6011 }");6012 writeFile($Path_v2."/ClassRemovedField.java",6013 "package $PackageName;6014 public class ClassRemovedField {6015 public Integer otherField;6016 }");6017 6018 writeFile($TestsPath."/Test_ClassRemovedField.java",6019 "import $PackageName.*;6020 public class Test_ClassRemovedField {6021 public static void main(String[] args) {6022 ClassRemovedField X = new ClassRemovedField();6023 Integer Copy = X.removedField;6024 }6025 }");6026 6027 writeFile($TestsPath."/Test_RemovedAnnotation.java",6028 "import $PackageName.*;6029 public class Test_RemovedAnnotation {6030 public static void main(String[] args) {6031 testMethod();6032 }6033 6034 \@RemovedAnnotation6035 static void testMethod() {6036 }6037 }");6038 6039 # Removed_Constant_Field (Interface)6040 writeFile($Path_v1."/InterfaceRemovedConstantField.java",6041 "package $PackageName;6042 public interface InterfaceRemovedConstantField {6043 public String someMethod();6044 public int removedField_Int = 1000;6045 public String removedField_Str = \"Value\";6046 }");6047 writeFile($Path_v2."/InterfaceRemovedConstantField.java",6048 "package $PackageName;6049 public interface InterfaceRemovedConstantField {6050 public String someMethod();6051 }");6052 6053 # Removed_NonConstant_Field (Interface)6054 writeFile($Path_v1."/InterfaceRemovedField.java",6055 "package $PackageName;6056 public interface InterfaceRemovedField {6057 public String someMethod();6058 public BaseClass removedField = new BaseClass();6059 }");6060 writeFile($Path_v2."/InterfaceRemovedField.java",6061 "package $PackageName;6062 public interface InterfaceRemovedField {6063 public String someMethod();6064 }");6065 6066 # Renamed_Field6067 writeFile($Path_v1."/RenamedField.java",6068 "package $PackageName;6069 public class RenamedField {6070 public String oldName;6071 }");6072 writeFile($Path_v2."/RenamedField.java",6073 "package $PackageName;6074 public class RenamedField {6075 public String newName;6076 }");6077 6078 # Renamed_Constant_Field6079 writeFile($Path_v1."/RenamedConstantField.java",6080 "package $PackageName;6081 public class RenamedConstantField {6082 public final String oldName = \"Value\";6083 }");6084 writeFile($Path_v2."/RenamedConstantField.java",6085 "package $PackageName;6086 public class RenamedConstantField {6087 public final String newName = \"Value\";6088 }");6089 6090 # Changed_Field_Type6091 writeFile($Path_v1."/ChangedFieldType.java",6092 "package $PackageName;6093 public class ChangedFieldType {6094 public String fieldName;6095 }");6096 writeFile($Path_v2."/ChangedFieldType.java",6097 "package $PackageName;6098 public class ChangedFieldType {6099 public Integer fieldName;6100 }");6101 6102 # Changed_Field_Access6103 writeFile($Path_v1."/ChangedFieldAccess.java",6104 "package $PackageName;6105 public class ChangedFieldAccess {6106 public String fieldName;6107 }");6108 writeFile($Path_v2."/ChangedFieldAccess.java",6109 "package $PackageName;6110 public class ChangedFieldAccess {6111 private String fieldName;6112 }");6113 6114 # Changed_Final_Field_Value6115 writeFile($Path_v1."/ChangedFinalFieldValue.java",6116 "package $PackageName;6117 public class ChangedFinalFieldValue {6118 public final int field = 1;6119 public final String field2 = \" \";6120 }");6121 writeFile($Path_v2."/ChangedFinalFieldValue.java",6122 "package $PackageName;6123 public class ChangedFinalFieldValue {6124 public final int field = 2;6125 public final String field2 = \"newValue\";6126 }");6127 6128 # NonConstant_Field_Became_Static6129 writeFile($Path_v1."/NonConstantFieldBecameStatic.java",6130 "package $PackageName;6131 public class NonConstantFieldBecameStatic {6132 public String fieldName;6133 }");6134 writeFile($Path_v2."/NonConstantFieldBecameStatic.java",6135 "package $PackageName;6136 public class NonConstantFieldBecameStatic {6137 public static String fieldName;6138 }");6139 6140 # NonConstant_Field_Became_NonStatic6141 writeFile($Path_v1."/NonConstantFieldBecameNonStatic.java",6142 "package $PackageName;6143 public class NonConstantFieldBecameNonStatic {6144 public static String fieldName;6145 }");6146 writeFile($Path_v2."/NonConstantFieldBecameNonStatic.java",6147 "package $PackageName;6148 public class NonConstantFieldBecameNonStatic {6149 public String fieldName;6150 }");6151 6152 # Constant_Field_Became_NonStatic6153 writeFile($Path_v1."/ConstantFieldBecameNonStatic.java",6154 "package $PackageName;6155 public class ConstantFieldBecameNonStatic {6156 public final static String fieldName = \"Value\";6157 }");6158 writeFile($Path_v2."/ConstantFieldBecameNonStatic.java",6159 "package $PackageName;6160 public class ConstantFieldBecameNonStatic {6161 public final String fieldName = \"Value\";6162 }");6163 6164 # Field_Became_Final6165 writeFile($Path_v1."/FieldBecameFinal.java",6166 "package $PackageName;6167 public class FieldBecameFinal {6168 public String fieldName;6169 }");6170 writeFile($Path_v2."/FieldBecameFinal.java",6171 "package $PackageName;6172 public class FieldBecameFinal {6173 public final String fieldName = \"Value\";6174 }");6175 6176 # Field_Became_NonFinal6177 writeFile($Path_v1."/FieldBecameNonFinal.java",6178 "package $PackageName;6179 public class FieldBecameNonFinal {6180 public final String fieldName = \"Value\";6181 }");6182 writeFile($Path_v2."/FieldBecameNonFinal.java",6183 "package $PackageName;6184 public class FieldBecameNonFinal {6185 public String fieldName;6186 }");6187 6188 # Removed_Method6189 writeFile($Path_v1."/RemovedMethod.java",6190 "package $PackageName;6191 public class RemovedMethod {6192 public Integer field = 100;6193 public Integer removedMethod(Integer param1, String param2) { return param1; }6194 public static Integer removedStaticMethod(Integer param) { return param; }6195 }");6196 writeFile($Path_v2."/RemovedMethod.java",6197 "package $PackageName;6198 public class RemovedMethod {6199 public Integer field = 100;6200 }");6201 6202 # Removed_Method (move up to java.lang.Object)6203 writeFile($Path_v1."/MoveUpToJavaLangObject.java",6204 "package $PackageName;6205 public class MoveUpToJavaLangObject extends java.lang.Object {6206 public int hashCode() { return 0; }6207 }");6208 writeFile($Path_v2."/MoveUpToJavaLangObject.java",6209 "package $PackageName;6210 public class MoveUpToJavaLangObject extends java.lang.Object {6211 }");6212 6213 writeFile($TestsPath."/Test_MoveUpToJavaLangObject.java",6214 "import $PackageName.*;6215 public class Test_MoveUpToJavaLangObject {6216 public static void main(String[] args) {6217 MoveUpToJavaLangObject X = new MoveUpToJavaLangObject();6218 int R = X.hashCode();6219 }6220 }");6221 6222 # Removed_Method (Deprecated)6223 writeFile($Path_v1."/RemovedDeprecatedMethod.java",6224 "package $PackageName;6225 public class RemovedDeprecatedMethod {6226 public Integer field = 100;6227 public Integer otherMethod(Integer param) { return param; }6228 \@Deprecated6229 public Integer removedMethod(Integer param1, String param2) { return param1; }6230 }");6231 writeFile($Path_v2."/RemovedDeprecatedMethod.java",6232 "package $PackageName;6233 public class RemovedDeprecatedMethod {6234 public Integer field = 100;6235 public Integer otherMethod(Integer param) { return param; }6236 }");6237 6238 # Interface_Removed_Abstract_Method6239 writeFile($Path_v1."/InterfaceRemovedAbstractMethod.java",6240 "package $PackageName;6241 public interface InterfaceRemovedAbstractMethod extends BaseInterface, BaseInterface2 {6242 public void removedMethod(Integer param1, java.io.ObjectOutput param2);6243 public void someMethod(Integer param);6244 }");6245 writeFile($Path_v2."/InterfaceRemovedAbstractMethod.java",6246 "package $PackageName;6247 public interface InterfaceRemovedAbstractMethod extends BaseInterface, BaseInterface2 {6248 public void someMethod(Integer param);6249 }");6250 6251 # Interface_Added_Abstract_Method6252 writeFile($Path_v1."/InterfaceAddedAbstractMethod.java",6253 "package $PackageName;6254 public interface InterfaceAddedAbstractMethod extends BaseInterface, BaseInterface2 {6255 public void someMethod(Integer param);6256 }");6257 writeFile($Path_v2."/InterfaceAddedAbstractMethod.java",6258 "package $PackageName;6259 public interface InterfaceAddedAbstractMethod extends BaseInterface, BaseInterface2 {6260 public void someMethod(Integer param);6261 public Integer addedMethod(Integer param);6262 }");6263 6264 # Interface_Added_Default_Method6265 writeFile($Path_v1."/InterfaceAddedDefaultMethod.java",6266 "package $PackageName;6267 public interface InterfaceAddedDefaultMethod {6268 public void someMethod(Integer param);6269 }");6270 writeFile($Path_v2."/InterfaceAddedDefaultMethod.java",6271 "package $PackageName;6272 public interface InterfaceAddedDefaultMethod {6273 public void someMethod(Integer param);6274 default Integer addedMethod(Integer param) { return 0; }6275 }");6276 6277 # Method_Became_NonDefault6278 writeFile($Path_v1."/MethodBecameNonDefault.java",6279 "package $PackageName;6280 public interface MethodBecameNonDefault {6281 default Integer someMethod(Integer param) { return 0; }6282 }");6283 writeFile($Path_v2."/MethodBecameNonDefault.java",6284 "package $PackageName;6285 public interface MethodBecameNonDefault {6286 public Integer someMethod(Integer param);6287 }");6288 6289 writeFile($TestsPath."/Test_MethodBecameNonDefault.java",6290 "import $PackageName.*;6291 class Class_MethodBecameNonDefault implements MethodBecameNonDefault {6292 };6293 6294 public class Test_MethodBecameNonDefault6295 {6296 public static void main(String[] args)6297 {6298 Class_MethodBecameNonDefault Obj = new Class_MethodBecameNonDefault();6299 Integer Res = Obj.someMethod(0);6300 }6301 }");6302 6303 # Variable_Arity_To_Array6304 writeFile($Path_v1."/VariableArityToArray.java",6305 "package $PackageName;6306 public class VariableArityToArray {6307 public void someMethod(Integer x, String... y) { };6308 }");6309 writeFile($Path_v2."/VariableArityToArray.java",6310 "package $PackageName;6311 public class VariableArityToArray {6312 public void someMethod(Integer x, String[] y) { };6313 }");6314 6315 # Class_Became_Interface6316 writeFile($Path_v1."/ClassBecameInterface.java",6317 "package $PackageName;6318 public class ClassBecameInterface extends BaseClass {6319 public Integer someMethod(Integer param) {6320 return param;6321 }6322 }");6323 writeFile($Path_v2."/ClassBecameInterface.java",6324 "package $PackageName;6325 public interface ClassBecameInterface extends BaseInterface, BaseInterface2 {6326 public Integer someMethod(Integer param);6327 }");6328 6329 # Added_Super_Class6330 writeFile($Path_v1."/AddedSuperClass.java",6331 "package $PackageName;6332 public class AddedSuperClass {6333 public Integer someMethod(Integer param) {6334 return param;6335 }6336 }");6337 writeFile($Path_v2."/AddedSuperClass.java",6338 "package $PackageName;6339 public class AddedSuperClass extends BaseClass {6340 public Integer someMethod(Integer param) {6341 return param;6342 }6343 }");6344 6345 # Abstract_Class_Added_Super_Abstract_Class6346 writeFile($Path_v1."/AbstractClassAddedSuperAbstractClass.java",6347 "package $PackageName;6348 public abstract class AbstractClassAddedSuperAbstractClass {6349 public Integer someMethod(Integer param) {6350 return param;6351 }6352 }");6353 writeFile($Path_v2."/AbstractClassAddedSuperAbstractClass.java",6354 "package $PackageName;6355 public abstract class AbstractClassAddedSuperAbstractClass extends BaseAbstractClass {6356 public Integer someMethod(Integer param) {6357 return param;6358 }6359 }");6360 6361 # Removed_Super_Class6362 writeFile($Path_v1."/RemovedSuperClass.java",6363 "package $PackageName;6364 public class RemovedSuperClass extends BaseClass {6365 public Integer someMethod(Integer param) {6366 return param;6367 }6368 }");6369 writeFile($Path_v2."/RemovedSuperClass.java",6370 "package $PackageName;6371 public class RemovedSuperClass {6372 public Integer someMethod(Integer param) {6373 return param;6374 }6375 }");6376 6377 # Changed_Super_Class6378 writeFile($Path_v1."/ChangedSuperClass.java",6379 "package $PackageName;6380 public class ChangedSuperClass extends BaseClass {6381 public Integer someMethod(Integer param) {6382 return param;6383 }6384 }");6385 writeFile($Path_v2."/ChangedSuperClass.java",6386 "package $PackageName;6387 public class ChangedSuperClass extends BaseClass2 {6388 public Integer someMethod(Integer param) {6389 return param;6390 }6391 }");6392 6393 # Abstract_Class_Added_Super_Interface6394 writeFile($Path_v1."/AbstractClassAddedSuperInterface.java",6395 "package $PackageName;6396 public abstract class AbstractClassAddedSuperInterface implements BaseInterface {6397 public Integer method(Integer param) {6398 return param;6399 }6400 }");6401 writeFile($Path_v2."/AbstractClassAddedSuperInterface.java",6402 "package $PackageName;6403 public abstract class AbstractClassAddedSuperInterface implements BaseInterface, BaseInterface2 {6404 public Integer method(Integer param) {6405 return param;6406 }6407 }");6408 6409 # Abstract_Class_Added_Super_Interface_With_Implemented_Methods6410 writeFile($Path_v1."/AbstractClassAddedSuperInterfaceWithImplementedMethods.java",6411 "package $PackageName;6412 public abstract class AbstractClassAddedSuperInterfaceWithImplementedMethods implements BaseInterface {6413 public Integer method(Integer param) {6414 return param;6415 }6416 public Integer method2(Integer param) {6417 return param;6418 }6419 }");6420 writeFile($Path_v2."/AbstractClassAddedSuperInterfaceWithImplementedMethods.java",6421 "package $PackageName;6422 public abstract class AbstractClassAddedSuperInterfaceWithImplementedMethods implements BaseInterface, BaseInterface2 {6423 public Integer method(Integer param) {6424 return param;6425 }6426 public Integer method2(Integer param) {6427 return param;6428 }6429 }");6430 6431 # Class_Removed_Super_Interface6432 writeFile($Path_v1."/ClassRemovedSuperInterface.java",6433 "package $PackageName;6434 public class ClassRemovedSuperInterface implements BaseInterface, BaseInterface2 {6435 public Integer method(Integer param) {6436 return param;6437 }6438 public Integer method2(Integer param) {6439 return param;6440 }6441 }");6442 writeFile($Path_v2."/ClassRemovedSuperInterface.java",6443 "package $PackageName;6444 public class ClassRemovedSuperInterface implements BaseInterface {6445 public Integer method(Integer param) {6446 return param;6447 }6448 public Integer method2(Integer param) {6449 return param;6450 }6451 }");6452 6453 writeFile($TestsPath."/Test_ClassRemovedSuperInterface.java",6454 "import $PackageName.*;6455 public class Test_ClassRemovedSuperInterface6456 {6457 public static void main(String[] args)6458 {6459 ClassRemovedSuperInterface Obj = new ClassRemovedSuperInterface();6460 Integer Res = Obj.method2(0);6461 }6462 }");6463 6464 # Interface_Added_Super_Interface6465 writeFile($Path_v1."/InterfaceAddedSuperInterface.java",6466 "package $PackageName;6467 public interface InterfaceAddedSuperInterface extends BaseInterface {6468 public Integer someMethod(Integer param);6469 }");6470 writeFile($Path_v2."/InterfaceAddedSuperInterface.java",6471 "package $PackageName;6472 public interface InterfaceAddedSuperInterface extends BaseInterface, BaseInterface2 {6473 public Integer someMethod(Integer param);6474 }");6475 6476 # Interface_Added_Super_Constant_Interface6477 writeFile($Path_v1."/InterfaceAddedSuperConstantInterface.java",6478 "package $PackageName;6479 public interface InterfaceAddedSuperConstantInterface extends BaseInterface {6480 public Integer someMethod(Integer param);6481 }");6482 writeFile($Path_v2."/InterfaceAddedSuperConstantInterface.java",6483 "package $PackageName;6484 public interface InterfaceAddedSuperConstantInterface extends BaseInterface, BaseConstantInterface {6485 public Integer someMethod(Integer param);6486 }");6487 6488 # Interface_Removed_Super_Interface6489 writeFile($Path_v1."/InterfaceRemovedSuperInterface.java",6490 "package $PackageName;6491 public interface InterfaceRemovedSuperInterface extends BaseInterface, BaseInterface2 {6492 public Integer someMethod(Integer param);6493 }");6494 writeFile($Path_v2."/InterfaceRemovedSuperInterface.java",6495 "package $PackageName;6496 public interface InterfaceRemovedSuperInterface extends BaseInterface {6497 public Integer someMethod(Integer param);6498 }");6499 6500 # Interface_Removed_Super_Constant_Interface6501 writeFile($Path_v1."/InterfaceRemovedSuperConstantInterface.java",6502 "package $PackageName;6503 public interface InterfaceRemovedSuperConstantInterface extends BaseInterface, BaseConstantInterface {6504 public Integer someMethod(Integer param);6505 }");6506 writeFile($Path_v2."/InterfaceRemovedSuperConstantInterface.java",6507 "package $PackageName;6508 public interface InterfaceRemovedSuperConstantInterface extends BaseInterface {6509 public Integer someMethod(Integer param);6510 }");6511 6512 # Interface_Became_Class6513 writeFile($Path_v1."/InterfaceBecameClass.java",6514 "package $PackageName;6515 public interface InterfaceBecameClass extends BaseInterface, BaseInterface2 {6516 public Integer someMethod(Integer param);6517 }");6518 writeFile($Path_v2."/InterfaceBecameClass.java",6519 "package $PackageName;6520 public class InterfaceBecameClass extends BaseClass {6521 public Integer someMethod(Integer param) {6522 return param;6523 }6524 }");6525 6526 # Removed_Class6527 writeFile($Path_v1."/RemovedClass.java",6528 "package $PackageName;6529 public class RemovedClass extends BaseClass {6530 public Integer someMethod(Integer param){6531 return param;6532 }6533 }");6534 6535 # Removed_Class (w/o methods)6536 writeFile($Path_v1."/RemovedFieldClass.java",6537 "package $PackageName;6538 public class RemovedFieldClass {6539 public Integer field;6540 }");6541 6542 writeFile($TestsPath."/Test_RemovedFieldClass.java",6543 "import $PackageName.*;6544 public class Test_RemovedFieldClass extends RemovedFieldClass6545 {6546 public static void main(String[] args)6547 {6548 RemovedFieldClass X = new RemovedFieldClass();6549 Integer Copy = X.field;6550 }6551 }");6552 6553 # Removed_Class (with static fields, private constructor)6554 writeFile($Path_v1."/RemovedClassWithStaticField.java",6555 "package $PackageName;6556 public class RemovedClassWithStaticField6557 {6558 private RemovedClassWithStaticField(){}6559 public static Integer cnt = 0;6560 }");6561 6562 writeFile($TestsPath."/Test_RemovedClassWithStaticField.java",6563 "import $PackageName.*;6564 public class Test_RemovedClassWithStaticField6565 {6566 public static void main(String[] args)6567 {6568 Integer Copy = RemovedClassWithStaticField.cnt;6569 }6570 }");6571 6572 # Removed_Field (static field, private constructor)6573 writeFile($Path_v1."/RemovedStaticFieldFromClassWithPrivateCtor.java",6574 "package $PackageName;6575 public class RemovedStaticFieldFromClassWithPrivateCtor6576 {6577 private RemovedStaticFieldFromClassWithPrivateCtor(){}6578 public static Integer cnt = 0;6579 }");6580 6581 writeFile($Path_v2."/RemovedStaticFieldFromClassWithPrivateCtor.java",6582 "package $PackageName;6583 public class RemovedStaticFieldFromClassWithPrivateCtor6584 {6585 private RemovedStaticFieldFromClassWithPrivateCtor(){}6586 }");6587 6588 writeFile($TestsPath."/Test_RemovedStaticFieldFromClassWithPrivateCtor.java",6589 "import $PackageName.*;6590 public class Test_RemovedStaticFieldFromClassWithPrivateCtor6591 {6592 public static void main(String[] args)6593 {6594 Integer Copy = RemovedStaticFieldFromClassWithPrivateCtor.cnt;6595 }6596 }");6597 6598 # Removed_Constant_Field6599 writeFile($Path_v1."/ClassRemovedStaticConstantField.java",6600 "package $PackageName;6601 public class ClassRemovedStaticConstantField6602 {6603 public static int removedField_Int = 1000;6604 public static String removedField_Str = \"Value\";6605 }");6606 writeFile($Path_v2."/ClassRemovedStaticConstantField.java",6607 "package $PackageName;6608 public class ClassRemovedStaticConstantField {6609 }");6610 6611 writeFile($TestsPath."/Test_ClassRemovedStaticConstantField.java",6612 "import $PackageName.*;6613 public class Test_ClassRemovedStaticConstantField6614 {6615 public static void main(String[] args)6616 {6617 Integer Copy = ClassRemovedStaticConstantField.removedField_Int;6618 }6619 }");6620 6621 # Removed_Class (Deprecated)6622 writeFile($Path_v1."/RemovedDeprecatedClass.java",6623 "package $PackageName;6624 \@Deprecated6625 public class RemovedDeprecatedClass {6626 public Integer someMethod(Integer param){6627 return param;6628 }6629 }");6630 6631 # Removed_Interface6632 writeFile($Path_v1."/RemovedInterface.java",6633 "package $PackageName;6634 public interface RemovedInterface extends BaseInterface, BaseInterface2 {6635 public Integer someMethod(Integer param);6636 }");6637 6638 # NonAbstract_Class_Added_Abstract_Method6639 writeFile($Path_v1."/NonAbstractClassAddedAbstractMethod.java",6640 "package $PackageName;6641 public class NonAbstractClassAddedAbstractMethod {6642 public Integer someMethod(Integer param1, String[] param2) {6643 return param1;6644 };6645 }");6646 writeFile($Path_v2."/NonAbstractClassAddedAbstractMethod.java",6647 "package $PackageName;6648 public abstract class NonAbstractClassAddedAbstractMethod {6649 public Integer someMethod(Integer param1, String[] param2) {6650 return param1;6651 };6652 public abstract Integer addedMethod(Integer param);6653 }");6654 6655 # Abstract_Class_Added_Abstract_Method6656 writeFile($Path_v1."/AbstractClassAddedAbstractMethod.java",6657 "package $PackageName;6658 public abstract class AbstractClassAddedAbstractMethod {6659 public Integer someMethod(Integer param1, String[] param2) {6660 return param1;6661 };6662 }");6663 writeFile($Path_v2."/AbstractClassAddedAbstractMethod.java",6664 "package $PackageName;6665 public abstract class AbstractClassAddedAbstractMethod {6666 public Integer someMethod(Integer param1, String[] param2) {6667 return param1;6668 };6669 public abstract Integer addedMethod(Integer param);6670 }");6671 6672 # Class_Became_Abstract6673 writeFile($Path_v1."/ClassBecameAbstract.java",6674 "package $PackageName;6675 public class ClassBecameAbstract {6676 public Integer someMethod(Integer param1, String[] param2) {6677 return param1;6678 };6679 }");6680 writeFile($Path_v2."/ClassBecameAbstract.java",6681 "package $PackageName;6682 public abstract class ClassBecameAbstract {6683 public Integer someMethod(Integer param1, String[] param2) {6684 return param1;6685 };6686 public abstract Integer addedMethod(Integer param);6687 }");6688 6689 # Class_Became_Final6690 writeFile($Path_v1."/ClassBecameFinal.java",6691 "package $PackageName;6692 public class ClassBecameFinal {6693 public Integer someMethod(Integer param1, String[] param2) {6694 return param1;6695 };6696 }");6697 writeFile($Path_v2."/ClassBecameFinal.java",6698 "package $PackageName;6699 public final class ClassBecameFinal {6700 public Integer someMethod(Integer param1, String[] param2) {6701 return param1;6702 };6703 }");6704 6705 # Class_Removed_Abstract_Method6706 writeFile($Path_v1."/ClassRemovedAbstractMethod.java",6707 "package $PackageName;6708 public abstract class ClassRemovedAbstractMethod {6709 public Integer someMethod(Integer param1, String[] param2) {6710 return param1;6711 };6712 public abstract Integer removedMethod(Integer param);6713 }");6714 writeFile($Path_v2."/ClassRemovedAbstractMethod.java",6715 "package $PackageName;6716 public abstract class ClassRemovedAbstractMethod {6717 public Integer someMethod(Integer param1, String[] param2) {6718 return param1;6719 };6720 }");6721 6722 # Class_Method_Became_Abstract6723 writeFile($Path_v1."/ClassMethodBecameAbstract.java",6724 "package $PackageName;6725 public abstract class ClassMethodBecameAbstract {6726 public Integer someMethod(Integer param1, String[] param2) {6727 return param1;6728 };6729 public Integer someMethod(Integer param){6730 return param;6731 };6732 }");6733 writeFile($Path_v2."/ClassMethodBecameAbstract.java",6734 "package $PackageName;6735 public abstract class ClassMethodBecameAbstract {6736 public Integer someMethod(Integer param1, String[] param2) {6737 return param1;6738 };6739 public abstract Integer someMethod(Integer param);6740 }");6741 6742 # Class_Method_Became_NonAbstract6743 writeFile($Path_v1."/ClassMethodBecameNonAbstract.java",6744 "package $PackageName;6745 public abstract class ClassMethodBecameNonAbstract {6746 public Integer someMethod(Integer param1, String[] param2) {6747 return param1;6748 };6749 public abstract Integer someMethod(Integer param);6750 }");6751 writeFile($Path_v2."/ClassMethodBecameNonAbstract.java",6752 "package $PackageName;6753 public abstract class ClassMethodBecameNonAbstract {6754 public Integer someMethod(Integer param1, String[] param2) {6755 return param1;6756 };6757 public Integer someMethod(Integer param){6758 return param;6759 };6760 }");6761 6762 # Method_Became_Static6763 writeFile($Path_v1."/MethodBecameStatic.java",6764 "package $PackageName;6765 public class MethodBecameStatic {6766 public Integer someMethod(Integer param) {6767 return param;6768 };6769 }");6770 writeFile($Path_v2."/MethodBecameStatic.java",6771 "package $PackageName;6772 public class MethodBecameStatic {6773 public static Integer someMethod(Integer param) {6774 return param;6775 };6776 }");6777 6778 # Method_Became_NonStatic6779 writeFile($Path_v1."/MethodBecameNonStatic.java",6780 "package $PackageName;6781 public class MethodBecameNonStatic {6782 public static Integer someMethod(Integer param) {6783 return param;6784 };6785 }");6786 writeFile($Path_v2."/MethodBecameNonStatic.java",6787 "package $PackageName;6788 public class MethodBecameNonStatic {6789 public Integer someMethod(Integer param) {6790 return param;6791 };6792 }");6793 6794 # Static_Method_Became_Final6795 writeFile($Path_v1."/StaticMethodBecameFinal.java",6796 "package $PackageName;6797 public class StaticMethodBecameFinal {6798 public static Integer someMethod(Integer param) {6799 return param;6800 };6801 }");6802 writeFile($Path_v2."/StaticMethodBecameFinal.java",6803 "package $PackageName;6804 public class StaticMethodBecameFinal {6805 public static final Integer someMethod(Integer param) {6806 return param;6807 };6808 }");6809 6810 # NonStatic_Method_Became_Final6811 writeFile($Path_v1."/NonStaticMethodBecameFinal.java",6812 "package $PackageName;6813 public class NonStaticMethodBecameFinal {6814 public Integer someMethod(Integer param) {6815 return param;6816 };6817 }");6818 writeFile($Path_v2."/NonStaticMethodBecameFinal.java",6819 "package $PackageName;6820 public class NonStaticMethodBecameFinal {6821 public final Integer someMethod(Integer param) {6822 return param;6823 };6824 }");6825 6826 # Method_Became_Abstract6827 writeFile($Path_v1."/MethodBecameAbstract.java",6828 "package $PackageName;6829 public abstract class MethodBecameAbstract {6830 public Integer someMethod(Integer param) {6831 return param;6832 };6833 }");6834 writeFile($Path_v2."/MethodBecameAbstract.java",6835 "package $PackageName;6836 public abstract class MethodBecameAbstract {6837 public abstract Integer someMethod(Integer param);6838 }");6839 6840 # Method_Became_NonAbstract6841 writeFile($Path_v1."/MethodBecameNonAbstract.java",6842 "package $PackageName;6843 public abstract class MethodBecameNonAbstract {6844 public abstract Integer someMethod(Integer param);6845 }");6846 writeFile($Path_v2."/MethodBecameNonAbstract.java",6847 "package $PackageName;6848 public abstract class MethodBecameNonAbstract {6849 public Integer someMethod(Integer param) {6850 return param;6851 };6852 }");6853 6854 # Changed_Method_Access6855 writeFile($Path_v1."/ChangedMethodAccess.java",6856 "package $PackageName;6857 public class ChangedMethodAccess {6858 public Integer someMethod(Integer param) {6859 return param;6860 };6861 }");6862 writeFile($Path_v2."/ChangedMethodAccess.java",6863 "package $PackageName;6864 public class ChangedMethodAccess {6865 protected Integer someMethod(Integer param) {6866 return param;6867 };6868 }");6869 6870 # Method_Became_Synchronized6871 writeFile($Path_v1."/MethodBecameSynchronized.java",6872 "package $PackageName;6873 public class MethodBecameSynchronized {6874 public Integer someMethod(Integer param) {6875 return param;6876 };6877 }");6878 writeFile($Path_v2."/MethodBecameSynchronized.java",6879 "package $PackageName;6880 public class MethodBecameSynchronized {6881 public synchronized Integer someMethod(Integer param) {6882 return param;6883 };6884 }");6885 6886 # Method_Became_NonSynchronized6887 writeFile($Path_v1."/MethodBecameNonSynchronized.java",6888 "package $PackageName;6889 public class MethodBecameNonSynchronized {6890 public synchronized Integer someMethod(Integer param) {6891 return param;6892 };6893 }");6894 writeFile($Path_v2."/MethodBecameNonSynchronized.java",6895 "package $PackageName;6896 public class MethodBecameNonSynchronized {6897 public Integer someMethod(Integer param) {6898 return param;6899 };6900 }");6901 6902 # Class_Overridden_Method6903 writeFile($Path_v1."/OverriddenMethod.java",6904 "package $PackageName;6905 public class OverriddenMethod extends BaseClass {6906 public Integer someMethod(Integer param) { return param; }6907 }");6908 writeFile($Path_v2."/OverriddenMethod.java",6909 "package $PackageName;6910 public class OverriddenMethod extends BaseClass {6911 public Integer someMethod(Integer param) { return param; }6912 public Integer method(Integer param) { return 2*param; }6913 }");6914 6915 # Class_Method_Moved_Up_Hierarchy6916 writeFile($Path_v1."/ClassMethodMovedUpHierarchy.java",6917 "package $PackageName;6918 public class ClassMethodMovedUpHierarchy extends BaseClass {6919 public Integer someMethod(Integer param) { return param; }6920 public Integer method(Integer param) { return 2*param; }6921 }");6922 writeFile($Path_v2."/ClassMethodMovedUpHierarchy.java",6923 "package $PackageName;6924 public class ClassMethodMovedUpHierarchy extends BaseClass {6925 public Integer someMethod(Integer param) { return param; }6926 }");6927 6928 # Class_Method_Moved_Up_Hierarchy (Interface Method) - should not be reported6929 writeFile($Path_v1."/InterfaceMethodMovedUpHierarchy.java",6930 "package $PackageName;6931 public interface InterfaceMethodMovedUpHierarchy extends BaseInterface {6932 public Integer method(Integer param);6933 public Integer method2(Integer param);6934 }");6935 writeFile($Path_v2."/InterfaceMethodMovedUpHierarchy.java",6936 "package $PackageName;6937 public interface InterfaceMethodMovedUpHierarchy extends BaseInterface {6938 public Integer method2(Integer param);6939 }");6940 6941 # Class_Method_Moved_Up_Hierarchy (Abstract Method) - should not be reported6942 writeFile($Path_v1."/AbstractMethodMovedUpHierarchy.java",6943 "package $PackageName;6944 public abstract class AbstractMethodMovedUpHierarchy implements BaseInterface {6945 public abstract Integer method(Integer param);6946 public abstract Integer method2(Integer param);6947 }");6948 writeFile($Path_v2."/AbstractMethodMovedUpHierarchy.java",6949 "package $PackageName;6950 public abstract class AbstractMethodMovedUpHierarchy implements BaseInterface {6951 public abstract Integer method2(Integer param);6952 }");6953 6954 # Use6955 writeFile($Path_v1."/Use.java",6956 "package $PackageName;6957 public class Use6958 {6959 public FieldBecameFinal field;6960 public void someMethod(FieldBecameFinal[] param) { };6961 public void someMethod(Use param) { };6962 public Integer someMethod(AbstractClassAddedSuperAbstractClass param) {6963 return 0;6964 }6965 public Integer someMethod(AbstractClassAddedAbstractMethod param) {6966 return 0;6967 }6968 public Integer someMethod(InterfaceAddedAbstractMethod param) {6969 return 0;6970 }6971 public Integer someMethod(InterfaceAddedSuperInterface param) {6972 return 0;6973 }6974 public Integer someMethod(AbstractClassAddedSuperInterface param) {6975 return 0;6976 }6977 public Integer someMethod(AbstractClassAddedSuperInterfaceWithImplementedMethods param) {6978 return 0;6979 }6980 }");6981 writeFile($Path_v2."/Use.java",6982 "package $PackageName;6983 public class Use6984 {6985 public FieldBecameFinal field;6986 public void someMethod(FieldBecameFinal[] param) { };6987 public void someMethod(Use param) { };6988 public Integer someMethod(AbstractClassAddedSuperAbstractClass param) {6989 return param.abstractMethod(100)+param.field;6990 }6991 public Integer someMethod(AbstractClassAddedAbstractMethod param) {6992 return param.addedMethod(100);6993 }6994 public Integer someMethod(InterfaceAddedAbstractMethod param) {6995 return param.addedMethod(100);6996 }6997 public Integer someMethod(InterfaceAddedSuperInterface param) {6998 return param.method2(100);6999 }7000 public Integer someMethod(AbstractClassAddedSuperInterface param) {7001 return param.method2(100);7002 }7003 public Integer someMethod(AbstractClassAddedSuperInterfaceWithImplementedMethods param) {7004 return param.method2(100);7005 }7006 }");7007 7008 # Added_Package7009 writeFile($Path_v2."/AddedPackage/AddedPackageClass.java",7010 "package $PackageName.AddedPackage;7011 public class AddedPackageClass {7012 public Integer field;7013 public void someMethod(Integer param) { };7014 }");7015 7016 # Removed_Package7017 writeFile($Path_v1."/RemovedPackage/RemovedPackageClass.java",7018 "package $PackageName.RemovedPackage;7019 public class RemovedPackageClass {7020 public Integer field;7021 public void someMethod(Integer param) { };7022 }");7023 my $BuildRoot1 = get_dirname($Path_v1);7024 my $BuildRoot2 = get_dirname($Path_v2);7025 if(compileJavaLib($LibName, $BuildRoot1, $BuildRoot2))7026 {7027 runTests($TestsPath, $PackageName, $BuildRoot1, $BuildRoot2);7028 runChecker($LibName, $BuildRoot1, $BuildRoot2);7029 }7030 }7031 7032 sub readArchive($$)7033 { # 1, 2 - library, 0 - client7034 my ($LibVersion, $Path) = @_;7035 return if(not $Path or not -e $Path);7036 7037 if($LibVersion)7038 {7039 my $ArchiveName = get_filename($Path);7040 $LibArchives{$LibVersion}{$ArchiveName} = 1;7041 }7042 7043 $Path = get_abs_path($Path);7044 my $JarCmd = get_CmdPath("jar");7045 if(not $JarCmd) {7046 exitStatus("Not_Found", "can't find \"jar\" command");7047 }7048 my $ExtractPath = joinPath($TMP_DIR, $ExtractCounter);7049 if(-d $ExtractPath) {7050 rmtree($ExtractPath);7051 }7052 mkpath($ExtractPath);7053 chdir($ExtractPath);7054 system($JarCmd." -xf \"$Path\"");7055 if($?) {7056 exitStatus("Error", "can't extract \'$Path\'");7057 }7058 chdir($ORIG_DIR);7059 my @Classes = ();7060 foreach my $ClassPath (cmd_find($ExtractPath,"","*\.class",""))7061 {7062 if($OSgroup ne "windows") {7063 $ClassPath=~s/\.class\Z//g;7064 }7065 7066 my $ClassName = get_filename($ClassPath);7067 if($ClassName=~/\$\d/) {7068 next;7069 }7070 $ClassPath = cut_path_prefix($ClassPath, $ExtractPath); # javap decompiler accepts relative paths only7071 7072 my $ClassDir = get_dirname($ClassPath);7073 if($ClassDir=~/\./)7074 { # jaxb-osgi.jar/1.0/org/apache7075 next;7076 }7077 7078 my $Package = get_PFormat($ClassDir);7079 if($LibVersion)7080 {7081 if(skipPackage($Package, $LibVersion))7082 { # internal packages7083 next;7084 }7085 }7086 7087 $ClassName=~s/\$/./g; # real name for GlyphView$GlyphPainter is GlyphView.GlyphPainter7088 push(@Classes, $ClassPath);7089 }7090 7091 if($#Classes!=-1)7092 {7093 foreach my $PartRef (divideArray(\@Classes))7094 {7095 if($LibVersion) {7096 readClasses($PartRef, $LibVersion, get_filename($Path));7097 }7098 else {7099 readClasses_Usage($PartRef);7100 }7101 }7102 }7103 7104 $ExtractCounter+=1;7105 7106 if($LibVersion)7107 {7108 foreach my $SubArchive (cmd_find($ExtractPath,"","*\.jar",""))7109 { # recursive step7110 readArchive($LibVersion, $SubArchive);7111 }7112 }7113 7114 rmtree($ExtractPath);7115 }7116 7117 sub native_path($)7118 {7119 my $Path = $_[0];7120 if($OSgroup eq "windows") {7121 $Path=~s/[\/\\]+/\\/g;7122 }7123 return $Path;7124 }7125 7126 sub divideArray($)7127 {7128 my $ArrRef = $_[0];7129 return () if(not $ArrRef);7130 my @Array = @{$ArrRef};7131 return () if($#{$ArrRef}==-1);7132 7133 my @Res = ();7134 my $Sub = [];7135 my $Len = 0;7136 7137 foreach my $Pos (0 .. $#{$ArrRef})7138 {7139 my $Arg = $ArrRef->[$Pos];7140 my $Arg_L = length($Arg) + 1; # space7141 if($Len < $ARG_MAX - 250)7142 {7143 push(@{$Sub}, $Arg);7144 $Len += $Arg_L;7145 }7146 else7147 {7148 push(@Res, $Sub);7149 7150 $Sub = [$Arg];7151 $Len = $Arg_L;7152 }7153 }7154 7155 if($#{$Sub}!=-1) {7156 push(@Res, $Sub);7157 }7158 7159 return @Res;7160 }7161 7162 sub registerType($$)7163 {7164 my ($TName, $LibVersion) = @_;7165 7166 if(not $TName) {7167 return 0;7168 }7169 7170 $TName=~s/#/./g;7171 if($TName_Tid{$LibVersion}{$TName}) {7172 return $TName_Tid{$LibVersion}{$TName};7173 }7174 7175 if(not $TName_Tid{$LibVersion}{$TName})7176 {7177 my $ID = undef;7178 if($REPRODUCIBLE) {7179 $ID = getMd5($TName);7180 }7181 else {7182 $ID = ++$TYPE_ID;7183 }7184 $TName_Tid{$LibVersion}{$TName} = "$ID";7185 }7186 7187 my $Tid = $TName_Tid{$LibVersion}{$TName};7188 $TypeInfo{$LibVersion}{$Tid}{"Name"} = $TName;7189 if($TName=~/(.+)\[\]\Z/)7190 {7191 if(my $BaseTypeId = registerType($1, $LibVersion))7192 {7193 $TypeInfo{$LibVersion}{$Tid}{"BaseType"} = $BaseTypeId;7194 $TypeInfo{$LibVersion}{$Tid}{"Type"} = "array";7195 }7196 }7197 7198 return $Tid;7199 }7200 7201 sub readClasses_Usage($)7202 {7203 my $Paths = $_[0];7204 return () if(not $Paths);7205 7206 my $JavapCmd = get_CmdPath("javap");7207 if(not $JavapCmd) {7208 exitStatus("Not_Found", "can't find \"javap\" command");7209 }7210 7211 my $Input = join(" ", @{$Paths});7212 if($OSgroup ne "windows")7213 { # on unix ensure that the system does not try and interpret the $, by escaping it7214 $Input=~s/\$/\\\$/g;7215 }7216 7217 chdir($TMP_DIR."/".$ExtractCounter);7218 open(CONTENT, "$JavapCmd -c -private $Input 2>\"$TMP_DIR/warn\" |");7219 while(<CONTENT>)7220 {7221 if(/\/\/\s*(Method|InterfaceMethod)\s+(.+)\Z/)7222 {7223 my $M = $2;7224 $UsedMethods_Client{$M} = 1;7225 7226 if($M=~/\A(.*)+\.\w+\:\(/)7227 {7228 my $C = $1;7229 $C=~s/\//./g;7230 $UsedClasses_Client{$C} = 1;7231 }7232 }7233 elsif(/\/\/\s*Field\s+(.+)\Z/)7234 {7235 my $FieldName = $1;7236 if(/\s+(putfield|getfield|getstatic|putstatic)\s+/) {7237 $UsedFields_Client{$FieldName} = $1;7238 }7239 }7240 elsif(/ ([^\s]+) [^: ]+\(([^()]+)\)/)7241 {7242 my ($Ret, $Params) = ($1, $2);7243 7244 $Ret=~s/\[\]//g; # quals7245 $UsedClasses_Client{$Ret} = 1;7246 7247 foreach my $Param (split(/\s*,\s*/, $Params))7248 {7249 $Param=~s/\[\]//g; # quals7250 $UsedClasses_Client{$Param} = 1;7251 }7252 }7253 elsif(/ class /)7254 {7255 if(/extends ([^\s{]+)/)7256 {7257 foreach my $Class (split(/\s*,\s*/, $1)) {7258 $UsedClasses_Client{$Class} = 1;7259 }7260 }7261 7262 if(/implements ([^\s{]+)/)7263 {7264 foreach my $Interface (split(/\s*,\s*/, $1)) {7265 $UsedClasses_Client{$Interface} = 1;7266 }7267 }7268 }7269 }7270 close(CONTENT);7271 chdir($ORIG_DIR);7272 }7273 7274 sub readClasses($$$)7275 {7276 my ($Paths, $LibVersion, $ArchiveName) = @_;7277 return if(not $Paths or not $LibVersion or not $ArchiveName);7278 7279 my $JavapCmd = get_CmdPath("javap");7280 if(not $JavapCmd) {7281 exitStatus("Not_Found", "can't find \"javap\" command");7282 }7283 7284 my $Input = join(" ", @{$Paths});7285 if($OSgroup ne "windows")7286 { # on unix ensure that the system does not try and interpret the $, by escaping it7287 $Input=~s/\$/\\\$/g;7288 }7289 7290 my $Output = $TMP_DIR."/class-dump.txt";7291 if(-e $Output) {7292 unlink($Output);7293 }7294 7295 my $Cmd = "$JavapCmd -s -private";7296 if(not $Quick) {7297 $Cmd .= " -c -verbose";7298 }7299 7300 chdir($TMP_DIR."/".$ExtractCounter);7301 system($Cmd." ".$Input." >\"$Output\" 2>\"$TMP_DIR/warn\"");7302 chdir($ORIG_DIR);7303 7304 if(not -e $Output) {7305 exitStatus("Error", "internal error in parser, try to reduce ARG_MAX");7306 }7307 if($Debug) {7308 appendFile($DEBUG_PATH{$LibVersion}."/class-dump.txt", readFile($Output));7309 }7310 7311 # ! private info should be processed7312 open(CONTENT, "$TMP_DIR/class-dump.txt");7313 my @Content = <CONTENT>;7314 close(CONTENT);7315 7316 my (%TypeAttr, $CurrentMethod, $CurrentPackage, $CurrentClass) = ();7317 my ($InParamTable, $InExceptionTable, $InCode) = (0, 0, 0);7318 7319 my $InAnnotations = undef;7320 my $InAnnotations_Class = undef;7321 my $InAnnotations_Method = undef;7322 my %AnnotationName = ();7323 my %AnnotationNum = (); # support for Java 77324 7325 my ($ParamPos, $FieldPos, $LineNum) = (0, 0, 0);7326 while($LineNum<=$#Content)7327 {7328 my $LINE = $Content[$LineNum++];7329 my $LINE_N = $Content[$LineNum];7330 7331 if($LINE=~/\A\s*(?:const|AnnotationDefault|Compiled|Source|Constant)/) {7332 next;7333 }7334 7335 if($LINE=~/\sof\s|\sline \d+:|\[\s*class|= \[|\$[\d\$\(:\.;]| class\$|[\.\/]\$|\._\d|\$eq/)7336 { # artificial methods and code7337 next;7338 }7339 7340 if($LINE=~/ (\w+\$|)\w+\$\w+[\(:]/) {7341 next;7342 }7343 7344 # $LINE=~s/ \$(\w)/ $1/g;7345 # $LINE_N=~s/ \$(\w)/ $1/g;7346 7347 if(not $InParamTable)7348 {7349 if($LINE=~/ \$/) {7350 next;7351 }7352 }7353 7354 $LINE=~s/\$([\> ]|\Z)/$1/g;7355 $LINE_N=~s/\$([\> ]|\Z)/$1/g;7356 7357 if($LINE eq "\n" or $LINE eq "}\n")7358 {7359 $CurrentMethod = undef;7360 $InCode = 0;7361 $InAnnotations_Method = 0;7362 $InParamTable = 0;7363 }7364 7365 if($LINE eq "}\n") {7366 $InAnnotations_Class = 1;7367 }7368 7369 if($LINE=~/\A\s*#(\d+)/)7370 { # Constant pool7371 my $CNum = $1;7372 if($LINE=~/\s+([^ ]+?);/)7373 {7374 my $AName = $1;7375 $AName=~s/\AL//;7376 $AName=~s/\$/./g;7377 $AName=~s/\//./g;7378 7379 $AnnotationName{$CNum} = $AName;7380 7381 if(defined $AnnotationNum{$CNum})7382 { # support for Java 77383 if($InAnnotations_Class) {7384 $TypeAttr{"Annotations"}{registerType($AName, $LibVersion)} = 1;7385 }7386 delete($AnnotationNum{$CNum});7387 }7388 }7389 7390 next;7391 }7392 7393 # Java 7: templates7394 if(index($LINE, "<")!=-1)7395 { # <T extends java.lang.Object>7396 # <KEYIN extends java.lang.Object ...7397 if($LINE=~/<[A-Z\d\?]+ /i)7398 {7399 while($LINE=~/<([A-Z\d\?]+ .*?)>( |\Z)/i)7400 {7401 my $Str = $1;7402 my @Prms = ();7403 foreach my $P (separate_Params($Str, 0, 0))7404 {7405 $P=~s/\A([A-Z\d\?]+) .*\Z/$1/ig;7406 push(@Prms, $P);7407 }7408 my $Str_N = join(", ", @Prms);7409 $LINE=~s/\Q$Str\E/$Str_N/g;7410 }7411 }7412 }7413 7414 $LINE=~s/\s*,\s*/,/g;7415 $LINE=~s/\$/#/g;7416 7417 if(index($LINE, "LocalVariableTable")!=-1) {7418 $InParamTable += 1;7419 }7420 elsif($LINE=~/Exception\s+table/) {7421 $InExceptionTable = 1;7422 }7423 elsif($LINE=~/\A\s*Code:/)7424 {7425 $InCode += 1;7426 $InAnnotations = undef;7427 }7428 elsif($LINE=~/\A\s*\d+:\s*(.*)\Z/)7429 { # read Code7430 if($InCode==1)7431 {7432 if($CurrentMethod)7433 {7434 if(index($LINE, "invoke")!=-1)7435 {7436 if($LINE=~/ invoke(\w+) .* \/\/\s*(Method|InterfaceMethod)\s+(.+)\Z/)7437 { # 3: invokevirtual #2; //Method "[Lcom/sleepycat/je/Database#DbState;".clone:()Ljava/lang/Object;7438 my ($InvokeType, $InvokedName) = ($1, $3);7439 7440 if($InvokedName!~/\A(\w+:|java\/(lang|util|io)\/)/7441 and index($InvokedName, '"<init>":')!=0)7442 {7443 $InvokedName=~s/#/\$/g;7444 $MethodUsed{$LibVersion}{$InvokedName}{$CurrentMethod} = $InvokeType;7445 }7446 }7447 }7448 # elsif($LINE=~/ (getstatic|putstatic) .* \/\/\s*Field\s+(.+)\Z/)7449 # {7450 # my $UsedFieldName = $2;7451 # $FieldUsed{$LibVersion}{$UsedFieldName}{$CurrentMethod} = 1;7452 # }7453 }7454 }7455 elsif(defined $InAnnotations)7456 {7457 if($LINE=~/\A\s*\d+\:\s*#(\d+)/)7458 {7459 if(my $AName = $AnnotationName{$1})7460 {7461 if($InAnnotations_Class) {7462 $TypeAttr{"Annotations"}{registerType($AName, $LibVersion)} = 1;7463 }7464 elsif($InAnnotations_Method) {7465 $MethodInfo{$LibVersion}{$CurrentMethod}{"Annotations"}{registerType($AName, $LibVersion)} = 1;7466 }7467 }7468 else7469 { # suport for Java 77470 $AnnotationNum{$1} = 1;7471 }7472 }7473 }7474 }7475 elsif($CurrentMethod and $InParamTable==1 and $LINE=~/\A\s+0\s+\d+\s+\d+\s+(\#?)(\w+)/)7476 { # read parameter names from LocalVariableTable7477 my $Art = $1;7478 my $PName = $2;7479 7480 if(($PName ne "this" or $Art) and $PName=~/[a-z]/i)7481 {7482 if($CurrentMethod)7483 {7484 if(defined $MethodInfo{$LibVersion}{$CurrentMethod}7485 and defined $MethodInfo{$LibVersion}{$CurrentMethod}{"Param"}7486 and defined $MethodInfo{$LibVersion}{$CurrentMethod}{"Param"}{$ParamPos}7487 and defined $MethodInfo{$LibVersion}{$CurrentMethod}{"Param"}{$ParamPos}{"Type"})7488 {7489 $MethodInfo{$LibVersion}{$CurrentMethod}{"Param"}{$ParamPos}{"Name"} = $PName;7490 $ParamPos++;7491 }7492 }7493 }7494 }7495 elsif($CurrentClass and $LINE=~/(\A|\s+)([^\s]+)\s+([^\s]+)\s*\((.*)\)\s*(throws\s*([^\s]+)|)\s*;\Z/)7496 { # attributes of methods and constructors7497 my (%MethodAttr, $ParamsLine, $Exceptions) = ();7498 7499 $InParamTable = 0; # read the first local variable table7500 $InCode = 0; # read the first code7501 $InAnnotations_Method = 1;7502 $InAnnotations_Class = 0;7503 7504 ($MethodAttr{"Return"}, $MethodAttr{"ShortName"}, $ParamsLine, $Exceptions) = ($2, $3, $4, $6);7505 $MethodAttr{"ShortName"}=~s/#/./g;7506 7507 if($Exceptions)7508 {7509 foreach my $E (split(/,/, $Exceptions)) {7510 $MethodAttr{"Exceptions"}{registerType($E, $LibVersion)} = 1;7511 }7512 }7513 if($LINE=~/(\A|\s+)(public|protected|private)\s+/) {7514 $MethodAttr{"Access"} = $2;7515 }7516 else {7517 $MethodAttr{"Access"} = "package-private";7518 }7519 $MethodAttr{"Class"} = registerType($TypeAttr{"Name"}, $LibVersion);7520 if($MethodAttr{"ShortName"}=~/\A(|(.+)\.)\Q$CurrentClass\E\Z/)7521 {7522 if($2)7523 {7524 $MethodAttr{"Package"} = $2;7525 $CurrentPackage = $MethodAttr{"Package"};7526 $MethodAttr{"ShortName"} = $CurrentClass;7527 }7528 $MethodAttr{"Constructor"} = 1;7529 delete($MethodAttr{"Return"});7530 }7531 else7532 {7533 $MethodAttr{"Return"} = registerType($MethodAttr{"Return"}, $LibVersion);7534 }7535 7536 my @Params = separate_Params($ParamsLine, 0, 1);7537 7538 $ParamPos = 0;7539 foreach my $ParamTName (@Params)7540 {7541 %{$MethodAttr{"Param"}{$ParamPos}} = ("Type"=>registerType($ParamTName, $LibVersion), "Name"=>"p".($ParamPos+1));7542 $ParamPos++;7543 }7544 $ParamPos = 0;7545 if(not $MethodAttr{"Constructor"})7546 { # methods7547 if($CurrentPackage) {7548 $MethodAttr{"Package"} = $CurrentPackage;7549 }7550 if($LINE=~/(\A|\s+)abstract\s+/) {7551 $MethodAttr{"Abstract"} = 1;7552 }7553 if($LINE=~/(\A|\s+)final\s+/) {7554 $MethodAttr{"Final"} = 1;7555 }7556 if($LINE=~/(\A|\s+)static\s+/) {7557 $MethodAttr{"Static"} = 1;7558 }7559 if($LINE=~/(\A|\s+)native\s+/) {7560 $MethodAttr{"Native"} = 1;7561 }7562 if($LINE=~/(\A|\s+)synchronized\s+/) {7563 $MethodAttr{"Synchronized"} = 1;7564 }7565 }7566 7567 # read the Signature7568 if($LINE_N=~/(Signature|descriptor):\s*(.+)\Z/i)7569 { # create run-time unique name ( java/io/PrintStream.println (Ljava/lang/String;)V )7570 if($MethodAttr{"Constructor"}) {7571 $CurrentMethod = $CurrentClass.".\"<init>\":".$2;7572 }7573 else {7574 $CurrentMethod = $CurrentClass.".".$MethodAttr{"ShortName"}.":".$2;7575 }7576 if(my $PackageName = get_SFormat($CurrentPackage)) {7577 $CurrentMethod = $PackageName."/".$CurrentMethod;7578 }7579 7580 $LineNum++;7581 }7582 else {7583 exitStatus("Error", "internal error - can't read method signature");7584 }7585 7586 $MethodAttr{"Archive"} = $ArchiveName;7587 if($CurrentMethod)7588 {7589 %{$MethodInfo{$LibVersion}{$CurrentMethod}} = %MethodAttr;7590 if($MethodAttr{"Access"}=~/public|protected/)7591 {7592 $Class_Methods{$LibVersion}{$TypeAttr{"Name"}}{$CurrentMethod} = 1;7593 if($MethodAttr{"Abstract"}) {7594 $Class_AbstractMethods{$LibVersion}{$TypeAttr{"Name"}}{$CurrentMethod} = 1;7595 }7596 }7597 }7598 }7599 elsif($CurrentClass and $LINE=~/(\A|\s+)([^\s]+)\s+(\w+);\Z/)7600 { # fields7601 my ($TName, $FName) = ($2, $3);7602 $TypeAttr{"Fields"}{$FName}{"Type"} = registerType($TName, $LibVersion);7603 if($LINE=~/(\A|\s+)final\s+/) {7604 $TypeAttr{"Fields"}{$FName}{"Final"} = 1;7605 }7606 if($LINE=~/(\A|\s+)static\s+/) {7607 $TypeAttr{"Fields"}{$FName}{"Static"} = 1;7608 }7609 if($LINE=~/(\A|\s+)transient\s+/) {7610 $TypeAttr{"Fields"}{$FName}{"Transient"} = 1;7611 }7612 if($LINE=~/(\A|\s+)volatile\s+/) {7613 $TypeAttr{"Fields"}{$FName}{"Volatile"} = 1;7614 }7615 if($LINE=~/(\A|\s+)(public|protected|private)\s+/) {7616 $TypeAttr{"Fields"}{$FName}{"Access"} = $2;7617 }7618 else {7619 $TypeAttr{"Fields"}{$FName}{"Access"} = "package-private";7620 }7621 if($TypeAttr{"Fields"}{$FName}{"Access"}!~/private/) {7622 $Class_Fields{$LibVersion}{$TypeAttr{"Name"}}{$FName}=$TypeAttr{"Fields"}{$FName}{"Type"};7623 }7624 $TypeAttr{"Fields"}{$FName}{"Pos"} = $FieldPos++;7625 7626 # read the Signature7627 if($Content[$LineNum++]=~/(Signature|descriptor):\s*(.+)\Z/i)7628 {7629 my $FSignature = $2;7630 if(my $PackageName = get_SFormat($CurrentPackage)) {7631 $TypeAttr{"Fields"}{$FName}{"Mangled"} = $PackageName."/".$CurrentClass.".".$FName.":".$FSignature;7632 }7633 }7634 if($Content[$LineNum]=~/flags:/i)7635 { # flags: ACC_PUBLIC, ACC_STATIC, ACC_FINAL, ACC_ANNOTATION7636 $LineNum++;7637 }7638 7639 # read the Value7640 if($Content[$LineNum]=~/Constant\s*value:\s*([^\s]+)\s(.*)\Z/i)7641 {7642 # Java 6: Constant value: ...7643 # Java 7: ConstantValue: ...7644 $LineNum+=1;7645 my ($TName, $Value) = ($1, $2);7646 if($Value)7647 {7648 if($Value=~s/Deprecated:\s*true\Z//g) {7649 # deprecated values: ?7650 }7651 $TypeAttr{"Fields"}{$FName}{"Value"} = $Value;7652 }7653 elsif($TName eq "String") {7654 $TypeAttr{"Fields"}{$FName}{"Value"} = "\@EMPTY_STRING\@";7655 }7656 }7657 }7658 elsif($LINE=~/(\A|\s+)(class|interface)\s+([^\s\{]+)(\s+|\{|\Z)/)7659 { # properties of classes and interfaces7660 if($TypeAttr{"Name"})7661 { # register previous7662 %{$TypeInfo{$LibVersion}{registerType($TypeAttr{"Name"}, $LibVersion)}} = %TypeAttr;7663 }7664 7665 %TypeAttr = ("Type"=>$2, "Name"=>$3); # reset previous class7666 %AnnotationName = (); # reset annotations of the class7667 %AnnotationNum = (); # support for Java 77668 $InAnnotations_Class = 1;7669 7670 $FieldPos = 0; # reset field position7671 $CurrentMethod = ""; # reset current method7672 $TypeAttr{"Archive"} = $ArchiveName;7673 if($TypeAttr{"Name"}=~/\A(.+)\.([^.]+)\Z/)7674 {7675 $CurrentClass = $2;7676 $TypeAttr{"Package"} = $1;7677 $CurrentPackage = $TypeAttr{"Package"};7678 }7679 else7680 {7681 $CurrentClass = $TypeAttr{"Name"};7682 $CurrentPackage = "";7683 }7684 if($CurrentClass=~s/#/./g)7685 { # javax.swing.text.GlyphView.GlyphPainter <=> GlyphView$GlyphPainter7686 $TypeAttr{"Name"}=~s/#/./g;7687 }7688 if($LINE=~/(\A|\s+)(public|protected|private)\s+/) {7689 $TypeAttr{"Access"} = $2;7690 }7691 else {7692 $TypeAttr{"Access"} = "package-private";7693 }7694 if($LINE=~/\s+extends\s+([^\s\{]+)/)7695 {7696 my $Extended = $1;7697 7698 if($TypeAttr{"Type"} eq "class")7699 {7700 if($Extended ne $CurrentPackage.".".$CurrentClass) {7701 $TypeAttr{"SuperClass"} = registerType($Extended, $LibVersion);7702 }7703 }7704 elsif($TypeAttr{"Type"} eq "interface")7705 {7706 my @Elems = separate_Params($Extended, 0, 0);7707 foreach my $SuperInterface (@Elems)7708 {7709 if($SuperInterface ne $CurrentPackage.".".$CurrentClass) {7710 $TypeAttr{"SuperInterface"}{registerType($SuperInterface, $LibVersion)} = 1;7711 }7712 7713 if($SuperInterface eq "java.lang.annotation.Annotation") {7714 $TypeAttr{"Annotation"} = 1;7715 }7716 }7717 }7718 }7719 if($LINE=~/\s+implements\s+([^\s\{]+)/)7720 {7721 my $Implemented = $1;7722 my @Elems = separate_Params($Implemented, 0, 0);7723 7724 foreach my $SuperInterface (@Elems) {7725 $TypeAttr{"SuperInterface"}{registerType($SuperInterface, $LibVersion)} = 1;7726 }7727 }7728 if($LINE=~/(\A|\s+)abstract\s+/) {7729 $TypeAttr{"Abstract"} = 1;7730 }7731 if($LINE=~/(\A|\s+)final\s+/) {7732 $TypeAttr{"Final"} = 1;7733 }7734 if($LINE=~/(\A|\s+)static\s+/) {7735 $TypeAttr{"Static"} = 1;7736 }7737 }7738 elsif(index($LINE, "Deprecated: true")!=-17739 or index($LINE, "Deprecated: length")!=-1)7740 { # deprecated method or class7741 if($CurrentMethod) {7742 $MethodInfo{$LibVersion}{$CurrentMethod}{"Deprecated"} = 1;7743 }7744 elsif($CurrentClass) {7745 $TypeAttr{"Deprecated"} = 1;7746 }7747 }7748 elsif(index($LINE, "RuntimeInvisibleAnnotations")!=-17749 or index($LINE, "RuntimeVisibleAnnotations")!=-1)7750 {7751 $InAnnotations = 1;7752 $InCode = 0;7753 }7754 elsif(defined $InAnnotations and index($LINE, "InnerClasses")!=-1) {7755 $InAnnotations = undef;7756 }7757 else7758 {7759 # unparsed7760 }7761 }7762 if($TypeAttr{"Name"})7763 { # register last7764 %{$TypeInfo{$LibVersion}{registerType($TypeAttr{"Name"}, $LibVersion)}} = %TypeAttr;7765 }7766 }7767 7768 sub separate_Params($$$)7769 {7770 my ($Params, $Comma, $Sp) = @_;7771 my @Parts = ();7772 my %B = ( "("=>0, "<"=>0, ")"=>0, ">"=>0 );7773 my $Part = 0;7774 foreach my $Pos (0 .. length($Params) - 1)7775 {7776 my $S = substr($Params, $Pos, 1);7777 if(defined $B{$S}) {7778 $B{$S} += 1;7779 }7780 if($S eq "," and7781 $B{"("}==$B{")"} and $B{"<"}==$B{">"})7782 {7783 if($Comma)7784 { # include comma7785 $Parts[$Part] .= $S;7786 }7787 $Part += 1;7788 }7789 else {7790 $Parts[$Part] .= $S;7791 }7792 }7793 if(not $Sp)7794 { # remove spaces7795 foreach (@Parts)7796 {7797 s/\A //g;7798 s/ \Z//g;7799 }7800 }7801 return @Parts;7802 }7803 7804 3721 sub registerUsage($$) 7805 3722 { 7806 my ($TypeId, $L ibVersion) = @_;7807 $Class_Constructed{$L ibVersion}{$TypeId} = 1;7808 if(my $BaseId = $TypeInfo{$L ibVersion}{$TypeId}{"BaseType"}) {7809 $Class_Constructed{$L ibVersion}{$BaseId} = 1;3723 my ($TypeId, $LVer) = @_; 3724 $Class_Constructed{$LVer}{$TypeId} = 1; 3725 if(my $BaseId = $TypeInfo{$LVer}{$TypeId}{"BaseType"}) { 3726 $Class_Constructed{$LVer}{$BaseId} = 1; 7810 3727 } 7811 3728 } … … 7814 3731 { 7815 3732 my $Method = $_[0]; 7816 return "" if(not $Method);3733 7817 3734 if($Method=~s/\)(.+)\Z/\)V/g) { 7818 3735 return $Method; 7819 3736 } 7820 else { 7821 return ""; 7822 } 3737 3738 return undef; 7823 3739 } 7824 3740 … … 7834 3750 7835 3751 my $ClassId = $MethodInfo{2}{$Method}{"Class"}; 7836 my %Class = get_Type($ClassId, 2);3752 my $CName = getTypeName($ClassId, 2); 7837 3753 7838 $CheckedTypes{$C lass{"Name"}} = 1;3754 $CheckedTypes{$CName} = 1; 7839 3755 $CheckedMethods{$Method} = 1; 7840 3756 7841 3757 if(not $MethodInfo{2}{$Method}{"Constructor"} 7842 and my $Overridden = findMethod($Method, 2, $C lass{"Name"}, 2))3758 and my $Overridden = findMethod($Method, 2, $CName, 2)) 7843 3759 { 7844 3760 if(defined $MethodInfo{1}{$Overridden} 7845 and get _TypeType($ClassId, 2) eq "class" and $TName_Tid{1}{$Class{"Name"}})3761 and getTypeType($ClassId, 2) eq "class" and $TName_Tid{1}{$CName}) 7846 3762 { # class should exist in previous version 7847 %{$CompatProblems{$Overridden}{"Class_Overridden_Method"}{"this.".get _SFormat($Method)}}=(7848 "Type_Name"=>$C lass{"Name"},3763 %{$CompatProblems{$Overridden}{"Class_Overridden_Method"}{"this.".getSFormat($Method)}}=( 3764 "Type_Name"=>$CName, 7849 3765 "Target"=>$MethodInfo{2}{$Method}{"Signature"}, 7850 3766 "Old_Value"=>$Overridden, 7851 "New_Value"=>$Method 3767 "New_Value"=>$Method); 7852 3768 } 7853 3769 } 7854 3770 if($MethodInfo{2}{$Method}{"Abstract"}) { 7855 $AddedMethod_Abstract{$C lass{"Name"}}{$Method} = 1;3771 $AddedMethod_Abstract{$CName}{$Method} = 1; 7856 3772 } 7857 3773 … … 7860 3776 if(not $MethodInfo{2}{$Method}{"Constructor"}) 7861 3777 { 7862 if(get _TypeName($MethodInfo{2}{$Method}{"Return"}, 2) ne "void"3778 if(getTypeName($MethodInfo{2}{$Method}{"Return"}, 2) ne "void" 7863 3779 and my $VoidMethod = checkVoidMethod($Method)) 7864 3780 { … … 7869 3785 7870 3786 %{$CompatProblems{$VoidMethod}{"Changed_Method_Return_From_Void"}{""}}=( 7871 "New_Value"=>get _TypeName($MethodInfo{2}{$Method}{"Return"}, 2)3787 "New_Value"=>getTypeName($MethodInfo{2}{$Method}{"Return"}, 2) 7872 3788 ); 7873 3789 } … … 7889 3805 7890 3806 my $ClassId = $MethodInfo{1}{$Method}{"Class"}; 7891 my %Class = get_Type($ClassId, 1);3807 my $CName = getTypeName($ClassId, 1); 7892 3808 7893 $CheckedTypes{$C lass{"Name"}} = 1;3809 $CheckedTypes{$CName} = 1; 7894 3810 $CheckedMethods{$Method} = 1; 7895 3811 7896 3812 if(not $MethodInfo{1}{$Method}{"Constructor"} 7897 and my $MovedUp = findMethod($Method, 1, $C lass{"Name"}, 2))7898 { 7899 if(get _TypeType($ClassId, 1) eq "class"7900 and not $MethodInfo{1}{$Method}{"Abstract"} and $TName_Tid{2}{$C lass{"Name"}})3813 and my $MovedUp = findMethod($Method, 1, $CName, 2)) 3814 { 3815 if(getTypeType($ClassId, 1) eq "class" 3816 and not $MethodInfo{1}{$Method}{"Abstract"} and $TName_Tid{2}{$CName}) 7901 3817 {# class should exist in newer version 7902 %{$CompatProblems{$Method}{"Class_Method_Moved_Up_Hierarchy"}{"this.".get _SFormat($MovedUp)}}=(7903 "Type_Name"=>$C lass{"Name"},3818 %{$CompatProblems{$Method}{"Class_Method_Moved_Up_Hierarchy"}{"this.".getSFormat($MovedUp)}}=( 3819 "Type_Name"=>$CName, 7904 3820 "Target"=>$MethodInfo{2}{$MovedUp}{"Signature"}, 7905 3821 "Old_Value"=>$Method, 7906 "New_Value"=>$MovedUp 3822 "New_Value"=>$MovedUp); 7907 3823 } 7908 3824 } … … 7910 3826 { 7911 3827 if($MethodInfo{1}{$Method}{"Abstract"}) { 7912 $RemovedMethod_Abstract{$C lass{"Name"}}{$Method} = 1;3828 $RemovedMethod_Abstract{$CName}{$Method} = 1; 7913 3829 } 7914 3830 %{$CompatProblems{$Method}{"Removed_Method"}{""}}=(); … … 7918 3834 } 7919 3835 7920 sub getArchives($)7921 {7922 my $LibVersion = $_[0];7923 my @Paths = ();7924 foreach my $Path (split(/\s*\n\s*/, $Descriptor{$LibVersion}{"Archives"}))7925 {7926 if(not -e $Path) {7927 exitStatus("Access_Error", "can't access \'$Path\'");7928 }7929 foreach (getArchivePaths($Path, $LibVersion)) {7930 push(@Paths, $_);7931 }7932 }7933 return @Paths;7934 }7935 7936 3836 sub getArchivePaths($$) 7937 3837 { 7938 my ($Dest, $L ibVersion) = @_;3838 my ($Dest, $LVer) = @_; 7939 3839 if(-f $Dest) { 7940 3840 return ($Dest); … … 7943 3843 { 7944 3844 $Dest=~s/[\/\\]+\Z//g; 7945 my @AllClasses = (); 7946 foreach my $Path (cmd_find($Dest,"","*\.jar","")) 7947 { 7948 next if(ignore_path($Path, $Dest)); 7949 push(@AllClasses, resolve_symlink($Path)); 7950 } 7951 return @AllClasses; 3845 next if(not $Dest); 3846 3847 my @Archives = (); 3848 foreach my $Path (cmdFind($Dest, "", "*\\.jar")) 3849 { 3850 next if(ignorePath($Path, $Dest)); 3851 push(@Archives, realpath_F($Path)); 3852 } 3853 return @Archives; 7952 3854 } 7953 3855 return (); 7954 3856 } 7955 3857 7956 sub isCyclical($$) 7957 { 3858 sub isCyclical($$) { 7958 3859 return (grep {$_ eq $_[1]} @{$_[0]}); 7959 3860 } 7960 3861 7961 sub read_symlink($) 7962 { 7963 my $Path = $_[0]; 7964 return "" if(not $Path or not -f $Path); 7965 return $Cache{"read_symlink"}{$Path} if(defined $Cache{"read_symlink"}{$Path}); 7966 if(my $ReadlinkCmd = get_CmdPath("readlink")) 7967 { 7968 my $Res = `$ReadlinkCmd -n \"$Path\"`; 7969 return ($Cache{"read_symlink"}{$Path} = $Res); 7970 } 7971 elsif(my $FileCmd = get_CmdPath("file")) 7972 { 7973 my $Info = `$FileCmd \"$Path\"`; 7974 if($Info=~/symbolic\s+link\s+to\s+['`"]*([\w\d\.\-\/\\]+)['`"]*/i) { 7975 return ($Cache{"read_symlink"}{$Path} = $1); 7976 } 7977 } 7978 return ($Cache{"read_symlink"}{$Path} = ""); 7979 } 7980 7981 sub resolve_symlink($) 7982 { 7983 my $Path = $_[0]; 7984 return "" if(not $Path or not -f $Path); 7985 return $Path if(isCyclical(\@RecurSymlink, $Path)); 7986 push(@RecurSymlink, $Path); 7987 if(-l $Path and my $Redirect=read_symlink($Path)) 7988 { 7989 if(is_abs($Redirect)) 7990 { 7991 my $Res = resolve_symlink($Redirect); 7992 pop(@RecurSymlink); 7993 return $Res; 7994 } 7995 elsif($Redirect=~/\.\.[\/\\]/) 7996 { 7997 $Redirect = joinPath(get_dirname($Path),$Redirect); 7998 while($Redirect=~s&(/|\\)[^\/\\]+(\/|\\)\.\.(\/|\\)&$1&){}; 7999 my $Res = resolve_symlink($Redirect); 8000 pop(@RecurSymlink); 8001 return $Res; 8002 } 8003 elsif(-f get_dirname($Path)."/".$Redirect) 8004 { 8005 my $Res = resolve_symlink(joinPath(get_dirname($Path),$Redirect)); 8006 pop(@RecurSymlink); 8007 return $Res; 8008 } 8009 return $Path; 3862 sub mergeAPIs($$) 3863 { 3864 my ($LVer, $Dep) = @_; 3865 3866 foreach my $TId (keys(%{$Dep->{"TypeInfo"}})) 3867 { 3868 $TypeInfo{$LVer}{$TId} = $Dep->{"TypeInfo"}{$TId}; 3869 $TypeInfo{$LVer}{$TId}{"Dep"} = 1; 3870 } 3871 3872 my $MInfo = $Dep->{"MethodInfo"}; 3873 foreach my $M_Id (keys(%{$MInfo})) 3874 { 3875 if(my $Name = $MInfo->{$M_Id}{"Name"}) 3876 { 3877 $MethodInfo{$LVer}{$Name} = $MInfo->{$M_Id}; 3878 $MethodInfo{$LVer}{$Name}{"Dep"} = 1; 3879 } 3880 } 3881 } 3882 3883 sub readAPIDump($$$) 3884 { 3885 my ($LVer, $Path, $Subj) = @_; 3886 3887 if(not $In::Opt{"CountMethods"}) { 3888 printMsg("INFO", "Reading API dump ($LVer) ..."); 3889 } 3890 3891 my $FilePath = ""; 3892 if(isDump_U($Path)) 3893 { # input *.dump 3894 $FilePath = $Path; 8010 3895 } 8011 3896 else 8012 { 8013 pop(@RecurSymlink); 8014 return $Path; 8015 } 8016 } 8017 8018 sub cmpVersions($$) 8019 {# compare two version strings in dotted-numeric format 8020 my ($V1, $V2) = @_; 8021 return 0 if($V1 eq $V2); 8022 my @V1Parts = split(/\./, $V1); 8023 my @V2Parts = split(/\./, $V2); 8024 for (my $i = 0; $i <= $#V1Parts && $i <= $#V2Parts; $i++) { 8025 return -1 if(int($V1Parts[$i]) < int($V2Parts[$i])); 8026 return 1 if(int($V1Parts[$i]) > int($V2Parts[$i])); 8027 } 8028 return -1 if($#V1Parts < $#V2Parts); 8029 return 1 if($#V1Parts > $#V2Parts); 8030 return 0; 8031 } 8032 8033 sub majorVersion($) 8034 { 8035 my $Version = $_[0]; 8036 return 0 if(not $Version); 8037 my @VParts = split(/\./, $Version); 8038 return $VParts[0]; 8039 } 8040 8041 sub isDump($) 8042 { 8043 if($_[0]=~/\A(.+)\.(api|dump|apidump)(\Q.tar.gz\E|\Q.zip\E|)\Z/) 8044 { # returns a name of package 8045 return $1; 8046 } 8047 return 0; 8048 } 8049 8050 sub isDumpFile($) 8051 { 8052 if($_[0]=~/\.(api|dump|apidump)\Z/) 8053 { 8054 return 1; 8055 } 8056 return 0; 8057 } 8058 8059 sub read_API_Dump($$$) 8060 { 8061 my ($LibVersion, $Path, $Subj) = @_; 8062 return if(not $LibVersion or not -e $Path); 8063 8064 my $FilePath = unpackDump($Path); 8065 if(not isDumpFile($FilePath)) { 8066 exitStatus("Invalid_Dump", "specified API dump \'$Path\' is not valid, try to recreate it"); 8067 } 8068 my $Content = readFile($FilePath); 8069 rmtree($TMP_DIR."/unpack"); 3897 { # input *.dump.tar.gz 3898 $FilePath = unpackDump($Path); 3899 if(not isDump_U($FilePath)) { 3900 exitStatus("Invalid_Dump", "specified API dump \'$Path\' is not valid, try to recreate it"); 3901 } 3902 } 3903 3904 my $APIRef = {}; 3905 3906 open(DUMP, $FilePath); 3907 local $/ = undef; 3908 my $Content = <DUMP>; 3909 close(DUMP); 3910 3911 if(getDirname($FilePath) eq $In::Opt{"Tmp"}."/unpack") 3912 { # remove temp file 3913 unlink($FilePath); 3914 } 8070 3915 8071 3916 if($Content!~/};\s*\Z/) { 8072 3917 exitStatus("Invalid_Dump", "specified API dump \'$Path\' is not valid, try to recreate it"); 8073 3918 } 8074 my $APIDump = eval($Content); 8075 if(not $APIDump) { 3919 3920 $APIRef = eval($Content); 3921 3922 if(not $APIRef) { 8076 3923 exitStatus("Error", "internal error - eval() procedure seem to not working correctly, try to remove 'use strict' and try again"); 8077 3924 } 8078 my $DumpVersion = $APIDump->{"API_DUMP_VERSION"}; 8079 if(majorVersion($DumpVersion) ne $API_DUMP_MAJOR) 8080 { # compatible with the dumps of the same major version 8081 exitStatus("Dump_Version", "incompatible version $DumpVersion of specified API dump (allowed only $API_DUMP_MAJOR.0<=V<=$API_DUMP_MAJOR.9)"); 8082 } 8083 8084 if(defined $TypeInfo{$LibVersion}) 8085 { 8086 foreach my $TId (keys(%{$APIDump->{"TypeInfo"}})) 8087 { 8088 $TypeInfo{$LibVersion}{$TId} = $APIDump->{"TypeInfo"}{$TId}; 8089 } 8090 } 8091 else { 8092 $TypeInfo{$LibVersion} = $APIDump->{"TypeInfo"}; 8093 } 8094 8095 foreach my $TypeId (keys(%{$APIDump->{"TypeInfo"}})) 8096 { 8097 my %TypeAttr = %{$TypeInfo{$LibVersion}{$TypeId}}; 8098 $TName_Tid{$LibVersion}{$TypeAttr{"Name"}} = $TypeId; 8099 8100 if($Subj ne "Dep") 8101 { 8102 if(my $Archive = $TypeAttr{"Archive"}) { 8103 $LibArchives{$LibVersion}{$Archive} = 1; 8104 } 8105 } 8106 8107 foreach my $FieldName (keys(%{$TypeAttr{"Fields"}})) 8108 { 8109 if($TypeAttr{"Fields"}{$FieldName}{"Access"}=~/public|protected/) { 8110 $Class_Fields{$LibVersion}{$TypeAttr{"Name"}}{$FieldName} = $TypeAttr{"Fields"}{$FieldName}{"Type"}; 8111 } 8112 } 8113 8114 if($Subj eq "Dep") { 8115 $TypeInfo{$LibVersion}{$TypeId}{"Dep"} = 1; 8116 } 8117 } 8118 my $MInfo = $APIDump->{"MethodInfo"}; 8119 foreach my $M_Id (keys(%{$MInfo})) 8120 { 8121 my $Name = $MInfo->{$M_Id}{"Name"}; 8122 $MethodInfo{$LibVersion}{$Name} = $MInfo->{$M_Id}; 8123 8124 if($Subj eq "Dep") { 8125 $MethodInfo{$LibVersion}{$Name}{"Dep"} = 1; 8126 } 8127 } 8128 8129 my $MUsed = $APIDump->{"MethodUsed"}; 8130 foreach my $M_Id (keys(%{$MUsed})) 8131 { 8132 my $Name = $MUsed->{$M_Id}{"Name"}; 8133 $MethodUsed{$LibVersion}{$Name} = $MUsed->{$M_Id}{"Used"}; 8134 } 8135 8136 foreach my $Method (keys(%{$MethodInfo{$LibVersion}})) 8137 { 8138 if(my $ClassId = $MethodInfo{$LibVersion}{$Method}{"Class"} 8139 and $MethodInfo{$LibVersion}{$Method}{"Access"}=~/public|protected/) 8140 { 8141 $Class_Methods{$LibVersion}{get_TypeName($ClassId, $LibVersion)}{$Method} = 1; 8142 if($MethodInfo{$LibVersion}{$Method}{"Abstract"}) { 8143 $Class_AbstractMethods{$LibVersion}{get_TypeName($ClassId, $LibVersion)}{$Method} = 1; 8144 } 8145 } 8146 } 8147 8148 # $FieldUsed{$LibVersion} = $APIDump->{"FieldUsed"}; 8149 8150 if(keys(%{$LibArchives{$LibVersion}})) { 8151 $Descriptor{$LibVersion}{"Archives"} = "OK"; 8152 } 8153 $Descriptor{$LibVersion}{"Version"} = $APIDump->{"LibraryVersion"}; 8154 $Descriptor{$LibVersion}{"Dump"} = 1; 8155 } 8156 8157 sub createDescriptor($$) 8158 { 8159 my ($LibVersion, $Path) = @_; 8160 return if(not $LibVersion or not $Path or not -e $Path); 8161 8162 if(isDump($Path)) 8163 { # API dump 8164 read_API_Dump($LibVersion, $Path, "Main"); 8165 } 8166 else 8167 { 8168 if(-d $Path or $Path=~/\.jar\Z/) 8169 { 8170 readDescriptor($LibVersion," 8171 <version> 8172 ".$TargetVersion{$LibVersion}." 8173 </version> 8174 8175 <archives> 8176 $Path 8177 </archives>"); 8178 } 8179 else 8180 { # standard XML descriptor 8181 readDescriptor($LibVersion, readFile($Path)); 8182 } 8183 } 8184 8185 if(my $Dep = $DepDump{$LibVersion}) { 8186 read_API_Dump($LibVersion, $Dep, "Dep"); 8187 } 8188 } 8189 8190 sub get_version($) 8191 { 8192 my $Cmd = $_[0]; 8193 return "" if(not $Cmd); 8194 my $Version = `$Cmd --version 2>\"$TMP_DIR/null\"`; 8195 return $Version; 8196 } 8197 8198 sub get_depth($) 8199 { 8200 if(defined $Cache{"get_depth"}{$_[0]}) { 8201 return $Cache{"get_depth"}{$_[0]} 8202 } 8203 return ($Cache{"get_depth"}{$_[0]} = ($_[0]=~tr![\/\\]|\:\:!!)); 8204 } 8205 8206 sub show_time_interval($) 8207 { 8208 my $Interval = $_[0]; 8209 my $Hr = int($Interval/3600); 8210 my $Min = int($Interval/60)-$Hr*60; 8211 my $Sec = $Interval-$Hr*3600-$Min*60; 8212 if($Hr) { 8213 return "$Hr hr, $Min min, $Sec sec"; 8214 } 8215 elsif($Min) { 8216 return "$Min min, $Sec sec"; 8217 } 8218 else { 8219 return "$Sec sec"; 8220 } 3925 3926 my $APIVer = $APIRef->{"API_DUMP_VERSION"}; 3927 3928 if($APIVer) 3929 { 3930 if(cmpVersions($APIVer, $API_DUMP_VERSION)>0) 3931 { # future formats 3932 exitStatus("Dump_Version", "the versions of the API dump is newer than version of the tool"); 3933 } 3934 } 3935 3936 if(cmpVersions($APIVer, $API_DUMP_VERSION_MIN)<0) { 3937 exitStatus("Dump_Version", "the version of the API dump is too old and unsupported anymore, please regenerate it"); 3938 } 3939 3940 if($Subj ne "Dep") 3941 { 3942 $In::Desc{$LVer}{"Version"} = $APIRef->{"LibraryVersion"}; 3943 $In::Desc{$LVer}{"Dump"} = 1; 3944 } 3945 3946 return $APIRef; 8221 3947 } 8222 3948 8223 3949 sub checkVersionNum($$) 8224 3950 { 8225 my ($L ibVersion, $Path) = @_;8226 8227 if($ TargetVersion{$LibVersion}) {3951 my ($LVer, $Path) = @_; 3952 3953 if($In::Desc{$LVer}{"TargetVersion"}) { 8228 3954 return; 8229 3955 } … … 8236 3962 8237 3963 if(not defined $Ver) { 8238 $Ver = getManifestVersion(get _abs_path($Path));3964 $Ver = getManifestVersion(getAbsPath($Path)); 8239 3965 } 8240 3966 8241 3967 if(not defined $Ver) { 8242 $Ver = getPkgVersion(get _filename($Path));3968 $Ver = getPkgVersion(getFilename($Path)); 8243 3969 } 8244 3970 … … 8249 3975 if(not defined $Ver) 8250 3976 { 8251 if($ DumpAPI)3977 if($In::Opt{"DumpAPI"}) 8252 3978 { 8253 3979 $Ver = "XYZ"; … … 8255 3981 else 8256 3982 { 8257 if($L ibVersion==1) {3983 if($LVer==1) { 8258 3984 $Ver = "X"; 8259 3985 } … … 8264 3990 } 8265 3991 8266 $ TargetVersion{$LibVersion} = $Ver;8267 8268 if($ DumpAPI) {3992 $In::Desc{$LVer}{"TargetVersion"} = $Ver; 3993 3994 if($In::Opt{"DumpAPI"}) { 8269 3995 printMsg("WARNING", "set version number to $Ver (use -vnum option to change it)"); 8270 3996 } 8271 3997 else { 8272 printMsg("WARNING", "set #$L ibVersion version number to $Ver (use --v$LibVersion=NUM option to change it)");3998 printMsg("WARNING", "set #$LVer version number to $Ver (use --v$LVer=NUM option to change it)"); 8273 3999 } 8274 4000 } … … 8278 4004 my $Path = $_[0]; 8279 4005 8280 if(not $Path or not -e $Path) { 8281 return undef; 8282 } 8283 8284 my $JarCmd = get_CmdPath("jar"); 4006 my $JarCmd = getCmdPath("jar"); 8285 4007 if(not $JarCmd) { 8286 4008 exitStatus("Not_Found", "can't find \"jar\" command"); 8287 4009 } 8288 chdir($TMP_DIR); 4010 4011 my $TmpDir = $In::Opt{"Tmp"}; 4012 4013 chdir($TmpDir); 8289 4014 system($JarCmd." -xf \"$Path\" META-INF 2>null"); 8290 chdir($ORIG_DIR); 8291 if(my $Content = readFile("$TMP_DIR/META-INF/MANIFEST.MF")) 8292 { 8293 if($Content=~/(\A|\s)Implementation\-Version:\s*(.+)(\s|\Z)/i) { 8294 return $2; 4015 chdir($In::Opt{"OrigDir"}); 4016 4017 my $Manifest = $TmpDir."/META-INF/MANIFEST.MF"; 4018 4019 if(-f $Manifest) 4020 { 4021 if(my $Content = readFile($Manifest)) 4022 { 4023 if($Content=~/(\A|\s)Implementation\-Version:\s*(.+)(\s|\Z)/i) { 4024 return $2; 4025 } 8295 4026 } 8296 4027 } … … 8337 4068 } 8338 4069 8339 sub get_OSgroup() 8340 { 8341 if($Config{"osname"}=~/macos|darwin|rhapsody/i) { 8342 return "macos"; 8343 } 8344 elsif($Config{"osname"}=~/freebsd|openbsd|netbsd/i) { 8345 return "bsd"; 8346 } 8347 elsif($Config{"osname"}=~/haiku|beos/i) { 8348 return "beos"; 8349 } 8350 elsif($Config{"osname"}=~/symbian|epoc/i) { 8351 return "symbian"; 8352 } 8353 elsif($Config{"osname"}=~/win/i) { 8354 return "windows"; 8355 } 8356 else { 8357 return $Config{"osname"}; 8358 } 8359 } 8360 8361 sub get_ARG_MAX() 8362 { 8363 if($OSgroup eq "windows") { 8364 return 1990; # 8191, 2047 8365 } 8366 else 8367 { # Linux 8368 # TODO: set max possible value (~131000) 8369 return 32767; 8370 } 8371 } 8372 8373 sub dump_sorting($) 4070 sub dumpSorting($) 8374 4071 { 8375 4072 my $Hash = $_[0]; … … 8387 4084 } 8388 4085 8389 sub detect_bin_default_paths()8390 {8391 my $EnvPaths = $ENV{"PATH"};8392 if($OSgroup eq "beos") {8393 $EnvPaths.=":".$ENV{"BETOOLS"};8394 }8395 elsif($OSgroup eq "windows"8396 and my $JHome = $ENV{"JAVA_HOME"}) {8397 $EnvPaths.=";$JHome\\bin";8398 }8399 my $Sep = ($OSgroup eq "windows")?";":":|;";8400 foreach my $Path (sort {length($a)<=>length($b)} split(/$Sep/, $EnvPaths))8401 {8402 $Path=~s/[\/\\]+\Z//g;8403 next if(not $Path);8404 $DefaultBinPaths{$Path} = 1;8405 }8406 }8407 8408 sub detect_default_paths()8409 {8410 if(keys(%SystemPaths))8411 {# run once8412 return;8413 }8414 8415 foreach my $Type (keys(%{$OS_AddPath{$OSgroup}}))8416 {# additional search paths8417 foreach my $Path (keys(%{$OS_AddPath{$OSgroup}{$Type}}))8418 {8419 next if(not -d $Path);8420 $SystemPaths{$Type}{$Path} = $OS_AddPath{$OSgroup}{$Type}{$Path};8421 }8422 }8423 if($OSgroup ne "windows")8424 {8425 foreach my $Type ("include", "lib", "bin")8426 {# autodetecting system "devel" directories8427 foreach my $Path (cmd_find("/","d","*$Type*",1)) {8428 $SystemPaths{$Type}{$Path} = 1;8429 }8430 if(-d "/usr") {8431 foreach my $Path (cmd_find("/usr","d","*$Type*",1)) {8432 $SystemPaths{$Type}{$Path} = 1;8433 }8434 }8435 }8436 }8437 detect_bin_default_paths();8438 foreach my $Path (keys(%DefaultBinPaths)) {8439 $SystemPaths{"bin"}{$Path} = $DefaultBinPaths{$Path};8440 }8441 8442 if(not $TestSystem)8443 {8444 if(my $JavacCmd = get_CmdPath("javac"))8445 {8446 if(my $Ver = `$JavacCmd -version 2>&1`)8447 {8448 if($Ver=~/javac\s+(.+)/) {8449 printMsg("INFO", "using Java ".$1);8450 }8451 }8452 }8453 }8454 }8455 8456 sub exitStatus($$)8457 {8458 my ($Code, $Msg) = @_;8459 print STDERR "ERROR: ". $Msg."\n";8460 exit($ERROR_CODE{$Code});8461 }8462 8463 sub printMsg($$)8464 {8465 my ($Type, $Msg) = @_;8466 if($Type!~/\AINFO/) {8467 $Msg = $Type.": ".$Msg;8468 }8469 if($Type!~/_C\Z/) {8470 $Msg .= "\n";8471 }8472 if($Type eq "ERROR") {8473 print STDERR $Msg;8474 }8475 else {8476 print $Msg;8477 }8478 }8479 8480 4086 sub printStatMsg($) 8481 4087 { 8482 4088 my $Level = $_[0]; 8483 printMsg("INFO", " total ".lc($Level)." compatibility problems: ".$RESULT{$Level}{"Problems"}.", warnings: ".$RESULT{$Level}{"Warnings"});4089 printMsg("INFO", "Total ".lc($Level)." compatibility problems: ".$RESULT{$Level}{"Problems"}.", warnings: ".$RESULT{$Level}{"Warnings"}); 8484 4090 } 8485 4091 8486 4092 sub printReport() 8487 4093 { 8488 printMsg("INFO", " creating compatibility report ...");4094 printMsg("INFO", "Creating compatibility report ..."); 8489 4095 createReport(); 8490 if($ JoinReport or $DoubleReport)4096 if($In::Opt{"JoinReport"} or $In::Opt{"DoubleReport"}) 8491 4097 { 8492 4098 if($RESULT{"Binary"}{"Problems"} 8493 4099 or $RESULT{"Source"}{"Problems"}) 8494 4100 { 8495 printMsg("INFO", " binary compatibility: ".(100-$RESULT{"Binary"}{"Affected"})."\%");8496 printMsg("INFO", " source compatibility: ".(100-$RESULT{"Source"}{"Affected"})."\%");4101 printMsg("INFO", "Binary compatibility: ".(100-$RESULT{"Binary"}{"Affected"})."\%"); 4102 printMsg("INFO", "Source compatibility: ".(100-$RESULT{"Source"}{"Affected"})."\%"); 8497 4103 } 8498 4104 else 8499 4105 { 8500 printMsg("INFO", " binary compatibility: 100\%");8501 printMsg("INFO", " source compatibility: 100\%");4106 printMsg("INFO", "Binary compatibility: 100\%"); 4107 printMsg("INFO", "Source compatibility: 100\%"); 8502 4108 } 8503 4109 printStatMsg("Binary"); 8504 4110 printStatMsg("Source"); 8505 4111 } 8506 elsif($ BinaryOnly)4112 elsif($In::Opt{"BinaryOnly"}) 8507 4113 { 8508 4114 if($RESULT{"Binary"}{"Problems"}) { 8509 printMsg("INFO", " binary compatibility: ".(100-$RESULT{"Binary"}{"Affected"})."\%");4115 printMsg("INFO", "Binary compatibility: ".(100-$RESULT{"Binary"}{"Affected"})."\%"); 8510 4116 } 8511 4117 else { 8512 printMsg("INFO", " binary compatibility: 100\%");4118 printMsg("INFO", "Binary compatibility: 100\%"); 8513 4119 } 8514 4120 printStatMsg("Binary"); 8515 4121 } 8516 elsif($ SourceOnly)4122 elsif($In::Opt{"SourceOnly"}) 8517 4123 { 8518 4124 if($RESULT{"Source"}{"Problems"}) { 8519 printMsg("INFO", " source compatibility: ".(100-$RESULT{"Source"}{"Affected"})."\%");4125 printMsg("INFO", "Source compatibility: ".(100-$RESULT{"Source"}{"Affected"})."\%"); 8520 4126 } 8521 4127 else { 8522 printMsg("INFO", " source compatibility: 100\%");4128 printMsg("INFO", "Source compatibility: 100\%"); 8523 4129 } 8524 4130 printStatMsg("Source"); 8525 4131 } 8526 if($ JoinReport)8527 { 8528 printMsg("INFO", " report: ".getReportPath("Join"));8529 } 8530 elsif($ DoubleReport)4132 if($In::Opt{"JoinReport"}) 4133 { 4134 printMsg("INFO", "Report: ".getReportPath("Join")); 4135 } 4136 elsif($In::Opt{"DoubleReport"}) 8531 4137 { # default 8532 printMsg("INFO", " report (BC): ".getReportPath("Binary"));8533 printMsg("INFO", " report (SC): ".getReportPath("Source"));8534 } 8535 elsif($ BinaryOnly)4138 printMsg("INFO", "Report (BC): ".getReportPath("Binary")); 4139 printMsg("INFO", "Report (SC): ".getReportPath("Source")); 4140 } 4141 elsif($In::Opt{"BinaryOnly"}) 8536 4142 { # --binary 8537 printMsg("INFO", " report: ".getReportPath("Binary"));8538 } 8539 elsif($ SourceOnly)4143 printMsg("INFO", "Report: ".getReportPath("Binary")); 4144 } 4145 elsif($In::Opt{"SourceOnly"}) 8540 4146 { # --source 8541 printMsg("INFO", " report: ".getReportPath("Source"));4147 printMsg("INFO", "Report: ".getReportPath("Source")); 8542 4148 } 8543 4149 } … … 8546 4152 { 8547 4153 my $Level = $_[0]; 8548 my $Dir = "compat_reports/ $TargetLibraryName/".$Descriptor{1}{"Version"}."_to_".$Descriptor{2}{"Version"};4154 my $Dir = "compat_reports/".$In::Opt{"TargetLib"}."/".$In::Desc{1}{"Version"}."_to_".$In::Desc{2}{"Version"}; 8549 4155 if($Level eq "Binary") 8550 4156 { 8551 if($ BinaryReportPath)4157 if($In::Opt{"BinaryReportPath"}) 8552 4158 { # --bin-report-path 8553 return $ BinaryReportPath;8554 } 8555 elsif($ OutputReportPath)4159 return $In::Opt{"BinaryReportPath"}; 4160 } 4161 elsif($In::Opt{"OutputReportPath"}) 8556 4162 { # --report-path 8557 return $ OutputReportPath;4163 return $In::Opt{"OutputReportPath"}; 8558 4164 } 8559 4165 else … … 8564 4170 elsif($Level eq "Source") 8565 4171 { 8566 if($ SourceReportPath)4172 if($In::Opt{"SourceReportPath"}) 8567 4173 { # --src-report-path 8568 return $ SourceReportPath;8569 } 8570 elsif($ OutputReportPath)4174 return $In::Opt{"SourceReportPath"}; 4175 } 4176 elsif($In::Opt{"OutputReportPath"}) 8571 4177 { # --report-path 8572 return $ OutputReportPath;4178 return $In::Opt{"OutputReportPath"}; 8573 4179 } 8574 4180 else … … 8579 4185 else 8580 4186 { 8581 if($ OutputReportPath)4187 if($In::Opt{"OutputReportPath"}) 8582 4188 { # --report-path 8583 return $ OutputReportPath;4189 return $In::Opt{"OutputReportPath"}; 8584 4190 } 8585 4191 else … … 8590 4196 } 8591 4197 8592 sub initLogging($) 8593 { 8594 my $LibVersion = $_[0]; 8595 if($Debug) 8596 { # debug directory 8597 $DEBUG_PATH{$LibVersion} = "debug/$TargetLibraryName/".$Descriptor{$LibVersion}{"Version"}; 8598 8599 if(-d $DEBUG_PATH{$LibVersion}) { 8600 rmtree($DEBUG_PATH{$LibVersion}); 4198 sub unpackDump($) 4199 { 4200 my $Path = $_[0]; 4201 4202 if(isDump_U($Path)) { 4203 return $Path; 4204 } 4205 4206 my $TmpDir = $In::Opt{"Tmp"}; 4207 4208 $Path = getAbsPath($Path); 4209 $Path = pathFmt($Path); 4210 4211 my ($Dir, $FileName) = sepPath($Path); 4212 my $UnpackDir = $TmpDir."/unpack"; 4213 if(-d $UnpackDir) { 4214 rmtree($UnpackDir); 4215 } 4216 mkpath($UnpackDir); 4217 4218 if($FileName=~s/\Q.zip\E\Z//g) 4219 { # *.zip 4220 my $UnzipCmd = getCmdPath("unzip"); 4221 if(not $UnzipCmd) { 4222 exitStatus("Not_Found", "can't find \"unzip\" command"); 4223 } 4224 chdir($UnpackDir); 4225 system("$UnzipCmd \"$Path\" >contents.txt"); 4226 if($?) { 4227 exitStatus("Error", "can't extract \'$Path\'"); 4228 } 4229 chdir($In::Opt{"OrigDir"}); 4230 my @Contents = (); 4231 foreach (split("\n", readFile("$UnpackDir/contents.txt"))) 4232 { 4233 if(/inflating:\s*([^\s]+)/) { 4234 push(@Contents, $1); 4235 } 4236 } 4237 if(not @Contents) { 4238 exitStatus("Error", "can't extract \'$Path\'"); 4239 } 4240 return join_P($UnpackDir, $Contents[0]); 4241 } 4242 elsif($FileName=~s/\Q.tar.gz\E\Z//g) 4243 { # *.tar.gz 4244 if($In::Opt{"OS"} eq "windows") 4245 { # -xvzf option is not implemented in tar.exe (2003) 4246 # use "gzip.exe -k -d -f" + "tar.exe -xvf" instead 4247 my $TarCmd = getCmdPath("tar"); 4248 if(not $TarCmd) { 4249 exitStatus("Not_Found", "can't find \"tar\" command"); 4250 } 4251 my $GzipCmd = getCmdPath("gzip"); 4252 if(not $GzipCmd) { 4253 exitStatus("Not_Found", "can't find \"gzip\" command"); 4254 } 4255 chdir($UnpackDir); 4256 qx/$GzipCmd -k -d -f "$Path"/; # keep input files (-k) 4257 if($?) { 4258 exitStatus("Error", "can't extract \'$Path\'"); 4259 } 4260 my @Contents = qx/$TarCmd -xvf "$Dir\\$FileName.tar"/; 4261 if($? or not @Contents) { 4262 exitStatus("Error", "can't extract \'$Path\'"); 4263 } 4264 chdir($In::Opt{"OrigDir"}); 4265 unlink($Dir."/".$FileName.".tar"); 4266 chomp $Contents[0]; 4267 return join_P($UnpackDir, $Contents[0]); 4268 } 4269 else 4270 { # Linux, Unix, OS X 4271 my $TarCmd = getCmdPath("tar"); 4272 if(not $TarCmd) { 4273 exitStatus("Not_Found", "can't find \"tar\" command"); 4274 } 4275 chdir($UnpackDir); 4276 my @Contents = qx/$TarCmd -xvzf "$Path" 2>&1/; 4277 if($? or not @Contents) { 4278 exitStatus("Error", "can't extract \'$Path\'"); 4279 } 4280 chdir($In::Opt{"OrigDir"}); 4281 $Contents[0]=~s/^x //; # OS X 4282 chomp $Contents[0]; 4283 return join_P($UnpackDir, $Contents[0]); 8601 4284 } 8602 4285 } … … 8609 4292 $To = "."; 8610 4293 } 8611 if(not $Path or not -e $Path 8612 or not -d $To) { 8613 return ""; 8614 } 8615 my ($From, $Name) = separate_path($Path); 8616 if($OSgroup eq "windows") 4294 4295 my $TmpDir = $In::Opt{"Tmp"}; 4296 4297 my ($From, $Name) = sepPath($Path); 4298 if($In::Opt{"OS"} eq "windows") 8617 4299 { # *.zip 8618 my $ZipCmd = get _CmdPath("zip");4300 my $ZipCmd = getCmdPath("zip"); 8619 4301 if(not $ZipCmd) { 8620 4302 exitStatus("Not_Found", "can't find \"zip\""); … … 8623 4305 unlink($Pkg); 8624 4306 chdir($To); 8625 system("$ZipCmd -j \"$Name.zip\" \"$Path\" >\"$T MP_DIR/null\"");4307 system("$ZipCmd -j \"$Name.zip\" \"$Path\" >\"$TmpDir/null\""); 8626 4308 if($?) 8627 4309 { # cannot allocate memory (or other problems with "zip") … … 8629 4311 exitStatus("Error", "can't pack the API dump: ".$!); 8630 4312 } 8631 chdir($ ORIG_DIR);4313 chdir($In::Opt{"OrigDir"}); 8632 4314 unlink($Path); 8633 4315 return $Pkg; … … 8635 4317 else 8636 4318 { # *.tar.gz 8637 my $TarCmd = get _CmdPath("tar");4319 my $TarCmd = getCmdPath("tar"); 8638 4320 if(not $TarCmd) { 8639 4321 exitStatus("Not_Found", "can't find \"tar\""); 8640 4322 } 8641 my $GzipCmd = get _CmdPath("gzip");4323 my $GzipCmd = getCmdPath("gzip"); 8642 4324 if(not $GzipCmd) { 8643 4325 exitStatus("Not_Found", "can't find \"gzip\""); … … 8652 4334 exitStatus("Error", "can't pack the API dump: ".$!); 8653 4335 } 8654 chdir($ ORIG_DIR);4336 chdir($In::Opt{"OrigDir"}); 8655 4337 unlink($Path); 8656 4338 return $To."/".$Name.".tar.gz"; … … 8658 4340 } 8659 4341 8660 sub getMd5(@) 8661 { 8662 my $Md5 = md5_hex(@_); 8663 return substr($Md5, 0, $MD5_LEN); 8664 } 8665 8666 sub scenario() 8667 { 8668 if($BinaryOnly and $SourceOnly) 8669 { # both --binary and --source 8670 # is the default mode 8671 $DoubleReport = 1; 8672 $JoinReport = 0; 8673 $BinaryOnly = 0; 8674 $SourceOnly = 0; 8675 if($OutputReportPath) 8676 { # --report-path 8677 $DoubleReport = 0; 8678 $JoinReport = 1; 8679 } 8680 } 8681 elsif($BinaryOnly or $SourceOnly) 8682 { # --binary or --source 8683 $DoubleReport = 0; 8684 $JoinReport = 0; 8685 } 8686 if(defined $Help) 8687 { 8688 HELP_MESSAGE(); 8689 exit(0); 8690 } 8691 if(defined $ShowVersion) 8692 { 8693 printMsg("INFO", "Java API Compliance Checker (JAPICC) $TOOL_VERSION\nCopyright (C) 2016 Andrey Ponomarenko's ABI Laboratory\nLicense: LGPL or GPL <http://www.gnu.org/licenses/>\nThis program is free software: you can redistribute it and/or modify it.\n\nWritten by Andrey Ponomarenko."); 8694 exit(0); 8695 } 8696 if(defined $DumpVersion) 8697 { 8698 printMsg("INFO", $TOOL_VERSION); 8699 exit(0); 8700 } 8701 $Data::Dumper::Sortkeys = 1; 8702 8703 # FIXME: can't pass \&dump_sorting - cause a segfault sometimes 8704 if($SortDump) 8705 { 8706 $Data::Dumper::Useperl = 1; 8707 $Data::Dumper::Sortkeys = \&dump_sorting; 8708 } 8709 8710 if(defined $TestSystem) 8711 { 8712 detect_default_paths(); 8713 testSystem(); 8714 exit(0); 8715 } 8716 8717 if(defined $ShortMode) 8718 { 8719 if(not defined $AffectLimit) { 8720 $AffectLimit = 10; 8721 } 8722 } 8723 8724 if(not $TargetLibraryName and not $CountMethods) 8725 { 8726 if($DumpAPI) 8727 { 8728 if($DumpAPI=~/\.jar\Z/) 8729 { # short usage 8730 my ($Name, $Version) = getPkgVersion(get_filename($DumpAPI)); 8731 if($Name and $Version ne "") 8732 { 8733 $TargetLibraryName = $Name; 8734 if(not $TargetVersion{1}) { 8735 $TargetVersion{1} = $Version; 8736 } 8737 } 8738 } 8739 } 8740 else 8741 { 8742 if($Descriptor{1}{"Path"}=~/\.jar\Z/ and $Descriptor{2}{"Path"}=~/\.jar\Z/) 8743 { # short usage 8744 my ($Name1, $Version1) = getPkgVersion(get_filename($Descriptor{1}{"Path"})); 8745 my ($Name2, $Version2) = getPkgVersion(get_filename($Descriptor{2}{"Path"})); 8746 8747 if($Name1 and $Version1 ne "" 8748 and $Version2 ne "") 8749 { 8750 $TargetLibraryName = $Name1; 8751 if(not $TargetVersion{1}) { 8752 $TargetVersion{1} = $Version1; 8753 } 8754 if(not $TargetVersion{2}) { 8755 $TargetVersion{2} = $Version2; 8756 } 8757 } 8758 } 8759 } 8760 8761 if(not $TargetLibraryName) { 8762 exitStatus("Error", "library name is not selected (option --lib=NAME)"); 4342 sub initAliases($) 4343 { 4344 my $LVer = $_[0]; 4345 4346 initAPI($LVer); 4347 4348 $MethodInfo{$LVer} = $In::API{$LVer}{"MethodInfo"}; 4349 $TypeInfo{$LVer} = $In::API{$LVer}{"TypeInfo"}; 4350 $TName_Tid{$LVer} = $In::API{$LVer}{"TName_Tid"}; 4351 4352 initAliases_TypeAttr($LVer); 4353 } 4354 4355 sub createAPIFile($$) 4356 { 4357 my ($LVer, $DescPath) = @_; 4358 4359 if(not -e $DescPath) { 4360 exitStatus("Access_Error", "can't access \'$DescPath\'"); 4361 } 4362 4363 detectDefaultPaths("bin", "java"); 4364 4365 if(isDump($DescPath)) 4366 { 4367 $In::API{$LVer} = readAPIDump($LVer, $DescPath, "Main"); 4368 initAliases($LVer); 4369 4370 if(my $V = $In::Desc{$LVer}{"TargetVersion"}) { 4371 $In::Desc{$LVer}{"Version"} = $V; 4372 } 4373 else { 4374 $In::Desc{$LVer}{"Version"} = $In::API{$LVer}{"LibraryVersion"}; 8763 4375 } 8764 4376 } 8765 4377 else 8766 { # validate library name 8767 if($TargetLibraryName=~/[\*\/\\]/) { 8768 exitStatus("Error", "\"\\\", \"\/\" and \"*\" symbols are not allowed in the library name"); 8769 } 8770 } 8771 if(not $TargetTitle) { 8772 $TargetTitle = $TargetLibraryName; 8773 } 8774 if($ClassListPath) 8775 { 8776 if(not -f $ClassListPath) { 8777 exitStatus("Access_Error", "can't access file \'$ClassListPath\'"); 8778 } 8779 foreach my $Class (split(/\n/, readFile($ClassListPath))) 8780 { 8781 $Class=~s/\//./g; 8782 $ClassList_User{$Class} = 1; 8783 } 8784 } 8785 if($AnnotationsListPath) 8786 { 8787 if(not -f $AnnotationsListPath) { 8788 exitStatus("Access_Error", "can't access file \'$AnnotationsListPath\'"); 8789 } 8790 foreach my $Annotation (split(/\n/, readFile($AnnotationsListPath))) 8791 { 8792 $AnnotationList_User{$Annotation} = 1; 8793 } 8794 } 8795 if($SkipAnnotationsListPath) 8796 { 8797 if(not -f $SkipAnnotationsListPath) { 8798 exitStatus("Access_Error", "can't access file \'$SkipAnnotationsListPath\'"); 8799 } 8800 foreach my $Annotation (split(/\n/, readFile($SkipAnnotationsListPath))) 8801 { 8802 $SkipAnnotationList_User{$Annotation} = 1; 8803 } 8804 } 8805 if($SkipClassesList) 8806 { 8807 if(not -f $SkipClassesList) { 8808 exitStatus("Access_Error", "can't access file \'$SkipClassesList\'"); 8809 } 8810 foreach my $Class (split(/\n/, readFile($SkipClassesList))) 8811 { 8812 $Class=~s/\//./g; 8813 $SkipClasses{$Class} = 1; 8814 } 8815 } 8816 if($SkipPackagesList) 8817 { 8818 if(not -f $SkipPackagesList) { 8819 exitStatus("Access_Error", "can't access file \'$SkipPackagesList\'"); 8820 } 8821 foreach my $Package (split(/\n/, readFile($SkipPackagesList))) 8822 { 8823 $SkipPackages{1}{$Package} = 1; 8824 $SkipPackages{2}{$Package} = 1; 8825 } 8826 } 8827 if($ClientPath) 8828 { 8829 if($ClientPath=~/\.class\Z/) { 8830 exitStatus("Error", "input file is not a java archive"); 8831 } 8832 8833 if(-f $ClientPath) 8834 { 8835 detect_default_paths(); 8836 readArchive(0, $ClientPath) 8837 } 8838 else { 8839 exitStatus("Access_Error", "can't access file \'$ClientPath\'"); 8840 } 8841 } 8842 8843 if($CountMethods) 8844 { 8845 if(not -e $CountMethods) { 8846 exitStatus("Access_Error", "can't access \'$CountMethods\'"); 8847 } 8848 8849 read_API_Dump(1, $CountMethods, "Main"); 8850 8851 my $Count = 0; 8852 foreach my $Method (keys(%{$MethodInfo{1}})) { 8853 $Count += methodFilter($Method, 1); 8854 } 8855 8856 printMsg("INFO", $Count); 8857 exit(0); 8858 } 8859 8860 if($DumpAPI) 8861 { 8862 if(not -e $DumpAPI) { 8863 exitStatus("Access_Error", "can't access \'$DumpAPI\'"); 8864 } 8865 8866 detect_default_paths(); 8867 checkVersionNum(1, $DumpAPI); 8868 8869 my $TarCmd = get_CmdPath("tar"); 4378 { 4379 loadModule("APIDump"); 4380 4381 checkVersionNum($LVer, $DescPath); 4382 readDesc(createDesc($DescPath, $LVer), $LVer); 4383 4384 initLogging($LVer); 4385 4386 createAPIDump($LVer); 4387 } 4388 4389 if(my $Dep = $In::Desc{$LVer}{"DepDump"}) { 4390 mergeAPIs($LVer, readAPIDump($LVer, $Dep, "Dep")); 4391 } 4392 4393 printMsg("INFO", "Creating library API dump ..."); 4394 4395 $In::API{$LVer}{"API_DUMP_VERSION"} = $API_DUMP_VERSION; 4396 $In::API{$LVer}{"JAPI_COMPLIANCE_CHECKER_VERSION"} = $TOOL_VERSION; 4397 4398 foreach ("TName_Tid") { 4399 delete($In::API{$LVer}{$_}); 4400 } 4401 4402 my $DumpPath = "api_dumps/".$In::Opt{"TargetLib"}."/".$In::Desc{$LVer}{"Version"}."/API.dump"; 4403 if($In::Opt{"OutputDumpPath"}) 4404 { # user defined path 4405 $DumpPath = $In::Opt{"OutputDumpPath"}; 4406 } 4407 4408 my $ArExt = $In::Opt{"Ar"}; 4409 my $Archive = ($DumpPath=~s/\Q.$ArExt\E\Z//g); 4410 4411 if($Archive) 4412 { 4413 my $TarCmd = getCmdPath("tar"); 8870 4414 if(not $TarCmd) { 8871 4415 exitStatus("Not_Found", "can't find \"tar\""); 8872 4416 } 8873 my $GzipCmd = get _CmdPath("gzip");4417 my $GzipCmd = getCmdPath("gzip"); 8874 4418 if(not $GzipCmd) { 8875 4419 exitStatus("Not_Found", "can't find \"gzip\""); 8876 4420 } 8877 createDescriptor(1, $DumpAPI); 8878 if(not $Descriptor{1}{"Archives"}) { 8879 exitStatus("Error", "descriptor does not contain Java ARchives"); 8880 } 4421 } 4422 4423 my ($DDir, $DName) = sepPath($DumpPath); 4424 my $DPath = $In::Opt{"Tmp"}."/".$DName; 4425 if(not $Archive) { 4426 $DPath = $DumpPath; 4427 } 4428 4429 mkpath($DDir); 4430 4431 open(DUMP, ">", $DPath) || die ("can't open file \'$DPath\': $!\n"); 4432 print DUMP Dumper($In::API{$LVer}); 4433 close(DUMP); 4434 4435 if(not -s $DPath) { 4436 exitStatus("Error", "can't create API dump because something is going wrong with the Data::Dumper module"); 4437 } 4438 4439 if($Archive) { 4440 $DumpPath = createArchive($DPath, $DDir); 4441 } 4442 4443 if($In::Opt{"OutputDumpPath"}) { 4444 printMsg("INFO", "Dump path: ".$In::Opt{"OutputDumpPath"}); 4445 } 4446 else { 4447 printMsg("INFO", "Dump path: $DumpPath"); 4448 } 4449 exit(0); 4450 } 4451 4452 sub compareInit() 4453 { 4454 if(not $In::Desc{1}{"Path"}) { 4455 exitStatus("Error", "-old option is not specified"); 4456 } 4457 if(not -e $In::Desc{1}{"Path"}) { 4458 exitStatus("Access_Error", "can't access \'".$In::Desc{1}{"Path"}."\'"); 4459 } 4460 if(not $In::Desc{2}{"Path"}) { 4461 exitStatus("Error", "-new option is not specified"); 4462 } 4463 if(not -e $In::Desc{2}{"Path"}) { 4464 exitStatus("Access_Error", "can't access \'".$In::Desc{2}{"Path"}."\'"); 4465 } 4466 4467 if($In::Opt{"Quick"}) 4468 { 4469 $CompatRules{"Binary"}{"Interface_Added_Super_Interface"}{"Severity"} = "Low"; 4470 $CompatRules{"Binary"}{"Abstract_Class_Added_Super_Abstract_Class"}{"Severity"} = "Low"; 4471 $CompatRules{"Binary"}{"Abstract_Class_Added_Super_Interface"}{"Severity"} = "Low"; 4472 $CompatRules{"Binary"}{"Abstract_Class_Added_Abstract_Method"}{"Severity"} = "Low"; 4473 $CompatRules{"Binary"}{"Interface_Added_Abstract_Method"}{"Severity"} = "Low"; 4474 } 4475 4476 printMsg("INFO", "Preparing, please wait ..."); 4477 4478 detectDefaultPaths("bin", undef); 4479 4480 if(isDump($In::Desc{1}{"Path"})) 4481 { 4482 $In::API{1} = readAPIDump(1, $In::Desc{1}{"Path"}, "Main"); 4483 initAliases(1); 4484 4485 if(my $V = $In::Desc{1}{"TargetVersion"}) { 4486 $In::Desc{1}{"Version"} = $V; 4487 } 4488 else { 4489 $In::Desc{1}{"Version"} = $In::API{1}{"LibraryVersion"}; 4490 } 4491 } 4492 else 4493 { 4494 loadModule("APIDump"); 4495 4496 checkVersionNum(1, $In::Desc{1}{"Path"}); 4497 readDesc(createDesc($In::Desc{1}{"Path"}, 1), 1); 8881 4498 8882 4499 initLogging(1); 8883 readArchives(1); 8884 8885 printMsg("INFO", "creating library API dump ..."); 8886 if(not keys(%{$MethodInfo{1}})) { 8887 printMsg("WARNING", "empty dump"); 8888 } 8889 8890 my $MInfo = {}; 8891 my $MNum = 0; 8892 foreach my $Method (sort keys(%{$MethodInfo{1}})) 8893 { 8894 my $MId = $MNum; 8895 if($REPRODUCIBLE) { 8896 $MId = getMd5($Method); 8897 } 8898 $MInfo->{$MId} = $MethodInfo{1}{$Method}; 8899 $MInfo->{$MId}{"Name"} = $Method; 8900 8901 $MNum+=1; 8902 } 8903 8904 my $MUsed = {}; 8905 $MNum = 0; 8906 foreach my $Inv (sort keys(%{$MethodUsed{1}})) 8907 { 8908 my $MId = $MNum; 8909 if($REPRODUCIBLE) { 8910 $MId = getMd5($Inv); 8911 } 8912 8913 $MUsed->{$MId}{"Name"} = $Inv; 8914 $MUsed->{$MId}{"Used"} = $MethodUsed{1}{$Inv}; 8915 8916 $MNum+=1; 8917 } 8918 8919 my %API = ( 8920 "MethodInfo" => $MInfo, 8921 "TypeInfo" => $TypeInfo{1}, 8922 "MethodUsed" => $MUsed, 8923 # "FieldUsed" => $FieldUsed{1}, 8924 "LibraryVersion" => $Descriptor{1}{"Version"}, 8925 "LibraryName" => $TargetLibraryName, 8926 "Language" => "Java", 8927 "API_DUMP_VERSION" => $API_DUMP_VERSION, 8928 "JAPI_COMPLIANCE_CHECKER_VERSION" => $TOOL_VERSION 8929 ); 8930 8931 my $DumpPath = "api_dumps/$TargetLibraryName/".$TargetLibraryName."_".$Descriptor{1}{"Version"}.".api.".$AR_EXT; 8932 if($OutputDumpPath) 8933 { # user defined path 8934 $DumpPath = $OutputDumpPath; 8935 } 8936 8937 my $Archive = ($DumpPath=~s/\Q.$AR_EXT\E\Z//g); 8938 8939 my ($DDir, $DName) = separate_path($DumpPath); 8940 my $DPath = $TMP_DIR."/".$DName; 8941 if(not $Archive) { 8942 $DPath = $DumpPath; 8943 } 8944 8945 mkpath($DDir); 8946 8947 open(DUMP, ">", $DPath) || die ("can't open file \'$DPath\': $!\n"); 8948 print DUMP Dumper(\%API); 8949 close(DUMP); 8950 8951 if(not -s $DPath) { 8952 exitStatus("Error", "can't create API dump because something is going wrong with the Data::Dumper module"); 8953 } 8954 8955 if($Archive) { 8956 $DumpPath = createArchive($DPath, $DDir); 8957 } 8958 8959 if($OutputDumpPath) { 8960 printMsg("INFO", "dump path: $OutputDumpPath"); 4500 detectDefaultPaths(undef, "java"); 4501 createAPIDump(1); 4502 } 4503 4504 if(my $Dep = $In::Desc{1}{"DepDump"}) { 4505 mergeAPIs(1, readAPIDump(1, $Dep, "Dep")); 4506 } 4507 4508 if(isDump($In::Desc{2}{"Path"})) 4509 { 4510 $In::API{2} = readAPIDump(2, $In::Desc{2}{"Path"}, "Main"); 4511 initAliases(2); 4512 4513 if(my $V = $In::Desc{2}{"TargetVersion"}) { 4514 $In::Desc{2}{"Version"} = $V; 8961 4515 } 8962 4516 else { 8963 printMsg("INFO", "dump path: $DumpPath"); 8964 } 8965 exit(0); 8966 } 8967 if(not $Descriptor{1}{"Path"}) { 8968 exitStatus("Error", "-old option is not specified"); 8969 } 8970 if(not -e $Descriptor{1}{"Path"}) { 8971 exitStatus("Access_Error", "can't access \'".$Descriptor{1}{"Path"}."\'"); 8972 } 8973 if(not $Descriptor{2}{"Path"}) { 8974 exitStatus("Error", "-new option is not specified"); 8975 } 8976 if(not -e $Descriptor{2}{"Path"}) { 8977 exitStatus("Access_Error", "can't access \'".$Descriptor{2}{"Path"}."\'"); 8978 } 8979 8980 if($Quick) 8981 { 8982 $TypeProblems_Kind{"Binary"}{"Interface_Added_Super_Interface"} = "Low"; 8983 $TypeProblems_Kind{"Binary"}{"Abstract_Class_Added_Super_Abstract_Class"} = "Low"; 8984 $TypeProblems_Kind{"Binary"}{"Abstract_Class_Added_Super_Interface"} = "Low"; 8985 $TypeProblems_Kind{"Binary"}{"Abstract_Class_Added_Abstract_Method"} = "Low"; 8986 $TypeProblems_Kind{"Binary"}{"Interface_Added_Abstract_Method"} = "Low"; 8987 } 8988 8989 detect_default_paths(); 8990 8991 checkVersionNum(1, $Descriptor{1}{"Path"}); 8992 checkVersionNum(2, $Descriptor{2}{"Path"}); 8993 8994 createDescriptor(1, $Descriptor{1}{"Path"}); 8995 createDescriptor(2, $Descriptor{2}{"Path"}); 8996 8997 if(not $Descriptor{1}{"Archives"}) { 8998 exitStatus("Error", "descriptor d1 does not contain Java ARchives"); 8999 } 9000 if(not $Descriptor{2}{"Archives"}) { 9001 exitStatus("Error", "descriptor d2 does not contain Java ARchives"); 9002 } 9003 initLogging(1); 9004 initLogging(2); 9005 9006 if($Descriptor{1}{"Archives"} 9007 and not $Descriptor{1}{"Dump"}) { 9008 readArchives(1); 9009 } 9010 if($Descriptor{2}{"Archives"} 9011 and not $Descriptor{2}{"Dump"}) { 9012 readArchives(2); 9013 } 4517 $In::Desc{2}{"Version"} = $In::API{2}{"LibraryVersion"}; 4518 } 4519 } 4520 else 4521 { 4522 loadModule("APIDump"); 4523 4524 checkVersionNum(2, $In::Desc{2}{"Path"}); 4525 readDesc(createDesc($In::Desc{2}{"Path"}, 2), 2); 4526 4527 initLogging(2); 4528 detectDefaultPaths(undef, "java"); 4529 createAPIDump(2); 4530 } 4531 4532 if(my $Dep = $In::Desc{2}{"DepDump"}) { 4533 mergeAPIs(2, readAPIDump(2, $Dep, "Dep")); 4534 } 4535 4536 prepareData(1); 4537 prepareData(2); 9014 4538 9015 4539 foreach my $Inv (keys(%{$MethodUsed{2}})) … … 9059 4583 } 9060 4584 } 9061 9062 prepareMethods(1); 9063 prepareMethods(2); 4585 } 4586 4587 sub scenario() 4588 { 4589 setTarget("default"); 4590 4591 initAliases(1); 4592 initAliases(2); 4593 4594 $In::Opt{"OrigDir"} = cwd(); 4595 $In::Opt{"Tmp"} = tempdir(CLEANUP=>1); 4596 $In::Opt{"Reproducible"} = 1; 4597 4598 $In::Opt{"JoinReport"} = 1; 4599 $In::Opt{"DoubleReport"} = 0; 4600 4601 if($In::Opt{"BinaryOnly"} and $In::Opt{"SourceOnly"}) 4602 { # both --binary and --source 4603 # is the default mode 4604 $In::Opt{"DoubleReport"} = 1; 4605 $In::Opt{"JoinReport"} = 0; 4606 $In::Opt{"BinaryOnly"} = 0; 4607 $In::Opt{"SourceOnly"} = 0; 4608 if($In::Opt{"OutputReportPath"}) 4609 { # --report-path 4610 $In::Opt{"DoubleReport"} = 0; 4611 $In::Opt{"JoinReport"} = 1; 4612 } 4613 } 4614 elsif($In::Opt{"BinaryOnly"} or $In::Opt{"SourceOnly"}) 4615 { # --binary or --source 4616 $In::Opt{"DoubleReport"} = 0; 4617 $In::Opt{"JoinReport"} = 0; 4618 } 4619 if(defined $In::Opt{"Help"}) 4620 { 4621 helpMsg(); 4622 exit(0); 4623 } 4624 if(defined $In::Opt{"ShowVersion"}) 4625 { 4626 printMsg("INFO", "Java API Compliance Checker (JAPICC) $TOOL_VERSION\nCopyright (C) 2017 Andrey Ponomarenko's ABI Laboratory\nLicense: LGPL or GPL <http://www.gnu.org/licenses/>\nThis program is free software: you can redistribute it and/or modify it.\n\nWritten by Andrey Ponomarenko."); 4627 exit(0); 4628 } 4629 if(defined $In::Opt{"DumpVersion"}) 4630 { 4631 printMsg("INFO", $TOOL_VERSION); 4632 exit(0); 4633 } 4634 $Data::Dumper::Sortkeys = 1; 4635 4636 # FIXME: can't pass \&dumpSorting - cause a segfault sometimes 4637 if($In::Opt{"SortDump"}) 4638 { 4639 $Data::Dumper::Useperl = 1; 4640 $Data::Dumper::Sortkeys = \&dumpSorting; 4641 } 4642 4643 if(defined $In::Opt{"TestTool"}) 4644 { 4645 detectDefaultPaths("bin", "java"); 4646 loadModule("RegTests"); 4647 testTool(); 4648 exit(0); 4649 } 4650 4651 if(defined $In::Opt{"ShortMode"}) 4652 { 4653 if(not defined $In::Opt{"AffectLimit"}) { 4654 $In::Opt{"AffectLimit"} = 10; 4655 } 4656 } 4657 4658 if(not $In::Opt{"TargetLib"} and not $In::Opt{"CountMethods"}) 4659 { 4660 if($In::Opt{"DumpAPI"}) 4661 { 4662 if($In::Opt{"DumpAPI"}=~/\.jar\Z/) 4663 { # short usage 4664 my ($Name, $Version) = getPkgVersion(getFilename($In::Opt{"DumpAPI"})); 4665 if($Name and $Version ne "") 4666 { 4667 $In::Opt{"TargetLib"} = $Name; 4668 if(not $In::Desc{1}{"TargetVersion"}) { 4669 $In::Desc{1}{"TargetVersion"} = $Version; 4670 } 4671 } 4672 } 4673 } 4674 else 4675 { 4676 if($In::Desc{1}{"Path"}=~/\.jar\Z/ and $In::Desc{2}{"Path"}=~/\.jar\Z/) 4677 { # short usage 4678 my ($Name1, $Version1) = getPkgVersion(getFilename($In::Desc{1}{"Path"})); 4679 my ($Name2, $Version2) = getPkgVersion(getFilename($In::Desc{2}{"Path"})); 4680 4681 if($Name1 and $Version1 ne "" 4682 and $Version2 ne "") 4683 { 4684 $In::Opt{"TargetLib"} = $Name1; 4685 if(not $In::Desc{1}{"TargetVersion"}) { 4686 $In::Desc{1}{"TargetVersion"} = $Version1; 4687 } 4688 if(not $In::Desc{2}{"TargetVersion"}) { 4689 $In::Desc{2}{"TargetVersion"} = $Version2; 4690 } 4691 } 4692 } 4693 } 4694 4695 if(not $In::Opt{"TargetLib"}) { 4696 exitStatus("Error", "library name is not selected (option --lib=NAME)"); 4697 } 4698 } 4699 else 4700 { # validate library name 4701 if($In::Opt{"TargetLib"}=~/[\*\/\\]/) { 4702 exitStatus("Error", "\"\\\", \"\/\" and \"*\" symbols are not allowed in the library name"); 4703 } 4704 } 4705 if(not $In::Opt{"TargetTitle"}) { 4706 $In::Opt{"TargetTitle"} = $In::Opt{"TargetLib"}; 4707 } 4708 if(my $ClassListPath = $In::Opt{"ClassListPath"}) 4709 { 4710 if(not -f $ClassListPath) { 4711 exitStatus("Access_Error", "can't access file \'$ClassListPath\'"); 4712 } 4713 foreach my $Class (split(/\n/, readFile($ClassListPath))) 4714 { 4715 $Class=~s/\//./g; 4716 $In::Opt{"ClassList_User"}{$Class} = 1; 4717 } 4718 } 4719 if(my $AnnotationsListPath = $In::Opt{"AnnotationsListPath"}) 4720 { 4721 if(not -f $AnnotationsListPath) { 4722 exitStatus("Access_Error", "can't access file \'$AnnotationsListPath\'"); 4723 } 4724 foreach my $Annotation (split(/\n/, readFile($AnnotationsListPath))) 4725 { 4726 $In::Opt{"AnnotationList_User"}{$Annotation} = 1; 4727 } 4728 } 4729 if(my $SkipAnnotationsListPath = $In::Opt{"SkipAnnotationsListPath"}) 4730 { 4731 if(not -f $SkipAnnotationsListPath) { 4732 exitStatus("Access_Error", "can't access file \'$SkipAnnotationsListPath\'"); 4733 } 4734 foreach my $Annotation (split(/\n/, readFile($SkipAnnotationsListPath))) 4735 { 4736 $In::Opt{"SkipAnnotationList_User"}{$Annotation} = 1; 4737 } 4738 } 4739 if(my $SkipClassesList = $In::Opt{"SkipClassesList"}) 4740 { 4741 if(not -f $SkipClassesList) { 4742 exitStatus("Access_Error", "can't access file \'$SkipClassesList\'"); 4743 } 4744 foreach my $Class (split(/\n/, readFile($SkipClassesList))) 4745 { 4746 $Class=~s/\//./g; 4747 $In::Opt{"SkipClasses"}{$Class} = 1; 4748 } 4749 } 4750 if(my $SkipPackagesList = $In::Opt{"SkipPackagesList"}) 4751 { 4752 if(not -f $SkipPackagesList) { 4753 exitStatus("Access_Error", "can't access file \'$SkipPackagesList\'"); 4754 } 4755 foreach my $Package (split(/\n/, readFile($SkipPackagesList))) 4756 { 4757 $In::Desc{1}{"SkipPackages"}{$Package} = 1; 4758 $In::Desc{2}{"SkipPackages"}{$Package} = 1; 4759 } 4760 } 4761 if(my $ClientPath = $In::Opt{"ClientPath"}) 4762 { 4763 if($ClientPath=~/\.class\Z/) { 4764 exitStatus("Error", "input file is not a java archive"); 4765 } 4766 4767 if(-f $ClientPath) 4768 { 4769 detectDefaultPaths("bin", undef); 4770 readArchive(0, $ClientPath) 4771 } 4772 else { 4773 exitStatus("Access_Error", "can't access file \'$ClientPath\'"); 4774 } 4775 } 4776 4777 if(my $DPath = $In::Opt{"CountMethods"}) 4778 { 4779 if(not -e $DPath) { 4780 exitStatus("Access_Error", "can't access \'$DPath\'"); 4781 } 4782 4783 $In::API{1} = readAPIDump(1, $DPath, "Main"); 4784 initAliases(1); 4785 4786 my $Count = 0; 4787 foreach my $Method (keys(%{$MethodInfo{1}})) { 4788 $Count += methodFilter($Method, 1); 4789 } 4790 4791 printMsg("INFO", $Count); 4792 exit(0); 4793 } 4794 4795 if($In::Opt{"DumpAPI"}) 4796 { 4797 createAPIFile(1, $In::Opt{"DumpAPI"}); 4798 exit(0); 4799 } 4800 4801 compareInit(); 4802 4803 readRules("Binary"); 4804 readRules("Source"); 9064 4805 9065 4806 detectAdded(); 9066 4807 detectRemoved(); 9067 4808 9068 printMsg("INFO", " comparing classes ...");4809 printMsg("INFO", "Comparing classes ..."); 9069 4810 mergeClasses(); 9070 4811 mergeMethods(); 9071 4812 9072 foreach my $M (keys(%CompatProblems))9073 {9074 foreach my $K (keys(%{$CompatProblems{$M}}))9075 {9076 foreach my $L (keys(%{$CompatProblems{$M}{$K}}))9077 {9078 if(my $T = $CompatProblems{$M}{$K}{$L}{"Type_Name"}) {9079 $TypeProblemsIndex{$T}{$M} = 1;9080 }9081 }9082 }9083 }9084 9085 4813 printReport(); 9086 4814 9087 4815 if($RESULT{"Source"}{"Problems"} + $RESULT{"Binary"}{"Problems"}) { 9088 exit( $ERROR_CODE{"Incompatible"});4816 exit(getErrorCode("Incompatible")); 9089 4817 } 9090 4818 else { 9091 exit( $ERROR_CODE{"Compatible"});4819 exit(getErrorCode("Compatible")); 9092 4820 } 9093 4821 }
Note:
See TracChangeset
for help on using the changeset viewer.