com.redhat.lightblue.config.LightblueFactory.java Source code

Java tutorial

Introduction

Here is the source code for com.redhat.lightblue.config.LightblueFactory.java

Source

/*
 Copyright 2013 Red Hat, Inc. and/or its affiliates.
    
 This file is part of lightblue.
    
 This program is free software: you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
 the Free Software Foundation, either version 3 of the License, or
 (at your option) any later version.
    
 This program is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 GNU General Public License for more details.
    
 You should have received a copy of the GNU General Public License
 along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
package com.redhat.lightblue.config;

import java.io.IOException;
import java.io.InputStream;
import java.io.Serializable;
import java.lang.reflect.InvocationTargetException;
import java.util.Map;

import com.redhat.lightblue.hooks.SimpleHookResolver;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.node.JsonNodeFactory;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.redhat.lightblue.Request;
import com.redhat.lightblue.crud.CRUDController;
import com.redhat.lightblue.crud.CrudConstants;
import com.redhat.lightblue.crud.DeleteRequest;
import com.redhat.lightblue.crud.Factory;
import com.redhat.lightblue.crud.FindRequest;
import com.redhat.lightblue.crud.InsertionRequest;
import com.redhat.lightblue.crud.SaveRequest;
import com.redhat.lightblue.crud.UpdateRequest;
import com.redhat.lightblue.crud.interceptors.UIDInterceptor;
import com.redhat.lightblue.crud.validator.DefaultFieldConstraintValidators;
import com.redhat.lightblue.mediator.Mediator;
import com.redhat.lightblue.metadata.EntityInfo;
import com.redhat.lightblue.metadata.EntityMetadata;
import com.redhat.lightblue.metadata.EntitySchema;
import com.redhat.lightblue.metadata.Metadata;
import com.redhat.lightblue.metadata.MetadataConstants;
import com.redhat.lightblue.metadata.parser.DataStoreParser;
import com.redhat.lightblue.metadata.parser.Extensions;
import com.redhat.lightblue.metadata.parser.JSONMetadataParser;
import com.redhat.lightblue.metadata.types.DefaultTypes;
import com.redhat.lightblue.util.JsonUtils;

/**
 * Manager class that creates instances of Mediator, Factory, Metadata, etc.
 * based on configuration.
 */
public final class LightblueFactory implements Serializable {

    private static final long serialVersionUID = 1l;

    private static final Logger LOGGER = LoggerFactory.getLogger(LightblueFactory.class);

    private final DataSourcesConfiguration datasources;
    private final JsonNode crudNode;
    private final JsonNode metadataNode;

    private static final JsonNodeFactory NODE_FACTORY = JsonNodeFactory.withExactBigDecimals(true);

    private volatile Metadata metadata = null;
    private transient volatile JSONMetadataParser parser = null;
    private transient volatile Mediator mediator = null;
    private volatile Factory factory;
    private transient volatile JsonTranslator jsonTranslator = null;

    public LightblueFactory(DataSourcesConfiguration datasources) {
        this(datasources, null, null);
    }

    public LightblueFactory(DataSourcesConfiguration datasources, JsonNode crudNode, JsonNode metadataNode) {
        this.datasources = datasources;
        this.crudNode = crudNode;
        this.metadataNode = metadataNode;
    }

    private synchronized void initializeParser() throws NoSuchMethodException, InvocationTargetException,
            IllegalAccessException, IOException, InstantiationException {
        if (parser == null) {
            Extensions<JsonNode> extensions = new Extensions<>();
            extensions.addDefaultExtensions();

            Map<String, DataSourceConfiguration> ds = datasources.getDataSources();
            for (Map.Entry<String, DataSourceConfiguration> entry : ds.entrySet()) {
                Class<? extends DataStoreParser> tempParser = entry.getValue().getMetadataDataStoreParser();
                DataStoreParser backendParser = tempParser.newInstance();
                extensions.registerDataStoreParser(backendParser.getDefaultName(), backendParser);
            }

            parser = new JSONMetadataParser(extensions, new DefaultTypes(), NODE_FACTORY);
        }
    }

    private synchronized void initializeMediator() throws ClassNotFoundException, IllegalAccessException,
            InvocationTargetException, IOException, NoSuchMethodException, InstantiationException {
        if (mediator == null) {
            mediator = new Mediator(getMetadata(), getFactory());
        }
    }

    private synchronized void initializeFactory() throws ClassNotFoundException, IllegalAccessException,
            InvocationTargetException, IOException, NoSuchMethodException, InstantiationException {
        if (factory == null) {
            JsonNode root = crudNode;
            if (root == null) {
                try (InputStream is = Thread.currentThread().getContextClassLoader()
                        .getResourceAsStream(CrudConfiguration.FILENAME)) {
                    root = JsonUtils.json(is);
                }
            }

            // convert root to Configuration object
            CrudConfiguration configuration = new CrudConfiguration();
            configuration.initializeFromJson(root);

            // Set validation flag for all crud requests
            getJsonTranslator().setValidation(Request.class, configuration.isValidateRequests());

            Factory f = new Factory();
            f.addFieldConstraintValidators(new DefaultFieldConstraintValidators());

            // Add default interceptors
            new UIDInterceptor().register(f.getInterceptors());

            // validate
            if (!configuration.isValid()) {
                throw new IllegalStateException(
                        CrudConstants.ERR_CONFIG_NOT_VALID + " - " + CrudConfiguration.FILENAME);
            }

            for (ControllerConfiguration x : configuration.getControllers()) {
                ControllerFactory cfactory = x.getControllerFactory().newInstance();
                CRUDController controller = cfactory.createController(x, datasources);
                f.addCRUDController(x.getBackend(), controller);
            }
            // Make sure we assign factory after it is initialized. (factory is volatile, there's a memory barrier here)
            factory = f;
        }
    }

    private synchronized void initializeMetadata(Factory factory) throws IOException, ClassNotFoundException,
            NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
        if (metadata == null) {
            LOGGER.debug("Initializing metadata");

            JsonNode root = metadataNode;
            if (root == null) {
                try (InputStream is = Thread.currentThread().getContextClassLoader()
                        .getResourceAsStream(MetadataConfiguration.FILENAME)) {
                    root = JsonUtils.json(is);
                }
            }
            LOGGER.debug("Config root:{}", root);

            JsonNode cfgClass = root.get("type");
            if (cfgClass == null) {
                throw new IllegalStateException(MetadataConstants.ERR_CONFIG_NOT_FOUND + " - type");
            }

            MetadataConfiguration cfg = (MetadataConfiguration) Class.forName(cfgClass.asText()).newInstance();
            cfg.initializeFromJson(root);

            // Set validation flag for all metadata requests
            getJsonTranslator().setValidation(EntityMetadata.class, cfg.isValidateRequests());
            getJsonTranslator().setValidation(EntitySchema.class, cfg.isValidateRequests());
            getJsonTranslator().setValidation(EntityInfo.class, cfg.isValidateRequests());

            metadata = cfg.createMetadata(datasources, getJSONParser(), this);
            factory.setHookResolver(new SimpleHookResolver(cfg.getHookConfigurationParsers()));
        }
    }

    private synchronized void initializeJsonTranslator() {
        if (jsonTranslator == null) {
            LOGGER.debug("Initializing JsonTranslator");

            JsonTranslator tx = new JsonTranslator();

            tx.registerTranslation(EntityMetadata.class, new JsonTranslator.FromJson() {
                @Override
                public Object fromJson(JsonNode node) {
                    try {
                        return getJSONParser().parseEntityMetadata(node);
                    } catch (RuntimeException re) {
                        throw re;
                    } catch (Exception e) {
                        throw new RuntimeException(e);
                    }
                }
            }, "json-schema/metadata/metadata.json");
            tx.registerTranslation(EntityInfo.class, new JsonTranslator.FromJson() {
                @Override
                public Object fromJson(JsonNode node) {
                    try {
                        return getJSONParser().parseEntityInfo(node);
                    } catch (RuntimeException re) {
                        throw re;
                    } catch (Exception e) {
                        throw new RuntimeException(e);
                    }
                }
            }, "json-schema/metadata/entityInfo.json");
            tx.registerTranslation(EntitySchema.class, new JsonTranslator.FromJson() {
                @Override
                public Object fromJson(JsonNode node) {
                    try {
                        return getJSONParser().parseEntitySchema(node);
                    } catch (RuntimeException re) {
                        throw re;
                    } catch (Exception e) {
                        throw new RuntimeException(e);
                    }
                }
            }, "json-schema/metadata/schema.json");

            try {
                tx.registerTranslation(FindRequest.class,
                        new JsonTranslator.StaticFactoryMethod(FindRequest.class, "fromJson", ObjectNode.class),
                        "json-schema/findRequest.json");
                tx.registerTranslation(InsertionRequest.class, new JsonTranslator.StaticFactoryMethod(
                        InsertionRequest.class, "fromJson", ObjectNode.class), "json-schema/insertRequest.json");
                tx.registerTranslation(DeleteRequest.class,
                        new JsonTranslator.StaticFactoryMethod(DeleteRequest.class, "fromJson", ObjectNode.class),
                        "json-schema/deleteRequest.json");
                tx.registerTranslation(SaveRequest.class,
                        new JsonTranslator.StaticFactoryMethod(SaveRequest.class, "fromJson", ObjectNode.class),
                        "json-schema/saveRequest.json");
                tx.registerTranslation(UpdateRequest.class,
                        new JsonTranslator.StaticFactoryMethod(UpdateRequest.class, "fromJson", ObjectNode.class),
                        "json-schema/updateRequest.json");
            } catch (RuntimeException re) {
                throw re;
            } catch (Exception e) {
                throw new RuntimeException(e);
            }

            jsonTranslator = tx;
        }
    }

    public Metadata getMetadata() throws IOException, ClassNotFoundException, NoSuchMethodException,
            IllegalAccessException, InvocationTargetException, InstantiationException {
        if (metadata == null) {
            initializeMetadata(getFactory());
        }

        return metadata;
    }

    public JSONMetadataParser getJSONParser() throws ClassNotFoundException, NoSuchMethodException, IOException,
            IllegalAccessException, InvocationTargetException, InstantiationException {
        if (parser == null) {
            initializeParser();

            // Metadata is loaded next because the hooks need to be registered on the Factory.
            getMetadata();
        }

        return parser;
    }

    public Factory getFactory() throws ClassNotFoundException, IllegalAccessException, InvocationTargetException,
            IOException, NoSuchMethodException, InstantiationException {
        if (factory == null) {
            initializeFactory();
        }
        return factory;
    }

    public Mediator getMediator() throws ClassNotFoundException, IllegalAccessException, InvocationTargetException,
            IOException, NoSuchMethodException, InstantiationException {
        if (mediator == null) {
            initializeMediator();
        }

        return mediator;
    }

    public JsonTranslator getJsonTranslator() {
        if (jsonTranslator == null) {
            initializeJsonTranslator();
        }
        return jsonTranslator;
    }
}