javaclass 0.4.1 → 0.4.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|
+
#
|