# java -- lintian check script -*- perl -*- # Copyright (C) 2011 Vincent Fourmond # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, you can find it on the World Wide # Web at http://www.gnu.org/copyleft/gpl.html, or write to the Free # Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, # MA 02110-1301, USA. package Lintian::java; use strict; use warnings; use Lintian::Tags qw(tag); use Util; sub run { my $pkg = shift; my $type = shift; my $info = shift; my $java_info = $info->java_info; my $missing_jarwrapper = 0; my $need_cp = 0; my $has_public_jars = 0; my $has_jars = 0; my $depends = $info->relation('strong')->unparse(); # Remove all libX-java-doc packages to avoid thinking they are java libs # - note the result may not be a valid dependency listing $depends =~ s/lib[^\s,]+-java-doc//go; my @java_lib_depends = ($depends =~ m/\b(lib[^\s,]+-java)\b/og); $need_cp = 1 if @java_lib_depends; # We first loop over jar files to find problems for my $jar_file (sort keys %{$java_info}) { my $file_list = $java_info->{$jar_file}->{files}; my $manifest = $java_info->{$jar_file}->{manifest}; my $operm = $info->{index}->{$jar_file}->{operm}; my $jar_dir; my $classes = 1; my $datafiles = 1; my $cp = ''; my $bsname = ''; # The Java Policy says very little about requires for (jars in) JVMs next if $jar_file =~ m#usr/lib/jvm(?:-exports)?/[^/]++/#o; # Ignore Mozilla's jar files, see #635495 next if $jar_file =~ m#usr/lib/xul(?:-ext|runner[^/]*+)/#o; $jar_dir = $jar_file; $jar_dir =~ s,[^/]+$,,o; $has_jars = 1; if($jar_file =~ m#^usr/share/java/[^/]+\.jar$#o) { $has_public_jars = 1; } # check for common code files like .class or .clj (Clojure files) $classes = 0 unless grep m/\.(?:class|clj)$/oi, @{$file_list}; $datafiles = 0 unless grep m/\.(?:xml|properties|x?html|xhp)$/io, @{$file_list}; if($operm & 0111) { # Executable ? tag 'executable-jar-without-main-class', $jar_file unless $manifest && $manifest->{'Main-Class'}; # Here, we need to check that the package depends on # jarwrapper. $missing_jarwrapper = 1 unless $info->relation('strong')->implies('jarwrapper'); } elsif ($jar_file !~ m#^usr/share/#) { tag 'jar-not-in-usr-share', $jar_file; } $cp = $manifest->{'Class-Path'}//'' if $manifest; $bsname = $manifest->{'Bundle-SymbolicName'}//'' if $manifest; if ($manifest) { if(!$classes) { # Eclipse / OSGi bundles are sometimes source bundles # these do not ship classes but java files and other sources. if ($bsname !~ m/\.source$/o || $cp) { tag 'codeless-jar', $jar_file; } } } elsif ($classes) { tag 'missing-manifest', $jar_file; } if(!$cp) { # Do we have OSGi instead? $need_cp = 0 if $bsname; # Maybe it is a maven plugin? $need_cp = 0 if $need_cp && grep { m,^META-INF/maven/plugin.xml$,io } @{$file_list}; } else { # Only run the tests when a classpath is present my @relative = (); my @paths = split(m/\s++/o, $cp); $need_cp = 0; for my $p (@paths) { if($p) { # Strip leading ./ $p =~ s#^\./++##og; if($p !~ m#^(?:file://)?/#o) { if($p =~ m#/#o) { my $target = resolve_pkg_path($jar_dir, $p); my $tinfo; # Relative link to usr/share/java ? Works if we # are depending of a Java library. next if $target =~ m,^usr/share/java/[^/]+.jar$,o and @java_lib_depends; $tinfo = $info->{index}->{$target}; # Points to file or link in this package, which is sometimes # easier than re-writing the classpath. next if defined $tinfo && ($tinfo->{type} =~ m/^[-hl]/o); # Relative path with subdirectories. push @relative, $p; } # @todo add an info tag for relative paths, to educate # maintainers ? } } } tag 'classpath-contains-relative-path', "$jar_file: " . join(', ', @relative) if @relative; } } tag 'missing-dep-on-jarwrapper' if $missing_jarwrapper; if($has_jars && $need_cp) { # Only tag if there is at least one jar file and one strong java dependency # and no classpath/osgi. Technically there should be no reason to have a # strong relation with a java library without having a jar file, but # we ignore some jars (e.g. in JVMs) so going safe here. tag 'missing-classpath', join(', ', @java_lib_depends); } if(! $has_public_jars && $pkg =~ /^lib[^\s,]+-java$/) { # Skip this if it installs a symlink in usr/share/java return if grep m@^usr/share/java/[^/]+\.jar$@o, @{ $info->sorted_index }; tag 'javalib-but-no-public-jars'; } } 1; # Local Variables: # indent-tabs-mode: nil # cperl-indent-level: 4 # End: # vim: syntax=perl sw=4 sts=4 sr et