mirror of
https://github.com/Eaglercraft-TeaVM-Fork/eagler-teavm.git
synced 2024-12-23 00:24:11 -08:00
Adds incomplete implementation of build-time resource proxy
This commit is contained in:
parent
a533e6f112
commit
c23f62ced7
|
@ -15,5 +15,10 @@
|
||||||
<artifactId>teavm-core</artifactId>
|
<artifactId>teavm-core</artifactId>
|
||||||
<version>${project.version}</version>
|
<version>${project.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>junit</groupId>
|
||||||
|
<artifactId>junit</artifactId>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
</project>
|
</project>
|
|
@ -23,7 +23,7 @@ import java.lang.annotation.Target;
|
||||||
/**
|
/**
|
||||||
* <p>Marks a valid <b>resource interface</b>. Resource interface is an interface, that has get* and set* methods,
|
* <p>Marks a valid <b>resource interface</b>. Resource interface is an interface, that has get* and set* methods,
|
||||||
* according the default convention for JavaBeans. Each property must have both getter and setter.
|
* according the default convention for JavaBeans. Each property must have both getter and setter.
|
||||||
* Also each property's must be either primitive value, except for <code>long</code> or valid resource.</p>
|
* Also each property's must be either primitive value (except for <code>long</code>) or a valid resource.</p>
|
||||||
*
|
*
|
||||||
* @see MetadataGenerator
|
* @see MetadataGenerator
|
||||||
* @see ResourceArray
|
* @see ResourceArray
|
||||||
|
|
|
@ -20,6 +20,8 @@ package org.teavm.platform.metadata;
|
||||||
* @author Alexey Andreev <konsoletyper@gmail.com>
|
* @author Alexey Andreev <konsoletyper@gmail.com>
|
||||||
*/
|
*/
|
||||||
public interface ResourceMap<T> {
|
public interface ResourceMap<T> {
|
||||||
|
boolean has(String key);
|
||||||
|
|
||||||
T get(String key);
|
T get(String key);
|
||||||
|
|
||||||
void put(String key, T value);
|
void put(String key, T value);
|
||||||
|
|
|
@ -0,0 +1,43 @@
|
||||||
|
/*
|
||||||
|
* 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.platform.plugin;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import org.teavm.platform.metadata.ResourceArray;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Alexey Andreev
|
||||||
|
*/
|
||||||
|
class BuildTimeResourceArray<T> implements ResourceArray<T> {
|
||||||
|
private List<T> data = new ArrayList<>();
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int size() {
|
||||||
|
return data.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public T get(int i) {
|
||||||
|
return data.get(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void add(T elem) {
|
||||||
|
data.add(elem);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,33 @@
|
||||||
|
/*
|
||||||
|
* 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.platform.plugin;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Alexey Andreev
|
||||||
|
*/
|
||||||
|
class BuildTimeResourceGetter implements BuildTimeResourceMethod {
|
||||||
|
private int index;
|
||||||
|
|
||||||
|
public BuildTimeResourceGetter(int index) {
|
||||||
|
this.index = index;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object invoke(BuildTimeResourceProxy proxy, Object[] args) throws Throwable {
|
||||||
|
return proxy.data[index];
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,43 @@
|
||||||
|
/*
|
||||||
|
* 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.platform.plugin;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
import org.teavm.platform.metadata.ResourceMap;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Alexey Andreev
|
||||||
|
*/
|
||||||
|
class BuildTimeResourceMap<T> implements ResourceMap<T> {
|
||||||
|
private Map<String, T> data = new HashMap<>();
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean has(String key) {
|
||||||
|
return data.containsKey(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public T get(String key) {
|
||||||
|
return data.get(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void put(String key, T value) {
|
||||||
|
data.put(key, value);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,24 @@
|
||||||
|
/*
|
||||||
|
* 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.platform.plugin;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Alexey Andreev
|
||||||
|
*/
|
||||||
|
interface BuildTimeResourceMethod {
|
||||||
|
Object invoke(BuildTimeResourceProxy proxy, Object[] args) throws Throwable;
|
||||||
|
}
|
|
@ -0,0 +1,40 @@
|
||||||
|
/*
|
||||||
|
* 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.platform.plugin;
|
||||||
|
|
||||||
|
import java.lang.reflect.InvocationHandler;
|
||||||
|
import java.lang.reflect.Method;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Alexey Andreev <konsoletyper@gmail.com>
|
||||||
|
*/
|
||||||
|
class BuildTimeResourceProxy implements InvocationHandler {
|
||||||
|
private Map<Method, BuildTimeResourceMethod> methods;
|
||||||
|
Object[] data;
|
||||||
|
|
||||||
|
public BuildTimeResourceProxy(Map<Method, BuildTimeResourceMethod> methods, Object[] initialData) {
|
||||||
|
this.methods = methods;
|
||||||
|
data = Arrays.copyOf(initialData, initialData.length);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
|
||||||
|
return methods.get(method).invoke(this, args);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,203 @@
|
||||||
|
/*
|
||||||
|
* 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.platform.plugin;
|
||||||
|
|
||||||
|
import java.lang.reflect.Method;
|
||||||
|
import java.util.*;
|
||||||
|
import org.teavm.platform.metadata.Resource;
|
||||||
|
import org.teavm.platform.metadata.ResourceArray;
|
||||||
|
import org.teavm.platform.metadata.ResourceMap;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Alexey Andreev
|
||||||
|
*/
|
||||||
|
class BuildTimeResourceProxyBuilder {
|
||||||
|
private Map<Class<?>, BuildTimeResourceProxyFactory> factories = new HashMap<>();
|
||||||
|
private static Set<Class<?>> allowedPropertyTypes = new HashSet<>(Arrays.<Class<?>>asList(
|
||||||
|
boolean.class, Boolean.class, byte.class, Byte.class, short.class, Short.class,
|
||||||
|
int.class, Integer.class, float.class, Float.class, double.class, Double.class,
|
||||||
|
String.class, ResourceArray.class, ResourceMap.class));
|
||||||
|
|
||||||
|
public BuildTimeResourceProxy buildProxy(Class<?> iface) {
|
||||||
|
BuildTimeResourceProxyFactory factory = factories.get(iface);
|
||||||
|
if (factory == null) {
|
||||||
|
factory = createFactory(iface);
|
||||||
|
factories.put(iface, factory);
|
||||||
|
}
|
||||||
|
return factory.create();
|
||||||
|
}
|
||||||
|
|
||||||
|
private BuildTimeResourceProxyFactory createFactory(Class<?> iface) {
|
||||||
|
return new ProxyFactoryCreation(iface).create();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class ProxyFactoryCreation {
|
||||||
|
private Class<?> rootIface;
|
||||||
|
Map<String, Class<?>> getters = new HashMap<>();
|
||||||
|
Map<String, Class<?>> setters = new HashMap<>();
|
||||||
|
Map<Method, BuildTimeResourceMethod> methods = new HashMap<>();
|
||||||
|
private List<Object> initialData = new ArrayList<>();
|
||||||
|
private Map<String, Integer> propertyIndexes = new HashMap<>();
|
||||||
|
|
||||||
|
public ProxyFactoryCreation(Class<?> iface) {
|
||||||
|
this.rootIface = iface;
|
||||||
|
}
|
||||||
|
|
||||||
|
BuildTimeResourceProxyFactory create() {
|
||||||
|
if (!rootIface.isInterface()) {
|
||||||
|
throw new IllegalArgumentException("Error creating a new resource of type " + rootIface.getName() +
|
||||||
|
" that is not an interface");
|
||||||
|
}
|
||||||
|
scanIface(rootIface);
|
||||||
|
return new BuildTimeResourceProxyFactory(methods, initialData.toArray(new Object[initialData.size()]));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void scanIface(Class<?> iface) {
|
||||||
|
if (iface.isAnnotationPresent(Resource.class)) {
|
||||||
|
throw new IllegalArgumentException("Error creating a new resource of type " + iface.getName() +
|
||||||
|
". This type is not marked with the " + Resource.class.getName() + " annotation");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Scan methods
|
||||||
|
getters.clear();
|
||||||
|
setters.clear();
|
||||||
|
for (Method method : iface.getDeclaredMethods()) {
|
||||||
|
if (method.getName().startsWith("get")) {
|
||||||
|
scanGetter(method);
|
||||||
|
} else if (method.getName().startsWith("is")) {
|
||||||
|
scanBooleanGetter(method);
|
||||||
|
} else if (method.getName().startsWith("set")) {
|
||||||
|
scanSetter(method);
|
||||||
|
} else {
|
||||||
|
throwInvalidMethod(method);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Verify consistency of getters and setters
|
||||||
|
for (Map.Entry<String, Class<?>> property : getters.entrySet()) {
|
||||||
|
String propertyName = property.getKey();
|
||||||
|
Class<?> getterType = property.getValue();
|
||||||
|
Class<?> setterType = setters.get(propertyName);
|
||||||
|
if (setterType == null) {
|
||||||
|
throw new IllegalArgumentException("Property " + iface.getName() + "." + propertyName +
|
||||||
|
" has a getter, but does not have a setter");
|
||||||
|
}
|
||||||
|
if (!setterType.equals(getterType)) {
|
||||||
|
throw new IllegalArgumentException("Property " + iface.getName() + "." + propertyName +
|
||||||
|
" has a getter and a setter of different types");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (String propertyName : setters.keySet()) {
|
||||||
|
if (!getters.containsKey(propertyName)) {
|
||||||
|
throw new IllegalArgumentException("Property " + iface.getName() + "." + propertyName +
|
||||||
|
" has a setter, but does not have a getter");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Verify types of properties and fill default values
|
||||||
|
for (Map.Entry<String, Class<?>> property : getters.entrySet()) {
|
||||||
|
String propertyName = property.getKey();
|
||||||
|
Class<?> propertyType = property.getValue();
|
||||||
|
if (allowedPropertyTypes.contains(propertyType)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (!propertyType.isInterface() || !propertyType.isAnnotationPresent(Resource.class)) {
|
||||||
|
throw new IllegalArgumentException("Property " + iface.getName() + "." + propertyName +
|
||||||
|
" has an illegal type " + propertyType.getName());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// TODO: fill default values
|
||||||
|
|
||||||
|
// Scan superinterfaces
|
||||||
|
for (Class<?> superIface : iface.getInterfaces()) {
|
||||||
|
scanIface(superIface);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void throwInvalidMethod(Method method) {
|
||||||
|
throw new IllegalArgumentException("Method " + method.getDeclaringClass().getName() + "." +
|
||||||
|
method.getName() + " is not likely to be either getter or setter");
|
||||||
|
}
|
||||||
|
|
||||||
|
private void scanGetter(Method method) {
|
||||||
|
String propertyName = extractPropertyName(method.getName().substring(3));
|
||||||
|
if (propertyName == null || method.getReturnType().equals(void.class) ||
|
||||||
|
method.getParameterTypes().length > 0) {
|
||||||
|
throwInvalidMethod(method);
|
||||||
|
}
|
||||||
|
if (getters.put(propertyName, method.getReturnType()) != null) {
|
||||||
|
throw new IllegalArgumentException("Method " + method.getDeclaringClass().getName() + "." +
|
||||||
|
method.getName() + " is a duplicate getter for property " + propertyName);
|
||||||
|
}
|
||||||
|
methods.put(method, new BuildTimeResourceGetter(getPropertyIndex(propertyName)));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void scanBooleanGetter(Method method) {
|
||||||
|
String propertyName = extractPropertyName(method.getName().substring(2));
|
||||||
|
if (propertyName == null || !method.getReturnType().equals(boolean.class) ||
|
||||||
|
method.getParameterTypes().length > 0) {
|
||||||
|
throwInvalidMethod(method);
|
||||||
|
}
|
||||||
|
if (getters.put(propertyName, method.getReturnType()) != null) {
|
||||||
|
throw new IllegalArgumentException("Method " + method.getDeclaringClass().getName() + "." +
|
||||||
|
method.getName() + " is a duplicate getter for property " + propertyName);
|
||||||
|
}
|
||||||
|
methods.put(method, new BuildTimeResourceGetter(getPropertyIndex(propertyName)));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void scanSetter(Method method) {
|
||||||
|
String propertyName = extractPropertyName(method.getName().substring(2));
|
||||||
|
if (propertyName == null || !method.getReturnType().equals(void.class) ||
|
||||||
|
method.getParameterTypes().length != 1) {
|
||||||
|
throwInvalidMethod(method);
|
||||||
|
}
|
||||||
|
if (setters.put(propertyName, method.getParameterTypes()[0]) != null) {
|
||||||
|
throw new IllegalArgumentException("Method " + method.getDeclaringClass().getName() + "." +
|
||||||
|
method.getName() + " is a duplicate setter for property " + propertyName);
|
||||||
|
}
|
||||||
|
methods.put(method, new BuildTimeResourceSetter(getPropertyIndex(propertyName)));
|
||||||
|
}
|
||||||
|
|
||||||
|
private String extractPropertyName(String propertyName) {
|
||||||
|
if (propertyName.isEmpty()) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
char c = propertyName.charAt(0);
|
||||||
|
if (c != Character.toUpperCase(c)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
if (propertyName.length() == 1) {
|
||||||
|
return propertyName.toLowerCase();
|
||||||
|
}
|
||||||
|
c = propertyName.charAt(1);
|
||||||
|
if (c == Character.toUpperCase(c)) {
|
||||||
|
return propertyName;
|
||||||
|
} else {
|
||||||
|
return Character.toLowerCase(propertyName.charAt(0)) + propertyName.substring(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private int getPropertyIndex(String propertyName) {
|
||||||
|
Integer index = propertyIndexes.get(propertyName);
|
||||||
|
if (index == null) {
|
||||||
|
index = propertyIndexes.size();
|
||||||
|
propertyIndexes.put(propertyName, index);
|
||||||
|
}
|
||||||
|
return index;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,38 @@
|
||||||
|
/*
|
||||||
|
* 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.platform.plugin;
|
||||||
|
|
||||||
|
import java.lang.reflect.Method;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Alexey Andreev
|
||||||
|
*/
|
||||||
|
class BuildTimeResourceProxyFactory {
|
||||||
|
private Map<Method, BuildTimeResourceMethod> methods = new HashMap<>();
|
||||||
|
private Object[] initialData;
|
||||||
|
|
||||||
|
public BuildTimeResourceProxyFactory(Map<Method, BuildTimeResourceMethod> methods, Object[] initialData) {
|
||||||
|
this.methods = methods;
|
||||||
|
this.initialData = initialData;
|
||||||
|
}
|
||||||
|
|
||||||
|
BuildTimeResourceProxy create() {
|
||||||
|
return new BuildTimeResourceProxy(methods, initialData);
|
||||||
|
}
|
||||||
|
}
|
|
@ -15,16 +15,20 @@
|
||||||
*/
|
*/
|
||||||
package org.teavm.platform.plugin;
|
package org.teavm.platform.plugin;
|
||||||
|
|
||||||
import java.lang.reflect.InvocationHandler;
|
|
||||||
import java.lang.reflect.Method;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @author Alexey Andreev <konsoletyper@gmail.com>
|
* @author Alexey Andreev
|
||||||
*/
|
*/
|
||||||
class ResourceProxy implements InvocationHandler {
|
class BuildTimeResourceSetter implements BuildTimeResourceMethod {
|
||||||
|
private int index;
|
||||||
|
|
||||||
|
public BuildTimeResourceSetter(int index) {
|
||||||
|
this.index = index;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
|
public Object invoke(BuildTimeResourceProxy proxy, Object[] args) throws Throwable {
|
||||||
|
proxy.data[index] = args[0];
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -0,0 +1,72 @@
|
||||||
|
/*
|
||||||
|
* 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.platform.plugin;
|
||||||
|
|
||||||
|
import java.lang.reflect.Proxy;
|
||||||
|
import java.util.Properties;
|
||||||
|
import org.teavm.model.ListableClassReaderSource;
|
||||||
|
import org.teavm.platform.metadata.MetadataGeneratorContext;
|
||||||
|
import org.teavm.platform.metadata.ResourceArray;
|
||||||
|
import org.teavm.platform.metadata.ResourceMap;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Alexey Andreev
|
||||||
|
*/
|
||||||
|
class DefaultMetadataGeneratorContext implements MetadataGeneratorContext {
|
||||||
|
private ListableClassReaderSource classSource;
|
||||||
|
private ClassLoader classLoader;
|
||||||
|
private Properties properties;
|
||||||
|
private BuildTimeResourceProxyBuilder proxyBuilder = new BuildTimeResourceProxyBuilder();
|
||||||
|
|
||||||
|
private DefaultMetadataGeneratorContext(ListableClassReaderSource classSource, ClassLoader classLoader,
|
||||||
|
Properties properties) {
|
||||||
|
this.classSource = classSource;
|
||||||
|
this.classLoader = classLoader;
|
||||||
|
this.properties = properties;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ListableClassReaderSource getClassSource() {
|
||||||
|
return classSource;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ClassLoader getClassLoader() {
|
||||||
|
return classLoader;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Properties getProperties() {
|
||||||
|
return new Properties(properties);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public <T> T createResource(Class<T> resourceType) {
|
||||||
|
return resourceType.cast(Proxy.newProxyInstance(classLoader, new Class<?>[] { resourceType },
|
||||||
|
proxyBuilder.buildProxy(resourceType)));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public <T> ResourceArray<T> createResourceArray() {
|
||||||
|
return new BuildTimeResourceArray<>();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public <T> ResourceMap<T> createResourceMap() {
|
||||||
|
return new BuildTimeResourceMap<>();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,43 @@
|
||||||
|
/*
|
||||||
|
* 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.platform.plugin;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import org.teavm.codegen.SourceWriter;
|
||||||
|
import org.teavm.javascript.ni.Generator;
|
||||||
|
import org.teavm.javascript.ni.GeneratorContext;
|
||||||
|
import org.teavm.model.*;
|
||||||
|
import org.teavm.platform.metadata.MetadataProvider;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Alexey Andreev
|
||||||
|
*/
|
||||||
|
class MetadataProviderNativeGenerator implements Generator {
|
||||||
|
@Override
|
||||||
|
public void generate(GeneratorContext context, SourceWriter writer, MethodReference methodRef) throws IOException {
|
||||||
|
ClassReader cls = context.getClassSource().get(methodRef.getClassName());
|
||||||
|
MethodReader method = cls.getMethod(methodRef.getDescriptor());
|
||||||
|
AnnotationReader providerAnnot = method.getAnnotations().get(MetadataProvider.class.getName());
|
||||||
|
if (providerAnnot == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!method.hasModifier(ElementModifier.NATIVE)) {
|
||||||
|
throw new IllegalStateException("Method " + method.getReference() + " was marked with " +
|
||||||
|
MetadataProvider.class.getName() + " but it is not native");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,39 @@
|
||||||
|
/*
|
||||||
|
* 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.platform.plugin;
|
||||||
|
|
||||||
|
import org.teavm.javascript.ni.GeneratedBy;
|
||||||
|
import org.teavm.model.*;
|
||||||
|
import org.teavm.platform.metadata.MetadataProvider;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Alexey Andreev
|
||||||
|
*/
|
||||||
|
class MetadataProviderTransformer implements ClassHolderTransformer {
|
||||||
|
@Override
|
||||||
|
public void transformClass(ClassHolder cls, ClassReaderSource innerSource) {
|
||||||
|
for (MethodHolder method : cls.getMethods()) {
|
||||||
|
AnnotationReader providerAnnot = method.getAnnotations().get(MetadataProvider.class.getName());
|
||||||
|
if (providerAnnot == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
AnnotationHolder genAnnot = new AnnotationHolder(GeneratedBy.class.getName());
|
||||||
|
genAnnot.getValues().put("value", new AnnotationValue(ValueType.object(null)));
|
||||||
|
method.getAnnotations().add(genAnnot);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -25,5 +25,6 @@ import org.teavm.vm.spi.TeaVMPlugin;
|
||||||
public class PlatformPlugin implements TeaVMPlugin {
|
public class PlatformPlugin implements TeaVMPlugin {
|
||||||
@Override
|
@Override
|
||||||
public void install(TeaVMHost host) {
|
public void install(TeaVMHost host) {
|
||||||
|
host.add(new MetadataProviderTransformer());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,24 @@
|
||||||
|
/*
|
||||||
|
* 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.platform.metadata;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Alexey Andreev
|
||||||
|
*/
|
||||||
|
public class MetadataGeneratorTest {
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,31 @@
|
||||||
|
/*
|
||||||
|
* 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.platform.metadata;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Alexey Andreev
|
||||||
|
*/
|
||||||
|
@Resource
|
||||||
|
public interface TestResource {
|
||||||
|
int getInt();
|
||||||
|
|
||||||
|
void setInt(int value);
|
||||||
|
|
||||||
|
String getString();
|
||||||
|
|
||||||
|
void setString(String string);
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user