Adds service registration and retrieval infrastructure

This commit is contained in:
konsoletyper 2014-06-10 11:10:11 +04:00
parent c3e30cc295
commit 8e521c457f
9 changed files with 93 additions and 12 deletions

View File

@ -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.common;
/**
*
* @author Alexey Andreev
*/
public interface ServiceRepository {
<T> T getService(Class<T> type);
}

View File

@ -15,6 +15,7 @@
*/
package org.teavm.dependency;
import org.teavm.common.ServiceRepository;
import org.teavm.model.ClassHolder;
import org.teavm.model.FieldReference;
import org.teavm.model.MethodReference;
@ -23,7 +24,7 @@ import org.teavm.model.MethodReference;
*
* @author Alexey Andreev
*/
public interface DependencyAgent extends DependencyInfo {
public interface DependencyAgent extends DependencyInfo, ServiceRepository {
DependencyNode createNode();
String generateClassName();

View File

@ -45,18 +45,21 @@ public class DependencyChecker implements DependencyInfo, DependencyAgent {
private ConcurrentMap<String, Object> achievableClasses = new ConcurrentHashMap<>();
private ConcurrentMap<String, Object> initializedClasses = new ConcurrentHashMap<>();
private List<DependencyListener> listeners = new ArrayList<>();
private ServiceRepository services;
ConcurrentMap<MethodReference, DependencyStack> missingMethods = new ConcurrentHashMap<>();
ConcurrentMap<String, DependencyStack> missingClasses = new ConcurrentHashMap<>();
ConcurrentMap<FieldReference, DependencyStack> missingFields = new ConcurrentHashMap<>();
public DependencyChecker(ClassReaderSource classSource, ClassLoader classLoader) {
this(classSource, classLoader, new SimpleFiniteExecutor());
public DependencyChecker(ClassReaderSource classSource, ClassLoader classLoader, ServiceRepository services) {
this(classSource, classLoader, services, new SimpleFiniteExecutor());
}
public DependencyChecker(ClassReaderSource classSource, ClassLoader classLoader, FiniteExecutor executor) {
public DependencyChecker(ClassReaderSource classSource, ClassLoader classLoader, ServiceRepository services,
FiniteExecutor executor) {
this.classSource = new DependencyClassSource(classSource);
this.classLoader = classLoader;
this.executor = executor;
this.services = services;
methodReaderCache = new ConcurrentCachedMapper<>(new Mapper<MethodReference, MethodReader>() {
@Override public MethodReader map(MethodReference preimage) {
return findMethodReader(preimage);
@ -447,4 +450,9 @@ public class DependencyChecker implements DependencyInfo, DependencyAgent {
sb.append('\n');
}
}
@Override
public <T> T getService(Class<T> type) {
return services.getService(type);
}
}

View File

@ -22,6 +22,7 @@ import java.util.*;
import org.teavm.codegen.NamingException;
import org.teavm.codegen.NamingStrategy;
import org.teavm.codegen.SourceWriter;
import org.teavm.common.ServiceRepository;
import org.teavm.javascript.ast.*;
import org.teavm.javascript.ni.GeneratorContext;
import org.teavm.javascript.ni.InjectedBy;
@ -44,6 +45,7 @@ public class Renderer implements ExprVisitor, StatementVisitor, RenderingContext
private boolean minifying;
private Map<MethodReference, InjectorHolder> injectorMap = new HashMap<>();
private Properties properties = new Properties();
private ServiceRepository services;
private static class InjectorHolder {
public final Injector injector;
@ -57,11 +59,13 @@ public class Renderer implements ExprVisitor, StatementVisitor, RenderingContext
injectorMap.put(method, new InjectorHolder(injector));
}
public Renderer(SourceWriter writer, ListableClassHolderSource classSource, ClassLoader classLoader) {
public Renderer(SourceWriter writer, ListableClassHolderSource classSource, ClassLoader classLoader,
ServiceRepository services) {
this.naming = writer.getNaming();
this.writer = writer;
this.classSource = classSource;
this.classLoader = classLoader;
this.services = services;
}
@Override
@ -506,7 +510,12 @@ public class Renderer implements ExprVisitor, StatementVisitor, RenderingContext
@Override
public Properties getProperties() {
return null;
return new Properties(properties);
}
@Override
public <T> T getService(Class<T> type) {
return services.getService(type);
}
}
@ -1429,5 +1438,20 @@ public class Renderer implements ExprVisitor, StatementVisitor, RenderingContext
public int argumentCount() {
return arguments.size();
}
@Override
public <T> T getService(Class<T> type) {
return services.getService(type);
}
@Override
public Properties getProperties() {
return new Properties(properties);
}
}
@Override
public <T> T getService(Class<T> type) {
return services.getService(type);
}
}

View File

@ -18,13 +18,14 @@ package org.teavm.javascript;
import java.util.Properties;
import org.teavm.codegen.NamingStrategy;
import org.teavm.codegen.SourceWriter;
import org.teavm.common.ServiceRepository;
import org.teavm.model.ListableClassReaderSource;
/**
*
* @author Alexey Andreev <konsoletyper@gmail.com>
*/
public interface RenderingContext {
public interface RenderingContext extends ServiceRepository {
NamingStrategy getNaming();
SourceWriter getWriter();

View File

@ -16,13 +16,14 @@
package org.teavm.javascript.ni;
import java.util.Properties;
import org.teavm.common.ServiceRepository;
import org.teavm.model.ListableClassReaderSource;
/**
*
* @author Alexey Andreev <konsoletyper@gmail.com>
*/
public interface GeneratorContext {
public interface GeneratorContext extends ServiceRepository {
String getParameterName(int index);
ListableClassReaderSource getClassSource();

View File

@ -16,7 +16,9 @@
package org.teavm.javascript.ni;
import java.io.IOException;
import java.util.Properties;
import org.teavm.codegen.SourceWriter;
import org.teavm.common.ServiceRepository;
import org.teavm.javascript.ast.Expr;
import org.teavm.model.ValueType;
@ -24,7 +26,7 @@ import org.teavm.model.ValueType;
*
* @author Alexey Andreev <konsoletyper@gmail.com>
*/
public interface InjectorContext {
public interface InjectorContext extends ServiceRepository {
Expr getArgument(int index);
int argumentCount();
@ -33,6 +35,8 @@ public interface InjectorContext {
SourceWriter getWriter();
Properties getProperties();
void writeEscaped(String str) throws IOException;
void writeType(ValueType type) throws IOException;

View File

@ -19,6 +19,7 @@ import java.io.*;
import java.util.*;
import org.teavm.codegen.*;
import org.teavm.common.FiniteExecutor;
import org.teavm.common.ServiceRepository;
import org.teavm.dependency.*;
import org.teavm.javascript.Decompiler;
import org.teavm.javascript.Renderer;
@ -65,7 +66,7 @@ import org.teavm.vm.spi.TeaVMPlugin;
*
* @author Alexey Andreev
*/
public class TeaVM implements TeaVMHost {
public class TeaVM implements TeaVMHost, ServiceRepository {
private ClassReaderSource classSource;
private DependencyChecker dependencyChecker;
private FiniteExecutor executor;
@ -78,12 +79,13 @@ public class TeaVM implements TeaVMHost {
private Map<MethodReference, Generator> methodGenerators = new HashMap<>();
private Map<MethodReference, Injector> methodInjectors = new HashMap<>();
private List<RendererListener> rendererListeners = new ArrayList<>();
private Map<Class<?>, Object> services = new HashMap<>();
private Properties properties = new Properties();
TeaVM(ClassReaderSource classSource, ClassLoader classLoader, FiniteExecutor executor) {
this.classSource = classSource;
this.classLoader = classLoader;
dependencyChecker = new DependencyChecker(this.classSource, classLoader, executor);
dependencyChecker = new DependencyChecker(this.classSource, classLoader, this, executor);
this.executor = executor;
}
@ -335,7 +337,7 @@ public class TeaVM implements TeaVMHost {
SourceWriterBuilder builder = new SourceWriterBuilder(naming);
builder.setMinified(minifying);
SourceWriter sourceWriter = builder.build(writer);
Renderer renderer = new Renderer(sourceWriter, classSet, classLoader);
Renderer renderer = new Renderer(sourceWriter, classSet, classLoader, this);
for (Map.Entry<MethodReference, Injector> entry : methodInjectors.entrySet()) {
renderer.addInjector(entry.getKey(), entry.getValue());
}
@ -529,4 +531,18 @@ public class TeaVM implements TeaVMHost {
plugin.install(this);
}
}
@Override
public <T> T getService(Class<T> type) {
Object service = services.get(type);
if (service == null) {
throw new IllegalArgumentException("Service not registered: " + type.getName());
}
return type.cast(service);
}
@Override
public <T> void registerService(Class<T> type, T instance) {
services.put(type, instance);
}
}

View File

@ -41,6 +41,8 @@ public interface TeaVMHost {
void add(RendererListener listener);
<T> void registerService(Class<T> type, T instance);
/**
* Gets class loaded that is used by TeaVM. This class loader is usually specified by
* {@link TeaVMBuilder#setClassLoader(ClassLoader)}