├── bigpic.jpg ├── contrib ├── ckjm_ruby-1.0 │ ├── doc │ │ ├── created.rid │ │ ├── index.html │ │ ├── fr_file_index.html │ │ ├── classes │ │ │ ├── MetricsUtils │ │ │ │ ├── Plotter.src │ │ │ │ │ ├── M000008.html │ │ │ │ │ ├── M000006.html │ │ │ │ │ ├── M000004.html │ │ │ │ │ ├── M000007.html │ │ │ │ │ └── M000005.html │ │ │ │ ├── JavaMetrics.src │ │ │ │ │ ├── M000009.html │ │ │ │ │ ├── M000011.html │ │ │ │ │ └── M000010.html │ │ │ │ ├── CKJMMetricGrapher.src │ │ │ │ │ ├── M000002.html │ │ │ │ │ └── M000003.html │ │ │ │ ├── CKJMMetricGrapher.html │ │ │ │ ├── JavaMetrics.html │ │ │ │ └── Plotter.html │ │ │ ├── App.src │ │ │ │ └── M000001.html │ │ │ ├── MetricsUtils.html │ │ │ └── App.html │ │ ├── fr_class_index.html │ │ ├── fr_method_index.html │ │ ├── files │ │ │ ├── metrics_utils_rb.html │ │ │ └── mk_ckjm_graphs_rb.html │ │ └── rdoc-style.css │ ├── examples │ │ ├── util_concurrent_ca_metric.png │ │ ├── util_concurrent_cbo_metric.png │ │ ├── util_concurrent_dit_metric.png │ │ ├── util_concurrent_noc_metric.png │ │ ├── util_concurrent_npm_metric.png │ │ ├── util_concurrent_rfc_metric.png │ │ ├── util_concurrent_wmc_metric.png │ │ ├── util_concurrent_lcom_metric.png │ │ └── util_concurrent.ckjm │ ├── mk_ckjm_graphs.rb │ └── metrics_utils.rb └── README ├── smallpic.jpg ├── lib ├── bcel-6.8.1.jar ├── NOTICE.txt └── LICENSE.txt ├── test └── ckjm-1.8.jar ├── doc ├── eclipse-cbo.png ├── contr.xml ├── ckjm2xml ├── Makefile ├── index.xml ├── web.xml ├── detail.xml ├── oper.xml ├── intro.xml ├── insel.xml ├── anttask.xml ├── ver.xml ├── outfmt.xml ├── metric.xml ├── faq.xml ├── bib.xml └── bib.bib ├── .gitignore ├── README.txt ├── .github └── workflows │ └── maven-test.yml ├── tests ├── run ├── gr │ └── spinellis │ │ └── ckjm │ │ └── MetricsFilterTest.java └── Test.java ├── README.md ├── src └── gr │ └── spinellis │ └── ckjm │ ├── PrintPlainResults.java │ ├── CkjmOutputHandler.java │ ├── ant │ ├── PrintXmlResults.java │ └── CkjmTask.java │ ├── ClassMetricsContainer.java │ ├── MethodVisitor.java │ ├── MetricsFilter.java │ ├── ClassMetrics.java │ └── ClassVisitor.java ├── Makefile ├── xsl ├── ckjm.xsl └── ckjm_extra.xsl ├── pom.xml ├── index.html └── LICENSE /bigpic.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dspinellis/ckjm/HEAD/bigpic.jpg -------------------------------------------------------------------------------- /contrib/ckjm_ruby-1.0/doc/created.rid: -------------------------------------------------------------------------------- 1 | Thu Feb 15 01:30:46 -0500 2007 2 | -------------------------------------------------------------------------------- /smallpic.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dspinellis/ckjm/HEAD/smallpic.jpg -------------------------------------------------------------------------------- /lib/bcel-6.8.1.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dspinellis/ckjm/HEAD/lib/bcel-6.8.1.jar -------------------------------------------------------------------------------- /test/ckjm-1.8.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dspinellis/ckjm/HEAD/test/ckjm-1.8.jar -------------------------------------------------------------------------------- /doc/eclipse-cbo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dspinellis/ckjm/HEAD/doc/eclipse-cbo.png -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | build/ 2 | doc/fmtcache/ 3 | hsqldb.xml 4 | javadoc/ 5 | output_extra.html 6 | output_simple.html 7 | test/new.txt 8 | ckjm-[0-9]* 9 | -------------------------------------------------------------------------------- /contrib/ckjm_ruby-1.0/examples/util_concurrent_ca_metric.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dspinellis/ckjm/HEAD/contrib/ckjm_ruby-1.0/examples/util_concurrent_ca_metric.png -------------------------------------------------------------------------------- /contrib/ckjm_ruby-1.0/examples/util_concurrent_cbo_metric.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dspinellis/ckjm/HEAD/contrib/ckjm_ruby-1.0/examples/util_concurrent_cbo_metric.png -------------------------------------------------------------------------------- /contrib/ckjm_ruby-1.0/examples/util_concurrent_dit_metric.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dspinellis/ckjm/HEAD/contrib/ckjm_ruby-1.0/examples/util_concurrent_dit_metric.png -------------------------------------------------------------------------------- /contrib/ckjm_ruby-1.0/examples/util_concurrent_noc_metric.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dspinellis/ckjm/HEAD/contrib/ckjm_ruby-1.0/examples/util_concurrent_noc_metric.png -------------------------------------------------------------------------------- /contrib/ckjm_ruby-1.0/examples/util_concurrent_npm_metric.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dspinellis/ckjm/HEAD/contrib/ckjm_ruby-1.0/examples/util_concurrent_npm_metric.png -------------------------------------------------------------------------------- /contrib/ckjm_ruby-1.0/examples/util_concurrent_rfc_metric.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dspinellis/ckjm/HEAD/contrib/ckjm_ruby-1.0/examples/util_concurrent_rfc_metric.png -------------------------------------------------------------------------------- /contrib/ckjm_ruby-1.0/examples/util_concurrent_wmc_metric.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dspinellis/ckjm/HEAD/contrib/ckjm_ruby-1.0/examples/util_concurrent_wmc_metric.png -------------------------------------------------------------------------------- /contrib/ckjm_ruby-1.0/examples/util_concurrent_lcom_metric.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dspinellis/ckjm/HEAD/contrib/ckjm_ruby-1.0/examples/util_concurrent_lcom_metric.png -------------------------------------------------------------------------------- /contrib/README: -------------------------------------------------------------------------------- 1 | This directory contains contributed code that has been designed 2 | to interoperate with ckjm. 3 | 4 | ckjm_ruby-1.0 contains Runy scripts to plot the ckjm metrics in charts. 5 | -------------------------------------------------------------------------------- /doc/contr.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 |
4 |
Panagiotis Louridas
Fix for a script in the documentation
5 |
Antti Pöyhönen
RFC fix, count exceptions
6 |
Julien Rentrop
XML output and Ant task
7 |
8 |
9 | 10 | -------------------------------------------------------------------------------- /doc/ckjm2xml: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sed -f 2 | 1i\ 3 | \ 4 | 5 | s/^// 6 | s/ /<\/classname>/ 7 | s/ /<\/WMC>/ 8 | s/ /<\/DIT>/ 9 | s/ /<\/NOC>/ 10 | s/ /<\/CBO>/ 11 | s/ /<\/RFC>/ 12 | s/ /<\/LCOM>/ 13 | s/ /<\/Ca>/ 14 | s/$/<\/NPM><\/metric>/ 15 | $a\ 16 | 17 | -------------------------------------------------------------------------------- /doc/Makefile: -------------------------------------------------------------------------------- 1 | # 2 | # $Id: Makefile 1.1 2002/09/20 08:08:59 dds Exp dds $ 3 | # 4 | 5 | DESTDIR=/dds/pubs/web/home/sw/ckjm 6 | NOTETOOLS=/dds/pubs/courses/tools 7 | XML := $(wildcard *.xml) 8 | 9 | all: $(XML) 10 | sh $(UH)/$(NOTETOOLS)/coursebib.sh bib 11 | echo "ckjm - A Tool for Calculating Chidamber and Kemerer Java Metrics" | perl $(NOTETOOLS)/thread.pl -h html -r -p ../index.html index ${DESTDIR}/doc 12 | -------------------------------------------------------------------------------- /lib/NOTICE.txt: -------------------------------------------------------------------------------- 1 | ========================================================================= 2 | == NOTICE file corresponding to the section 4 d of == 3 | == the Apache License, Version 2.0, == 4 | == in this case for the Apache Jakarta-BCEL distribution. == 5 | ========================================================================= 6 | 7 | This product includes software developed by 8 | The Apache Software Foundation (http://www.apache.org/). 9 | 10 | 11 | -------------------------------------------------------------------------------- /doc/index.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | Introductionintro 4 | Operationoper 5 | Using Pipelines to Select Classesinsel 6 | Using Pipelines to Format the Outputoutfmt 7 | Metric Descriptionsmetric 8 | Measurement Detailsdetail 9 | Using Ckjm With Antanttask 10 | Web Links and Acknowledgementsweb 11 | Bibliographybib 12 | Version Historyver 13 | Frequently Asked Questionsfaq 14 | Contributorscontr 15 | 16 | -------------------------------------------------------------------------------- /doc/web.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 |

Related Links

4 | 9 |

Derived Software

10 | 13 |

14 | This product includes software developed by the 15 | Apache Software Foundation. 16 |

17 |
18 | -------------------------------------------------------------------------------- /README.txt: -------------------------------------------------------------------------------- 1 | ckjm - Chidamber and Kemerer metrics for Java 2 | 3 | This directory contains the source and compiled version for 4 | a program to calculate the Chidamber and Kemerer metrics 5 | in a set of Java class files. 6 | 7 | The compiled jar file you need to extract the metrics is 8 | in the build directory. Place is in a convenient location. 9 | 10 | The build.xml file allows you to build the project from source 11 | using ant. Compilation requires Java 1.5 (J2SE5). 12 | 13 | Complete documentation, in HTML format, is in the doc directory. 14 | To print the documentation as a single document, open the 15 | file indexw.html, to browse it, open the file index.html. 16 | 17 | The project's home page is http://www.spinellis.gr/sw/ckjm 18 | 19 | Diomidis Spinellis, February 2005 20 | -------------------------------------------------------------------------------- /.github/workflows/maven-test.yml: -------------------------------------------------------------------------------- 1 | name: Maven Test Workflow 2 | 3 | 4 | on: 5 | push: 6 | branches: [ "master" ] 7 | pull_request: 8 | branches: [ "master" ] 9 | 10 | jobs: 11 | build-and-test: 12 | runs-on: ubuntu-latest 13 | 14 | steps: 15 | # Check out the code from the repository 16 | - name: Checkout repository 17 | uses: actions/checkout@v4 18 | 19 | # Set up Java with Maven 20 | - name: Set up Java 21 | uses: actions/setup-java@v4 22 | with: 23 | distribution: 'temurin' # Use Eclipse Temurin as the JDK distribution 24 | java-version: '17' 25 | cache: 'maven' # Enable caching for Maven dependencies 26 | 27 | # Build and run tests using Maven 28 | - name: Build and run tests 29 | run: mvn test 30 | -------------------------------------------------------------------------------- /contrib/ckjm_ruby-1.0/doc/index.html: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 11 | 12 | 13 | RDoc Documentation 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /contrib/ckjm_ruby-1.0/doc/fr_file_index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | 7 | 12 | 13 | 14 | Files 15 | 16 | 17 | 18 | 19 | 20 |
21 |

Files

22 |
23 | metrics_utils.rb
24 | mk_ckjm_graphs.rb
25 |
26 |
27 | 28 | -------------------------------------------------------------------------------- /contrib/ckjm_ruby-1.0/doc/classes/MetricsUtils/Plotter.src/M000008.html: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 8 | end_of_data (MetricsUtils::Plotter) 9 | 10 | 11 | 12 | 13 |
# File metrics_utils.rb, line 82
14 |     def end_of_data
15 |       print_to_graph "e" # gnuplot-specific
16 |     end
17 | 18 | -------------------------------------------------------------------------------- /tests/run: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # 3 | # $Id: \\dds\\src\\Research\\ckjm.RCS\\tests\\run,v 1.1 2005/11/05 08:37:28 dds Exp $ 4 | # 5 | VER=`sed -n 's/^VERSION=\(.*\)/\1/p' ../Makefile` 6 | echo Testing version $VER 7 | echo Expect 4 \"Test \# passed\" lines 8 | 9 | javac Test.java 10 | 11 | # Test metric values 12 | java -jar ../build/ckjm-$VER.jar *.class | sed 's/ /,WMC=/;s/ /,DIT=/;s/ /,NOC=/;s/ /,CBO=/;s/ /,RFC=/;s/ /,LCOM=/;s/ /,CA=/;s/ /,NPM=/' | sort >test.new 13 | diff -u test.ok test.new && echo Test 1 passed 14 | 15 | # Test invocation on multiple non trivial files 16 | java -jar ../build/ckjm-$VER.jar ../build/classes/gr/spinellis/ckjm/*.class >nul && echo Test 2 passed 17 | 18 | # Test jar reading 19 | java -jar ../build/ckjm-$VER.jar "../build/ckjm-$VER.jar gr/spinellis/ckjm/ClassVisitor.class" >nul && echo Test 3 passed 20 | 21 | # Test stdin specifications 22 | echo "../build/ckjm-$VER.jar gr/spinellis/ckjm/ClassVisitor.class" | java -jar ../build/ckjm-$VER.jar >nul && echo Test 4 passed 23 | -------------------------------------------------------------------------------- /contrib/ckjm_ruby-1.0/doc/classes/MetricsUtils/JavaMetrics.src/M000009.html: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 8 | new (MetricsUtils::JavaMetrics) 9 | 10 | 11 | 12 | 13 |
# File metrics_utils.rb, line 111
14 |     def initialize(ckjm_file_name)
15 |       @ckjm_file_name = ckjm_file_name
16 |       @distribution = {}
17 |     end
18 | 19 | -------------------------------------------------------------------------------- /contrib/ckjm_ruby-1.0/doc/classes/MetricsUtils/Plotter.src/M000006.html: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 8 | close (MetricsUtils::Plotter) 9 | 10 | 11 | 12 | 13 |
# File metrics_utils.rb, line 68
14 |     def close
15 |       @plot_pipe && @plot_pipe.close
16 |     ensure
17 |       @plot_pipe = nil
18 |     end
19 | 20 | -------------------------------------------------------------------------------- /contrib/ckjm_ruby-1.0/doc/fr_class_index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | 7 | 12 | 13 | 14 | Classes 15 | 16 | 17 | 18 | 19 | 20 |
21 |

Classes

22 |
23 | App
24 | MetricsUtils
25 | MetricsUtils::CKJMMetricGrapher
26 | MetricsUtils::JavaMetrics
27 | MetricsUtils::Plotter
28 |
29 |
30 | 31 | -------------------------------------------------------------------------------- /contrib/ckjm_ruby-1.0/doc/classes/MetricsUtils/JavaMetrics.src/M000011.html: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 8 | metric_desc (MetricsUtils::JavaMetrics) 9 | 10 | 11 | 12 | 13 |
# File metrics_utils.rb, line 143
14 |     def metric_desc(sym)
15 |       METRIC_DESC[sym] or raise ArgumentError, "Unknown symbol :#{sym}"
16 |     end
17 | 18 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Chidamber and Kemerer Java Metrics 2 | 3 | [![DOI](https://zenodo.org/badge/3928910.svg)](https://zenodo.org/badge/latestdoi/3928910) 4 | 5 | 6 | The program _ckjm_ calculates Chidamber and Kemerer object-oriented metrics by processing the bytecode of compiled Java files. The program calculates for each class the following six metrics proposed by Chidamber and Kemerer. 7 | 8 | * WMC: Weighted methods per class 9 | * DIT: Depth of Inheritance Tree 10 | * NOC: Number of Children 11 | * CBO: Coupling between object classes 12 | * RFC: Response for a Class 13 | * LCOM: Lack of cohesion in methods 14 | 15 | In addition it also calculates for each class 16 | 17 | * Ca: Afferent couplings 18 | * NPM: Number of public methods 19 | 20 | If you use this tool in your research, please cite the following paper. 21 | 22 | Diomidis Spinellis. [Tool writing: A forgotten art?](http://www.spinellis.gr/pubs/jrnl/2005-IEEESW-TotT/html/v22n4.html) _IEEE Software_, 22(4):9–11, July/August 2005. [doi:10.1109/MS.2005.111](http://dx.doi.org/10.1109/MS.2005.111). 23 | 24 | Visit the project's [home page](http://www.spinellis.gr/sw/ckjm/) for more information. 25 | -------------------------------------------------------------------------------- /contrib/ckjm_ruby-1.0/doc/classes/MetricsUtils/Plotter.src/M000004.html: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 8 | new (MetricsUtils::Plotter) 9 | 10 | 11 | 12 | 13 |
# File metrics_utils.rb, line 45
14 |     def initialize
15 |       @plot_cmd = "gnuplot -"
16 |       @plot_cmd << " > /dev/null 2>&1" unless $debug_mode
17 |     end
18 | 19 | -------------------------------------------------------------------------------- /contrib/ckjm_ruby-1.0/doc/classes/MetricsUtils/Plotter.src/M000007.html: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 8 | print_to_graph (MetricsUtils::Plotter) 9 | 10 | 11 | 12 | 13 |
# File metrics_utils.rb, line 75
14 |     def print_to_graph(plot_data)
15 |       @plot_pipe.puts plot_data
16 |       puts(plot_data) if $debug_mode
17 |     end
18 | 19 | -------------------------------------------------------------------------------- /src/gr/spinellis/ckjm/PrintPlainResults.java: -------------------------------------------------------------------------------- 1 | /* 2 | * (C) Copyright 2005 Diomidis Spinellis, Julien Rentrop 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package gr.spinellis.ckjm; 18 | 19 | import java.io.PrintStream; 20 | 21 | /** 22 | * Simple plain text output formatter 23 | * @author Julien Rentrop 24 | */ 25 | public class PrintPlainResults implements CkjmOutputHandler { 26 | private PrintStream p; 27 | 28 | public PrintPlainResults (PrintStream p) { 29 | this.p = p; 30 | } 31 | 32 | public void handleClass(String name, ClassMetrics c) { 33 | p.println(name + " " + c.toString()); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/gr/spinellis/ckjm/CkjmOutputHandler.java: -------------------------------------------------------------------------------- 1 | /* 2 | * (C) Copyright 2005 Diomidis Spinellis, Julien Rentrop 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package gr.spinellis.ckjm; 18 | 19 | /** 20 | * Interface of output handlers 21 | * Use this interface to couple your tool to CKJM. Example implenations 22 | * which could use this tool are ant task writing, IDE integration, 23 | * GUI based interfaces etc. 24 | * 25 | * @author Julien Rentrop 26 | */ 27 | public interface CkjmOutputHandler { 28 | /** 29 | * Method called when metrics are generated 30 | * @param name Name of the class 31 | * @param c Value object that contains the corresponding metrics 32 | */ 33 | void handleClass(String name, ClassMetrics c); 34 | } 35 | -------------------------------------------------------------------------------- /contrib/ckjm_ruby-1.0/doc/classes/MetricsUtils/CKJMMetricGrapher.src/M000002.html: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 8 | new (MetricsUtils::CKJMMetricGrapher) 9 | 10 | 11 | 12 | 13 |
# File metrics_utils.rb, line 160
14 |     def initialize(ckjm_file_name, project_desc, plotter, jm)
15 |       @ckjm_file_name, @project_desc, @plotter, @jm = ckjm_file_name, project_desc, plotter, jm
16 |     end
17 | 18 | -------------------------------------------------------------------------------- /tests/gr/spinellis/ckjm/MetricsFilterTest.java: -------------------------------------------------------------------------------- 1 | package gr.spinellis.ckjm; 2 | 3 | import static org.junit.Assert.assertEquals; 4 | import static org.junit.Assert.assertTrue; 5 | 6 | import java.io.File; 7 | import java.util.concurrent.CountDownLatch; 8 | import java.util.concurrent.TimeUnit; 9 | import java.util.concurrent.atomic.AtomicReference; 10 | 11 | import org.junit.Test; 12 | 13 | import gr.spinellis.ckjm.CkjmOutputHandler; 14 | import gr.spinellis.ckjm.ClassMetrics; 15 | import gr.spinellis.ckjm.MetricsFilter; 16 | 17 | public class MetricsFilterTest { 18 | 19 | @Test 20 | public void test() throws InterruptedException { 21 | final CountDownLatch latch = new CountDownLatch(1); 22 | final AtomicReference ref = new AtomicReference<>(); 23 | CkjmOutputHandler outputHandler = new CkjmOutputHandler() { 24 | @Override 25 | public void handleClass(String name, ClassMetrics c) { 26 | System.out.println("name: " + name + ", WMC: " + c.getWmc()); 27 | ref.set(c); 28 | latch.countDown(); 29 | } 30 | }; 31 | File f = new File("target/classes/gr/spinellis/ckjm/MetricsFilter.class"); 32 | assertTrue("File " + f.getAbsolutePath() + " not present", f.exists()); 33 | MetricsFilter.runMetrics(new String[] { f.getAbsolutePath() }, outputHandler); 34 | latch.await(1, TimeUnit.SECONDS); 35 | assertEquals(7, ref.get().getWmc()); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /contrib/ckjm_ruby-1.0/doc/classes/MetricsUtils/CKJMMetricGrapher.src/M000003.html: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 8 | plot_metrics (MetricsUtils::CKJMMetricGrapher) 9 | 10 | 11 | 12 | 13 |
# File metrics_utils.rb, line 165
14 |     def plot_metrics
15 |       @jm.metrics.each do |metric_sym, vals|
16 |         @plotter.open do
17 |           plot_metric metric_sym, vals
18 |         end
19 |       end
20 |     end
21 | 22 | -------------------------------------------------------------------------------- /contrib/ckjm_ruby-1.0/doc/classes/MetricsUtils/Plotter.src/M000005.html: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 8 | open (MetricsUtils::Plotter) 9 | 10 | 11 | 12 | 13 |
# File metrics_utils.rb, line 53
14 |     def open(&blk) # :yields:
15 |       @plot_pipe = IO.popen(@plot_cmd, "w")
16 | 
17 |       if blk
18 |         begin
19 |           blk.call
20 |         ensure
21 |           self.close
22 |         end
23 |       end
24 |       nil
25 |     end
26 | 27 | -------------------------------------------------------------------------------- /contrib/ckjm_ruby-1.0/doc/fr_method_index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | 7 | 12 | 13 | 14 | Methods 15 | 16 | 17 | 18 | 19 | 20 |
21 |

Methods

22 | 35 |
36 | 37 | -------------------------------------------------------------------------------- /tests/Test.java: -------------------------------------------------------------------------------- 1 | /* 2 | * ckjm test data 3 | * 4 | * $Id: \\dds\\src\\Research\\ckjm.RCS\\tests\\Test.java,v 1.2 2005/11/05 08:37:28 dds Exp $ 5 | * 6 | */ 7 | 8 | import java.util.*; 9 | 10 | /* NOC = 1, LCOM = 2 - 1 = 1 */ 11 | class Test { 12 | int fieldname_a; 13 | int fieldname_b; 14 | int fieldname_c; 15 | int fieldname_d; 16 | int fieldname_e; 17 | int fieldname_x; 18 | int fieldname_y; 19 | int fieldname_z; 20 | String fieldname_s1; 21 | String fieldname_s2[]; 22 | Set fieldname_s3; 23 | static int sa; 24 | 25 | Test() { 26 | System.out.println( 27 | fieldname_a + fieldname_b + 28 | fieldname_c + fieldname_d + 29 | fieldname_e); 30 | } 31 | 32 | int methodname_2(int i) { 33 | System.out.println("hi"); 34 | return (fieldname_a + fieldname_b + fieldname_e); 35 | } 36 | 37 | AbstractCollection methodname_3(AbstractCollection a, ArrayList b[]) { 38 | System.out.println("hi"); 39 | Integer i = new Integer(fieldname_x + fieldname_y + fieldname_z); 40 | return a; 41 | } 42 | } 43 | 44 | /* Coupling via extension + DIT=2 */ 45 | class STest extends Test { 46 | } 47 | 48 | /* DIT=3 */ 49 | class SSTest extends STest { 50 | } 51 | 52 | /* Coupling (1) via field type */ 53 | class Test2 { 54 | Test a; 55 | Test b; 56 | } 57 | 58 | /* Coupling (1) via method invocation */ 59 | class Test3 { 60 | int foo() { Test a = null; return a.methodname_2(1); } 61 | } 62 | 63 | /* Coupling (2) via local variable type ctor */ 64 | class Test4 { 65 | void foo() { STest a = new SSTest(); a.methodname_2(4); } 66 | } 67 | 68 | 69 | /* Coupling (1) via field access */ 70 | class Test5 { 71 | int foo() { return Test.sa; } 72 | } 73 | 74 | /* Coupling (1) via method return type */ 75 | class Test6 { 76 | Test foo() { return null; } 77 | } 78 | 79 | /* Coupling (1) via method argument type; also public method */ 80 | class Test7 { 81 | public void foo(Test a) {} 82 | } 83 | 84 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | # 2 | # $Id: \\dds\\src\\Research\\ckjm.RCS\\Makefile,v 1.15 2008/04/17 08:44:48 dds Exp $ 3 | # 4 | 5 | VERSION=1.9 6 | TARBALL=ckjm-$(VERSION).tar.gz 7 | ZIPBALL=ckjm-$(VERSION).zip 8 | DISTDIR=ckjm-$(VERSION) 9 | WEBDIR=$(UH)/dds/pubs/web/home/sw/ckjm 10 | SRCFILE=README.txt LICENSE.txt build.xml src/gr/spinellis/ckjm/*.java src/gr/spinellis/ckjm/ant/*.java xsl/*.xsl lib/*.txt 11 | BCEL=bcel-6.0.jar 12 | EGHTML=output_simple.html output_extra.html 13 | ART=smallpic.jpg 14 | 15 | all: antcompile 16 | 17 | antcompile: 18 | ant -Dversion=$(VERSION) -Dbcel=$(BCEL) 19 | ant -Dversion=$(VERSION) -Dbcel=$(BCEL) javadocs 20 | 21 | $(EGHTML): Makefile xsl/ckjm.xsl xsl/ckjm_extra.xsl 22 | ant -Dversion=$(VERSION) -Dbcel=$(BCEL) html 23 | 24 | $(TARBALL): docs Makefile 25 | -cmd /c rd /s/q $(DISTDIR) 26 | mkdir $(DISTDIR) 27 | mkdir $(DISTDIR)/{doc,src,lib,build,xsl} 28 | mkdir -p $(DISTDIR)/src/gr/spinellis/ckjm/ant 29 | tar cf - javadoc contrib | tar -C $(DISTDIR) -xf - 30 | cp $(WEBDIR)/doc/* $(DISTDIR)/doc 31 | cp build/ckjm-$(VERSION).jar $(DISTDIR)/build 32 | cp lib/$(BCEL) $(DISTDIR)/lib 33 | for i in $(SRCFILE) ;\ 34 | do \ 35 | perl -p -e 'BEGIN {binmode(STDOUT);} s/\r//' $$i >$(DISTDIR)/$$i;\ 36 | done 37 | perl -p -e 'BEGIN {binmode(STDOUT);} s/\r//;print q{ } if (/VERSION/); if (/THE END/) { print qq{\n}; last;}' build.xml >$(DISTDIR)/build.xml 38 | tar czvf $(TARBALL) $(DISTDIR) 39 | zip -r $(ZIPBALL) $(DISTDIR) 40 | 41 | docs: 42 | #rm $(WEBDIR)/doc/* 43 | (cd doc && make) 44 | tar cf - javadoc | tar -C $(WEBDIR) -xf - 45 | 46 | web: $(TARBALL) $(EGHTML) 47 | cp $(ART) $(EGHTML) $(TARBALL) $(ZIPBALL) $(WEBDIR) 48 | sed "s/VERSION/$(VERSION)/g" index.html >$(WEBDIR)/index.html 49 | 50 | # A simple regression test 51 | test: antcompile 52 | jar tf test/ckjm-1.8.jar | sed -n '/\.class$$/s/^/test\/ckjm-1.8.jar /p' | java -jar build/ckjm-$(VERSION).jar >test/new.txt 53 | diff test/old.txt test/new.txt && echo OK 54 | -------------------------------------------------------------------------------- /src/gr/spinellis/ckjm/ant/PrintXmlResults.java: -------------------------------------------------------------------------------- 1 | /* 2 | * (C) Copyright 2005 Diomidis Spinellis, Julien Rentrop 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package gr.spinellis.ckjm.ant; 17 | 18 | import gr.spinellis.ckjm.CkjmOutputHandler; 19 | import gr.spinellis.ckjm.ClassMetrics; 20 | 21 | import java.io.PrintStream; 22 | 23 | /** 24 | * XML output formatter 25 | * 26 | * @author Julien Rentrop 27 | */ 28 | public class PrintXmlResults implements CkjmOutputHandler { 29 | private PrintStream p; 30 | 31 | public PrintXmlResults(PrintStream p) { 32 | this.p = p; 33 | } 34 | 35 | public void printHeader() { 36 | p.println(""); 37 | p.println(""); 38 | } 39 | 40 | public void handleClass(String name, ClassMetrics c) { 41 | p.print("\n" + 42 | "" + name + "\n" + 43 | "" + c.getWmc() + "\n" + 44 | "" + c.getDit() + "\n" + 45 | "" + c.getNoc() + "\n" + 46 | "" + c.getCbo() + "\n" + 47 | "" + c.getRfc() + "\n" + 48 | "" + c.getLcom() + "\n" + 49 | "" + c.getCa() + "\n" + 50 | "" + c.getNpm() + "\n" + 51 | "\n"); 52 | } 53 | 54 | public void printFooter () { 55 | p.println(""); 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /doc/detail.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | The original definition of the metrics, and implementation details 4 | of both the program, and the Java language provide some leeway on 5 | how the metrics are measured. 6 | The following list contains the most important decisions. 7 | These are marked in the source code with a comment, 8 | such as the following. 9 | 10 | /* Measuring decision: couple interfaces */ 11 | 12 |
    13 |
  • Interfaces are measured when considering a class's coupling. 14 | Rationale: changes to the interface may well require changes 15 | to the class.
  • 16 |
  • Use of Java SDK classes (java.*, javax.*, and some others) 17 | does not count toward a class's coupling. 18 | Rationale: the Java SDK classes are relatively stable, 19 | in comparison to the rest of the project. 20 | A command line argument switch (-s) is available for including 21 | the Java SDK classes into the calculation.
  • 22 |
  • Calls to JDK methods are included in the RFC calculation. 23 | Rationale: the method calls increase the class's complexity.
  • 24 |
  • The classes used for catching exceptions contribute toward the 25 | class's coupling measurements. 26 | Rationale: at the point where an exception is caught a new object 27 | of the corresponding type is instantiated.
  • 28 |
  • The complexity of each method is considered 1, when calculating WMC. 29 | Rationale: ease of implementation, and compatibility with Chidamber and Kemerer.
  • 30 |
  • LCOM is calculated following the 1994 paper description, and not 31 | by looking at disjoint graph components. 32 | Rationale: ease of implementation, and compatibility with Chidamber and Kemerer.
  • 33 |
  • RFC is calculated up to the first method call level, and not 34 | through the transitive closure of all method calls. 35 | Rationale: ease of implementation, and compatibility with Chidamber and Kemerer.
  • 36 |
  • A class's own methods contribute to its RFC. 37 | Rationale: the original Chidamber and Kemerer article describes RFC as a 38 | union of the set of methods called by the class and the set of methods in 39 | the class. 40 |
  • 41 |
42 |
43 | -------------------------------------------------------------------------------- /contrib/ckjm_ruby-1.0/doc/classes/App.src/M000001.html: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 8 | run (App) 9 | 10 | 11 | 12 | 13 |
# File mk_ckjm_graphs.rb, line 117
14 |   def App.run(argv)
15 |     App.usage unless argv.length == 2
16 |     ckjm_file_name, project_desc = argv
17 |     jm = MetricsUtils::JavaMetrics.new(ckjm_file_name)
18 |     plotter = MetricsUtils::Plotter.instance
19 |     grapher = MetricsUtils::CKJMMetricGrapher.new(ckjm_file_name, project_desc, plotter, jm)
20 |     grapher.plot_metrics
21 |   end
22 | 23 | -------------------------------------------------------------------------------- /doc/oper.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | To run ckjm you must run java with the -jar 4 | flag, providing as its argument the location of the file 5 | ckjm.jar. 6 | Next, you can specify as arguments the Java class files you want 7 | to analyze. 8 |
9 | Example: 10 | 11 | java -jar /usr/local/lib/ckjm-1.5.jar build/classes/gr/spinellis/ckjm/*.class 12 | 13 | (Replace the sequence /usr/local/lib/ckjm-1.5.jar 14 | with the actual path and filename of the ckjm version you are using.) 15 |

16 | The command's output will be a list of class names (prefixed by the 17 | package they are defined in), followed by the corresponding 18 | metrics for that class: WMC, DIT, NOC, CBO, RFC, LCOM, Ce, and NPM. 19 |

20 | gr.spinellis.ckjm.ClassMetricsContainer 3 1 0 3 18 0 2 2
21 | gr.spinellis.ckjm.MethodVisitor 11 1 0 21 40 0 1 8
22 | gr.spinellis.ckjm.CkjmOutputHandler 1 1 0 1 1 0 3 1
23 | gr.spinellis.ckjm.ClassMetrics 24 1 0 0 33 196 6 23
24 | gr.spinellis.ckjm.MetricsFilter 7 1 0 6 30 11 2 5
25 | gr.spinellis.ckjm.ClassVisitor 13 1 0 14 71 34 2 9
26 | gr.spinellis.ckjm.ClassMap 3 1 0 1 21 0 0 2
27 | gr.spinellis.ckjm.PrintPlainResults 2 1 0 2 8 0 1 2
28 | 
29 |

30 | If the classes are located in a jar archive, you can 31 | specify as a single argument the name of the archive, 32 | followed by a space, followed by the name of the class in the archive. 33 | 34 | java -jar /usr/local/lib/ckjm.jar 'ant-jai.jar org/apache/tools/ant/types/optional/image/Text.class' 35 | 36 |

37 | Finally, instead of specifying the classes to be analyszed as the 38 | command's arguments, you pass them (as class files, or as jar file, class 39 | file pairs) on the command's standard input. 40 | The following example will process all class files located in the 41 | build directory. 42 | 43 | find build -name '*.class' -print | java -jar /usr/local/lib/ckjm.jar 44 | 45 |

46 | The program, by default, will not take into account classes that belong 47 | to the Java SDK packages. 48 | The command-line option switch -s, can be used to enable this 49 | processing. 50 | 51 | -------------------------------------------------------------------------------- /src/gr/spinellis/ckjm/ClassMetricsContainer.java: -------------------------------------------------------------------------------- 1 | /* 2 | * (C) Copyright 2005 Diomidis Spinellis 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package gr.spinellis.ckjm; 18 | 19 | import org.apache.bcel.classfile.*; 20 | import java.util.*; 21 | import java.io.*; 22 | 23 | 24 | /** 25 | * A container of class metrics mapping class names to their metrics. 26 | * This class contains the the metrics for all class's during the filter's 27 | * operation. Some metrics need to be updated as the program processes 28 | * other classes, so the class's metrics will be recovered from this 29 | * container to be updated. 30 | * 31 | * @version $Revision: 1.9 $ 32 | * @author Diomidis Spinellis 33 | */ 34 | class ClassMetricsContainer { 35 | 36 | /** The map from class names to the corresponding metrics */ 37 | private HashMap m = new HashMap(); 38 | 39 | /** Return a class's metrics */ 40 | public ClassMetrics getMetrics(String name) { 41 | ClassMetrics cm = m.get(name); 42 | if (cm == null) { 43 | cm = new ClassMetrics(); 44 | m.put(name, cm); 45 | } 46 | return cm; 47 | } 48 | 49 | /** Print the metrics of all the visited classes. */ 50 | public void printMetrics(CkjmOutputHandler handler) { 51 | Set> entries = m.entrySet(); 52 | Iterator> i; 53 | 54 | for (i = entries.iterator(); i.hasNext(); ) { 55 | Map.Entry e = i.next(); 56 | ClassMetrics cm = e.getValue(); 57 | if (cm.isVisited() && (MetricsFilter.includeAll() || cm.isPublic())) 58 | handler.handleClass(e.getKey(), cm); 59 | } 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /doc/intro.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 |

4 | The program ckjm calculates Chidamber and Kemerer object-oriented 5 | metrics by processing the bytecode of compiled Java files. 6 | The program calculates for each class the following six metrics, and displays 7 | them on its standard output, following the class's name: 8 |

9 |
    10 |
  • WMC: Weighted methods per class
  • 11 |
  • DIT: Depth of Inheritance Tree
  • 12 |
  • NOC: Number of Children
  • 13 |
  • CBO: Coupling between object classes
  • 14 |
  • RFC: Response for a Class
  • 15 |
  • LCOM: Lack of cohesion in methods
  • 16 |
  • Ca: Afferent coupling (not a C&K metric)
  • 17 |
  • NPM: Number of Public Methods for a class (not a C&K metric)
  • 18 |
19 |

20 | I wrote this program out of frustration over the 21 | lack 22 | of reliable programs to calculate the 23 | Chidamber and Kemerer object-oriented metrics. 24 | The programs I found on the web were either 25 | incomplete (they calculated only some of the metrics), 26 | or unreliable (they calculated results that were obviously wrong), 27 | or extremely inefficient (they required GBs of RAM and hours of processing). 28 | Ckjm is mean and lean, following the Unix tradition of doing 29 | one thing well. 30 | It will not automatically recurse directories looking for the files 31 | you want measured, 32 | it does not offer a GUI and fancy diagrams (or even an XML output facility), 33 | and it calculates only few metrics other than the six ones specified 34 | by Chidamber and Kemerer. 35 | However, it does this job thoroughly, and efficiently: 36 | on a 1.6GHz Pentium-M machine version 1.1 of the tool 37 | processed the 33MB of the Eclipse 3.0 38 | jar files (19717 classes) in 95 seconds. 39 |

40 |

41 | To run the program you simply specify the class files 42 | (or pairs of jar/class files) 43 | on its command line or standard input. 44 | The program will produce on its standard output a line for each class 45 | containing the complete name of the class and the values of the corresponding 46 | class metrics. 47 | This operation model allows the tool to be easilly extended using textual 48 | pre and post processors. 49 |

50 |
51 | -------------------------------------------------------------------------------- /doc/insel.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | Using the Unix find command to select the class files 4 | to process, provides infinite flexibility. 5 |
    6 |
  • 7 | You can specify a range of modification times for the files. 8 | As an example, the following command will print the metrics of 9 | the class files modified during the last week. 10 | 11 | find build -name '*.class' -mtime -7 -print | java -jar /usr/local/lib/ckjm.jar 12 | 13 |
  • 14 |
  • 15 | You can filter out specific patterns, either with the GNU 16 | find's regular expression options, or by piping its results 17 | through grep. 18 | As an example, the following command will not print metrics for 19 | internal classes (their name contains a $ character). 20 | 21 | find build -name '*.class' | fgrep -v '$' | java -jar /usr/local/lib/ckjm.jar 22 | 23 |
  • 24 |
  • 25 | You process contents from several directories. 26 | As an example, the following command will process the class files 27 | located in the build and lib directories. 28 | 29 | find build lib -name '*.class' -print | java -jar /usr/local/lib/ckjm.jar 30 | 31 |
  • 32 |
  • 33 | You generate the list of class files, by processing the list of 34 | contents of a jar file. 35 | The following example will calculate the metrics for all class files 36 | located in the file ant.jar (the sed step prints only the lines 37 | ending in .class, replacing the beginning of the line with the name of the 38 | jar file, ant.jar. 39 | . 40 | 41 | jar tf ant.jar | 42 | sed -n '/\.class$/s/^/ant.jar /p' | 43 | java -jar /usr/local/lib/ckjm.jar 44 | 45 |
  • 46 |
  • You can also combine the above patterns (and more) 47 | into more sophisticated file location and selection options. 48 | The following example, will process the classes of 49 | all jar files located in the lib directory. 50 | 51 | for i in lib/*.jar 52 | do 53 | jar tf $i | 54 | sed -n "/\.class$/s,^,$i ,p" 55 | done | 56 | java -jar /usr/java/ckjm-1.3/build/ckjm-1.3.jar 57 | 58 | (Replace the sequence /usr/java/ckjm-1.3/build/ckjm-1.3.jar 59 | with the actual path and filename of the ckjm version you are using.) 60 |
  • 61 |
62 |
63 | -------------------------------------------------------------------------------- /xsl/ckjm.xsl: -------------------------------------------------------------------------------- 1 | 2 | 18 | 19 | 21 | 22 | 23 | 24 | 25 | CKJM Chidamber and Kemerer Java Metrics 26 | 27 | 61 | 62 | 63 |

CKJM Chidamber and Kemerer Java Metrics

64 |

Designed for use with CKJM and Ant.

65 | 66 |
67 | 68 |

Summary

69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 |
84 | 85 | 86 | 87 |
88 | 89 |
90 | -------------------------------------------------------------------------------- /contrib/ckjm_ruby-1.0/doc/classes/MetricsUtils/JavaMetrics.src/M000010.html: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 8 | metrics (MetricsUtils::JavaMetrics) 9 | 10 | 11 | 12 | 13 |
# File metrics_utils.rb, line 124
14 |     def metrics
15 |       @distribution.clear
16 |       File.foreach(@ckjm_file_name) do |line|
17 |         line.chomp!
18 |         if line =~ /^\S+(\s+\d+){8}\s*$/
19 |           class_name, *metrics_vals = line.split(/\s+/)
20 |           METRICS.each_index do |i|
21 |             value = metrics_vals[i].to_i
22 |             (@distribution[METRICS[i][0]] ||= Hash.new(0))[value] += 1
23 |           end
24 |         end
25 |       end
26 |       @distribution
27 |     end
28 | 29 | -------------------------------------------------------------------------------- /contrib/ckjm_ruby-1.0/doc/files/metrics_utils_rb.html: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 8 | File: metrics_utils.rb 9 | 10 | 11 | 12 | 43 | 44 | 45 | 46 | 47 | 48 | 49 |
50 |

metrics_utils.rb

51 | 52 | 53 | 54 | 56 | 57 | 58 | 59 | 60 | 61 |
Path:metrics_utils.rb 55 |
Last Update:Thu Feb 15 01:26:23 -0500 2007
62 |
63 | 64 | 65 |
66 | 67 | 68 | 69 |
70 | 71 |
72 |

73 | This module contains utilities to plot Chidamber-Kemerer metrics. 74 |

75 | 76 |
77 | 78 |
79 |

Required files

80 | 81 |
82 | singleton   83 |
84 |
85 | 86 |
87 | 88 | 89 |
90 | 91 | 92 | 93 | 94 |
95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 |
107 | 108 | 109 |
110 |

[Validate]

111 |
112 | 113 | 114 | -------------------------------------------------------------------------------- /doc/anttask.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | First define the ant task in your build.xml file. 4 | The ckjm jar file should be in the classpath. 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | Now you can make use of the ckjm task. 14 | The attributes of the ckjm task are the following: 15 | 16 |
17 |
format
'plain' or 'xml'. Default is 'plain'
18 |
outputfile
Required. Output will be written to outputfile.
19 |
classdir
Required. Base directory which contains the class files.
20 |
21 | 22 | The ckjm 23 | task supports the nested elements <include> and <exclude>, 24 | which can be used to select the class files and the nested element 25 | <extdirs>, which is used to specify other class files participating in the 26 | inheritance hierarchy. 27 | The elements support 28 | path-like structures. 29 | 30 | Example usage: 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | You can use an XSL stylesheet to generate an HTML report from the XML 40 | output file. 41 | 42 | Example: 43 | 44 | " ) 40 | 41 | // ]]> 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 |
50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 63 | 64 | 65 |
ModuleMetricsUtils
In: 58 | 59 | metrics_utils.rb 60 | 61 |
62 |
66 |
67 | 68 | 69 |
70 | 71 | 72 | 73 |
74 | 75 |
76 |

77 | This module contains utilities to plot Chidamber-Kemerer metrics. 78 |

79 | 80 |
81 | 82 | 83 |
84 | 85 | 86 |
87 | 88 | 89 | 90 | 91 |
92 | 93 |
94 |

Classes and Modules

95 | 96 | Class MetricsUtils::CKJMMetricGrapher
97 | Class MetricsUtils::JavaMetrics
98 | Class MetricsUtils::Plotter
99 | 100 |
101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 |
112 | 113 | 114 |
115 |

[Validate]

116 |
117 | 118 | 119 | -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 4.0.0 6 | 7 | gr.spinellis 8 | ckjm 9 | 1.0-SNAPSHOT 10 | 11 | ckjm 12 | https://www.spinellis.gr/sw/ckjm/ 13 | 14 | 15 | UTF-8 16 | 1.7 17 | 1.7 18 | 19 | 20 | 21 | 22 | 23 | 24 | org.apache.ant 25 | ant 26 | 1.10.11 27 | 28 | 29 | 30 | 31 | org.apache.bcel 32 | bcel 33 | 6.6.0 34 | 35 | 36 | 37 | junit 38 | junit 39 | 4.13.1 40 | test 41 | 42 | 43 | 44 | 45 | tests 46 | src 47 | 48 | 49 | 50 | 51 | maven-clean-plugin 52 | 3.1.0 53 | 54 | 55 | 56 | maven-resources-plugin 57 | 3.0.2 58 | 59 | 60 | maven-compiler-plugin 61 | 3.8.0 62 | 63 | 64 | maven-surefire-plugin 65 | 2.22.1 66 | 67 | 68 | maven-jar-plugin 69 | 3.0.2 70 | 71 | 72 | maven-install-plugin 73 | 2.5.2 74 | 75 | 76 | maven-deploy-plugin 77 | 2.8.2 78 | 79 | 80 | 81 | maven-site-plugin 82 | 3.7.1 83 | 84 | 85 | maven-project-info-reports-plugin 86 | 3.0.0 87 | 88 | 89 | 90 | 91 | 92 | -------------------------------------------------------------------------------- /doc/outfmt.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | The output of ckjm is textual: 4 | one line for each class, each line contains 8 space-separated fields: 5 | the classname and the 7 metrics. 6 | If your application requires something more fancy, 7 | it is easy to post-process the ckjm output to 8 | obtain it. 9 | For example, the following sed script will generate 10 | XML output. 11 | 12 | #!/bin/sed -f 13 | 1i\ 14 | \ 15 | 16 | s/^// 17 | s/ /<\/classname>/ 18 | s/ /<\/WMC>/ 19 | s/ /<\/DIT>/ 20 | s/ /<\/NOC>/ 21 | s/ /<\/CBO>/ 22 | s/ /<\/RFC>/ 23 | s/ /<\/LCOM>/ 24 | s/ /<\/Ca>/ 25 | s/$/<\/NPM><\/metric>/ 26 | $a\ 27 | 28 | 29 | If you name the script ckjm2xml and make it executable, 30 | you can generate XML output and save it into a file as follows. 31 | 32 | java -jar /usr/local/lib/ckjm.jar *.class | ckjm2xml >metrics.xml 33 | 34 | (Replace the sequence /usr/local/lib/ckjm.jar 35 | with the actual path and filename of the ckjm version you are using.) 36 |
37 | Here is an example of the output. 38 | 41 | 42 | 43 | 44 | gr.spinellis.ckjm.ClassMetricsContainer310318022 45 | gr.spinellis.ckjm.MethodVisitor11102140018 46 | gr.spinellis.ckjm.CkjmOutputHandler11011031 47 | gr.spinellis.ckjm.ClassMetrics2410033196623 48 | gr.spinellis.ckjm.MetricsFilter7106301125 49 | gr.spinellis.ckjm.ClassVisitor131014713429 50 | gr.spinellis.ckjm.ClassMap310121002 51 | gr.spinellis.ckjm.PrintPlainResults21028012 52 | 53 | 54 |

55 | To copy the ckjm's output to the Microsoft Windows clipboard 56 | to later paste the results into an MS-Word table, simply 57 | pipe the output of ckjm to the winclip command of the 58 | Outwit tool suite. 59 |

60 | You can also plot the results in various formats by using 61 | gnuplot. 62 | Here is a diagram depicting the distribution of the CBO metric within 63 | the classes of Eclipse.
64 | the distribution of the CBO metric within the classes of Eclipse 65 | 66 | -------------------------------------------------------------------------------- /doc/metric.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | The metrics ckjm will calculate and display for 4 | each class are the following. 5 |

6 |
WMC - Weighted methods per class
7 | A class's weighted methods per class WMC 8 | metric is simply the sum of the complexities of its methods. 9 | As a measure of complexity we can use the cyclomatic complexity, 10 | or we can abritrarily assign a complexity value of 1 to each method. 11 | The ckjm program assigns a complexity value of 1 to each method, 12 | and therefore the value of the WMC is equal to the number of methods 13 | in the class. 14 |
DIT - Depth of Inheritance Tree
15 | The depth of inheritance tree (DIT) metric provides 16 | for each class a measure of the inheritance levels from the object 17 | hierarchy top. 18 | In Java where all classes inherit Object the minimum value 19 | of DIT is 1. 20 |
NOC - Number of Children
21 | A class's number of children (NOC) 22 | metric simply 23 | measures the number of immediate descendants of the class. 24 |
CBO - Coupling between object classes
25 | The coupling between object classes (CBO) 26 | metric represents the number of classes coupled to a given 27 | class (efferent couplings, Ce). 28 | This coupling can occur through method calls, 29 | field accesses, inheritance, arguments, return types, 30 | and exceptions. 31 |
RFC - Response for a Class
32 | The metric called the response for a class (RFC) 33 | measures the number of different 34 | methods that can be executed when an object of that 35 | class receives a message (when a method is invoked 36 | for that object). 37 | Ideally, we would want to find for each method 38 | of the class, the methods that class will call, 39 | and repeat this for each called method, 40 | calculating what is called the transitive closure 41 | of the method's call graph. 42 | This process can however be both expensive and quite 43 | inaccurate. 44 | In ckjm, we calculate a rough 45 | approximation to the response set 46 | by simply inspecting method calls within the class's 47 | method bodies. 48 | This simplification was also used in the 1994 Chidamber and Kemerer 49 | description of the metrics. 50 |
LCOM - Lack of cohesion in methods
51 | A class's lack of cohesion in methods (LCOM) 52 | metric counts the sets of methods in a class that are not related 53 | through the sharing of some of the class's fields. 54 | The original definition of this metric 55 | (which is the one used in ckjm) 56 | considers all pairs of a class's methods. 57 | In some of these pairs both methods access at 58 | least one common field of the class, while in 59 | other pairs the two methods to not share any 60 | common field accesses. 61 | The lack of cohesion in methods is then calculated 62 | by subtracting from the number of method pairs 63 | that don't share a field access the number of 64 | method pairs that do. 65 | Note that subsequent definitions 66 | of this metric used as a measurement basis the number 67 | of disjoint graph components of the class's methods. 68 | Others modified the definition of connectedness to 69 | include calls between the methods of the class. 70 | The program ckjm follows the original (1994) definition 71 | by Chidamber and Kemerer. 72 |
Ca - Afferent couplings
73 | A class's afferent couplings is a measure of how many other classes 74 | use the specific class. 75 | Ca is calculated using the same definition as that used for 76 | calculating CBO (Ce). 77 |
NPM - Number of Public Methods
78 | The NPM metric simply counts all the methods in a class that 79 | are declared as public. 80 | It can be used to measure the size of an API provided by a package. 81 |
82 |
83 |
84 | -------------------------------------------------------------------------------- /doc/faq.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 8 | 9 |

Contents

10 | 19 | 20 |

The metrics calculated by the program do not agree with those I calculate by hand. How come?

21 | The ckjm program calculates the metrics from the code 22 | appearing in the compiled bytecode files. 23 | The Java compiler optimizes away some elements of the code 24 | (for example static final fields, and these do not 25 | take part in the calculations. 26 | You may want to consult the disassembled code 27 | (using a command like javap -c -private to see 28 | what elements ckjm takes into account. 29 | 30 |

How can I process class files located in a jar file?

31 | See the documentation section titled 32 | Using Pipelines to Select Classes. 33 | 34 |

How can I run the tool in a JDK 1.4 environment?

35 | You can use the open source tool retroweaver 36 | to create a backwards-compatible jar file. 37 | (Suggested by Paul King). 38 | 39 |

I'm getting a ClassNotFoundException. How can I fix it?

40 | If you are getting messages like the one below, it means that ckjm 41 | can't locate the code for the corresponding classes, in order to properly 42 | calculate the depth of the inheritance tree (DIT) metric. 43 | 44 | java.lang.ClassNotFoundException: Exception while looking for class 45 | javax.servlet.http.HttpServlet: java.io.IOException: 46 | Couldn't find: javax.servlet.http.HttpServlet.class 47 | 48 | To solve this problem you must explicitly setup the 49 | java.ext.dirs property pointing to a directory containing 50 | the jar files where ckjm can locate those classes. 51 | Example: 52 | 53 | java -Djava.ext.dirs=lib -jar ckjm-1.8.jar *.class 54 | 55 |

I'm using ckjm in my research. How shall I cite it?

56 | Please cite the following article, which describes ckjm 57 | and the rationale of its design. 58 |
59 |

60 | Diomidis Spinellis. 61 | Tool writing: A forgotten art?. 62 | IEEE Software, 22(4):9-11, July/August 2005. 63 | (doi:10.1109/MS.2005.111) 64 |

65 |
66 |

How can I deal with directory names containing spaces?

67 | It's best to avoid putting spaces in file and directory names, because 68 | these can confuse many Unix-related tools that use spaces to separate 69 | arguments. 70 | If you can't avoid them, here are two tricks for getting around the problem. 71 | In a Windows environment use dir /x on the command line to 72 | obtain the short (8.3) name of the corresponding directory. 73 | On a Unix machine create a symbolic from the directory containing spaces 74 | to a directory without spaces, and use that second name: 75 | 76 | ln -s '/path/to/directory with spaces/' /tmp/shortname 77 | 78 |
79 | -------------------------------------------------------------------------------- /contrib/ckjm_ruby-1.0/doc/classes/App.html: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 8 | Class: App 9 | 10 | 11 | 12 | 43 | 44 | 45 | 46 | 47 | 48 | 49 |
50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 63 | 64 | 65 | 66 | 67 | 70 | 71 |
ClassApp
In: 58 | 59 | mk_ckjm_graphs.rb 60 | 61 |
62 |
Parent: 68 | Object 69 |
72 |
73 | 74 | 75 |
76 | 77 | 78 | 79 |
80 | 81 |
82 |

83 | This is the top-level application that ties together all the other elements 84 | to plot the ckjm data. 85 |

86 | 87 |
88 | 89 | 90 |
91 | 92 |
93 |

Methods

94 | 95 |
96 | run   97 |
98 |
99 | 100 |
101 | 102 | 103 | 104 | 105 |
106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 |
116 |

Public Class methods

117 | 118 |
119 | 120 | 121 | 127 | 128 |
129 |

130 | Runs the application. 131 |

132 | 133 | 136 |
argv:array containing [ckjm_file_name, project_desc]. 134 | 135 |
137 |
138 |
139 | 140 | 141 |
142 | 143 | 144 |
145 | 146 | 147 |
148 |

[Validate]

149 |
150 | 151 | 152 | -------------------------------------------------------------------------------- /src/gr/spinellis/ckjm/MethodVisitor.java: -------------------------------------------------------------------------------- 1 | /* 2 | * (C) Copyright 2005 Diomidis Spinellis 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package gr.spinellis.ckjm; 18 | 19 | import org.apache.bcel.generic.*; 20 | import org.apache.bcel.Constants; 21 | import org.apache.bcel.util.*; 22 | import java.util.*; 23 | 24 | /** 25 | * Visit a method calculating the class's Chidamber-Kemerer metrics. 26 | * A helper class for ClassVisitor. 27 | * 28 | * @see ClassVisitor 29 | * @version $Revision: 1.8 $ 30 | * @author Diomidis Spinellis 31 | */ 32 | class MethodVisitor extends EmptyVisitor { 33 | /** Method generation template. */ 34 | private MethodGen mg; 35 | /* The class's constant pool. */ 36 | private ConstantPoolGen cp; 37 | /** The visitor of the class the method visitor is in. */ 38 | private ClassVisitor cv; 39 | /** The metrics of the class the method visitor is in. */ 40 | private ClassMetrics cm; 41 | 42 | /** Constructor. */ 43 | MethodVisitor(MethodGen m, ClassVisitor c) { 44 | mg = m; 45 | cv = c; 46 | cp = mg.getConstantPool(); 47 | cm = cv.getMetrics(); 48 | } 49 | 50 | /** Start the method's visit. */ 51 | public void start() { 52 | if (!mg.isAbstract() && !mg.isNative()) { 53 | for (InstructionHandle ih = mg.getInstructionList().getStart(); 54 | ih != null; ih = ih.getNext()) { 55 | Instruction i = ih.getInstruction(); 56 | 57 | if(!visitInstruction(i)) 58 | i.accept(this); 59 | } 60 | updateExceptionHandlers(); 61 | } 62 | } 63 | 64 | /** Visit a single instruction. */ 65 | private boolean visitInstruction(Instruction i) { 66 | short opcode = i.getOpcode(); 67 | 68 | return ((InstructionConstants.INSTRUCTIONS[opcode] != null) && 69 | !(i instanceof ConstantPushInstruction) && 70 | !(i instanceof ReturnInstruction)); 71 | } 72 | 73 | /** Local variable use. */ 74 | public void visitLocalVariableInstruction(LocalVariableInstruction i) { 75 | if(i.getOpcode() != Constants.IINC) 76 | cv.registerCoupling(i.getType(cp)); 77 | } 78 | 79 | /** Array use. */ 80 | public void visitArrayInstruction(ArrayInstruction i) { 81 | cv.registerCoupling(i.getType(cp)); 82 | } 83 | 84 | /** Field access. */ 85 | public void visitFieldInstruction(FieldInstruction i) { 86 | cv.registerFieldAccess(i.getClassName(cp), i.getFieldName(cp)); 87 | cv.registerCoupling(i.getFieldType(cp)); 88 | } 89 | 90 | /** Method invocation. */ 91 | public void visitInvokeInstruction(InvokeInstruction i) { 92 | Type[] argTypes = i.getArgumentTypes(cp); 93 | for (int j = 0; j < argTypes.length; j++) 94 | cv.registerCoupling(argTypes[j]); 95 | cv.registerCoupling(i.getReturnType(cp)); 96 | /* Measuring decision: measure overloaded methods separately */ 97 | cv.registerMethodInvocation(i.getClassName(cp), i.getMethodName(cp), argTypes); 98 | } 99 | 100 | /** Visit an instanceof instruction. */ 101 | public void visitINSTANCEOF(INSTANCEOF i) { 102 | cv.registerCoupling(i.getType(cp)); 103 | } 104 | 105 | /** Visit checklast instruction. */ 106 | public void visitCHECKCAST(CHECKCAST i) { 107 | cv.registerCoupling(i.getType(cp)); 108 | } 109 | 110 | /** Visit return instruction. */ 111 | public void visitReturnInstruction(ReturnInstruction i) { 112 | cv.registerCoupling(i.getType(cp)); 113 | } 114 | 115 | /** Visit the method's exception handlers. */ 116 | private void updateExceptionHandlers() { 117 | CodeExceptionGen[] handlers = mg.getExceptionHandlers(); 118 | 119 | /* Measuring decision: couple exceptions */ 120 | for(int i=0; i < handlers.length; i++) { 121 | Type t = handlers[i].getCatchType(); 122 | if (t != null) 123 | cv.registerCoupling(t); 124 | } 125 | } 126 | } 127 | -------------------------------------------------------------------------------- /src/gr/spinellis/ckjm/MetricsFilter.java: -------------------------------------------------------------------------------- 1 | /* 2 | * (C) Copyright 2005 Diomidis Spinellis 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package gr.spinellis.ckjm; 18 | 19 | import org.apache.bcel.classfile.*; 20 | import org.apache.bcel.generic.*; 21 | import org.apache.bcel.Repository; 22 | import org.apache.bcel.Constants; 23 | import org.apache.bcel.util.*; 24 | import java.io.*; 25 | import java.util.*; 26 | 27 | /** 28 | * Convert a list of classes into their metrics. 29 | * Process standard input lines or command line arguments 30 | * containing a class file name or a jar file name, 31 | * followed by a space and a class file name. 32 | * Display on the standard output the name of each class, followed by its 33 | * six Chidamber Kemerer metrics: 34 | * WMC, DIT, NOC, CBO, RFC, LCOM 35 | * 36 | * @see ClassMetrics 37 | * @version $Revision: 1.9 $ 38 | * @author Diomidis Spinellis 39 | */ 40 | public class MetricsFilter { 41 | /** True if the measurements should include calls to the Java JDK into account */ 42 | private static boolean includeJdk = false; 43 | 44 | /** True if the reports should only include public classes */ 45 | private static boolean onlyPublic = false; 46 | 47 | /** Return true if the measurements should include calls to the Java JDK into account */ 48 | public static boolean isJdkIncluded() { return includeJdk; } 49 | /** Return true if the measurements should include all classes */ 50 | public static boolean includeAll() { return !onlyPublic; } 51 | 52 | /** 53 | * Load and parse the specified class. 54 | * The class specification can be either a class file name, or 55 | * a jarfile, followed by space, followed by a class file name. 56 | */ 57 | static void processClass(ClassMetricsContainer cm, String clspec) { 58 | int spc; 59 | JavaClass jc = null; 60 | 61 | if ((spc = clspec.indexOf(' ')) != -1) { 62 | String jar = clspec.substring(0, spc); 63 | clspec = clspec.substring(spc + 1); 64 | try { 65 | jc = new ClassParser(jar, clspec).parse(); 66 | } catch (IOException e) { 67 | System.err.println("Error loading " + clspec + " from " + jar + ": " + e); 68 | } 69 | } else { 70 | try { 71 | jc = new ClassParser(clspec).parse(); 72 | } catch (IOException e) { 73 | System.err.println("Error loading " + clspec + ": " + e); 74 | } 75 | } 76 | if (jc != null) { 77 | ClassVisitor visitor = new ClassVisitor(jc, cm); 78 | visitor.start(); 79 | visitor.end(); 80 | } 81 | } 82 | 83 | /** 84 | * The interface for other Java based applications. 85 | * Implement the outputhandler to catch the results 86 | * 87 | * @param files Class files to be analyzed 88 | * @param outputHandler An implementation of the CkjmOutputHandler interface 89 | */ 90 | public static void runMetrics(String[] files, CkjmOutputHandler outputHandler) { 91 | ClassMetricsContainer cm = new ClassMetricsContainer(); 92 | 93 | for (int i = 0; i < files.length; i++) 94 | processClass(cm, files[i]); 95 | cm.printMetrics(outputHandler); 96 | } 97 | 98 | /** The filter's main body. 99 | * Process command line arguments and the standard input. 100 | */ 101 | public static void main(String[] argv) { 102 | int argp = 0; 103 | 104 | if (argv.length > argp && argv[argp].equals("-s")) { 105 | includeJdk = true; 106 | argp++; 107 | } 108 | if (argv.length > argp && argv[argp].equals("-p")) { 109 | onlyPublic = true; 110 | argp++; 111 | } 112 | ClassMetricsContainer cm = new ClassMetricsContainer(); 113 | 114 | if (argv.length == argp) { 115 | BufferedReader in = new BufferedReader(new InputStreamReader(System.in)); 116 | try { 117 | String s; 118 | while ((s = in.readLine()) != null) 119 | processClass(cm, s); 120 | } catch (Exception e) { 121 | System.err.println("Error reading line: " + e); 122 | System.exit(1); 123 | } 124 | } 125 | 126 | for (int i = argp; i < argv.length; i++) 127 | processClass(cm, argv[i]); 128 | 129 | CkjmOutputHandler handler = new PrintPlainResults(System.out); 130 | cm.printMetrics(handler); 131 | } 132 | } 133 | -------------------------------------------------------------------------------- /src/gr/spinellis/ckjm/ClassMetrics.java: -------------------------------------------------------------------------------- 1 | /* 2 | * (C) Copyright 2005 Diomidis Spinellis 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package gr.spinellis.ckjm; 18 | 19 | import java.util.HashSet; 20 | 21 | /** 22 | * Store details needed for calculating a class's Chidamber-Kemerer metrics. 23 | * Most fields in this class are set by ClassVisitor. 24 | * This class also encapsulates some policy decision regarding metrics 25 | * measurement. 26 | * 27 | * @see ClassVisitor 28 | * @version $Revision: 1.12 $ 29 | * @author Diomidis Spinellis 30 | */ 31 | public class ClassMetrics { 32 | /** Weighted methods per class */ 33 | private int wmc; 34 | /** Number of children */ 35 | private int noc; 36 | /** Response for a Class */ 37 | private int rfc; 38 | /** Coupling between object classes */ 39 | private int cbo; 40 | /** Depth of inheritence tree */ 41 | private int dit; 42 | /** Lack of cohesion in methods */ 43 | private int lcom; 44 | /** Number of public methods */ 45 | private int npm; 46 | /** True if the class has been visited by the metrics gatherer */ 47 | private boolean visited; 48 | /** True if the class is public */ 49 | private boolean isPublicClass; 50 | /** Coupled classes: classes that use this class */ 51 | private HashSet afferentCoupledClasses; 52 | 53 | /** Default constructor. */ 54 | ClassMetrics() { 55 | wmc = 0; 56 | noc = 0; 57 | cbo = 0; 58 | npm = 0; 59 | visited = false; 60 | afferentCoupledClasses = new HashSet(); 61 | } 62 | 63 | /** Increment the weighted methods count */ 64 | public void incWmc() { wmc++; } 65 | /** Return the weighted methods per class metric */ 66 | public int getWmc() { return wmc; } 67 | 68 | /** Increment the number of children */ 69 | public void incNoc() { noc++; } 70 | /** Return the number of children */ 71 | public int getNoc() { return noc; } 72 | 73 | /** Increment the Response for a Class */ 74 | public void setRfc(int r) { rfc = r; } 75 | /** Return the Response for a Class */ 76 | public int getRfc() { return rfc; } 77 | 78 | /** Set the depth of inheritence tree metric */ 79 | public void setDit(int d) { dit = d; } 80 | /** Return the depth of the class's inheritance tree */ 81 | public int getDit() { return dit; } 82 | 83 | /** Set the coupling between object classes metric */ 84 | public void setCbo(int c) { cbo = c; } 85 | /** Return the coupling between object classes metric */ 86 | public int getCbo() { return cbo; } 87 | 88 | /** Return the class's lack of cohesion in methods metric */ 89 | public int getLcom() { return lcom; } 90 | /** Set the class's lack of cohesion in methods metric */ 91 | public void setLcom(int l) { lcom = l; } 92 | 93 | /** Return the class's afferent couplings metric */ 94 | public int getCa() { return afferentCoupledClasses.size(); } 95 | /** Add a class to the set of classes that depend on this class */ 96 | public void addAfferentCoupling(String name) { afferentCoupledClasses.add(name); } 97 | 98 | /** Increment the number of public methods count */ 99 | public void incNpm() { npm++; } 100 | /** Return the number of public methods metric */ 101 | public int getNpm() { return npm; } 102 | 103 | /** Return true if the class is public */ 104 | public boolean isPublic() { return isPublicClass; } 105 | /** Call to set the class as public */ 106 | public void setPublic() { isPublicClass = true; } 107 | 108 | /** Return true if the class name is part of the Java SDK */ 109 | public static boolean isJdkClass(String s) { 110 | return (s.startsWith("java.") || 111 | s.startsWith("javax.") || 112 | s.startsWith("org.omg.") || 113 | s.startsWith("org.w3c.dom.") || 114 | s.startsWith("org.xml.sax.")); 115 | } 116 | 117 | /** Return the 6 CK metrics plus Ce as a space-separated string */ 118 | public String toString() { 119 | return ( 120 | wmc + 121 | " " + getDit() + 122 | " " + noc + 123 | " " + cbo + 124 | " " + rfc + 125 | " " + lcom + 126 | " " + getCa()+ 127 | " " + npm); 128 | } 129 | 130 | /** Mark the instance as visited by the metrics analyzer */ 131 | public void setVisited() { visited = true; } 132 | /** 133 | * Return true if the class has been visited by the metrics analyzer. 134 | * Classes may appear in the collection as a result of some kind 135 | * of coupling. However, unless they are visited and analyzed, 136 | * we do not want them to appear in the output results. 137 | */ 138 | public boolean isVisited() { return visited; } 139 | } 140 | -------------------------------------------------------------------------------- /contrib/ckjm_ruby-1.0/doc/rdoc-style.css: -------------------------------------------------------------------------------- 1 | 2 | body { 3 | font-family: Verdana,Arial,Helvetica,sans-serif; 4 | font-size: 90%; 5 | margin: 0; 6 | margin-left: 40px; 7 | padding: 0; 8 | background: white; 9 | } 10 | 11 | h1,h2,h3,h4 { margin: 0; color: #efefef; background: transparent; } 12 | h1 { font-size: 150%; } 13 | h2,h3,h4 { margin-top: 1em; } 14 | 15 | a { background: #eef; color: #039; text-decoration: none; } 16 | a:hover { background: #039; color: #eef; } 17 | 18 | /* Override the base stylesheet's Anchor inside a table cell */ 19 | td > a { 20 | background: transparent; 21 | color: #039; 22 | text-decoration: none; 23 | } 24 | 25 | /* and inside a section title */ 26 | .section-title > a { 27 | background: transparent; 28 | color: #eee; 29 | text-decoration: none; 30 | } 31 | 32 | /* === Structural elements =================================== */ 33 | 34 | div#index { 35 | margin: 0; 36 | margin-left: -40px; 37 | padding: 0; 38 | font-size: 90%; 39 | } 40 | 41 | 42 | div#index a { 43 | margin-left: 0.7em; 44 | } 45 | 46 | div#index .section-bar { 47 | margin-left: 0px; 48 | padding-left: 0.7em; 49 | background: #ccc; 50 | font-size: small; 51 | } 52 | 53 | 54 | div#classHeader, div#fileHeader { 55 | width: auto; 56 | color: white; 57 | padding: 0.5em 1.5em 0.5em 1.5em; 58 | margin: 0; 59 | margin-left: -40px; 60 | border-bottom: 3px solid #006; 61 | } 62 | 63 | div#classHeader a, div#fileHeader a { 64 | background: inherit; 65 | color: white; 66 | } 67 | 68 | div#classHeader td, div#fileHeader td { 69 | background: inherit; 70 | color: white; 71 | } 72 | 73 | 74 | div#fileHeader { 75 | background: #057; 76 | } 77 | 78 | div#classHeader { 79 | background: #048; 80 | } 81 | 82 | 83 | .class-name-in-header { 84 | font-size: 180%; 85 | font-weight: bold; 86 | } 87 | 88 | 89 | div#bodyContent { 90 | padding: 0 1.5em 0 1.5em; 91 | } 92 | 93 | div#description { 94 | padding: 0.5em 1.5em; 95 | background: #efefef; 96 | border: 1px dotted #999; 97 | } 98 | 99 | div#description h1,h2,h3,h4,h5,h6 { 100 | color: #125;; 101 | background: transparent; 102 | } 103 | 104 | div#validator-badges { 105 | text-align: center; 106 | } 107 | div#validator-badges img { border: 0; } 108 | 109 | div#copyright { 110 | color: #333; 111 | background: #efefef; 112 | font: 0.75em sans-serif; 113 | margin-top: 5em; 114 | margin-bottom: 0; 115 | padding: 0.5em 2em; 116 | } 117 | 118 | 119 | /* === Classes =================================== */ 120 | 121 | table.header-table { 122 | color: white; 123 | font-size: small; 124 | } 125 | 126 | .type-note { 127 | font-size: small; 128 | color: #DEDEDE; 129 | } 130 | 131 | .xxsection-bar { 132 | background: #eee; 133 | color: #333; 134 | padding: 3px; 135 | } 136 | 137 | .section-bar { 138 | color: #333; 139 | border-bottom: 1px solid #999; 140 | margin-left: -20px; 141 | } 142 | 143 | 144 | .section-title { 145 | background: #79a; 146 | color: #eee; 147 | padding: 3px; 148 | margin-top: 2em; 149 | margin-left: -30px; 150 | border: 1px solid #999; 151 | } 152 | 153 | .top-aligned-row { vertical-align: top } 154 | .bottom-aligned-row { vertical-align: bottom } 155 | 156 | /* --- Context section classes ----------------------- */ 157 | 158 | .context-row { } 159 | .context-item-name { font-family: monospace; font-weight: bold; color: black; } 160 | .context-item-value { font-size: small; color: #448; } 161 | .context-item-desc { color: #333; padding-left: 2em; } 162 | 163 | /* --- Method classes -------------------------- */ 164 | .method-detail { 165 | background: #efefef; 166 | padding: 0; 167 | margin-top: 0.5em; 168 | margin-bottom: 1em; 169 | border: 1px dotted #ccc; 170 | } 171 | .method-heading { 172 | color: black; 173 | background: #ccc; 174 | border-bottom: 1px solid #666; 175 | padding: 0.2em 0.5em 0 0.5em; 176 | } 177 | .method-signature { color: black; background: inherit; } 178 | .method-name { font-weight: bold; } 179 | .method-args { font-style: italic; } 180 | .method-description { padding: 0 0.5em 0 0.5em; } 181 | 182 | /* --- Source code sections -------------------- */ 183 | 184 | a.source-toggle { font-size: 90%; } 185 | div.method-source-code { 186 | background: #262626; 187 | color: #ffdead; 188 | margin: 1em; 189 | padding: 0.5em; 190 | border: 1px dashed #999; 191 | overflow: hidden; 192 | } 193 | 194 | div.method-source-code pre { color: #ffdead; overflow: hidden; } 195 | 196 | /* --- Ruby keyword styles --------------------- */ 197 | 198 | .standalone-code { background: #221111; color: #ffdead; overflow: hidden; } 199 | 200 | .ruby-constant { color: #7fffd4; background: transparent; } 201 | .ruby-keyword { color: #00ffff; background: transparent; } 202 | .ruby-ivar { color: #eedd82; background: transparent; } 203 | .ruby-operator { color: #00ffee; background: transparent; } 204 | .ruby-identifier { color: #ffdead; background: transparent; } 205 | .ruby-node { color: #ffa07a; background: transparent; } 206 | .ruby-comment { color: #b22222; font-weight: bold; background: transparent; } 207 | .ruby-regexp { color: #ffa07a; background: transparent; } 208 | .ruby-value { color: #7fffd4; background: transparent; } -------------------------------------------------------------------------------- /src/gr/spinellis/ckjm/ant/CkjmTask.java: -------------------------------------------------------------------------------- 1 | /* 2 | * (C) Copyright 2005 Diomidis Spinellis, Julien Rentrop 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package gr.spinellis.ckjm.ant; 18 | 19 | import gr.spinellis.ckjm.MetricsFilter; 20 | import gr.spinellis.ckjm.PrintPlainResults; 21 | 22 | import java.io.File; 23 | import java.io.FileOutputStream; 24 | import java.io.IOException; 25 | import java.io.OutputStream; 26 | import java.io.PrintStream; 27 | 28 | import org.apache.tools.ant.BuildException; 29 | import org.apache.tools.ant.DirectoryScanner; 30 | import org.apache.tools.ant.taskdefs.MatchingTask; 31 | import org.apache.tools.ant.types.Path; 32 | 33 | /** 34 | * Ant task definition for the CKJM metrics tool. 35 | * 36 | * @version $Revision: 1.3 $ 37 | * @author Julien Rentrop 38 | */ 39 | public class CkjmTask extends MatchingTask { 40 | private File outputFile; 41 | 42 | private File classDir; 43 | 44 | private Path extdirs; 45 | 46 | private String format; 47 | 48 | public CkjmTask() { 49 | this.format = "plain"; 50 | } 51 | 52 | /** 53 | * Sets the format of the output file. 54 | * 55 | * @param format 56 | * the format of the output file. Allowable values are 'plain' or 57 | * 'xml'. 58 | */ 59 | public void setFormat(String format) { 60 | this.format = format; 61 | 62 | } 63 | 64 | /** 65 | * Sets the outputfile 66 | * 67 | * @param outputfile 68 | * Location of outputfile 69 | */ 70 | public void setOutputfile(File outputfile) { 71 | this.outputFile = outputfile; 72 | } 73 | 74 | /** 75 | * Sets the dir which contains the class files that will be analyzed 76 | * 77 | * @param classDir 78 | * Location of class files 79 | */ 80 | public void setClassdir(File classDir) { 81 | this.classDir = classDir; 82 | } 83 | 84 | /** 85 | * Sets the extension directories that will be used by ckjm. 86 | * @param e extdirs a path containing .jar files 87 | */ 88 | public void setExtdirs(Path e) { 89 | if (extdirs == null) { 90 | extdirs = e; 91 | } else { 92 | extdirs.append(e); 93 | } 94 | } 95 | 96 | /** 97 | * Gets the extension directories that will be used by ckjm. 98 | * @return the extension directories as a path 99 | */ 100 | public Path getExtdirs() { 101 | return extdirs; 102 | } 103 | 104 | /** 105 | * Adds a path to extdirs. 106 | * @return a path to be modified 107 | */ 108 | public Path createExtdirs() { 109 | if (extdirs == null) { 110 | extdirs = new Path(getProject()); 111 | } 112 | return extdirs.createPath(); 113 | } 114 | 115 | /** 116 | * Executes the CKJM Ant Task. This method redirects the output of the CKJM 117 | * tool to a file. When XML format is used it will buffer the output and 118 | * translate it to the XML format. 119 | * 120 | * @throws BuildException 121 | * if an error occurs. 122 | */ 123 | public void execute() throws BuildException { 124 | if (classDir == null) { 125 | throw new BuildException("classdir attribute must be set!"); 126 | } 127 | if (!classDir.exists()) { 128 | throw new BuildException("classdir does not exist!"); 129 | } 130 | if (!classDir.isDirectory()) { 131 | throw new BuildException("classdir is not a directory!"); 132 | } 133 | 134 | if (extdirs != null && extdirs.size() > 0) { 135 | if (System.getProperty("java.ext.dirs").length() == 0) 136 | System.setProperty("java.ext.dirs", extdirs.toString()); 137 | else 138 | System.setProperty("java.ext.dirs", 139 | System.getProperty("java.ext.dirs") + File.pathSeparator + 140 | extdirs); 141 | } 142 | 143 | DirectoryScanner ds = super.getDirectoryScanner(classDir); 144 | 145 | String files[] = ds.getIncludedFiles(); 146 | if (files.length == 0) { 147 | log("No class files in specified directory " + classDir); 148 | } else { 149 | for (int i = 0; i < files.length; i++) { 150 | files[i] = classDir.getPath() + File.separatorChar + files[i]; 151 | } 152 | 153 | try { 154 | OutputStream outputStream = new FileOutputStream(outputFile); 155 | 156 | if (format.equals("xml")) { 157 | PrintXmlResults outputXml = new PrintXmlResults( 158 | new PrintStream(outputStream)); 159 | 160 | outputXml.printHeader(); 161 | MetricsFilter.runMetrics(files, outputXml); 162 | outputXml.printFooter(); 163 | } else { 164 | PrintPlainResults outputPlain = new PrintPlainResults( 165 | new PrintStream(outputStream)); 166 | MetricsFilter.runMetrics(files, outputPlain); 167 | } 168 | 169 | outputStream.close(); 170 | 171 | } catch (IOException ioe) { 172 | throw new BuildException("Error file handling: " 173 | + ioe.getMessage()); 174 | } 175 | } 176 | } 177 | } 178 | -------------------------------------------------------------------------------- /contrib/ckjm_ruby-1.0/doc/classes/MetricsUtils/CKJMMetricGrapher.html: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 8 | Class: MetricsUtils::CKJMMetricGrapher 9 | 10 | 11 | 12 | 43 | 44 | 45 | 46 | 47 | 48 | 49 |
50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 63 | 64 | 65 | 66 | 67 | 70 | 71 |
ClassMetricsUtils::CKJMMetricGrapher
In: 58 | 59 | metrics_utils.rb 60 | 61 |
62 |
Parent: 68 | Object 69 |
72 |
73 | 74 | 75 |
76 | 77 | 78 | 79 |
80 | 81 |
82 |

83 | This class graphs the Chidamber-Kemerer metrics to PNG files, as currently 84 | configured. It needs gnuplot v4.0 or later. 85 |

86 | 87 |
88 | 89 | 90 |
91 | 92 |
93 |

Methods

94 | 95 |
96 | new   97 | plot_metrics   98 |
99 |
100 | 101 |
102 | 103 | 104 | 105 | 106 |
107 | 108 | 109 |
110 |

Constants

111 | 112 |
113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 |
FILE_FORMAT="png"
FORMAT_OPTIONS="small"
125 |
126 |
127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 |
135 |

Public Class methods

136 | 137 |
138 | 139 | 140 | 146 | 147 |
148 |

149 | Initializes the instance. 150 |

151 | 152 | 155 | 158 | 162 | 165 |
ckjm_file_name:Input file 153 | 154 |
project_desc:Short project description to go on graphs 156 | 157 |
plotter:A Plotter-like object that responds to open, 159 | close, print_to_graph(str), and end_of_data 160 | 161 |
jm:An instance of the JavaMetrics object 163 | 164 |
166 |
167 |
168 | 169 |

Public Instance methods

170 | 171 |
172 | 173 | 174 | 180 | 181 |
182 |

183 | Plots all metrics 184 |

185 |
186 |
187 | 188 | 189 |
190 | 191 | 192 |
193 | 194 | 195 |
196 |

[Validate]

197 |
198 | 199 | 200 | -------------------------------------------------------------------------------- /contrib/ckjm_ruby-1.0/doc/classes/MetricsUtils/JavaMetrics.html: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 8 | Class: MetricsUtils::JavaMetrics 9 | 10 | 11 | 12 | 43 | 44 | 45 | 46 | 47 | 48 | 49 |
50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 63 | 64 | 65 | 66 | 67 | 70 | 71 |
ClassMetricsUtils::JavaMetrics
In: 58 | 59 | metrics_utils.rb 60 | 61 |
62 |
Parent: 68 | Object 69 |
72 |
73 | 74 | 75 |
76 | 77 | 78 | 79 |
80 | 81 |
82 |

83 | This class parses the text output of the ckjm program and stores the data 84 | points. 85 |

86 | 87 |
88 | 89 | 90 |
91 | 92 |
93 |

Methods

94 | 95 |
96 | metric_desc   97 | metrics   98 | new   99 |
100 |
101 | 102 |
103 | 104 | 105 | 106 | 107 |
108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 |
118 |

Public Class methods

119 | 120 |
121 | 122 | 123 | 129 | 130 |
131 |

132 | Initializes this instance with the name of the text file containing the 133 | output of the ckjm program. 134 |

135 |
136 |
137 | 138 |

Public Instance methods

139 | 140 |
141 | 142 | 143 | 149 | 150 |
151 |

152 | Returns string description corresponding to sym; raises 153 | ArgumentError if sym unknown. Valid values for 154 | sym are :wmc, :dit, :noc, :cbo, :rfc, :lcom, :ca, and :npm. 155 |

156 |
157 |
158 | 159 |
160 | 161 | 162 | 168 | 169 |
170 |

171 | Computes the distribution of the 8 ckjm metrics by counting how many classes 173 | fall into a bucket with a specific metric value. Buckets are just 174 | individual metric values, (e.g. 1, 2, 3 for DIT). Returns the distribution 175 | as a hash of hashes: 176 |

177 |
178 |   { metric_sym => { metric_value => count } }
179 | 
180 |

181 | Example: 182 |

183 |
184 |   { :wmc => { 7 => 134 } }
185 | 
186 |
187 |
188 | 189 | 190 |
191 | 192 | 193 |
194 | 195 | 196 |
197 |

[Validate]

198 |
199 | 200 | 201 | -------------------------------------------------------------------------------- /doc/bib.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 8 | 9 |
    10 | 11 | 12 |
  • Rajendra K. Bandi, 13 | Vijay K. Vaishnavi, and Daniel E. Turk. 14 | Predicting maintenance performance using object-oriented design complexity 15 | metrics. 16 | IEEE Transactions on Software Engineering, 29(1):77–87, 2003. 17 | (doi:10.1109/TSE.2003.1166590)

  • 18 | 19 | 20 |
  • Victor R. Basili, 21 | Lionel C. Briand, and Walcélio L. Melo. 22 | A validation of object-oriented design metrics as quality indicators. 23 | IEEE Transactions on Software Engineering, 22(10):751–761, 24 | 1996. 25 | (doi:10.1109/32.544352)

  • 26 | 27 | 28 |
  • Shyam R. Chidamber 29 | and Chris F. Kemerer. 30 | A metrics suite for object oriented design. 31 | IEEE Transactions on Software Engineering, 20(6):476–493, 1994. 32 | (doi:10.1109/32.295895)

  • 33 | 34 | 35 |
  • Shyam R. Chidamber, 36 | David P. Darcy, and Chris F. Kemerer. 37 | Managerial use of metrics for object-oriented software: An exploratory 38 | analysis. 39 | IEEE Transactions on Software Engineering, 24(8):629–639, 1998. 40 | (doi:10.1109/32.707698)

  • 41 | 42 | 43 |
  • Rudolf Ferenc, István 44 | Siket, and Tibor Gyimóthy. 45 | Extracting facts from 46 | open source software. 47 | In ICSM '04: Proceedings of the 20th IEEE International Conference on 48 | Software Maintenance (ICSM'04), pages 60–69. IEEE Computer Society, 49 | 2004.

  • 50 | 51 | 53 |
  • Brian L. 54 | Henderson-Sellers, Larry L. Constantine, and Ian M. Graham. 55 | Coupling and cohesion: Towards a valid metrics suite for object-oriented 56 | analysis and design. 57 | Object Oriented Systems, 3(3):143–158, 1996.

  • 58 | 59 | 60 |
  • Brian 61 | Henderson-Sellers. 62 | Object-Oriented Metrics: Measures of Complexity. 63 | Prentice-Hall, Englewood Cliffs, NJ, 1996.

  • 64 | 65 | 66 |
  • Martin Hitz and 67 | Behzad Montazeri. 68 | Chidamber and Kemerer's metrics suite: A measurement theory perspective. 69 | IEEE Transactions on Software Engineering, 22(4):267–271, 1996. 70 | (doi:10.1109/32.491650)

  • 71 | 72 | 73 |
  • Tobias Mayer and Tracy 74 | Hall. 75 | A critical analysis of current OO design metrics. 76 | Software Quality Control, 8(2):97–110, 1999. 77 | (doi:10.1023/A:1008900825849)

  • 78 | 79 | 80 |
  • Sandeep Purao and 81 | Vijay Vaishnavi. 82 | Product metrics for object-oriented systems. 83 | ACM Computing Surveys, 35(2):191–221, 2003. 84 | (doi:10.1145/857076.857090)

  • 85 | 86 | 87 |
  • Linda Rosenberg, 88 | Ruth Stapko, and Al Gallo. 89 | Applying 90 | object-oriented metrics. 91 | In Sixth International Symposium on Software Metrics—Measurement for 92 | Object-Oriented Software Projects Workshop, November 1999. 93 | Presentation available online 94 | http://www.software.org/metrics99/rosenberg.ppt (December 2005).

  • 96 | 97 | 98 |
  • Linda Rosenberg, Ruth 99 | Stapko, and Al Gallo. 100 | Risk-based 101 | object oriented testing. 102 | In Twenty-Fourth Annual Software Engineering Workshop. NASA, 103 | Software Engineering Laboratory, December 1999.

  • 104 | 105 | 106 |
  • Linda H. Rosenberg. 107 | Applying and 108 | interpreting object oriented metrics. 109 | In Software Technology Conference '98, 1998.

  • 110 | 111 | 112 |
  • Diomidis Spinellis. 113 | Tool 114 | writing: A forgotten art?. 115 | IEEE Software, 22(4):9–11, July/August 2005. 116 | (doi:10.1109/MS.2005.111)

  • 117 | 118 | 119 |
  • Diomidis Spinellis. 120 | Code Quality: The Open 121 | Source Perspective. 122 | Addison-Wesley, Boston, MA, 2006.

  • 123 | 124 |
125 | 126 | 127 |
128 | -------------------------------------------------------------------------------- /doc/bib.bib: -------------------------------------------------------------------------------- 1 | @article{MH99, 2 | author = {Tobias Mayer and Tracy Hall}, 3 | title = {A Critical Analysis of Current {OO} Design Metrics}, 4 | journal = {Software Quality Control}, 5 | volume = {8}, 6 | number = {2}, 7 | year = {1999}, 8 | issn = {0963-9314}, 9 | pages = {97--110}, 10 | doi = {http://dx.doi.org/10.1023/A:1008900825849}, 11 | publisher = {Kluwer Academic Publishers}, 12 | } 13 | 14 | @article{PV03, 15 | author = {Sandeep Purao and Vijay Vaishnavi}, 16 | title = {Product metrics for object-oriented systems}, 17 | journal = {ACM Computing Surveys}, 18 | volume = {35}, 19 | number = {2}, 20 | year = {2003}, 21 | issn = {0360-0300}, 22 | pages = {191--221}, 23 | doi = {http://doi.acm.org/10.1145/857076.857090}, 24 | publisher = {ACM Press}, 25 | Where="Have" 26 | } 27 | 28 | 29 | @article{BBM96, 30 | author = {Victor R. Basili and Lionel C. Briand and Walc\'{e}lio L. Melo}, 31 | title = {A Validation of Object-Oriented Design Metrics as Quality Indicators}, 32 | journal = ieeese, 33 | volume = {22}, 34 | number = {10}, 35 | year = {1996}, 36 | issn = {0098-5589}, 37 | pages = {751--761}, 38 | doi = {http://dx.doi.org/10.1109/32.544352}, 39 | publisher = {IEEE Press}, 40 | } 41 | 42 | @article{CK94, 43 | author = {Shyam R. Chidamber and Chris F. Kemerer}, 44 | title = {A Metrics Suite for Object Oriented Design}, 45 | journal = ieeese, 46 | volume = {20}, 47 | number = {6}, 48 | year = {1994}, 49 | issn = {0098-5589}, 50 | pages = {476--493}, 51 | doi = {http://dx.doi.org/10.1109/32.295895}, 52 | publisher = {IEEE Press}, 53 | Where="pub/lib" 54 | } 55 | 56 | @article{BVT03, 57 | author = {Rajendra K. Bandi and Vijay K. Vaishnavi and Daniel E. Turk}, 58 | title = {Predicting Maintenance Performance Using Object-Oriented Design Complexity Metrics}, 59 | journal = ieeese, 60 | volume = {29}, 61 | number = {1}, 62 | year = {2003}, 63 | issn = {0098-5589}, 64 | pages = {77--87}, 65 | doi = {http://dx.doi.org/10.1109/TSE.2003.1166590}, 66 | publisher = {IEEE Press}, 67 | } 68 | 69 | @Book {Sel96, 70 | author="Brian Henderson-Sellers", 71 | Title="Object-Oriented Metrics: Measures of Complexity", 72 | Publisher="Prentice-Hall", 73 | Address="Englewood Cliffs, NJ", 74 | Year="1996" 75 | } 76 | @inproceedings{Ros98, 77 | author = {Linda H. Rosenberg}, 78 | title = {Applying and Interpreting Object Oriented Metrics}, 79 | booktitle = {Software Technology Conference '98}, 80 | year = {1998}, 81 | location = "Salt Lake City, Utah", 82 | Where="pub/lib,photocopy", 83 | URL="http://www.literateprogramming.com/ooapply.pdf" 84 | } 85 | 86 | @article{HCG96, 87 | author = {Henderson-Sellers, Brian L. and Constantine, Larry L. and Graham, Ian M.}, 88 | title = {Coupling and Cohesion: Towards a Valid Metrics Suite for Object-oriented Analysis and Design}, 89 | journal = {Object Oriented Systems}, 90 | volume = {3}, 91 | number = {3}, 92 | year = {1996}, 93 | pages = {143--158} 94 | } 95 | 96 | @article{HM96, 97 | author = {Martin Hitz and Behzad Montazeri}, 98 | title = {{C}hidamber and {K}emerer's Metrics Suite: A Measurement Theory Perspective}, 99 | journal = ieeese, 100 | volume = {22}, 101 | number = {4}, 102 | year = {1996}, 103 | issn = {0098-5589}, 104 | pages = {267--271}, 105 | doi = {http://dx.doi.org/10.1109/32.491650}, 106 | publisher = {IEEE Press}, 107 | Where="pub/lib" 108 | } 109 | 110 | @article{CDK98, 111 | author = {Shyam R. Chidamber and David P. Darcy and Chris F. Kemerer}, 112 | title = {Managerial Use of Metrics for Object-Oriented Software: An Exploratory Analysis}, 113 | journal = ieeese, 114 | volume = {24}, 115 | number = {8}, 116 | year = {1998}, 117 | issn = {0098-5589}, 118 | pages = {629--639}, 119 | doi = {http://dx.doi.org/10.1109/32.707698}, 120 | publisher = {IEEE Press}, 121 | Where="pub/lib" 122 | } 123 | 124 | % Link from http://sel.gsfc.nasa.gov/website/sew/past-sew.htm 125 | @inproceedings{RSG99, 126 | author = {Linda Rosenberg and Ruth Stapko and Al Gallo}, 127 | title = {Risk-based Object Oriented Testing}, 128 | booktitle = {Twenty-Fourth Annual Software Engineering Workshop}, 129 | year = {1999}, 130 | month=dec, 131 | location = {Goddard Space Flight Center, Greenbelt, MD}, 132 | Organization="NASA, Software Engineering Laboratory", 133 | Where="pub/lib", 134 | URL="http://sel.gsfc.nasa.gov/website/sew/1999/topics/rosenberg_SEW99paper.pdf" 135 | } 136 | 137 | 138 | @inproceedings{RSG99b, 139 | author = {Linda Rosenberg and Ruth Stapko and Al Gallo}, 140 | title = {Applying Object-Oriented Metrics}, 141 | booktitle = {Sixth International Symposium on Software Metrics---Measurement for Object-Oriented Software Projects Workshop}, 142 | year = {1999}, 143 | Note="Presentation available online \url{http://www.software.org/metrics99/rosenberg.ppt} (December 2005)", 144 | month=nov, 145 | location = {Boca Raton, FL}, 146 | Where="pub/lib", 147 | URL="http://www.software.org/metrics99/rosenberg.ppt" 148 | } 149 | 150 | @inproceedings{FSG04, 151 | author = {Rudolf Ferenc and Istv\'{a}n Siket and Tibor Gyim\'{o}thy}, 152 | title = {Extracting Facts from Open Source Software}, 153 | booktitle = {ICSM '04: Proceedings of the 20th IEEE International Conference on Software Maintenance (ICSM'04)}, 154 | year = {2004}, 155 | isbn = {0-7695-2213-0}, 156 | pages = {60--69}, 157 | publisher = {IEEE Computer Society}, 158 | Where="pub/lib,have" 159 | } 160 | 161 | @Article{Spi05g, 162 | Title="Tool Writing: A Forgotten Art?", 163 | Author="Diomidis Spinellis", 164 | Journal="IEEE Software", 165 | Month="July/August", 166 | Pages="9--11", 167 | Volume=22, 168 | Number=4, 169 | Year=2005, 170 | DOI="doi:10.1109/MS.2005.111", 171 | URL="http://www.dmst.aueb.gr/dds/pubs/jrnl/2005-IEEESW-TotT/html/v22n4.html" 172 | } 173 | 174 | @Book {Spi06, 175 | Author="Diomidis Spinellis", 176 | Title="Code Quality: The Open Source Perspective", 177 | Publisher="Addison-Wesley", 178 | Address="Boston, MA", 179 | URL="http://www.spinellis.gr/codequality", 180 | XISBN="0-321-16607-8", 181 | Year=2006 182 | } 183 | 184 | -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 8 | 9 | ckjm — Chidamber and Kemerer Java Metrics 10 | 11 | 12 | 13 | Fork me on GitHub



14 |

ckjm dds

15 |

ckjm — Chidamber and Kemerer Java Metrics

16 | 17 |

18 | Picture of the Java book, the metrics paper, and a measure tape 19 | The program ckjm calculates Chidamber and Kemerer object-oriented 20 | metrics by processing the bytecode of compiled Java files. 21 | The program calculates for each class the following six metrics proposed 22 | by Chidamber and Kemerer. 23 |

24 |
    25 |
  • WMC: Weighted methods per class
  • 26 |
  • DIT: Depth of Inheritance Tree
  • 27 |
  • NOC: Number of Children
  • 28 |
  • CBO: Coupling between object classes
  • 29 |
  • RFC: Response for a Class
  • 30 |
  • LCOM: Lack of cohesion in methods
  • 31 |
32 |

33 | In addition it also calculates for each class 34 |

35 |
    36 |
  • Ca: Afferent couplings
  • 37 |
  • NPM: Number of public methods
  • 38 |
39 |

Citation and Background

40 |

41 | If you use this tool in your research, please cite it as follows.
42 | Diomidis Spinellis. 43 | Tool writing: A forgotten art? 44 | IEEE Software, 22(4):9–11, July/August 2005. 45 | (doi:10.1109/MS.2005.111). 46 |

47 |

48 | I wrote this program out of frustration over the 49 | lack 50 | of reliable programs to calculate the 51 | Chidamber and Kemerer object-oriented metrics I needed 52 | to illustrate some concepts in my book 53 | Code Quality: The Open Source Perspective. 54 | The programs I found on the web were either 55 | incomplete (they calculated only some of the metrics), 56 | or unreliable (they calculated results that were obviously wrong), 57 | or extremely inefficient (they required GB of RAM and hours of processing). 58 | Ckjm is mean and lean, following the Unix tradition of doing 59 | one thing well. 60 | It will not automatically recurse directories looking for the files 61 | you want measured and it does not offer a GUI. 62 | However, it does this job thoroughly, and efficiently: 63 | on a 1.6GHz Pentium-M machine it will process the 33MB of the Eclipse 3.0 64 | jar files (19717 classes) in 95 seconds. 65 |

66 |

Getting Started

67 |

68 | To run the program you simply specify the class files 69 | (or pairs of jar/class files) 70 | on its command line or standard input. 71 | The program will produce on its standard output a line for each class 72 | containing the complete name of the class and the values of its metrics. 73 | This operation model allows the tool to be easilly extended using textual 74 | pre- and post-processors. 75 |

76 |

77 | From version 1.2 and onward ckjm can be used as an 78 | ant task, and can also directly generate XML output. 79 | You can post-process the XML output with XSLT to generate nice-looking 80 | reports. 81 | Here is a report example using 82 | simple report style 83 | and here is an example using the 84 | fancy report style. 85 | XSL files for both report styles are part of the distribution. 86 |

87 | 88 | 89 | 90 |

Download and Links

91 | Ckjm is hereby made freely available as Open Source Software. 92 | The current version of ckjm is VERSION. 93 | You can download ckjm and its documentation from the following links: 94 | 123 | 124 |

Projects Using ckjm

125 |

126 | ckjm is now also available through the following projects. 127 |

135 |

136 | 137 |

138 | Diomidis Spinellis home page 139 |


140 | 141 | 153 |
142 | Valid XHTML 1.0! 143 | Level Triple-A conformance icon, W3C-WAI Web Content Accessibility Guidelines 1.0 144 | 145 | 146 | (C) Copyright 2005-2010 D. Spinellis. 147 | May be freely uploaded by WWW viewers and similar programs. 148 | All other rights reserved. 149 |
150 | Last modified: $Date: 2010/05/22 10:27:16 $ 151 |
152 |
154 | 155 | 156 | -------------------------------------------------------------------------------- /contrib/ckjm_ruby-1.0/mk_ckjm_graphs.rb: -------------------------------------------------------------------------------- 1 | #-- 2 | # Copyright (c) 2007, Edwin Fine, Fine Computer Consultants, Inc. 3 | # All rights reserved. 4 | # 5 | # Redistribution and use in source and binary forms, with or without 6 | # modification, are permitted provided that the following conditions are 7 | # met: 8 | # 9 | # * Redistributions of source code must retain the above copyright 10 | # notice, this list of conditions and the following disclaimer. 11 | # * Redistributions in binary form must reproduce the above copyright 12 | # notice, this list of conditions and the following disclaimer in the 13 | # documentation and/or other materials provided with the distribution. 14 | # * Neither the name of Diomidis Spinellis nor the names of its 15 | # contributors may be used to endorse or promote products derived from 16 | # this software without specific prior written permission. 17 | # 18 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 | # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 | # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 | # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22 | # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 | # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 24 | # TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 25 | # PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 26 | # LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 27 | # NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 28 | # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | #++ 30 | # This program gets statistics based on the output of the ckjm program 31 | # (http://www.spinellis.gr/sw/ckjm) and generates graphs in PNG format 32 | # using gnuplot (V4 or later required). There is one graph per metric, 33 | # which all get stored in the current directory. ckjm must create output 34 | # using the "plain" (default) option. 35 | # 36 | # To run this program: 37 | # 38 | # ruby mk_ckjm_graphs.rb ckjm-text-file 39 | # 40 | # ckjm plain output creates a text file with a line for each 41 | # class. Each line consists of the class name, followed by 8 42 | # numeric metrics as described below. Values are space-separated. 43 | # 44 | # com.my.ClassName WMC DIT NOC CBO RFC LCOM Ca NPM 45 | # 46 | # Example: 47 | # 48 | # com.vz.schedule.data.ScheduleData 15 1 0 0 20 69 3 15 49 | # 50 | # The following text is from Diomidis Spinellis' ckjm web page: 51 | # 52 | # The metrics ckjm will calculate and display for each class are the 53 | # following. 54 | # 55 | # * WMC - Weighted methods per class. 56 | # A class's weighted methods per class WMC metric is simply the sum 57 | # of the complexities of its methods. As a measure of complexity we 58 | # can use the cyclomatic complexity, or we can abritrarily assign a 59 | # complexity value of 1 to each method. The ckjm program assigns a 60 | # complexity value of 1 to each method, and therefore the value of 61 | # the WMC is equal to the number of methods in the class. 62 | # * DIT - Depth of Inheritance Tree. 63 | # The depth of inheritance tree (DIT) metric provides for each class a 64 | # measure of the inheritance levels from the object hierarchy top. In 65 | # Java where all classes inherit Object the minimum value of DIT is 1. 66 | # * NOC - Number of Children. 67 | # A class's number of children (NOC) metric simply measures the number 68 | # of immediate descendants of the class. 69 | # * CBO - Coupling between object classes. 70 | # The coupling between object classes (CBO) metric represents the 71 | # number of classes coupled to a given class (efferent couplings, 72 | # Ce). This coupling can occur through method calls, field accesses, 73 | # inheritance, arguments, return types, and exceptions. 74 | # * RFC - Response for a Class. 75 | # The metric called the response for a class (RFC) measures the 76 | # number of different methods that can be executed when an object of 77 | # that class receives a message (when a method is invoked for that 78 | # object). Ideally, we would want to find for each method of the class, 79 | # the methods that class will call, and repeat this for each called 80 | # method, calculating what is called the transitive closure of the 81 | # method's call graph. This process can however be both expensive 82 | # and quite inaccurate. In ckjm, we calculate a rough approximation 83 | # to the response set by simply inspecting method calls within the 84 | # class's method bodies. This simplification was also used in the 1994 85 | # Chidamber and Kemerer description of the metrics. 86 | # * LCOM - Lack of cohesion in methods. 87 | # A class's lack of cohesion in methods (LCOM) metric counts the sets 88 | # of methods in a class that are not related through the sharing of 89 | # some of the class's fields. The original definition of this metric 90 | # (which is the one used in ckjm) considers all pairs of a class's 91 | # methods. In some of these pairs both methods access at least one 92 | # common field of the class, while in other pairs the two methods 93 | # to not share any common field accesses. The lack of cohesion in 94 | # methods is then calculated by subtracting from the number of method 95 | # pairs that don't share a field access the number of method pairs 96 | # that do. Note that subsequent definitions of this metric used as a 97 | # measurement basis the number of disjoint graph components of the 98 | # class's methods. Others modified the definition of connectedness 99 | # to include calls between the methods of the class. The program ckjm 100 | # follows the original (1994) definition by Chidamber and Kemerer. 101 | # * Ca - Afferent couplings. 102 | # A class's afferent couplings is a measure of how many other classes 103 | # use the specific class. Ca is calculated using the same definition 104 | # as that used for calculating CBO (Ce). 105 | # * NPM - Number of Public Methods. 106 | # The NPM metric simply counts all the methods in a class that are 107 | # declared as public. It can be used to measure the size of an API 108 | # provided by a package. 109 | 110 | require 'metrics_utils' 111 | 112 | # This is the top-level application that ties together 113 | # all the other elements to plot the ckjm data. 114 | class App 115 | # Runs the application. 116 | # +argv+:: array containing [ckjm_file_name, project_desc]. 117 | def App.run(argv) 118 | App.usage unless argv.length == 2 119 | ckjm_file_name, project_desc = argv 120 | jm = MetricsUtils::JavaMetrics.new(ckjm_file_name) 121 | plotter = MetricsUtils::Plotter.instance 122 | grapher = MetricsUtils::CKJMMetricGrapher.new(ckjm_file_name, project_desc, plotter, jm) 123 | grapher.plot_metrics 124 | end 125 | 126 | private 127 | 128 | # Displays a usage message and exits. 129 | def App.usage 130 | puts "usage: ruby #{File.basename $0} ckjm-input-file project-desc" 131 | exit 1 132 | end 133 | end 134 | 135 | argv = ARGV.to_a 136 | $debug_mode = argv.reject! {|elem| elem == "-d"} 137 | App.run(argv) 138 | -------------------------------------------------------------------------------- /contrib/ckjm_ruby-1.0/doc/classes/MetricsUtils/Plotter.html: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 8 | Class: MetricsUtils::Plotter 9 | 10 | 11 | 12 | 43 | 44 | 45 | 46 | 47 | 48 | 49 |
50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 63 | 64 | 65 | 66 | 67 | 70 | 71 |
ClassMetricsUtils::Plotter
In: 58 | 59 | metrics_utils.rb 60 | 61 |
62 |
Parent: 68 | Object 69 |
72 |
73 | 74 | 75 |
76 | 77 | 78 | 79 |
80 | 81 |
82 |

83 | This class exists to provide access to the underlying plotting mechanism. 84 | It configures the plotter program and accepts plot data to send to the 85 | program. At the moment, it uses gnuplot as the plotter program. It seems 86 | unlikely to change in the foreseeable future unless I make a full plotter 87 | abstraction, which given the time I have to do this, is about as likely as 88 | me winning the jackpot. 89 |

90 | 91 |
92 | 93 | 94 |
95 | 96 |
97 |

Methods

98 | 99 |
100 | close   101 | end_of_data   102 | new   103 | open   104 | print_to_graph   105 |
106 |
107 | 108 |
109 | 110 | 111 | 112 |
113 |

Included Modules

114 | 115 |
116 | Singleton 117 |
118 |
119 | 120 |
121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 |
131 |

Public Class methods

132 | 133 |
134 | 135 | 136 | 142 | 143 |
144 |

145 | Initializes the plotter instance 146 |

147 |
148 |
149 | 150 |

Public Instance methods

151 | 152 |
153 | 154 | 155 | 161 | 162 |
163 |

164 | Closes the plotter if it‘s open. 165 | Returns nil. 166 |

167 |
168 |
169 | 170 |
171 | 172 | 173 | 179 | 180 |
181 |

182 | Sends an "end of data" signal to the plotter to signify the 183 | closing of a plot. 184 |

185 |
186 |
187 | 188 |
189 | 190 | 191 | 197 | 198 |
199 |

200 | Opens the plotter for writing. If a block is provided, calls that block and 201 | closes the plotter when the block returns. Always returns nil. 202 |

203 |
204 |
205 | 206 |
207 | 208 | 209 | 215 | 216 |
217 |

218 | Prints plot data to the plotter. 219 |

220 |
221 |
222 | 223 | 224 |
225 | 226 | 227 |
228 | 229 | 230 |
231 |

[Validate]

232 |
233 | 234 | 235 | -------------------------------------------------------------------------------- /contrib/ckjm_ruby-1.0/doc/files/mk_ckjm_graphs_rb.html: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 8 | File: mk_ckjm_graphs.rb 9 | 10 | 11 | 12 | 43 | 44 | 45 | 46 | 47 | 48 | 49 |
50 |

mk_ckjm_graphs.rb

51 | 52 | 53 | 54 | 56 | 57 | 58 | 59 | 60 | 61 |
Path:mk_ckjm_graphs.rb 55 |
Last Update:Thu Feb 15 01:30:39 -0500 2007
62 |
63 | 64 | 65 |
66 | 67 | 68 | 69 |
70 | 71 |
72 |

73 | This program gets statistics based on the output of the ckjm program (www.spinellis.gr/sw/ckjm) and 75 | generates graphs in PNG format using gnuplot (V4 or later required). There 76 | is one graph per metric, which all get stored in the current directory. 77 | ckjm must create output using the "plain" (default) option. 78 |

79 |

80 | To run this program: 81 |

82 |
 83 |   ruby mk_ckjm_graphs.rb ckjm-text-file
 84 | 
85 |

86 | ckjm plain output creates a text file with a line for each class. Each line 87 | consists of the class name, followed by 8 numeric metrics as described 88 | below. Values are space-separated. 89 |

90 |
 91 |   com.my.ClassName WMC DIT NOC CBO RFC LCOM Ca NPM
 92 | 
93 |

94 | Example: 95 |

96 |
 97 |   com.vz.schedule.data.ScheduleData 15 1 0 0 20 69 3 15
 98 | 
99 |

100 | The following text is from Diomidis Spinellis’ ckjm web page: 101 |

102 |

103 | The metrics ckjm will calculate and display for each class are the 104 | following. 105 |

106 |
    107 |
  • WMC - Weighted methods per class. A class‘s weighted methods 108 | per class WMC metric is simply the sum of the complexities of its methods. 109 | As a measure of complexity we can use the cyclomatic complexity, or we can 110 | abritrarily assign a complexity value of 1 to each method. The ckjm program 111 | assigns a complexity value of 1 to each method, and therefore the value of 112 | the WMC is equal to the number of methods in the class. 113 | 114 |
  • 115 |
  • DIT - Depth of Inheritance Tree. The depth of inheritance tree (DIT) 116 | metric provides for each class a measure of the inheritance levels from the 117 | object hierarchy top. In Java where all classes inherit Object the minimum 118 | value of DIT is 1. 119 | 120 |
  • 121 |
  • NOC - Number of Children. A class‘s number of children (NOC) 122 | metric simply measures the number of immediate descendants of the class. 123 | 124 |
  • 125 |
  • CBO - Coupling between object classes. The coupling between object 126 | classes (CBO) metric represents the number of classes coupled to a given 127 | class (efferent couplings, Ce). This coupling can occur through method 128 | calls, field accesses, inheritance, arguments, return types, and 129 | exceptions. 130 | 131 |
  • 132 |
  • RFC - Response for a Class. The metric called the response for a 133 | class (RFC) measures the number of different methods that can be executed 134 | when an object of that class receives a message (when a method is invoked 135 | for that object). Ideally, we would want to find for each method of the 136 | class, the methods that class will call, and repeat this for each called 137 | method, calculating what is called the transitive closure of the 138 | method‘s call graph. This process can however be both expensive and 139 | quite inaccurate. In ckjm, we calculate a rough approximation to the 140 | response set by simply inspecting method calls within the class‘s 141 | method bodies. This simplification was also used in the 1994 Chidamber and 142 | Kemerer description of the metrics. 143 | 144 |
  • 145 |
  • LCOM - Lack of cohesion in methods. A class‘s lack of cohesion 146 | in methods (LCOM) metric counts the sets of methods in a class that are not 147 | related through the sharing of some of the class‘s fields. The 148 | original definition of this metric (which is the one used in ckjm) 149 | considers all pairs of a class‘s methods. In some of these pairs both 150 | methods access at least one common field of the class, while in other pairs 151 | the two methods to not share any common field accesses. The lack of 152 | cohesion in methods is then calculated by subtracting from the number of 153 | method pairs that don‘t share a field access the number of method 154 | pairs that do. Note that subsequent definitions of this metric used as a 155 | measurement basis the number of disjoint graph components of the 156 | class‘s methods. Others modified the definition of connectedness to 157 | include calls between the methods of the class. The program ckjm follows 158 | the original (1994) definition by Chidamber and Kemerer. 159 | 160 |
  • 161 |
  • Ca - Afferent couplings. A class‘s afferent couplings is a 162 | measure of how many other classes use the specific class. Ca is calculated 163 | using the same definition as that used for calculating CBO (Ce). 164 | 165 |
  • 166 |
  • NPM - Number of Public Methods. The NPM metric simply counts all the 167 | methods in a class that are declared as public. It can be used to measure 168 | the size of an API provided by a package. 169 | 170 |
  • 171 |
172 | 173 |
174 | 175 |
176 |

Required files

177 | 178 |
179 | metrics_utils   180 |
181 |
182 | 183 |
184 | 185 | 186 |
187 | 188 | 189 | 190 | 191 |
192 | 193 | 194 | 195 | 196 | 197 | 198 | 199 | 200 | 201 | 202 | 203 |
204 | 205 | 206 |
207 |

[Validate]

208 |
209 | 210 | 211 | -------------------------------------------------------------------------------- /src/gr/spinellis/ckjm/ClassVisitor.java: -------------------------------------------------------------------------------- 1 | /* 2 | * (C) Copyright 2005 Diomidis Spinellis 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package gr.spinellis.ckjm; 18 | 19 | import org.apache.bcel.classfile.*; 20 | import org.apache.bcel.generic.*; 21 | import org.apache.bcel.Repository; 22 | import org.apache.bcel.Constants; 23 | import org.apache.bcel.util.*; 24 | import java.io.*; 25 | import java.util.*; 26 | import java.lang.reflect.Modifier; 27 | 28 | /** 29 | * Visit a class updating its Chidamber-Kemerer metrics. 30 | * 31 | * @see ClassMetrics 32 | * @version $Revision: 1.21 $ 33 | * @author Diomidis Spinellis 34 | */ 35 | public class ClassVisitor extends org.apache.bcel.classfile.EmptyVisitor { 36 | /** The class being visited. */ 37 | private JavaClass visitedClass; 38 | /** The class's constant pool. */ 39 | private ConstantPoolGen cp; 40 | /** The class's fully qualified name. */ 41 | private String myClassName; 42 | /** The container where metrics for all classes are stored. */ 43 | private ClassMetricsContainer cmap; 44 | /** The emtrics for the class being visited. */ 45 | private ClassMetrics cm; 46 | /* Classes encountered. 47 | * Its cardinality is used for calculating the CBO. 48 | */ 49 | private HashSet efferentCoupledClasses = new HashSet(); 50 | /** Methods encountered. 51 | * Its cardinality is used for calculating the RFC. 52 | */ 53 | private HashSet responseSet = new HashSet(); 54 | /** Use of fields in methods. 55 | * Its contents are used for calculating the LCOM. 56 | * We use a Tree rather than a Hash to calculate the 57 | * intersection in O(n) instead of O(n*n). 58 | */ 59 | ArrayList> mi = new ArrayList>(); 60 | 61 | public ClassVisitor(JavaClass jc, ClassMetricsContainer classMap) { 62 | visitedClass = jc; 63 | cp = new ConstantPoolGen(visitedClass.getConstantPool()); 64 | cmap = classMap; 65 | myClassName = jc.getClassName(); 66 | cm = cmap.getMetrics(myClassName); 67 | } 68 | 69 | /** Return the class's metrics container. */ 70 | public ClassMetrics getMetrics() { return cm; } 71 | 72 | public void start() { 73 | visitJavaClass(visitedClass); 74 | } 75 | 76 | /** Calculate the class's metrics based on its elements. */ 77 | public void visitJavaClass(JavaClass jc) { 78 | String super_name = jc.getSuperclassName(); 79 | String package_name = jc.getPackageName(); 80 | 81 | cm.setVisited(); 82 | if (jc.isPublic()) 83 | cm.setPublic(); 84 | ClassMetrics pm = cmap.getMetrics(super_name); 85 | 86 | pm.incNoc(); 87 | try { 88 | cm.setDit(jc.getSuperClasses().length); 89 | } catch( ClassNotFoundException ex) { 90 | System.err.println("Error obtaining all superclasses of " + jc); 91 | } 92 | registerCoupling(super_name); 93 | 94 | String ifs[] = jc.getInterfaceNames(); 95 | /* Measuring decision: couple interfaces */ 96 | for (int i = 0; i < ifs.length; i++) 97 | registerCoupling(ifs[i]); 98 | 99 | Field[] fields = jc.getFields(); 100 | for(int i=0; i < fields.length; i++) 101 | fields[i].accept(this); 102 | 103 | Method[] methods = jc.getMethods(); 104 | for(int i=0; i < methods.length; i++) 105 | methods[i].accept(this); 106 | } 107 | 108 | /** Add a given class to the classes we are coupled to */ 109 | public void registerCoupling(String className) { 110 | /* Measuring decision: don't couple to Java SDK */ 111 | if ((MetricsFilter.isJdkIncluded() || 112 | !ClassMetrics.isJdkClass(className)) && 113 | !myClassName.equals(className)) { 114 | efferentCoupledClasses.add(className); 115 | cmap.getMetrics(className).addAfferentCoupling(myClassName); 116 | } 117 | } 118 | 119 | /* Add the type's class to the classes we are coupled to */ 120 | public void registerCoupling(Type t) { 121 | registerCoupling(className(t)); 122 | } 123 | 124 | /* Add a given class to the classes we are coupled to */ 125 | void registerFieldAccess(String className, String fieldName) { 126 | registerCoupling(className); 127 | if (className.equals(myClassName)) 128 | mi.get(mi.size() - 1).add(fieldName); 129 | } 130 | 131 | /* Add a given method to our response set */ 132 | void registerMethodInvocation(String className, String methodName, Type[] args) { 133 | registerCoupling(className); 134 | /* Measuring decision: calls to JDK methods are included in the RFC calculation */ 135 | incRFC(className, methodName, args); 136 | } 137 | 138 | /** Called when a field access is encountered. */ 139 | public void visitField(Field field) { 140 | registerCoupling(field.getType()); 141 | } 142 | 143 | /** Called when encountering a method that should be included in the 144 | class's RFC. */ 145 | private void incRFC(String className, String methodName, Type[] arguments) { 146 | String argumentList = Arrays.asList(arguments).toString(); 147 | // remove [ ] chars from begin and end 148 | String args = argumentList.substring(1, argumentList.length() - 1); 149 | String signature = className + "." + methodName + "(" + args + ")"; 150 | responseSet.add(signature); 151 | } 152 | 153 | /** Called when a method invocation is encountered. */ 154 | public void visitMethod(Method method) { 155 | MethodGen mg = new MethodGen(method, visitedClass.getClassName(), cp); 156 | 157 | Type result_type = mg.getReturnType(); 158 | Type[] argTypes = mg.getArgumentTypes(); 159 | 160 | registerCoupling(mg.getReturnType()); 161 | for (int i = 0; i < argTypes.length; i++) 162 | registerCoupling(argTypes[i]); 163 | 164 | String[] exceptions = mg.getExceptions(); 165 | for (int i = 0; i < exceptions.length; i++) 166 | registerCoupling(exceptions[i]); 167 | 168 | /* Measuring decision: A class's own methods contribute to its RFC */ 169 | incRFC(myClassName, method.getName(), argTypes); 170 | 171 | cm.incWmc(); 172 | if (Modifier.isPublic(method.getModifiers())) 173 | cm.incNpm(); 174 | mi.add(new TreeSet()); 175 | MethodVisitor factory = new MethodVisitor(mg, this); 176 | factory.start(); 177 | } 178 | 179 | /** Return a class name associated with a type. */ 180 | static String className(Type t) { 181 | String ts = t.toString(); 182 | 183 | if (t.getType() <= Constants.T_VOID) { 184 | return "java.PRIMITIVE"; 185 | } else if(t instanceof ArrayType) { 186 | ArrayType at = (ArrayType)t; 187 | return className(at.getBasicType()); 188 | } else { 189 | return t.toString(); 190 | } 191 | } 192 | 193 | /** Do final accounting at the end of the visit. */ 194 | public void end() { 195 | cm.setCbo(efferentCoupledClasses.size()); 196 | cm.setRfc(responseSet.size()); 197 | /* 198 | * Calculate LCOM as |P| - |Q| if |P| - |Q| > 0 or 0 otherwise 199 | * where 200 | * P = set of all empty set intersections 201 | * Q = set of all nonempty set intersections 202 | */ 203 | int lcom = 0; 204 | for (int i = 0; i < mi.size(); i++) 205 | for (int j = i + 1; j < mi.size(); j++) { 206 | /* A shallow unknown-type copy is enough */ 207 | TreeSet intersection = (TreeSet)mi.get(i).clone(); 208 | intersection.retainAll(mi.get(j)); 209 | if (intersection.size() == 0) 210 | lcom++; 211 | else 212 | lcom--; 213 | } 214 | cm.setLcom(lcom > 0 ? lcom : 0); 215 | } 216 | } 217 | -------------------------------------------------------------------------------- /contrib/ckjm_ruby-1.0/metrics_utils.rb: -------------------------------------------------------------------------------- 1 | #-- 2 | # Copyright (c) 2007, Edwin Fine, Fine Computer Consultants, Inc. 3 | # All rights reserved. 4 | # 5 | # Redistribution and use in source and binary forms, with or without 6 | # modification, are permitted provided that the following conditions are 7 | # met: 8 | # 9 | # * Redistributions of source code must retain the above copyright 10 | # notice, this list of conditions and the following disclaimer. 11 | # * Redistributions in binary form must reproduce the above copyright 12 | # notice, this list of conditions and the following disclaimer in the 13 | # documentation and/or other materials provided with the distribution. 14 | # * Neither the name of Diomidis Spinellis nor the names of its 15 | # contributors may be used to endorse or promote products derived from 16 | # this software without specific prior written permission. 17 | # 18 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 | # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 | # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 | # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22 | # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 | # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 24 | # TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 25 | # PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 26 | # LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 27 | # NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 28 | # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | #++ 30 | # This module contains utilities to plot Chidamber-Kemerer metrics. 31 | module MetricsUtils 32 | 33 | require 'singleton' 34 | 35 | # This class exists to provide access to the underlying plotting mechanism. 36 | # It configures the plotter program and accepts plot data to send to the program. 37 | # At the moment, it uses gnuplot as the plotter program. It seems unlikely to 38 | # change in the foreseeable future unless I make a full plotter abstraction, 39 | # which given the time I have to do this, is about as likely as me winning 40 | # the jackpot. 41 | class Plotter 42 | include Singleton 43 | 44 | # Initializes the plotter instance 45 | def initialize 46 | @plot_cmd = "gnuplot -" 47 | @plot_cmd << " > /dev/null 2>&1" unless $debug_mode 48 | end 49 | 50 | # Opens the plotter for writing. If a block is provided, 51 | # calls that block and closes the plotter when the block 52 | # returns. Always returns +nil+. 53 | def open(&blk) # :yields: 54 | @plot_pipe = IO.popen(@plot_cmd, "w") 55 | 56 | if blk 57 | begin 58 | blk.call 59 | ensure 60 | self.close 61 | end 62 | end 63 | nil 64 | end 65 | 66 | # Closes the plotter if it's open. 67 | # Returns nil. 68 | def close 69 | @plot_pipe && @plot_pipe.close 70 | ensure 71 | @plot_pipe = nil 72 | end 73 | 74 | # Prints plot data to the plotter. 75 | def print_to_graph(plot_data) 76 | @plot_pipe.puts plot_data 77 | puts(plot_data) if $debug_mode 78 | end 79 | 80 | # Sends an "end of data" signal to the plotter 81 | # to signify the closing of a plot. 82 | def end_of_data 83 | print_to_graph "e" # gnuplot-specific 84 | end 85 | 86 | end # class Plotter 87 | 88 | # This class parses the text output of the ckjm program 89 | # and stores the data points. 90 | class JavaMetrics 91 | # :stopdoc: 92 | # Metrics are expected in this order in the input record 93 | METRICS = [ 94 | [ :wmc, 'Weighted methods per class' ], 95 | [ :dit, 'Depth of Inheritance Tree' ], 96 | [ :noc, 'Number of Children' ], 97 | [ :cbo, 'Coupling between object classes' ], 98 | [ :rfc, 'Response for a Class' ], 99 | [ :lcom, 'Lack of cohesion in methods' ], 100 | [ :ca, 'Afferent couplings' ], 101 | [ :npm, 'Number of Public Methods' ] 102 | ].freeze # :nodoc: 103 | 104 | # Maps metric symbols to long descriptions 105 | METRIC_DESC = Hash[*METRICS.flatten].freeze 106 | # :startdoc: 107 | 108 | # Initializes this instance with the name of the 109 | # text file containing the output of the ckjm 110 | # program. 111 | def initialize(ckjm_file_name) 112 | @ckjm_file_name = ckjm_file_name 113 | @distribution = {} 114 | end 115 | 116 | # Computes the distribution of the 8 ckjm metrics 117 | # by counting how many classes fall into a bucket 118 | # with a specific metric value. Buckets are just 119 | # individual metric values, (e.g. 1, 2, 3 for DIT). 120 | # Returns the distribution as a hash of hashes: 121 | # { metric_sym => { metric_value => count } } 122 | # Example: 123 | # { :wmc => { 7 => 134 } } 124 | def metrics 125 | @distribution.clear 126 | File.foreach(@ckjm_file_name) do |line| 127 | line.chomp! 128 | if line =~ /^\S+(\s+\d+){8}\s*$/ 129 | class_name, *metrics_vals = line.split(/\s+/) 130 | METRICS.each_index do |i| 131 | value = metrics_vals[i].to_i 132 | (@distribution[METRICS[i][0]] ||= Hash.new(0))[value] += 1 133 | end 134 | end 135 | end 136 | @distribution 137 | end 138 | 139 | # Returns string description corresponding 140 | # to +sym+; raises +ArgumentError+ if +sym+ unknown. 141 | # Valid values for +sym+ are :wmc, :dit, :noc, 142 | # :cbo, :rfc, :lcom, :ca, and :npm. 143 | def metric_desc(sym) 144 | METRIC_DESC[sym] or raise ArgumentError, "Unknown symbol :#{sym}" 145 | end 146 | end 147 | 148 | # This class graphs the Chidamber-Kemerer metrics to PNG 149 | # files, as currently configured. It needs gnuplot v4.0 or later. 150 | class CKJMMetricGrapher 151 | FILE_FORMAT = "png" 152 | FORMAT_OPTIONS = "small" 153 | 154 | # Initializes the instance. 155 | # +ckjm_file_name+:: Input file 156 | # +project_desc+:: Short project description to go on graphs 157 | # +plotter+:: A Plotter-like object that responds to open, close, 158 | # print_to_graph(str), and end_of_data 159 | # +jm+:: An instance of the JavaMetrics object 160 | def initialize(ckjm_file_name, project_desc, plotter, jm) 161 | @ckjm_file_name, @project_desc, @plotter, @jm = ckjm_file_name, project_desc, plotter, jm 162 | end 163 | 164 | # Plots all metrics 165 | def plot_metrics 166 | @jm.metrics.each do |metric_sym, vals| 167 | @plotter.open do 168 | plot_metric metric_sym, vals 169 | end 170 | end 171 | end 172 | 173 | private 174 | 175 | # Returns file name for graph 176 | def fmt_graph_filename(metric_sym) 177 | "#{@project_desc.gsub(/\s+/, '_')}_#{metric_sym.to_s}_metric.png" 178 | end 179 | 180 | # Returns graph title 181 | def fmt_graph_title(metric_sym) 182 | "#{@jm.metric_desc(metric_sym)} (#{metric_sym.to_s.upcase})" 183 | end 184 | 185 | # Plots a single metric whose symbol is *sym* (e.g. :dit) 186 | # and which consists of the hash *vals*. Each hash key/value 187 | # pair is { metric_value => count }. 188 | def plot_metric(metric_sym, vals) 189 | @plotter.print_to_graph %{ 190 | set terminal #{FILE_FORMAT} #{FORMAT_OPTIONS} 191 | set output '#{fmt_graph_filename(metric_sym)}' 192 | set title '#{fmt_graph_title(metric_sym)}' 193 | set xrange [-0.5:*] 194 | set xlabel '#{metric_sym.to_s.upcase}' 195 | set ylabel 'Number of classes' 196 | set timestamp 'Generated for #@project_desc on %Y/%m/%d' top 197 | set boxwidth 0.8 absolute 198 | set style fill solid 0.25 border 199 | show timestamp 200 | plot '-' using 1:2 notitle with boxes 201 | } 202 | 203 | vals.sort.each do |point| 204 | @plotter.print_to_graph point.join(" ") 205 | end 206 | 207 | @plotter.end_of_data 208 | @plotter.print_to_graph "set output" # close file, end of plot 209 | end 210 | 211 | end 212 | end 213 | -------------------------------------------------------------------------------- /xsl/ckjm_extra.xsl: -------------------------------------------------------------------------------- 1 | 2 | 18 | 19 | 20 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | CKJM Chidamber and Kemerer Java Metrics 30 | 31 | 86 | 87 | 88 |

CKJM Chidamber and Kemerer Java Metrics

89 |

Designed for use with CKJM and Ant.

90 | 91 |
92 | 93 | 94 | 95 | 96 | 97 | 98 | 104 | 110 | 111 |
99 | 100 | NV 101 |

Top :

102 |
103 |
105 | 106 | [#NV ] 107 | 108 | [explanations] 109 |
112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 |
130 |
131 | 132 | 133 |

Explanations

134 |
135 |
136 |
WMC - Weighted methods per class
137 | A class's weighted methods per class WMC 138 | metric is simply the sum of the complexities of its methods. 139 | As a measure of complexity we can use the cyclomatic complexity, 140 | or we can abritrarily assign a complexity value of 1 to each method. 141 | The ckjm program assigns a complexity value of 1 to each method, 142 | and therefore the value of the WMC is equal to the number of methods 143 | in the class. 144 |
DIT - Depth of Inheritance Tree
145 | The depth of inheritance tree (DIT) metric provides 146 | for each class a measure of the inheritance levels from the object 147 | hierarchy top. 148 | In Java where all classes inherit Object the minimum value 149 | of DIT is 1. 150 |
NOC - Number of Children
151 | 152 | A class's number of children (NOC) 153 | metric simply 154 | measures the number of immediate descendants of the class. 155 |
CBO - Coupling between object classes
156 | The coupling between object classes (CBO) 157 | metric represents the number of classes coupled to a given 158 | class. 159 | This coupling can occur through method calls, 160 | field accesses, inheritance, arguments, return types, 161 | and exceptions. 162 |
RFC - Response for a Class
163 | The metric called the response for a class (RFC) 164 | measures the number of different 165 | methods that can be executed when an object of that 166 | class receives a message (when a method is invoked 167 | for that object). 168 | Ideally, we would want to find for each method 169 | of the class, the methods that class will call, 170 | and repeat this for each called method, 171 | calculating what is called the transitive closure 172 | 173 | of the method's call graph. 174 | This process can however be both expensive and quite 175 | inaccurate. 176 | In ckjm, we calculate a rough 177 | approximation to the response set 178 | by simply inspecting method calls within the class's 179 | method bodies. 180 | This simplification was also used in the 1994 Chidamber and Kemerer 181 | description of the metrics. 182 |
LCOM - Lack of cohesion in methods
183 | A class's lack of cohesion in methods (LCOM) 184 | metric counts the sets of methods in a class that are not related 185 | through the sharing of some of the class's fields. 186 | The original definition of this metric 187 | (which is the one used in ckjm) 188 | considers all pairs of a class's methods. 189 | In some of these pairs both methods access at 190 | least one common field of the class, while in 191 | other pairs the two methods to not share any 192 | common field accesses. 193 | The lack of cohesion in methods is then calculated 194 | by subtracting from the number of method pairs 195 | that don't share a field access the number of 196 | method pairs that do. 197 | Note that subsequent definitions 198 | of this metric used as a measurement basis the number 199 | of disjoint graph components of the class's methods. 200 | Others modified the definition of connectedness to 201 | include calls between the methods of the class. 202 | The program ckjm follows the original (1994) definition 203 | by Chidamber and Kemerer. 204 |
Ca - Afferent couplings
205 | A class's afferent couplings is a measure of how many other classes 206 | use the specific class. 207 | Ca is calculated using the same definition as that used for 208 | calculating CBO. 209 |
NPM - Number of Public Methods
210 | The NPM metric simply counts all the methods in a class that 211 | are declared as public. 212 | It can be used to measure the size of an API provided by a package. 213 |
214 |
215 | 216 | 217 | 218 |
219 | 220 |
221 | -------------------------------------------------------------------------------- /contrib/ckjm_ruby-1.0/examples/util_concurrent.ckjm: -------------------------------------------------------------------------------- 1 | EDU.oswego.cs.dl.util.concurrent.WaitFreeQueue$Node 2 1 0 0 3 1 1 0 2 | EDU.oswego.cs.dl.util.concurrent.VetoableChangeMulticaster 16 1 0 0 35 18 0 12 3 | EDU.oswego.cs.dl.util.concurrent.ConcurrentReaderHashMap$KeyIterator 2 2 0 2 3 1 2 0 4 | EDU.oswego.cs.dl.util.concurrent.QueuedExecutor$RunLoop 2 1 0 2 6 0 1 1 5 | EDU.oswego.cs.dl.util.concurrent.SemaphoreControlledChannel 10 1 2 2 22 0 2 8 6 | EDU.oswego.cs.dl.util.concurrent.ClockDaemon 10 2 0 6 34 1 1 8 7 | EDU.oswego.cs.dl.util.concurrent.FIFOReadWriteLock$ReaderSync 4 1 0 2 8 0 1 3 8 | EDU.oswego.cs.dl.util.concurrent.WaitableShort 20 3 0 1 33 0 0 20 9 | EDU.oswego.cs.dl.util.concurrent.SyncList$SyncCollectionListIterator 8 2 0 4 22 0 1 6 10 | EDU.oswego.cs.dl.util.concurrent.ConcurrentReaderHashMap$HashIterator 7 1 2 2 12 5 3 5 11 | EDU.oswego.cs.dl.util.concurrent.FJTask$Seq 3 2 0 1 5 0 1 3 12 | EDU.oswego.cs.dl.util.concurrent.SynchronizedInt 23 2 1 1 27 0 2 23 13 | EDU.oswego.cs.dl.util.concurrent.LinkedNode 3 1 0 0 4 1 4 3 14 | EDU.oswego.cs.dl.util.concurrent.SyncSet 5 2 1 3 13 8 2 5 15 | EDU.oswego.cs.dl.util.concurrent.CountDown 6 1 0 1 13 0 0 6 16 | EDU.oswego.cs.dl.util.concurrent.FutureResult$1 2 1 0 2 6 0 1 1 17 | EDU.oswego.cs.dl.util.concurrent.FJTaskRunner 22 1 0 3 48 53 2 1 18 | EDU.oswego.cs.dl.util.concurrent.SynchronizedBoolean 16 2 1 1 20 34 1 16 19 | EDU.oswego.cs.dl.util.concurrent.WaitableByte 20 3 0 1 33 0 0 20 20 | EDU.oswego.cs.dl.util.concurrent.Heap 11 1 0 0 16 23 2 7 21 | EDU.oswego.cs.dl.util.concurrent.ClockDaemon$RunLoop 2 1 0 2 6 0 1 1 22 | EDU.oswego.cs.dl.util.concurrent.ReaderPreferenceReadWriteLock 2 2 0 1 3 1 0 1 23 | EDU.oswego.cs.dl.util.concurrent.Puttable 2 1 0 0 2 1 1 2 24 | EDU.oswego.cs.dl.util.concurrent.WaitFreeQueue 9 1 0 2 17 18 0 6 25 | EDU.oswego.cs.dl.util.concurrent.Takable 2 1 0 0 2 1 1 2 26 | EDU.oswego.cs.dl.util.concurrent.ConcurrentHashMap$KeySet 7 1 0 3 13 0 1 5 27 | EDU.oswego.cs.dl.util.concurrent.BrokenBarrierException 2 1 0 0 4 0 2 2 28 | EDU.oswego.cs.dl.util.concurrent.ObservableSync$SyncObserver 2 1 0 0 2 1 1 2 29 | EDU.oswego.cs.dl.util.concurrent.CopyOnWriteArrayList 42 1 0 2 78 481 3 36 30 | EDU.oswego.cs.dl.util.concurrent.FJTaskRunnerGroup 18 1 0 6 48 17 2 10 31 | EDU.oswego.cs.dl.util.concurrent.NullSync 4 1 0 1 7 6 0 4 32 | EDU.oswego.cs.dl.util.concurrent.ConcurrentHashMap 31 1 0 8 62 297 6 20 33 | EDU.oswego.cs.dl.util.concurrent.ThreadedExecutor 2 2 0 3 8 1 0 2 34 | EDU.oswego.cs.dl.util.concurrent.ThreadFactory 1 1 0 0 1 0 7 1 35 | EDU.oswego.cs.dl.util.concurrent.SyncCollection 22 1 2 4 47 0 5 20 36 | EDU.oswego.cs.dl.util.concurrent.ReentrantLock 6 1 0 1 15 0 0 6 37 | EDU.oswego.cs.dl.util.concurrent.ConcurrentReaderHashMap$BarrierLock 1 1 0 0 2 0 1 0 38 | EDU.oswego.cs.dl.util.concurrent.SynchronizedDouble 16 2 1 1 21 34 1 16 39 | EDU.oswego.cs.dl.util.concurrent.SynchronizedShort 23 2 1 1 27 0 1 23 40 | EDU.oswego.cs.dl.util.concurrent.CopyOnWriteArraySet 15 1 0 1 30 0 1 15 41 | EDU.oswego.cs.dl.util.concurrent.QueuedSemaphore$WaitQueue 3 1 2 1 4 3 5 0 42 | EDU.oswego.cs.dl.util.concurrent.PrioritySemaphore$PriorityWaitQueue 3 2 0 3 9 0 1 0 43 | EDU.oswego.cs.dl.util.concurrent.PooledExecutor$DiscardWhenBlocked 2 1 0 2 3 1 1 1 44 | EDU.oswego.cs.dl.util.concurrent.ConcurrentReaderHashMap$1 0 1 0 0 0 0 4 0 45 | EDU.oswego.cs.dl.util.concurrent.FIFOReadWriteLock 9 1 0 5 20 0 2 3 46 | EDU.oswego.cs.dl.util.concurrent.WaitableLong 20 3 0 1 33 0 0 20 47 | EDU.oswego.cs.dl.util.concurrent.TimedCallable 2 2 0 4 10 0 0 2 48 | EDU.oswego.cs.dl.util.concurrent.FIFOSemaphore 1 3 0 3 3 0 1 1 49 | EDU.oswego.cs.dl.util.concurrent.SynchronizedLong 23 2 1 1 27 0 3 23 50 | EDU.oswego.cs.dl.util.concurrent.ThreadFactoryUser$DefaultThreadFactory 2 1 0 1 4 1 1 1 51 | EDU.oswego.cs.dl.util.concurrent.CyclicBarrier 9 1 0 3 21 14 0 8 52 | EDU.oswego.cs.dl.util.concurrent.ConcurrentReaderHashMap 34 1 0 8 66 349 6 22 53 | EDU.oswego.cs.dl.util.concurrent.SynchronizedFloat 16 2 1 1 21 34 1 16 54 | EDU.oswego.cs.dl.util.concurrent.CopyOnWriteArrayList$COWIterator 10 1 0 0 13 3 1 9 55 | EDU.oswego.cs.dl.util.concurrent.SyncSortedSet 10 3 0 3 22 39 0 9 56 | EDU.oswego.cs.dl.util.concurrent.CopyOnWriteArrayList$COWSubList$COWSubListIterator 10 1 0 2 18 19 1 9 57 | EDU.oswego.cs.dl.util.concurrent.ReadWriteLock 2 1 0 1 2 1 8 2 58 | EDU.oswego.cs.dl.util.concurrent.FJTaskRunnerGroup$InvokableFJTask 4 2 0 1 9 0 1 1 59 | EDU.oswego.cs.dl.util.concurrent.SyncList 18 2 0 4 42 127 1 17 60 | EDU.oswego.cs.dl.util.concurrent.SynchronousChannel 8 1 0 3 23 0 1 7 61 | EDU.oswego.cs.dl.util.concurrent.PooledExecutor$AbortWhenBlocked 2 1 0 2 4 1 1 1 62 | EDU.oswego.cs.dl.util.concurrent.Sync 3 1 0 0 3 3 26 3 63 | EDU.oswego.cs.dl.util.concurrent.PooledExecutor 32 2 0 12 64 290 6 29 64 | EDU.oswego.cs.dl.util.concurrent.Channel 5 1 0 2 5 10 8 5 65 | EDU.oswego.cs.dl.util.concurrent.WaitableFloat 14 3 0 1 25 0 0 14 66 | EDU.oswego.cs.dl.util.concurrent.PropertyChangeMulticaster 16 1 0 0 34 18 0 12 67 | EDU.oswego.cs.dl.util.concurrent.WaitableDouble 14 3 0 1 25 0 0 14 68 | EDU.oswego.cs.dl.util.concurrent.Rendezvous 9 1 0 7 25 16 0 8 69 | EDU.oswego.cs.dl.util.concurrent.ConcurrentHashMap$1 0 1 0 0 0 0 4 0 70 | EDU.oswego.cs.dl.util.concurrent.BoundedChannel 1 1 0 1 1 0 4 1 71 | EDU.oswego.cs.dl.util.concurrent.Latch 4 1 0 1 11 0 0 4 72 | EDU.oswego.cs.dl.util.concurrent.FJTaskRunner$VolatileTaskRef 5 1 0 1 6 4 1 0 73 | EDU.oswego.cs.dl.util.concurrent.ObservableSync 9 1 0 3 18 0 0 9 74 | EDU.oswego.cs.dl.util.concurrent.PooledExecutor$DiscardOldestWhenBlocked 2 1 0 3 6 0 1 1 75 | EDU.oswego.cs.dl.util.concurrent.WaitableInt 20 3 0 1 33 0 0 20 76 | EDU.oswego.cs.dl.util.concurrent.WaitableBoolean 12 3 0 1 23 0 0 12 77 | EDU.oswego.cs.dl.util.concurrent.PooledExecutor$BlockedExecutionHandler 1 1 0 0 1 0 6 1 78 | EDU.oswego.cs.dl.util.concurrent.TimeoutException 2 1 0 0 4 0 4 2 79 | EDU.oswego.cs.dl.util.concurrent.FIFOSemaphore$FIFOWaitQueue 3 2 0 2 4 0 2 0 80 | EDU.oswego.cs.dl.util.concurrent.PooledExecutor$RunWhenBlocked 2 1 0 2 4 1 1 1 81 | EDU.oswego.cs.dl.util.concurrent.TimeoutSync 4 1 0 2 8 0 0 4 82 | EDU.oswego.cs.dl.util.concurrent.SynchronousChannel$Queue 3 1 0 1 4 1 1 0 83 | EDU.oswego.cs.dl.util.concurrent.CopyOnWriteArrayList$COWSubList 11 1 0 2 25 0 2 8 84 | EDU.oswego.cs.dl.util.concurrent.SyncCollection$SyncCollectionIterator 4 1 1 2 15 0 2 3 85 | EDU.oswego.cs.dl.util.concurrent.WriterPreferenceReadWriteLock 14 1 2 5 18 7 5 3 86 | EDU.oswego.cs.dl.util.concurrent.Semaphore 6 1 2 1 14 0 4 6 87 | EDU.oswego.cs.dl.util.concurrent.ReentrantWriterPreferenceReadWriteLock 7 2 0 4 17 0 0 1 88 | EDU.oswego.cs.dl.util.concurrent.WriterPreferenceReadWriteLock$WriterLock 5 2 0 4 19 0 3 3 89 | EDU.oswego.cs.dl.util.concurrent.Slot 5 2 0 1 7 0 0 3 90 | EDU.oswego.cs.dl.util.concurrent.FJTask$Wrap 2 2 0 1 4 0 1 2 91 | EDU.oswego.cs.dl.util.concurrent.DirectExecutor 2 1 0 1 6 1 0 2 92 | EDU.oswego.cs.dl.util.concurrent.ConcurrentHashMap$Entry 7 1 0 0 17 0 2 6 93 | EDU.oswego.cs.dl.util.concurrent.Mutex 4 1 0 1 11 0 0 4 94 | EDU.oswego.cs.dl.util.concurrent.LayeredSync 4 1 0 1 9 0 0 4 95 | EDU.oswego.cs.dl.util.concurrent.PooledExecutor$Worker 2 1 0 1 6 0 1 1 96 | EDU.oswego.cs.dl.util.concurrent.ConcurrentHashMap$EntrySet 7 1 0 3 16 0 1 5 97 | EDU.oswego.cs.dl.util.concurrent.ConcurrentHashMap$Segment 3 1 0 0 4 3 2 0 98 | EDU.oswego.cs.dl.util.concurrent.WaitableRef 8 3 0 1 15 0 0 8 99 | EDU.oswego.cs.dl.util.concurrent.Rendezvous$Rotator 2 1 0 1 3 1 1 2 100 | EDU.oswego.cs.dl.util.concurrent.SyncMap 22 1 1 5 49 0 1 20 101 | EDU.oswego.cs.dl.util.concurrent.WriterPreferenceReadWriteLock$ReaderLock 5 2 0 4 19 0 3 3 102 | EDU.oswego.cs.dl.util.concurrent.Rendezvous$RendezvousFunction 1 1 0 0 1 0 2 1 103 | EDU.oswego.cs.dl.util.concurrent.Callable 1 1 0 0 1 0 3 1 104 | EDU.oswego.cs.dl.util.concurrent.SynchronizedByte 23 2 1 1 27 0 1 23 105 | EDU.oswego.cs.dl.util.concurrent.SynchronizedVariable 4 1 9 1 8 0 9 4 106 | EDU.oswego.cs.dl.util.concurrent.LinkedQueue 9 1 0 2 18 12 1 7 107 | EDU.oswego.cs.dl.util.concurrent.PrioritySemaphore 1 3 0 3 3 0 0 1 108 | EDU.oswego.cs.dl.util.concurrent.ConcurrentHashMap$KeyIterator 2 2 0 2 3 1 2 0 109 | EDU.oswego.cs.dl.util.concurrent.ClockDaemon$TaskNode 7 1 0 0 8 9 2 1 110 | EDU.oswego.cs.dl.util.concurrent.Executor 1 1 0 0 1 0 7 1 111 | EDU.oswego.cs.dl.util.concurrent.LockedExecutor 2 1 0 2 6 0 0 2 112 | EDU.oswego.cs.dl.util.concurrent.ConcurrentHashMap$ValueIterator 2 2 0 2 3 1 2 0 113 | EDU.oswego.cs.dl.util.concurrent.BoundedLinkedQueue 15 1 0 3 26 29 1 11 114 | EDU.oswego.cs.dl.util.concurrent.WaiterPreferenceSemaphore 5 2 0 1 12 0 1 5 115 | EDU.oswego.cs.dl.util.concurrent.DefaultChannelCapacity 4 1 0 1 9 0 4 3 116 | EDU.oswego.cs.dl.util.concurrent.FJTask 18 1 6 6 32 147 9 17 117 | EDU.oswego.cs.dl.util.concurrent.SynchronizedRef 6 2 1 1 9 0 1 6 118 | EDU.oswego.cs.dl.util.concurrent.FJTask$Par 3 2 0 1 5 0 1 3 119 | EDU.oswego.cs.dl.util.concurrent.ConcurrentReaderHashMap$KeySet 7 1 0 3 13 0 1 5 120 | EDU.oswego.cs.dl.util.concurrent.PooledExecutor$WaitWhenBlocked 2 1 0 3 4 0 1 1 121 | EDU.oswego.cs.dl.util.concurrent.ThreadFactoryUser 3 1 5 2 5 0 5 3 122 | EDU.oswego.cs.dl.util.concurrent.FutureResult 11 1 0 3 19 0 2 10 123 | EDU.oswego.cs.dl.util.concurrent.ConcurrentReaderHashMap$Values 6 1 0 3 11 0 1 4 124 | EDU.oswego.cs.dl.util.concurrent.BoundedPriorityQueue 8 2 0 3 15 8 0 6 125 | EDU.oswego.cs.dl.util.concurrent.SyncSortedMap 10 2 0 3 21 39 0 9 126 | EDU.oswego.cs.dl.util.concurrent.QueuedExecutor 10 2 0 7 20 7 1 8 127 | EDU.oswego.cs.dl.util.concurrent.ConcurrentHashMap$HashIterator 7 1 2 3 12 5 3 5 128 | EDU.oswego.cs.dl.util.concurrent.FJTask$Par2 2 2 0 1 4 0 1 2 129 | EDU.oswego.cs.dl.util.concurrent.Barrier 2 1 0 0 2 1 2 2 130 | EDU.oswego.cs.dl.util.concurrent.FJTask$Seq2 2 2 0 1 4 0 1 2 131 | EDU.oswego.cs.dl.util.concurrent.ConcurrentReaderHashMap$ValueIterator 2 2 0 2 3 1 2 0 132 | EDU.oswego.cs.dl.util.concurrent.ConcurrentHashMap$Values 6 1 0 3 11 0 1 4 133 | EDU.oswego.cs.dl.util.concurrent.BoundedBuffer 13 1 0 2 22 4 0 9 134 | EDU.oswego.cs.dl.util.concurrent.QueuedSemaphore$WaitQueue$WaitNode 4 1 0 1 12 0 4 0 135 | EDU.oswego.cs.dl.util.concurrent.FIFOReadWriteLock$WriterSync 4 1 0 2 8 0 1 3 136 | EDU.oswego.cs.dl.util.concurrent.QueuedExecutor$1 2 1 0 0 3 1 1 1 137 | EDU.oswego.cs.dl.util.concurrent.CondVar 5 1 0 1 17 4 0 5 138 | EDU.oswego.cs.dl.util.concurrent.SynchronizedChar 16 2 1 1 20 34 1 16 139 | EDU.oswego.cs.dl.util.concurrent.WaitableChar 14 3 0 1 25 0 0 14 140 | EDU.oswego.cs.dl.util.concurrent.ConcurrentReaderHashMap$Entry 7 1 0 0 17 0 2 6 141 | EDU.oswego.cs.dl.util.concurrent.QueuedSemaphore 8 2 2 3 18 18 3 4 142 | EDU.oswego.cs.dl.util.concurrent.ConcurrentReaderHashMap$EntrySet 7 1 0 3 16 0 1 5 143 | EDU.oswego.cs.dl.util.concurrent.WriterPreferenceReadWriteLock$Signaller 2 1 2 1 3 1 4 0 144 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright 2005-2016 Diomidis Spinellis 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /lib/LICENSE.txt: -------------------------------------------------------------------------------- 1 | /* 2 | * Apache License 3 | * Version 2.0, January 2004 4 | * http://www.apache.org/licenses/ 5 | * 6 | * TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 7 | * 8 | * 1. Definitions. 9 | * 10 | * "License" shall mean the terms and conditions for use, reproduction, 11 | * and distribution as defined by Sections 1 through 9 of this document. 12 | * 13 | * "Licensor" shall mean the copyright owner or entity authorized by 14 | * the copyright owner that is granting the License. 15 | * 16 | * "Legal Entity" shall mean the union of the acting entity and all 17 | * other entities that control, are controlled by, or are under common 18 | * control with that entity. For the purposes of this definition, 19 | * "control" means (i) the power, direct or indirect, to cause the 20 | * direction or management of such entity, whether by contract or 21 | * otherwise, or (ii) ownership of fifty percent (50%) or more of the 22 | * outstanding shares, or (iii) beneficial ownership of such entity. 23 | * 24 | * "You" (or "Your") shall mean an individual or Legal Entity 25 | * exercising permissions granted by this License. 26 | * 27 | * "Source" form shall mean the preferred form for making modifications, 28 | * including but not limited to software source code, documentation 29 | * source, and configuration files. 30 | * 31 | * "Object" form shall mean any form resulting from mechanical 32 | * transformation or translation of a Source form, including but 33 | * not limited to compiled object code, generated documentation, 34 | * and conversions to other media types. 35 | * 36 | * "Work" shall mean the work of authorship, whether in Source or 37 | * Object form, made available under the License, as indicated by a 38 | * copyright notice that is included in or attached to the work 39 | * (an example is provided in the Appendix below). 40 | * 41 | * "Derivative Works" shall mean any work, whether in Source or Object 42 | * form, that is based on (or derived from) the Work and for which the 43 | * editorial revisions, annotations, elaborations, or other modifications 44 | * represent, as a whole, an original work of authorship. For the purposes 45 | * of this License, Derivative Works shall not include works that remain 46 | * separable from, or merely link (or bind by name) to the interfaces of, 47 | * the Work and Derivative Works thereof. 48 | * 49 | * "Contribution" shall mean any work of authorship, including 50 | * the original version of the Work and any modifications or additions 51 | * to that Work or Derivative Works thereof, that is intentionally 52 | * submitted to Licensor for inclusion in the Work by the copyright owner 53 | * or by an individual or Legal Entity authorized to submit on behalf of 54 | * the copyright owner. For the purposes of this definition, "submitted" 55 | * means any form of electronic, verbal, or written communication sent 56 | * to the Licensor or its representatives, including but not limited to 57 | * communication on electronic mailing lists, source code control systems, 58 | * and issue tracking systems that are managed by, or on behalf of, the 59 | * Licensor for the purpose of discussing and improving the Work, but 60 | * excluding communication that is conspicuously marked or otherwise 61 | * designated in writing by the copyright owner as "Not a Contribution." 62 | * 63 | * "Contributor" shall mean Licensor and any individual or Legal Entity 64 | * on behalf of whom a Contribution has been received by Licensor and 65 | * subsequently incorporated within the Work. 66 | * 67 | * 2. Grant of Copyright License. Subject to the terms and conditions of 68 | * this License, each Contributor hereby grants to You a perpetual, 69 | * worldwide, non-exclusive, no-charge, royalty-free, irrevocable 70 | * copyright license to reproduce, prepare Derivative Works of, 71 | * publicly display, publicly perform, sublicense, and distribute the 72 | * Work and such Derivative Works in Source or Object form. 73 | * 74 | * 3. Grant of Patent License. Subject to the terms and conditions of 75 | * this License, each Contributor hereby grants to You a perpetual, 76 | * worldwide, non-exclusive, no-charge, royalty-free, irrevocable 77 | * (except as stated in this section) patent license to make, have made, 78 | * use, offer to sell, sell, import, and otherwise transfer the Work, 79 | * where such license applies only to those patent claims licensable 80 | * by such Contributor that are necessarily infringed by their 81 | * Contribution(s) alone or by combination of their Contribution(s) 82 | * with the Work to which such Contribution(s) was submitted. If You 83 | * institute patent litigation against any entity (including a 84 | * cross-claim or counterclaim in a lawsuit) alleging that the Work 85 | * or a Contribution incorporated within the Work constitutes direct 86 | * or contributory patent infringement, then any patent licenses 87 | * granted to You under this License for that Work shall terminate 88 | * as of the date such litigation is filed. 89 | * 90 | * 4. Redistribution. You may reproduce and distribute copies of the 91 | * Work or Derivative Works thereof in any medium, with or without 92 | * modifications, and in Source or Object form, provided that You 93 | * meet the following conditions: 94 | * 95 | * (a) You must give any other recipients of the Work or 96 | * Derivative Works a copy of this License; and 97 | * 98 | * (b) You must cause any modified files to carry prominent notices 99 | * stating that You changed the files; and 100 | * 101 | * (c) You must retain, in the Source form of any Derivative Works 102 | * that You distribute, all copyright, patent, trademark, and 103 | * attribution notices from the Source form of the Work, 104 | * excluding those notices that do not pertain to any part of 105 | * the Derivative Works; and 106 | * 107 | * (d) If the Work includes a "NOTICE" text file as part of its 108 | * distribution, then any Derivative Works that You distribute must 109 | * include a readable copy of the attribution notices contained 110 | * within such NOTICE file, excluding those notices that do not 111 | * pertain to any part of the Derivative Works, in at least one 112 | * of the following places: within a NOTICE text file distributed 113 | * as part of the Derivative Works; within the Source form or 114 | * documentation, if provided along with the Derivative Works; or, 115 | * within a display generated by the Derivative Works, if and 116 | * wherever such third-party notices normally appear. The contents 117 | * of the NOTICE file are for informational purposes only and 118 | * do not modify the License. You may add Your own attribution 119 | * notices within Derivative Works that You distribute, alongside 120 | * or as an addendum to the NOTICE text from the Work, provided 121 | * that such additional attribution notices cannot be construed 122 | * as modifying the License. 123 | * 124 | * You may add Your own copyright statement to Your modifications and 125 | * may provide additional or different license terms and conditions 126 | * for use, reproduction, or distribution of Your modifications, or 127 | * for any such Derivative Works as a whole, provided Your use, 128 | * reproduction, and distribution of the Work otherwise complies with 129 | * the conditions stated in this License. 130 | * 131 | * 5. Submission of Contributions. Unless You explicitly state otherwise, 132 | * any Contribution intentionally submitted for inclusion in the Work 133 | * by You to the Licensor shall be under the terms and conditions of 134 | * this License, without any additional terms or conditions. 135 | * Notwithstanding the above, nothing herein shall supersede or modify 136 | * the terms of any separate license agreement you may have executed 137 | * with Licensor regarding such Contributions. 138 | * 139 | * 6. Trademarks. This License does not grant permission to use the trade 140 | * names, trademarks, service marks, or product names of the Licensor, 141 | * except as required for reasonable and customary use in describing the 142 | * origin of the Work and reproducing the content of the NOTICE file. 143 | * 144 | * 7. Disclaimer of Warranty. Unless required by applicable law or 145 | * agreed to in writing, Licensor provides the Work (and each 146 | * Contributor provides its Contributions) on an "AS IS" BASIS, 147 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 148 | * implied, including, without limitation, any warranties or conditions 149 | * of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 150 | * PARTICULAR PURPOSE. You are solely responsible for determining the 151 | * appropriateness of using or redistributing the Work and assume any 152 | * risks associated with Your exercise of permissions under this License. 153 | * 154 | * 8. Limitation of Liability. In no event and under no legal theory, 155 | * whether in tort (including negligence), contract, or otherwise, 156 | * unless required by applicable law (such as deliberate and grossly 157 | * negligent acts) or agreed to in writing, shall any Contributor be 158 | * liable to You for damages, including any direct, indirect, special, 159 | * incidental, or consequential damages of any character arising as a 160 | * result of this License or out of the use or inability to use the 161 | * Work (including but not limited to damages for loss of goodwill, 162 | * work stoppage, computer failure or malfunction, or any and all 163 | * other commercial damages or losses), even if such Contributor 164 | * has been advised of the possibility of such damages. 165 | * 166 | * 9. Accepting Warranty or Additional Liability. While redistributing 167 | * the Work or Derivative Works thereof, You may choose to offer, 168 | * and charge a fee for, acceptance of support, warranty, indemnity, 169 | * or other liability obligations and/or rights consistent with this 170 | * License. However, in accepting such obligations, You may act only 171 | * on Your own behalf and on Your sole responsibility, not on behalf 172 | * of any other Contributor, and only if You agree to indemnify, 173 | * defend, and hold each Contributor harmless for any liability 174 | * incurred by, or claims asserted against, such Contributor by reason 175 | * of your accepting any such warranty or additional liability. 176 | * 177 | * END OF TERMS AND CONDITIONS 178 | * 179 | * APPENDIX: How to apply the Apache License to your work. 180 | * 181 | * To apply the Apache License to your work, attach the following 182 | * boilerplate notice, with the fields enclosed by brackets "[]" 183 | * replaced with your own identifying information. (Don't include 184 | * the brackets!) The text should be enclosed in the appropriate 185 | * comment syntax for the file format. We also recommend that a 186 | * file or class name and description of purpose be included on the 187 | * same "printed page" as the copyright notice for easier 188 | * identification within third-party archives. 189 | * 190 | * Copyright [yyyy] [name of copyright owner] 191 | * 192 | * Licensed under the Apache License, Version 2.0 (the "License"); 193 | * you may not use this file except in compliance with the License. 194 | * You may obtain a copy of the License at 195 | * 196 | * http://www.apache.org/licenses/LICENSE-2.0 197 | * 198 | * Unless required by applicable law or agreed to in writing, software 199 | * distributed under the License is distributed on an "AS IS" BASIS, 200 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 201 | * See the License for the specific language governing permissions and 202 | * limitations under the License. 203 | */ 204 | 205 | --------------------------------------------------------------------------------