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,99 +1,113 @@
1
1
  require 'javaclass/classfile/constants/single_reference'
2
2
  require 'javaclass/java_name'
3
3
 
4
- module JavaClass
5
- module ClassFile
6
- module Constants
7
-
8
- # Superclass of double reference constants like +ConstantField+ (+FieldRef+) in the constant pool.
4
+ module JavaClass
5
+ module ClassFile
6
+ module Constants
7
+
8
+ # Superclass of double reference constants like +ConstantField+ (+FieldRef+) in the constant pool.
9
9
  # Author:: Peter Kofler
10
10
  class DoubleReference < SingleReference
11
-
11
+
12
12
  attr_reader :second_index
13
-
13
+
14
14
  # Define a double reference into _pool_ from _data_ beginning at _start_
15
15
  def initialize(pool, data, start, name=nil)
16
16
  super(pool, data, start, name)
17
17
  @size = 5
18
-
18
+
19
19
  @second_index = data.u2(start+3)
20
20
  end
21
-
21
+
22
22
  # Return the second value, which is the referenced value from the pool.
23
23
  def second_value
24
24
  get(@second_index)
25
25
  end
26
-
26
+
27
27
  # Return the value, which are both referenced values from the pool.
28
28
  def to_s
29
29
  "#{super}.#{second_value}"
30
30
  end
31
-
31
+
32
32
  # Return part of debug output.
33
33
  def dump
34
34
  "#{@name}\t##{@first_index}.##{@second_index};\t// #{to_s}"
35
35
  end
36
-
36
+
37
37
  end
38
-
38
+
39
39
  class ConstantField < DoubleReference # ZenTest SKIP
40
- alias class_index first_index
41
- alias name_and_type_index second_index
42
- def initialize(pool, data, start)
40
+ alias class_index first_index
41
+ alias name_and_type_index second_index
42
+
43
+ def initialize(pool, data, start)
43
44
  super(pool, data, start)
44
45
  end
45
- def first_value
46
- # is a classname
47
- super.to_javaname
46
+
47
+ def first_value
48
+ JavaVMName.new(super) # this is a classname
48
49
  end
49
50
  alias class_name first_value
50
51
  alias signature second_value
52
+
53
+ def const_field?
54
+ true
55
+ end
51
56
  end
52
-
57
+
53
58
  class ConstantMethod < DoubleReference # ZenTest SKIP
54
- alias class_index first_index
55
- alias name_and_type_index second_index
56
- def initialize(pool, data, start)
59
+ alias class_index first_index
60
+ alias name_and_type_index second_index
61
+
62
+ def initialize(pool, data, start)
57
63
  super(pool, data, start)
58
- end
59
- def first_value
60
- # is a classname
61
- super.to_javaname
62
64
  end
65
+
66
+ def first_value
67
+ JavaVMName.new(super) # this is a classname
68
+ end
69
+
63
70
  alias class_name first_value
64
71
  alias signature second_value
72
+
73
+ def const_method?
74
+ true
75
+ end
65
76
  end
66
-
77
+
67
78
  class ConstantInterfaceMethod < DoubleReference # ZenTest SKIP
68
- alias class_index first_index
69
- alias name_and_type_index second_index
70
- def initialize(pool, data, start)
79
+ alias class_index first_index
80
+ alias name_and_type_index second_index
81
+
82
+ def initialize(pool, data, start)
71
83
  super(pool, data, start)
72
- end
73
- def first_value
74
- # is a classname
75
- super.to_javaname
76
84
  end
85
+
86
+ def first_value
87
+ JavaVMName.new(super) # this is a classname
88
+ end
89
+
77
90
  alias class_name first_value
78
91
  alias signature second_value
79
92
  end
80
-
93
+
81
94
  class ConstantNameAndType < DoubleReference # ZenTest SKIP
82
- alias name_index first_index
83
- alias descriptor_index second_index
95
+ alias name_index first_index
96
+ alias descriptor_index second_index
97
+
84
98
  def initialize(pool, data, start)
85
99
  super(pool, data, start)
86
100
  end
87
-
101
+
88
102
  def to_s
89
103
  "#{get(name_index)}:#{get(descriptor_index)}"
90
104
  end
91
-
105
+
92
106
  def dump
93
107
  "#{@name}\t##{name_index}:##{descriptor_index};// #{to_s}"
94
108
  end
95
109
  end
96
-
110
+
97
111
  end
98
112
  end
99
113
  end
@@ -1,65 +1,73 @@
1
1
  require 'javaclass/classfile/constants/base'
2
2
  require 'javaclass/java_name'
3
3
 
4
- module JavaClass
5
- module ClassFile
6
- module Constants
7
-
8
- # Superclass of single reference constants like +ConstantClass+ (+Class+) in the constant pool.
4
+ module JavaClass
5
+ module ClassFile
6
+ module Constants
7
+
8
+ # Superclass of single reference constants like +ConstantClass+ (+Class+) in the constant pool.
9
9
  # Author:: Peter Kofler
10
10
  class SingleReference < Base
11
-
11
+
12
12
  attr_reader :first_index
13
-
13
+
14
14
  # Define a single reference into _pool_ from _data_ beginning at _start_
15
15
  def initialize(pool, data, start, name=nil)
16
16
  super(name)
17
17
  @tag = data.u1(start)
18
-
18
+
19
19
  @enclosing_pool = pool
20
20
  @first_index = data.u2(start+1)
21
21
  end
22
-
22
+
23
23
  # Return the value, which is the referenced value from the pool.
24
24
  def first_value
25
25
  get(@first_index)
26
26
  end
27
- alias to_s first_value
28
-
27
+ def to_s
28
+ first_value
29
+ end
30
+
29
31
  # Return part of debug output.
30
32
  def dump
31
33
  super + "##{@first_index};\t// #{to_s}"
32
34
  end
33
-
35
+
34
36
  protected
35
-
37
+
36
38
  # Get a reference _ref_ from the +enclosing_pool+
37
39
  def get(ref)
38
40
  @enclosing_pool[ref].to_s
39
41
  end
40
-
42
+
41
43
  end
42
-
44
+
43
45
  class ConstantClass < SingleReference # ZenTest SKIP
44
46
  alias name_index first_index
47
+
45
48
  def initialize(pool, data, start)
46
49
  super(pool, data, start, "class")
47
50
  end
48
- def first_value
49
- # is a classname
50
- super.to_javaname
51
+
52
+ def first_value
53
+ JavaVMName.new(super) # this is a classname
51
54
  end
52
55
  alias class_name first_value
56
+
57
+ def const_class?
58
+ true
59
+ end
53
60
  end
54
-
61
+
55
62
  class ConstantString < SingleReference # ZenTest SKIP
56
63
  alias string_index first_index
57
- def initialize(pool, data, start)
64
+
65
+ def initialize(pool, data, start)
58
66
  super(pool, data, start)
59
67
  end
60
68
  alias string_value first_value
61
69
  end
62
-
70
+
63
71
  end
64
72
  end
65
73
  end
@@ -1,116 +1,126 @@
1
1
  require 'javaclass/classfile/constants/base'
2
2
 
3
- module JavaClass
4
- module ClassFile
5
- module Constants
6
-
7
- # Superclass of value constants like +ConstantInt+ (+Integer+) in the constant pool.
3
+ module JavaClass
4
+ module ClassFile
5
+ module Constants
6
+
7
+ # Superclass of value constants like +ConstantInt+ (+Integer+) in the constant pool.
8
8
  # Author:: Peter Kofler
9
9
  class Value < Base
10
-
10
+
11
11
  attr_reader :value
12
-
12
+
13
13
  # Create a constant value with an optional downcase _name_
14
14
  def initialize(name=self.class.to_s[/::[^:]+$/][10..-1].downcase)
15
15
  super(name)
16
16
  end
17
-
17
+
18
18
  # Return the value as string.
19
19
  def to_s
20
20
  @value.to_s
21
21
  end
22
-
22
+
23
23
  # Return part of debug output.
24
24
  def dump
25
- super + "#{@value}"
25
+ super + to_s
26
26
  end
27
-
27
+
28
28
  protected
29
-
29
+
30
30
  # Define a +value+ from _data_ beginning at position _start_ with the _size_ in bytes and _slots_ (1 or 2).
31
31
  def get_value(data, start, size, slots=1)
32
32
  @tag = data.u1(start)
33
33
  @size = size
34
34
  @slots = slots
35
-
35
+
36
36
  data[start+1..start+size-1]
37
37
  end
38
-
38
+
39
39
  # Dummy method to "fix" unused warning of param _pool_ in Eclipse.
40
40
  def silence_unused_warning(pool)
41
- raise "pool is nil" unless pool
41
+ raise ArgumentError, 'pool is nil' unless pool
42
42
  end
43
-
43
+
44
44
  end
45
-
45
+
46
46
  class ConstantInt < Value # ZenTest SKIP
47
- def initialize(pool, data, start)
47
+
48
+ def initialize(pool, data, start)
48
49
  super()
49
50
  silence_unused_warning(pool)
50
51
  @value = get_value(data, start, 5).u4
51
52
  end
52
-
53
+
53
54
  def dump
54
55
  super + ';'
55
56
  end
56
57
  end
57
-
58
+
58
59
  class ConstantFloat < Value # ZenTest SKIP
59
- def initialize(pool, data, start)
60
+
61
+ def initialize(pool, data, start)
60
62
  super()
61
63
  silence_unused_warning(pool)
62
- @value = get_value(data, start, 5).single
64
+ @value = get_value(data, start, 5).single
63
65
  end
66
+
64
67
  def to_s
65
- super.upcase # sprintf('%E',@value)
68
+ sprintf('%.14e', @value).sub(/e(\+|-)0+/, 'e\\1')
66
69
  end
70
+
67
71
  def dump
68
72
  super + 'f;'
69
73
  end
70
74
  end
71
-
75
+
72
76
  class ConstantLong < Value # ZenTest SKIP
73
- def initialize(pool, data, start)
77
+
78
+ def initialize(pool, data, start)
74
79
  super()
75
80
  silence_unused_warning(pool)
76
81
  @value = get_value(data, start, 9, 2).u8
77
82
  end
83
+
78
84
  def dump
79
85
  super + 'l;'
80
86
  end
81
87
  end
82
-
88
+
83
89
  class ConstantDouble < Value # ZenTest SKIP
84
- def initialize(pool, data, start)
90
+
91
+ def initialize(pool, data, start)
85
92
  super()
86
93
  silence_unused_warning(pool)
87
94
  @value = get_value(data, start, 9, 2).double
88
95
  end
96
+
89
97
  def to_s
90
- @value.to_s.upcase # sprintf('%E',@value)
98
+ sprintf('%.14e', @value).sub(/e(\+|-)0+/, 'e\\1')
91
99
  end
100
+
92
101
  def dump
93
102
  super + 'd;'
94
103
  end
95
104
  end
96
-
105
+
97
106
  class ConstantAsciz < Value # ZenTest SKIP
98
107
  alias string value
99
- def initialize(pool, data, start)
108
+
109
+ def initialize(pool, data, start)
100
110
  super('Asciz')
101
111
  silence_unused_warning(pool)
102
112
  @tag = data.u1(start)
103
-
113
+
104
114
  @length = data.u2(start+1)
105
115
  @size = 3 + @length
106
116
  @value = data[start+3..start+3+@length-1]
107
117
  end
108
-
118
+
109
119
  def dump
110
120
  super + ';'
111
121
  end
112
122
  end
113
-
123
+
114
124
  end
115
125
  end
116
126
  end
@@ -6,89 +6,115 @@ require 'javaclass/classfile/references'
6
6
  require 'javaclass/classfile/access_flags'
7
7
  require 'javaclass/java_name'
8
8
 
9
- module JavaClass
10
- module ClassFile # :nodoc:
11
-
9
+ module JavaClass
10
+
11
+ # The module ClassFile is for separating namespaces. It contains the logic
12
+ # to parse a Java class file. This logic is tied to the JVM specification
13
+ # of class files, very low-level and has no usage/DSL features.
14
+ # The main entry point is JavaClassHeader. It's the only "public" class
15
+ # of the module, so the only class to require from outside.
16
+ # Author:: Peter Kofler
17
+ module ClassFile
18
+
12
19
  # Parse and disassemble Java class files, similar to the +javap+ command.
13
20
  # Provides all information of a Java class file. This is just a container for all kind of
14
- # specialised elements. The constuctor parses and creates all contained elements.
21
+ # specialised elements. The constuctor parses and creates all contained elements.
15
22
  # See:: http://java.sun.com/docs/books/jvms/second_edition/html/ClassFile.doc.html
16
23
  # See:: {en.wikipedia.org/wiki/Class}[http://en.wikipedia.org/wiki/Class_(file_format)]
17
24
  # Author:: Peter Kofler
18
25
  class JavaClassHeader
19
-
20
- attr_reader :magic
26
+
27
+ attr_reader :magic
21
28
  attr_reader :version
22
29
  attr_reader :constant_pool
23
30
  attr_reader :access_flags
24
31
  attr_reader :references
25
-
32
+ attr_reader :interfaces
33
+
26
34
  # Create a header with the binary _data_ from the class file.
27
35
  def initialize(data)
28
-
36
+
29
37
  # ClassFile {
30
- # u4 magic; - ok
31
- # u2 minor_version; - ok
32
- # u2 major_version; - ok
33
- # u2 constant_pool_count; - ok
34
- # cp_info constant_pool[constant_pool_count-1]; - ok
35
- # u2 access_flags; - ok
36
- # u2 this_class; - ok
37
- # u2 super_class; - ok
38
- # TODO implement function for fields and methods (JVM spec)
38
+ # u4 magic;
39
+ @magic = ClassMagic.new(data)
40
+
41
+ # u2 minor_version;
42
+ # u2 major_version;
43
+ @version = ClassVersion.new(data)
44
+
45
+ # u2 constant_pool_count;
46
+ # cp_info constant_pool[constant_pool_count-1];
47
+ @constant_pool = ConstantPool.new(data)
48
+ pos = 8 + @constant_pool.size
49
+
50
+ # u2 access_flags;
51
+ @access_flags = AccessFlags.new(data, pos)
52
+ pos += 2
53
+
54
+ # u2 this_class;
55
+ @this_class_idx = data.u2(pos)
56
+ pos += 2
57
+
58
+ # u2 super_class;
59
+ @super_class_idx = data.u2(pos)
60
+ pos += 2
61
+
39
62
  # u2 interfaces_count;
40
63
  # u2 interfaces[interfaces_count];
64
+ count = data.u2(pos)
65
+ @interfaces = data.u2rep(count, pos + 2).collect { |i| @constant_pool.class_item(i) }
66
+ pos += 2 + count*2
67
+
68
+ # TODO Implement parsing of fields and methods of the JVM spec
41
69
  # u2 fields_count;
42
70
  # field_info fields[fields_count];
71
+ # count = data.u2(pos)
72
+ # @fields = data.u2rep(count, pos + 2).collect { |i| @constant_pool.field_item(i) }
73
+ # pos += 2 + count*2
74
+
43
75
  # u2 methods_count;
44
76
  # method_info methods[methods_count];
77
+ # count = data.u2(pos)
78
+ # @methods = data.u2rep(count, pos + 2).collect { |i| @constant_pool.method_item(i) }
79
+ # pos += 2 + count*2
80
+
45
81
  # u2 attributes_count;
46
82
  # attribute_info attributes[attributes_count];
47
83
  # }
48
- # TODO Java 1.0 - "private protected" fields.
49
-
50
- @magic = ClassMagic.new(data)
51
- @version = ClassVersion.new(data)
52
-
53
- @constant_pool = ConstantPool.new(data)
54
- pos = 8 + @constant_pool.size
55
-
56
- @access_flags = AccessFlags.new(data, pos)
57
- pos += 2
58
-
59
- idx = data.u2(pos)
60
- pos += 2
61
- @this_class_idx = idx
62
-
63
84
  @references = References.new(@constant_pool, @this_class_idx)
64
85
 
65
- idx = data.u2(pos)
66
- pos += 2
67
- @super_class_idx = idx
86
+ # Body {
87
+ # Class: add the byte code sequences to the methods so it can be analysed later (see JVM spec)
88
+ # }
89
+
68
90
  end
69
-
70
- # Return the name of this class.
91
+
92
+ # Return the name of this class. Returns a JavaVMName.
71
93
  def this_class
72
- @constant_pool[@this_class_idx].to_s.to_javaname
94
+ # This is a ConstantClass entry in the constant pool.
95
+ @jvmname ||= @constant_pool.class_item(@this_class_idx).class_name
73
96
  end
74
-
75
- # Return the name of the superclass of this class or +nil+.
97
+
98
+ # Return the name of the superclass of this class or +nil+. Returns a JavaVMName.
76
99
  def super_class
77
100
  if @super_class_idx > 0
78
- @constant_pool[@super_class_idx].to_s.to_javaname
101
+ # This is a ConstantClass entry in the constant pool.
102
+ @constant_pool.class_item(@super_class_idx).class_name
79
103
  else
104
+ # special case: java.lang.Object has no superclass
80
105
  nil
81
106
  end
82
107
  end
83
-
108
+
84
109
  # Return a debug output of this class that looks similar to +javap+ output.
85
110
  def dump
86
111
  d = []
87
112
  mod = @access_flags.public? ? 'public ' : ''
88
- ext = super_class ? "extends #{super_class.to_classname}" : ''
89
- d << "#{mod}class #{this_class.to_classname} #{ext}"
113
+ ext = super_class ? " extends #{super_class.to_classname}" : ''
114
+ int = !@interfaces.empty? ? " implements #{@interfaces.join(',')}" : ''
115
+ d << "#{mod}class #{this_class.to_classname}#{ext}#{int}"
90
116
  # d << " SourceFile: \"#{read from LineNumberTable?}\""
91
- d += @version.dump
117
+ d += @version.dump
92
118
  d += @constant_pool.dump
93
119
  d << ''
94
120
  d << '{'
@@ -97,6 +123,6 @@ module JavaClass
97
123
  end
98
124
 
99
125
  end
100
-
126
+
101
127
  end
102
128
  end
@@ -0,0 +1,33 @@
1
+ require 'javaclass/delegate_directive'
2
+
3
+ module JavaClass
4
+ module ClassFile
5
+
6
+ class JavaClassHeader
7
+ extend DelegateDirective
8
+
9
+ # Extend JavaClassHeader to behave like a JavaName in delegating to _this_class_ method which returns a JavaVMName.
10
+ def to_javaname
11
+ this_class
12
+ end
13
+
14
+ def to_jvmname
15
+ this_class
16
+ end
17
+
18
+ delegate :to_classname, :this_class
19
+ delegate :to_java_file, :this_class
20
+ delegate :to_class_file, :this_class
21
+
22
+ delegate :package, :this_class
23
+ delegate :simple_name, :this_class
24
+ delegate :full_name, :this_class
25
+ delegate :same_or_subpackage_of?, :this_class
26
+ delegate :subpackage_of?, :this_class
27
+ delegate :split_simple_name, :this_class
28
+ delegate :in_jdk?, :this_class
29
+
30
+ end
31
+
32
+ end
33
+ end
@@ -0,0 +1,19 @@
1
+ module JavaClass
2
+ module ClassFile
3
+
4
+ class JavaClassHeader
5
+
6
+ # Is this class an interface (and not an annotation)?
7
+ def interface?
8
+ access_flags.interface? && !access_flags.annotation?
9
+ end
10
+
11
+ # Is this class an abstract class (and not an interface)?
12
+ def abstract_class?
13
+ access_flags.abstract? && !access_flags.interface?
14
+ end
15
+
16
+ end
17
+
18
+ end
19
+ end