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);
  }
}


Feedbacks

Tags