javaclass 0.0.3 → 0.0.4

Sign up to get free protection for your applications and to get access to all the features.
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