File Coverage

checks/java.pm
Criterion Covered Total %
statement 44 116 37.9
branch 7 78 8.9
condition 8 52 15.3
subroutine 8 11 72.7
total 67 257 26.0


line stmt bran cond sub time code
1           # java -- lintian check script -*- perl -*-
2            
3           # Copyright (C) 2011 Vincent Fourmond
4           #
5           # This program is free software; you can redistribute it and/or modify
6           # it under the terms of the GNU General Public License as published by
7           # the Free Software Foundation; either version 2 of the License, or
8           # (at your option) any later version.
9           #
10           # This program is distributed in the hope that it will be useful,
11           # but WITHOUT ANY WARRANTY; without even the implied warranty of
12           # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13           # GNU General Public License for more details.
14           #
15           # You should have received a copy of the GNU General Public License
16           # along with this program. If not, you can find it on the World Wide
17           # Web at http://www.gnu.org/copyleft/gpl.html, or write to the Free
18           # Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
19           # MA 02110-1301, USA.
20            
21           package Lintian::java;
22 2963     2963 26685 use strict;
  2963       10383  
  2963       131669  
23 2963     2963 23621 use warnings;
  2963       9238  
  2963       147498  
24 2963     2963 24014 use autodie;
  2963       8786  
  2963       29772  
25            
26 2963     2963 27346904 use List::MoreUtils qw(any none);
  2963       13156  
  2963       57027  
27 2963     2963 2902827 use Lintian::Data ();
  2963       10195  
  2963       107205  
28            
29 2963     2963 25545 use Lintian::Tags qw(tag);
  2963       9067  
  2963       481051  
30 2963     2963 27210 use Lintian::Util qw(normalize_pkg_path);
  2963       9250  
  2963       7981923  
31            
32           our $MAX_BYTECODE = Lintian::Data->new('java/constants', qr/\s*=\s*/o);
33            
34           sub run {
35 5543     5543 26890 my ($pkg, undef, $info) = @_;
36 5543       122150 my $java_info = $info->java_info;
37 5543       20590 my $missing_jarwrapper = 0;
38 5543       17564 my $need_cp = 0;
39 5543       16688 my $has_public_jars = 0;
40 5543       17218 my $has_jars = 0;
41 5543       26780 my $jmajlow = '-';
42            
43 5543       34308 my $depends = $info->relation('strong')->unparse;
44           # Remove all libX-java-doc packages to avoid thinking they are java libs
45           # - note the result may not be a valid dependency listing
46 5543       30127 $depends =~ s/lib[^\s,]+-java-doc//go;
47            
48 5543       28161 my @java_lib_depends = ($depends =~ m/\b(lib[^\s,]+-java)\b/og);
49            
50 5543 50     31659 $need_cp = 1 if @java_lib_depends;
51            
52           # We first loop over jar files to find problems
53            
54 5543       21949 for my $jar_file (sort keys %{$java_info}) {
  5543       48051  
55 0       0 my $files = $java_info->{$jar_file}{files};
56 0       0 my $manifest = $java_info->{$jar_file}{manifest};
57 0       0 my $operm = $info->index($jar_file)->operm;
58 0       0 my $jar_dir;
59 0       0 my $classes = 0;
60 0       0 my $datafiles = 1;
61 0       0 my $cp = '';
62 0       0 my $bsname = '';
63            
64 0 0     0 if (exists $java_info->{$jar_file}{error}) {
65 0       0 tag 'zip-parse-error', "$jar_file:",$java_info->{$jar_file}{error};
66 0       0 next;
67           }
68            
69           # The Java Policy says very little about requires for (jars in) JVMs
70 0 0     0 next if $jar_file =~ m#usr/lib/jvm(?:-exports)?/[^/]++/#o;
71           # Ignore Mozilla's jar files, see #635495
72 0 0     0 next if $jar_file =~ m#usr/lib/xul(?:-ext|runner[^/]*+)/#o;
73            
74 0       0 $jar_dir = $jar_file;
75 0       0 $jar_dir =~ s,[^/]+$,,o;
76 0       0 $has_jars = 1;
77            
78 0 0     0 if($jar_file =~ m#^usr/share/java/[^/]+\.jar$#o) {
79 0       0 $has_public_jars = 1;
80           }
81           # check for common code files like .class or .clj (Clojure files)
82 0       0 foreach my $class (grep { m/\.(?:class|clj)$/oi } sort keys %{$files}){
  0       0  
  0       0  
83 0       0 my $mver = $files->{$class};
84 0       0 $classes = 1;
85 0 0     0 next if $class =~ m/\.clj$/;
86           # .class but no major version?
87 0 0     0 next if $mver eq '-';
88 0 0 0   0 if ( $mver <= $MAX_BYTECODE->value('min-bytecode-version') - 1
89           or $mver
90           > $MAX_BYTECODE->value('max-bytecode-existing-version')) {
91           # First public major version was 45 (Java1), latest
92           # version is 52 (Java8).
93 0       0 tag 'unknown-java-class-version', $jar_file,
94           "($class -> $mver)";
95           # Skip the rest of this Jar.
96 0       0 last;
97           }
98            
99           # Collect the "lowest" Class version used. We assume that
100           # mixed class formats implies special compat code for certain
101           # JVM cases.
102 0 0     0 if ($jmajlow eq '-') {
103           # first;
104 0       0 $jmajlow = $mver;
105           } else {
106 0 0     0 $jmajlow = $mver if $mver < $jmajlow;
107           }
108           }
109            
110           $datafiles = 0
111 0 0   0 0 if none { m/\.(?:xml|properties|x?html|xhp)$/io } keys %$files;
  0       0  
112            
113 0 0     0 if($operm & 0111) {
    0        
114           # Executable ?
115           tag 'executable-jar-without-main-class', $jar_file
116 0 0 0   0 unless $manifest && $manifest->{'Main-Class'};
117            
118           # Here, we need to check that the package depends on
119           # jarwrapper.
120 0 0     0 $missing_jarwrapper = 1
121           unless $info->relation('strong')->implies('jarwrapper');
122           } elsif ($jar_file !~ m#^usr/share/#) {
123 0       0 tag 'jar-not-in-usr-share', $jar_file;
124           }
125            
126 0 0 0   0 $cp = $manifest->{'Class-Path'}//'' if $manifest;
127 0 0 0   0 $bsname = $manifest->{'Bundle-SymbolicName'}//'' if $manifest;
128            
129 0 0     0 if ($manifest) {
    0        
130 0 0     0 if (!$classes) {
131            
132           # Eclipse / OSGi bundles are sometimes source bundles
133           # these do not ship classes but java files and other sources.
134           # Javadoc jars deployed in the Maven repository also do not ship
135           # classes but HTML files, images and CSS files
136 0 0 0   0 if ((
      0      
137           $bsname !~ m/\.source$/o
138           && $jar_file!~ m#^usr/share/maven-repo/.*-javadoc\.jar#
139           && $jar_file!~m#\.doc(?:\.(?:user|isv))?_[^/]+.jar#
140           && $jar_file!~m#\.source_[^/]+.jar#
141           )
142           || $cp
143           ) {
144 0       0 tag 'codeless-jar', $jar_file;
145           }
146           }
147           } elsif ($classes) {
148 0       0 tag 'missing-manifest', $jar_file;
149           }
150            
151 0 0     0 if (!$cp) {
152           # Do we have OSGi instead?
153 0 0     0 $need_cp = 0 if $bsname;
154           # Maybe it is a maven plugin?
155           $need_cp = 0
156           if $need_cp
157 0 0 0 0 0 && any { m,^META-INF/maven/plugin.xml$,io } keys %$files;
  0       0  
158           } else {
159           # Only run the tests when a classpath is present
160 0       0 my @relative;
161 0       0 my @paths = split(m/\s++/o, $cp);
162 0       0 $need_cp = 0;
163 0       0 for my $p (@paths) {
164 0 0     0 if ($p) {
165           # Strip leading ./
166 0       0 $p =~ s#^\./++##og;
167 0 0 0   0 if ($p !~ m#^(?:file://)?/#o and $p =~ m#/#o) {
168 0       0 my $target = normalize_pkg_path($jar_dir, $p);
169 0       0 my $tinfo;
170           # Can it be normalized?
171 0 0     0 next unless defined($target);
172           # Relative link to usr/share/java ? Works if
173           # we are depending of a Java library.
174           next
175 0 0 0   0 if $target =~ m,^usr/share/java/[^/]+.jar$,o
176           and @java_lib_depends;
177 0       0 $tinfo = $info->index($target);
178           # Points to file or link in this package,
179           # which is sometimes easier than
180           # re-writing the classpath.
181           next
182 0 0 0   0 if defined $tinfo
      0      
183           and ($tinfo->is_symlink or $tinfo->is_file);
184           # Relative path with subdirectories.
185 0       0 push @relative, $p;
186           }
187           # @todo add an info tag for relative paths, to educate
188           # maintainers ?
189           }
190           }
191            
192 0 0     0 tag 'classpath-contains-relative-path',
193           "$jar_file: " . join(', ', @relative)
194           if @relative;
195           }
196            
197 0 0 0   0 if ( $has_public_jars
      0      
198           && $pkg =~ /^lib.*maven.*plugin.*/
199           && $jar_file !~ m#^usr/share/maven-repo/.*\.jar#) {
200           # Trigger a warning when a maven plugin lib is installed in
201           # /usr/share/java/
202 0       0 tag 'maven-plugin-in-usr-share-java', $jar_file;
203           }
204            
205           }
206            
207 5543 50     36160 tag 'missing-dep-on-jarwrapper' if $missing_jarwrapper;
208            
209 5543 50     32781 if ($jmajlow ne '-') {
210           # Byte code numbers:
211           # 45-49 -> Java1 - Java5 (Always ok)
212           # 50 -> Java6
213           # 51 -> Java7
214           # 52 -> Java8
215 0       0 my $bad = 0;
216            
217           # If the lowest version used is greater than the requested
218           # limit, then flag it.
219 0 0     0 $bad = 1
220           if $jmajlow > $MAX_BYTECODE->value('max-bytecode-version');
221            
222           # Technically we ought to do some checks with Java6 class
223           # files and dependencies/package types, but for now just skip
224           # that. (See #673276)
225            
226 0 0     0 if ($bad) {
227           # Map the Class version to a Java version.
228 0       0 my $v = $jmajlow - 44;
229 0       0 tag 'incompatible-java-bytecode-format',
230           "Java${v} version (Class format: $jmajlow)";
231           }
232           }
233            
234 5543 0 33   49002 if ($has_jars && $need_cp && $pkg =~ /^lib[^\s,]+-java$/) {
      33      
235           # Only tag if there is at least one jar file and one strong
236           # java dependency and no classpath/osgi. Technically there
237           # should be no reason to have a strong relation with a java
238           # library without having a jar file, but we ignore some jars
239           # (e.g. in JVMs) so going safe here.
240 0       0 tag 'missing-classpath', join(', ', @java_lib_depends);
241           }
242            
243 5543       38592 my $is_transitional = $info->is_pkg_class('transitional');
244 5543 100 66   145404 if (!$has_public_jars && !$is_transitional && $pkg =~ /^lib[^\s,]+-java$/){
      100      
245           # Skip this if it installs a symlink in usr/share/java
246 27       297 my $java_dir = $info->index_resolved_path('usr/share/java/');
247 27       81 my $has_jars = 0;
248           $has_jars = 1
249           if $java_dir
250 27 50 33 0 291 and any { $_->name =~ m@^[^/]+\.jar$@o } $java_dir->children;
  0       0  
251 27 50     288 tag 'javalib-but-no-public-jars' if not $has_jars;
252           }
253            
254 5543       28431 return;
255           }
256            
257           1;
258            
259           # Local Variables:
260           # indent-tabs-mode: nil
261           # cperl-indent-level: 4
262           # End:
263           # vim: syntax=perl sw=4 sts=4 sr et