Changeset 11682 in josm
- 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