javaclass 0.0.3 → 0.0.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (175) hide show
  1. data/Rakefile +67 -56
  2. data/Readme.txt +42 -39
  3. data/example_task.rb +172 -0
  4. data/examples/check_interface_names.rb +44 -0
  5. data/examples/corpus.rb +19 -0
  6. data/examples/count_classes_in_modules.rb +38 -0
  7. data/examples/cumulative_dependencies.rb +39 -0
  8. data/examples/find_all_imported_types.rb +44 -0
  9. data/examples/find_referenced_modules.rb +53 -0
  10. data/examples/find_unreferenced_classes.rb +65 -0
  11. data/examples/generate_class_lists.rb +67 -43
  12. data/examples/profiler_scratchpad.rb +33 -0
  13. data/examples/simple_usage.rb +42 -0
  14. data/history.txt +29 -7
  15. data/javaclass.gemspec +31 -0
  16. data/lib/javaclass/adder_tree.rb +92 -0
  17. data/lib/javaclass/analyse/dependencies.rb +52 -0
  18. data/lib/javaclass/{metric/metrics.txt → analyse/ideas.txt} +2 -2
  19. data/lib/javaclass/analyse/transitive_dependencies.rb +52 -0
  20. data/lib/javaclass/classfile/access_flag_constants.rb +24 -0
  21. data/lib/javaclass/classfile/access_flags.rb +49 -26
  22. data/lib/javaclass/classfile/class_format_error.rb +37 -0
  23. data/lib/javaclass/classfile/class_magic.rb +16 -8
  24. data/lib/javaclass/classfile/class_version.rb +19 -25
  25. data/lib/javaclass/classfile/constant_pool.rb +110 -45
  26. data/lib/javaclass/classfile/constants/base.rb +33 -12
  27. data/lib/javaclass/classfile/constants/double_reference.rb +55 -41
  28. data/lib/javaclass/classfile/constants/single_reference.rb +29 -21
  29. data/lib/javaclass/classfile/constants/value.rb +43 -33
  30. data/lib/javaclass/classfile/java_class_header.rb +72 -46
  31. data/lib/javaclass/classfile/java_class_header_as_java_name.rb +33 -0
  32. data/lib/javaclass/classfile/java_class_header_shortcuts.rb +19 -0
  33. data/lib/javaclass/classfile/references.rb +21 -19
  34. data/lib/javaclass/classlist/class_entry.rb +26 -27
  35. data/lib/javaclass/classlist/jar_searcher.rb +34 -25
  36. data/lib/javaclass/classlist/list.rb +31 -31
  37. data/lib/javaclass/classlist/package_entry.rb +25 -24
  38. data/lib/javaclass/classpath/any_classpath.rb +48 -0
  39. data/lib/javaclass/classpath/class_not_found_error.rb +20 -0
  40. data/lib/javaclass/classpath/classpaths.txt +2 -2
  41. data/lib/javaclass/classpath/composite_classpath.rb +56 -54
  42. data/lib/javaclass/classpath/convention_classpath.rb +38 -0
  43. data/lib/javaclass/classpath/eclipse_classpath.rb +74 -0
  44. data/lib/javaclass/classpath/factory.rb +65 -0
  45. data/lib/javaclass/classpath/file_classpath.rb +47 -0
  46. data/lib/javaclass/classpath/folder_classpath.rb +42 -44
  47. data/lib/javaclass/classpath/jar_classpath.rb +91 -52
  48. data/lib/javaclass/classpath/java_home_classpath.rb +24 -13
  49. data/lib/javaclass/classpath/maven_classpath.rb +44 -0
  50. data/lib/javaclass/classpath/temporary_unpacker.rb +111 -0
  51. data/lib/javaclass/classpath/tracking_classpath.rb +144 -0
  52. data/lib/javaclass/classscanner/ideas.txt +3 -0
  53. data/lib/javaclass/classscanner/imported_types.rb +29 -0
  54. data/lib/javaclass/classscanner/scanners.rb +29 -0
  55. data/lib/javaclass/delegate_directive.rb +15 -0
  56. data/lib/javaclass/dsl/caching_classpath.rb +38 -0
  57. data/lib/javaclass/dsl/classpath_analysers.rb +27 -0
  58. data/lib/javaclass/dsl/java_name_factory.rb +79 -0
  59. data/lib/javaclass/dsl/loader.rb +42 -0
  60. data/lib/javaclass/dsl/loading_classpath.rb +53 -0
  61. data/lib/javaclass/dsl/mixin.rb +54 -0
  62. data/lib/javaclass/gems/zip_file.rb +154 -0
  63. data/lib/javaclass/java_language.rb +50 -0
  64. data/lib/javaclass/java_name.rb +329 -55
  65. data/lib/javaclass/java_name_scanner.rb +95 -0
  66. data/lib/javaclass/resources/iso_3166_countries.txt +240 -0
  67. data/lib/javaclass/resources/jdk0_packages.txt +6 -0
  68. data/lib/javaclass/resources/jdk1_packages.txt +6 -0
  69. data/lib/javaclass/resources/jdk2_packages.txt +4 -0
  70. data/lib/javaclass/resources/jdk3_packages.txt +6 -0
  71. data/lib/javaclass/resources/jdk4_packages.txt +22 -0
  72. data/lib/javaclass/resources/jdk5_packages.txt +5 -0
  73. data/lib/javaclass/resources/jdk6_packages.txt +7 -0
  74. data/lib/javaclass/resources/jdk7_packages.txt +0 -0
  75. data/lib/javaclass/resources/jdk_packages.txt +53 -0
  76. data/lib/javaclass/resources/reserved_words.txt +50 -0
  77. data/lib/javaclass/string_hexdump.rb +76 -0
  78. data/lib/javaclass/string_ux.rb +21 -10
  79. data/lib/javaclass.rb +16 -41
  80. data/license.txt +28 -0
  81. data/planned.txt +13 -0
  82. data/test/data/Object_102.class +0 -0
  83. data/test/data/Runnable_102.class +0 -0
  84. data/test/data/access_flags/AccessFlagsTestAnnotation.class +0 -0
  85. data/test/data/access_flags/AccessFlagsTestAnnotation.java +3 -0
  86. data/test/data/access_flags/AccessFlagsTestEnum$1.class +0 -0
  87. data/test/data/access_flags/AccessFlagsTestEnum.class +0 -0
  88. data/test/data/access_flags/AccessFlagsTestEnum.java +6 -0
  89. data/test/data/access_flags/AccessFlagsTestInner$1.class +0 -0
  90. data/test/data/access_flags/AccessFlagsTestInner$2.class +0 -0
  91. data/test/data/access_flags/AccessFlagsTestInner.class +0 -0
  92. data/test/data/access_flags/AccessFlagsTestInner.java +13 -0
  93. data/test/data/access_flags/AccessFlagsTestPackage.class +0 -0
  94. data/test/data/access_flags/AccessFlagsTestPackage.java +1 -1
  95. data/test/data/api/packagename/AccessFlagsTestPublic.class +0 -0
  96. data/test/data/class_version/ClassVersionTest17.class +0 -0
  97. data/test/data/class_version/make.bat +6 -2
  98. data/test/data/eclipse_classpath/classes/ClassVersionTest12.class +0 -0
  99. data/test/data/eclipse_classpath/lib/JarClasspathTest.jar +0 -0
  100. data/test/data/eclipse_classpath/test-classes/ClassVersionTest13.class +0 -0
  101. data/test/data/folder_classpath/{JarClasspathTestFolder → classes}/ClassVersionTest10.class +0 -0
  102. data/test/data/folder_classpath/{JarClasspathTestFolder → classes}/package/ClassVersionTest11.class +0 -0
  103. data/test/data/jar_classpath/JarClasspathTest.jar +0 -0
  104. data/test/data/jar_classpath/JarClasspathTest.zip +0 -0
  105. data/test/data/jar_classpath/JarClasspathTestManifest.jar +0 -0
  106. data/test/data/jar_classpath/JarClasspathTestMultiManifest.jar +0 -0
  107. data/test/data/jar_classpath/make.bat +6 -2
  108. data/test/data/jar_searcher/BrokenRunnable_102.class +0 -0
  109. data/test/data/java_home_classpath/jdk118/lib/classes.zip +0 -0
  110. data/test/data/java_name_scanner/META-INF/MANIFEST.MF +12 -0
  111. data/test/data/java_name_scanner/plugin.xml +18 -0
  112. data/test/data/maven_classpath/module/pom.xml +8 -0
  113. data/test/data/maven_classpath/module/target/classes/ClassVersionTest12.class +0 -0
  114. data/test/data/maven_classpath/pom.xml +8 -0
  115. data/test/data/maven_classpath/target/classes/ClassVersionTest10.class +0 -0
  116. data/test/data/maven_classpath/target/test-classes/ClassVersionTest11.class +0 -0
  117. data/test/data/transitive_dependencies/A.class +0 -0
  118. data/test/data/transitive_dependencies/A.java +5 -0
  119. data/test/data/transitive_dependencies/B.class +0 -0
  120. data/test/data/transitive_dependencies/B.java +3 -0
  121. data/test/data/transitive_dependencies/C.class +0 -0
  122. data/test/data/transitive_dependencies/C.java +3 -0
  123. data/test/data/transitive_dependencies/Start.class +0 -0
  124. data/test/data/transitive_dependencies/Start.java +4 -0
  125. data/test/data/transitive_dependencies/make.bat +3 -0
  126. data/test/data/zip_file/commons-math-2.2-broken.zip +0 -0
  127. data/test/data/zip_file/regenerated-with-7zip.zip +0 -0
  128. data/test/data/zip_file/regenerated-with-jar.zip +0 -0
  129. data/test/dot_classpath.rb +33 -0
  130. data/test/logging_folder_classpath.rb +19 -0
  131. data/test/setup.rb +1 -1
  132. data/test/test_access_flags.rb +58 -32
  133. data/test/test_adder_tree.rb +78 -0
  134. data/test/test_any_classpath.rb +39 -0
  135. data/test/test_base.rb +9 -7
  136. data/test/test_caching_classpath.rb +41 -0
  137. data/test/test_class_entry.rb +60 -60
  138. data/test/test_class_magic.rb +31 -0
  139. data/test/test_class_version.rb +25 -25
  140. data/test/test_composite_classpath.rb +22 -23
  141. data/test/test_constant_pool.rb +37 -13
  142. data/test/test_convention_classpath.rb +39 -0
  143. data/test/test_eclipse_classpath.rb +73 -0
  144. data/test/test_factory.rb +61 -0
  145. data/test/test_folder_classpath.rb +26 -10
  146. data/test/test_imported_types.rb +34 -0
  147. data/test/test_jar_classpath.rb +29 -14
  148. data/test/test_jar_searcher.rb +27 -14
  149. data/test/test_java_class_header.rb +22 -10
  150. data/test/test_java_class_header_as_java_name.rb +41 -0
  151. data/test/test_java_home_classpath.rb +17 -11
  152. data/test/test_java_name.rb +204 -64
  153. data/test/test_java_name_factory.rb +52 -0
  154. data/test/test_java_name_scanner.rb +24 -0
  155. data/test/test_javaclass_api.rb +43 -0
  156. data/test/test_list.rb +58 -44
  157. data/test/test_load_directive.rb +34 -0
  158. data/test/test_maven_classpath.rb +46 -0
  159. data/test/test_package_entry.rb +27 -22
  160. data/test/test_references.rb +14 -14
  161. data/test/test_string_hexdump.rb +24 -0
  162. data/test/test_string_ux.rb +18 -106
  163. data/test/test_tracking_classpath.rb +112 -0
  164. data/test/test_transitive_dependencies.rb +31 -0
  165. data/test/test_unpacking_jar_classpath.rb +43 -0
  166. data/test/test_zip_file.rb +33 -0
  167. data/test/ts_all_tests.rb +80 -18
  168. data/thanks.txt +2 -0
  169. metadata +151 -22
  170. data/lib/javaclass/classpath/port_ClassPathEntry.java +0 -202
  171. data/lib/javaclass/classpath/port_ClassPathEntryFactory.java +0 -311
  172. data/lib/javaclass/classpath/port_DirectoryRepository.java +0 -24
  173. data/lib/javaclass/metric/ccd.rb +0 -68
  174. data/lib/javaclass/metric/class_usage.rb +0 -41
  175. data/test/test_javaclass.rb +0 -22
@@ -1,43 +1,45 @@
1
1
  require 'javaclass/classfile/constant_pool'
2
2
 
3
3
  module JavaClass
4
- module ClassFile
5
-
4
+ module ClassFile
5
+
6
6
  # Container class for list of all classes, methods and fields referenced by this class.
7
7
  # This information is derived from the constant pool, no analysis.
8
8
  # Author:: Peter Kofler
9
9
  class References
10
-
11
- # Create a references container with the constant _pool_ and skip references to index _classidx_ which is the host class itself.
10
+
11
+ # Create a references container with the constant _pool_ and skip references to index _classidx_ which is the host class itself.
12
12
  def initialize(pool, classidx)
13
13
  @constant_pool = pool
14
14
  @class_idx = classidx
15
15
  end
16
-
17
- # Return the constants referring to fields (Constants::ConstantField).
18
- # If _includeown_ is +true+ then fields of this class are returned also.
16
+
17
+ # Return the constants referring to fields (Constants::ConstantField).
18
+ # If _includeown_ is +true+ then fields of this class are returned also.
19
19
  def referenced_fields(includeown=false)
20
- @constant_pool.find(ConstantPool::FIELD_TAG).find_all do |field|
20
+ @constant_pool.find(ConstantPool::FIELD_TAG).find_all do |field|
21
21
  includeown || field.class_index != @class_idx
22
22
  end
23
23
  end
24
-
25
- # Return the constants referring to methods (Constants::ConstantMethod) in classes or interfaces.
26
- # If _includeown_ is +true+ then methods of this class are returned also.
24
+
25
+ # Return the constants referring to methods (Constants::ConstantMethod) in classes or interfaces.
26
+ # If _includeown_ is +true+ then methods of this class are returned also.
27
27
  def referenced_methods(includeown=false)
28
- @constant_pool.find(ConstantPool::METHOD_TAG, ConstantPool::INTERFACE_METHOD_TAG).find_all do |method|
29
- includeown || method.class_index != @class_idx
28
+ @constant_pool.find(ConstantPool::METHOD_TAG, ConstantPool::INTERFACE_METHOD_TAG).find_all do |method|
29
+ includeown || method.class_index != @class_idx
30
30
  end
31
31
  end
32
-
33
- # Return the list of all constants containing class names of all used classes.
32
+
33
+ # Return the list of all constant pool constantss containing class names of all used classes.
34
+ # Returns a list of ConstantClass.
34
35
  def used_classes
35
- @constant_pool.find(ConstantPool::CLASS_TAG).find_all do |cl|
36
- cl.class_name != @constant_pool[@class_idx].to_s
36
+ my_class_name = @constant_pool[@class_idx].class_name
37
+ @constant_pool.find(ConstantPool::CLASS_TAG).find_all do |cl|
38
+ cl.class_name != my_class_name
37
39
  end
38
40
  end
39
-
41
+
40
42
  end
41
-
43
+
42
44
  end
43
45
  end
@@ -1,20 +1,19 @@
1
1
  require 'javaclass/java_name'
2
2
 
3
3
  module JavaClass
4
- module ClassList # :nodoc:
5
-
6
- # An entry in the list. A ClassEntry belongs to a PackageEntry and has a list ov versions it exists in.
4
+ module ClassList
5
+
6
+ # An entry in the list. A ClassEntry belongs to a PackageEntry and has a list of versions it exists in.
7
7
  # Author:: Peter Kofler
8
8
  class ClassEntry
9
-
9
+
10
10
  # Return the short (simple) name of this class.
11
11
  attr_reader :name
12
12
  attr_reader :full_name
13
13
  # Return the list of versions this class exists.
14
14
  attr_reader :version
15
-
16
- # Create a new entry. _parent_ must provide a +version+ field to compare against. _vers_ is the
17
- # base version of this class.
15
+
16
+ # Create a new entry. _parent_ must provide a +version+ field to compare against. _vers_ is the base version of this class.
18
17
  def initialize(parent, full_name, is_public, vers)
19
18
  @parent = parent
20
19
  @full_name = full_name.to_javaname.to_classname
@@ -22,68 +21,68 @@ module JavaClass
22
21
  @is_public = is_public
23
22
  @version = [vers]
24
23
  end
25
-
24
+
26
25
  def public?
27
26
  @is_public
28
27
  end
29
-
28
+
30
29
  # Update the _version_ this class also exists in.
31
30
  def update(version, is_public=@is_public)
32
31
  raise "update class #{@name} is older than its last version: latest version=#{@version.last}, new version=#{version}" if version <= @version.last
33
32
  # check for holes in versions
34
33
  if version > @version.last+1
35
- warn "#{@full_name} last in version #{@version.last}, not in #{@version.last+1}, but again in #{version}"
34
+ warn "#{@full_name} last in version #{@version.last}, not in #{@version.last+1}, but again in #{version}"
36
35
  end
37
- @version << version
38
-
36
+ @version << version
37
+
39
38
  if !is_public && @is_public
40
39
  warn "#{@full_name} changed from public to package in version #{version}"
41
40
  @is_public = is_public
42
41
  @version = [version] # skip older versions
43
42
  elsif is_public && ! @is_public
44
- info "#{@full_name} changed from package to public in version #{version}"
43
+ puts "#{@full_name} changed from package to public in version #{version}"
45
44
  @is_public = is_public
46
45
  @version = [version] # skip older versions
47
46
  end
48
47
  end
49
-
48
+
50
49
  # Sorts by simple +name+ inside the package.
51
50
  def <=>(other)
52
51
  @name.casecmp other.name
53
52
  end
54
-
53
+
55
54
  def to_s
56
55
  @full_name
57
56
  end
58
-
59
- # Return a string containing the full qualified name together with first and last version
60
- # of this class. Ignore package versions, but obey _minversion_ and _maxversion_ .
57
+
58
+ # Return a string containing the full qualified name together with first and last version of this class. Ignore package versions, but
59
+ # obey _minversion_ and _maxversion_ .
61
60
  # Print all versions, first to last, but skip <code>first<=minversion</code> and <code>last>=maxversion</code>.
62
61
  def to_full_qualified_s(minversion, maxversion)
63
62
  format_version(@full_name, minversion, maxversion)
64
63
  end
65
-
64
+
66
65
  # Return a string containing the simple name and the version, if it is different from the package version.
67
66
  def to_package_shortcut_s
68
67
  vp = @parent.version
69
68
  format_version(" #{@name}", vp.first, vp.last)
70
69
  end
71
-
70
+
72
71
  private
73
-
72
+
74
73
  def format_version(start, minversion, maxversion)
75
74
  # this class has a set of versions where it exists
76
75
  # the parent has a set of versions where it exists, contains class versions
77
76
  is_newer = @version.first > minversion
78
77
  is_outdated = @version.last < maxversion
79
- line = start +
80
- " [#{ is_newer || (!@is_public && @version.first>0) ? @version.first.to_s : ''}" +
81
- "#{is_outdated ? '-' + @version.last.to_s : ''}" +
82
- "#{!@is_public ? 'p' : '' }]" +
83
- " - \n"
78
+ line = start +
79
+ " [#{ is_newer || (!@is_public && @version.first>0) ? @version.first.to_s : ''}" +
80
+ "#{is_outdated ? '-' + @version.last.to_s : ''}" +
81
+ "#{!@is_public ? 'p' : '' }]" +
82
+ " - \n"
84
83
  line.sub(/\[-0/, "[0-0").sub(/(\d)-\1/, "only \\1").sub(/ \[\]/, '')
85
84
  end
86
85
  end
87
-
86
+
88
87
  end
89
88
  end
@@ -1,30 +1,40 @@
1
- require 'javaclass/classpath/composite_classpath'
1
+ require 'javaclass/classpath/any_classpath'
2
2
  require 'javaclass/classfile/java_class_header'
3
3
 
4
4
  module JavaClass
5
- module ClassList # :nodoc:
6
-
7
- # Search in zip or jar files for Java class files, check for package access or inner classes and
8
- # call back a list of all these.
5
+
6
+ # The module ClassList is for separating namespaces. It contains the logic
7
+ # to create a list of all classes of all JDK versions. The main logic is
8
+ # performed in ClassList::JarSearcher, which creates the ClassList::List.
9
+ # It uses a
10
+ # Classpath::CompositeClasspath to find all classes and ClassFile::JavaClassHeader
11
+ # to read the class information from. The generated list contains packages
12
+ # and these packages contain the names of classes, their accessibility
13
+ # and the versions they were added (or removed) from JDK. ClassList is an
14
+ # "application" using the JavaClass infrastructure. For a full example see
15
+ # {how to generate lists of JDK classes}[link:/files/lib/generated/examples/generate_class_lists_txt.html].
16
+ # Author:: Peter Kofler
17
+ module ClassList
18
+
19
+ # 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.
9
20
  # Author:: Peter Kofler
10
21
  class JarSearcher
11
-
22
+
12
23
  attr_accessor :skip_inner_classes
13
24
  attr_accessor :skip_package_classes
14
-
25
+
15
26
  # Create a new searcher.
16
27
  def initialize
17
28
  @skip_inner_classes = true
18
29
  @skip_package_classes = false
19
30
  @package_filters = []
20
31
  end
21
-
22
- # The given _filters_ will be dropped during searching.
23
- # _filters_ contain the beginning of package paths, i.e. <code>com/sun/</code>.
32
+
33
+ # The given _filters_ will be dropped during searching. _filters_ contain the beginning of package paths, i.e. <code>com/sun/</code>.
24
34
  def filters=(filters)
25
35
  @package_filters = filters.collect{ |f| /^#{f}/ }
26
36
  end
27
-
37
+
28
38
  # Return the list of classnames of this list of _classes_ .
29
39
  # Skips inner classes if +skip_inner_classes+ is true.
30
40
  # Skips classes that are in the filtered packages.
@@ -33,37 +43,36 @@ module JavaClass
33
43
  !(@skip_inner_classes && name =~ /\$/) && (@package_filters.find { |filter| name =~ filter } == nil)
34
44
  end
35
45
  end
36
-
37
- # Return true if the _classfile_ in the given _classpath_ is public. This is expensive because
38
- # the jarfile is opened and the _classfile_ is extracted and read.
46
+
47
+ # Return true if the _classfile_ in the given _classpath_ is public. This is expensive because the JAR file is opened and the
48
+ # _classfile_ is extracted and read.
39
49
  def public?(classpath, classfile)
40
50
  begin
41
51
  header = ClassFile::JavaClassHeader.new(classpath.load_binary(classfile))
42
- rescue
43
- puts "error #{$1} for class #{classfile} on #{classpath.to_s}"
44
- raise
52
+ rescue JavaClass::ClassFile::ClassFormatError => ex
53
+ ex.add_classname(classfile, classpath.to_s)
54
+ raise ex
45
55
  end
46
- raise "invalid java class #{classfile}" unless header.magic.valid?
56
+ header.magic.check("invalid java class #{classfile}")
47
57
  header.access_flags.accessible?
48
58
  end
49
-
50
- # Compile the class list for the given _version_ of Java. This searches the _path_ for zips and jars
59
+
60
+ # Compile the class list for the given _version_ of Java. This searches the _path_ for zips and JARs
51
61
  # and adds them to the given _list_ of found classes. _version_ is a number >= 0, e.g. 2 for JDK 1.2.
52
62
  # _list_ must provide a <code>add_class(entry, is_public, version)</code> method.
53
63
  def compile_list(version, path, list)
54
- cpe = JavaClass::Classpath::CompositeClasspath.new
55
- cpe.find_jars(path)
64
+ cpe = Classpath::AnyClasspath.new(path)
56
65
  filter_classes(cpe.names).each do |entry|
57
66
  is_public = public?(cpe, entry)
58
67
  next if @skip_package_classes && !is_public
59
68
  list.add_class(entry, is_public, version) if list
60
69
  yield(entry, is_public, version) if block_given?
61
70
  end
62
-
71
+
63
72
  list
64
73
  end
65
-
74
+
66
75
  end
67
-
76
+
68
77
  end
69
78
  end
@@ -2,31 +2,31 @@ require 'javaclass/java_name'
2
2
  require 'javaclass/classlist/package_entry'
3
3
 
4
4
  module JavaClass
5
- module ClassList # :nodoc:
6
-
7
- # Classes to form a list of JDK classes to find classes which have been added in new releases.
8
- # The list of classes. It list contains packages.
5
+ module ClassList
6
+
7
+ # Classes to form a list of JDK classes to find classes which have been
8
+ # added in new releases. This is the list containing packages (PackageEntry).
9
9
  # Author:: Peter Kofler
10
10
  class List
11
-
11
+
12
12
  def initialize
13
- @packages = {}
13
+ @packages = Hash.new # package_name (String) => PackageEntry
14
14
  end
15
-
16
- # Add a _fileentry_ to the list. The _fileentry_ is the file name of the class in the jar file. _version_
15
+
16
+ # Add a _fileentry_ to the list. The _fileentry_ is the file name of the class in the JAR file. _version_
17
17
  # is the version of the JDK scanned and is used if the class is new.
18
18
  def add_class(fileentry, is_public, version)
19
19
  class_name = fileentry.to_javaname.to_classname
20
20
  package_name = class_name.package
21
21
  @packages[package_name] = PackageEntry.new(package_name, version) unless @packages.has_key?(package_name)
22
- @packages[package_name].add_class(class_name, is_public, version)
22
+ @packages[package_name].add_class(class_name.full_name, is_public, version)
23
23
  end
24
-
24
+
25
25
  # Parse a _line_ from a <code>fullClassList</code> and fill the list again. _maxversion_ is the maximum
26
26
  # max version from the list, i.e. the highest possible value, so we can continue to use it.
27
27
  def parse_line(line, maxversion)
28
28
  class_name, versions = line.scan(/^([^\s]+)\s(?:\[(.*)\]\s)?-\s*$/)[0]
29
-
29
+
30
30
  # no [], so we have it from always and it is public
31
31
  first_vers = 0
32
32
  last_vers = maxversion
@@ -35,7 +35,7 @@ module JavaClass
35
35
  # extract package access and drop it
36
36
  is_public = (versions !~ /p/)
37
37
  versions = versions.gsub(/p/, '')
38
-
38
+
39
39
  # \d, \d-\d, only \d, -\d, oder leer
40
40
  if versions =~ /^(\d)$/
41
41
  first_vers = $1.to_i
@@ -51,54 +51,54 @@ module JavaClass
51
51
  raise "can't match version number #{versions} in line #{line.chomp}" unless versions == ''
52
52
  end
53
53
  end
54
-
55
- first_vers.upto(last_vers) do |v|
56
- add_class(class_name, is_public, v)
54
+
55
+ first_vers.upto(last_vers) do |v|
56
+ add_class(class_name, is_public, v)
57
57
  end
58
58
  rescue
59
59
  raise "#{$!} in line #{line.chomp}: class_name=#{class_name}, versions=#{versions}, first_vers=#{first_vers}, last_vers=#{last_vers}, is_public=#{is_public}"
60
60
  end
61
-
61
+
62
62
  def packages
63
63
  @packages.values.sort
64
64
  end
65
-
65
+
66
66
  # Return the version list of all packages.
67
67
  def version
68
68
  packages.collect { |p| p.version }.flatten.uniq.sort
69
69
  end
70
-
70
+
71
71
  # Return the first and last version of this list.
72
72
  def first_last_versions
73
73
  v = version
74
74
  [v.first, v.last]
75
75
  end
76
-
76
+
77
77
  def to_s
78
78
  packages.collect { |p| p.to_s }.join("\n")
79
79
  end
80
-
80
+
81
81
  # Return the number of classes in this list.
82
82
  def size
83
83
  @packages.values.inject(0) {|sum, p| sum + p.size }
84
84
  end
85
-
85
+
86
86
  # The access list is the raw list of all package access classes for one version. It was used to differ
87
87
  # normal classes from hidden classes and was saved in <code>doc/AccessLists/*_p.txt</code>.
88
- # This works only if JarSearcher was used with +skip_package_classes+ set to false (default).
89
- # If there are more versions loaded, then only the last version is printed. So we get consecutive lists
88
+ # This works only if JarSearcher was used with <i>skip_package_classes</i> set to false (default).
89
+ # If there are more versions loaded, then only the last version is printed. So we get consecutive lists
90
90
  # of new package access classes with every JDK version.
91
91
  def old_access_list
92
92
  v = first_last_versions
93
- packages.collect { |pkg|
93
+ packages.collect { |pkg|
94
94
  pkg.classes.find_all { |c| !c.public? && c.version == [v[1]]}.collect { |c| c.to_full_qualified_s(v[0], v[1]) }
95
95
  }.flatten.sort{|a,b| a.casecmp b }
96
96
  end
97
-
98
- # The class list is the raw list of all classes for one version without version or package access
97
+
98
+ # The class list is the raw list of all classes for one version without version or package access
99
99
  # descriptors. It was used to find differences and was saved in <code>doc/ClassLists/*_classes.txt</code>.
100
100
  # This usually was done with JarSearcher set +skip_package_classes+ to false.
101
- # If a block is given it is invoked with ClassEntry and should return if to add the class or not.
101
+ # If a block is given it is invoked with ClassEntry and should return if to add the class or not.
102
102
  def plain_class_list
103
103
  packages.collect { |pkg|
104
104
  cls = pkg.classes
@@ -108,19 +108,19 @@ module JavaClass
108
108
  cls.collect { |c| c.full_name + "\n" }
109
109
  }.flatten.sort{|a,b| a.casecmp b }
110
110
  end
111
-
111
+
112
112
  # Create a full class list with version numbers and different versions to compare.
113
113
  # This was the base for classlists and was saved in <code>doc/fullClassList1x.txt</code>.
114
114
  # This usually was done with JarSearcher set +skip_package_classes+ to false and
115
115
  # contained different classlists merged together.
116
116
  def full_class_list
117
117
  v = first_last_versions
118
- packages.collect { |pkg|
118
+ packages.collect { |pkg|
119
119
  pkg.classes.collect { |c| c.to_full_qualified_s(v[0], v[1]) }
120
120
  }.flatten.sort{|a,b| a.casecmp b }
121
121
  end
122
-
122
+
123
123
  end
124
-
124
+
125
125
  end
126
126
  end
@@ -1,34 +1,35 @@
1
1
  require 'javaclass/classlist/class_entry'
2
2
 
3
3
  module JavaClass
4
- module ClassList # :nodoc:
5
-
6
- # A package in the List.
4
+ module ClassList
5
+
6
+ # A package in the List. A package contains ClassEntry.
7
7
  # Author:: Peter Kofler
8
8
  class PackageEntry # ZenTest FULL to find method <=>
9
-
9
+
10
10
  attr_reader :name
11
11
  # Return the list of versions this package exists. This is the sum of all versions of all classes in the package.
12
12
  attr_reader :version
13
-
13
+
14
14
  # Create a new package with name _name_ and first version _vers_ which is the version of the first class in the package.
15
15
  def initialize(name, vers=0)
16
16
  @name = name
17
17
  @version = [vers]
18
- @classes = {}
18
+ @classes = Hash.new # class_name (most likely String) => ClassEntry
19
19
  end
20
-
20
+
21
21
  def add_class(class_name, is_public, version)
22
22
  @version << version unless @version.include? version
23
23
  @version = @version.sort
24
-
24
+
25
25
  unless @classes.has_key?(class_name)
26
26
  @classes[class_name] = ClassEntry.new(self, class_name, is_public, version)
27
+ # class_name does not need to be frozen because it's not read from the keys
27
28
  else
28
29
  @classes[class_name].update(version, is_public)
29
30
  end
30
31
  end
31
-
32
+
32
33
  # Sorting in packages is: <code>java.lang</code>, other <code>java.*</code>, <code>javax.*</code> and then others.
33
34
  def <=>(other)
34
35
  if @name =~ /^java\.lang$/ and other.name !~ /^java\.lang$/
@@ -47,41 +48,41 @@ module JavaClass
47
48
  @name <=> other.name
48
49
  end
49
50
  end
50
-
51
+
51
52
  # Return the classes in this package.
52
53
  def classes
53
54
  @classes.values.sort
54
55
  end
55
-
56
+
56
57
  # Return the number of classes in this package.
57
58
  def size
58
59
  @classes.size
59
60
  end
60
-
61
+
61
62
  def to_s
62
63
  @name
63
64
  end
64
-
65
- # Special version of +to_s+ for package shortcut. A package needs _minversion_ and _maxversion_ to
66
- # determine if the whole package was dropped.
65
+
66
+ # Special version of +to_s+ for package shortcut. A package needs _minversion_ and _maxversion_ to determine if the whole package was
67
+ # dropped.
67
68
  def to_package_shortcut_s(minversion, maxversion)
68
- "#{@name}#{format_version(minversion, maxversion)} - \n" +
69
+ "#{@name}#{format_version(minversion, maxversion)} - \n" +
69
70
  classes.collect { |c| c.to_package_shortcut_s }.join
70
71
  end
71
-
72
+
72
73
  private
73
-
74
+
74
75
  def format_version(minversion, maxversion)
75
76
  is_newer = @version.first > minversion
76
77
  is_outdated = @version.last < maxversion
77
- line =
78
- " [#{ is_newer ? @version.first.to_s : ''}" +
79
- "#{is_outdated ? '-' + @version.last.to_s : ''}" +
80
- "]"
78
+ line =
79
+ " [#{ is_newer ? @version.first.to_s : ''}" +
80
+ "#{is_outdated ? '-' + @version.last.to_s : ''}" +
81
+ "]"
81
82
  line.sub(/(\d)-\1/, "only \\1").sub(/ \[\]/, '')
82
83
  end
83
-
84
+
84
85
  end
85
-
86
+
86
87
  end
87
88
  end
@@ -0,0 +1,48 @@
1
+ require 'javaclass/classpath/composite_classpath'
2
+
3
+ module JavaClass
4
+ module Classpath
5
+
6
+ # Classpath containing everything under a folder. This is for an unstructured
7
+ # collection of JARs and class files.
8
+ # Author:: Peter Kofler
9
+ class AnyClasspath < CompositeClasspath
10
+
11
+ # Create a classpath with all classes found under this _folder_ wherever they are.
12
+ def initialize(folder)
13
+ super(File.join(folder, '*'))
14
+ find_jars(folder)
15
+
16
+ # TODO Implement "find_classes_under(folder)" to find all class folders under this path.
17
+ # Search for classes, open the first one, check its package, backtrack to its base folder,
18
+ # add it to this classpath "add_file_name(sub_folders)", skip it in further analysis and continue.
19
+ end
20
+
21
+ # Search the given _path_ recursively for zips or jars. Add all found jars to this classpath.
22
+ def find_jars(path)
23
+ if FileTest.file?(path) && path =~ /\.jar$|\.zip$/
24
+ add_file_name File.expand_path(path)
25
+ return
26
+ end
27
+
28
+ current = Dir.getwd
29
+ begin
30
+ Dir.chdir File.expand_path(path)
31
+
32
+ Dir['*'].collect do |name|
33
+ if FileTest.directory?(name)
34
+ find_jars(name)
35
+ elsif name =~ /\.jar$|\.zip$/
36
+ add_file_name File.expand_path(name)
37
+ end
38
+ end
39
+
40
+ ensure
41
+ Dir.chdir current
42
+ end
43
+ end
44
+
45
+ end
46
+
47
+ end
48
+ end
@@ -0,0 +1,20 @@
1
+ module JavaClass
2
+ module Classpath
3
+
4
+ # An error in the classpath. The requested classfile could not be found.
5
+ # Author:: Peter Kofler
6
+ class ClassNotFoundError < IOError
7
+
8
+ attr_reader :classname
9
+ attr_reader :classpath
10
+
11
+ def initialize(classname, classpath=nil)
12
+ @classname = classname
13
+ @classpath = classpath
14
+ super("class #{@classname} not found in classpath #{@classpath}")
15
+ end
16
+
17
+ end
18
+
19
+ end
20
+ end
@@ -1,2 +1,2 @@
1
- * Java 1.1 Home classpath with lib/classes.zip
2
- * other classpath abstractions: - WARs and EARs contain JARs and a folder
1
+ TODO other classpath abstractions:
2
+ * WARs and EARs contain JARs and a folder