4141import java .util .Arrays ;
4242import java .util .ConcurrentModificationException ;
4343import java .util .Date ;
44- import java .util .HashSet ;
4544import java .util .List ;
46- import java .util .Set ;
4745import java .util .TimeZone ;
4846import java .util .concurrent .ScheduledThreadPoolExecutor ;
4947import java .util .concurrent .TimeUnit ;
5654import org .graalvm .nativeimage .ProcessProperties ;
5755import org .graalvm .nativeimage .hosted .Feature ;
5856
57+ import com .oracle .svm .agent .conditionalconfig .ConditionalConfigurationWriter ;
5958import com .oracle .svm .agent .configwithorigins .ConfigurationWithOriginsWriter ;
6059import com .oracle .svm .agent .configwithorigins .MethodInfoRecordKeeper ;
6160import com .oracle .svm .agent .ignoredconfig .AgentMetaInfProcessor ;
62- import com .oracle .svm .agent .conditionalconfig .ConditionalConfigurationWriter ;
6361import com .oracle .svm .agent .stackaccess .EagerlyLoadedJavaStackAccess ;
6462import com .oracle .svm .agent .stackaccess .InterceptedState ;
6563import com .oracle .svm .agent .stackaccess .OnDemandJavaStackAccess ;
7068import com .oracle .svm .configure .config .ConditionalConfigurationPredicate ;
7169import com .oracle .svm .configure .config .ConfigurationFileCollection ;
7270import com .oracle .svm .configure .config .ConfigurationSet ;
71+ import com .oracle .svm .configure .filters .ComplexFilter ;
72+ import com .oracle .svm .configure .filters .ConfigurationFilter ;
7373import com .oracle .svm .configure .filters .FilterConfigurationParser ;
7474import com .oracle .svm .configure .filters .RuleNode ;
7575import com .oracle .svm .configure .trace .AccessAdvisor ;
@@ -130,8 +130,8 @@ protected int onLoadCallback(JNIJavaVM vm, JvmtiEnv jvmti, JvmtiEventCallbacks c
130130 boolean experimentalOmitClasspathConfig = false ;
131131 boolean build = false ;
132132 boolean configurationWithOrigins = false ;
133- Set <String > conditionalConfigUserPackagePrefixes = new HashSet <>();
134- Set < Pattern > conditionalConfigClassNameExcludePatterns = new HashSet <>();
133+ List <String > conditionalConfigUserPackageFilterFiles = new ArrayList <>();
134+ List < String > conditionalConfigClassNameFilterFiles = new ArrayList <>();
135135 int configWritePeriod = -1 ; // in seconds
136136 int configWritePeriodInitialDelay = 1 ; // in seconds
137137 boolean trackReflectionMetadata = true ;
@@ -203,12 +203,10 @@ protected int onLoadCallback(JNIJavaVM vm, JvmtiEnv jvmti, JvmtiEventCallbacks c
203203 build = Boolean .parseBoolean (getTokenValue (token ));
204204 } else if (token .equals ("experimental-configuration-with-origins" )) {
205205 configurationWithOrigins = true ;
206- } else if (token .startsWith ("experimental-conditional-config-for-package=" )) {
207- String userPackagePrefix = getTokenValue (token );
208- conditionalConfigUserPackagePrefixes .add (userPackagePrefix );
209- } else if (token .startsWith ("conditional-config-class-name-exclude-pattern=" )) {
210- String classNamePattern = getTokenValue (token );
211- conditionalConfigClassNameExcludePatterns .add (Pattern .compile (classNamePattern ));
206+ } else if (token .startsWith ("experimental-conditional-config-filter-file=" )) {
207+ conditionalConfigUserPackageFilterFiles .add (getTokenValue (token ));
208+ } else if (token .startsWith ("conditional-config-class-name-filter-file=" )) {
209+ conditionalConfigClassNameFilterFiles .add (getTokenValue (token ));
212210 } else if (token .equals ("track-reflection-metadata" )) {
213211 trackReflectionMetadata = true ;
214212 } else if (token .startsWith ("track-reflection-metadata=" )) {
@@ -223,7 +221,7 @@ protected int onLoadCallback(JNIJavaVM vm, JvmtiEnv jvmti, JvmtiEventCallbacks c
223221 inform ("no output/build options provided, tracking dynamic accesses and writing configuration to directory: " + configOutputDir );
224222 }
225223
226- if (configurationWithOrigins && !conditionalConfigUserPackagePrefixes .isEmpty ()) {
224+ if (configurationWithOrigins && !conditionalConfigUserPackageFilterFiles .isEmpty ()) {
227225 return error (5 , "The agent can only be used in either the configuration with origins mode or the predefined classes mode." );
228226 }
229227
@@ -236,29 +234,32 @@ protected int onLoadCallback(JNIJavaVM vm, JvmtiEnv jvmti, JvmtiEventCallbacks c
236234 warn ("using experimental configuration with origins mode. Note that native-image cannot process these files, and this flag may change or be removed without a warning!" );
237235 }
238236
239- RuleNode callerFilter = null ;
237+ ComplexFilter callerFilter = null ;
238+ RuleNode callerFilterRuleNode = null ;
240239 if (!builtinCallerFilter ) {
241- callerFilter = RuleNode .createRoot ();
242- callerFilter . addOrGetChildren ( "**" , RuleNode . Inclusion . Include );
240+ callerFilterRuleNode = RuleNode .createRootWithIncludedChildren ();
241+ callerFilter = new ComplexFilter ( callerFilterRuleNode );
243242 }
243+
244244 if (!callerFilterFiles .isEmpty ()) {
245- if (callerFilter == null ) {
246- callerFilter = AccessAdvisor .copyBuiltinCallerFilterTree ();
245+ if (callerFilterRuleNode == null ) {
246+ callerFilterRuleNode = AccessAdvisor .copyBuiltinCallerFilterTree ();
247+ callerFilter = new ComplexFilter (callerFilterRuleNode );
247248 }
248249 if (!parseFilterFiles (callerFilter , callerFilterFiles )) {
249250 return 1 ;
250251 }
251252 }
252253
253- RuleNode accessFilter = null ;
254+ ComplexFilter accessFilter = null ;
254255 if (!accessFilterFiles .isEmpty ()) {
255- accessFilter = AccessAdvisor .copyBuiltinAccessFilterTree ();
256+ accessFilter = new ComplexFilter ( AccessAdvisor .copyBuiltinAccessFilterTree () );
256257 if (!parseFilterFiles (accessFilter , accessFilterFiles )) {
257258 return 1 ;
258259 }
259260 }
260261
261- boolean shouldTraceOriginInformation = configurationWithOrigins || !conditionalConfigUserPackagePrefixes .isEmpty ();
262+ boolean shouldTraceOriginInformation = configurationWithOrigins || !conditionalConfigUserPackageFilterFiles .isEmpty ();
262263 final MethodInfoRecordKeeper recordKeeper = new MethodInfoRecordKeeper (shouldTraceOriginInformation );
263264 final Supplier <InterceptedState > interceptedStateSupplier = shouldTraceOriginInformation ? EagerlyLoadedJavaStackAccess .stackAccessSupplier ()
264265 : OnDemandJavaStackAccess .stackAccessSupplier ();
@@ -307,9 +308,23 @@ protected int onLoadCallback(JNIJavaVM vm, JvmtiEnv jvmti, JvmtiEventCallbacks c
307308 ConfigurationWithOriginsWriter writer = new ConfigurationWithOriginsWriter (processor , recordKeeper );
308309 tracer = writer ;
309310 tracingResultWriter = writer ;
310- } else if (!conditionalConfigUserPackagePrefixes .isEmpty ()) {
311- ConditionalConfigurationPredicate filter = new ConditionalConfigurationPredicate (conditionalConfigClassNameExcludePatterns );
312- ConditionalConfigurationWriter writer = new ConditionalConfigurationWriter (processor , recordKeeper , conditionalConfigUserPackagePrefixes , filter );
311+ } else if (!conditionalConfigUserPackageFilterFiles .isEmpty ()) {
312+ ComplexFilter userCodeFilter = new ComplexFilter (RuleNode .createRoot ());
313+ if (!parseFilterFiles (userCodeFilter , conditionalConfigUserPackageFilterFiles )) {
314+ return 2 ;
315+ }
316+ ComplexFilter classNameFilter ;
317+ if (!conditionalConfigClassNameFilterFiles .isEmpty ()) {
318+ classNameFilter = new ComplexFilter (RuleNode .createRoot ());
319+ if (!parseFilterFiles (classNameFilter , conditionalConfigClassNameFilterFiles )) {
320+ return 3 ;
321+ }
322+ } else {
323+ classNameFilter = new ComplexFilter (RuleNode .createRootWithIncludedChildren ());
324+ }
325+
326+ ConditionalConfigurationPredicate predicate = new ConditionalConfigurationPredicate (classNameFilter );
327+ ConditionalConfigurationWriter writer = new ConditionalConfigurationWriter (processor , recordKeeper , userCodeFilter , predicate );
313328 tracer = writer ;
314329 tracingResultWriter = writer ;
315330 } else {
@@ -389,7 +404,7 @@ private static <T> T usage(T result, String message) {
389404 return result ;
390405 }
391406
392- private static AccessAdvisor createAccessAdvisor (boolean builtinHeuristicFilter , RuleNode callerFilter , RuleNode accessFilter ) {
407+ private static AccessAdvisor createAccessAdvisor (boolean builtinHeuristicFilter , ConfigurationFilter callerFilter , ConfigurationFilter accessFilter ) {
393408 AccessAdvisor advisor = new AccessAdvisor ();
394409 advisor .setHeuristicsEnabled (builtinHeuristicFilter );
395410 if (callerFilter != null ) {
@@ -409,15 +424,15 @@ private static int parseIntegerOrNegative(String number) {
409424 }
410425 }
411426
412- private static boolean parseFilterFiles (RuleNode filter , List <String > filterFiles ) {
427+ private static boolean parseFilterFiles (ComplexFilter filter , List <String > filterFiles ) {
413428 for (String path : filterFiles ) {
414429 try {
415430 new FilterConfigurationParser (filter ).parseAndRegister (Paths .get (path ).toUri ());
416431 } catch (Exception e ) {
417432 return error (false , "cannot parse filter file " + path + ": " + e );
418433 }
419434 }
420- filter .removeRedundantNodes ();
435+ filter .getRuleNode (). removeRedundantNodes ();
421436 return true ;
422437 }
423438
0 commit comments