LoginSignup
3
6

More than 5 years have passed since last update.

パッケージ配下のクラス一覧を再帰的に探索したい

Posted at

しがないSIerのシステムエンジニアとして日銭を稼ぐ毎日を送っているのですが、「作成したJavaクラスをパッケージ名を付与して一覧化する」という設計書(?)を作る機会がここ最近ありました。作ったJavaクラスの数からいって手作業はめんどくさいというか無謀な話。そこで「パッケージを再帰的に探索して、パッケージ名を付与したクラス一覧を出力する」プログラムを書くことにしました。以下はそのサンプルです。

image

たとえば上記のようなパッケージ構造のプロジェクトがあったとして、"jp.co"配下に属するクラスをパッケージ名付きで出力するプログラムは次のようになるはずです。

import java.io.File;
import java.io.IOException;
import java.net.URISyntaxException;
import java.net.URL;
import java.nio.file.FileVisitResult;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.SimpleFileVisitor;
import java.nio.file.attribute.BasicFileAttributes;
import java.util.Enumeration;
import java.util.PriorityQueue;

public class Main {

    private static final String PACKAGE_SEPARATOR = ".";

    private static final String CLASS_SUFFIX = ".class";

    public static void main(String[] args) throws IOException, URISyntaxException {
        // クラスローダを利用して、パッケージ配下のリソースを取得する。
        String rootPackageName = "jp.co".replace(PACKAGE_SEPARATOR, File.separator);
        ClassLoader classLoader = ClassLoader.getSystemClassLoader();
        Enumeration<URL> rootUrls = classLoader.getResources(rootPackageName);

        // ディレクトリを再帰的に探索して、".class"で終わるファイルを見つけた場合は
        // 文字列を整形したのちにリストへ格納しておく。
        PriorityQueue<String> classNames = new PriorityQueue();
        while (rootUrls.hasMoreElements()) {
            URL rootUrl = rootUrls.nextElement();
            Path rootPath = Paths.get(rootUrl.toURI());

            Files.walkFileTree(rootPath, new SimpleFileVisitor<Path>(){
                @Override
                public FileVisitResult visitFile(Path path, BasicFileAttributes attrs) throws IOException {
                    String pathName = path.toString();
                    if (pathName.endsWith(CLASS_SUFFIX)) {
                        int beginIndex = pathName.lastIndexOf(rootPackageName);
                        int endIndex = pathName.lastIndexOf(CLASS_SUFFIX);
                        String className = pathName.substring(beginIndex, endIndex)
                                                   .replace(File.separator, PACKAGE_SEPARATOR);

                        classNames.add(className);
                    }

                    return super.visitFile(path, attrs);
                }
            });
        }

        // 見つけ出したクラス名の一覧を出力する。
        for (String className : classNames) {
            System.out.println(className);
        }

        /*
        jp.co.first.ClassA
        jp.co.first.ClassB
        jp.co.first.sub.ClassC
        jp.co.first.sub.ClassD
        jp.co.second.ClassE
        jp.co.second.ClassF
        */
    }
}

3
6
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
6