All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.eclipse.yasson.internal.JsonbContext Maven / Gradle / Ivy

There is a newer version: 3.0.4
Show newest version
/*
 * Copyright (c) 2016, 2022 Oracle and/or its affiliates. All rights reserved.
 *
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Public License v. 2.0 which is available at
 * http://www.eclipse.org/legal/epl-2.0,
 * or the Eclipse Distribution License v. 1.0 which is available at
 * http://www.eclipse.org/org/documents/edl-v10.php.
 *
 * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
 */

package org.eclipse.yasson.internal;

import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.ServiceLoader;
import java.util.logging.Logger;

import jakarta.json.bind.JsonbConfig;
import jakarta.json.bind.JsonbException;
import jakarta.json.spi.JsonProvider;
import jakarta.json.stream.JsonGenerator;
import jakarta.json.stream.JsonParserFactory;

import org.eclipse.yasson.internal.components.JsonbComponentInstanceCreatorFactory;
import org.eclipse.yasson.internal.deserializer.DeserializationModelCreator;
import org.eclipse.yasson.internal.properties.MessageKeys;
import org.eclipse.yasson.internal.properties.Messages;
import org.eclipse.yasson.internal.serializer.SerializationModelCreator;
import org.eclipse.yasson.spi.JsonbComponentInstanceCreator;

/**
 * Jsonb context holding central components and configuration of jsonb runtime. Scoped to instance of Jsonb runtime.
 */
public class JsonbContext {

    private static final Logger LOGGER = Logger.getLogger(JsonbContext.class.getName());

    private final JsonbConfig jsonbConfig;

    private final MappingContext mappingContext;

    private final DeserializationModelCreator deserializationModelCreator;

    private final SerializationModelCreator serializationModelCreator;

    private final JsonbComponentInstanceCreator componentInstanceCreator;

    private final JsonProvider jsonProvider;

    private final JsonParserFactory jsonParserFactory;

    private final ComponentMatcher componentMatcher;

    private final AnnotationIntrospector annotationIntrospector;

    private final JsonbConfigProperties configProperties;

    /**
     * Creates and initialize context.
     *
     * @param jsonbConfig  jsonb jsonbConfig not null
     * @param jsonProvider provider of JSONP
     */
    public JsonbContext(JsonbConfig jsonbConfig, JsonProvider jsonProvider) {
        Objects.requireNonNull(jsonbConfig);
        this.jsonbConfig = jsonbConfig;
        this.mappingContext = new MappingContext(this);
        this.componentInstanceCreator = initComponentInstanceCreator();
        this.componentMatcher = new ComponentMatcher(this);
        this.annotationIntrospector = new AnnotationIntrospector(this);
        this.jsonProvider = jsonProvider;
        this.jsonParserFactory = initJsonParserFactory();
        this.configProperties = new JsonbConfigProperties(jsonbConfig);
        this.deserializationModelCreator = new DeserializationModelCreator(this);
        this.serializationModelCreator = new SerializationModelCreator(this);
    }

    /**
     * Gets {@link JsonbConfig}.
     *
     * @return Configuration.
     */
    public JsonbConfig getConfig() {
        return jsonbConfig;
    }

    /**
     * Gets mapping context.
     *
     * @return Mapping context.
     */
    public MappingContext getMappingContext() {
        return mappingContext;
    }

    /**
     * Get chain model creator.
     *
     * @return chain model creator
     */
    public DeserializationModelCreator getChainModelCreator() {
        return deserializationModelCreator;
    }

    /**
     * Get serialization model creator.
     *
     * @return serialization model creator
     */
    public SerializationModelCreator getSerializationModelCreator() {
        return serializationModelCreator;
    }

    /**
     * Gets JSONP provider.
     *
     * @return JSONP provider.
     */
    public JsonProvider getJsonProvider() {
        return jsonProvider;
    }

    /**
     * Implementation creating instances of user components used by JSONB, such as adapters and strategies.
     *
     * @return Instance creator.
     */
    public JsonbComponentInstanceCreator getComponentInstanceCreator() {
        return componentInstanceCreator;
    }

    /**
     * Component matcher for lookup of (de)serializers and adapters.
     *
     * @return Component matcher.
     */
    public ComponentMatcher getComponentMatcher() {
        return componentMatcher;
    }

    /**
     * Gets component for annotation parsing.
     *
     * @return Annotation introspector.
     */
    public AnnotationIntrospector getAnnotationIntrospector() {
        return annotationIntrospector;
    }

    public JsonbConfigProperties getConfigProperties() {
        return configProperties;
    }

    public JsonParserFactory getJsonParserFactory() {
        return jsonParserFactory;
    }

    private JsonParserFactory initJsonParserFactory() {
        return jsonProvider.createParserFactory(createJsonpProperties(jsonbConfig));
    }

    /**
     * Propagates properties from JsonbConfig to JSONP generator / parser factories.
     *
     * @param jsonbConfig jsonb config
     * @return properties for JSONP generator / parser
     */
    protected Map createJsonpProperties(JsonbConfig jsonbConfig) {
        //JSONP 1.0 actually ignores the value, just checks the key is present. Only set if JsonbConfig.FORMATTING is true.
        final Optional property = jsonbConfig.getProperty(JsonbConfig.FORMATTING);
        final Map factoryProperties = new HashMap<>();
        if (property.isPresent()) {
            final Object value = property.get();
            if (!(value instanceof Boolean)) {
                throw new JsonbException(Messages.getMessage(MessageKeys.JSONB_CONFIG_FORMATTING_ILLEGAL_VALUE));
            }
            if ((Boolean) value) {
                factoryProperties.put(JsonGenerator.PRETTY_PRINTING, Boolean.TRUE);
            }
            return factoryProperties;
        }
        return factoryProperties;
    }

    private JsonbComponentInstanceCreator initComponentInstanceCreator() {
        ServiceLoader loader = AccessController
                .doPrivileged((PrivilegedAction>) () -> ServiceLoader
                        .load(JsonbComponentInstanceCreator.class));
        List creators = new ArrayList<>();
        for (JsonbComponentInstanceCreator creator : loader) {
            creators.add(creator);
        }
        if (creators.isEmpty()) {
            // No service provider found - use the defaults
            return JsonbComponentInstanceCreatorFactory.getComponentInstanceCreator();
        }
        creators.sort(Comparator.comparingInt(JsonbComponentInstanceCreator::getPriority).reversed());
        JsonbComponentInstanceCreator creator = creators.get(0);
        LOGGER.finest("Component instance creator:" + creator.getClass());
        return creator;
    }

}