001/*
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements.  See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License.  You may obtain a copy of the License at
008 *
009 *      http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017package org.apache.juneau.commons.bean;
018
019import java.util.*;
020import java.util.concurrent.atomic.*;
021
022/**
023 * Discovery helper for {@link PropertyValidatorFactory} via {@link ServiceLoader ServiceLoader}.
024 *
025 * <p>
026 * Used by the marshalling side (e.g. {@code MarshalledPropertyPostProcessor}) to obtain a validator factory at
027 * {@link BeanMeta} construction time without taking a hard compile-time dependency on the
028 * {@code juneau-bean-jsonschema} module.
029 *
030 * <p>
031 * If no factory is registered, {@link #factory()} returns <jk>null</jk> and schema-validation mode becomes a silent
032 * no-op.  Callers can override the resolved factory at runtime via {@link #setFactory(PropertyValidatorFactory)} as an
033 * escape hatch for multi-classloader / OSGi environments where {@link ServiceLoader} discovery does not see provider
034 * jars on the consumer classloader.
035 *
036 * @see PropertyValidator
037 * @see PropertyValidatorFactory
038 * @since 10.0.0
039 */
040public final class PropertyValidators {
041
042   private static final AtomicReference<PropertyValidatorFactory> factory = new AtomicReference<>(resolve());
043
044   private PropertyValidators() {
045   }
046
047   /**
048    * Returns the registered factory, or <jk>null</jk> if none is on the classpath.
049    *
050    * @return The factory, or <jk>null</jk>.
051    */
052   public static PropertyValidatorFactory factory() {
053      return factory.get();
054   }
055
056   /**
057    * Overrides the factory resolved via {@link ServiceLoader}.
058    *
059    * <p>
060    * Pass <jk>null</jk> to disable schema validation entirely.
061    *
062    * @param value The factory to use, or <jk>null</jk> to disable.
063    */
064   public static void setFactory(PropertyValidatorFactory value) {
065      factory.set(value);
066   }
067
068   private static PropertyValidatorFactory resolve() {
069      var it = ServiceLoader.load(PropertyValidatorFactory.class).iterator();
070      return it.hasNext() ? it.next() : null;
071   }
072}