javaclass 0.0.3 → 0.0.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (175) hide show
  1. data/Rakefile +67 -56
  2. data/Readme.txt +42 -39
  3. data/example_task.rb +172 -0
  4. data/examples/check_interface_names.rb +44 -0
  5. data/examples/corpus.rb +19 -0
  6. data/examples/count_classes_in_modules.rb +38 -0
  7. data/examples/cumulative_dependencies.rb +39 -0
  8. data/examples/find_all_imported_types.rb +44 -0
  9. data/examples/find_referenced_modules.rb +53 -0
  10. data/examples/find_unreferenced_classes.rb +65 -0
  11. data/examples/generate_class_lists.rb +67 -43
  12. data/examples/profiler_scratchpad.rb +33 -0
  13. data/examples/simple_usage.rb +42 -0
  14. data/history.txt +29 -7
  15. data/javaclass.gemspec +31 -0
  16. data/lib/javaclass/adder_tree.rb +92 -0
  17. data/lib/javaclass/analyse/dependencies.rb +52 -0
  18. data/lib/javaclass/{metric/metrics.txt → analyse/ideas.txt} +2 -2
  19. data/lib/javaclass/analyse/transitive_dependencies.rb +52 -0
  20. data/lib/javaclass/classfile/access_flag_constants.rb +24 -0
  21. data/lib/javaclass/classfile/access_flags.rb +49 -26
  22. data/lib/javaclass/classfile/class_format_error.rb +37 -0
  23. data/lib/javaclass/classfile/class_magic.rb +16 -8
  24. data/lib/javaclass/classfile/class_version.rb +19 -25
  25. data/lib/javaclass/classfile/constant_pool.rb +110 -45
  26. data/lib/javaclass/classfile/constants/base.rb +33 -12
  27. data/lib/javaclass/classfile/constants/double_reference.rb +55 -41
  28. data/lib/javaclass/classfile/constants/single_reference.rb +29 -21
  29. data/lib/javaclass/classfile/constants/value.rb +43 -33
  30. data/lib/javaclass/classfile/java_class_header.rb +72 -46
  31. data/lib/javaclass/classfile/java_class_header_as_java_name.rb +33 -0
  32. data/lib/javaclass/classfile/java_class_header_shortcuts.rb +19 -0
  33. data/lib/javaclass/classfile/references.rb +21 -19
  34. data/lib/javaclass/classlist/class_entry.rb +26 -27
  35. data/lib/javaclass/classlist/jar_searcher.rb +34 -25
  36. data/lib/javaclass/classlist/list.rb +31 -31
  37. data/lib/javaclass/classlist/package_entry.rb +25 -24
  38. data/lib/javaclass/classpath/any_classpath.rb +48 -0
  39. data/lib/javaclass/classpath/class_not_found_error.rb +20 -0
  40. data/lib/javaclass/classpath/classpaths.txt +2 -2
  41. data/lib/javaclass/classpath/composite_classpath.rb +56 -54
  42. data/lib/javaclass/classpath/convention_classpath.rb +38 -0
  43. data/lib/javaclass/classpath/eclipse_classpath.rb +74 -0
  44. data/lib/javaclass/classpath/factory.rb +65 -0
  45. data/lib/javaclass/classpath/file_classpath.rb +47 -0
  46. data/lib/javaclass/classpath/folder_classpath.rb +42 -44
  47. data/lib/javaclass/classpath/jar_classpath.rb +91 -52
  48. data/lib/javaclass/classpath/java_home_classpath.rb +24 -13
  49. data/lib/javaclass/classpath/maven_classpath.rb +44 -0
  50. data/lib/javaclass/classpath/temporary_unpacker.rb +111 -0
  51. data/lib/javaclass/classpath/tracking_classpath.rb +144 -0
  52. data/lib/javaclass/classscanner/ideas.txt +3 -0
  53. data/lib/javaclass/classscanner/imported_types.rb +29 -0
  54. data/lib/javaclass/classscanner/scanners.rb +29 -0
  55. data/lib/javaclass/delegate_directive.rb +15 -0
  56. data/lib/javaclass/dsl/caching_classpath.rb +38 -0
  57. data/lib/javaclass/dsl/classpath_analysers.rb +27 -0
  58. data/lib/javaclass/dsl/java_name_factory.rb +79 -0
  59. data/lib/javaclass/dsl/loader.rb +42 -0
  60. data/lib/javaclass/dsl/loading_classpath.rb +53 -0
  61. data/lib/javaclass/dsl/mixin.rb +54 -0
  62. data/lib/javaclass/gems/zip_file.rb +154 -0
  63. data/lib/javaclass/java_language.rb +50 -0
  64. data/lib/javaclass/java_name.rb +329 -55
  65. data/lib/javaclass/java_name_scanner.rb +95 -0
  66. data/lib/javaclass/resources/iso_3166_countries.txt +240 -0
  67. data/lib/javaclass/resources/jdk0_packages.txt +6 -0
  68. data/lib/javaclass/resources/jdk1_packages.txt +6 -0
  69. data/lib/javaclass/resources/jdk2_packages.txt +4 -0
  70. data/lib/javaclass/resources/jdk3_packages.txt +6 -0
  71. data/lib/javaclass/resources/jdk4_packages.txt +22 -0
  72. data/lib/javaclass/resources/jdk5_packages.txt +5 -0
  73. data/lib/javaclass/resources/jdk6_packages.txt +7 -0
  74. data/lib/javaclass/resources/jdk7_packages.txt +0 -0
  75. data/lib/javaclass/resources/jdk_packages.txt +53 -0
  76. data/lib/javaclass/resources/reserved_words.txt +50 -0
  77. data/lib/javaclass/string_hexdump.rb +76 -0
  78. data/lib/javaclass/string_ux.rb +21 -10
  79. data/lib/javaclass.rb +16 -41
  80. data/license.txt +28 -0
  81. data/planned.txt +13 -0
  82. data/test/data/Object_102.class +0 -0
  83. data/test/data/Runnable_102.class +0 -0
  84. data/test/data/access_flags/AccessFlagsTestAnnotation.class +0 -0
  85. data/test/data/access_flags/AccessFlagsTestAnnotation.java +3 -0
  86. data/test/data/access_flags/AccessFlagsTestEnum$1.class +0 -0
  87. data/test/data/access_flags/AccessFlagsTestEnum.class +0 -0
  88. data/test/data/access_flags/AccessFlagsTestEnum.java +6 -0
  89. data/test/data/access_flags/AccessFlagsTestInner$1.class +0 -0
  90. data/test/data/access_flags/AccessFlagsTestInner$2.class +0 -0
  91. data/test/data/access_flags/AccessFlagsTestInner.class +0 -0
  92. data/test/data/access_flags/AccessFlagsTestInner.java +13 -0
  93. data/test/data/access_flags/AccessFlagsTestPackage.class +0 -0
  94. data/test/data/access_flags/AccessFlagsTestPackage.java +1 -1
  95. data/test/data/api/packagename/AccessFlagsTestPublic.class +0 -0
  96. data/test/data/class_version/ClassVersionTest17.class +0 -0
  97. data/test/data/class_version/make.bat +6 -2
  98. data/test/data/eclipse_classpath/classes/ClassVersionTest12.class +0 -0
  99. data/test/data/eclipse_classpath/lib/JarClasspathTest.jar +0 -0
  100. data/test/data/eclipse_classpath/test-classes/ClassVersionTest13.class +0 -0
  101. data/test/data/folder_classpath/{JarClasspathTestFolder → classes}/ClassVersionTest10.class +0 -0
  102. data/test/data/folder_classpath/{JarClasspathTestFolder → classes}/package/ClassVersionTest11.class +0 -0
  103. data/test/data/jar_classpath/JarClasspathTest.jar +0 -0
  104. data/test/data/jar_classpath/JarClasspathTest.zip +0 -0
  105. data/test/data/jar_classpath/JarClasspathTestManifest.jar +0 -0
  106. data/test/data/jar_classpath/JarClasspathTestMultiManifest.jar +0 -0
  107. data/test/data/jar_classpath/make.bat +6 -2
  108. data/test/data/jar_searcher/BrokenRunnable_102.class +0 -0
  109. data/test/data/java_home_classpath/jdk118/lib/classes.zip +0 -0
  110. data/test/data/java_name_scanner/META-INF/MANIFEST.MF +12 -0
  111. data/test/data/java_name_scanner/plugin.xml +18 -0
  112. data/test/data/maven_classpath/module/pom.xml +8 -0
  113. data/test/data/maven_classpath/module/target/classes/ClassVersionTest12.class +0 -0
  114. data/test/data/maven_classpath/pom.xml +8 -0
  115. data/test/data/maven_classpath/target/classes/ClassVersionTest10.class +0 -0
  116. data/test/data/maven_classpath/target/test-classes/ClassVersionTest11.class +0 -0
  117. data/test/data/transitive_dependencies/A.class +0 -0
  118. data/test/data/transitive_dependencies/A.java +5 -0
  119. data/test/data/transitive_dependencies/B.class +0 -0
  120. data/test/data/transitive_dependencies/B.java +3 -0
  121. data/test/data/transitive_dependencies/C.class +0 -0
  122. data/test/data/transitive_dependencies/C.java +3 -0
  123. data/test/data/transitive_dependencies/Start.class +0 -0
  124. data/test/data/transitive_dependencies/Start.java +4 -0
  125. data/test/data/transitive_dependencies/make.bat +3 -0
  126. data/test/data/zip_file/commons-math-2.2-broken.zip +0 -0
  127. data/test/data/zip_file/regenerated-with-7zip.zip +0 -0
  128. data/test/data/zip_file/regenerated-with-jar.zip +0 -0
  129. data/test/dot_classpath.rb +33 -0
  130. data/test/logging_folder_classpath.rb +19 -0
  131. data/test/setup.rb +1 -1
  132. data/test/test_access_flags.rb +58 -32
  133. data/test/test_adder_tree.rb +78 -0
  134. data/test/test_any_classpath.rb +39 -0
  135. data/test/test_base.rb +9 -7
  136. data/test/test_caching_classpath.rb +41 -0
  137. data/test/test_class_entry.rb +60 -60
  138. data/test/test_class_magic.rb +31 -0
  139. data/test/test_class_version.rb +25 -25
  140. data/test/test_composite_classpath.rb +22 -23
  141. data/test/test_constant_pool.rb +37 -13
  142. data/test/test_convention_classpath.rb +39 -0
  143. data/test/test_eclipse_classpath.rb +73 -0
  144. data/test/test_factory.rb +61 -0
  145. data/test/test_folder_classpath.rb +26 -10
  146. data/test/test_imported_types.rb +34 -0
  147. data/test/test_jar_classpath.rb +29 -14
  148. data/test/test_jar_searcher.rb +27 -14
  149. data/test/test_java_class_header.rb +22 -10
  150. data/test/test_java_class_header_as_java_name.rb +41 -0
  151. data/test/test_java_home_classpath.rb +17 -11
  152. data/test/test_java_name.rb +204 -64
  153. data/test/test_java_name_factory.rb +52 -0
  154. data/test/test_java_name_scanner.rb +24 -0
  155. data/test/test_javaclass_api.rb +43 -0
  156. data/test/test_list.rb +58 -44
  157. data/test/test_load_directive.rb +34 -0
  158. data/test/test_maven_classpath.rb +46 -0
  159. data/test/test_package_entry.rb +27 -22
  160. data/test/test_references.rb +14 -14
  161. data/test/test_string_hexdump.rb +24 -0
  162. data/test/test_string_ux.rb +18 -106
  163. data/test/test_tracking_classpath.rb +112 -0
  164. data/test/test_transitive_dependencies.rb +31 -0
  165. data/test/test_unpacking_jar_classpath.rb +43 -0
  166. data/test/test_zip_file.rb +33 -0
  167. data/test/ts_all_tests.rb +80 -18
  168. data/thanks.txt +2 -0
  169. metadata +151 -22
  170. data/lib/javaclass/classpath/port_ClassPathEntry.java +0 -202
  171. data/lib/javaclass/classpath/port_ClassPathEntryFactory.java +0 -311
  172. data/lib/javaclass/classpath/port_DirectoryRepository.java +0 -24
  173. data/lib/javaclass/metric/ccd.rb +0 -68
  174. data/lib/javaclass/metric/class_usage.rb +0 -41
  175. data/test/test_javaclass.rb +0 -22
data/Rakefile CHANGED
@@ -1,63 +1,56 @@
1
- #require 'FileUtils' # already required
2
1
  require 'net/http'
3
2
  require 'rubygems'
4
3
  require 'rubygems/gem_runner' # install and uninstall
4
+ require 'rubygems/package_task'
5
5
  require 'rake'
6
6
  require 'rake/clean' # for clean/clobber
7
7
  require 'rake/testtask'
8
- require 'rake/gempackagetask'
9
8
  require 'rake/packagetask'
10
9
  require 'rake/rdoctask'
10
+ require 'example_task'
11
11
 
12
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"
13
+ # Author:: Peter Kofler
14
+ # See:: http://rake.rubyforge.org/files/doc/rakefile_rdoc.html
15
+ # Acknowledgement:: Building this Rake file was supported as System One Research Day. Thank you System One for funding Open Source :-)
16
+
17
17
  RDOC_DIR = 'html'
18
18
  RDOC_REPO = 'api'
19
19
 
20
- gemspec = Gem::Specification.new do |s|
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}/"
27
- s.author = 'Peter Kofler'
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'
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
20
+ gemspec = eval(IO.readlines('javaclass.gemspec').join)
44
21
  full_gem_name = "#{gemspec.name}-#{gemspec.version}"
45
22
 
46
23
  desc 'Validates the gemspec'
47
- task :validate_gem do
24
+ task :validate_gem do
48
25
  gemspec.validate
49
26
  end
50
27
 
51
28
  desc 'Displays the current version'
52
- task :version do
29
+ task :version do
53
30
  puts gemspec.version
54
31
  end
55
32
 
56
33
  # :test
57
- Rake::TestTask.new do |t|
34
+ Rake::TestTask.new do |t|
35
+ t.test_files = gemspec.test_files
36
+ t.warning = true
37
+ # t.verbose = false is default
38
+ end
39
+
40
+ begin
41
+ require 'rcov/rcovtask'
42
+
43
+ # :rcov
44
+ Rcov::RcovTask.new do |t|
58
45
  t.test_files = gemspec.test_files
59
46
  t.warning = true
60
- #t.verbose = false is default
47
+ t.rcov_opts << "--sort=coverage"
48
+ t.rcov_opts << "--only-uncovered"
49
+ end
50
+
51
+ rescue LoadError
52
+ # skip if not installed
53
+ warn("rcov not installed. coverage not available. #{$!}")
61
54
  end
62
55
 
63
56
  desc 'Find missing test methods with ZenTest'
@@ -68,12 +61,12 @@ task :zentest do
68
61
  end
69
62
 
70
63
  # :gem
71
- Rake::GemPackageTask.new(gemspec) do |pkg|
64
+ Gem::PackageTask.new(gemspec) do |pkg|
72
65
  pkg.need_zip = true
73
66
  end
74
67
 
75
68
  # :package, :clobber_package, :repackage
76
- Rake::PackageTask.new(gemspec.name, gemspec.version) do |pkg|
69
+ Rake::PackageTask.new(gemspec.name, gemspec.version) do |pkg|
77
70
  #pkg.need_tar = true - no compress in tar on unxutils in Windows
78
71
  #pkg.need_tar_gz = true - no compress in tar on unxutils in Windows
79
72
  pkg.need_zip = true
@@ -99,7 +92,9 @@ end
99
92
  desc 'Tag current version in Hg'
100
93
  task :tag do
101
94
  hg ['tag', '-f', "-m \"Released gem version #{gemspec.version}\"", "#{full_gem_name}"]
95
+ # hg ['push']
102
96
  puts 'Tag created. Don\'t forget to push'
97
+ puts 'hg push'
103
98
  end
104
99
 
105
100
  # internal - desc 'Release the gem to Rubygems'
@@ -112,11 +107,11 @@ end
112
107
  # <code>HOME</code> environment must be set.
113
108
  def user_pass_from_hgrc(authname)
114
109
  lines = IO.readlines(File.expand_path('~/.hgrc'))
115
- user = lines.find{ |l| l =~ /#{authname}.username/ }[/[^\s=]+$/]
110
+ user = lines.find{ |l| l =~ /#{authname}.username/ }[/[^\s=]+$/]
116
111
  raise "could not find key #{authname}.username in ~/.hgrc" unless user
117
112
  pass = lines.find{ |l| l =~ /#{authname}.password/ }[/[^\s=]+$/]
118
113
  raise "could not find key #{authname}.password in ~/.hgrc" unless pass
119
- [user, pass]
114
+ [user, pass]
120
115
  end
121
116
 
122
117
  # Download the <code>googlecode_upload.py</code> from Google Code repository and save it as _name_ .
@@ -142,19 +137,34 @@ task :release_googlecode => :package do
142
137
  download_googlecode_upload_py 'googlecode_upload.py'
143
138
  ['gem', 'zip'].each do |extension|
144
139
  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}"]
140
+ python ['googlecode_upload.py', "-s \"JavaClass #{gemspec.version} #{extension.capitalize}\"",
141
+ "-p #{GOOGLE_PROJECT}", "-u #{user}", "-w #{pass}",
142
+ "pkg/#{full_gem_name}.#{extension}"]
146
143
  end
147
144
  end
148
145
 
149
146
  desc 'Package and upload gem to Rubygems and Google Code'
150
- task :publish_gem => [:clobber_package, :package, :release_rubygems, :release_googlecode]
147
+ task :publish_gem => [:clobber_package, :example, :package, :release_rubygems, :release_googlecode]
148
+
149
+ # :example, :clobber_example, :reexample
150
+ example_task_lib = Rake::ExampleTask.new do |example|
151
+ example.example_files.include 'examples/**/*.rb'
152
+ end
153
+ task :clobber_rdoc => [:clobber_example]
154
+ task :rdoc => [:example]
155
+ task :package => [:example]
151
156
 
152
157
  # :rdoc, :clobber_rdoc, :rerdoc
153
158
  Rake::RDocTask.new do |rdoc|
154
159
  rdoc.rdoc_dir = RDOC_DIR # 'html' is default anyway
155
160
  rdoc.title = "#{full_gem_name} Documentation"
156
161
  rdoc.main = 'Readme.txt'
157
- rdoc.rdoc_files.include 'Readme.txt', 'lib/**/*.rb', 'history.txt'
162
+
163
+ # examples are generated later and not necessarily available at definition time
164
+ examples = example_task_lib.conversion_pairs.map { |a| a[1] }
165
+
166
+ rdoc.rdoc_files.include *examples
167
+ rdoc.rdoc_files.include 'lib/**/*.rb', *gemspec.extra_rdoc_files
158
168
  end
159
169
 
160
170
  # Helper method to add target="_parent" to all external links in _file_ html.
@@ -162,7 +172,7 @@ def add_href_parent(file)
162
172
  lines = IO.readlines(file).collect do |line|
163
173
  if line =~ /(href=(?:'|")https?:\/\/)/
164
174
  "#{$`}target=\"_parent\" #{$1}#{$'}"
165
- else
175
+ else
166
176
  line
167
177
  end
168
178
  end
@@ -170,8 +180,8 @@ def add_href_parent(file)
170
180
  end
171
181
 
172
182
  desc 'Fix the RDoc hrefs in framesets'
173
- task :fix_rdoc => [:rdoc] do
174
- Dir["#{RDOC_DIR}/**/*.html"].each { |file| add_href_parent(file) }
183
+ task :fix_rdoc => [:rdoc] do
184
+ Dir["#{RDOC_DIR}/**/*.html"].each { |file| add_href_parent(file) }
175
185
  end
176
186
 
177
187
  # Helper method to add the gem version _dir_ into index _file_ to frameset links.
@@ -179,7 +189,7 @@ def add_frameset_version(file, dir)
179
189
  lines = IO.readlines(file).collect do |line|
180
190
  if line =~ /(frame src=")/
181
191
  "#{$`}#{$1}#{dir}/#{$'}"
182
- else
192
+ else
183
193
  line
184
194
  end
185
195
  end
@@ -187,35 +197,36 @@ def add_frameset_version(file, dir)
187
197
  end
188
198
 
189
199
  desc 'Publish the RDoc files to Google Code'
190
- task :publish_rdoc => [:clobber_rdoc, :rdoc, :fix_rdoc] do
200
+ task :publish_rdoc => [:clobber_rdoc, :fix_rdoc] do
191
201
  puts "Releasing #{full_gem_name} to API"
192
-
193
- remote_repo = "https://#{RDOC_REPO}.#{GOOGLE_PROJECT}.googlecode.com/hg/"
202
+ remote_repo = "https://code.google.com/p/#{GOOGLE_PROJECT}.#{RDOC_REPO}"
194
203
  remote_dir = "#{gemspec.version}"
195
-
204
+
196
205
  FileUtils.rm_r RDOC_REPO rescue nil
197
206
  hg ['clone', remote_repo, RDOC_REPO]
198
-
207
+
199
208
  FileUtils.rm_r "#{RDOC_REPO}/#{remote_dir}" rescue nil
200
209
  FileUtils.cp_r RDOC_DIR, "#{RDOC_REPO}/#{remote_dir}"
201
-
210
+
202
211
  # modify index, update redirect in frameset
203
212
  file = "#{RDOC_REPO}/index.html"
204
213
  FileUtils.cp "#{RDOC_REPO}/#{remote_dir}/index.html", file
205
214
  add_frameset_version(file, remote_dir)
206
-
215
+
207
216
  hg ['addremove', '-q', "-R #{RDOC_REPO}"]
208
217
  hg ['ci', "-m \"Update Rdoc for version #{gemspec.version}\"", "-R #{RDOC_REPO}"]
209
218
  hg ['tag', '-f', "-m \"Released gem version #{gemspec.version}\"", "-R #{RDOC_REPO}", "#{full_gem_name}"]
210
- hg ['push', "-R #{RDOC_REPO}"]
219
+ # hg ['push', "-R #{RDOC_REPO}"]
220
+ puts 'API site created. Don\'t forget to push'
221
+ puts "hg push -R #{RDOC_REPO}"
211
222
  end
212
223
 
213
- # :clean :clobber
214
- CLOBBER.include(RDOC_REPO, 'googlecode_upload.py')
224
+ # :clean :clobber
225
+ CLOBBER.include(RDOC_REPO, 'googlecode_upload.py', 'ClassLists', 'fullClassList*.txt')
215
226
 
216
227
  # Helper method to grep all the sources for some _pattern_ words.
217
228
  def egrep(pattern)
218
- Dir['**/*'].find_all { |fn| FileTest.file? fn }.each do |fn|
229
+ Dir['**/*'].find_all { |fn| FileTest.file?(fn) && File.basename(fn) != /^\./ }.each do |fn|
219
230
  line_count = 0
220
231
  open(fn) do |f|
221
232
  while line = f.gets
data/Readme.txt CHANGED
@@ -17,10 +17,10 @@ of the classes passed to it together with a list of all outgoing references.
17
17
  I am still doing Java most of the time. I used to be quite enthusiastic about
18
18
  it, but after 11 years I can see the advantages of being a polyglot. So I use
19
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
20
+ analysis I wrote it in 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
22
  which might be the base for some serious static code analysis tools. (I
23
- started adding methods to that end...)
23
+ {started adding methods}[link:/files/history_txt.html] to that end.)
24
24
 
25
25
  == Install
26
26
 
@@ -29,56 +29,59 @@ started adding methods to that end...)
29
29
  * {Gem Hosting}[http://rubygems.org/gems/javaclass]
30
30
  * {Download of tarballs and gems}[http://code.google.com/p/javaclass-rb/downloads/list]
31
31
 
32
- == Usage
33
-
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)
42
-
43
- clazz.version # => 50.0
44
- clazz.constant_pool.items[1] # => packagename/Public
45
- clazz.access_flags.public? # => true
46
- clazz.this_class # => packagename/Public
47
- clazz.this_class.to_java_file # => packagename/Public.java
48
- clazz.super_class # => java/lang/Object
49
- clazz.super_class.to_classname # => java.lang.Object
50
- clazz.references.referenced_methods[0] # => java/lang/Object.<init>:()V
51
-
52
32
  == Documentation
53
33
 
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.
34
+ Module JavaClass is the entry point for basic functions. All advanced functions are
35
+ available in Object through the JavaClass::Dsl::Mixin. The main class or the parser
36
+ is JavaClass::ClassFile::JavaClassHeader which provides access to all information
37
+ of a Java class file.
58
38
 
59
39
  * {API RDoc}[http://api.javaclass-rb.googlecode.com/hg/index.html]
60
40
 
41
+ I tried hard to rdoc all classes and public methods, so just {read it}[http://api.javaclass-rb.googlecode.com/hg/index.html].
42
+
43
+ == Usage
44
+
45
+ See the various examples in the examples folder of the gem.
46
+
47
+ * {Basic Usage}[link:/files/lib/generated/examples/simple_usage_txt.html]
48
+ * {Number of classes in modules/JARs}[link:/files/lib/generated/examples/count_classes_in_modules_txt.html]
49
+ * {Check names of all interfaces}[link:/files/lib/generated/examples/check_interface_names_txt.html]
50
+ * {All imported types}[link:/files/lib/generated/examples/find_all_imported_types_txt.html]
51
+ * {Cumulative dependencies of a class}[link:/files/lib/generated/examples/cumulative_dependencies_txt.html]
52
+ * {Find (un)referenced JARs}[link:/files/lib/generated/examples/find_referenced_modules_txt.html]
53
+ * {Find unused classes}[link:/files/lib/generated/examples/find_unreferenced_classes_txt.html]
54
+ * {Generate lists of JDK classes}[link:/files/lib/generated/examples/generate_class_lists_txt.html]
55
+
56
+ There is some experimental logic to recognize Java class name literals in Ruby
57
+ which are mapped to JavaClass::JavaQualifiedName. Packages have to be suffixed
58
+ with ".*" to be recognized. See JavaClass::Dsl::JavaNameFactory for its usage.
59
+
61
60
  == Support
62
61
 
63
- The bug tracker is available at http://code.google.com/p/javaclass-rb/issues/list or just drop me an email.
62
+ The bug tracker is available at {Google Code}[http://code.google.com/p/javaclass-rb/issues/list]
63
+ or just drop me an email.
64
+
65
+ == How to submit patches
66
+
67
+ Read the {8 steps for fixing other people's code}[http://drnicwilliams.com/2007/06/01/8-steps-for-fixing-other-peoples-code/]
68
+ and for section 8, use the {Issue Tracker}[http://code.google.com/p/javaclass-rb/issues/list].
69
+
70
+ The trunk repository is available with
71
+
72
+ hg clone https://javaclass-rb.googlecode.com/hg/ javaclass-rb
64
73
 
65
74
  == Dependencies
66
75
 
67
- * Ruby 1.8.6
68
- * {rubyzip}[http://rubyzip.sourceforge.net/]
76
+ * Ruby 1.8.6 (runs with 1.8.7 and 1.9.1, too)
77
+ * {rubyzip}[http://rubyzip.sourceforge.net/] 0.9.1
69
78
 
70
79
  == References
71
80
 
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]
81
+ * {The Java class file lifestyle}[http://www.javaworld.com/javaworld/jw-07-1996/jw-07-classfile.html], JavaWorld 1996.
82
+ * {The class File Format}[http://java.sun.com/docs/books/jvms/second_edition/html/ClassFile.doc.html], The Java Virtual Machine Specification, Second Edition.
83
+ * {Similar Project by unageanu}[http://github.com/unageanu/javaclass], GitHub 2010.
75
84
 
76
85
  == License
77
86
 
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.
87
+ * {BSD License}[http://www.opensource.org/licenses/bsd-license.php], it's enclosed in {license.txt}[link:/files/license_txt.html].
data/example_task.rb ADDED
@@ -0,0 +1,172 @@
1
+ require 'rake'
2
+ require 'rake/tasklib'
3
+
4
+ module Rake
5
+
6
+ # Create a documentation task that will generate the example files for a project.
7
+ #
8
+ # The ExampleTask will create the following targets:
9
+ #
10
+ # [<b>:<em>example</em></b>]
11
+ # Main task for this example task.
12
+ #
13
+ # [<b>:clobber_<em>example</em></b>]
14
+ # Delete all the example files. This target is automatically added to the main clobber target.
15
+ #
16
+ # [<b>:re<em>example</em></b>]
17
+ # Rebuild the example files from scratch, even if they are not out of date.
18
+ #
19
+ # Simple example:
20
+ #
21
+ # Rake::ExampleTask.new do |rd|
22
+ # rd.target_dir = 'generated/examples'
23
+ # rd.example_files.include('examples/**/*.rb')
24
+ # end
25
+ #
26
+ # The +rd+ object passed to the block is an ExampleTask object. See the
27
+ # attributes list for the ExampleTask class for available customization options.
28
+ #
29
+ # == Specifying different task names
30
+ #
31
+ # You may wish to give the task a different name, such as if you are generating two
32
+ # sets of examples. For instance, if you want to have a development set of examples:
33
+ #
34
+ # Rake::ExampleTask.new(:example_dev) do |rd|
35
+ # rd.example_files.include('dev_examples/**/*.rb')
36
+ # end
37
+ #
38
+ # The tasks would then be named :<em>example_dev</em>, :clobber_<em>example_dev</em>, and :re<em>example_dev</em>.
39
+ #
40
+ class ExampleTask < TaskLib
41
+
42
+ # Name of the main, top level task. (default is :example)
43
+ attr_accessor :name
44
+
45
+ # Name of directory to receive the example output files. (default is 'lib/generated/examples')
46
+ attr_accessor :target_dir
47
+
48
+ # List of files to be included in the example generation. (default is [])
49
+ attr_accessor :example_files
50
+
51
+ # Create the Example tasks with the given base _name_ .
52
+ def initialize(name = :example) # :yield: self
53
+ @name = name
54
+ @example_files = Rake::FileList.new
55
+ @target_dir = 'lib/generated/examples'
56
+
57
+ yield self if block_given?
58
+
59
+ define_tasks
60
+ end
61
+
62
+ private
63
+
64
+ # Create the tasks defined by this task lib.
65
+ def define_tasks
66
+ define_repeat_task
67
+ define_clobber_task
68
+ define_build_task
69
+ end
70
+
71
+ def define_repeat_task
72
+ desc 'Force a rebuild of the example files'
73
+ task repeat_task_name => [clobber_task_name, build_task_name]
74
+ end
75
+
76
+ def define_clobber_task
77
+ desc 'Remove example products'
78
+ task clobber_task_name do
79
+ rm_r @target_dir rescue nil
80
+ end
81
+
82
+ task :clobber => [clobber_task_name]
83
+ end
84
+
85
+ def define_build_task
86
+ desc "Build the #{build_task_name} files"
87
+ task build_task_name
88
+
89
+ directory @target_dir
90
+ conversion_pairs.each { | a | define_transform(*a) }
91
+ end
92
+
93
+ def conversion_pairs
94
+ files_to_convert.map do |example_path|
95
+ [example_path, to_target_file(example_path)]
96
+ end
97
+ end
98
+ public :conversion_pairs
99
+
100
+ def files_to_convert
101
+ @example_files.find_all { |example_path| convert?(example_path) }
102
+ end
103
+
104
+ def define_transform(example_path, example_target)
105
+ task build_task_name => [example_target]
106
+ file example_target => [example_path, Rake.application.rakefile] do
107
+ print '.'
108
+ transform(example_path, example_target)
109
+ end
110
+ end
111
+
112
+ def build_task_name
113
+ name.to_s
114
+ end
115
+
116
+ def clobber_task_name
117
+ "clobber_#{name}"
118
+ end
119
+
120
+ def repeat_task_name
121
+ "re#{name}"
122
+ end
123
+
124
+ def convert?(text_file)
125
+ IO.readlines(text_file).find { |line| line =~ /# *:nodoc:/ } == nil
126
+ end
127
+
128
+ def to_target_file(file)
129
+ target_file = File.basename(file)
130
+ target_file[/\.rb$/] = '.txt'
131
+ File.join(@target_dir, target_file)
132
+ end
133
+
134
+ def transform(source, dest)
135
+ input = IO.readlines(source)
136
+ if source =~ /\.rb$/
137
+ lines = commentify(input)
138
+ else
139
+ lines = source
140
+ end
141
+ save(dest, lines)
142
+ end
143
+
144
+ def commentify(input)
145
+ lines = []
146
+ input.inject(true) do |add, line|
147
+ if line =~ /^#--/
148
+ false
149
+ elsif line =~ /^#\+\+/
150
+ true
151
+ elsif !add
152
+ false
153
+ elsif line =~ /^#/
154
+ lines << line
155
+ true
156
+ else
157
+ lines << "# #{line}"
158
+ true
159
+ end
160
+ end
161
+ lines
162
+ end
163
+
164
+ def save(name, lines)
165
+ folder = File.dirname(name)
166
+ mkdir_p folder unless File.exist?(folder)
167
+ File.delete name rescue nil
168
+ File.open(name, 'w') { |f| f.print lines.join }
169
+ end
170
+
171
+ end
172
+ end
@@ -0,0 +1,44 @@
1
+ # Example usage of classpath and class files: Scan all classes of an workspace.
2
+ # Find all interfaces, print their names and find all which are prefixed with 'I'.
3
+ # Author:: Peter Kofler
4
+ # Copyright:: Copyright (c) 2009, Peter Kofler.
5
+ # License:: {BSD License}[link:/files/license_txt.html]
6
+ #
7
+ # === Steps
8
+
9
+ #--
10
+ # add the lib of this gem to the load path
11
+ $:.unshift File.join(File.dirname(__FILE__), '..', 'lib')
12
+ require File.join(File.dirname(__FILE__), 'corpus')
13
+
14
+ location = Corpus[:Base]
15
+ package = 'at.kugel'
16
+ #++
17
+ require 'javaclass/dsl/mixin'
18
+
19
+ # 1) define the location of the project and a package you are interrested
20
+ # location = 'C:\Eclipse\workspace'
21
+ # package = 'com.biz.app'
22
+
23
+ # e.g. add an Eclipse classpath variable to find external dependencies.
24
+ Eclipse.add_variable('KOR_HOME', location)
25
+
26
+ # 2) create the classpath of the given workspace
27
+ cp = workspace(location)
28
+ puts "#{cp.elements.size} classpaths found under the workspace #{location}:"
29
+ puts " #{cp.elements.join("\n ")}"
30
+ puts "#{cp.count} classes found on classpath"
31
+
32
+ # 3) filter the classes to analyse, using JavaClass::JavaQualifiedName methods
33
+ to_analyse = cp.names { |classname| classname.same_or_subpackage_of?(package) }
34
+ puts "#{to_analyse.size} classes matched #{package}"
35
+
36
+ # 4) load all selected classes, parse into JavaClass::ClassFile, find all interfaces and collect their qualified names
37
+ names = cp.values(to_analyse).
38
+ find_all { |clazz| clazz.interface? }.
39
+ collect { |clazz| clazz.to_classname }
40
+ puts "#{names.size} interfaces found:\n #{names.sort.join("\n ")}"
41
+
42
+ # 5) print all qualified names have a simple namee staring with an I
43
+ inames = names.find_all { |classname| classname.simple_name =~ /^I[A-Z][a-z]/ }
44
+ puts "#{inames.size} interfaces start with I:\n #{inames.join("\n ")}"
@@ -0,0 +1,19 @@
1
+ # :nodoc:
2
+ # Set location of the test data corpus.
3
+ corpus_root = 'E:\OfficeDateien\Corpus'
4
+ Corpus = Hash[
5
+ *[
6
+ %w[Sun10 Java1_JDK-1.0.2(Sun_official) ],
7
+ %w[WF Java2_Swing(WF_iMagine) ],
8
+ %w[S1 Java5_Batch(S1_Fabric) ],
9
+ %w[Harmony15 Java5_JDK-1.5M15-r991518(Apache_Harmony) ],
10
+ %w[Harmony16 Java5_JDK-1.6M3-r991881(Apache_Harmony) ],
11
+ %w[RCP Java5_RCP_2011(IBM_Costing) ],
12
+ %w[BIA Java6_Swing(BIA_Monarch) ],
13
+ %w[HBD Java6_Web(HBD_Online) ],
14
+ ].map { |pair|
15
+ [pair[0].to_sym, File.join(corpus_root, pair[1])]
16
+ }.flatten
17
+ ]
18
+ Corpus[:Base] = 'E:\Develop\Java'
19
+ Corpus[:Lib] = 'E:\Develop\Java\CodeLib'
@@ -0,0 +1,38 @@
1
+ # Example usage of classpath (JavaClass::Classpath): Scan all classpaths (e.g. modules)
2
+ # of an an Eclipse "workspace". A workspace is a folder containing several Eclipse
3
+ # projects, e.g. JavaClass::Classpath::EclipseClasspath. Report the number of found
4
+ # classes per module.
5
+ # Author:: Peter Kofler
6
+ # Copyright:: Copyright (c) 2009, Peter Kofler.
7
+ # License:: {BSD License}[link:/files/license_txt.html]
8
+ #
9
+ # === Steps
10
+
11
+ #--
12
+ # add the lib of this gem to the load path
13
+ $:.unshift File.join(File.dirname(__FILE__), '..', 'lib')
14
+ require File.join(File.dirname(__FILE__), 'corpus')
15
+
16
+ location = Corpus[:HBD]
17
+ #++
18
+ require 'javaclass/classpath/factory'
19
+ include JavaClass::Classpath::Factory
20
+ # The require/include above just imports what is needed, but usually one would require the whole
21
+ # JavaClass::Dsl::Mixin for conveniance, e.g. require 'javaclass/dsl/mixin'.
22
+
23
+ # 1) define the location of the project
24
+ # location = 'C:\Eclipse\workspace'
25
+
26
+ # 2) create a JavaClass::Classpath::CompositeClasspath of the complete workspace, which will contain many classpath elements.
27
+ cp = workspace(location)
28
+ puts "#{cp.elements.size} classpaths found under the workspace #{location}"
29
+
30
+ # 3a) find all empty elements by querying the classpath elements
31
+ empty = cp.elements.find_all { |clp| clp.count == 0 }
32
+ puts "\n#{empty.size} empty modules found:\n #{empty.join("\n ")}"
33
+
34
+ # 3b) or print the list of each element with its class count
35
+ puts "library (module path): number of contained classes"
36
+ puts cp.elements.map { |clp| [clp.to_s, clp.count] }.
37
+ sort { |a,b| a[1] <=> b[1] }.
38
+ map { |e| " #{e[0]}: #{e[1]}" }
@@ -0,0 +1,39 @@
1
+ # Example usage of the featuress of JavaClass::Analyse::TransitiveDependencies
2
+ # to collect all transitive dependencies of a certain class or a whole package
3
+ # (Cumulative Component Dependencies).
4
+ # Author:: Peter Kofler
5
+ # Copyright:: Copyright (c) 2009, Peter Kofler.
6
+ # License:: {BSD License}[link:/files/license_txt.html]
7
+ # See:: Another example how to {list all imported types}[link:/files/lib/generated/examples/find_all_imported_types_txt.html]
8
+ #
9
+ # === Steps
10
+
11
+ #--
12
+ # add the lib of this gem to the load path
13
+ $:.unshift File.join(File.dirname(__FILE__), '..', 'lib')
14
+ require File.join(File.dirname(__FILE__), 'corpus')
15
+
16
+ location = Corpus[:HBD]
17
+ package = 'at.herold'
18
+ start_class = 'at.herold.waf.hbd.servlet.HBDServlet'
19
+ # 'at/spardat/krimiaps/service/client/service/impl/ClientSmeSearchServiceImpl'
20
+ # 'at/spardat/krimiaps/service/client/service/impl/ClientPrivateSearchServiceImpl'
21
+ #++
22
+ require 'javaclass/dsl/mixin'
23
+
24
+ # 1) create the classpath of the given workspace
25
+ cp = workspace(location)
26
+ puts "#{cp.count} classes found on classpath"
27
+
28
+ # define a filter to limit all operations to the classes we are interested in
29
+ filter = Proc.new { |classname| classname.same_or_subpackage_of?(package) }
30
+
31
+ # 2a) collect all transitive dependencies of a single class into an AdderTree
32
+ dependencies = cp.transitive_dependency_tree(start_class.to_javaname, &filter)
33
+ puts "#{dependencies.size} classes in transitive dependency graph of class #{start_class}"
34
+ dependencies.debug_print
35
+
36
+ # 2b) or collect all transitive dependencies of a whole package
37
+ dependencies = cp.transitive_dependencies_package(start_class.to_javaname.package, &filter)
38
+ puts "#{dependencies.size} classes in transitive dependency graph of package"
39
+ # dependencies.debug_print