4545import static java .io .ObjectInputFilter .Status .*;
4646import static java .lang .System .Logger .Level .TRACE ;
4747import static java .lang .System .Logger .Level .DEBUG ;
48+ import static java .lang .System .Logger .Level .ERROR ;
4849
4950/**
5051 * Filter classes, array lengths, and graph metrics during deserialization.
@@ -308,10 +309,12 @@ public interface ObjectInputFilter {
308309 * <li>Otherwise, return {@code otherStatus}.</li>
309310 * </ul>
310311 * <p>
311- * Example, to create a filter that will allow any class loaded from the platform classloader.
312+ * Example, to create a filter that will allow any class loaded from the platform
313+ * or bootstrap classloaders.
312314 * <pre><code>
313- * ObjectInputFilter f = allowFilter(cl -> cl.getClassLoader() == ClassLoader.getPlatformClassLoader()
314- * || cl.getClassLoader() == null, Status.UNDECIDED);
315+ * ObjectInputFilter f
316+ * = allowFilter(cl -> cl.getClassLoader() == ClassLoader.getPlatformClassLoader() ||
317+ * cl.getClassLoader() == null, Status.UNDECIDED);
315318 * </code></pre>
316319 *
317320 * @param predicate a predicate to test a non-null Class
@@ -527,23 +530,17 @@ enum Status {
527530 * The syntax for the property value is the same as for the
528531 * {@link #createFilter(String) createFilter} method.
529532 *
530- * <p> If only `jdk.serialFilter` is set and not `jdk.serialFilterFactory` the builtin
531- * filter factory, compatible with previous versions, is set and can not be replaced,
532- * see below to override the builtin filter factory.
533533 * <p>
534534 * If the Java virtual machine is started with the system property
535535 * {@systemProperty jdk.serialFilterFactory} or the {@link java.security.Security} property
536536 * of the same name, its value names the class to configure the JVM-wide deserialization
537- * filter factory or the special value `OVERRIDE` .
537+ * filter factory.
538538 * If the system property is not defined, and the {@link java.security.Security} property
539539 * {@code jdk.serialFilterFactory} is defined then it is used to configure the filter factory.
540- *
541- * If the value is `OVERRIDE`, the filter factory can be set by the application before
542- * the first deserialization using {@link Config#setSerialFilterFactory(BinaryOperator)};
543540 * If it remains unset, the filter factory is a builtin filter factory compatible
544541 * with previous versions.
545542 *
546- * <p>If not `OVERRIDE`, the class must be public, must have a public zero-argument constructor, implement the
543+ * <p>The class must be public, must have a public zero-argument constructor, implement the
547544 * {@link BinaryOperator {@literal BinaryOperator<ObjectInputFilter>}} interface, provide its implementation and
548545 * be accessible via the {@linkplain ClassLoader#getSystemClassLoader() application class loader}.
549546 * If the filter factory constructor is not invoked successfully, an {@link ExceptionInInitializerError}
@@ -579,11 +576,6 @@ final class Config {
579576 */
580577 private static final String SERIAL_FILTER_FACTORY_PROPNAME = "jdk.serialFilterFactory" ;
581578
582- /**
583- * The property name to enable tracing of filters.
584- */
585- private static final String SERIAL_FILTER_TRACE_PROPNAME = "jdk.serialFilterTrace" ;
586-
587579 /**
588580 * Current static filter.
589581 */
@@ -599,34 +591,30 @@ final class Config {
599591 * Boolean to indicate that the filter factory can not be set or replaced.
600592 * - an ObjectInputStream has already been created using the current filter factory
601593 * - has been set on the command line
602- * - jdk.serialFilter is set and jdk.serialFilterFactory is unset, the builtin can not be replaced
603594 * @see Config#setSerialFilterFactory(BinaryOperator)
604595 */
605596 private static final AtomicBoolean filterFactoryNoReplace = new AtomicBoolean ();
606597
607598 /**
608- * Debug: Logger
599+ * Debug and Trace Logger
609600 */
610601 private static final System .Logger configLog ;
611602
612- /**
613- * True when tracing of filters is enabled.
614- */
615- private static final boolean traceFilters ;
616-
617603 static {
618604 /*
619605 * Initialize the configuration containing the filter factory, static filter, and logger.
620606 * <ul>
607+ * <li>The logger is created.
621608 * <li>The property 'jdk.serialFilter" is read, either as a system property or a security property,
622609 * and if set, defines the configured static JVM-wide filter and is logged.
623610 * <li>The property jdk.serialFilterFactory is read, either as a system property or a security property,
624611 * and if set, defines the initial filter factory and is logged.
625- * <li>The property jdk.serialFilterTrace, is read, and if set enables tracing of filters.
626- * <li>If either property is defined or tracing is enabled, the logger is created.
627612 * </ul>
628613 */
629614
615+ // Initialize the logger.
616+ configLog = System .getLogger ("java.io.serialization" );
617+
630618 // Get the values of the system properties, if they are defined
631619 String factoryClassName = StaticProperty .jdkSerialFilterFactory ();
632620 if (factoryClassName == null ) {
@@ -642,12 +630,6 @@ final class Config {
642630 Security .getProperty (SERIAL_FILTER_PROPNAME ));
643631 }
644632
645- traceFilters = GetBooleanAction .privilegedGetProperty (SERIAL_FILTER_TRACE_PROPNAME );
646-
647- // Initialize the logger if either filter factory or filter property is set
648- configLog = (filterString != null || factoryClassName != null || traceFilters )
649- ? System .getLogger ("java.io.serialization" ) : null ;
650-
651633 // Initialize the static filter if the jdk.serialFilter is present
652634 ObjectInputFilter filter = null ;
653635 if (filterString != null ) {
@@ -656,53 +638,40 @@ final class Config {
656638 try {
657639 filter = createFilter (filterString );
658640 } catch (RuntimeException re ) {
659- configLog .log (System . Logger . Level . ERROR ,
641+ configLog .log (ERROR ,
660642 "Error configuring filter: {0}" , re );
661643 }
662644 }
663645 serialFilter = filter ;
664646
665647 // Initialize the filter factory if the jdk.serialFilterFactory is defined
666648 // otherwise use the builtin filter factory.
667- if (factoryClassName == null || "OVERRIDE" . equals ( factoryClassName ) ) {
649+ if (factoryClassName == null ) {
668650 serialFilterFactory = new BuiltinFilterFactory ();
669- if (serialFilter != null && factoryClassName == null ) {
670- // Ensure backward compatibility, unless factory is explicitly allowed to override
671- // Do not allow factory to be overridden by Config.setSerialFilterFactory
672- filterFactoryNoReplace .set (true );
673- }
674-
675651 } else {
676- configLog .log (DEBUG ,
677- "Creating deserialization filter factory for {0}" , factoryClassName );
678652 try {
679653 // Load using the system class loader, the named class may be an application class.
680- // The static initialization of the class or constructor may create a race
681- // if either calls Config.setSerialFilterFactory; the command line configured
682- // Class should not be overridden.
654+ // Cause Config.setSerialFilterFactory to throw {@link IllegalStateException}
655+ // if Config.setSerialFilterFactory is called as a side effect of the
656+ // static initialization of the class or constructor.
657+ filterFactoryNoReplace .set (true );
658+
683659 Class <?> factoryClass = Class .forName (factoryClassName , true ,
684660 ClassLoader .getSystemClassLoader ());
685661 @ SuppressWarnings ("unchecked" )
686- BinaryOperator <ObjectInputFilter > f =
662+ BinaryOperator <ObjectInputFilter > factory =
687663 (BinaryOperator <ObjectInputFilter >)
688664 factoryClass .getConstructor ().newInstance (new Object [0 ]);
689- if (serialFilterFactory != null ) {
690- // Init cycle if Config.setSerialFilterFactory called from class initialization
691- configLog .log (System .Logger .Level .ERROR ,
692- "FilterFactory provided on the command line can not be overridden" );
693- // Do not continue if configuration not initialized
694- throw new ExceptionInInitializerError (
695- "FilterFactory provided on the command line can not be overridden" );
696- }
697- serialFilterFactory = f ;
698- filterFactoryNoReplace .set (true );
665+ configLog .log (DEBUG ,
666+ "Creating deserialization filter factory for {0}" , factoryClassName );
667+ serialFilterFactory = factory ;
699668 } catch (RuntimeException | ClassNotFoundException | NoSuchMethodException |
700669 IllegalAccessException | InstantiationException | InvocationTargetException ex ) {
701- configLog .log (System .Logger .Level .ERROR ,
702- "Error configuring filter factory" , ex );
670+ Throwable th = (ex instanceof InvocationTargetException ite ) ? ite .getCause () : ex ;
671+ configLog .log (ERROR ,
672+ "Error configuring filter factory: {0}" , (Object )th );
703673 // Do not continue if configuration not initialized
704- throw new ExceptionInInitializerError (
705- "FilterFactory configuration: jdk.serialFilterFactory: " + ex .getMessage ());
674+ throw new ExceptionInInitializerError (th );
706675 }
707676 }
708677 // Setup shared secrets for RegistryImpl to use.
@@ -719,9 +688,7 @@ private Config() {
719688 * Logger for filter actions.
720689 */
721690 private static void traceFilter (String msg , Object ... args ) {
722- if (traceFilters && configLog != null ) {
723- configLog .log (TRACE , msg , args );
724- }
691+ configLog .log (TRACE , msg , args );
725692 }
726693
727694 /**
@@ -840,12 +807,14 @@ public static void setSerialFilterFactory(BinaryOperator<ObjectInputFilter> filt
840807 if (sm != null ) {
841808 sm .checkPermission (ObjectStreamConstants .SERIAL_FILTER_PERMISSION );
842809 }
843- if (serialFilterFactory == null )
844- throw new IllegalStateException ("Serial filter factory initialization incomplete" );
845810 if (filterFactoryNoReplace .getAndSet (true )) {
846- throw new IllegalStateException ("Cannot replace filter factory: " +
847- serialFilterFactory .getClass ().getName ());
811+ final String msg = serialFilterFactory != null
812+ ? serialFilterFactory .getClass ().getName ()
813+ : "initialization incomplete" ;
814+ throw new IllegalStateException ("Cannot replace filter factory: " + msg );
848815 }
816+ configLog .log (DEBUG ,
817+ "Setting deserialization filter factory to {0}" , filterFactory .getClass ().getName ());
849818 serialFilterFactory = filterFactory ;
850819 }
851820
@@ -1163,7 +1132,7 @@ public Status checkInput(FilterInfo filterInfo) {
11631132 }
11641133 if (!checkComponentType ) {
11651134 // As revised; do not check the component type for arrays
1166- traceFilter ("Pattern array class: {0}, filter: {1}" , clazz , this );
1135+ traceFilter ("Pattern filter array class: {0}, filter: {1}" , clazz , this );
11671136 return Status .UNDECIDED ;
11681137 }
11691138 do {
@@ -1174,7 +1143,7 @@ public Status checkInput(FilterInfo filterInfo) {
11741143
11751144 if (clazz .isPrimitive ()) {
11761145 // Primitive types are undecided; let someone else decide
1177- traceFilter ("Pattern UNDECIDED, primitive class: {0}, filter: {1}" , clazz , this );
1146+ traceFilter ("Pattern filter UNDECIDED, primitive class: {0}, filter: {1}" , clazz , this );
11781147 return UNDECIDED ;
11791148 } else {
11801149 // Find any filter that allowed or rejected the class
@@ -1184,7 +1153,7 @@ public Status checkInput(FilterInfo filterInfo) {
11841153 .filter (p -> p != Status .UNDECIDED )
11851154 .findFirst ();
11861155 Status s = status .orElse (Status .UNDECIDED );
1187- traceFilter ("Pattern {0}, class: {1}, filter: {2}" , s , cl , this );
1156+ traceFilter ("Pattern filter {0}, class: {1}, filter: {2}" , s , cl , this );
11881157 return s ;
11891158 }
11901159 }
@@ -1283,18 +1252,18 @@ private static class MergeFilter implements ObjectInputFilter {
12831252 public ObjectInputFilter .Status checkInput (FilterInfo info ) {
12841253 Status firstStatus = Objects .requireNonNull (first .checkInput (info ), "status" );
12851254 if (REJECTED .equals (firstStatus )) {
1286- traceFilter ("MergeFilter REJECT first: {0}, filter: {1}" ,
1255+ traceFilter ("MergeFilter REJECTED first: {0}, filter: {1}" ,
12871256 firstStatus , this );
12881257 return REJECTED ;
12891258 }
12901259 Status secondStatus = Objects .requireNonNull (second .checkInput (info ), "other status" );
12911260 if (REJECTED .equals (secondStatus )) {
1292- traceFilter ("MergeFilter REJECT {0}, {1}, filter: {2}" ,
1261+ traceFilter ("MergeFilter REJECTED {0}, {1}, filter: {2}" ,
12931262 firstStatus , secondStatus , this );
12941263 return REJECTED ;
12951264 }
12961265 if (ALLOWED .equals (firstStatus ) || ALLOWED .equals (secondStatus )) {
1297- traceFilter ("MergeFilter ALLOW either: {0}, {1}, filter: {2}" ,
1266+ traceFilter ("MergeFilter ALLOWED either: {0}, {1}, filter: {2}" ,
12981267 firstStatus , secondStatus , this );
12991268 return ALLOWED ;
13001269 }
@@ -1332,7 +1301,6 @@ public ObjectInputFilter.Status checkInput(FilterInfo info) {
13321301 Class <?> clazz = info .serialClass ();
13331302 if (clazz == null || !UNDECIDED .equals (status ))
13341303 return status ;
1335- status = REJECTED ;
13361304 // Find the base component type
13371305 while (clazz .isArray ()) {
13381306 clazz = clazz .getComponentType ();
0 commit comments