Skip to content

Commit ae2ac39

Browse files
committed
Conditional proxy configuration
1 parent a506f60 commit ae2ac39

File tree

9 files changed

+162
-75
lines changed

9 files changed

+162
-75
lines changed

substratevm/src/com.oracle.svm.configure.test/src/com/oracle/svm/configure/test/config/OmitPreviousConfigTests.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -182,8 +182,9 @@ private static void doTestMethods(TypeConfiguration typeConfig) {
182182
}
183183

184184
private static void doTestProxyConfig(ProxyConfiguration proxyConfig) {
185-
Assert.assertFalse(proxyConfig.contains("testProxySeenA", "testProxySeenB", "testProxySeenC"));
186-
Assert.assertTrue(proxyConfig.contains("testProxyUnseen"));
185+
ConfigurationCondition condition = ConfigurationCondition.objectReachable();
186+
Assert.assertFalse(proxyConfig.contains(condition, "testProxySeenA", "testProxySeenB", "testProxySeenC"));
187+
Assert.assertTrue(proxyConfig.contains(condition, "testProxyUnseen"));
187188
}
188189

189190
private static void doTestResourceConfig(ResourceConfiguration resourceConfig) {

substratevm/src/com.oracle.svm.configure/src/com/oracle/svm/configure/config/ConfigurationSet.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@
3030
import java.net.URI;
3131
import java.nio.file.Path;
3232
import java.nio.file.Paths;
33-
import java.util.Arrays;
33+
import java.util.ArrayList;
3434
import java.util.Collection;
3535
import java.util.LinkedHashSet;
3636
import java.util.Set;
@@ -112,7 +112,7 @@ public TypeConfiguration loadReflectConfig(Function<IOException, Exception> exce
112112

113113
public ProxyConfiguration loadProxyConfig(Function<IOException, Exception> exceptionHandler) throws Exception {
114114
ProxyConfiguration proxyConfiguration = new ProxyConfiguration();
115-
loadConfig(proxyConfigPaths, new ProxyConfigurationParser(types -> proxyConfiguration.add(Arrays.asList(types)), true), exceptionHandler);
115+
loadConfig(proxyConfigPaths, new ProxyConfigurationParser(types -> proxyConfiguration.add(types.getCondition(), new ArrayList<>(types.getElement())), true), exceptionHandler);
116116
return proxyConfiguration;
117117
}
118118

substratevm/src/com.oracle.svm.configure/src/com/oracle/svm/configure/config/ProxyConfiguration.java

Lines changed: 32 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -30,31 +30,34 @@
3030
import java.util.List;
3131
import java.util.concurrent.ConcurrentHashMap;
3232

33+
import org.graalvm.nativeimage.impl.ConfigurationCondition;
34+
3335
import com.oracle.svm.configure.ConfigurationBase;
3436
import com.oracle.svm.configure.json.JsonWriter;
37+
import com.oracle.svm.core.configure.ConditionalElement;
3538

3639
public class ProxyConfiguration implements ConfigurationBase {
37-
private final ConcurrentHashMap.KeySetView<List<String>, Boolean> interfaceLists = ConcurrentHashMap.newKeySet();
40+
private final ConcurrentHashMap.KeySetView<ConditionalElement<List<String>>, Boolean> interfaceLists = ConcurrentHashMap.newKeySet();
3841

3942
public ProxyConfiguration() {
4043
}
4144

4245
public ProxyConfiguration(ProxyConfiguration other) {
43-
for (List<String> interfaceList : other.interfaceLists) {
44-
interfaceLists.add(new ArrayList<>(interfaceList));
46+
for (ConditionalElement<List<String>> interfaceList : other.interfaceLists) {
47+
interfaceLists.add(new ConditionalElement<>(interfaceList.getCondition(), new ArrayList<>(interfaceList.getElement())));
4548
}
4649
}
4750

48-
public void add(List<String> interfaceList) {
49-
interfaceLists.add(interfaceList);
51+
public void add(ConfigurationCondition condition, List<String> interfaceList) {
52+
interfaceLists.add(new ConditionalElement<>(condition, interfaceList));
5053
}
5154

52-
public boolean contains(List<String> interfaceList) {
53-
return interfaceLists.contains(interfaceList);
55+
public boolean contains(ConfigurationCondition condition, List<String> interfaceList) {
56+
return interfaceLists.contains(new ConditionalElement<>(condition, interfaceList));
5457
}
5558

56-
public boolean contains(String... interfaces) {
57-
return contains(Arrays.asList(interfaces));
59+
public boolean contains(ConfigurationCondition condition, String... interfaces) {
60+
return contains(condition, Arrays.asList(interfaces));
5861
}
5962

6063
public void removeAll(ProxyConfiguration other) {
@@ -63,29 +66,25 @@ public void removeAll(ProxyConfiguration other) {
6366

6467
@Override
6568
public void printJson(JsonWriter writer) throws IOException {
66-
List<String[]> lists = new ArrayList<>(interfaceLists.size());
67-
for (List<String> list : interfaceLists) {
68-
lists.add(list.toArray(new String[0]));
69-
}
70-
lists.sort((a, b) -> {
71-
int c = 0;
72-
for (int i = 0; c == 0 && i < a.length && i < b.length; i++) {
73-
c = a[i].compareTo(b[i]);
74-
}
75-
return (c != 0) ? c : (a.length - b.length);
76-
});
69+
List<ConditionalElement<List<String>>> lists = new ArrayList<>(interfaceLists.size());
70+
lists.addAll(interfaceLists);
71+
lists.sort(ConditionalElement.comparator(ProxyConfiguration::compareList));
7772

7873
writer.append('[');
7974
writer.indent();
8075
String prefix = "";
81-
for (String[] list : lists) {
82-
writer.append(prefix).newline().append('[');
76+
for (ConditionalElement<List<String>> list : lists) {
77+
writer.append(prefix).newline();
78+
writer.append('{').indent().newline();
79+
ConfigurationConditionPrintable.printConditionAttribute(list.getCondition(), writer);
80+
writer.quote("interfaces").append(":").append('[');
8381
String typePrefix = "";
84-
for (String type : list) {
82+
for (String type : list.getElement()) {
8583
writer.append(typePrefix).quote(type);
8684
typePrefix = ",";
8785
}
8886
writer.append(']');
87+
writer.append('}').unindent().newline();
8988
prefix = ",";
9089
}
9190
writer.unindent().newline();
@@ -97,4 +96,14 @@ public boolean isEmpty() {
9796
return interfaceLists.isEmpty();
9897
}
9998

99+
private static <T extends Comparable<T>> int compareList(List<T> l1, List<T> l2) {
100+
for (int i = 0; i < l1.size() && i < l2.size(); i++) {
101+
int c = l1.get(i).compareTo(l2.get(i));
102+
if (c != 0) {
103+
return c;
104+
}
105+
}
106+
return l1.size() - l2.size();
107+
}
108+
100109
}

substratevm/src/com.oracle.svm.configure/src/com/oracle/svm/configure/trace/ReflectionProcessor.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -268,7 +268,7 @@ private void addDynamicProxy(List<?> interfaceList, LazyValue<String> callerClas
268268
return;
269269
}
270270
}
271-
proxyConfiguration.add(interfaces);
271+
proxyConfiguration.add(ConfigurationCondition.objectReachable(), interfaces);
272272
}
273273

274274
private void addDynamicProxyUnchecked(List<?> checkedInterfaceList, List<?> uncheckedInterfaceList, LazyValue<String> callerClass) {
@@ -285,6 +285,6 @@ private void addDynamicProxyUnchecked(List<?> checkedInterfaceList, List<?> unch
285285
List<String> interfaces = new ArrayList<>();
286286
interfaces.addAll(checkedInterfaces);
287287
interfaces.addAll(uncheckedInterfaces);
288-
proxyConfiguration.add(interfaces);
288+
proxyConfiguration.add(ConfigurationCondition.objectReachable(), interfaces);
289289
}
290290
}

substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/configure/ConditionalElement.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,4 +72,11 @@ public static <T extends Comparable<T>> Comparator<ConditionalElement<T>> compar
7272
.thenComparing(ConditionalElement::getCondition)
7373
.compare(o1, o2);
7474
}
75+
76+
public static <T> Comparator<ConditionalElement<T>> comparator(Comparator<T> elementComparator) {
77+
return (o1, o2) -> Comparator
78+
.comparing((Function<ConditionalElement<T>, T>) ConditionalElement::getElement, elementComparator)
79+
.thenComparing(ConditionalElement::getCondition)
80+
.compare(o1, o2);
81+
}
7582
}

substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/configure/ProxyConfigurationParser.java

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,9 @@
3030
import java.util.List;
3131
import java.util.Map;
3232
import java.util.function.Consumer;
33+
import java.util.stream.Collectors;
34+
35+
import org.graalvm.nativeimage.impl.ConfigurationCondition;
3336

3437
import com.oracle.svm.core.jdk.proxy.DynamicProxyRegistry;
3538
import com.oracle.svm.core.util.json.JSONParser;
@@ -41,9 +44,9 @@
4144
* Parses JSON describing lists of interfaces and register them in the {@link DynamicProxyRegistry}.
4245
*/
4346
public final class ProxyConfigurationParser extends ConfigurationParser {
44-
private final Consumer<String[]> interfaceListConsumer;
47+
private final Consumer<ConditionalElement<List<String>>> interfaceListConsumer;
4548

46-
public ProxyConfigurationParser(Consumer<String[]> interfaceListConsumer, boolean strictConfiguration) {
49+
public ProxyConfigurationParser(Consumer<ConditionalElement<List<String>>> interfaceListConsumer, boolean strictConfiguration) {
4750
super(strictConfiguration);
4851
this.interfaceListConsumer = interfaceListConsumer;
4952
}
@@ -61,10 +64,10 @@ private void parseTopLevelArray(List<Object> proxyConfiguration) {
6164
for (Object proxyConfigurationObject : proxyConfiguration) {
6265
if (proxyConfigurationObject instanceof List) {
6366
foundInterfaceLists = true;
64-
parseInterfaceList(asList(proxyConfigurationObject, "<shouldn't reach here>"));
67+
parseInterfaceList(ConfigurationCondition.objectReachable(), asList(proxyConfigurationObject, "<shouldn't reach here>"));
6568
} else if (proxyConfigurationObject instanceof Map) {
6669
foundProxyConfigurationObjects = true;
67-
parseWithPredicatedConfig(asMap(proxyConfigurationObject, "<shouldn't reach here>"));
70+
parseWithConditionalConfig(asMap(proxyConfigurationObject, "<shouldn't reach here>"));
6871
} else {
6972
throw new JSONParserException("second level must be composed of either interface lists or proxy configuration objects");
7073
}
@@ -74,23 +77,20 @@ private void parseTopLevelArray(List<Object> proxyConfiguration) {
7477
}
7578
}
7679

77-
private void parseInterfaceList(List<?> data) {
78-
String[] interfaces = new String[data.size()];
79-
int i = 0;
80-
for (Object value : data) {
81-
interfaces[i] = asString(value);
82-
i++;
83-
}
80+
private void parseInterfaceList(ConfigurationCondition condition, List<?> data) {
81+
List<String> interfaces = data.stream().map(ConfigurationParser::asString).collect(Collectors.toList());
82+
8483
try {
85-
interfaceListConsumer.accept(interfaces);
84+
interfaceListConsumer.accept(new ConditionalElement<>(condition, interfaces));
8685
} catch (Exception e) {
8786
throw new JSONParserException(e.toString());
8887
}
8988
}
9089

91-
private void parseWithPredicatedConfig(Map<String, Object> proxyConfigObject) {
92-
checkAttributes(proxyConfigObject, "proxy descriptor object", Collections.singleton("interfaces"));
93-
parseInterfaceList(asList(proxyConfigObject.get("interfaces"), "\"interfaces\" must be an array of fully qualified interface names"));
90+
private void parseWithConditionalConfig(Map<String, Object> proxyConfigObject) {
91+
checkAttributes(proxyConfigObject, "proxy descriptor object", Collections.singleton("interfaces"), Collections.singletonList(CONDITIONAL_KEY));
92+
ConfigurationCondition condition = parseCondition(proxyConfigObject);
93+
parseInterfaceList(condition, asList(proxyConfigObject.get("interfaces"), "\"interfaces\" must be an array of fully qualified interface names"));
9494
}
9595

9696
}

substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/jdk/JNIRegistrationAwt.java

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -24,16 +24,6 @@
2424
*/
2525
package com.oracle.svm.hosted.jdk;
2626

27-
import java.awt.*;
28-
29-
import org.graalvm.compiler.serviceprovider.JavaVersionUtil;
30-
import org.graalvm.nativeimage.ImageSingletons;
31-
import org.graalvm.nativeimage.Platform;
32-
import org.graalvm.nativeimage.Platforms;
33-
import org.graalvm.nativeimage.hosted.Feature;
34-
import org.graalvm.nativeimage.impl.ConfigurationCondition;
35-
import org.graalvm.nativeimage.impl.InternalPlatform;
36-
3727
import com.oracle.svm.core.SubstrateOptions;
3828
import com.oracle.svm.core.annotate.AutomaticFeature;
3929
import com.oracle.svm.core.configure.ResourcesRegistry;
@@ -43,6 +33,15 @@
4333
import com.oracle.svm.core.jni.JNIRuntimeAccess;
4434
import com.oracle.svm.hosted.FeatureImpl;
4535
import com.oracle.svm.hosted.c.NativeLibraries;
36+
import org.graalvm.compiler.serviceprovider.JavaVersionUtil;
37+
import org.graalvm.nativeimage.ImageSingletons;
38+
import org.graalvm.nativeimage.Platform;
39+
import org.graalvm.nativeimage.Platforms;
40+
import org.graalvm.nativeimage.hosted.Feature;
41+
import org.graalvm.nativeimage.impl.ConfigurationCondition;
42+
import org.graalvm.nativeimage.impl.InternalPlatform;
43+
44+
import java.awt.GraphicsEnvironment;
4645

4746
@Platforms({InternalPlatform.PLATFORM_JNI.class})
4847
@AutomaticFeature

substratevm/src/com.oracle.svm.reflect/src/com/oracle/svm/reflect/proxy/hosted/DynamicProxyFeature.java

Lines changed: 21 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -26,20 +26,20 @@
2626

2727
import java.util.Collections;
2828
import java.util.List;
29-
import java.util.function.Consumer;
3029

31-
import com.oracle.svm.core.configure.ConfigurationFile;
3230
import org.graalvm.nativeimage.ImageSingletons;
3331
import org.graalvm.nativeimage.hosted.Feature;
3432

3533
import com.oracle.svm.core.annotate.AutomaticFeature;
34+
import com.oracle.svm.core.configure.ConfigurationFile;
3635
import com.oracle.svm.core.configure.ConfigurationFiles;
3736
import com.oracle.svm.core.configure.ProxyConfigurationParser;
3837
import com.oracle.svm.core.jdk.proxy.DynamicProxyRegistry;
39-
import com.oracle.svm.core.util.UserError;
38+
import com.oracle.svm.hosted.ConfigurationTypeResolver;
4039
import com.oracle.svm.hosted.FallbackFeature;
4140
import com.oracle.svm.hosted.FeatureImpl.DuringSetupAccessImpl;
4241
import com.oracle.svm.hosted.ImageClassLoader;
42+
import com.oracle.svm.hosted.NativeImageOptions;
4343
import com.oracle.svm.hosted.config.ConfigurationParserUtils;
4444
import com.oracle.svm.reflect.hosted.ReflectionFeature;
4545
import com.oracle.svm.reflect.proxy.DynamicProxySupport;
@@ -60,29 +60,29 @@ public void duringSetup(DuringSetupAccess a) {
6060
ImageClassLoader imageClassLoader = access.getImageClassLoader();
6161
DynamicProxySupport dynamicProxySupport = new DynamicProxySupport(imageClassLoader.getClassLoader());
6262
ImageSingletons.add(DynamicProxyRegistry.class, dynamicProxySupport);
63-
64-
Consumer<String[]> adapter = interfaceNames -> {
65-
Class<?>[] interfaces = new Class<?>[interfaceNames.length];
66-
for (int i = 0; i < interfaceNames.length; i++) {
67-
String className = interfaceNames[i];
68-
Class<?> clazz = imageClassLoader.findClass(className).get();
69-
if (clazz == null) {
70-
throw UserError.abort("Class " + className + " not found");
71-
}
72-
if (!clazz.isInterface()) {
73-
throw UserError.abort("The class \"" + className + "\" is not an interface.");
74-
}
75-
interfaces[i] = clazz;
76-
}
77-
/* The interfaces array can be empty. The java.lang.reflect.Proxy API allows it. */
78-
dynamicProxySupport.addProxyClass(interfaces);
79-
};
80-
ProxyConfigurationParser parser = new ProxyConfigurationParser(adapter, ConfigurationFiles.Options.StrictConfiguration.getValue());
63+
ConfigurationTypeResolver typeResolver = new ConfigurationTypeResolver("resource configuration", imageClassLoader, NativeImageOptions.AllowIncompleteClasspath.getValue());
64+
ProxyRegistry proxyRegistry = new ProxyRegistry(typeResolver, dynamicProxySupport, imageClassLoader);
65+
ImageSingletons.add(ProxyRegistry.class, proxyRegistry);
66+
ProxyConfigurationParser parser = new ProxyConfigurationParser(proxyRegistry, ConfigurationFiles.Options.StrictConfiguration.getValue());
8167
loadedConfigurations = ConfigurationParserUtils.parseAndRegisterConfigurations(parser, imageClassLoader, "dynamic proxy",
8268
ConfigurationFiles.Options.DynamicProxyConfigurationFiles, ConfigurationFiles.Options.DynamicProxyConfigurationResources,
8369
ConfigurationFile.DYNAMIC_PROXY.getFileName());
8470
}
8571

72+
private static ProxyRegistry proxyRegistry() {
73+
return ImageSingletons.lookup(ProxyRegistry.class);
74+
}
75+
76+
@Override
77+
public void beforeAnalysis(BeforeAnalysisAccess access) {
78+
proxyRegistry().flushConditionalConfiguration(access);
79+
}
80+
81+
@Override
82+
public void duringAnalysis(DuringAnalysisAccess access) {
83+
proxyRegistry().flushConditionalConfiguration(access);
84+
}
85+
8686
@Override
8787
public void beforeCompilation(BeforeCompilationAccess access) {
8888
if (!ImageSingletons.contains(FallbackFeature.class)) {

0 commit comments

Comments
 (0)