Javaの特定パッケージに入ってるClassをとる

2007/11/08 19:10

※ 商品のリンクをクリックして何かを購入すると私に少額の報酬が入ることがあります【広告表示】

Python温泉とかCross Community Conferenceとかのイベント参加した><

Teeda(S2)記事のムック頂いた><

とかいろいろ書かなきゃいけない事がスタックしてるんだけど、勢いで書いちゃえ。

ちょいと仕事でJava縛りになったりする(というかほとんどがそう)ので、JavaでもDjangoとかrhacoとかの気分で書きたいんですわ。

S2も相当楽にしてくれるんだけど、我々は大したものを作っていないので不要な抽象化とか、Javaの仕様に従ってるがための制限とかが我々を苦しめてくれます :(

なので、いずれはオレオレっちゃいたいと思ってるんだけど、それについてもいろいろな制限に苦しんじゃってたりします。

「パッケージ名なんて自由に決めさせる必要ないよねー。」と思って特定パッケージに属しているクラス一覧をとろうと思ったら、パッケージクラスにそんなメソッドが無くって慌てた。

java-ja で聞いたら、「クラスがあって初めてパッケージになるからねぇ」ということを教えてもらえた。

java-jaは暖かい :)

で、指定したパッケージ直下のクラス一覧をとるクラスを書いたよ。世の中に数人困っている人がいたので、汚いコードを晒すよ。単にデフォルトのクラスパスとJarの中からパッケージ名がマッチするクラスの名前を返すだけ。

汎用性とか阿呆らしいと思っているので目的に対してハードコードですが、おおよそのやり方として見れば全く役に立たない事も無いんじゃないかと…。 ノーテスト!インナークラスとか知らない><

  package org.jarts.core;

  import java.io.BufferedInputStream;
  import java.io.File;
  import java.io.FileInputStream;
  import java.io.FilenameFilter;
  import java.io.IOException;
  import java.util.ArrayList;
  import java.util.LinkedHashMap;
  import java.util.List;
  import java.util.Map;
  import java.util.Set;
  import java.util.jar.JarInputStream;
  import java.util.jar.JarEntry;

  public class AppClassLoader extends ClassLoader {
    static String DIR_SEPARATOR = File.separator;
    static String PATH_SEPARATOR =
    System.getProperty("path.separator");
    static String PACKAGE_SEPARATOR = "\\.";

    static String MODELS_PACKAGE = "models";
    static String VIEWS_PACKAGE = "views";

    @SuppressWarnings("unchecked")
    public Map<String, List<Class>> getAppModels(String[]
    applications) throws IOException, ClassNotFoundException {
      return getAppClass(applications, MODELS_PACKAGE);
    }

    @SuppressWarnings("unchecked")
    public Map<String, List<Class>> getAppViews(String[]
    applications) throws IOException, ClassNotFoundException {
      return getAppClass(applications, VIEWS_PACKAGE);
    }


    @SuppressWarnings("unchecked")
    public Map<String, List<Class>> getAppClass(String[]
    applications, String packageSuffix) throws IOException,
    ClassNotFoundException {
      Map<String, List<Class>> map = new LinkedHashMap<String,
      List<Class>>();
      for(String app: applications) {
        map.put(app, new ArrayList<Class>());
      }
      String pathes = System.getProperty("java.class.path");
      String[] pathList = pathes.split(PATH_SEPARATOR);
      for(String path: pathList) {
        if(path.endsWith(".jar") || path.endsWith(".zip")) {
          JarInputStream jis = null;
          try {
            jis = new JarInputStream(new
            BufferedInputStream(new FileInputStream(path)));
            JarEntry entry;
            while((entry = jis.getNextJarEntry()) != null) {
              String name = entry.getName();
              for(String app: applications) {
                String appmodeldir =
                app.replaceAll(PACKAGE_SEPARATOR, DIR_SEPARATOR) +
                DIR_SEPARATOR + packageSuffix;
                if(name.indexOf(appmodeldir) == 0) {
                  map.get(app).add(Class.forName(
                      name
                      .replaceAll(DIR_SEPARATOR,
                      PACKAGE_SEPARATOR)
                      .replaceAll(".class", "")
                      )
                    );
                }
              }
            }
          } finally {
            if(jis != null) jis.close();
          }
        } else {
          for(String app: applications) {
            String dir = path + DIR_SEPARATOR +
            app.replaceAll(PACKAGE_SEPARATOR, DIR_SEPARATOR) +
            File.separator + packageSuffix;
            try {
              File directory = new File(dir);
              File[] files = directory.listFiles(new
              ClassFilter(null));

              if(files != null) {
                for(File f: files) {
                  map.get(app).add(Class.forName(
                      f.getPath()
                      .replaceAll(path +
                      DIR_SEPARATOR, "")
                      .replaceAll(DIR_SEPARATOR,
                      PACKAGE_SEPARATOR)
                      .replaceAll(".class", "")
                  ));
                  System.out.println("found:" + app +
                  "->" + f.getPath()
                      .replaceAll(path +
                      DIR_SEPARATOR, "")
                      .replaceAll(DIR_SEPARATOR,
                      PACKAGE_SEPARATOR)
                      .replaceAll(".class", ""));

                }
              }
            } catch(Exception e) {}
          }
        }
      }
      return map;
    }

    @SuppressWarnings("unchecked")
    public static void main(String[] args) throws IOException,
    ClassNotFoundException {
      AppClassLoader l = new AppClassLoader();
      Map<String, List<Class>> modelMap = l.getAppModels(new
      String[]{"org.jarts.app.sample"});
      Set<String> appset = modelMap.keySet();
      for(String app: appset) {
        List<Class> app_class = modelMap.get(app);
        for(Class k: app_class) {
          System.out.println(app);
          System.out.println("  :" + k);
        }
      }
    }
  }

  class ClassFilter implements FilenameFilter {
    String extension = ".class";
    public ClassFilter(String extension) {
      if(extension != null) this.extension = extension;
    }
    public boolean accept(File dir, String name){
      return name.toLowerCase().endsWith(extension);
    }
  }
2007/11/08 19:56 by ヨシオリ
generics の部分が悲しいことになってますよ><
2007/11/09 11:01 by makoto
おっと、HTML直書きがばれた><
さーんくす。

Prev Entry

Next Entry