Example #1
0
 // Stream of classNames
 private static Stream<String> zipContents(Path p) throws IOException {
   JarFile jarFile = new JarFile(p.toFile());
   return jarFile
       .stream()
       .map(entry -> entry.toString())
       .filter(path -> path.endsWith(".class"))
       .map(Scanner::toClassName)
       .onClose(
           () -> {
             try {
               jarFile.close();
             } catch (IOException e) {
             }
           });
 }
Example #2
0
  /**
   * JARファイルから、指定されたパッケージ配下にある全クラスを検索します。
   *
   * <p>サブパッケージも全て検索します。
   *
   * @param file JARファイル
   * @param packageName パッケージ名
   * @return 検索されたクラスの完全修飾名(バイナリー名)のセット
   * @throws IOException JARファイルの読み込みに失敗した場合
   */
  public static Set<String> searchClassInJar(File file, String packageName) throws IOException {
    try (JarFile jar = new JarFile(file)) {
      /*
       * なお、「クラスの完全修飾名」とは、以下を全て満たすものです。
       * 1. 拡張子が".class"である。
       * 2. "package-info.class"ではない。
       * 動作確認は、searchClassInJar(new File("【mavenリポジトリ】", "lombok-1.16.6.jar"), "lombok")でやってみてください。
       */

      //			return jar.stream()                                     // JarEntryのストリームを取得
      //				.map(jarEntry -> jarEntry.getName())                // entry中のファイル名を取得
      //				.filter(str -> str.endsWith(".class"))              // 拡張子が.classのものを選択
      //				.filter(str -> !str.endsWith("package-info.class")) // package-info.classではないものを選択
      //				.filter(str -> str.startsWith(packageName + "/"))   // 引数パッケージから始まるものを選択
      //				.map(str -> str.replace("/", "."))                  // "/"を"."に変換
      //				.map(str -> str.substring(0, str.indexOf(".class")))// 先頭から”.classよリ前を取得
      //				.collect(Collectors.toSet());                       // Setに集計

      String suffix = ".class";
      String prefix =
          packageName.replace('.', '/') + "/"; // packageName中のドットをスラッシュに置換しておかないと、filterでヒットしません。
      // "lombok.launch"等のテストケースが漏れてましたね。
      // また、streamに依存しない処理は、予め済ませておきましょう。速度が向上します。

      return jar.stream()
          .map(JarEntry::getName)
          .filter(
              name ->
                  name.startsWith(prefix) // 最も絞り込みが期待できる評価式から実行しましょう
                      && name.endsWith(suffix) // streamメソッドの数を減らすのが容易である場合は、減らした方が速度が向上します。
                      && !name.endsWith(
                          "package-info.class")) // 可読性と相談しながら、streamメソッドの数を減らすことを検討してください。
          .map(
              name ->
                  name.substring(
                          0,
                          name.length()
                              - suffix.length()) // 文字列の長さが変化してなく、かつ末尾がsuffixであることは、保証されています。
                      .replace('/', '.')) // replace(CharSequence,CharSequence)よりも、こっちの方が高速です。
          .collect(Collectors.toSet());
    }
  }