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
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