Java tutorial
/** * 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); } } } }