org.jboss.dashboard.export.ImportManagerImpl.java Source code

Java tutorial

Introduction

Here is the source code for org.jboss.dashboard.export.ImportManagerImpl.java

Source

/**
 * Copyright (C) 2012 JBoss Inc
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.jboss.dashboard.export;

import java.io.InputStream;
import java.io.StringReader;
import java.util.Locale;
import javax.enterprise.context.ApplicationScoped;
import javax.inject.Inject;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;

import org.jboss.dashboard.DataDisplayerServices;
import org.jboss.dashboard.displayer.DataDisplayer;
import org.jboss.dashboard.displayer.DataDisplayerManager;
import org.jboss.dashboard.displayer.DataDisplayerRenderer;
import org.jboss.dashboard.displayer.DataDisplayerType;
import org.jboss.dashboard.kpi.KPI;
import org.jboss.dashboard.kpi.KPIManager;
import org.jboss.dashboard.provider.*;
import org.jboss.dashboard.LocaleManager;
import org.jboss.dashboard.commons.message.Message;
import org.jboss.dashboard.commons.message.MessageList;
import org.apache.commons.lang3.StringEscapeUtils;
import org.slf4j.Logger;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.InputSource;

@ApplicationScoped
public class ImportManagerImpl implements ImportManager {

    @Inject
    private transient Logger log;

    @Inject
    protected DataDisplayerManager dataDisplayerManager;

    public ImportOptions createImportOptions() {
        return new ImportOptionsImpl();
    }

    public ImportResults createImportResults() {
        return new ImportResultsImpl();
    }

    /**
     * Save the elements (KPI, DataProvider) contained in the import results instance.
     * The ImportResults message list gives us feedback about any problem found while saving.
     * @throws Exception If the specified import results contains ERROR messages.
     */
    public void save(ImportResults importResults) throws Exception {
        // Get errors.
        Locale locale = LocaleManager.currentLocale();
        MessageList messages = importResults.getMessages();
        if (messages.containsMessagesOfType(Message.ERROR)) {
            for (Message bProcessDescriptorMessage : messages.getMessagesOfType(Message.ERROR)) {
                throw new RuntimeException(bProcessDescriptorMessage.getMessage(locale));
            }
        }

        // Save the imported data providers.
        DataProviderManager provMgr = DataDisplayerServices.lookup().getDataProviderManager();
        for (DataProvider newProvider : importResults.getDataProviders()) {
            DataProvider oldProvider = provMgr.getDataProviderByCode(newProvider.getCode());
            if (oldProvider != null) {
                // If the provider is already present in the database then simply replace the references to the old provider.
                importResults.replaceDataProvider(newProvider, oldProvider);
                oldProvider.setDataLoader(newProvider.getDataLoader());
                oldProvider.save();
                importResults.getMessages().add(new ImportExportMessage(ImportExportMessage.PROVIDER_UPDATED,
                        new Object[] { oldProvider }));
            } else {
                newProvider.save();
                importResults.getMessages().add(new ImportExportMessage(ImportExportMessage.PROVIDER_CREATED,
                        new Object[] { newProvider }));
            }
        }

        // Save the imported KPIs.
        KPIManager kpiMgr = DataDisplayerServices.lookup().getKPIManager();
        for (KPI newKPI : importResults.getKPIs()) {
            KPI oldKPI = kpiMgr.getKPIByCode(newKPI.getCode());
            if (oldKPI != null) {
                // If the KPI is already present in the database then simply replace the references to the old KPI.
                importResults.replaceKPI(newKPI, oldKPI);
                oldKPI.merge(newKPI);
                oldKPI.save();
                importResults.getMessages()
                        .add(new ImportExportMessage(ImportExportMessage.KPI_UPDATED, new Object[] { oldKPI }));
            } else {
                newKPI.save();
                importResults.getMessages()
                        .add(new ImportExportMessage(ImportExportMessage.KPI_CREATED, new Object[] { newKPI }));
            }
        }
    }

    /**
     * Creates elements (KPI, DataProvider ,..) parsing the specified XML fragment.
     */
    public ImportResults parse(String xml) throws Exception {
        return parse(xml, createImportOptions());
    }

    /**
     * Creates elements (KPI, DataProvider ,..) parsing the specified XML stream.
     */
    public ImportResults parse(InputStream xml) throws Exception {
        return parse(xml, createImportOptions());
    }

    /**
     * Creates elements (KPI, DataProvider ,..) parsing the specified XML fragment.
     */
    public ImportResults parse(String xml, ImportOptions options) throws Exception {
        StringReader isr = new StringReader(xml);
        DocumentBuilder dBuilder = createDocumentBuilder();
        Document doc = dBuilder.parse(new InputSource(isr));
        isr.close();
        return parse(doc.getChildNodes(), options);
    }

    /**
     * Creates elements (KPI, DataProvider ,..) parsing the specified XML stream.
     */
    public ImportResults parse(InputStream xml, ImportOptions options) throws Exception {
        DocumentBuilder dBuilder = createDocumentBuilder();
        Document doc = dBuilder.parse(xml);
        return parse(doc.getChildNodes(), options);
    }

    protected DocumentBuilder createDocumentBuilder() throws Exception {
        DocumentBuilderFactory dFactory = DocumentBuilderFactory.newInstance();
        dFactory.setIgnoringComments(true);

        // BZ-1211316: XXE/SSRF vulnerability
        dFactory.setFeature("http://xml.org/sax/features/external-general-entities", false);
        dFactory.setFeature("http://xml.org/sax/features/external-parameter-entities", false);
        dFactory.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);

        return dFactory.newDocumentBuilder();
    }

    /**
     * Creates elements (KPI, DataProvider ,..) parsing the specified XML nodes.
     */
    public ImportResults parse(NodeList xmlNodes, ImportOptions options) throws Exception {
        ImportResults results = createImportResults();
        for (int i = 0; i < xmlNodes.getLength(); i++) {
            Node root = xmlNodes.item(0);
            if (!options.ignoreDataProviders())
                parseProviders(root.getChildNodes(), results);
            if (!options.ignoreKPIs())
                parseKPIs(root.getChildNodes(), results);
        }
        return results;
    }

    protected void parseKPIs(NodeList xmlNodes, ImportResults results) throws Exception {
        for (int i = 0; i < xmlNodes.getLength(); i++) {
            Node item = xmlNodes.item(i);
            if (item.getNodeName().equals("kpi")) {
                try {
                    KPI kpi = DataDisplayerServices.lookup().getKPIManager().createKPI();
                    Node codeNode = item.getAttributes().getNamedItem("code");
                    if (codeNode != null)
                        kpi.setCode(StringEscapeUtils.unescapeXml(codeNode.getNodeValue()));

                    NodeList subNodes = item.getChildNodes();
                    for (int j = 0; j < subNodes.getLength(); j++) {
                        item = subNodes.item(j);

                        // Description
                        if (item.getNodeName().equals("description") && item.hasChildNodes()) {
                            String description = item.getFirstChild().getNodeValue();
                            Locale locale = LocaleManager.currentLocale();
                            Node languageNode = item.getAttributes().getNamedItem("language");
                            if (languageNode != null)
                                locale = new Locale(languageNode.getNodeValue());
                            kpi.setDescription(StringEscapeUtils.unescapeXml(description), locale);
                        }

                        // Provider
                        if (item.getNodeName().equals("provider") && item.hasAttributes()) {
                            String providerCode = item.getAttributes().getNamedItem("code").getNodeValue();
                            DataProvider provider = results.getDataProviderByCode(providerCode);
                            if (provider == null)
                                provider = DataDisplayerServices.lookup().getDataProviderManager()
                                        .getDataProviderByCode(providerCode);
                            if (provider == null) {
                                results.getMessages()
                                        .add(new ImportExportMessage(ImportExportMessage.PROVIDER_CODE_NOT_FOUND,
                                                new Object[] { providerCode }));
                                throw new RuntimeException("Continue with the next KPI...");
                            }
                            kpi.setDataProvider(provider);
                        }

                        // Displayer
                        if (item.getNodeName().equals("displayer") && item.hasAttributes()
                                && item.hasChildNodes()) {
                            String typeUid = item.getAttributes().getNamedItem("type").getNodeValue();
                            DataDisplayerType type = dataDisplayerManager.getDisplayerTypeByUid(typeUid);
                            if (type == null) {
                                results.getMessages().add(new ImportExportMessage(
                                        ImportExportMessage.DISPLAYER_TYPE_NOT_FOUND, new Object[] { typeUid }));
                                throw new RuntimeException("Continue with the next KPI...");
                            }
                            DataDisplayerRenderer renderer = null;
                            Node rendererNode = item.getAttributes().getNamedItem("renderer");
                            if (rendererNode != null) {
                                String rendUid = rendererNode.getNodeValue();
                                renderer = dataDisplayerManager.getDisplayerRendererByUid(rendUid);
                                if (renderer == null) {
                                    results.getMessages()
                                            .add(new ImportExportMessage(
                                                    ImportExportMessage.DISPLAYER_RENDERER_NOT_FOUND,
                                                    new Object[] { rendUid }));
                                    throw new RuntimeException("Continue with the next KPI...");
                                }
                            }
                            DataDisplayer displayer = type.getXmlFormat().parse(subNodes, results);
                            if (results.getMessages().hasErrors()) {
                                throw new Exception(results.getMessages().get(0).toString());
                            }

                            displayer.setDataDisplayerType(type);
                            displayer.setDataDisplayerRenderer(renderer);
                            kpi.setDataDisplayer(displayer);
                        }
                    }
                    results.addKPI(kpi);
                } catch (Exception e) {
                    log.error("Error parsing KPI", e);
                    // Continue with the next KPI...
                }
            }
        }
    }

    public void parseProviders(NodeList xmlNodes, ImportResults results) throws Exception {
        for (int i = 0; i < xmlNodes.getLength(); i++) {
            Node item = xmlNodes.item(i);
            if (item.getNodeName().equals("dataprovider")) {

                // Get the provider type module by class.
                String uid = item.getAttributes().getNamedItem("type").getNodeValue();
                DataProviderType type = DataDisplayerServices.lookup().getDataProviderManager()
                        .getProviderTypeByUid(uid);
                if (type == null) {
                    results.getMessages().add(new ImportExportMessage(ImportExportMessage.PROVIDER_TYPE_NOT_FOUND,
                            new Object[] { uid }));
                    continue;
                }

                // Parse the provider instance custom part.
                NodeList subNodes = item.getChildNodes();
                DataLoader loader = type.getXmlFormat().parse(subNodes);
                if (results.getMessages().hasErrors()) {
                    throw new Exception(results.getMessages().get(0).toString());
                }
                loader.setDataProviderType(type);

                // Get the provider instance common properties.
                DataProviderImpl provider = new DataProviderImpl();
                provider.setDataLoader(loader);
                Node codeNode = item.getAttributes().getNamedItem("code");
                if (codeNode != null)
                    provider.setCode(StringEscapeUtils.unescapeXml(codeNode.getNodeValue()));
                for (int j = 0; j < subNodes.getLength(); j++) {
                    item = subNodes.item(j);

                    if (item.getNodeName().equals("canEdit") && item.hasChildNodes()) {
                        String canEditStr = item.getFirstChild().getNodeValue();
                        if ("false".equalsIgnoreCase(canEditStr))
                            provider.canEdit = false;
                    }

                    if (item.getNodeName().equals("canEditProperties") && item.hasChildNodes()) {
                        String canEditPropertiesStr = item.getFirstChild().getNodeValue();
                        if ("false".equalsIgnoreCase(canEditPropertiesStr))
                            provider.canEditProperties = false;
                    }

                    if (item.getNodeName().equals("canDelete") && item.hasChildNodes()) {
                        String canDelete = item.getFirstChild().getNodeValue();
                        if ("false".equalsIgnoreCase(canDelete))
                            provider.canDelete = false;
                    }

                    if (item.getNodeName().equals("description") && item.hasChildNodes()) {
                        String description = item.getFirstChild().getNodeValue();
                        Locale locale = LocaleManager.currentLocale();
                        Node languageNode = item.getAttributes().getNamedItem("language");
                        if (languageNode != null)
                            locale = new Locale(languageNode.getNodeValue());
                        provider.setDescription(StringEscapeUtils.unescapeXml(description), locale);
                    }

                    if (item.getNodeName().equals("dataproperties") && item.hasChildNodes()) {
                        provider.getDataSet().parseXMLProperties(item.getChildNodes());
                    }
                }

                // Register the imported provider.
                results.addDataProvider(provider);
            }
        }
    }
}