ctree:クラスパス中のクラス一覧、衝突検出、ツリー構造化
※弊社製オープンソースソフトはオープンソースソフトウェアとしてまとめているので参照されたい。
このライブラリは、かなり特殊な用途である。行うことは、
- 実行中のjarファイルなりフォルダ(Eclipse開発環境等の場合)の中にあるクラスの一覧を取得する。
- もしくは、実行中の全クラスパスの中の全クラスの一覧を取得する。
- 二番目の方法で取得した場合には、クラスの衝突が無いかをチェックする。
- クラス一覧ををツリー構造に構成する。
このライブラリの用途としては、もちろんクラスの衝突を検出することである。ありとあらゆるライブラリjarを利用すると、その中には衝突してしまっているものもある。これを検出することである。
もう一つは、プログラムの実行中にLog4jの設定を変更してログ対象クラスを変更したかったことだ。基本的にLog4jの設定は、最も簡単なcommons-logging + Log4jの使い方にも書いたことだが、プログラム実行中に変更することができる。
わざわざ、実行を停止し、プロパティファイルを書き直し、再実行するなどという必要はない。
この目的のため、単にクラス名をクリックすれば、そのクラス名をLog4jのプロパティファイルに書き込むというシステムになっているのだが、もちろんその分のコードはctreeには含まれない。基本的にはあくまでクラス一覧を取得することである。
githubはhttps://github.com/ysugimura/ctreeになる。
Mavenリポジトリはhttps://ysugimura.github.io/mavenにある。
以下は、githubにあるサンプルである。
Sample1
以下はSample1が含まれるフォルダあるいはjarファイルにあるクラス一覧を表示する。
public class Sample1 {
public static void main(String[]args) throws IOException {
ClassNames classNames = ClassNames.loadFor(Sample1.class);
classNames.getNameSet().forEach(System.out::println);
}
}
実行結果は以下である。
com.cm55.ctree.ClassNames
com.cm55.ctree.sample.Sample3
com.cm55.ctree.sample.Sample2
com.cm55.ctree.sample.TreeAdapterImpl
com.cm55.ctree.ClassPathLocator
com.cm55.ctree.sample.JavaClassTree$PackageNode
com.cm55.ctree.sample.JavaClassTree$ClassNode
....
Sample2
以下はSample2が含まれるクラスローダ内にあるすべてのクラスの一覧を表示し、さらに衝突をチェックする。
※注意事項:これはJava9では動作しない。Java9のシステムクラスローダがURLClassLoaderでは無いからだ。Java8でのみ動作する。Java9以降での対処方法は現在のところ不明。
public class Sample2 {
public static void main(String[]args) throws IOException {
List<ClassNames>classNamesList = ClassNames.loadAllFor(Sample2.class);
classNamesList.forEach(classNames-> {
System.out.println(classNames.getFile());
classNames.getNameSet().forEach(n-> System.out.println(" " + n));
});
System.out.println("conflicts....");
System.out.println(ClassNamesBinder.checkConflict(classNamesList));
}
}
クラスローダにあるすべてのJar及びフォルダなので、当然のことながら、Javaそれ自体のライブラリも含み、出力は膨大なものになる。また、この例では衝突が無いのだが、あればconflicts….の後に出力されるはず。
C:\Program Files\Java\jdk1.8.0_111\jre\lib\resources.jar
C:\Program Files\Java\jdk1.8.0_111\jre\lib\rt.jar
com.sun.xml.internal.bind.v2.runtime.unmarshaller.Base64Data
com.sun.org.apache.xml.internal.security.transforms.implementations.TransformC14N11
com.sun.xml.internal.ws.encoding.fastinfoset.FastInfosetStreamSOAPCodec
sun.text.normalizer.NormalizerImpl$NormTrieImpl
com.sun.jmx.remote.internal.NotificationBuffer
sun.tools.jar.resources.jar_sv
com.sun.java.swing.plaf.motif.resources.motif
com.sun.xml.internal.stream.dtd.nonvalidating.XMLNotationDecl
javax.print.attribute.standard.OutputDeviceAssigned
sun.awt.AWTAccessor$MenuAccessor
sun.rmi.server.ActivatableRef
..........
com.cm55.ctree.sample.package-info
com.cm55.ctree.ClassNamesBinderTest
com.cm55.ctree.package-info
conflicts....
Sample3
今度は、このJarファイルあるいはフォルダ(Eclipse開発環境等の場合)の全クラスについて、それを木構造化してみる。
これには、木構造を表すノードと、ノード作成用のアダプタ必要になるが、それらはここでは示さない。
public class Sample3 {
public static void main(String[]args) throws IOException {
ClassNames classNames = ClassNames.loadFor(Sample1.class);
PackageNode root = TreeCreator.createTree(classNames, new TreeAdapterImpl());
System.out.println(JavaClassTree.toString(root));
}
}
木構造に従ってインデントした結果の出力は以下のようになる。
com
cm55
ctree
ClassNames
sample
Sample3
Sample2
TreeAdapterImpl
JavaClassTree$PackageNode
JavaClassTree$ClassNode
Sample1
JavaClassTree$Node
JavaClassTree
package-info
ClassPathLocator
ClassNamesBinder
TreeAdapter
TreeCreator
ClassNamesBinderTest
package-info
package-info