javaclass 0.0.3 → 0.0.4
Sign up to get free protection for your applications and to get access to all the features.
- data/Rakefile +67 -56
- data/Readme.txt +42 -39
- data/example_task.rb +172 -0
- data/examples/check_interface_names.rb +44 -0
- data/examples/corpus.rb +19 -0
- data/examples/count_classes_in_modules.rb +38 -0
- data/examples/cumulative_dependencies.rb +39 -0
- data/examples/find_all_imported_types.rb +44 -0
- data/examples/find_referenced_modules.rb +53 -0
- data/examples/find_unreferenced_classes.rb +65 -0
- data/examples/generate_class_lists.rb +67 -43
- data/examples/profiler_scratchpad.rb +33 -0
- data/examples/simple_usage.rb +42 -0
- data/history.txt +29 -7
- data/javaclass.gemspec +31 -0
- data/lib/javaclass/adder_tree.rb +92 -0
- data/lib/javaclass/analyse/dependencies.rb +52 -0
- data/lib/javaclass/{metric/metrics.txt → analyse/ideas.txt} +2 -2
- data/lib/javaclass/analyse/transitive_dependencies.rb +52 -0
- data/lib/javaclass/classfile/access_flag_constants.rb +24 -0
- data/lib/javaclass/classfile/access_flags.rb +49 -26
- data/lib/javaclass/classfile/class_format_error.rb +37 -0
- data/lib/javaclass/classfile/class_magic.rb +16 -8
- data/lib/javaclass/classfile/class_version.rb +19 -25
- data/lib/javaclass/classfile/constant_pool.rb +110 -45
- data/lib/javaclass/classfile/constants/base.rb +33 -12
- data/lib/javaclass/classfile/constants/double_reference.rb +55 -41
- data/lib/javaclass/classfile/constants/single_reference.rb +29 -21
- data/lib/javaclass/classfile/constants/value.rb +43 -33
- data/lib/javaclass/classfile/java_class_header.rb +72 -46
- data/lib/javaclass/classfile/java_class_header_as_java_name.rb +33 -0
- data/lib/javaclass/classfile/java_class_header_shortcuts.rb +19 -0
- data/lib/javaclass/classfile/references.rb +21 -19
- data/lib/javaclass/classlist/class_entry.rb +26 -27
- data/lib/javaclass/classlist/jar_searcher.rb +34 -25
- data/lib/javaclass/classlist/list.rb +31 -31
- data/lib/javaclass/classlist/package_entry.rb +25 -24
- data/lib/javaclass/classpath/any_classpath.rb +48 -0
- data/lib/javaclass/classpath/class_not_found_error.rb +20 -0
- data/lib/javaclass/classpath/classpaths.txt +2 -2
- data/lib/javaclass/classpath/composite_classpath.rb +56 -54
- data/lib/javaclass/classpath/convention_classpath.rb +38 -0
- data/lib/javaclass/classpath/eclipse_classpath.rb +74 -0
- data/lib/javaclass/classpath/factory.rb +65 -0
- data/lib/javaclass/classpath/file_classpath.rb +47 -0
- data/lib/javaclass/classpath/folder_classpath.rb +42 -44
- data/lib/javaclass/classpath/jar_classpath.rb +91 -52
- data/lib/javaclass/classpath/java_home_classpath.rb +24 -13
- data/lib/javaclass/classpath/maven_classpath.rb +44 -0
- data/lib/javaclass/classpath/temporary_unpacker.rb +111 -0
- data/lib/javaclass/classpath/tracking_classpath.rb +144 -0
- data/lib/javaclass/classscanner/ideas.txt +3 -0
- data/lib/javaclass/classscanner/imported_types.rb +29 -0
- data/lib/javaclass/classscanner/scanners.rb +29 -0
- data/lib/javaclass/delegate_directive.rb +15 -0
- data/lib/javaclass/dsl/caching_classpath.rb +38 -0
- data/lib/javaclass/dsl/classpath_analysers.rb +27 -0
- data/lib/javaclass/dsl/java_name_factory.rb +79 -0
- data/lib/javaclass/dsl/loader.rb +42 -0
- data/lib/javaclass/dsl/loading_classpath.rb +53 -0
- data/lib/javaclass/dsl/mixin.rb +54 -0
- data/lib/javaclass/gems/zip_file.rb +154 -0
- data/lib/javaclass/java_language.rb +50 -0
- data/lib/javaclass/java_name.rb +329 -55
- data/lib/javaclass/java_name_scanner.rb +95 -0
- data/lib/javaclass/resources/iso_3166_countries.txt +240 -0
- data/lib/javaclass/resources/jdk0_packages.txt +6 -0
- data/lib/javaclass/resources/jdk1_packages.txt +6 -0
- data/lib/javaclass/resources/jdk2_packages.txt +4 -0
- data/lib/javaclass/resources/jdk3_packages.txt +6 -0
- data/lib/javaclass/resources/jdk4_packages.txt +22 -0
- data/lib/javaclass/resources/jdk5_packages.txt +5 -0
- data/lib/javaclass/resources/jdk6_packages.txt +7 -0
- data/lib/javaclass/resources/jdk7_packages.txt +0 -0
- data/lib/javaclass/resources/jdk_packages.txt +53 -0
- data/lib/javaclass/resources/reserved_words.txt +50 -0
- data/lib/javaclass/string_hexdump.rb +76 -0
- data/lib/javaclass/string_ux.rb +21 -10
- data/lib/javaclass.rb +16 -41
- data/license.txt +28 -0
- data/planned.txt +13 -0
- data/test/data/Object_102.class +0 -0
- data/test/data/Runnable_102.class +0 -0
- data/test/data/access_flags/AccessFlagsTestAnnotation.class +0 -0
- data/test/data/access_flags/AccessFlagsTestAnnotation.java +3 -0
- data/test/data/access_flags/AccessFlagsTestEnum$1.class +0 -0
- data/test/data/access_flags/AccessFlagsTestEnum.class +0 -0
- data/test/data/access_flags/AccessFlagsTestEnum.java +6 -0
- data/test/data/access_flags/AccessFlagsTestInner$1.class +0 -0
- data/test/data/access_flags/AccessFlagsTestInner$2.class +0 -0
- data/test/data/access_flags/AccessFlagsTestInner.class +0 -0
- data/test/data/access_flags/AccessFlagsTestInner.java +13 -0
- data/test/data/access_flags/AccessFlagsTestPackage.class +0 -0
- data/test/data/access_flags/AccessFlagsTestPackage.java +1 -1
- data/test/data/api/packagename/AccessFlagsTestPublic.class +0 -0
- data/test/data/class_version/ClassVersionTest17.class +0 -0
- data/test/data/class_version/make.bat +6 -2
- data/test/data/eclipse_classpath/classes/ClassVersionTest12.class +0 -0
- data/test/data/eclipse_classpath/lib/JarClasspathTest.jar +0 -0
- data/test/data/eclipse_classpath/test-classes/ClassVersionTest13.class +0 -0
- data/test/data/folder_classpath/{JarClasspathTestFolder → classes}/ClassVersionTest10.class +0 -0
- data/test/data/folder_classpath/{JarClasspathTestFolder → classes}/package/ClassVersionTest11.class +0 -0
- data/test/data/jar_classpath/JarClasspathTest.jar +0 -0
- data/test/data/jar_classpath/JarClasspathTest.zip +0 -0
- data/test/data/jar_classpath/JarClasspathTestManifest.jar +0 -0
- data/test/data/jar_classpath/JarClasspathTestMultiManifest.jar +0 -0
- data/test/data/jar_classpath/make.bat +6 -2
- data/test/data/jar_searcher/BrokenRunnable_102.class +0 -0
- data/test/data/java_home_classpath/jdk118/lib/classes.zip +0 -0
- data/test/data/java_name_scanner/META-INF/MANIFEST.MF +12 -0
- data/test/data/java_name_scanner/plugin.xml +18 -0
- data/test/data/maven_classpath/module/pom.xml +8 -0
- data/test/data/maven_classpath/module/target/classes/ClassVersionTest12.class +0 -0
- data/test/data/maven_classpath/pom.xml +8 -0
- data/test/data/maven_classpath/target/classes/ClassVersionTest10.class +0 -0
- data/test/data/maven_classpath/target/test-classes/ClassVersionTest11.class +0 -0
- data/test/data/transitive_dependencies/A.class +0 -0
- data/test/data/transitive_dependencies/A.java +5 -0
- data/test/data/transitive_dependencies/B.class +0 -0
- data/test/data/transitive_dependencies/B.java +3 -0
- data/test/data/transitive_dependencies/C.class +0 -0
- data/test/data/transitive_dependencies/C.java +3 -0
- data/test/data/transitive_dependencies/Start.class +0 -0
- data/test/data/transitive_dependencies/Start.java +4 -0
- data/test/data/transitive_dependencies/make.bat +3 -0
- data/test/data/zip_file/commons-math-2.2-broken.zip +0 -0
- data/test/data/zip_file/regenerated-with-7zip.zip +0 -0
- data/test/data/zip_file/regenerated-with-jar.zip +0 -0
- data/test/dot_classpath.rb +33 -0
- data/test/logging_folder_classpath.rb +19 -0
- data/test/setup.rb +1 -1
- data/test/test_access_flags.rb +58 -32
- data/test/test_adder_tree.rb +78 -0
- data/test/test_any_classpath.rb +39 -0
- data/test/test_base.rb +9 -7
- data/test/test_caching_classpath.rb +41 -0
- data/test/test_class_entry.rb +60 -60
- data/test/test_class_magic.rb +31 -0
- data/test/test_class_version.rb +25 -25
- data/test/test_composite_classpath.rb +22 -23
- data/test/test_constant_pool.rb +37 -13
- data/test/test_convention_classpath.rb +39 -0
- data/test/test_eclipse_classpath.rb +73 -0
- data/test/test_factory.rb +61 -0
- data/test/test_folder_classpath.rb +26 -10
- data/test/test_imported_types.rb +34 -0
- data/test/test_jar_classpath.rb +29 -14
- data/test/test_jar_searcher.rb +27 -14
- data/test/test_java_class_header.rb +22 -10
- data/test/test_java_class_header_as_java_name.rb +41 -0
- data/test/test_java_home_classpath.rb +17 -11
- data/test/test_java_name.rb +204 -64
- data/test/test_java_name_factory.rb +52 -0
- data/test/test_java_name_scanner.rb +24 -0
- data/test/test_javaclass_api.rb +43 -0
- data/test/test_list.rb +58 -44
- data/test/test_load_directive.rb +34 -0
- data/test/test_maven_classpath.rb +46 -0
- data/test/test_package_entry.rb +27 -22
- data/test/test_references.rb +14 -14
- data/test/test_string_hexdump.rb +24 -0
- data/test/test_string_ux.rb +18 -106
- data/test/test_tracking_classpath.rb +112 -0
- data/test/test_transitive_dependencies.rb +31 -0
- data/test/test_unpacking_jar_classpath.rb +43 -0
- data/test/test_zip_file.rb +33 -0
- data/test/ts_all_tests.rb +80 -18
- data/thanks.txt +2 -0
- metadata +151 -22
- data/lib/javaclass/classpath/port_ClassPathEntry.java +0 -202
- data/lib/javaclass/classpath/port_ClassPathEntryFactory.java +0 -311
- data/lib/javaclass/classpath/port_DirectoryRepository.java +0 -24
- data/lib/javaclass/metric/ccd.rb +0 -68
- data/lib/javaclass/metric/class_usage.rb +0 -41
- 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
|
-
|
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
|
-
|
46
|
-
|
47
|
-
super
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
49
|
-
|
50
|
-
super
|
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
|
-
|
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 +
|
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
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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.
|
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
|
-
|
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
|
-
|
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;
|
31
|
-
|
32
|
-
|
33
|
-
# u2
|
34
|
-
#
|
35
|
-
|
36
|
-
|
37
|
-
# u2
|
38
|
-
#
|
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
|
-
|
66
|
-
|
67
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|