Class: JavaClass::ClassList::JarSearcher

Inherits:
Object
  • Object
show all
Defined in:
lib/javaclass/classlist/jar_searcher.rb

Overview

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

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initializeJarSearcher

Create a new searcher.



27
28
29
30
31
# File 'lib/javaclass/classlist/jar_searcher.rb', line 27

def initialize
  @skip_inner_classes = true
  @skip_package_classes = false
  @package_filters = []
end

Instance Attribute Details

#skip_inner_classesObject

Returns the value of attribute skip_inner_classes.



23
24
25
# File 'lib/javaclass/classlist/jar_searcher.rb', line 23

def skip_inner_classes
  @skip_inner_classes
end

#skip_package_classesObject

Returns the value of attribute skip_package_classes.



24
25
26
# File 'lib/javaclass/classlist/jar_searcher.rb', line 24

def skip_package_classes
  @skip_package_classes
end

Instance Method Details

#accessible?Boolean

Returns:

  • (Boolean)


62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
# 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) ⇒ Object

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.



105
106
107
108
109
110
111
112
113
# 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) ⇒ Object

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.



96
97
98
99
100
# 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) ⇒ Object

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.



41
42
43
44
45
# 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) ⇒ Object

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



34
35
36
# File 'lib/javaclass/classlist/jar_searcher.rb', line 34

def filters=(filters)
  @package_filters = filters.collect{ |f| /^#{f}/ }
end

#public?(classpath, classfile) ⇒ Boolean

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.

Returns:

  • (Boolean)


49
50
51
52
53
54
55
56
57
58
59
60
# 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