Created
April 1, 2011 02:03
-
-
Save monzou/897622 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package scripts; | |
import java.io.File; | |
import java.io.FileNotFoundException; | |
import java.io.FileOutputStream; | |
import java.io.IOException; | |
import java.lang.reflect.Method; | |
import java.util.List; | |
import java.util.Set; | |
import java.util.regex.Matcher; | |
import java.util.regex.Pattern; | |
import javax.tools.DiagnosticCollector; | |
import javax.tools.JavaCompiler; | |
import javax.tools.JavaFileManager; | |
import javax.tools.JavaFileObject; | |
import javax.tools.JavaFileObject.Kind; | |
import javax.tools.StandardLocation; | |
import javax.tools.ToolProvider; | |
import net.arnx.jsonic.JSON; | |
import net.arnx.jsonic.JSONException; | |
import org.apache.commons.io.FileUtils; | |
import org.apache.commons.lang.ArrayUtils; | |
import org.apache.commons.lang.StringUtils; | |
import com.google.common.base.Function; | |
import com.google.common.base.Joiner; | |
import com.google.common.collect.Collections2; | |
import com.google.common.collect.Lists; | |
import com.google.common.collect.Sets; | |
/** | |
* ClassJSONWriter | |
* | |
* @author monzou | |
*/ | |
public class ClassJSONWriter { | |
public static void main(String[] args) throws IOException, ClassNotFoundException { | |
String dir = (String) args[0]; | |
String[] packages = (String[]) ArrayUtils.subarray(args, 1, args.length); | |
System.out.println("output directory=" + dir); | |
System.out.println("target packages=" + StringUtils.join(packages, ", ")); | |
new ClassJSONWriter(dir).write(dir, packages); | |
} | |
private static final String JSON_EXTENSION = "json"; | |
private final JavaClassFinder finder; | |
ClassJSONWriter(String dir) { | |
finder = new JavaClassFinder(); | |
} | |
void write(String dir, String... packages) throws IOException, ClassNotFoundException { | |
JSONFileWriter writer = new JSONFileWriter(dir); | |
writer.prepareDirectory(); | |
for (String pkg : packages) { | |
for (Class<?> clazz : finder.findAll(pkg, true)) { | |
System.out.println(clazz.getName()); | |
writer.write(clazz); | |
} | |
} | |
} | |
private static class JSONFileWriter { | |
private final ClassBeanConverter converter; | |
private File directory; | |
JSONFileWriter(String dir) { | |
converter = new ClassBeanConverter(); | |
directory = new File(dir); | |
} | |
void write(Class<?> clazz) throws IOException { | |
ClassBean bean = converter.toBean(clazz); | |
String path = String.format("%s/%s.%s", directory.getPath(), bean.className, JSON_EXTENSION); | |
try { | |
FileOutputStream out = new FileOutputStream(new File(path)); | |
JSON.encode(bean, out); | |
} catch (FileNotFoundException e) { | |
throw new RuntimeException(e); | |
} catch (JSONException e) { | |
throw new RuntimeException(e); | |
} | |
} | |
boolean prepareDirectory() throws IOException { | |
if (directory.exists()) { | |
cleanDirectory(); | |
return false; | |
} else { | |
return directory.mkdirs(); | |
} | |
} | |
void cleanDirectory() throws IOException { | |
if (directory.exists()) { | |
FileUtils.cleanDirectory(directory); | |
} | |
} | |
} | |
private static class JavaClassFinder { | |
public List<Class<?>> findAll(String pkg, boolean recursive) throws IOException, ClassNotFoundException { | |
String regex = String.format(".*(%s.*)\\.class", pkg.replaceAll("\\.", "/")); | |
System.err.println(regex); | |
Pattern pattern = Pattern.compile(regex); | |
JavaCompiler compiler = ToolProvider.getSystemJavaCompiler(); | |
JavaFileManager fm = compiler.getStandardFileManager(new DiagnosticCollector<JavaFileObject>(), null, null); | |
Set<Kind> kinds = Sets.newHashSet(JavaFileObject.Kind.CLASS); | |
List<Class<?>> classes = Lists.newArrayList(); | |
for (JavaFileObject f : fm.list(StandardLocation.CLASS_PATH, pkg, kinds, recursive)) { | |
String path = f.toUri().getPath(); | |
if (isApplicable(path)) { | |
Matcher matcher = pattern.matcher(path); | |
if (matcher.matches()) { | |
classes.add(Class.forName(matcher.group(1).replaceAll("/", "."))); | |
} | |
} | |
} | |
return classes; | |
} | |
private boolean isApplicable(String path) { | |
if (path.contains("$") || path.contains("package-info") || path.contains("Test")) { | |
// Proxy, package-info, Test は除外 | |
return false; | |
} | |
return true; | |
} | |
} | |
private static class ClassBeanConverter { | |
private static final Function<Class<?>, String> CLASS_NAME_RESOLVER = new Function<Class<?>, String>() { | |
/** {@inheritDoc} */ | |
@Override | |
public String apply(Class<?> input) { | |
return input.getName(); | |
} | |
}; | |
public ClassBean toBean(Class<?> clazz) { | |
ClassBean bean = new ClassBean(); | |
bean.className = clazz.getSimpleName(); | |
bean.packageName = clazz.getPackage().getName(); | |
bean.methods = Lists.newArrayList(); | |
for (Method method : clazz.getDeclaredMethods()) { | |
if (ignoreMethod(method)) { | |
continue; | |
} | |
MethodBean mb = new MethodBean(); | |
mb.methodName = method.getName(); | |
mb.returnType = method.getReturnType().getName(); | |
mb.argTypes = joinClassNames(method.getParameterTypes()); | |
mb.throwables = joinClassNames(method.getExceptionTypes()); | |
bean.methods.add(mb); | |
} | |
return bean; | |
} | |
private String joinClassNames(Class<?>[] classes) { | |
Joiner joiner = Joiner.on(", "); | |
return joiner.join(Collections2.transform(Lists.newArrayList(classes), CLASS_NAME_RESOLVER)); | |
} | |
private boolean ignoreMethod(Method method) { | |
if (method.getDeclaringClass() == Object.class) { | |
return true; | |
} | |
return method.isSynthetic() || method.isBridge(); | |
} | |
} | |
public static class ClassBean { | |
public String packageName; | |
public String className; | |
public List<MethodBean> methods; | |
} | |
public static class MethodBean { | |
public String methodName; | |
public String argTypes; | |
public String returnType; | |
public String throwables; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment