javaclass 0.0.2 → 0.0.3

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 (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
data/Rakefile CHANGED
@@ -1,51 +1,236 @@
1
+ #require 'FileUtils' # already required
2
+ require 'net/http'
1
3
  require 'rubygems'
2
-
4
+ require 'rubygems/gem_runner' # install and uninstall
3
5
  require 'rake'
6
+ require 'rake/clean' # for clean/clobber
4
7
  require 'rake/testtask'
5
- require 'rake/packagetask'
6
8
  require 'rake/gempackagetask'
9
+ require 'rake/packagetask'
7
10
  require 'rake/rdoctask'
8
11
 
9
- jcversion = '0.0.2'
12
+ # Test, package and publish functions.
13
+ # Author:: Peter Kofler
14
+ # See: http://rake.rubyforge.org/files/doc/rakefile_rdoc.html
15
+ GEM_NAME = 'javaclass'
16
+ GOOGLE_PROJECT = "#{GEM_NAME}-rb"
17
+ RDOC_DIR = 'html'
18
+ RDOC_REPO = 'api'
10
19
 
11
20
  gemspec = Gem::Specification.new do |s|
12
- s.name = 'javaclass'
13
- s.version = jcversion
14
- s.summary ='A parser and disassembler for Java class files'
15
- s.files = FileList['Readme.txt', '{lib,test}/**/*.*', 'history.txt', 'Rakefile']
16
- s.test_files = FileList["{test}/**/test_*.rb"]
17
- s.require_path = 'lib'
18
- s.has_rdoc = true
19
- s.rubyforge_project = 'javaclass'
20
- s.homepage = 'http://javaclass.rubyforge.org/'
21
+ s.version = '0.0.3'
22
+ s.name = GEM_NAME
23
+ s.rubyforge_project = 'javaclass' # old, just redirects
24
+ s.summary = 'A parser and disassembler for Java class files'
25
+ s.description = 'Provides access to the package, protected, and public fields and methods of the classes passed to it together with a list of all outgoing references.'
26
+ s.homepage = "http://code.google.com/p/#{GOOGLE_PROJECT}/"
21
27
  s.author = 'Peter Kofler'
22
- s.email = 'bruno41 at rubyforge dot org'
23
- # TODO use new cc email
28
+ s.email = 'peter dot kofler at code minus cop dot org'
29
+
30
+ s.files = FileList['Readme.txt', '{lib,test,examples}/**/*.*', 'history.txt', 'Rakefile']
31
+ s.test_files = FileList['test/**/test_*.rb']
32
+ s.require_path = 'lib'
33
+ s.add_dependency('rubyzip', '>= 0.9.1')
34
+ s.required_ruby_version = '>= 1.8.6'
24
35
  s.platform = Gem::Platform::RUBY
36
+ s.add_development_dependency('rake', '>= 0.8.4')
37
+ s.add_development_dependency('ZenTest', '>= 4.4.0')
38
+
39
+ s.has_rdoc = true
40
+ s.extra_rdoc_files = ['Readme.txt', 'history.txt']
41
+ s.rdoc_options << '--title' << "#{s.name}-#{s.version} Documentation" <<
42
+ '--main' << 'Readme.txt'
43
+ end
44
+ full_gem_name = "#{gemspec.name}-#{gemspec.version}"
45
+
46
+ desc 'Validates the gemspec'
47
+ task :validate_gem do
48
+ gemspec.validate
49
+ end
50
+
51
+ desc 'Displays the current version'
52
+ task :version do
53
+ puts gemspec.version
54
+ end
55
+
56
+ # :test
57
+ Rake::TestTask.new do |t|
58
+ t.test_files = gemspec.test_files
59
+ t.warning = true
60
+ #t.verbose = false is default
61
+ end
62
+
63
+ desc 'Find missing test methods with ZenTest'
64
+ task :zentest do
65
+ files = gemspec.files.find_all { |f| f =~ /^#{gemspec.require_path}.*\.rb$/ } + gemspec.test_files
66
+ output = `ruby -I#{gemspec.require_path} -e "require 'rubygems'; load(Gem.bin_path('ZenTest', 'zentest'))" #{files.join(' ')}`
67
+ puts output.gsub(/^#.*\n/, '') # skip all ZenTest comments
25
68
  end
26
69
 
27
- Rake::GemPackageTask.new(gemspec) do |pkg|
70
+ # :gem
71
+ Rake::GemPackageTask.new(gemspec) do |pkg|
28
72
  pkg.need_zip = true
29
73
  end
30
74
 
31
- Rake::PackageTask.new(gemspec.name, gemspec.version) do |pkg|
75
+ # :package, :clobber_package, :repackage
76
+ Rake::PackageTask.new(gemspec.name, gemspec.version) do |pkg|
32
77
  #pkg.need_tar = true - no compress in tar on unxutils in Windows
33
78
  #pkg.need_tar_gz = true - no compress in tar on unxutils in Windows
34
79
  pkg.need_zip = true
35
80
  pkg.package_files.include gemspec.files
36
81
  end
37
82
 
38
- Rake::TestTask.new do |t|
39
- t.pattern = 'test/**/test_*.rb'
40
- t.warning = true
41
- t.verbose = false
83
+ desc 'Install the gem locally'
84
+ task :install_gem => :package do
85
+ Gem::GemRunner.new.run ['install', "pkg/#{full_gem_name}"]
86
+ end
87
+
88
+ desc 'Uninstall the gem'
89
+ task :uninstall_gem do
90
+ Gem::GemRunner.new.run ['uninstall', gemspec.name]
91
+ end
92
+
93
+ # Helper method to execute Mercurial with the _params_ array.
94
+ # The +hg+ executable must be in the path.
95
+ def hg(params)
96
+ puts `hg #{params.join(' ')}`
97
+ end
98
+
99
+ desc 'Tag current version in Hg'
100
+ task :tag do
101
+ hg ['tag', '-f', "-m \"Released gem version #{gemspec.version}\"", "#{full_gem_name}"]
102
+ puts 'Tag created. Don\'t forget to push'
103
+ end
104
+
105
+ # internal - desc 'Release the gem to Rubygems'
106
+ task :release_rubygems => :package do
107
+ puts "Releasing #{full_gem_name} to Rubygems"
108
+ Gem::GemRunner.new.run ['push', "pkg/#{full_gem_name}.gem"]
109
+ end
110
+
111
+ # Read username and password from the <code>~/.hgrc</code> for _authname_ prefix.
112
+ # <code>HOME</code> environment must be set.
113
+ def user_pass_from_hgrc(authname)
114
+ lines = IO.readlines(File.expand_path('~/.hgrc'))
115
+ user = lines.find{ |l| l =~ /#{authname}.username/ }[/[^\s=]+$/]
116
+ raise "could not find key #{authname}.username in ~/.hgrc" unless user
117
+ pass = lines.find{ |l| l =~ /#{authname}.password/ }[/[^\s=]+$/]
118
+ raise "could not find key #{authname}.password in ~/.hgrc" unless pass
119
+ [user, pass]
120
+ end
121
+
122
+ # Download the <code>googlecode_upload.py</code> from Google Code repository and save it as _name_ .
123
+ # See:: http://support.googlecode.com/svn/trunk/scripts/googlecode_upload.py
124
+ def download_googlecode_upload_py(name)
125
+ Net::HTTP.start('support.googlecode.com', 80) do |http|
126
+ body = http.get("/svn/trunk/scripts/#{name}").body
127
+ File.open(name, 'w') { |f| f.print body }
128
+ end
129
+ end
130
+
131
+ # Helper method to execute Python with the _params_ array.
132
+ # The +python+ executable must be in the path.
133
+ def python(params)
134
+ puts `python #{params.join(' ')}`
135
+ end
136
+
137
+ # internal - desc 'Release the gem to Google Code'
138
+ task :release_googlecode => :package do
139
+ puts "Releasing #{full_gem_name} to GoogleCode"
140
+ user, pass = user_pass_from_hgrc(gemspec.name)
141
+ # See:: http://code.google.com/p/support/wiki/ScriptedUploads
142
+ download_googlecode_upload_py 'googlecode_upload.py'
143
+ ['gem', 'zip'].each do |extension|
144
+ puts "uploading \"pkg/#{full_gem_name}.#{extension}\"..."
145
+ python ['googlecode_upload.py', "-s \"JavaClass #{gemspec.version} #{extension.capitalize}\"", "-p #{GOOGLE_PROJECT}", "-u #{user}", "-w #{pass}", "pkg/#{full_gem_name}.#{extension}"]
146
+ end
42
147
  end
43
148
 
149
+ desc 'Package and upload gem to Rubygems and Google Code'
150
+ task :publish_gem => [:clobber_package, :package, :release_rubygems, :release_googlecode]
151
+
152
+ # :rdoc, :clobber_rdoc, :rerdoc
44
153
  Rake::RDocTask.new do |rdoc|
45
- # rdoc.rdoc_dir = 'html'
46
- rdoc.title = "JavaClass javaclass-#{jcversion} Documentation"
47
- rdoc.main = 'Readme.txt'
154
+ rdoc.rdoc_dir = RDOC_DIR # 'html' is default anyway
155
+ rdoc.title = "#{full_gem_name} Documentation"
156
+ rdoc.main = 'Readme.txt'
48
157
  rdoc.rdoc_files.include 'Readme.txt', 'lib/**/*.rb', 'history.txt'
49
158
  end
50
159
 
160
+ # Helper method to add target="_parent" to all external links in _file_ html.
161
+ def add_href_parent(file)
162
+ lines = IO.readlines(file).collect do |line|
163
+ if line =~ /(href=(?:'|")https?:\/\/)/
164
+ "#{$`}target=\"_parent\" #{$1}#{$'}"
165
+ else
166
+ line
167
+ end
168
+ end
169
+ File.open(file, 'w') { |f| f.print lines.join }
170
+ end
171
+
172
+ desc 'Fix the RDoc hrefs in framesets'
173
+ task :fix_rdoc => [:rdoc] do
174
+ Dir["#{RDOC_DIR}/**/*.html"].each { |file| add_href_parent(file) }
175
+ end
176
+
177
+ # Helper method to add the gem version _dir_ into index _file_ to frameset links.
178
+ def add_frameset_version(file, dir)
179
+ lines = IO.readlines(file).collect do |line|
180
+ if line =~ /(frame src=")/
181
+ "#{$`}#{$1}#{dir}/#{$'}"
182
+ else
183
+ line
184
+ end
185
+ end
186
+ File.open(file, 'w') { |f| f.print lines.join }
187
+ end
188
+
189
+ desc 'Publish the RDoc files to Google Code'
190
+ task :publish_rdoc => [:clobber_rdoc, :rdoc, :fix_rdoc] do
191
+ puts "Releasing #{full_gem_name} to API"
192
+
193
+ remote_repo = "https://#{RDOC_REPO}.#{GOOGLE_PROJECT}.googlecode.com/hg/"
194
+ remote_dir = "#{gemspec.version}"
195
+
196
+ FileUtils.rm_r RDOC_REPO rescue nil
197
+ hg ['clone', remote_repo, RDOC_REPO]
198
+
199
+ FileUtils.rm_r "#{RDOC_REPO}/#{remote_dir}" rescue nil
200
+ FileUtils.cp_r RDOC_DIR, "#{RDOC_REPO}/#{remote_dir}"
201
+
202
+ # modify index, update redirect in frameset
203
+ file = "#{RDOC_REPO}/index.html"
204
+ FileUtils.cp "#{RDOC_REPO}/#{remote_dir}/index.html", file
205
+ add_frameset_version(file, remote_dir)
206
+
207
+ hg ['addremove', '-q', "-R #{RDOC_REPO}"]
208
+ hg ['ci', "-m \"Update Rdoc for version #{gemspec.version}\"", "-R #{RDOC_REPO}"]
209
+ hg ['tag', '-f', "-m \"Released gem version #{gemspec.version}\"", "-R #{RDOC_REPO}", "#{full_gem_name}"]
210
+ hg ['push', "-R #{RDOC_REPO}"]
211
+ end
212
+
213
+ # :clean :clobber
214
+ CLOBBER.include(RDOC_REPO, 'googlecode_upload.py')
215
+
216
+ # Helper method to grep all the sources for some _pattern_ words.
217
+ def egrep(pattern)
218
+ Dir['**/*'].find_all { |fn| FileTest.file? fn }.each do |fn|
219
+ line_count = 0
220
+ open(fn) do |f|
221
+ while line = f.gets
222
+ line_count += 1
223
+ if line =~ pattern
224
+ puts "#{fn}:#{line_count}:#{line.strip}"
225
+ end
226
+ end
227
+ end
228
+ end
229
+ end
230
+
231
+ desc 'Look for TODO and FIXME tags'
232
+ task :todo do
233
+ egrep(/#.*(FI[X]ME|TO[D]O|T[B]D|H[A]CK)/i) # use 'odd' brackets to not find myself (and not have Eclipse markers)
234
+ end
235
+
51
236
  task :default => :test
data/Readme.txt CHANGED
@@ -1,47 +1,84 @@
1
- JavaClass
2
- by {Peter Kofler}[http://kofler.dot.at/work/]
1
+ javaclass-rb
2
+ by {Peter 'Code Cop' Kofler}[http://www.code-cop.org/]
3
3
 
4
- * {Homepage}[http://javaclass.rubyforge.org/]
5
- * {Rubyforge Project}[http://rubyforge.org/projects/javaclass]
6
- * email bruno41 at rubyforge dot org
4
+ * {Homepage (Google Code)}[http://code.google.com/p/javaclass-rb/]
5
+ * {Rubyforge Project (old)}[http://rubyforge.org/projects/javaclass]
6
+ * email peter dot kofler at code minus cop dot org
7
7
 
8
8
  == Description
9
9
 
10
- JavaClass (Java Class File Parser) is a
11
- parser and disassembler for Java class files, similar to the javap command.
12
- It provides access to the package, protected, and public fields and methods
13
- of the classes passed to it together with a list of all outgoing references.
10
+ javaclass-rb (Java Class File Parser for Ruby) is a
11
+ parser and disassembler for Java class files, similar to the javap command.
12
+ It provides access to the package, protected, and public fields and methods
13
+ of the classes passed to it together with a list of all outgoing references.
14
14
 
15
15
  == Motivation
16
16
 
17
- I am still doing Java most of the time. I used to be quite enthusiatic about
18
- it, but after 9 years I can see the advantages of being a polyglot. So I use
19
- Ruby for all kind of stuff, just for fun. Recently I needed some Java class
20
- analysis and happened to write it with Ruby. As I am a puritan, I did not
17
+ I am still doing Java most of the time. I used to be quite enthusiastic about
18
+ it, but after 11 years I can see the advantages of being a polyglot. So I use
19
+ Ruby for all kind of stuff, just for fun. When I needed some Java class
20
+ analysis I wrote it with Ruby. As I am a puritan, I did not
21
21
  want to call javap from my script, so I started disassembling the class files,
22
- which might be the the base for some serious static code analysis tools. (I
23
- started adding methods to that end...)
22
+ which might be the base for some serious static code analysis tools. (I
23
+ started adding methods to that end...)
24
24
 
25
25
  == Install
26
26
 
27
27
  sudo gem install javaclass
28
28
 
29
+ * {Gem Hosting}[http://rubygems.org/gems/javaclass]
30
+ * {Download of tarballs and gems}[http://code.google.com/p/javaclass-rb/downloads/list]
31
+
29
32
  == Usage
30
33
 
31
34
  require 'javaclass'
35
+
36
+ # load the class directly from the file system
37
+ clazz = JavaClass.load_fs('packagename/Public.class')
38
+
39
+ # better lookup the class from some classpath
40
+ classpath = JavaClass.classpath('some/path')
41
+ clazz = JavaClass.load_cp('packagename.Public', classpath)
32
42
 
33
- clazz = JavaClass.parse('packagename/Public.class')
34
43
  clazz.version # => 50.0
35
44
  clazz.constant_pool.items[1] # => packagename/Public
36
45
  clazz.access_flags.public? # => true
37
46
  clazz.this_class # => packagename/Public
47
+ clazz.this_class.to_java_file # => packagename/Public.java
38
48
  clazz.super_class # => java/lang/Object
49
+ clazz.super_class.to_classname # => java.lang.Object
39
50
  clazz.references.referenced_methods[0] # => java/lang/Object.<init>:()V
40
51
 
41
- == Requirements
52
+ == Documentation
53
+
54
+ Module +JavaClass+ is the entry point for most functions in the gem.
55
+ The main class is JavaClass::ClassFile::JavaClassHeader which provides access to
56
+ all information of a Java class file. There are also some examples in the examples
57
+ folder of the gem.
58
+
59
+ * {API RDoc}[http://api.javaclass-rb.googlecode.com/hg/index.html]
60
+
61
+ == Support
42
62
 
43
- JavaClass does not depend on any other installed libraries or gems.
63
+ The bug tracker is available at http://code.google.com/p/javaclass-rb/issues/list or just drop me an email.
64
+
65
+ == Dependencies
66
+
67
+ * Ruby 1.8.6
68
+ * {rubyzip}[http://rubyzip.sourceforge.net/]
69
+
70
+ == References
71
+
72
+ * {JavaWorld: The Java class file lifestyle}[http://www.javaworld.com/javaworld/jw-07-1996/jw-07-classfile.html]
73
+ * {VM Spec: The class File Format}[http://java.sun.com/docs/books/jvms/second_edition/html/ClassFile.doc.html]
74
+ * {Similar Project by unageanu}[http://github.com/unageanu/javaclass]
44
75
 
45
76
  == License
46
77
 
47
- Same as Ruby.
78
+ * {New BSD License}[http://www.opensource.org/licenses/bsd-license.php]
79
+
80
+ == Disclaimer Note
81
+
82
+ This software is provided "as is" and without any express or implied warranties,
83
+ including, without limitation, the implied warranties of merchantability and
84
+ fitness for a particular purpose.
@@ -0,0 +1,61 @@
1
+ $:.unshift File.join(File.dirname(__FILE__), '..', 'lib')
2
+ require 'javaclass/classlist/list'
3
+ require 'javaclass/classlist/jar_searcher'
4
+
5
+ # Generate the full class lists starting from a saved one.
6
+ # Author:: Peter Kofler
7
+ puts "create full class lists for JDKs (by search and open class)"
8
+
9
+ # Struct to keep configuration what kind of JDK classes should be searched and added.
10
+ JDK_CONFIG = Struct.new(:version, :label, :paths)
11
+ # Define information about JDK to process one after another.
12
+ JDKS = [
13
+ JDK_CONFIG.new(0, "1.0.2", ['E:\Develop\Java\Compiler\jdk1.0.2\lib']),
14
+ JDK_CONFIG.new(1, "1.1.8-09", ['E:\Develop\Java\Compiler\jdk1.1.8\lib', 'E:\Develop\Java\JDK-1.1\Library\swing-1.1.1\lib']),
15
+ JDK_CONFIG.new(2, "1.2.2-13", ['C:\Programme\Java\jdk1.2.2_13\jre\lib', 'C:\Programme\Java\jdk1.2.2_13\lib\dt.jar']),
16
+ JDK_CONFIG.new(3, "1.3.1-08", ['C:\Programme\Java\jdk1.3.1_08\jre\lib', 'C:\Programme\Java\jdk1.3.1_08\lib\dt.jar']),
17
+ JDK_CONFIG.new(4, "1.4.2-03", ['C:\Programme\Java\jdk1.4.2_03\jre\lib', 'C:\Programme\Java\jdk1.4.2_03\lib\dt.jar']),
18
+ JDK_CONFIG.new(5, "1.5.0-07", ['C:\Programme\Java\jdk1.5.0_07\jre\lib', 'C:\Programme\Java\jdk1.5.0_07\lib\dt.jar']),
19
+ JDK_CONFIG.new(6, "1.6.0-11", ['C:\Programme\Java\jdk1.6.0_21\jre\lib', 'C:\Programme\Java\jdk1.6.0_21\lib\dt.jar']),
20
+ #JDK_CONFIG.new(7, "1.7.0-xx", ['C:\Programme\Java\jdk1.7.0_xx\jre\lib']),
21
+ ]
22
+
23
+ BASE_NAME = 'fullClassList'
24
+
25
+ # Create a new list
26
+ @list = JavaClass::ClassList::List.new
27
+
28
+ # load already good list if we do not start with JDK 1.0
29
+ if JDKS[0].version > 0
30
+ old_version = JDKS[0].version-1
31
+ old_class_list_name = Dir["./#{BASE_NAME}?#{old_version}?.txt"].first
32
+ if FileTest.exist?(old_class_list_name)
33
+ puts "loading #{old_version}"
34
+ IO.readlines(old_class_list_name).each {|line| @list.parse_line(line, old_version) }
35
+ end
36
+ end
37
+
38
+ # init the searcher
39
+ @searcher = JavaClass::ClassList::JarSearcher.new
40
+ @searcher.filters = %w[sun/ sunw/ com/sun/ netscape/ COM/rsa/ quicktime/ com/apple/mrj/macos/carbon/ org/jcp/xml/dsig/internal/]
41
+ # netscape ... applet js security [2]
42
+ # COM/rsa/ ... jsafe [4]
43
+ # quicktime ... quicktime [5]
44
+ # org/jcp/xml/dsig/internal ... xml dsig [6]
45
+
46
+ #Dir.mkdir './ClassLists' unless File.exist? './ClassLists'
47
+
48
+ # Work on all lists defined in +JDK+ and yield the block with the jdk label and the class list.
49
+ JDKS.each do |conf|
50
+ puts "processing #{conf.version}"
51
+ conf.paths.each { |p| @list = @searcher.compile_list(conf.version, p, @list) }
52
+
53
+ #basename = "jdk#{conf.label.gsub(/\./, '')}"
54
+ #File.open("./ClassLists/#{basename}_new_package_classes.txt", "w") { |f| f.print @list.old_access_list.collect{|m| m.sub(/\s.*$/, '')} }
55
+ #File.open("./ClassLists/#{basename}_all_classes.txt", "w") { |f| f.print @list.plain_class_list }
56
+ #File.open("./ClassLists/#{basename}_all_public_classes.txt", "w") { |f| f.print @list.plain_class_list { |c| c.public? } }
57
+ #File.open("./ClassLists/#{basename}_new_public_classes.txt", "w") { |f| f.print @list.plain_class_list { |c| c.public? and c.version.first == conf.version } }
58
+
59
+ baseversion = conf.label.gsub(/\.|-.+$/, '')
60
+ File.open("./#{BASE_NAME}#{baseversion}.txt", "w") { |f| f.print @list.full_class_list }
61
+ end
data/history.txt CHANGED
@@ -1,3 +1,14 @@
1
+ === 0.0.3 02/10/2010
2
+
3
+ * integrated ClassList from another project as first analyser
4
+ * add JavaName to all class names that are returned
5
+ * fix links in RDoc, update documentation
6
+ * move classes into submodules for classpath, classfile, etc.
7
+ * migrated to Google Code and Mercurial repository
8
+ * added access flag $1000
9
+ * added references to used classes
10
+ * added classpath abstraction
11
+
1
12
  === 0.0.2 08/04/2009
2
13
 
3
14
  * refactored code to smaller objects for version and constant pool
@@ -8,22 +19,5 @@
8
19
  === 0.0.1 01/03/2009
9
20
 
10
21
  * initial version extracted from ClassList project
11
- * reads the class version and package/public flag of a class
12
- * understands the constant pool but does not use it
13
-
14
- === Planned
15
-
16
- * continue function for fields and methods
17
- * implement
18
- * dump to return the class same as javap
19
- * isAnnotation (checks version>=5 & superclass)
20
- * are Annotation extendable, if so how do they look? (javap)
21
- * isEnum (checks version>=5 & superclass)
22
- * are Enums extendable (yes), if so how do they look? (javap)
23
- * test
24
- * test with all classes of all JDKs against javap from this version
25
- * Java 1.0 - private protected fields.
26
- * Java 1.0 - http://www.javaworld.com/javaworld/javaqa/1999-06/03-synchronized.html
27
- * think about
28
- * "metric" if all referencing classes of a class is another package, propose moving it there.
29
- * add zip gem to load classes directly from the classpath (i.e. the jars), add gem dependency
22
+ * reads the class version and package/public flag of a class
23
+ * understands the constant pool but does not use it
@@ -0,0 +1,52 @@
1
+ require 'javaclass/string_ux'
2
+
3
+ module JavaClass
4
+ module ClassFile
5
+
6
+ # The access flags of a class or interface.
7
+ # Author:: Peter Kofler
8
+ class AccessFlags
9
+
10
+ # Access flags as defined by JVM spec.
11
+ ACC_PUBLIC = 0x0001
12
+ ACC_FINAL = 0x0010
13
+ ACC_SUPER = 0x0020 # old invokespecial instruction semantics
14
+ ACC_INTERFACE = 0x0200
15
+ ACC_ABSTRACT = 0x0400
16
+ ACC_INNER = 0x1000 # TODO unknown access flag, find in spec
17
+ ACC_OTHER = 0xffff ^ ACC_PUBLIC ^ ACC_FINAL ^ ACC_SUPER ^ ACC_INTERFACE ^ ACC_ABSTRACT ^ ACC_INNER
18
+
19
+ def initialize(data, pos)
20
+ @flags = data.u2(pos)
21
+ raise "inconsistent flags #{@flags} (abstract and final)" if abstract? && final?
22
+ if interface? && !abstract?
23
+ # JDK 1.0 and 1.1 do have non abstract interfaces, fix it
24
+ @flags = @flags | ACC_ABSTRACT
25
+ end
26
+ raise "inconsistent flags #{@flags} (interface not abstract)" if interface? && !abstract?
27
+ raise "inconsistent flags #{@flags} (interface is final)" if interface? && final?
28
+ raise "inconsistent flags #{@flags} (other value #{@flags & ACC_OTHER})" if (@flags & ACC_OTHER) != 0
29
+ end
30
+
31
+ # Return +true+ if the class is public.
32
+ def public?
33
+ (@flags & ACC_PUBLIC) != 0
34
+ end
35
+ alias accessible? public?
36
+
37
+ def final?
38
+ (@flags & ACC_FINAL) != 0
39
+ end
40
+
41
+ def abstract?
42
+ (@flags & ACC_ABSTRACT) != 0
43
+ end
44
+
45
+ def interface?
46
+ (@flags & ACC_INTERFACE) != 0
47
+ end
48
+
49
+ end
50
+
51
+ end
52
+ end
@@ -0,0 +1,29 @@
1
+ module JavaClass
2
+ module ClassFile
3
+
4
+ # The +CAFEBABE+ magic of a class file. This just checks if CAFEBABE is here.
5
+ # Author:: Peter Kofler
6
+ class ClassMagic # ZenTest SKIP
7
+
8
+ CAFE_BABE = "\xCA\xFE\xBA\xBE"
9
+
10
+ # Check the class magic in the _data_ beginning at position _start_ (which is usually 0).
11
+ def initialize(data, start=0)
12
+ # "parsing"
13
+ @bytes = data[start..start+3]
14
+ end
15
+
16
+ # Return +true+ if the data was valid, i.e. if the class started with +CAFEBABE+.
17
+ def valid?
18
+ @bytes == CAFE_BABE
19
+ end
20
+
21
+ # Return the value of the magic in this class.
22
+ def bytes
23
+ @bytes.dup
24
+ end
25
+
26
+ end
27
+
28
+ end
29
+ end
@@ -0,0 +1,67 @@
1
+ require 'javaclass/string_ux'
2
+
3
+ module JavaClass
4
+ module ClassFile
5
+
6
+ # Version of a class file.
7
+ # Author:: Peter Kofler
8
+ # See:: http://java.sun.com/docs/books/jvms/second_edition/html/ClassFile.doc.html#75883
9
+ class ClassVersion # ZenTest FULL to find method to_s
10
+
11
+ attr_reader :minor
12
+ attr_reader :major
13
+
14
+ # Extract the class version from the bytes _data_ starting at position _start_ (which is usually 4).
15
+ def initialize(data, start=4)
16
+ # parsing
17
+ @minor = data.u2(start)
18
+ @major = data.u2(start+2)
19
+ end
20
+
21
+ # Return the class file version as +major+.+minor+ string like 48.0 (Java 1.4) or 50.0 (Java 6).
22
+ def to_s
23
+ "#{@major}.#{@minor}"
24
+ end
25
+
26
+ # Return the version as +major+.+minor+ float.
27
+ def to_f
28
+ if @minor <= 0
29
+ denom = 1.0
30
+ else
31
+ denom = 1.0 * 10**(Math.log10(@minor).floor + 1)
32
+ end
33
+
34
+ @major + @minor/denom
35
+ end
36
+
37
+ # Return a debug output of this version.
38
+ def dump
39
+ [" minor version: #{@minor}", " major version: #{@major}"]
40
+ end
41
+
42
+ # Return the JDK version corresponding to this version like "1.6" or "unknown" if none matched.
43
+ def jdk_version
44
+ v = to_f
45
+ if v >= 45.0 && v <= 45.3 # 1.0.2 supports class file format versions 45.0 through 45.3 inclusive.
46
+ '1.0'
47
+ elsif v > 45.3 && v <= 45.65535 # 1.1.X can support class file formats of versions in the range 45.0 through 45.65535 inclusive
48
+ '1.1'
49
+ elsif v == 46.0 # JDK 1.2=46
50
+ '1.2'
51
+ elsif v == 47.0 # JDK 1.3=47
52
+ '1.3'
53
+ elsif v == 48.0 # JDK 1.4=48
54
+ '1.4'
55
+ elsif v == 49.0 # J2SE 5.0=49
56
+ '1.5'
57
+ elsif v == 50.0 # J2SE 6.0=50
58
+ '1.6'
59
+ else
60
+ 'unknown'
61
+ end
62
+ end
63
+
64
+ end
65
+
66
+ end
67
+ end