javaclass 0.4.1 → 0.4.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/Rakefile +188 -194
- data/Readme.txt +33 -29
- data/examples/generate_class_lists.rb +16 -9
- data/history.txt +15 -4
- data/javaclass.gemspec +10 -8
- data/lib/generated/examples/chart_class_dependencies.txt +35 -0
- data/lib/generated/examples/chart_module_dependencies.txt +43 -0
- data/lib/generated/examples/check_interface_names.txt +36 -0
- data/lib/generated/examples/count_classes_in_modules.txt +31 -0
- data/lib/generated/examples/cumulative_dependencies.txt +28 -0
- data/lib/generated/examples/find_all_imported_types.txt +38 -0
- data/lib/generated/examples/find_incoming_dependency_graph.txt +73 -0
- data/lib/generated/examples/find_layers_of_modules.txt +70 -0
- data/lib/generated/examples/find_referenced_modules.txt +41 -0
- data/lib/generated/examples/find_unreferenced_classes.txt +66 -0
- data/lib/generated/examples/generate_class_lists.txt +53 -0
- data/lib/generated/examples/show_jar_api.txt +64 -0
- data/lib/generated/examples/simple_usage.txt +38 -0
- data/lib/javaclass/classfile/access_flag_constants.rb +32 -5
- data/lib/javaclass/classfile/access_flags.rb +39 -20
- data/lib/javaclass/classfile/attributes/attributes.rb +134 -0
- data/lib/javaclass/classfile/class_access_flags.rb +37 -0
- data/lib/javaclass/classfile/class_file_attributes.rb +62 -0
- data/lib/javaclass/classfile/class_version.rb +0 -1
- data/lib/javaclass/classfile/constant_pool.rb +17 -11
- data/lib/javaclass/classfile/constants/single_reference.rb +53 -0
- data/lib/javaclass/classfile/fields.rb +37 -0
- data/lib/javaclass/classfile/java_class_header.rb +22 -13
- data/lib/javaclass/classfile/java_class_header_shortcuts.rb +6 -2
- data/lib/javaclass/classfile/methods.rb +37 -0
- data/lib/javaclass/classlist/jar_searcher.rb +38 -4
- data/lib/javaclass/classpath/temporary_unpacker.rb +1 -1
- data/lib/javaclass/string_hexdump.rb +1 -1
- data/license.txt +7 -7
- data/test/data/access_flags/{AccessFlagsTestInner$1.class → AccessFlagsTestAnonym$1.class} +0 -0
- data/test/data/access_flags/{AccessFlagsTestInner.class → AccessFlagsTestAnonym.class} +0 -0
- data/test/data/access_flags/AccessFlagsTestAnonym.java +9 -0
- data/test/data/access_flags/AccessFlagsTestPublic_javap.txt +1 -0
- data/test/data/constant_pool/Java8_JavaFX_Animation$1_Tag15.class +0 -0
- data/test/data/constant_pool/Java9_Activation_module-info_Tag20.class +0 -0
- data/test/data/jar_searcher/JarClassListTest.jar +0 -0
- data/test/data/jar_searcher/PublicClass.java +44 -1
- data/test/data/jar_searcher/make.bat +1 -2
- data/test/{test_access_flags.rb → test_class_access_flags.rb} +91 -93
- data/test/test_class_file_attributes.rb +57 -0
- data/test/test_constant_pool.rb +31 -0
- data/test/test_jar_searcher.rb +40 -7
- data/test/test_javaclass_api.rb +2 -2
- data/test/test_string_hexdump.rb +4 -1
- data/test/ts_all_tests.rb +4 -2
- metadata +100 -116
- data/test/data/access_flags/AccessFlagsTestInner$2.class +0 -0
- data/test/data/access_flags/AccessFlagsTestInner.java +0 -13
@@ -22,8 +22,8 @@ JDK_CONFIG = Struct.new(:version, :label, :paths)
|
|
22
22
|
# Windows 7 configuration for 32bit Sun/Oracle JVMs
|
23
23
|
PROGRAMS = 'C:\Program Files (x86)\Java'
|
24
24
|
JDKS = [
|
25
|
-
JDK_CONFIG.new(0, '1.0.2', ['
|
26
|
-
JDK_CONFIG.new(1, '1.1.8-09', ['
|
25
|
+
JDK_CONFIG.new(0, '1.0.2', [PROGRAMS + '\jdk1.0.2\lib']),
|
26
|
+
JDK_CONFIG.new(1, '1.1.8-09', [PROGRAMS + '\jdk1.1.8\lib', 'E:\Develop\Java\JDK-1.1\Library\swing-1.1.1\lib']),
|
27
27
|
JDK_CONFIG.new(2, '1.2.2-13', [PROGRAMS + '\jdk1.2.2_13\jre\lib', PROGRAMS + '\jdk1.2.2_13\lib\dt.jar']),
|
28
28
|
JDK_CONFIG.new(3, '1.3.1-08', [PROGRAMS + '\jdk1.3.1_08\jre\lib', PROGRAMS + '\jdk1.3.1_08\lib\dt.jar']),
|
29
29
|
JDK_CONFIG.new(4, '1.4.2-03', [PROGRAMS + '\jdk1.4.2_03\jre\lib', PROGRAMS + '\jdk1.4.2_03\lib\dt.jar']),
|
@@ -31,6 +31,7 @@ JDKS = [
|
|
31
31
|
JDK_CONFIG.new(6, '1.6.0-26', [PROGRAMS + '\jdk1.6.0_26\jre\lib', PROGRAMS + '\jdk1.6.0_26\lib\dt.jar']),
|
32
32
|
JDK_CONFIG.new(7, '1.7.0', [PROGRAMS + '\jdk1.7.0\jre\lib', PROGRAMS + '\jdk1.7.0\lib\dt.jar']),
|
33
33
|
JDK_CONFIG.new(8, '1.8.0', [PROGRAMS + '\jdk1.8.0_25\jre\lib', PROGRAMS + '\jdk1.8.0_25\lib\dt.jar']),
|
34
|
+
JDK_CONFIG.new(9, '9.0.4', [PROGRAMS + '\open_jdk9.0.4-1\jmods', PROGRAMS + '\open_jdk9.0.4-1\lib\jrt-fs.jar']),
|
34
35
|
]
|
35
36
|
#++
|
36
37
|
# configuration for some JDKs
|
@@ -39,16 +40,22 @@ JDKS = [
|
|
39
40
|
# 1) create a JavaClass::ClassList::JarSearcher
|
40
41
|
JavaClass.unpack_jars!(:unpack)
|
41
42
|
searcher = JavaClass::ClassList::JarSearcher.new
|
43
|
+
searcher.skip_inner_classes = false
|
44
|
+
searcher.skip_package_classes = true
|
42
45
|
|
43
46
|
# 2) filter out unwanted classes, e.g. vendor classes
|
44
|
-
searcher.filters = %w[sun/ sunw/ com/oracle/ com/sun/ netscape/
|
45
|
-
quicktime/ com/apple/mrj/macos/carbon/ org/jcp/xml/dsig/internal/
|
47
|
+
searcher.filters = %w[sun/ sunw/ com/oracle/ com/sun/ netscape/ com/rsa/
|
48
|
+
quicktime/ com/apple/mrj/macos/carbon/ org/jcp/xml/dsig/internal/
|
49
|
+
oracle/jrockit/ jdk/internal/ jdk/nashorn/internal/
|
50
|
+
jdk/dynalink/internal/ jdk/incubator/http.internal/ jdk/javadoc/internal/ jdk/tools/jlink/internal/ ]
|
46
51
|
#--
|
47
52
|
# netscape ... applet js security [2]
|
48
53
|
# COM/rsa/ ... jsafe [4]
|
49
54
|
# quicktime ... quicktime [5]
|
50
55
|
# org/jcp/xml/dsig/internal ... xml dsig [6]
|
51
56
|
# com/oracle/ ... com.oracle.net.Sdp [7]
|
57
|
+
# oracle/jrockit/ jdk/internal/ jdk/nashorn/internal/ [8]
|
58
|
+
# jdk/dynalink/internal/ jdk/incubator/http.internal/ jdk/javadoc/internal/ jdk/tools/jlink/internal/ [9]
|
52
59
|
|
53
60
|
Dir.mkdir './ClassLists' unless File.exist? './ClassLists'
|
54
61
|
#++
|
@@ -73,14 +80,14 @@ JDKS.each do |conf|
|
|
73
80
|
|
74
81
|
# 5) save various kind of lists
|
75
82
|
basename = "./ClassLists/jdk#{conf.label.gsub(/\./, '')}"
|
76
|
-
File.open("#{basename}_new_package_classes.txt", "w") { |f| f.print list.old_access_list.collect{|m| m.sub(/\s.*$/, '')} }
|
77
|
-
File.open("#{basename}_all_classes.txt", "w") { |f| f.print list.plain_class_list }
|
83
|
+
# File.open("#{basename}_new_package_classes.txt", "w") { |f| f.print list.old_access_list.collect{|m| m.sub(/\s.*$/, '')} }
|
84
|
+
# File.open("#{basename}_all_classes.txt", "w") { |f| f.print list.plain_class_list }
|
78
85
|
File.open("#{basename}_all_packages.txt", "w") { |f| f.print list.to_s }
|
79
|
-
File.open("#{basename}_all_public_classes.txt", "w") { |f| f.print list.plain_class_list { |c| c.public? } }
|
80
|
-
File.open("#{basename}_new_public_classes.txt", "w") { |f| f.print list.plain_class_list { |c| c.public? and c.version.first == conf.version } }
|
86
|
+
File.open("#{basename}_all_public_classes.txt", "w") { |f| f.print list.plain_class_list { |c| c.public? }.join() }
|
87
|
+
File.open("#{basename}_new_public_classes.txt", "w") { |f| f.print list.plain_class_list { |c| c.public? and c.version.first == conf.version }.join() }
|
81
88
|
|
82
89
|
baseversion = conf.label.gsub(/\.|-.+$/, '')
|
83
|
-
File.open("./fullClassList#{baseversion}.txt", "w") { |f| f.print list.full_class_list }
|
90
|
+
File.open("./fullClassList#{baseversion}.txt", "w") { |f| f.print list.full_class_list.join() }
|
84
91
|
|
85
92
|
puts "processed #{conf.label}"
|
86
93
|
end
|
data/history.txt
CHANGED
@@ -1,12 +1,23 @@
|
|
1
|
+
=== 0.4.2 16/09/2020
|
2
|
+
|
3
|
+
* fix license text and name
|
4
|
+
* tested with GitHub actions for Ruby 2.1 to 2.7
|
5
|
+
* fix some warnings shown by Ruby 2.1
|
6
|
+
* moved code to GitHub
|
7
|
+
* added outer class name for inner classes
|
8
|
+
* added new constant pool tags and access modifier for Java 9
|
9
|
+
* added method handle and invoke dynamic constant pool tags for Java 8
|
10
|
+
* parse class attributes: source file and inner classes
|
11
|
+
|
1
12
|
=== 0.4.1 30/05/2015
|
2
13
|
|
3
14
|
* make compatible with Ruby 2.0
|
4
15
|
* upgrade rubyzip to 1.x (still supports 0.x as well)
|
5
16
|
* moved code to Bitbucket, moved API doc to code-cop.org
|
6
|
-
* Cloudbees dropped support for Ruby 1.8.6 and 1.8.7 - not
|
17
|
+
* Cloudbees dropped support for Ruby 1.8.6 and 1.8.7 - not tested there any more
|
7
18
|
* add plain class Node for dependency graph
|
8
19
|
* add dependency graph and classpath (module/component/plugin) implementation
|
9
|
-
* add Maven
|
20
|
+
* add Maven artifact to generate classpath from group/name/version
|
10
21
|
* change version number from micro to minor which more proper reflects code
|
11
22
|
* fix some warnings shown by Ruby 1.9.1
|
12
23
|
|
@@ -14,7 +25,7 @@
|
|
14
25
|
|
15
26
|
* convert examples to RDOC using example_task
|
16
27
|
* added transitive dependency trees from references
|
17
|
-
* patched the rubyzip for invalid flags found in some JARs
|
28
|
+
* patched the rubyzip gem for invalid flags found in some JARs
|
18
29
|
* add some examples
|
19
30
|
* fixed generate_class_lists.rb
|
20
31
|
* finish first version of DSL with loading/values
|
@@ -37,7 +48,7 @@
|
|
37
48
|
* integrated ClassList from another project as first analyser
|
38
49
|
* added abstraction of Java names to all class names that are returned
|
39
50
|
* fixed links in RDoc, update documentation
|
40
|
-
* moved classes into
|
51
|
+
* moved classes into sub modules for classpath, class file, etc.
|
41
52
|
* migrated to Google Code and Mercurial repository
|
42
53
|
* added access flag $1000
|
43
54
|
* added references to used classes
|
data/javaclass.gemspec
CHANGED
@@ -1,17 +1,18 @@
|
|
1
1
|
GEM_NAME = 'javaclass'
|
2
|
-
|
2
|
+
GIT_PROJECT = "#{GEM_NAME}-rb"
|
3
3
|
|
4
4
|
Gem::Specification.new do |s|
|
5
|
-
s.version = '0.4.
|
5
|
+
s.version = '0.4.2'
|
6
6
|
s.name = GEM_NAME
|
7
|
-
s.rubyforge_project = 'javaclass'
|
7
|
+
s.rubyforge_project = 'javaclass' if s.respond_to? :rubyforge_project=
|
8
|
+
# Gem::Specification#rubyforge_project= is deprecated with no replacement in 2.7
|
8
9
|
s.summary = 'Java class files parser and disassembler for Ruby'
|
9
10
|
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.'
|
10
|
-
s.license = 'BSD'
|
11
|
-
s.homepage = "https://
|
11
|
+
s.license = 'BSD-2-Clause'
|
12
|
+
s.homepage = "https://github.com/codecop/#{GIT_PROJECT}"
|
12
13
|
s.author = 'Peter Kofler'
|
13
14
|
s.email = 'peter dot kofler at code minus cop dot org'
|
14
|
-
s.date = Time::gm(
|
15
|
+
s.date = Time::gm(2020, 9, 16) # set current date for release
|
15
16
|
|
16
17
|
s.files = Dir.glob('*.txt') + Dir.glob('{lib,test,examples}/**/*') + ['javaclass.gemspec', 'Rakefile'] + Dir.glob('rake_*.rb') + Dir.glob('dev/*_task.rb')
|
17
18
|
s.test_files = Dir.glob('test/**/test_*.rb')
|
@@ -20,12 +21,13 @@ Gem::Specification.new do |s|
|
|
20
21
|
s.required_ruby_version = '>= 1.8.6'
|
21
22
|
s.required_rubygems_version = nil if s.respond_to? :required_rubygems_version=
|
22
23
|
s.platform = Gem::Platform::RUBY
|
23
|
-
s.add_development_dependency('rake', '>= 0.8.3')
|
24
|
+
# s.add_development_dependency('rake', '>= 0.8.3')
|
24
25
|
# s.add_development_dependency('rcov', '>= 0.8.1.2')
|
25
26
|
# s.add_development_dependency('saikuro', '>= 1.2.1')
|
26
27
|
# s.add_development_dependency('ZenTest', '>= 4.4.0')
|
27
28
|
|
28
|
-
s.has_rdoc = true
|
29
|
+
s.has_rdoc = true if s.respond_to? :has_rdoc=
|
30
|
+
# Gem::Specification#has_rdoc= is deprecated with no replacement in 2.6
|
29
31
|
s.extra_rdoc_files = Dir.glob('*.txt')
|
30
32
|
s.rdoc_options << '--title' << "#{s.name}-#{s.version} Documentation" <<
|
31
33
|
'--main' << 'Readme.txt'
|
@@ -0,0 +1,35 @@
|
|
1
|
+
# Example usage of JavaClass::Dependencies::Graph: Iterate all classes of a
|
2
|
+
# classpath and construct the Java dependency graph.
|
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
|
+
# require 'javaclass/dsl/mixin'
|
10
|
+
# require 'javaclass/dependencies/graph'
|
11
|
+
# require 'javaclass/dependencies/class_node'
|
12
|
+
# require 'javaclass/dependencies/yaml_serializer'
|
13
|
+
# require 'javaclass/dependencies/graphml_serializer'
|
14
|
+
#
|
15
|
+
# 1) create the classpath of a given location
|
16
|
+
# cp = classpath(location)
|
17
|
+
#
|
18
|
+
# dependencies = JavaClass::Dependencies::Graph.new
|
19
|
+
#
|
20
|
+
# 2) iterate all classes of the classpath
|
21
|
+
# cp.values.each do |clazz|
|
22
|
+
# next unless clazz.access_flags.public?
|
23
|
+
#
|
24
|
+
# 3) add a JavaClass::Dependencies::ClassNode for each class to the graph
|
25
|
+
# dependencies.add(JavaClass::Dependencies::ClassNode.new(clazz))
|
26
|
+
# end
|
27
|
+
#
|
28
|
+
# 4) resolve all dependencies of all nodes in the graph. Now each class (Node) has a dependency to
|
29
|
+
# all imported classes (Nodes).
|
30
|
+
# dependencies.resolve_dependencies
|
31
|
+
# puts "#{dependencies.to_a.size} classes loaded"
|
32
|
+
#
|
33
|
+
# 5) save the result in various formats, e.g. GraphML or YAML, skipping outgoing edges information
|
34
|
+
# JavaClass::Dependencies::GraphmlSerializer.new(:edges => :no_text).save('class_dependencies', dependencies)
|
35
|
+
# JavaClass::Dependencies::YamlSerializer.new(:outgoing => :none).save('class_dependencies', dependencies)
|
@@ -0,0 +1,43 @@
|
|
1
|
+
# Example usage of JavaClass::Dependencies::Graph: Iterate all folders of a root folder.
|
2
|
+
# Load each component separately and construct the dependency graph.
|
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
|
+
# require 'javaclass/dsl/mixin'
|
10
|
+
# require 'javaclass/dependencies/graph'
|
11
|
+
# require 'javaclass/dependencies/classpath_node'
|
12
|
+
# require 'javaclass/dependencies/yaml_serializer'
|
13
|
+
# require 'javaclass/dependencies/graphml_serializer'
|
14
|
+
#
|
15
|
+
# 1) define the location of the plugins
|
16
|
+
# location = 'C:\Eclipse\workspace'
|
17
|
+
#
|
18
|
+
# plugins = JavaClass::Dependencies::Graph.new
|
19
|
+
#
|
20
|
+
# 2) iterate all plugins of a workspace location
|
21
|
+
# Dir.new(location).each do |folder|
|
22
|
+
# path = File.join(location, folder)
|
23
|
+
# next unless FileTest.directory? path
|
24
|
+
#
|
25
|
+
# classes = File.join(path, 'bin')
|
26
|
+
# next unless FileTest.exist?(classes)
|
27
|
+
#
|
28
|
+
# 3) create a classpath for each plugin
|
29
|
+
# cp = classpath(classes)
|
30
|
+
# next if cp.count == 0
|
31
|
+
#
|
32
|
+
# 4) add a JavaClass::Dependencies::Node for that plugin to the graph
|
33
|
+
# plugins.add(JavaClass::Dependencies::ClasspathNode.new(folder, cp))
|
34
|
+
# end
|
35
|
+
#
|
36
|
+
# 5) resolve all dependencies of all nodes in the graph
|
37
|
+
# plugins.resolve_dependencies
|
38
|
+
# puts "#{plugins.to_a.size} plugins loaded"
|
39
|
+
#
|
40
|
+
# 6) save the result in various formats, e.g. GraphML or YAML
|
41
|
+
# JavaClass::Dependencies::GraphmlSerializer.new.save('plugin_dependencies', plugins)
|
42
|
+
# JavaClass::Dependencies::YamlSerializer.new.save('plugin_dependencies', plugins)
|
43
|
+
# JavaClass::Dependencies::YamlSerializer.new(:outgoing => :summary).save('plugin_dependencies_summary', plugins)
|
@@ -0,0 +1,36 @@
|
|
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
|
+
# require 'javaclass/dsl/mixin'
|
10
|
+
#
|
11
|
+
# 1) define the location of the project and a package you are interrested
|
12
|
+
# location = 'C:\Eclipse\workspace'
|
13
|
+
# package = 'com.biz.app'
|
14
|
+
#
|
15
|
+
# e.g. add an Eclipse classpath variable to find external dependencies.
|
16
|
+
# Eclipse.add_variable('KOR_HOME', location)
|
17
|
+
#
|
18
|
+
# 2) create the classpath of the given workspace
|
19
|
+
# cp = workspace(location)
|
20
|
+
# puts "#{cp.elements.size} classpaths found under the workspace #{location}:"
|
21
|
+
# puts " #{cp.elements.join("\n ")}"
|
22
|
+
# puts "#{cp.count} classes found on classpath"
|
23
|
+
#
|
24
|
+
# 3) filter the classes to analyse, using JavaClass::JavaQualifiedName methods
|
25
|
+
# to_analyse = cp.names { |classname| classname.same_or_subpackage_of?(package) }
|
26
|
+
# puts "#{to_analyse.size} classes matched #{package}"
|
27
|
+
#
|
28
|
+
# 4) load all selected classes, parse into JavaClass::ClassFile, find all interfaces and collect their qualified names
|
29
|
+
# names = cp.values(to_analyse).
|
30
|
+
# find_all { |clazz| clazz.interface? }.
|
31
|
+
# collect { |clazz| clazz.to_classname }
|
32
|
+
# puts "#{names.size} interfaces found:\n #{names.sort.join("\n ")}"
|
33
|
+
#
|
34
|
+
# 5) print all qualified names have a simple namee staring with an I
|
35
|
+
# inames = names.find_all { |classname| classname.simple_name =~ /^I[A-Z][a-z]/ }
|
36
|
+
# puts "#{inames.size} interfaces start with I:\n #{inames.join("\n ")}"
|
@@ -0,0 +1,31 @@
|
|
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
|
+
# require 'javaclass/classpath/factory'
|
12
|
+
# include JavaClass::Classpath::Factory
|
13
|
+
# The require/include above just imports what is needed, but usually one would require the whole
|
14
|
+
# JavaClass::Dsl::Mixin for conveniance, e.g. require 'javaclass/dsl/mixin'.
|
15
|
+
#
|
16
|
+
# 1) define the location of the project
|
17
|
+
# location = 'C:\Eclipse\workspace'
|
18
|
+
#
|
19
|
+
# 2) create a JavaClass::Classpath::CompositeClasspath of the complete workspace, which will contain many classpath elements.
|
20
|
+
# cp = workspace(location)
|
21
|
+
# puts "#{cp.elements.size} classpaths found under the workspace #{location}"
|
22
|
+
#
|
23
|
+
# 3a) find all empty elements by querying the classpath elements
|
24
|
+
# empty = cp.elements.find_all { |clp| clp.count == 0 }
|
25
|
+
# puts "\n#{empty.size} empty modules found:\n #{empty.join("\n ")}"
|
26
|
+
#
|
27
|
+
# 3b) or print the list of each element with its class count
|
28
|
+
# puts "library (module path): number of contained classes"
|
29
|
+
# puts cp.elements.map { |clp| [clp.to_s, clp.count] }.
|
30
|
+
# sort { |a,b| a[1] <=> b[1] }.
|
31
|
+
# map { |e| " #{e[0]}: #{e[1]}" }
|
@@ -0,0 +1,28 @@
|
|
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
|
+
# require 'javaclass/dsl/mixin'
|
12
|
+
#
|
13
|
+
# 1) create the classpath of the given workspace
|
14
|
+
# cp = workspace(location)
|
15
|
+
# puts "#{cp.count} classes found on classpath"
|
16
|
+
#
|
17
|
+
# define a filter to limit all operations to the classes we are interested in
|
18
|
+
# filter = Proc.new { |classname| classname.same_or_subpackage_of?(package) }
|
19
|
+
#
|
20
|
+
# 2a) collect all transitive dependencies of a single class into an AdderTree
|
21
|
+
# dependencies = cp.transitive_dependency_tree(start_class.to_javaname, &filter)
|
22
|
+
# puts "#{dependencies.size} classes in transitive dependency graph of class #{start_class}"
|
23
|
+
# dependencies.debug_print
|
24
|
+
#
|
25
|
+
# 2b) or collect all transitive dependencies of a whole package
|
26
|
+
# dependencies = cp.transitive_dependencies_package(start_class.to_javaname.package, &filter)
|
27
|
+
# puts "#{dependencies.size} classes in transitive dependency graph of package #{start_class.to_javaname.package}"
|
28
|
+
# dependencies.debug_print
|
@@ -0,0 +1,38 @@
|
|
1
|
+
# Example usage of the class analysis featuress of JavaClass::ClassScanner and JavaClass::Analyse.
|
2
|
+
# After defining a classpath, use dependency analysis to find all used classes of a codebase.
|
3
|
+
# This code uses in turn the method <i>imported_3rd_party_types</i> of
|
4
|
+
# JavaClass::ClassScanner::ImportedTypes to find all imported classes.
|
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
|
+
# require 'javaclass/dsl/mixin'
|
12
|
+
#
|
13
|
+
# 1) create the classpath of production classes
|
14
|
+
# cp = classpath(prod_location)
|
15
|
+
#
|
16
|
+
# 2) remember all types defined on this classpath from JavaClass::Analyse::Dependencies
|
17
|
+
# prod_classnames = cp.types
|
18
|
+
#
|
19
|
+
# 3) collect all dependencies of all classes defined there
|
20
|
+
# imported_types_with_numbers = cp.used_types_map
|
21
|
+
# imported_classnames = imported_types_with_numbers.keys
|
22
|
+
#
|
23
|
+
# 4) also collect all classes referenced from config files, defined in JavaClass::JavaNameScanner
|
24
|
+
# hardcoded_classnames = scan_config_for_3rd_party_class_names(conf_location)
|
25
|
+
#
|
26
|
+
# 5) now we know all classes imported/used by production classes
|
27
|
+
# puts '---------- used 3rd party types in production ; 0 = hardcoded'
|
28
|
+
# used_classnames = (imported_classnames + hardcoded_classnames).uniq.sort - prod_classnames
|
29
|
+
# puts used_classnames
|
30
|
+
# used_classnames.each do |name|
|
31
|
+
# puts "#{name} ; #{imported_types_with_numbers[name]}"
|
32
|
+
# end
|
33
|
+
#
|
34
|
+
# 6) do the same for test classes, at least org.junit.* should show up here
|
35
|
+
# test_cp = classpath(test_location)
|
36
|
+
# puts '---------- used 3rd party types only in tests'
|
37
|
+
# test_classes = test_cp.external_types - prod_classnames - used_classnames
|
38
|
+
# puts test_classes
|
@@ -0,0 +1,73 @@
|
|
1
|
+
# Example usage of dependency graph: Invert the graph and see incoming dependencies of a module.
|
2
|
+
# After getting all classes of a module, use previously generated dependency graph to iterate
|
3
|
+
# all incoming edges. Then either report all incoming edges as CSV or find all private/inner
|
4
|
+
# classes of the module. Works with an existing dependency graph,
|
5
|
+
# e.g. created by {chart module dependencies example}[link:/files/lib/generated/examples/chart_module_dependencies_txt.html].
|
6
|
+
# Author:: Peter Kofler
|
7
|
+
# Copyright:: Copyright (c) 2012, Peter Kofler.
|
8
|
+
# License:: {BSD License}[link:/files/license_txt.html]
|
9
|
+
#
|
10
|
+
# === Steps
|
11
|
+
#
|
12
|
+
# require 'javaclass/dsl/mixin'
|
13
|
+
# require 'javaclass/classpath/tracking_classpath'
|
14
|
+
# require 'javaclass/dependencies/edge'
|
15
|
+
# require 'javaclass/dependencies/yaml_serializer'
|
16
|
+
#
|
17
|
+
# 1) create a classpath of the main model plugin
|
18
|
+
# Plugin_name = 'org.codecop.model'
|
19
|
+
# cp = classpath(File.join(location, Plugin_name, 'bin'))
|
20
|
+
# classes = cp.names
|
21
|
+
# puts "#{classes.count} classes found in main plugin"
|
22
|
+
# cp.reset_access
|
23
|
+
#
|
24
|
+
# 2) load a dependency Graph containing the model
|
25
|
+
# plugins = JavaClass::Dependencies::YamlSerializer.new.load('plugin_dependencies')
|
26
|
+
#
|
27
|
+
# used to strip beginning of full qualified names
|
28
|
+
# def strip(name)
|
29
|
+
# name.sub(/^org\.codecop\./, '*.')
|
30
|
+
# end
|
31
|
+
#
|
32
|
+
# 3) mark all accessed classes in model plugin using the dependency graph
|
33
|
+
# plugins.each_node do |plugin|
|
34
|
+
# next if plugin.name == Plugin_name
|
35
|
+
# plugin.each_edge do |dep, edge|
|
36
|
+
# next unless dep.name == Plugin_name
|
37
|
+
# cp.mark_accessed(edge.target)
|
38
|
+
# end
|
39
|
+
# end
|
40
|
+
#
|
41
|
+
# plugins.each_node do |plugin|
|
42
|
+
# plugin.each_dependency_provider do |dep, dependencies|
|
43
|
+
# plugin.dependencies[dep] = dependencies.map { |edge|
|
44
|
+
# # replace class edges by package edges
|
45
|
+
# # JavaClass::Dependencies::Edge.new(edge.source.to_javaname.package, edge.target.to_javaname.package)
|
46
|
+
#
|
47
|
+
# # replace class edges with source plugin, target package
|
48
|
+
# # JavaClass::Dependencies::Edge.new(plugin.name, edge.target.to_javaname.package)
|
49
|
+
#
|
50
|
+
# # replace source edges with source plugin
|
51
|
+
# JavaClass::Dependencies::Edge.new(plugin.name, edge.target)
|
52
|
+
# }.uniq.sort
|
53
|
+
# end
|
54
|
+
# end
|
55
|
+
#
|
56
|
+
# 4) report all incoming dependencies (edges) for further Excel analysis
|
57
|
+
# plugins.each_node do |plugin|
|
58
|
+
# next if plugin.name == Plugin_name
|
59
|
+
# plugin.each_edge do |dep, edge|
|
60
|
+
# next unless dep.name == Plugin_name
|
61
|
+
# puts "#{strip(edge.target)};#{strip(plugin.name)};#{strip(edge.source)}"
|
62
|
+
# end
|
63
|
+
# end
|
64
|
+
#
|
65
|
+
# 5) report unused classes in model from outside
|
66
|
+
# unused_classes = classes.
|
67
|
+
# find_all { |clazz| cp.accessed(clazz) == 0 }.
|
68
|
+
# reject { |clazz| clazz =~ /\$.*$/ }
|
69
|
+
# report = unused_classes.map { |clazz| "#{clazz.to_classname}" }.uniq
|
70
|
+
# puts "#{report.size} private classes found:"
|
71
|
+
# report.each do |clazz|
|
72
|
+
# puts "#{strip(clazz)};(internal);NA"
|
73
|
+
# end
|
@@ -0,0 +1,70 @@
|
|
1
|
+
# Example usage of dependency graph: Organize the nodes into layers
|
2
|
+
# depending on their dependencies. Works with an existing dependency graph,
|
3
|
+
# e.g. created by {chart module dependencies example}[link:/files/lib/generated/examples/chart_module_dependencies_txt.html].
|
4
|
+
# Author:: Peter Kofler
|
5
|
+
# Copyright:: Copyright (c) 2012, Peter Kofler.
|
6
|
+
# License:: {BSD License}[link:/files/license_txt.html]
|
7
|
+
#
|
8
|
+
# === Steps
|
9
|
+
#
|
10
|
+
# require 'javaclass/dependencies/yaml_serializer'
|
11
|
+
#
|
12
|
+
# 1) load dependency graph
|
13
|
+
# plugins = JavaClass::Dependencies::YamlSerializer.new.load('plugin_dependencies')
|
14
|
+
# components = plugins.to_a
|
15
|
+
#
|
16
|
+
# @layerOfComponents = []
|
17
|
+
#
|
18
|
+
# 2) find modules without any dependencies, these are the first/bottom
|
19
|
+
# first_elements = components.find_all { |c| c.dependencies.size == 0 }.sort
|
20
|
+
# @layerOfComponents << first_elements
|
21
|
+
# components = components - first_elements
|
22
|
+
#
|
23
|
+
# def has_all_deps_satisfied?(component)
|
24
|
+
# already_sorted_dependencies = @layerOfComponents.flatten
|
25
|
+
# component.dependencies.keys.find { |dependency|
|
26
|
+
# !already_sorted_dependencies.include?(dependency)
|
27
|
+
# } == nil
|
28
|
+
# end
|
29
|
+
#
|
30
|
+
# while components.size > 0
|
31
|
+
# cycle = true
|
32
|
+
#
|
33
|
+
# # 3) for each component, check if all dependencies are satisfied combined layers below
|
34
|
+
# components.each do |component|
|
35
|
+
#
|
36
|
+
# if has_all_deps_satisfied?(component)
|
37
|
+
# components -= [component]
|
38
|
+
#
|
39
|
+
# # 4) if yes, walk up the dependencies until highest/lowest possible
|
40
|
+
# index = @layerOfComponents.size - 1
|
41
|
+
# while (component.dependencies.keys.find { |dependency| @layerOfComponents[index].include?(dependency) } == nil)
|
42
|
+
# index = index -1
|
43
|
+
# end
|
44
|
+
# index = index + 1 # take next
|
45
|
+
#
|
46
|
+
# # and add to the layers
|
47
|
+
# if index == @layerOfComponents.size
|
48
|
+
# @layerOfComponents[index] = []
|
49
|
+
# end
|
50
|
+
# @layerOfComponents[index] << component
|
51
|
+
#
|
52
|
+
# puts "added #{component}"
|
53
|
+
# cycle = false
|
54
|
+
# break
|
55
|
+
# end
|
56
|
+
#
|
57
|
+
# end
|
58
|
+
#
|
59
|
+
# if cycle
|
60
|
+
# warn "cycle in #{components.join(', ')}, can't continue with layering"
|
61
|
+
# break
|
62
|
+
# end
|
63
|
+
# end
|
64
|
+
#
|
65
|
+
# 5) output the found layering
|
66
|
+
# (1..@layerOfComponents.size).each do |i|
|
67
|
+
# layer = @layerOfComponents[i-1].sort
|
68
|
+
# puts "#{i} " + layer.join(', ')
|
69
|
+
# end
|
70
|
+
#
|