All Downloads are FREE. Search and download functionalities are using the official Maven repository.

nablarch.core.util.ClassTraversal Maven / Gradle / Ivy

The newest version!
/*
 * 取り込み元
 *    ライブラリ名:     S2Util
 *    クラス名:         org.seasar.util.io.ClassTraversalUtil
 *    ソースリポジトリ: https://github.com/seasarorg/s2util/blob/master/s2util/src/main/java/org/seasar/util/io/ClassTraversalUtil.java
 *
 * 上記ファイルを取り込み、修正を加えた。
 *
 * Copyright 2016 TIS Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package nablarch.core.util;

import java.io.File;
import java.util.Enumeration;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;

/**
 * クラスに対して処理を行うためのユーティリティクラス。
 *
 * @author koichik
 */
public final class ClassTraversal {

    /** クラスファイルの拡張子 */
    private static final String CLASS_EXTENSION = ".class";

    /** warファイルの拡張子 */
    private static final String WAR_FILE_EXTENSION = ".war";

    /** war内にクラスが置かれるディレクトリ */
    private static final String WEB_INF_CLASSES_PATH = "WEB-INF/classes/";

    /**
     * 隠蔽コンストラクタ
     */
    private ClassTraversal() {
    }

    /**
     * ファイルシステム配下の指定されたルートパッケージ以下のクラスを処理する。
     *
     * @param rootDir ルートディレクトリ
     * @param rootPackage ルートパッケージ
     * @param handler クラスを処理するハンドラ
     */
    public static void forEach(
            final File rootDir, final String rootPackage, final ClassHandler handler) {
        final File packageDir = getPackageDir(rootDir, rootPackage);
        if (packageDir.exists()) {
            traverseFileSystem(packageDir, rootPackage, handler);
        }
    }

    /**
     * jarファイルに含まれるクラスを処理する。
     * 

* 指定されたjarファイルの拡張子が{@code war}の場合は、 jarファイル内のエントリのうち、 * 接頭辞{@code WEB-INF/classes}で始まるパスを持つクラスが対象となる。 * クラスを処理するハンドラには、接頭辞を除くエントリ名が渡される。 * 例えばjarファイル内に{@code /WEB-INF/classes/ccc/ddd/Eee.class}というクラスファイルが存在すると、 * ハンドラにはパッケージ名{@code ccc.ddd}およびクラス名{@code Eee}が渡される。 *

* * @param jarFile Jarファイル * @param handler クラスを処理するハンドラ */ public static void forEach(final JarFile jarFile, final ClassHandler handler) { if (jarFile.getName() .toLowerCase() .endsWith(WAR_FILE_EXTENSION)) { forEach(jarFile, WEB_INF_CLASSES_PATH, handler); } else { forEach(jarFile, "", handler); } } /** * jarファイルに含まれるクラスを処理する。 *

* jarファイル内のエントリのうち、接頭辞で始まるパスを持つクラスが処理対象となる。 *

* クラスを処理するハンドラには、接頭辞を除くエントリ名が渡される。 * 例えば接頭辞が {@code /aaa/bbb/}で、jarファイル内に {@code /aaa/bbb/ccc/ddd/Eee.class}というクラスファイルが存在すると、 * ハンドラには パッケージ名{@code ccc.ddd}およびクラス名{@code Eee}が渡される。 *

* * @param jarFile Jarファイル * @param prefix トラバースするリソースの名前が含む接頭辞。スラッシュ('/')で終了していなければなりません。 * @param handler クラスを処理するハンドラ */ public static void forEach(final JarFile jarFile, final String prefix, final ClassHandler handler) { final int startPos = prefix.length(); @SuppressWarnings("rawtypes") final Enumeration enumeration = jarFile.entries(); while (enumeration.hasMoreElements()) { final JarEntry entry = (JarEntry) enumeration.nextElement(); final String entryName = entry.getName() .replace('\\', '/'); if (entryName.startsWith(prefix) && entryName.endsWith(CLASS_EXTENSION)) { final String className = entryName.substring(startPos, entryName.length() - CLASS_EXTENSION.length()) .replace('/', '.'); final int pos = className.lastIndexOf('.'); final String packageName = (pos == -1) ? null : className .substring(0, pos); final String shortClassName = (pos == -1) ? className : className.substring(pos + 1); handler.process(packageName, shortClassName); } } } /** * ファイルシステム上のクラスファイルを処理する。 *

* サブパッケージが存在する場合には、再帰的に処理を繰り返す。 * * @param dir ディレクトリ * @param packageName パッケージ名 * @param handler クラスを処理するハンドラ */ private static void traverseFileSystem(final File dir, final String packageName, final ClassHandler handler) { final File[] files = dir.listFiles(); for (final File file : files) { final String fileName = file.getName(); if (file.isDirectory()) { traverseFileSystem(file, packageName == null ? fileName : packageName + '.' + fileName, handler); } else if (fileName.endsWith(".class")) { final String shortClassName = fileName.substring(0, fileName .length() - CLASS_EXTENSION.length()); handler.process(packageName, shortClassName); } } } /** * パッケージディレクトリを取得する。 * * @param rootDir ルートディレクトリ * @param rootPackage ルートパッケージ * @return File ルートパッケージを示す{@link File}オブジェクト */ private static File getPackageDir(final File rootDir, final String rootPackage) { File packageDir = rootDir; if (rootPackage != null) { final String[] names = rootPackage.split("\\."); for (String name : names) { packageDir = new File(packageDir, name); } } return packageDir; } /** * クラスを横断して処理するためのハンドラインタフェース。 * * @author koichik */ public interface ClassHandler { /** * クラスを処理します。 * * @param packageName パッケージ名 * @param className クラス名 */ void process(String packageName, String className); } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy