javaclass 0.0.2 → 0.0.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (111) hide show
  1. data/Rakefile +208 -23
  2. data/Readme.txt +56 -19
  3. data/examples/generate_class_lists.rb +61 -0
  4. data/history.txt +13 -19
  5. data/lib/javaclass/classfile/access_flags.rb +52 -0
  6. data/lib/javaclass/classfile/class_magic.rb +29 -0
  7. data/lib/javaclass/classfile/class_version.rb +67 -0
  8. data/lib/javaclass/classfile/constant_pool.rb +91 -0
  9. data/lib/javaclass/classfile/constants/base.rb +33 -0
  10. data/lib/javaclass/classfile/constants/double_reference.rb +99 -0
  11. data/lib/javaclass/classfile/constants/single_reference.rb +65 -0
  12. data/lib/javaclass/classfile/constants/value.rb +116 -0
  13. data/lib/javaclass/classfile/java_class_header.rb +102 -0
  14. data/lib/javaclass/classfile/references.rb +43 -0
  15. data/lib/javaclass/classlist/class_entry.rb +89 -0
  16. data/lib/javaclass/classlist/jar_searcher.rb +69 -0
  17. data/lib/javaclass/classlist/list.rb +126 -0
  18. data/lib/javaclass/classlist/package_entry.rb +87 -0
  19. data/lib/javaclass/classpath/classpaths.txt +2 -0
  20. data/lib/javaclass/classpath/composite_classpath.rb +99 -0
  21. data/lib/javaclass/classpath/folder_classpath.rb +83 -0
  22. data/lib/javaclass/classpath/jar_classpath.rb +100 -0
  23. data/lib/javaclass/classpath/java_home_classpath.rb +40 -0
  24. data/lib/javaclass/classpath/port_ClassPathEntry.java +202 -0
  25. data/lib/javaclass/classpath/port_ClassPathEntryFactory.java +311 -0
  26. data/lib/javaclass/classpath/port_DirectoryRepository.java +24 -0
  27. data/lib/javaclass/java_name.rb +90 -0
  28. data/lib/javaclass/metric/ccd.rb +68 -0
  29. data/lib/javaclass/metric/class_usage.rb +41 -0
  30. data/lib/javaclass/metric/metrics.txt +15 -0
  31. data/lib/javaclass.rb +44 -11
  32. data/test/data/ShortClientData$1-4000Wert.class +0 -0
  33. data/test/data/{AccessFlagsTestAbstract.class → access_flags/AccessFlagsTestAbstract.class} +0 -0
  34. data/test/data/{AccessFlagsTestAbstract.java → access_flags/AccessFlagsTestAbstract.java} +0 -0
  35. data/test/data/{AccessFlagsTestFinal.class → access_flags/AccessFlagsTestFinal.class} +0 -0
  36. data/test/data/{AccessFlagsTestFinal.java → access_flags/AccessFlagsTestFinal.java} +0 -0
  37. data/test/data/{AccessFlagsTestInterface.class → access_flags/AccessFlagsTestInterface.class} +0 -0
  38. data/test/data/{AccessFlagsTestInterface.java → access_flags/AccessFlagsTestInterface.java} +0 -0
  39. data/test/data/{AccessFlagsTestPackage.class → access_flags/AccessFlagsTestPackage.class} +0 -0
  40. data/test/data/{AccessFlagsTestPackage.java → access_flags/AccessFlagsTestPackage.java} +0 -0
  41. data/test/data/access_flags/AccessFlagsTestPublic$Inner.class +0 -0
  42. data/test/data/access_flags/AccessFlagsTestPublic$InnerInterface.class +0 -0
  43. data/test/data/access_flags/AccessFlagsTestPublic$StaticInner.class +0 -0
  44. data/test/data/access_flags/AccessFlagsTestPublic.class +0 -0
  45. data/test/data/access_flags/AccessFlagsTestPublic.java +11 -0
  46. data/test/data/access_flags/AccessFlagsTestPublic_javap.txt +29 -0
  47. data/test/data/{makeAccessFlagsTest.bat → access_flags/make.bat} +0 -0
  48. data/test/data/{ClassVersionTest.java → class_version/ClassVersionTest.java} +0 -0
  49. data/test/data/{ClassVersionTest10.class → class_version/ClassVersionTest10.class} +0 -0
  50. data/test/data/{ClassVersionTest11.class → class_version/ClassVersionTest11.class} +0 -0
  51. data/test/data/{ClassVersionTest12.class → class_version/ClassVersionTest12.class} +0 -0
  52. data/test/data/{ClassVersionTest13.class → class_version/ClassVersionTest13.class} +0 -0
  53. data/test/data/{ClassVersionTest14.class → class_version/ClassVersionTest14.class} +0 -0
  54. data/test/data/{ClassVersionTest15.class → class_version/ClassVersionTest15.class} +0 -0
  55. data/test/data/{ClassVersionTest16.class → class_version/ClassVersionTest16.class} +0 -0
  56. data/test/data/{makeClassVersionTest.bat → class_version/make.bat} +0 -0
  57. data/test/data/{ConstantPoolTest.class → constant_pool/ConstantPoolTest.class} +0 -0
  58. data/test/data/{ConstantPoolTest.java → constant_pool/ConstantPoolTest.java} +0 -0
  59. data/test/data/{makeConstantPoolTest.bat → constant_pool/make.bat} +0 -0
  60. data/test/data/folder_classpath/JarClasspathTestFolder/ClassVersionTest10.class +0 -0
  61. data/test/data/folder_classpath/JarClasspathTestFolder/package/ClassVersionTest11.class +0 -0
  62. data/test/data/jar_classpath/JarClasspathTest.jar +0 -0
  63. data/test/data/jar_classpath/JarClasspathTest.zip +0 -0
  64. data/test/data/jar_classpath/JarClasspathTestManifest.jar +0 -0
  65. data/test/data/jar_classpath/JarClasspathTestMultiManifest.jar +0 -0
  66. data/test/data/jar_classpath/make.bat +24 -0
  67. data/test/data/jar_searcher/JarClassListTest.jar +0 -0
  68. data/test/data/jar_searcher/PublicClass.java +12 -0
  69. data/test/data/jar_searcher/PublicInterface.java +5 -0
  70. data/test/data/jar_searcher/make.bat +13 -0
  71. data/test/data/java_home_classpath/jdk/jre/lib/rt.jar +0 -0
  72. data/test/data/java_home_classpath/jre/lib/rt.jar +0 -0
  73. data/test/data/java_home_classpath/jre-ext/lib/ext/ext.jar +0 -0
  74. data/test/data/java_home_classpath/jre-ext/lib/rt.jar +0 -0
  75. data/test/data/java_home_classpath/make.bat +13 -0
  76. data/test/data/references/ReferencesTest.class +0 -0
  77. data/test/data/references/ReferencesTest.java +12 -0
  78. data/test/data/references/make.bat +5 -0
  79. data/test/setup.rb +6 -5
  80. data/test/test_access_flags.rb +59 -44
  81. data/test/test_base.rb +20 -15
  82. data/test/test_class_entry.rb +198 -0
  83. data/test/test_class_version.rb +48 -46
  84. data/test/test_composite_classpath.rb +68 -0
  85. data/test/test_constant_pool.rb +49 -41
  86. data/test/test_folder_classpath.rb +45 -0
  87. data/test/test_jar_classpath.rb +57 -0
  88. data/test/test_jar_searcher.rb +93 -0
  89. data/test/test_java_class_header.rb +34 -22
  90. data/test/test_java_home_classpath.rb +50 -0
  91. data/test/test_java_name.rb +110 -0
  92. data/test/test_javaclass.rb +22 -0
  93. data/test/test_list.rb +123 -0
  94. data/test/test_package_entry.rb +91 -0
  95. data/test/test_references.rb +38 -20
  96. data/test/test_string_ux.rb +99 -2
  97. data/test/ts_all_tests.rb +42 -21
  98. metadata +171 -50
  99. data/lib/javaclass/access_flags.rb +0 -44
  100. data/lib/javaclass/class_magic.rb +0 -27
  101. data/lib/javaclass/class_version.rb +0 -65
  102. data/lib/javaclass/constant_pool.rb +0 -85
  103. data/lib/javaclass/constants/base.rb +0 -31
  104. data/lib/javaclass/constants/double_reference.rb +0 -81
  105. data/lib/javaclass/constants/single_reference.rb +0 -58
  106. data/lib/javaclass/constants/value.rb +0 -114
  107. data/lib/javaclass/java_class_header.rb +0 -88
  108. data/lib/javaclass/references.rb +0 -31
  109. data/test/data/AccessFlagsTestPublic$InnerClass.class +0 -0
  110. data/test/data/AccessFlagsTestPublic.class +0 -0
  111. data/test/data/AccessFlagsTestPublic.java +0 -7
@@ -0,0 +1,91 @@
1
+ require 'javaclass/string_ux'
2
+ require 'javaclass/classfile/constants/value'
3
+ require 'javaclass/classfile/constants/single_reference'
4
+ require 'javaclass/classfile/constants/double_reference'
5
+
6
+ module JavaClass
7
+ module ClassFile
8
+
9
+ # Container of the constant pool's constants.
10
+ # Author:: Peter Kofler
11
+ class ConstantPool
12
+
13
+ # Types of constants by their +tag+.
14
+ CONSTANT_TYPE_TAGS = {
15
+ CLASS_TAG = 7 => Constants::ConstantClass,
16
+ FIELD_TAG = 9 => Constants::ConstantField,
17
+ METHOD_TAG = 10 => Constants::ConstantMethod,
18
+ INTERFACE_METHOD_TAG = 11 => Constants::ConstantInterfaceMethod,
19
+ STRING_TAG = 8 => Constants::ConstantString,
20
+ INT_TAG = 3 => Constants::ConstantInt,
21
+ FLOAT_TAG = 4 => Constants::ConstantFloat,
22
+ LONG_TAG = 5 => Constants::ConstantLong,
23
+ DOUBLE_TAG = 6 => Constants::ConstantDouble,
24
+ NAME_AND_TYPE_TAG = 12 => Constants::ConstantNameAndType,
25
+ ASCIZ_TAG = 1 => Constants::ConstantAsciz,
26
+ }
27
+
28
+ # Size of the whole constant pool in bytes.
29
+ attr_reader :size
30
+
31
+ # Parse the constant pool from the bytes _data_ beginning at position _start_ (which is usually 8).
32
+ def initialize(data, start=8)
33
+ @pool = {} # cnt (fixnum) => constant
34
+
35
+ # parsing
36
+ @item_count = data.u2(start)
37
+ pos = start + 2
38
+ cnt = 1
39
+ while cnt <= @item_count-1
40
+
41
+ type = CONSTANT_TYPE_TAGS[data.u1(pos)]
42
+ unless type
43
+ #puts dump.join("\n")
44
+ raise "const ##{cnt} = unknown constant pool tag #{data[pos]} at pos #{pos} in class"
45
+ end
46
+
47
+ constant = type.new(@pool, data, pos)
48
+ @pool[cnt] = constant
49
+ pos += constant.size
50
+ cnt += constant.slots
51
+
52
+ end
53
+
54
+ @size = pos - start
55
+ end
56
+
57
+ # Return the number of pool items. This number might be larger than +items+ available,
58
+ # because +long+ and +double+ constants take two slots.
59
+ def item_count
60
+ @item_count-1
61
+ end
62
+
63
+ # Return the _index_'th pool item. _index_ is the real index in the pool which may skip numbers.
64
+ def[](index)
65
+ @pool[index]
66
+ end
67
+
68
+ # Return an array of the ordered list of constants.
69
+ def items
70
+ @pool.keys.sort.collect { |k| self[k] }
71
+ end
72
+
73
+ # Return an array of all constants of the given _tags_ types.
74
+ def find(*tags)
75
+ items.find_all { |item| tags.include? item.tag }
76
+ end
77
+
78
+ # Return all string constants.
79
+ def strings
80
+ find(STRING_TAG)
81
+ end
82
+
83
+ # Return a debug output of the whole pool.
84
+ def dump
85
+ [" Constant pool:"] + @pool.keys.sort.collect { |k| "const ##{k} = #{self[k].dump}"}
86
+ end
87
+
88
+ end
89
+
90
+ end
91
+ end
@@ -0,0 +1,33 @@
1
+ require 'javaclass/string_ux'
2
+
3
+ module JavaClass
4
+ module ClassFile
5
+ module Constants # :nodoc:
6
+
7
+ # Superclass of all constant values in the constant pool. Every constant has a +name+, a +tag+ and a +size+ in bytes.
8
+ # Author:: Peter Kofler
9
+ class Base # ZenTest FULL to find method name
10
+
11
+ attr_reader :name
12
+ attr_reader :tag
13
+ attr_reader :size
14
+ attr_reader :slots
15
+
16
+ # Set default constants.
17
+ def initialize(name=nil)
18
+ @name = self.class.to_s[/::[^:]+$/][10..-1] # skip modules (::) and "Constant"
19
+ @name = name if name
20
+ @size = 3
21
+ @slots = 1
22
+ end
23
+
24
+ # Return part of debug output.
25
+ def dump
26
+ "#{@name}\t" # #{@tag}
27
+ end
28
+
29
+ end
30
+
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,99 @@
1
+ require 'javaclass/classfile/constants/single_reference'
2
+ require 'javaclass/java_name'
3
+
4
+ module JavaClass
5
+ module ClassFile
6
+ module Constants
7
+
8
+ # Superclass of double reference constants like +ConstantField+ (+FieldRef+) in the constant pool.
9
+ # Author:: Peter Kofler
10
+ class DoubleReference < SingleReference
11
+
12
+ attr_reader :second_index
13
+
14
+ # Define a double reference into _pool_ from _data_ beginning at _start_
15
+ def initialize(pool, data, start, name=nil)
16
+ super(pool, data, start, name)
17
+ @size = 5
18
+
19
+ @second_index = data.u2(start+3)
20
+ end
21
+
22
+ # Return the second value, which is the referenced value from the pool.
23
+ def second_value
24
+ get(@second_index)
25
+ end
26
+
27
+ # Return the value, which are both referenced values from the pool.
28
+ def to_s
29
+ "#{super}.#{second_value}"
30
+ end
31
+
32
+ # Return part of debug output.
33
+ def dump
34
+ "#{@name}\t##{@first_index}.##{@second_index};\t// #{to_s}"
35
+ end
36
+
37
+ end
38
+
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)
43
+ super(pool, data, start)
44
+ end
45
+ def first_value
46
+ # is a classname
47
+ super.to_javaname
48
+ end
49
+ alias class_name first_value
50
+ alias signature second_value
51
+ end
52
+
53
+ 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)
57
+ super(pool, data, start)
58
+ end
59
+ def first_value
60
+ # is a classname
61
+ super.to_javaname
62
+ end
63
+ alias class_name first_value
64
+ alias signature second_value
65
+ end
66
+
67
+ 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)
71
+ super(pool, data, start)
72
+ end
73
+ def first_value
74
+ # is a classname
75
+ super.to_javaname
76
+ end
77
+ alias class_name first_value
78
+ alias signature second_value
79
+ end
80
+
81
+ class ConstantNameAndType < DoubleReference # ZenTest SKIP
82
+ alias name_index first_index
83
+ alias descriptor_index second_index
84
+ def initialize(pool, data, start)
85
+ super(pool, data, start)
86
+ end
87
+
88
+ def to_s
89
+ "#{get(name_index)}:#{get(descriptor_index)}"
90
+ end
91
+
92
+ def dump
93
+ "#{@name}\t##{name_index}:##{descriptor_index};// #{to_s}"
94
+ end
95
+ end
96
+
97
+ end
98
+ end
99
+ end
@@ -0,0 +1,65 @@
1
+ require 'javaclass/classfile/constants/base'
2
+ require 'javaclass/java_name'
3
+
4
+ module JavaClass
5
+ module ClassFile
6
+ module Constants
7
+
8
+ # Superclass of single reference constants like +ConstantClass+ (+Class+) in the constant pool.
9
+ # Author:: Peter Kofler
10
+ class SingleReference < Base
11
+
12
+ attr_reader :first_index
13
+
14
+ # Define a single reference into _pool_ from _data_ beginning at _start_
15
+ def initialize(pool, data, start, name=nil)
16
+ super(name)
17
+ @tag = data.u1(start)
18
+
19
+ @enclosing_pool = pool
20
+ @first_index = data.u2(start+1)
21
+ end
22
+
23
+ # Return the value, which is the referenced value from the pool.
24
+ def first_value
25
+ get(@first_index)
26
+ end
27
+ alias to_s first_value
28
+
29
+ # Return part of debug output.
30
+ def dump
31
+ super + "##{@first_index};\t// #{to_s}"
32
+ end
33
+
34
+ protected
35
+
36
+ # Get a reference _ref_ from the +enclosing_pool+
37
+ def get(ref)
38
+ @enclosing_pool[ref].to_s
39
+ end
40
+
41
+ end
42
+
43
+ class ConstantClass < SingleReference # ZenTest SKIP
44
+ alias name_index first_index
45
+ def initialize(pool, data, start)
46
+ super(pool, data, start, "class")
47
+ end
48
+ def first_value
49
+ # is a classname
50
+ super.to_javaname
51
+ end
52
+ alias class_name first_value
53
+ end
54
+
55
+ class ConstantString < SingleReference # ZenTest SKIP
56
+ alias string_index first_index
57
+ def initialize(pool, data, start)
58
+ super(pool, data, start)
59
+ end
60
+ alias string_value first_value
61
+ end
62
+
63
+ end
64
+ end
65
+ end
@@ -0,0 +1,116 @@
1
+ require 'javaclass/classfile/constants/base'
2
+
3
+ module JavaClass
4
+ module ClassFile
5
+ module Constants
6
+
7
+ # Superclass of value constants like +ConstantInt+ (+Integer+) in the constant pool.
8
+ # Author:: Peter Kofler
9
+ class Value < Base
10
+
11
+ attr_reader :value
12
+
13
+ # Create a constant value with an optional downcase _name_
14
+ def initialize(name=self.class.to_s[/::[^:]+$/][10..-1].downcase)
15
+ super(name)
16
+ end
17
+
18
+ # Return the value as string.
19
+ def to_s
20
+ @value.to_s
21
+ end
22
+
23
+ # Return part of debug output.
24
+ def dump
25
+ super + "#{@value}"
26
+ end
27
+
28
+ protected
29
+
30
+ # Define a +value+ from _data_ beginning at position _start_ with the _size_ in bytes and _slots_ (1 or 2).
31
+ def get_value(data, start, size, slots=1)
32
+ @tag = data.u1(start)
33
+ @size = size
34
+ @slots = slots
35
+
36
+ data[start+1..start+size-1]
37
+ end
38
+
39
+ # Dummy method to "fix" unused warning of param _pool_ in Eclipse.
40
+ def silence_unused_warning(pool)
41
+ raise "pool is nil" unless pool
42
+ end
43
+
44
+ end
45
+
46
+ class ConstantInt < Value # ZenTest SKIP
47
+ def initialize(pool, data, start)
48
+ super()
49
+ silence_unused_warning(pool)
50
+ @value = get_value(data, start, 5).u4
51
+ end
52
+
53
+ def dump
54
+ super + ';'
55
+ end
56
+ end
57
+
58
+ class ConstantFloat < Value # ZenTest SKIP
59
+ def initialize(pool, data, start)
60
+ super()
61
+ silence_unused_warning(pool)
62
+ @value = get_value(data, start, 5).single
63
+ end
64
+ def to_s
65
+ super.upcase # sprintf('%E',@value)
66
+ end
67
+ def dump
68
+ super + 'f;'
69
+ end
70
+ end
71
+
72
+ class ConstantLong < Value # ZenTest SKIP
73
+ def initialize(pool, data, start)
74
+ super()
75
+ silence_unused_warning(pool)
76
+ @value = get_value(data, start, 9, 2).u8
77
+ end
78
+ def dump
79
+ super + 'l;'
80
+ end
81
+ end
82
+
83
+ class ConstantDouble < Value # ZenTest SKIP
84
+ def initialize(pool, data, start)
85
+ super()
86
+ silence_unused_warning(pool)
87
+ @value = get_value(data, start, 9, 2).double
88
+ end
89
+ def to_s
90
+ @value.to_s.upcase # sprintf('%E',@value)
91
+ end
92
+ def dump
93
+ super + 'd;'
94
+ end
95
+ end
96
+
97
+ class ConstantAsciz < Value # ZenTest SKIP
98
+ alias string value
99
+ def initialize(pool, data, start)
100
+ super('Asciz')
101
+ silence_unused_warning(pool)
102
+ @tag = data.u1(start)
103
+
104
+ @length = data.u2(start+1)
105
+ @size = 3 + @length
106
+ @value = data[start+3..start+3+@length-1]
107
+ end
108
+
109
+ def dump
110
+ super + ';'
111
+ end
112
+ end
113
+
114
+ end
115
+ end
116
+ end
@@ -0,0 +1,102 @@
1
+ require 'javaclass/string_ux'
2
+ require 'javaclass/classfile/class_magic'
3
+ require 'javaclass/classfile/class_version'
4
+ require 'javaclass/classfile/constant_pool'
5
+ require 'javaclass/classfile/references'
6
+ require 'javaclass/classfile/access_flags'
7
+ require 'javaclass/java_name'
8
+
9
+ module JavaClass
10
+ module ClassFile # :nodoc:
11
+
12
+ # Parse and disassemble Java class files, similar to the +javap+ command.
13
+ # 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.
15
+ # See:: http://java.sun.com/docs/books/jvms/second_edition/html/ClassFile.doc.html
16
+ # See:: {en.wikipedia.org/wiki/Class}[http://en.wikipedia.org/wiki/Class_(file_format)]
17
+ # Author:: Peter Kofler
18
+ class JavaClassHeader
19
+
20
+ attr_reader :magic
21
+ attr_reader :version
22
+ attr_reader :constant_pool
23
+ attr_reader :access_flags
24
+ attr_reader :references
25
+
26
+ # Create a header with the binary _data_ from the class file.
27
+ def initialize(data)
28
+
29
+ # 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)
39
+ # u2 interfaces_count;
40
+ # u2 interfaces[interfaces_count];
41
+ # u2 fields_count;
42
+ # field_info fields[fields_count];
43
+ # u2 methods_count;
44
+ # method_info methods[methods_count];
45
+ # u2 attributes_count;
46
+ # attribute_info attributes[attributes_count];
47
+ # }
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
+ @references = References.new(@constant_pool, @this_class_idx)
64
+
65
+ idx = data.u2(pos)
66
+ pos += 2
67
+ @super_class_idx = idx
68
+ end
69
+
70
+ # Return the name of this class.
71
+ def this_class
72
+ @constant_pool[@this_class_idx].to_s.to_javaname
73
+ end
74
+
75
+ # Return the name of the superclass of this class or +nil+.
76
+ def super_class
77
+ if @super_class_idx > 0
78
+ @constant_pool[@super_class_idx].to_s.to_javaname
79
+ else
80
+ nil
81
+ end
82
+ end
83
+
84
+ # Return a debug output of this class that looks similar to +javap+ output.
85
+ def dump
86
+ d = []
87
+ mod = @access_flags.public? ? 'public ' : ''
88
+ ext = super_class ? "extends #{super_class.to_classname}" : ''
89
+ d << "#{mod}class #{this_class.to_classname} #{ext}"
90
+ # d << " SourceFile: \"#{read from LineNumberTable?}\""
91
+ d += @version.dump
92
+ d += @constant_pool.dump
93
+ d << ''
94
+ d << '{'
95
+ d << '}'
96
+ d
97
+ end
98
+
99
+ end
100
+
101
+ end
102
+ end
@@ -0,0 +1,43 @@
1
+ require 'javaclass/classfile/constant_pool'
2
+
3
+ module JavaClass
4
+ module ClassFile
5
+
6
+ # Container class for list of all classes, methods and fields referenced by this class.
7
+ # This information is derived from the constant pool, no analysis.
8
+ # Author:: Peter Kofler
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.
12
+ def initialize(pool, classidx)
13
+ @constant_pool = pool
14
+ @class_idx = classidx
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.
19
+ def referenced_fields(includeown=false)
20
+ @constant_pool.find(ConstantPool::FIELD_TAG).find_all do |field|
21
+ includeown || field.class_index != @class_idx
22
+ end
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.
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
30
+ end
31
+ end
32
+
33
+ # Return the list of all constants containing class names of all used classes.
34
+ def used_classes
35
+ @constant_pool.find(ConstantPool::CLASS_TAG).find_all do |cl|
36
+ cl.class_name != @constant_pool[@class_idx].to_s
37
+ end
38
+ end
39
+
40
+ end
41
+
42
+ end
43
+ end
@@ -0,0 +1,89 @@
1
+ require 'javaclass/java_name'
2
+
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.
7
+ # Author:: Peter Kofler
8
+ class ClassEntry
9
+
10
+ # Return the short (simple) name of this class.
11
+ attr_reader :name
12
+ attr_reader :full_name
13
+ # Return the list of versions this class exists.
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.
18
+ def initialize(parent, full_name, is_public, vers)
19
+ @parent = parent
20
+ @full_name = full_name.to_javaname.to_classname
21
+ @name = @full_name.simple_name
22
+ @is_public = is_public
23
+ @version = [vers]
24
+ end
25
+
26
+ def public?
27
+ @is_public
28
+ end
29
+
30
+ # Update the _version_ this class also exists in.
31
+ def update(version, is_public=@is_public)
32
+ raise "update class #{@name} is older than its last version: latest version=#{@version.last}, new version=#{version}" if version <= @version.last
33
+ # check for holes in versions
34
+ if version > @version.last+1
35
+ warn "#{@full_name} last in version #{@version.last}, not in #{@version.last+1}, but again in #{version}"
36
+ end
37
+ @version << version
38
+
39
+ if !is_public && @is_public
40
+ warn "#{@full_name} changed from public to package in version #{version}"
41
+ @is_public = is_public
42
+ @version = [version] # skip older versions
43
+ elsif is_public && ! @is_public
44
+ info "#{@full_name} changed from package to public in version #{version}"
45
+ @is_public = is_public
46
+ @version = [version] # skip older versions
47
+ end
48
+ end
49
+
50
+ # Sorts by simple +name+ inside the package.
51
+ def <=>(other)
52
+ @name.casecmp other.name
53
+ end
54
+
55
+ def to_s
56
+ @full_name
57
+ 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_ .
61
+ # Print all versions, first to last, but skip <code>first<=minversion</code> and <code>last>=maxversion</code>.
62
+ def to_full_qualified_s(minversion, maxversion)
63
+ format_version(@full_name, minversion, maxversion)
64
+ end
65
+
66
+ # Return a string containing the simple name and the version, if it is different from the package version.
67
+ def to_package_shortcut_s
68
+ vp = @parent.version
69
+ format_version(" #{@name}", vp.first, vp.last)
70
+ end
71
+
72
+ private
73
+
74
+ def format_version(start, minversion, maxversion)
75
+ # this class has a set of versions where it exists
76
+ # the parent has a set of versions where it exists, contains class versions
77
+ is_newer = @version.first > minversion
78
+ 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"
84
+ line.sub(/\[-0/, "[0-0").sub(/(\d)-\1/, "only \\1").sub(/ \[\]/, '')
85
+ end
86
+ end
87
+
88
+ end
89
+ end