class JavaClass::ClassList::JarSearcher

Search in zip or JAR files for Java class files, check for package access or inner classes and call back a list of all these.

Author

Peter Kofler

Attributes

skip_inner_classes[RW]
skip_package_classes[RW]

Public Class Methods

new() click to toggle source

Create a new searcher.

# File lib/javaclass/classlist/jar_searcher.rb, line 27
def initialize
  @skip_inner_classes = true
  @skip_package_classes = false
  @package_filters = []
end

Public Instance Methods

accessible?() click to toggle source
# File lib/javaclass/classlist/jar_searcher.rb, line 62
def accessible?
  if @skip_package_classes && !@header.access_flags.accessible?
    # not public and we only want public
    false
  
  elsif @skip_inner_classes || !@header.attributes.inner_class?
    # no inner classes have been collected, everything is accessible due its public flag
    # or this is not an inner class, so everything is OK
    true
    
  # it is an inner class
    
  elsif @header.access_flags.synthetic? || @header.attributes.anonymous?
    # the inner class is anonymous or synthetic, not accessible
    false

  elsif !@header.attributes.static_inner_class?
    # must be static (and not private nor protected) to be accessible
    false
    
  elsif !@skip_package_classes
    # inner class is public or package access, OK
    true
    
  else
    # inner class is public, but parent class might be package only
    public?(@classpath, @header.attributes.outer_class.to_class_file)
    
  end
end
add_list_from_classpath(version, classpath, list) { |entry, is_public, version| ... } click to toggle source

Compile the class list for the given classpath . This searches the path for zips and JARs and adds them to the given list of found classes. version is a number >= 0, e.g. 2 for JDK 1.2. list must provide a add_class(entry, is_public, version) method.

# File lib/javaclass/classlist/jar_searcher.rb, line 105
def add_list_from_classpath(version, classpath, list)
  filter_classes(classpath.names).each do |entry|
    is_public = public?(classpath, entry)
    next if !accessible?
    
    list.add_class(entry, is_public, version) if list
    yield(entry, is_public, version) if block_given?
  end
end
compile_list(version, path, list) click to toggle source

Compile the class list for the given version of Java. This searches the path for zips and JARs and adds them to the given list of found classes. version is a number >= 0, e.g. 2 for JDK 1.2. list must provide a add_class(entry, is_public, version) method.

# File lib/javaclass/classlist/jar_searcher.rb, line 96
def compile_list(version, path, list)
  cpe = Classpath::AnyClasspath.new(path)
  add_list_from_classpath(version, cpe, list)
  list
end
filter_classes(classes) click to toggle source

Return the list of classnames of this list of classes . Skips inner classes if skip_inner_classes is true. Skips classes that are in the filtered packages.

# File lib/javaclass/classlist/jar_searcher.rb, line 41
def filter_classes(classes)
  classes.find_all do |name|
    !(@skip_inner_classes && name =~ /\$/) && (@package_filters.find { |filter| name =~ filter } == nil)
  end
end
filters=(filters) click to toggle source

The given filters will be dropped during searching. filters contain the beginning of package paths, i.e. com/sun/.

# File lib/javaclass/classlist/jar_searcher.rb, line 34
def filters=(filters)
  @package_filters = filters.collect{ |f| /^#{f}/ }
end
public?(classpath, classfile) click to toggle source

Return true if the classfile in the given classpath is public. This is expensive because the JAR file is opened and the classfile is extracted and read.

# File lib/javaclass/classlist/jar_searcher.rb, line 49
def public?(classpath, classfile)
  # temporal hack, store @classpath and @header
  @classpath = classpath
  begin
    @header = ClassFile::JavaClassHeader.new(classpath.load_binary(classfile))
  rescue JavaClass::ClassFile::ClassFormatError => ex
    ex.add_classname(classfile, classpath.to_s)
    raise ex
  end
  @header.magic.check("invalid java class #{classfile}")
  @header.access_flags.accessible?
end