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.
Files changed (54) hide show
  1. checksums.yaml +7 -0
  2. data/Rakefile +188 -194
  3. data/Readme.txt +33 -29
  4. data/examples/generate_class_lists.rb +16 -9
  5. data/history.txt +15 -4
  6. data/javaclass.gemspec +10 -8
  7. data/lib/generated/examples/chart_class_dependencies.txt +35 -0
  8. data/lib/generated/examples/chart_module_dependencies.txt +43 -0
  9. data/lib/generated/examples/check_interface_names.txt +36 -0
  10. data/lib/generated/examples/count_classes_in_modules.txt +31 -0
  11. data/lib/generated/examples/cumulative_dependencies.txt +28 -0
  12. data/lib/generated/examples/find_all_imported_types.txt +38 -0
  13. data/lib/generated/examples/find_incoming_dependency_graph.txt +73 -0
  14. data/lib/generated/examples/find_layers_of_modules.txt +70 -0
  15. data/lib/generated/examples/find_referenced_modules.txt +41 -0
  16. data/lib/generated/examples/find_unreferenced_classes.txt +66 -0
  17. data/lib/generated/examples/generate_class_lists.txt +53 -0
  18. data/lib/generated/examples/show_jar_api.txt +64 -0
  19. data/lib/generated/examples/simple_usage.txt +38 -0
  20. data/lib/javaclass/classfile/access_flag_constants.rb +32 -5
  21. data/lib/javaclass/classfile/access_flags.rb +39 -20
  22. data/lib/javaclass/classfile/attributes/attributes.rb +134 -0
  23. data/lib/javaclass/classfile/class_access_flags.rb +37 -0
  24. data/lib/javaclass/classfile/class_file_attributes.rb +62 -0
  25. data/lib/javaclass/classfile/class_version.rb +0 -1
  26. data/lib/javaclass/classfile/constant_pool.rb +17 -11
  27. data/lib/javaclass/classfile/constants/single_reference.rb +53 -0
  28. data/lib/javaclass/classfile/fields.rb +37 -0
  29. data/lib/javaclass/classfile/java_class_header.rb +22 -13
  30. data/lib/javaclass/classfile/java_class_header_shortcuts.rb +6 -2
  31. data/lib/javaclass/classfile/methods.rb +37 -0
  32. data/lib/javaclass/classlist/jar_searcher.rb +38 -4
  33. data/lib/javaclass/classpath/temporary_unpacker.rb +1 -1
  34. data/lib/javaclass/string_hexdump.rb +1 -1
  35. data/license.txt +7 -7
  36. data/test/data/access_flags/{AccessFlagsTestInner$1.class → AccessFlagsTestAnonym$1.class} +0 -0
  37. data/test/data/access_flags/{AccessFlagsTestInner.class → AccessFlagsTestAnonym.class} +0 -0
  38. data/test/data/access_flags/AccessFlagsTestAnonym.java +9 -0
  39. data/test/data/access_flags/AccessFlagsTestPublic_javap.txt +1 -0
  40. data/test/data/constant_pool/Java8_JavaFX_Animation$1_Tag15.class +0 -0
  41. data/test/data/constant_pool/Java9_Activation_module-info_Tag20.class +0 -0
  42. data/test/data/jar_searcher/JarClassListTest.jar +0 -0
  43. data/test/data/jar_searcher/PublicClass.java +44 -1
  44. data/test/data/jar_searcher/make.bat +1 -2
  45. data/test/{test_access_flags.rb → test_class_access_flags.rb} +91 -93
  46. data/test/test_class_file_attributes.rb +57 -0
  47. data/test/test_constant_pool.rb +31 -0
  48. data/test/test_jar_searcher.rb +40 -7
  49. data/test/test_javaclass_api.rb +2 -2
  50. data/test/test_string_hexdump.rb +4 -1
  51. data/test/ts_all_tests.rb +4 -2
  52. metadata +100 -116
  53. data/test/data/access_flags/AccessFlagsTestInner$2.class +0 -0
  54. 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', ['E:\Develop\Java\Compiler\jdk1.0.2\lib']),
26
- JDK_CONFIG.new(1, '1.1.8-09', ['E:\Develop\Java\Compiler\jdk1.1.8\lib', 'E:\Develop\Java\JDK-1.1\Library\swing-1.1.1\lib']),
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/ COM/rsa/
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
@@ -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 testet there anymore
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 artefact to generate classpath from group/name/version
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 submodules for classpath, classfile, etc.
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
@@ -1,17 +1,18 @@
1
1
  GEM_NAME = 'javaclass'
2
- HG_PROJECT = "#{GEM_NAME}-rb"
2
+ GIT_PROJECT = "#{GEM_NAME}-rb"
3
3
 
4
4
  Gem::Specification.new do |s|
5
- s.version = '0.4.1'
5
+ s.version = '0.4.2'
6
6
  s.name = GEM_NAME
7
- s.rubyforge_project = 'javaclass' # old, just redirects
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://bitbucket.org/pkofler/#{HG_PROJECT}"
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(2015, 5, 30) # set current date for release
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
+ #