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; package org.teavm.dependency;
import org.teavm.common.ServiceRepository;
import org.teavm.model.ClassHolder; import org.teavm.model.ClassHolder;
import org.teavm.model.FieldReference; import org.teavm.model.FieldReference;
import org.teavm.model.MethodReference; import org.teavm.model.MethodReference;
@ -23,7 +24,7 @@ import org.teavm.model.MethodReference;
* *
* @author Alexey Andreev * @author Alexey Andreev
*/ */
public interface DependencyAgent extends DependencyInfo { public interface DependencyAgent extends DependencyInfo, ServiceRepository {
DependencyNode createNode(); DependencyNode createNode();
String generateClassName(); 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> achievableClasses = new ConcurrentHashMap<>();
private ConcurrentMap<String, Object> initializedClasses = new ConcurrentHashMap<>(); private ConcurrentMap<String, Object> initializedClasses = new ConcurrentHashMap<>();
private List<DependencyListener> listeners = new ArrayList<>(); private List<DependencyListener> listeners = new ArrayList<>();
private ServiceRepository services;
ConcurrentMap<MethodReference, DependencyStack> missingMethods = new ConcurrentHashMap<>(); ConcurrentMap<MethodReference, DependencyStack> missingMethods = new ConcurrentHashMap<>();
ConcurrentMap<String, DependencyStack> missingClasses = new ConcurrentHashMap<>(); ConcurrentMap<String, DependencyStack> missingClasses = new ConcurrentHashMap<>();
ConcurrentMap<FieldReference, DependencyStack> missingFields = new ConcurrentHashMap<>(); ConcurrentMap<FieldReference, DependencyStack> missingFields = new ConcurrentHashMap<>();
public DependencyChecker(ClassReaderSource classSource, ClassLoader classLoader) { public DependencyChecker(ClassReaderSource classSource, ClassLoader classLoader, ServiceRepository services) {
this(classSource, classLoader, new SimpleFiniteExecutor()); 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.classSource = new DependencyClassSource(classSource);
this.classLoader = classLoader; this.classLoader = classLoader;
this.executor = executor; this.executor = executor;
this.services = services;
methodReaderCache = new ConcurrentCachedMapper<>(new Mapper<MethodReference, MethodReader>() { methodReaderCache = new ConcurrentCachedMapper<>(new Mapper<MethodReference, MethodReader>() {
@Override public MethodReader map(MethodReference preimage) { @Override public MethodReader map(MethodReference preimage) {
return findMethodReader(preimage); return findMethodReader(preimage);
@ -447,4 +450,9 @@ public class DependencyChecker implements DependencyInfo, DependencyAgent {
sb.append('\n'); 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.NamingException;
import org.teavm.codegen.NamingStrategy; import org.teavm.codegen.NamingStrategy;
import org.teavm.codegen.SourceWriter; import org.teavm.codegen.SourceWriter;
import org.teavm.common.ServiceRepository;
import org.teavm.javascript.ast.*; import org.teavm.javascript.ast.*;
import org.teavm.javascript.ni.GeneratorContext; import org.teavm.javascript.ni.GeneratorContext;
import org.teavm.javascript.ni.InjectedBy; import org.teavm.javascript.ni.InjectedBy;
@ -44,6 +45,7 @@ public class Renderer implements ExprVisitor, StatementVisitor, RenderingContext
private boolean minifying; private boolean minifying;
private Map<MethodReference, InjectorHolder> injectorMap = new HashMap<>(); private Map<MethodReference, InjectorHolder> injectorMap = new HashMap<>();
private Properties properties = new Properties(); private Properties properties = new Properties();
private ServiceRepository services;
private static class InjectorHolder { private static class InjectorHolder {
public final Injector injector; public final Injector injector;
@ -57,11 +59,13 @@ public class Renderer implements ExprVisitor, StatementVisitor, RenderingContext
injectorMap.put(method, new InjectorHolder(injector)); 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.naming = writer.getNaming();
this.writer = writer; this.writer = writer;
this.classSource = classSource; this.classSource = classSource;
this.classLoader = classLoader; this.classLoader = classLoader;
this.services = services;
} }
@Override @Override
@ -506,7 +510,12 @@ public class Renderer implements ExprVisitor, StatementVisitor, RenderingContext
@Override @Override
public Properties getProperties() { 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() { public int argumentCount() {
return arguments.size(); 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 java.util.Properties;
import org.teavm.codegen.NamingStrategy; import org.teavm.codegen.NamingStrategy;
import org.teavm.codegen.SourceWriter; import org.teavm.codegen.SourceWriter;
import org.teavm.common.ServiceRepository;
import org.teavm.model.ListableClassReaderSource; import org.teavm.model.ListableClassReaderSource;
/** /**
* *
* @author Alexey Andreev <konsoletyper@gmail.com> * @author Alexey Andreev <konsoletyper@gmail.com>
*/ */
public interface RenderingContext { public interface RenderingContext extends ServiceRepository {
NamingStrategy getNaming(); NamingStrategy getNaming();
SourceWriter getWriter(); SourceWriter getWriter();

View File

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

View File

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

View File

@ -19,6 +19,7 @@ import java.io.*;
import java.util.*; import java.util.*;
import org.teavm.codegen.*; import org.teavm.codegen.*;
import org.teavm.common.FiniteExecutor; import org.teavm.common.FiniteExecutor;
import org.teavm.common.ServiceRepository;
import org.teavm.dependency.*; import org.teavm.dependency.*;
import org.teavm.javascript.Decompiler; import org.teavm.javascript.Decompiler;
import org.teavm.javascript.Renderer; import org.teavm.javascript.Renderer;
@ -65,7 +66,7 @@ import org.teavm.vm.spi.TeaVMPlugin;
* *
* @author Alexey Andreev * @author Alexey Andreev
*/ */
public class TeaVM implements TeaVMHost { public class TeaVM implements TeaVMHost, ServiceRepository {
private ClassReaderSource classSource; private ClassReaderSource classSource;
private DependencyChecker dependencyChecker; private DependencyChecker dependencyChecker;
private FiniteExecutor executor; private FiniteExecutor executor;
@ -78,12 +79,13 @@ public class TeaVM implements TeaVMHost {
private Map<MethodReference, Generator> methodGenerators = new HashMap<>(); private Map<MethodReference, Generator> methodGenerators = new HashMap<>();
private Map<MethodReference, Injector> methodInjectors = new HashMap<>(); private Map<MethodReference, Injector> methodInjectors = new HashMap<>();
private List<RendererListener> rendererListeners = new ArrayList<>(); private List<RendererListener> rendererListeners = new ArrayList<>();
private Map<Class<?>, Object> services = new HashMap<>();
private Properties properties = new Properties(); private Properties properties = new Properties();
TeaVM(ClassReaderSource classSource, ClassLoader classLoader, FiniteExecutor executor) { TeaVM(ClassReaderSource classSource, ClassLoader classLoader, FiniteExecutor executor) {
this.classSource = classSource; this.classSource = classSource;
this.classLoader = classLoader; this.classLoader = classLoader;
dependencyChecker = new DependencyChecker(this.classSource, classLoader, executor); dependencyChecker = new DependencyChecker(this.classSource, classLoader, this, executor);
this.executor = executor; this.executor = executor;
} }
@ -335,7 +337,7 @@ public class TeaVM implements TeaVMHost {
SourceWriterBuilder builder = new SourceWriterBuilder(naming); SourceWriterBuilder builder = new SourceWriterBuilder(naming);
builder.setMinified(minifying); builder.setMinified(minifying);
SourceWriter sourceWriter = builder.build(writer); 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()) { for (Map.Entry<MethodReference, Injector> entry : methodInjectors.entrySet()) {
renderer.addInjector(entry.getKey(), entry.getValue()); renderer.addInjector(entry.getKey(), entry.getValue());
} }
@ -529,4 +531,18 @@ public class TeaVM implements TeaVMHost {
plugin.install(this); 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); 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 * Gets class loaded that is used by TeaVM. This class loader is usually specified by
* {@link TeaVMBuilder#setClassLoader(ClassLoader)} * {@link TeaVMBuilder#setClassLoader(ClassLoader)}