mirror of
https://github.com/Eaglercraft-TeaVM-Fork/eagler-teavm.git
synced 2024-12-22 16:14:10 -08:00
Adds utility that checks which classes are implemented in JCL emulation
and produces JSON report
This commit is contained in:
parent
d714e880d3
commit
a29318668e
|
@ -58,6 +58,34 @@
|
|||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.codehaus.mojo</groupId>
|
||||
<artifactId>exec-maven-plugin</artifactId>
|
||||
<version>1.2.1</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<goals>
|
||||
<goal>java</goal>
|
||||
</goals>
|
||||
<phase>process-test-classes</phase>
|
||||
</execution>
|
||||
</executions>
|
||||
<configuration>
|
||||
<mainClass>org.teavm.classlib.impl.JCLComparisonBuilder</mainClass>
|
||||
<arguments>
|
||||
<argument>java.lang</argument>
|
||||
<argument>java.lang.annotation</argument>
|
||||
<argument>java.lang.reflect</argument>
|
||||
<argument>java.io</argument>
|
||||
<argument>java.net</argument>
|
||||
<argument>java.util</argument>
|
||||
<argument>java.util.logging</argument>
|
||||
<argument>java.util.concurrent</argument>
|
||||
<argument>-output</argument>
|
||||
<argument>${project.build.directory}/jcl-report/jcl-comparision.json</argument>
|
||||
</arguments>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
<pluginManagement>
|
||||
<plugins>
|
||||
|
|
|
@ -0,0 +1,121 @@
|
|||
/*
|
||||
* Copyright 2014 Alexey Andreev.
|
||||
*
|
||||
* 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 org.teavm.classlib.impl;
|
||||
|
||||
import java.io.*;
|
||||
import java.net.URL;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import java.util.jar.JarEntry;
|
||||
import java.util.jar.JarInputStream;
|
||||
import org.objectweb.asm.ClassReader;
|
||||
import org.teavm.parsing.ClasspathClassHolderSource;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Alexey Andreev
|
||||
*/
|
||||
public class JCLComparisonBuilder {
|
||||
private static final String JAR_PREFIX = "jar:file:";
|
||||
private static final String JAR_SUFFIX = "!/java/lang/Object.class";
|
||||
private static final String CLASS_SUFFIX = ".class";
|
||||
private Set<String> packages = new HashSet<>();
|
||||
private ClassLoader classLoader = JCLComparisonBuilder.class.getClassLoader();
|
||||
private JCLComparisonVisitor visitor;
|
||||
private String outputFile;
|
||||
|
||||
public ClassLoader getClassLoader() {
|
||||
return classLoader;
|
||||
}
|
||||
|
||||
public void setClassLoader(ClassLoader classLoader) {
|
||||
this.classLoader = classLoader;
|
||||
}
|
||||
|
||||
public Set<String> getPackages() {
|
||||
return packages;
|
||||
}
|
||||
|
||||
public String getOutputFile() {
|
||||
return outputFile;
|
||||
}
|
||||
|
||||
public void setOutputFile(String outputFile) {
|
||||
this.outputFile = outputFile;
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws IOException {
|
||||
if (args.length == 0) {
|
||||
System.err.println("Usage: package.name [package.name2 ...]");
|
||||
System.exit(1);
|
||||
}
|
||||
JCLComparisonBuilder builder = new JCLComparisonBuilder();
|
||||
|
||||
for (int i = 0; i < args.length; ++i) {
|
||||
if (args[i].equals("-output")) {
|
||||
builder.setOutputFile(args[++i]);
|
||||
} else {
|
||||
builder.getPackages().add(args[i].replace('.', '/'));
|
||||
}
|
||||
}
|
||||
|
||||
builder.buildComparisonReport();
|
||||
}
|
||||
|
||||
public void buildComparisonReport() throws IOException {
|
||||
URL url = classLoader.getResource("java/lang/Object" + CLASS_SUFFIX);
|
||||
String path = url.toString();
|
||||
if (!path.startsWith(JAR_PREFIX) || !path.endsWith(JAR_SUFFIX)) {
|
||||
throw new RuntimeException("Can't find JCL classes");
|
||||
}
|
||||
ClasspathClassHolderSource classSource = new ClasspathClassHolderSource(classLoader);
|
||||
path = path.substring(JAR_PREFIX.length(), path.length() - JAR_SUFFIX.length());
|
||||
File outDir = new File(outputFile).getParentFile();
|
||||
if (!outDir.exists()) {
|
||||
outDir.mkdirs();
|
||||
}
|
||||
try (JarInputStream jar = new JarInputStream(new FileInputStream(path));
|
||||
PrintStream out = new PrintStream(new FileOutputStream(outputFile))) {
|
||||
out.println("{");
|
||||
visitor = new JCLComparisonVisitor(classSource, out);
|
||||
while (true) {
|
||||
JarEntry entry = jar.getNextJarEntry();
|
||||
if (entry == null) {
|
||||
break;
|
||||
}
|
||||
if (validateName(entry.getName())) {
|
||||
compareClass(jar);
|
||||
}
|
||||
jar.closeEntry();
|
||||
}
|
||||
out.println();
|
||||
out.println("}");
|
||||
}
|
||||
}
|
||||
|
||||
private boolean validateName(String name) {
|
||||
if (!name.endsWith(CLASS_SUFFIX)) {
|
||||
return false;
|
||||
}
|
||||
int slashIndex = name.lastIndexOf('/');
|
||||
return packages.contains(name.substring(0, slashIndex));
|
||||
}
|
||||
|
||||
private void compareClass(InputStream input) throws IOException {
|
||||
ClassReader reader = new ClassReader(input);
|
||||
reader.accept(visitor, 0);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,143 @@
|
|||
/*
|
||||
* Copyright 2014 Alexey Andreev.
|
||||
*
|
||||
* 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 org.teavm.classlib.impl;
|
||||
|
||||
import java.io.PrintStream;
|
||||
import org.objectweb.asm.*;
|
||||
import org.teavm.model.*;
|
||||
import org.teavm.model.ClassReader;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Alexey Andreev
|
||||
*/
|
||||
class JCLComparisonVisitor implements ClassVisitor {
|
||||
private PrintStream out;
|
||||
private ClassReaderSource classSource;
|
||||
private boolean first = true;
|
||||
private boolean firstItem;
|
||||
private boolean pass;
|
||||
private boolean ended;
|
||||
private ClassReader classReader;
|
||||
|
||||
public JCLComparisonVisitor(ClassReaderSource classSource, PrintStream out) {
|
||||
this.classSource = classSource;
|
||||
this.out = out;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) {
|
||||
if ((access & Opcodes.ACC_PUBLIC) == 0) {
|
||||
return;
|
||||
}
|
||||
String javaName = name.replace('/', '.');
|
||||
if (!first) {
|
||||
out.println(",");
|
||||
}
|
||||
first = false;
|
||||
out.println(" \"" + javaName + "\" : {");
|
||||
classReader = classSource.get(javaName);
|
||||
if (classReader == null) {
|
||||
out.println(" \"implemented\" : false");
|
||||
pass = true;
|
||||
} else {
|
||||
out.println(" \"implemented\" : true,");
|
||||
out.println(" \"items\" : [");
|
||||
pass = false;
|
||||
}
|
||||
ended = false;
|
||||
firstItem = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public FieldVisitor visitField(int access, String name, String desc, String signature, Object value) {
|
||||
if (pass) {
|
||||
return null;
|
||||
}
|
||||
if ((access & (Opcodes.ACC_PUBLIC | Opcodes.ACC_PROTECTED)) == 0) {
|
||||
return null;
|
||||
}
|
||||
if (!firstItem) {
|
||||
out.println(",");
|
||||
}
|
||||
firstItem = false;
|
||||
out.println(" {");
|
||||
out.println(" \"type\" : \"field\",");
|
||||
out.println(" \"name\" : \"" + name + "\",");
|
||||
out.println(" \"descriptor\" : \"" + desc + "\",");
|
||||
FieldReader field = classReader.getField(name);
|
||||
out.println(" \"implemented\" : \"" + (field != null ? "true" : "false") + "\",");
|
||||
out.print(" }");
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) {
|
||||
if (pass) {
|
||||
return null;
|
||||
}
|
||||
if ((access & (Opcodes.ACC_PUBLIC | Opcodes.ACC_PROTECTED)) == 0) {
|
||||
return null;
|
||||
}
|
||||
if (!firstItem) {
|
||||
out.println(",");
|
||||
}
|
||||
firstItem = false;
|
||||
out.println(" {");
|
||||
out.println(" \"type\" : \"method\",");
|
||||
out.println(" \"name\" : \"" + name + "\",");
|
||||
out.println(" \"descriptor\" : \"" + desc + "\",");
|
||||
MethodReader method = classReader.getMethod(MethodDescriptor.parse(name + desc));
|
||||
out.println(" \"implemented\" : \"" + (method != null ? "true" : "false") + "\",");
|
||||
out.print(" }");
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitSource(String source, String debug) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitOuterClass(String owner, String name, String desc) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public AnnotationVisitor visitAnnotation(String desc, boolean visible) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitAttribute(Attribute attr) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitInnerClass(String name, String outerName, String innerName, int access) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitEnd() {
|
||||
if (!ended) {
|
||||
if (!pass) {
|
||||
if (!firstItem) {
|
||||
out.println();
|
||||
}
|
||||
out.println(" ]");
|
||||
}
|
||||
out.print(" }");
|
||||
ended = true;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -93,7 +93,7 @@ public class ClasspathResourceMapper implements Mapper<String, ClassHolder> {
|
|||
if (name.startsWith(transformation.packageName)) {
|
||||
int index = name.lastIndexOf('.');
|
||||
String className = name.substring(index + 1);
|
||||
String packageName = name.substring(0, index);
|
||||
String packageName = index > 0 ? name.substring(0, index) : "";
|
||||
ClassHolder classHolder = innerMapper.map(transformation.packagePrefix + packageName +
|
||||
"." + transformation.classPrefix + className);
|
||||
if (classHolder != null) {
|
||||
|
|
Loading…
Reference in New Issue
Block a user