Ignore:
Timestamp:
2018-04-02T23:20:00+02:00 (7 years ago)
Author:
Don-vip
Message:

tools update: Groovy 2.4.15, PMD 6.2.0, JAPICC 2.4

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/tools/japicc/japi-compliance-checker.pl

    r12872 r13595  
    11#!/usr/bin/perl
    2 ###########################################################################
    3 # Java API Compliance Checker (JAPICC) 2.3
     2#########################################################################
     3# Java API Compliance Checker (JAPICC) 2.4
    44# A tool for checking backward compatibility of a Java library API
    55#
    66# Written by Andrey Ponomarenko
    77#
    8 # Copyright (C) 2011-2017 Andrey Ponomarenko's ABI Laboratory
     8# Copyright (C) 2011-2018 Andrey Ponomarenko's ABI Laboratory
    99#
    1010# PLATFORMS
     
    1515# ============
    1616#  Linux, FreeBSD, Mac OS X
    17 #    - JDK or OpenJDK - development files (javap, javac)
     17#    - JDK or OpenJDK - development files (javap, javac, jar, jmod)
    1818#    - Perl 5 (5.8 or newer)
    1919#
    2020#  MS Windows
    21 #    - JDK or OpenJDK (javap, javac)
     21#    - JDK or OpenJDK (javap, javac, jar, jmod)
    2222#    - Active Perl 5 (5.8 or newer)
    2323#
    24 # This program is free software: you can redistribute it and/or modify
    25 # it under the terms of the GNU General Public License or the GNU Lesser
    26 # General Public License as published by the Free Software Foundation.
     24# This library is free software; you can redistribute it and/or
     25# modify it under the terms of the GNU Lesser General Public
     26# License as published by the Free Software Foundation; either
     27# version 2.1 of the License, or (at your option) any later version.
    2728#
    28 # This program is distributed in the hope that it will be useful,
     29# This library is distributed in the hope that it will be useful,
    2930# but WITHOUT ANY WARRANTY; without even the implied warranty of
    30 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    31 # GNU General Public License for more details.
     31# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     32# Lesser General Public License for more details.
    3233#
    33 # You should have received a copy of the GNU General Public License
    34 # and the GNU Lesser General Public License along with this program.
    35 # If not, see <http://www.gnu.org/licenses/>.
    36 ###########################################################################
     34# You should have received a copy of the GNU Lesser General Public
     35# License along with this library; if not, write to the Free Software
     36# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
     37# MA  02110-1301  USA.
     38#########################################################################
    3739use Getopt::Long;
    3840Getopt::Long::Configure ("posix_default", "no_ignore_case", "permute");
     
    4345use Data::Dumper;
    4446
    45 my $TOOL_VERSION = "2.3";
    46 my $API_DUMP_VERSION = "2.2";
     47my $TOOL_VERSION = "2.4";
     48my $API_DUMP_VERSION = "2.4";
    4749my $API_DUMP_VERSION_MIN = "2.2";
    4850
     
    7880my $ShortUsage = "Java API Compliance Checker (JAPICC) $TOOL_VERSION
    7981A tool for checking backward compatibility of a Java library API
    80 Copyright (C) 2017 Andrey Ponomarenko's ABI Laboratory
    81 License: GNU LGPL or GNU GPL
     82Copyright (C) 2018 Andrey Ponomarenko's ABI Laboratory
     83License: LGPLv2.1+
    8284
    8385Usage: $CmdName [options]
    84 Example: $CmdName OLD.jar NEW.jar
     86Example:
     87 $CmdName OLD.jar NEW.jar
     88 $CmdName OLD.jmod NEW.jmod
    8589
    8690More info: $CmdName --help";
     
    110114  "skip-internal-types=s" => \$In::Opt{"SkipInternalTypes"},
    111115  "dump|dump-api=s" => \$In::Opt{"DumpAPI"},
     116  "check-annotations!" => \$In::Opt{"CheckAnnotations"},
    112117  "check-packages=s" => \$In::Opt{"CheckPackages"},
    113118  "classes-list=s" => \$In::Opt{"ClassListPath"},
     
    117122  "skip-classes=s" => \$In::Opt{"SkipClassesList"},
    118123  "skip-packages=s" => \$In::Opt{"SkipPackagesList"},
     124  "non-impl=s" => \$In::Opt{"NonImplClassesList"},
     125  "non-impl-all!" => \$In::Opt{"NonImplAll"},
    119126  "short" => \$In::Opt{"ShortMode"},
    120127  "dump-path=s" => \$In::Opt{"OutputDumpPath"},
     
    189196
    190197  This tool is free software: you can redistribute it and/or modify it
    191   under the terms of the GNU LGPL or GNU GPL.
     198  under the terms of the GNU LGPL.
    192199
    193200USAGE:
    194201  $CmdName [options]
    195202
    196 EXAMPLE 1:
     203EXAMPLE (1):
    197204  $CmdName OLD.jar NEW.jar
    198205
    199 EXAMPLE 2:
     206EXAMPLE (2):
     207  $CmdName OLD.jmod NEW.jmod
     208
     209EXAMPLE (3):
    200210  $CmdName -lib NAME -old OLD.xml -new NEW.xml
    201211  OLD.xml and NEW.xml are XML-descriptors:
     
    206216   
    207217    <archives>
    208         /path1/to/JAR(s)/
    209         /path2/to/JAR(s)/
     218        /path1/to/JAR(s) OR JMOD(s)/
     219        /path2/to/JAR(s) OR JMOD(s)/
    210220        ...
    211221    </archives>
     
    229239      It may be one of the following:
    230240     
    231          1. Java archive (*.jar)
     241         1. Java archive (*.jar or *.jmod)
    232242         2. XML-descriptor (VERSION.xml file):
    233243
     
    237247             
    238248              <archives>
    239                   /path1/to/JAR(s)/
    240                   /path2/to/JAR(s)/
     249                  /path1/to/JAR(s) OR JMOD(s)/
     250                  /path2/to/JAR(s) OR JMOD(s)/
    241251                   ...
    242252              </archives>
     
    246256         3. API dump generated by -dump option
    247257
    248       If you are using *.jar as a descriptor then you should
    249       specify version numbers with -v1 and -v2 options too.
    250       If version numbers are not specified then the tool will
    251       try to detect them automatically.
     258      If you are using *.jar or *.jmod as a descriptor then
     259      you should specify version numbers with -v1 and -v2
     260      options too. If version numbers are not specified then
     261      the tool will try to detect them automatically.
    252262
    253263  -new|-d2 PATH
     
    304314      for debugging the tool. PATH is the path to the Java archive or
    305315      XML descriptor of the library.
     316 
     317  -check-annotations
     318      Check for changes in annotations like in any other interfaces.
    306319 
    307320  -check-packages PATTERN
     
    325338     
    326339  -skip-classes PATH
    327       This option allows to specify a file with a list
    328       of classes that should not be checked.
    329      
     340      List of classes that should not be checked.
     341 
    330342  -skip-packages PATH
    331       This option allows to specify a file with a list
    332       of packages that should not be checked.
    333      
     343      List of packages that should not be checked.
     344 
     345  -non-impl PATH
     346      List of interfaces that should not be implemented by users.
     347 
     348  -non-impl-all
     349      All interfaces should not be implemented by users.
     350 
    334351  -short
    335352      Do not list added/removed methods.
     
    805822                }
    806823            }
     824           
     825            if(defined $Class1->{"Annotation"})
     826            {
     827                my %AnnParam = ();
     828                foreach my $VN (1, 2)
     829                {
     830                    foreach my $Method (keys(%{$Class_Methods{$VN}{$ClassName}}))
     831                    {
     832                        my $MInfo = $MethodInfo{$VN}{$Method};
     833                        $AnnParam{$VN}{$MInfo->{"ShortName"}} = {"Default"=>$MInfo->{"Default"}, "Return"=>getTypeName($MInfo->{"Return"}, $VN)};
     834                    }
     835                }
     836                foreach my $AParam (sort keys(%{$AnnParam{1}}))
     837                {
     838                    my $R1 = $AnnParam{1}{$AParam}{"Return"};
     839                    my $D1 = $AnnParam{1}{$AParam}{"Default"};
     840                   
     841                    if(defined $AnnParam{2}{$AParam})
     842                    {
     843                        my $R2 = $AnnParam{2}{$AParam}{"Return"};
     844                        my $D2 = $AnnParam{2}{$AParam}{"Default"};
     845                       
     846                        if($R1 ne $R2)
     847                        {
     848                            if($R1 eq "java.lang.String" and $R2 eq "java.lang.String[]")
     849                            {
     850                                %{$CompatProblems{".client_method"}{"Annotation_Element_Changed_Type_Safe"}{$AParam}} = (
     851                                    "Type_Name"=>$ClassName,
     852                                    "Old_Value"=>$R1,
     853                                    "New_Value"=>$R2,
     854                                    "Target"=>$AParam);
     855                            }
     856                            else
     857                            {
     858                                %{$CompatProblems{".client_method"}{"Annotation_Element_Changed_Type"}{$AParam}} = (
     859                                    "Type_Name"=>$ClassName,
     860                                    "Old_Value"=>$R1,
     861                                    "New_Value"=>$R2,
     862                                    "Target"=>$AParam);
     863                            }
     864                        }
     865                       
     866                        if(defined $D1 and not defined $D2)
     867                        {
     868                            %{$CompatProblems{".client_method"}{"Annotation_Element_Removed_Default_Value"}{$AParam}} = (
     869                                "Type_Name"=>$ClassName,
     870                                "Old_Value"=>$D1,
     871                                "Target"=>$AParam);
     872                        }
     873                        elsif(not defined $D1 and defined $D2)
     874                        {
     875                            %{$CompatProblems{".client_method"}{"Annotation_Element_Added_Default_Value"}{$AParam}} = (
     876                                "Type_Name"=>$ClassName,
     877                                "New_Value"=>$D2,
     878                                "Target"=>$AParam);
     879                        }
     880                        elsif($D1 ne $D2)
     881                        {
     882                            %{$CompatProblems{".client_method"}{"Annotation_Element_Changed_Default_Value"}{$AParam}} = (
     883                                "Type_Name"=>$ClassName,
     884                                "Old_Value"=>$D1,
     885                                "New_Value"=>$D2,
     886                                "Target"=>$AParam);
     887                        }
     888                    }
     889                    else
     890                    {
     891                        if(defined $D1)
     892                        {
     893                            %{$CompatProblems{".client_method"}{"Removed_Annotation_Default_Element"}{$AParam}} = (
     894                                "Type_Name"=>$ClassName,
     895                                "Elem_Type"=>$R1,
     896                                "Old_Value"=>$D1,
     897                                "Target"=>$AParam);
     898                        }
     899                        else
     900                        {
     901                            %{$CompatProblems{".client_method"}{"Removed_Annotation_NonDefault_Element"}{$AParam}} = (
     902                                "Type_Name"=>$ClassName,
     903                                "Elem_Type"=>$R1,
     904                                "Target"=>$AParam);
     905                        }
     906                    }
     907                }
     908               
     909                foreach my $AParam (sort keys(%{$AnnParam{2}}))
     910                {
     911                    if(not defined $AnnParam{1}{$AParam})
     912                    {
     913                        my $R2 = $AnnParam{2}{$AParam}{"Return"};
     914                       
     915                        if(defined $AnnParam{2}{$AParam}{"Default"})
     916                        {
     917                            my $D2 = $AnnParam{2}{$AParam}{"Default"};
     918                            %{$CompatProblems{".client_method"}{"Added_Annotation_Default_Element"}{$AParam}} = (
     919                                "Type_Name"=>$ClassName,
     920                                "Elem_Type"=>$R2,
     921                                "New_Value"=>$D2,
     922                                "Target"=>$AParam);
     923                        }
     924                        else
     925                        {
     926                            %{$CompatProblems{".client_method"}{"Added_Annotation_NonDefault_Element"}{$AParam}} = (
     927                                "Type_Name"=>$ClassName,
     928                                "Elem_Type"=>$R2,
     929                                "Target"=>$AParam);
     930                        }
     931                    }
     932                }
     933            }
    807934        }
    808935        else
     
    10511178        else
    10521179        {
    1053             if(my @InvokedBy = sort keys(%{$MethodUsed{2}{$AddedMethod}}))
     1180            if(nonImplClass(\%Type1))
     1181            {
     1182                %{$SubProblems{"NonImpl_Interface_Added_Abstract_Method"}{getSFormat($AddedMethod)}} = (
     1183                    "Type_Name"=>$Type1{"Name"},
     1184                    "Type_Type"=>$Type1{"Type"},
     1185                    "Target"=>$AddedMethod);
     1186            }
     1187            elsif(my @InvokedBy = sort keys(%{$MethodUsed{2}{$AddedMethod}}))
    10541188            {
    10551189                %{$SubProblems{"Interface_Added_Abstract_Method_Invoked_By_Others"}{getSFormat($AddedMethod)}} = (
     
    17541888       
    17551889        my $ClassId1 = $MethodInfo{1}{$Method}{"Class"};
    1756         my $Class1_Name = getTypeName($ClassId1, 1);
    1757         my $Class1_Type = getTypeType($ClassId1, 1);
     1890        my $Class1 = getType($ClassId1, 1);
     1891       
     1892        if(not defined $In::Opt{"CheckAnnotations"} and $Class1->{"Annotation"}) {
     1893            next;
     1894        }
     1895       
     1896        my $Class1_Name = $Class1->{"Name"};
     1897        my $Class1_Type = $Class1->{"Type"};
    17581898       
    17591899        $CheckedTypes{$Class1_Name} = 1;
     
    25202660    foreach my $Method (sort keys(%CompatProblems))
    25212661    {
    2522         foreach my $Kind (keys(%{$CompatProblems{$Method}}))
     2662        foreach my $Kind (sort keys(%{$CompatProblems{$Method}}))
    25232663        {
    25242664            if(not defined $CompatRules{"Binary"}{$Kind} and not defined $CompatRules{"Source"}{$Kind})
     
    25272667                { # only one warning
    25282668                    printMsg("WARNING", "unknown rule \"$Kind\" (\"$Level\")");
    2529                     $UnknownRules{$Level}{$Kind}=1;
     2669                    $UnknownRules{$Level}{$Kind} = 1;
    25302670                }
    25312671            }
     
    26942834    $Checked_Archives_Link = "<a href='#Checked_Archives' style='color:Blue;'>".keys(%{$LibArchives{1}})."</a>" if(keys(%{$LibArchives{1}})>0);
    26952835   
    2696     $TestResults .= "<tr><th>Total JARs</th><td>$Checked_Archives_Link</td></tr>\n";
     2836    $TestResults .= "<tr><th>Total Java Modules</th><td>$Checked_Archives_Link</td></tr>\n";
    26972837    $TestResults .= "<tr><th>Total Methods / Classes</th><td>".keys(%CheckedMethods)." / ".keys(%CheckedTypes)."</td></tr>\n";
    26982838   
     
    33633503{
    33643504    my ($Name, $Html, $LVer) = @_;
    3365     my $TType = $TypeInfo{$LVer}{$TName_Tid{$LVer}{$Name}}{"Type"};
     3505    my $TInfo = $TypeInfo{$LVer}{$TName_Tid{$LVer}{$Name}};
     3506    my $TType = $TInfo->{"Type"};
     3507   
     3508    if($TInfo->{"Annotation"}) {
     3509        $TType = '@'.$TType;
     3510    }
     3511   
    33663512    if($Html) {
    33673513        $Name = "<span class='ttype'>".$TType."</span> ".specChars($Name);
     
    38944040    $Head .= "<head>\n";
    38954041    $Head .= "<meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\" />\n";
     4042    $Head .= "<meta name=\"viewport\" content=\"width=device-width,initial-scale=1\" />\n";
    38964043    $Head .= "<meta name=\"keywords\" content=\"$Keywords\" />\n";
    38974044    $Head .= "<meta name=\"description\" content=\"$Description\" />\n";
     
    39734120           
    39744121            my $Class = getType($MethodInfo{2}{$Method}{"Class"}, 2);
     4122           
     4123            if(not defined $In::Opt{"CheckAnnotations"} and $Class->{"Annotation"}) {
     4124                next;
     4125            }
    39754126           
    39764127            $CheckedTypes{$Class->{"Name"}} = 1;
     
    40484199            my $Class = getType($MethodInfo{1}{$Method}{"Class"}, 1);
    40494200           
     4201            if(not defined $In::Opt{"CheckAnnotations"} and $Class->{"Annotation"}) {
     4202                next;
     4203            }
     4204           
    40504205            $CheckedTypes{$Class->{"Name"}} = 1;
    40514206            $CheckedMethods{$Method} = 1;
     
    40794234}
    40804235
    4081 sub getArchivePaths($$)
    4082 {
    4083     my ($Dest, $LVer) = @_;
    4084     if(-f $Dest) {
    4085         return ($Dest);
    4086     }
    4087     elsif(-d $Dest)
    4088     {
    4089         $Dest=~s/[\/\\]+\Z//g;
    4090         next if(not $Dest);
    4091        
    4092         my @Archives = ();
    4093         foreach my $Path (cmdFind($Dest, "", "*\\.jar"))
    4094         {
    4095             next if(ignorePath($Path, $Dest));
    4096             push(@Archives, realpath_F($Path));
    4097         }
    4098         return @Archives;
    4099     }
    4100     return ();
    4101 }
    4102 
    41034236sub isCyclical($$) {
    41044237    return (grep {$_ eq $_[1]} @{$_[0]});
     
    42064339    }
    42074340   
    4208     if($Path!~/\.jar\Z/i) {
     4341    if($Path!~/\.(jar|jmod)\Z/i) {
    42094342        return;
    42104343    }
     
    42124345    my $Ver = undef;
    42134346   
    4214     if(not defined $Ver) {
    4215         $Ver = getManifestVersion(getAbsPath($Path));
     4347    if($Path=~/\.jar\Z/i)
     4348    {
     4349        if(not defined $Ver) {
     4350            $Ver = getManifestVersion(getAbsPath($Path));
     4351        }
    42164352    }
    42174353   
     
    48755011    if(defined $In::Opt{"ShowVersion"})
    48765012    {
    4877         printMsg("INFO", "Java API Compliance Checker (JAPICC) $TOOL_VERSION\nCopyright (C) 2017 Andrey Ponomarenko's ABI Laboratory\nLicense: LGPL or GPL <http://www.gnu.org/licenses/>\nThis program is free software: you can redistribute it and/or modify it.\n\nWritten by Andrey Ponomarenko.");
     5013        printMsg("INFO", "Java API Compliance Checker (JAPICC) $TOOL_VERSION\nCopyright (C) 2018 Andrey Ponomarenko's ABI Laboratory\nLicense: LGPLv2.1+ <http://www.gnu.org/licenses/>\nThis program is free software: you can redistribute it and/or modify it.\n\nWritten by Andrey Ponomarenko.");
    48785014        exit(0);
    48795015    }
     
    49115047        if($In::Opt{"DumpAPI"})
    49125048        {
    4913             if($In::Opt{"DumpAPI"}=~/\.jar\Z/)
     5049            if($In::Opt{"DumpAPI"}=~/\.(jar|jmod)\Z/)
    49145050            { # short usage
    49155051                my ($Name, $Version) = getPkgVersion(getFilename($In::Opt{"DumpAPI"}));
     
    49255061        else
    49265062        {
    4927             if($In::Desc{1}{"Path"}=~/\.jar\Z/ and $In::Desc{2}{"Path"}=~/\.jar\Z/)
     5063            if($In::Desc{1}{"Path"}=~/\.(jar|jmod)\Z/ and $In::Desc{2}{"Path"}=~/\.(jar|jmod)\Z/)
    49285064            { # short usage
    49295065                my ($Name1, $Version1) = getPkgVersion(getFilename($In::Desc{1}{"Path"}));
     
    49995135        }
    50005136    }
     5137    if(my $NonImplClassesList = $In::Opt{"NonImplClassesList"})
     5138    {
     5139        if(not -f $NonImplClassesList) {
     5140            exitStatus("Access_Error", "can't access file \'$NonImplClassesList\'");
     5141        }
     5142        foreach my $Class (split(/\n/, readFile($NonImplClassesList)))
     5143        {
     5144            $Class=~s/\//./g;
     5145            $In::Opt{"NonImplClasses"}{$Class} = 1;
     5146        }
     5147    }
    50015148    if(my $SkipPackagesList = $In::Opt{"SkipPackagesList"})
    50025149    {
Note: See TracChangeset for help on using the changeset viewer.