mirror of
https://github.com/Eaglercraft-TeaVM-Fork/eagler-teavm.git
synced 2024-12-22 08:14:09 -08:00
Fix bootstrap mode
This commit is contained in:
parent
b754c7401e
commit
48227b24a0
|
@ -0,0 +1,20 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2019 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;
|
||||||
|
|
||||||
|
public interface ServiceLoaderFilter {
|
||||||
|
boolean apply(String serviceType, String implementationType);
|
||||||
|
}
|
|
@ -0,0 +1,24 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2019 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;
|
||||||
|
|
||||||
|
import org.teavm.model.ClassReaderSource;
|
||||||
|
|
||||||
|
public interface ServiceLoaderFilterContext {
|
||||||
|
ClassLoader getClassLoader();
|
||||||
|
|
||||||
|
ClassReaderSource getClassSource();
|
||||||
|
}
|
|
@ -19,17 +19,21 @@ import java.io.BufferedReader;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.io.InputStreamReader;
|
import java.io.InputStreamReader;
|
||||||
|
import java.lang.reflect.InvocationTargetException;
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Enumeration;
|
import java.util.Enumeration;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
import java.util.LinkedHashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.ServiceLoader;
|
import java.util.ServiceLoader;
|
||||||
|
import java.util.Set;
|
||||||
import org.teavm.backend.javascript.codegen.SourceWriter;
|
import org.teavm.backend.javascript.codegen.SourceWriter;
|
||||||
import org.teavm.backend.javascript.spi.Generator;
|
import org.teavm.backend.javascript.spi.Generator;
|
||||||
import org.teavm.backend.javascript.spi.GeneratorContext;
|
import org.teavm.backend.javascript.spi.GeneratorContext;
|
||||||
|
import org.teavm.classlib.ServiceLoaderFilter;
|
||||||
import org.teavm.dependency.AbstractDependencyListener;
|
import org.teavm.dependency.AbstractDependencyListener;
|
||||||
import org.teavm.dependency.DependencyAgent;
|
import org.teavm.dependency.DependencyAgent;
|
||||||
import org.teavm.dependency.DependencyNode;
|
import org.teavm.dependency.DependencyNode;
|
||||||
|
@ -85,8 +89,48 @@ public class ServiceLoaderSupport extends AbstractDependencyListener implements
|
||||||
writer.append("return result;").softNewLine();
|
writer.append("return result;").softNewLine();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void parseServiceFile(DependencyAgent agent, DependencyNode targetNode, String service,
|
@Override
|
||||||
InputStream input, CallLocation location) throws IOException {
|
public void methodReached(DependencyAgent agent, MethodDependency method) {
|
||||||
|
MethodReference ref = method.getReference();
|
||||||
|
if (ref.getClassName().equals("java.util.ServiceLoader") && ref.getName().equals("loadServices")) {
|
||||||
|
List<ServiceLoaderFilter> filters = getFilters(agent);
|
||||||
|
method.getResult().propagate(agent.getType("[Ljava/lang/Object;"));
|
||||||
|
DependencyNode sourceNode = agent.linkMethod(LOAD_METHOD).getVariable(1).getClassValueNode();
|
||||||
|
sourceNode.connect(method.getResult().getArrayItem());
|
||||||
|
sourceNode.addConsumer(type -> {
|
||||||
|
CallLocation location = new CallLocation(LOAD_METHOD);
|
||||||
|
for (String implementationType : getImplementations(type.getName())) {
|
||||||
|
if (filters.stream().anyMatch(filter -> !filter.apply(type.getName(), implementationType))) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
serviceMap.computeIfAbsent(type.getName(), k -> new ArrayList<>()).add(implementationType);
|
||||||
|
|
||||||
|
MethodReference ctor = new MethodReference(implementationType,
|
||||||
|
new MethodDescriptor("<init>", ValueType.VOID));
|
||||||
|
agent.linkMethod(ctor).addLocation(location).use();
|
||||||
|
method.getResult().getArrayItem().propagate(agent.getType(implementationType));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private Set<String> getImplementations(String type) {
|
||||||
|
Set<String> result = new LinkedHashSet<>();
|
||||||
|
try {
|
||||||
|
Enumeration<URL> resources = classLoader.getResources("META-INF/services/" + type);
|
||||||
|
while (resources.hasMoreElements()) {
|
||||||
|
URL resource = resources.nextElement();
|
||||||
|
try (InputStream stream = resource.openStream()) {
|
||||||
|
parseServiceFile(stream, result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void parseServiceFile(InputStream input, Set<String> consumer) throws IOException {
|
||||||
BufferedReader reader = new BufferedReader(new InputStreamReader(input, StandardCharsets.UTF_8));
|
BufferedReader reader = new BufferedReader(new InputStreamReader(input, StandardCharsets.UTF_8));
|
||||||
while (true) {
|
while (true) {
|
||||||
String line = reader.readLine();
|
String line = reader.readLine();
|
||||||
|
@ -97,38 +141,37 @@ public class ServiceLoaderSupport extends AbstractDependencyListener implements
|
||||||
if (line.startsWith("#") || line.isEmpty()) {
|
if (line.startsWith("#") || line.isEmpty()) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
serviceMap.computeIfAbsent(service, k -> new ArrayList<>()).add(line);
|
|
||||||
|
|
||||||
MethodReference ctor = new MethodReference(line, new MethodDescriptor("<init>", ValueType.VOID));
|
consumer.add(line);
|
||||||
agent.linkMethod(ctor).addLocation(location).use();
|
|
||||||
targetNode.propagate(agent.getType(line));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
private List<ServiceLoaderFilter> getFilters(DependencyAgent agent) {
|
||||||
public void methodReached(DependencyAgent agent, MethodDependency method) {
|
List<ServiceLoaderFilter> filters = new ArrayList<>();
|
||||||
MethodReference ref = method.getReference();
|
for (String filterTypeName : getImplementations(ServiceLoaderFilter.class.getName())) {
|
||||||
if (ref.getClassName().equals("java.util.ServiceLoader") && ref.getName().equals("loadServices")) {
|
Class<?> filterType;
|
||||||
method.getResult().propagate(agent.getType("[Ljava/lang/Object;"));
|
try {
|
||||||
DependencyNode sourceNode = agent.linkMethod(LOAD_METHOD).getVariable(1).getClassValueNode();
|
filterType = Class.forName(filterTypeName, true, classLoader);
|
||||||
sourceNode.connect(method.getResult().getArrayItem());
|
} catch (ClassNotFoundException e) {
|
||||||
sourceNode.addConsumer(type -> initConstructor(agent, method.getResult().getArrayItem(),
|
agent.getDiagnostics().error(null, "Could not load ServiceLoader filter class '{{c0}}'",
|
||||||
type.getName(), new CallLocation(LOAD_METHOD)));
|
filterTypeName);
|
||||||
}
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void initConstructor(DependencyAgent agent, DependencyNode targetNode, String type,
|
if (!ServiceLoaderFilter.class.isAssignableFrom(filterType)) {
|
||||||
CallLocation location) {
|
agent.getDiagnostics().error(null, "Class '{{c0}}' does not implement ServiceLoaderFilter interface",
|
||||||
try {
|
filterTypeName);
|
||||||
Enumeration<URL> resources = classLoader.getResources("META-INF/services/" + type);
|
continue;
|
||||||
while (resources.hasMoreElements()) {
|
}
|
||||||
URL resource = resources.nextElement();
|
|
||||||
try (InputStream stream = resource.openStream()) {
|
try {
|
||||||
parseServiceFile(agent, targetNode, type, stream, location);
|
filters.add((ServiceLoaderFilter) filterType.getConstructor().newInstance());
|
||||||
}
|
} catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException
|
||||||
|
| InstantiationException e) {
|
||||||
|
agent.getDiagnostics().error(null, "Could not instantiate ServiceLoader filter '{{c0}}'",
|
||||||
|
filterTypeName);
|
||||||
}
|
}
|
||||||
} catch (IOException e) {
|
|
||||||
throw new RuntimeException(e);
|
|
||||||
}
|
}
|
||||||
|
return filters;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,22 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2019 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.java.lang.reflect;
|
||||||
|
|
||||||
|
import java.lang.reflect.Method;
|
||||||
|
|
||||||
|
public interface TInvocationHandler {
|
||||||
|
Object invoke(Object proxy, Method method, Object[] args) throws Throwable;
|
||||||
|
}
|
|
@ -18,12 +18,6 @@ package org.teavm.classlib.java.util;
|
||||||
import java.util.function.BiFunction;
|
import java.util.function.BiFunction;
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @author Alexey Andreev
|
|
||||||
* @param <K>
|
|
||||||
* @param <V>
|
|
||||||
*/
|
|
||||||
public interface TMap<K, V> {
|
public interface TMap<K, V> {
|
||||||
interface Entry<K1, V1> {
|
interface Entry<K1, V1> {
|
||||||
K1 getKey();
|
K1 getKey();
|
||||||
|
@ -43,6 +37,10 @@ public interface TMap<K, V> {
|
||||||
|
|
||||||
V get(Object key);
|
V get(Object key);
|
||||||
|
|
||||||
|
default V getOrDefault(K key, V defaultValue) {
|
||||||
|
return containsKey(key) ? get(key) : defaultValue;
|
||||||
|
}
|
||||||
|
|
||||||
V put(K key, V value);
|
V put(K key, V value);
|
||||||
|
|
||||||
V remove(Object key);
|
V remove(Object key);
|
||||||
|
|
|
@ -453,68 +453,15 @@ public class Renderer implements RenderingManager {
|
||||||
|
|
||||||
int start = writer.getOffset();
|
int start = writer.getOffset();
|
||||||
try {
|
try {
|
||||||
writer.append("$rt_metadata([");
|
writer.append("$rt_packages([");
|
||||||
ObjectIntMap<String> packageIndexes = generatePackageMetadata(classes, classesRequiringName);
|
ObjectIntMap<String> packageIndexes = generatePackageMetadata(classes, classesRequiringName);
|
||||||
|
|
||||||
boolean first = true;
|
|
||||||
for (ClassNode cls : classes) {
|
|
||||||
if (!first) {
|
|
||||||
writer.append(',').softNewLine();
|
|
||||||
}
|
|
||||||
first = false;
|
|
||||||
writer.appendClass(cls.getName()).append(",").ws();
|
|
||||||
|
|
||||||
if (classesRequiringName.contains(cls.getName())) {
|
|
||||||
String className = cls.getName();
|
|
||||||
int dotIndex = className.lastIndexOf('.') + 1;
|
|
||||||
String packageName = className.substring(0, dotIndex);
|
|
||||||
className = className.substring(dotIndex);
|
|
||||||
writer.append("\"").append(RenderingUtil.escapeString(className)).append("\"").append(",").ws();
|
|
||||||
writer.append(String.valueOf(packageIndexes.getOrDefault(packageName, -1)));
|
|
||||||
} else {
|
|
||||||
writer.append("0");
|
|
||||||
}
|
|
||||||
writer.append(",").ws();
|
|
||||||
|
|
||||||
if (cls.getParentName() != null) {
|
|
||||||
writer.appendClass(cls.getParentName());
|
|
||||||
} else {
|
|
||||||
writer.append("0");
|
|
||||||
}
|
|
||||||
writer.append(',').ws();
|
|
||||||
writer.append("[");
|
|
||||||
for (int i = 0; i < cls.getInterfaces().size(); ++i) {
|
|
||||||
String iface = cls.getInterfaces().get(i);
|
|
||||||
if (i > 0) {
|
|
||||||
writer.append(",").ws();
|
|
||||||
}
|
|
||||||
writer.appendClass(iface);
|
|
||||||
}
|
|
||||||
writer.append("],").ws();
|
|
||||||
|
|
||||||
writer.append(ElementModifier.pack(cls.getModifiers())).append(',').ws();
|
|
||||||
writer.append(cls.getAccessLevel().ordinal()).append(',').ws();
|
|
||||||
|
|
||||||
MethodReader clinit = classSource.get(cls.getName()).getMethod(
|
|
||||||
new MethodDescriptor("<clinit>", ValueType.VOID));
|
|
||||||
if (clinit != null) {
|
|
||||||
writer.append(naming.getNameForClassInit(cls.getName()));
|
|
||||||
} else {
|
|
||||||
writer.append('0');
|
|
||||||
}
|
|
||||||
writer.append(',').ws();
|
|
||||||
|
|
||||||
List<MethodReference> virtualMethods = new ArrayList<>();
|
|
||||||
for (MethodNode method : cls.getMethods()) {
|
|
||||||
if (!method.getModifiers().contains(ElementModifier.STATIC)) {
|
|
||||||
virtualMethods.add(method.getReference());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
collectMethodsToCopyFromInterfaces(classSource.get(cls.getName()), virtualMethods);
|
|
||||||
|
|
||||||
renderVirtualDeclarations(virtualMethods);
|
|
||||||
}
|
|
||||||
writer.append("]);").newLine();
|
writer.append("]);").newLine();
|
||||||
|
|
||||||
|
for (int i = 0; i < classes.size(); i += 50) {
|
||||||
|
int j = Math.min(i + 50, classes.size());
|
||||||
|
renderClassMetadataPortion(classes.subList(i, j), packageIndexes, classesRequiringName);
|
||||||
|
}
|
||||||
|
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
throw new RenderingException("IO error occurred", e);
|
throw new RenderingException("IO error occurred", e);
|
||||||
}
|
}
|
||||||
|
@ -522,6 +469,70 @@ public class Renderer implements RenderingManager {
|
||||||
metadataSize = writer.getOffset() - start;
|
metadataSize = writer.getOffset() - start;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void renderClassMetadataPortion(List<ClassNode> classes, ObjectIntMap<String> packageIndexes,
|
||||||
|
Set<String> classesRequiringName) throws IOException {
|
||||||
|
writer.append("$rt_metadata([");
|
||||||
|
boolean first = true;
|
||||||
|
for (ClassNode cls : classes) {
|
||||||
|
if (!first) {
|
||||||
|
writer.append(',').softNewLine();
|
||||||
|
}
|
||||||
|
first = false;
|
||||||
|
writer.appendClass(cls.getName()).append(",").ws();
|
||||||
|
|
||||||
|
if (classesRequiringName.contains(cls.getName())) {
|
||||||
|
String className = cls.getName();
|
||||||
|
int dotIndex = className.lastIndexOf('.') + 1;
|
||||||
|
String packageName = className.substring(0, dotIndex);
|
||||||
|
className = className.substring(dotIndex);
|
||||||
|
writer.append("\"").append(RenderingUtil.escapeString(className)).append("\"").append(",").ws();
|
||||||
|
writer.append(String.valueOf(packageIndexes.getOrDefault(packageName, -1)));
|
||||||
|
} else {
|
||||||
|
writer.append("0");
|
||||||
|
}
|
||||||
|
writer.append(",").ws();
|
||||||
|
|
||||||
|
if (cls.getParentName() != null) {
|
||||||
|
writer.appendClass(cls.getParentName());
|
||||||
|
} else {
|
||||||
|
writer.append("0");
|
||||||
|
}
|
||||||
|
writer.append(',').ws();
|
||||||
|
writer.append("[");
|
||||||
|
for (int i = 0; i < cls.getInterfaces().size(); ++i) {
|
||||||
|
String iface = cls.getInterfaces().get(i);
|
||||||
|
if (i > 0) {
|
||||||
|
writer.append(",").ws();
|
||||||
|
}
|
||||||
|
writer.appendClass(iface);
|
||||||
|
}
|
||||||
|
writer.append("],").ws();
|
||||||
|
|
||||||
|
writer.append(ElementModifier.pack(cls.getModifiers())).append(',').ws();
|
||||||
|
writer.append(cls.getAccessLevel().ordinal()).append(',').ws();
|
||||||
|
|
||||||
|
MethodReader clinit = classSource.get(cls.getName()).getMethod(
|
||||||
|
new MethodDescriptor("<clinit>", ValueType.VOID));
|
||||||
|
if (clinit != null) {
|
||||||
|
writer.append(naming.getNameForClassInit(cls.getName()));
|
||||||
|
} else {
|
||||||
|
writer.append('0');
|
||||||
|
}
|
||||||
|
writer.append(',').ws();
|
||||||
|
|
||||||
|
List<MethodReference> virtualMethods = new ArrayList<>();
|
||||||
|
for (MethodNode method : cls.getMethods()) {
|
||||||
|
if (!method.getModifiers().contains(ElementModifier.STATIC)) {
|
||||||
|
virtualMethods.add(method.getReference());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
collectMethodsToCopyFromInterfaces(classSource.get(cls.getName()), virtualMethods);
|
||||||
|
|
||||||
|
renderVirtualDeclarations(virtualMethods);
|
||||||
|
}
|
||||||
|
writer.append("]);").newLine();
|
||||||
|
}
|
||||||
|
|
||||||
private ObjectIntMap<String> generatePackageMetadata(List<ClassNode> classes, Set<String> classesRequiringName)
|
private ObjectIntMap<String> generatePackageMetadata(List<ClassNode> classes, Set<String> classesRequiringName)
|
||||||
throws IOException {
|
throws IOException {
|
||||||
PackageNode root = new PackageNode(null);
|
PackageNode root = new PackageNode(null);
|
||||||
|
@ -541,7 +552,6 @@ public class Renderer implements RenderingManager {
|
||||||
}
|
}
|
||||||
|
|
||||||
ObjectIntMap<String> indexes = new ObjectIntHashMap<>();
|
ObjectIntMap<String> indexes = new ObjectIntHashMap<>();
|
||||||
writer.append(String.valueOf(root.count())).append(",").ws();
|
|
||||||
writePackageStructure(root, -1, "", indexes);
|
writePackageStructure(root, -1, "", indexes);
|
||||||
writer.softNewLine();
|
writer.softNewLine();
|
||||||
return indexes;
|
return indexes;
|
||||||
|
@ -551,8 +561,11 @@ public class Renderer implements RenderingManager {
|
||||||
throws IOException {
|
throws IOException {
|
||||||
int index = startIndex;
|
int index = startIndex;
|
||||||
for (PackageNode child : node.children.values()) {
|
for (PackageNode child : node.children.values()) {
|
||||||
|
if (index >= 0) {
|
||||||
|
writer.append(",").ws();
|
||||||
|
}
|
||||||
writer.append(String.valueOf(startIndex)).append(",").ws()
|
writer.append(String.valueOf(startIndex)).append(",").ws()
|
||||||
.append("\"").append(RenderingUtil.escapeString(child.name)).append("\",").ws();
|
.append("\"").append(RenderingUtil.escapeString(child.name)).append("\"");
|
||||||
String fullName = prefix + child.name + ".";
|
String fullName = prefix + child.name + ".";
|
||||||
++index;
|
++index;
|
||||||
indexes.put(fullName, index);
|
indexes.put(fullName, index);
|
||||||
|
|
|
@ -419,16 +419,20 @@ var $rt_putStderr = typeof $rt_putStderrCustom === "function" ? $rt_putStderrCus
|
||||||
$rt_stderrBuffer += String.fromCharCode(ch);
|
$rt_stderrBuffer += String.fromCharCode(ch);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
function $rt_metadata(data) {
|
var $rt_packageData = null;
|
||||||
|
function $rt_packages(data) {
|
||||||
var i = 0;
|
var i = 0;
|
||||||
var packageCount = data[i++];
|
var packages = new Array(data.length);
|
||||||
var packages = new Array(packageCount);
|
for (var j = 0; j < data.length; ++j) {
|
||||||
for (var j = 0; j < packageCount; ++j) {
|
|
||||||
var prefixIndex = data[i++];
|
var prefixIndex = data[i++];
|
||||||
var prefix = prefixIndex >= 0 ? packages[prefixIndex] : "";
|
var prefix = prefixIndex >= 0 ? packages[prefixIndex] : "";
|
||||||
packages[j] = prefix + data[i++] + ".";
|
packages[j] = prefix + data[i++] + ".";
|
||||||
}
|
}
|
||||||
|
$rt_packageData = packages;
|
||||||
|
}
|
||||||
|
function $rt_metadata(data) {
|
||||||
|
var packages = $rt_packageData;
|
||||||
|
var i = 0;
|
||||||
while (i < data.length) {
|
while (i < data.length) {
|
||||||
var cls = data[i++];
|
var cls = data[i++];
|
||||||
cls.$meta = {};
|
cls.$meta = {};
|
||||||
|
@ -468,7 +472,7 @@ function $rt_metadata(data) {
|
||||||
|
|
||||||
var virtualMethods = data[i++];
|
var virtualMethods = data[i++];
|
||||||
if (virtualMethods !== 0) {
|
if (virtualMethods !== 0) {
|
||||||
for (j = 0; j < virtualMethods.length; j += 2) {
|
for (var j = 0; j < virtualMethods.length; j += 2) {
|
||||||
var name = virtualMethods[j];
|
var name = virtualMethods[j];
|
||||||
var func = virtualMethods[j + 1];
|
var func = virtualMethods[j + 1];
|
||||||
if (typeof name === 'string') {
|
if (typeof name === 'string') {
|
||||||
|
|
|
@ -23,7 +23,7 @@ class BuildTimeResourceGetter implements BuildTimeResourceMethod {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Object invoke(BuildTimeResourceProxy proxy, Object[] args) throws Throwable {
|
public Object invoke(BuildTimeResourceProxy proxy, Object[] args) {
|
||||||
return proxy.data[index];
|
return proxy.data[index];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,7 +24,7 @@ class BuildTimeResourceProxy implements InvocationHandler {
|
||||||
private Map<Method, BuildTimeResourceMethod> methods;
|
private Map<Method, BuildTimeResourceMethod> methods;
|
||||||
Object[] data;
|
Object[] data;
|
||||||
|
|
||||||
public BuildTimeResourceProxy(Map<Method, BuildTimeResourceMethod> methods, Object[] initialData) {
|
BuildTimeResourceProxy(Map<Method, BuildTimeResourceMethod> methods, Object[] initialData) {
|
||||||
this.methods = methods;
|
this.methods = methods;
|
||||||
data = Arrays.copyOf(initialData, initialData.length);
|
data = Arrays.copyOf(initialData, initialData.length);
|
||||||
}
|
}
|
||||||
|
|
|
@ -51,7 +51,7 @@ class BuildTimeResourceProxyBuilder {
|
||||||
private Object[] initialData;
|
private Object[] initialData;
|
||||||
private ResourceTypeDescriptor descriptor;
|
private ResourceTypeDescriptor descriptor;
|
||||||
|
|
||||||
public ProxyFactoryCreation(ResourceTypeDescriptor descriptor) {
|
ProxyFactoryCreation(ResourceTypeDescriptor descriptor) {
|
||||||
this.descriptor = descriptor;
|
this.descriptor = descriptor;
|
||||||
int index = 0;
|
int index = 0;
|
||||||
for (String propertyName : descriptor.getPropertyTypes().keySet()) {
|
for (String propertyName : descriptor.getPropertyTypes().keySet()) {
|
||||||
|
|
|
@ -23,7 +23,7 @@ class BuildTimeResourceProxyFactory {
|
||||||
private Object[] initialData;
|
private Object[] initialData;
|
||||||
ResourceTypeDescriptor typeDescriptor;
|
ResourceTypeDescriptor typeDescriptor;
|
||||||
|
|
||||||
public BuildTimeResourceProxyFactory(Map<Method, BuildTimeResourceMethod> methods, Object[] initialData,
|
BuildTimeResourceProxyFactory(Map<Method, BuildTimeResourceMethod> methods, Object[] initialData,
|
||||||
ResourceTypeDescriptor typeDescriptor) {
|
ResourceTypeDescriptor typeDescriptor) {
|
||||||
this.methods = methods;
|
this.methods = methods;
|
||||||
this.initialData = initialData;
|
this.initialData = initialData;
|
||||||
|
|
|
@ -31,7 +31,7 @@ class DefaultMetadataGeneratorContext implements MetadataGeneratorContext {
|
||||||
private ClassReaderSource classSource;
|
private ClassReaderSource classSource;
|
||||||
private ClassLoader classLoader;
|
private ClassLoader classLoader;
|
||||||
private Properties properties;
|
private Properties properties;
|
||||||
private BuildTimeResourceProxyBuilder proxyBuilder = new BuildTimeResourceProxyBuilder();
|
private BuildTimeResourceProxyBuilder proxyBuilder;
|
||||||
private ServiceRepository services;
|
private ServiceRepository services;
|
||||||
|
|
||||||
DefaultMetadataGeneratorContext(ClassReaderSource classSource, ClassLoader classLoader,
|
DefaultMetadataGeneratorContext(ClassReaderSource classSource, ClassLoader classLoader,
|
||||||
|
@ -42,6 +42,13 @@ class DefaultMetadataGeneratorContext implements MetadataGeneratorContext {
|
||||||
this.services = services;
|
this.services = services;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private BuildTimeResourceProxyBuilder getProxyBuilder() {
|
||||||
|
if (proxyBuilder == null) {
|
||||||
|
proxyBuilder = new BuildTimeResourceProxyBuilder();
|
||||||
|
}
|
||||||
|
return proxyBuilder;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ClassReaderSource getClassSource() {
|
public ClassReaderSource getClassSource() {
|
||||||
return classSource;
|
return classSource;
|
||||||
|
@ -61,12 +68,12 @@ class DefaultMetadataGeneratorContext implements MetadataGeneratorContext {
|
||||||
public <T extends Resource> T createResource(Class<T> resourceType) {
|
public <T extends Resource> T createResource(Class<T> resourceType) {
|
||||||
return resourceType.cast(Proxy.newProxyInstance(classLoader,
|
return resourceType.cast(Proxy.newProxyInstance(classLoader,
|
||||||
new Class<?>[] { resourceType, ResourceWriter.class, ResourceTypeDescriptorProvider.class },
|
new Class<?>[] { resourceType, ResourceWriter.class, ResourceTypeDescriptorProvider.class },
|
||||||
proxyBuilder.buildProxy(resourceType)));
|
getProxyBuilder().buildProxy(resourceType)));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ResourceTypeDescriptor getTypeDescriptor(Class<? extends Resource> type) {
|
public ResourceTypeDescriptor getTypeDescriptor(Class<? extends Resource> type) {
|
||||||
return proxyBuilder.getProxyFactory(type).typeDescriptor;
|
return getProxyBuilder().getProxyFactory(type).typeDescriptor;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
Loading…
Reference in New Issue
Block a user