ObjectStreamClassPredicate.java

  1. /*
  2.  * Licensed to the Apache Software Foundation (ASF) under one
  3.  * or more contributor license agreements.  See the NOTICE file
  4.  * distributed with this work for additional information
  5.  * regarding copyright ownership.  The ASF licenses this file
  6.  * to you under the Apache License, Version 2.0 (the
  7.  * "License"); you may not use this file except in compliance
  8.  * with the License.  You may obtain a copy of the License at
  9.  *
  10.  *   http://www.apache.org/licenses/LICENSE-2.0
  11.  *
  12.  * Unless required by applicable law or agreed to in writing,
  13.  * software distributed under the License is distributed on an
  14.  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
  15.  * KIND, either express or implied.  See the License for the
  16.  * specific language governing permissions and limitations
  17.  * under the License.
  18.  */

  19. package org.apache.commons.io.serialization;

  20. import java.io.ObjectStreamClass;
  21. import java.util.ArrayList;
  22. import java.util.List;
  23. import java.util.function.Predicate;
  24. import java.util.regex.Pattern;
  25. import java.util.stream.Stream;

  26. /**
  27.  * A predicate (boolean-valued function) of one argument to accept and reject classes.
  28.  * <p>
  29.  * The reject list takes precedence over the accept list.
  30.  * </p>
  31.  *
  32.  * @since 2.18.0
  33.  */
  34. public class ObjectStreamClassPredicate implements Predicate<ObjectStreamClass> {

  35.     // This is not a Set for now to avoid ClassNameMatchers requiring proper implementations of hashCode() and equals().
  36.     private final List<ClassNameMatcher> acceptMatchers = new ArrayList<>();

  37.     // This is not a Set for now to avoid ClassNameMatchers requiring proper implementations of hashCode() and equals().
  38.     private final List<ClassNameMatcher> rejectMatchers = new ArrayList<>();

  39.     /**
  40.      * Constructs a new instance.
  41.      */
  42.     public ObjectStreamClassPredicate() {
  43.         // empty
  44.     }

  45.     /**
  46.      * Accepts the specified classes for deserialization, unless they are otherwise rejected.
  47.      * <p>
  48.      * The reject list takes precedence over the accept list.
  49.      * </p>
  50.      *
  51.      * @param classes Classes to accept
  52.      * @return this object
  53.      */
  54.     public ObjectStreamClassPredicate accept(final Class<?>... classes) {
  55.         Stream.of(classes).map(c -> new FullClassNameMatcher(c.getName())).forEach(acceptMatchers::add);
  56.         return this;
  57.     }

  58.     /**
  59.      * Accepts class names where the supplied ClassNameMatcher matches for deserialization, unless they are otherwise rejected.
  60.      * <p>
  61.      * The reject list takes precedence over the accept list.
  62.      * </p>
  63.      *
  64.      * @param matcher a class name matcher to <em>accept</em> objects.
  65.      * @return this instance.
  66.      */
  67.     public ObjectStreamClassPredicate accept(final ClassNameMatcher matcher) {
  68.         acceptMatchers.add(matcher);
  69.         return this;
  70.     }

  71.     /**
  72.      * Accepts class names that match the supplied pattern for deserialization, unless they are otherwise rejected.
  73.      * <p>
  74.      * The reject list takes precedence over the accept list.
  75.      * </p>
  76.      *
  77.      * @param pattern a Pattern for compiled regular expression.
  78.      * @return this instance.
  79.      */
  80.     public ObjectStreamClassPredicate accept(final Pattern pattern) {
  81.         acceptMatchers.add(new RegexpClassNameMatcher(pattern));
  82.         return this;
  83.     }

  84.     /**
  85.      * Accepts the wildcard specified classes for deserialization, unless they are otherwise rejected.
  86.      * <p>
  87.      * The reject list takes precedence over the accept list.
  88.      * </p>
  89.      *
  90.      * @param patterns Wildcard file name patterns as defined by {@link org.apache.commons.io.FilenameUtils#wildcardMatch(String, String)
  91.      *                 FilenameUtils.wildcardMatch}
  92.      * @return this instance.
  93.      */
  94.     public ObjectStreamClassPredicate accept(final String... patterns) {
  95.         Stream.of(patterns).map(WildcardClassNameMatcher::new).forEach(acceptMatchers::add);
  96.         return this;
  97.     }

  98.     /**
  99.      * Rejects the specified classes for deserialization, even if they are otherwise accepted.
  100.      * <p>
  101.      * The reject list takes precedence over the accept list.
  102.      * </p>
  103.      *
  104.      * @param classes Classes to reject
  105.      * @return this instance.
  106.      */
  107.     public ObjectStreamClassPredicate reject(final Class<?>... classes) {
  108.         Stream.of(classes).map(c -> new FullClassNameMatcher(c.getName())).forEach(rejectMatchers::add);
  109.         return this;
  110.     }

  111.     /**
  112.      * Rejects class names where the supplied ClassNameMatcher matches for deserialization, even if they are otherwise accepted.
  113.      * <p>
  114.      * The reject list takes precedence over the accept list.
  115.      * </p>
  116.      *
  117.      * @param m the matcher to use
  118.      * @return this instance.
  119.      */
  120.     public ObjectStreamClassPredicate reject(final ClassNameMatcher m) {
  121.         rejectMatchers.add(m);
  122.         return this;
  123.     }

  124.     /**
  125.      * Rejects class names that match the supplied pattern for deserialization, even if they are otherwise accepted.
  126.      * <p>
  127.      * The reject list takes precedence over the accept list.
  128.      * </p>
  129.      *
  130.      * @param pattern standard Java regexp
  131.      * @return this instance.
  132.      */
  133.     public ObjectStreamClassPredicate reject(final Pattern pattern) {
  134.         rejectMatchers.add(new RegexpClassNameMatcher(pattern));
  135.         return this;
  136.     }

  137.     /**
  138.      * Rejects the wildcard specified classes for deserialization, even if they are otherwise accepted.
  139.      * <p>
  140.      * The reject list takes precedence over the accept list.
  141.      * </p>
  142.      *
  143.      * @param patterns Wildcard file name patterns as defined by {@link org.apache.commons.io.FilenameUtils#wildcardMatch(String, String)
  144.      *                 FilenameUtils.wildcardMatch}
  145.      * @return this instance.
  146.      */
  147.     public ObjectStreamClassPredicate reject(final String... patterns) {
  148.         Stream.of(patterns).map(WildcardClassNameMatcher::new).forEach(rejectMatchers::add);
  149.         return this;
  150.     }

  151.     /**
  152.      * Tests that the ObjectStreamClass conforms to requirements.
  153.      * <p>
  154.      * The reject list takes precedence over the accept list.
  155.      * </p>
  156.      *
  157.      * @param objectStreamClass The ObjectStreamClass to test.
  158.      * @return true if the input is accepted, false if rejected, false if neither.
  159.      */
  160.     @Override
  161.     public boolean test(final ObjectStreamClass objectStreamClass) {
  162.         return test(objectStreamClass.getName());
  163.     }

  164.     /**
  165.      * Tests that the class name conforms to requirements.
  166.      * <p>
  167.      * The reject list takes precedence over the accept list.
  168.      * </p>
  169.      *
  170.      * @param name The class name to test.
  171.      * @return true if the input is accepted, false if rejected, false if neither.
  172.      */
  173.     public boolean test(final String name) {
  174.         // The reject list takes precedence over the accept list.
  175.         for (final ClassNameMatcher m : rejectMatchers) {
  176.             if (m.matches(name)) {
  177.                 return false;
  178.             }
  179.         }
  180.         for (final ClassNameMatcher m : acceptMatchers) {
  181.             if (m.matches(name)) {
  182.                 return true;
  183.             }
  184.         }
  185.         return false;
  186.     }

  187. }