org.pentaho.reporting.ui.datasources.jdbc.ui.XulDatabaseDialog.java Source code

Java tutorial

Introduction

Here is the source code for org.pentaho.reporting.ui.datasources.jdbc.ui.XulDatabaseDialog.java

Source

/*
 * This program is free software; you can redistribute it and/or modify it under the
 * terms of the GNU Lesser General Public License, version 2.1 as published by the Free Software
 * Foundation.
 *
 * You should have received a copy of the GNU Lesser General Public License along with this
 * program; if not, you can obtain a copy at http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html
 * or from the Free Software Foundation, Inc.,
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * 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 Lesser General Public License for more details.
 *
 * Copyright (c) 2017 Hitachi Vantara.  All rights reserved.
 */

package org.pentaho.reporting.ui.datasources.jdbc.ui;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.pentaho.di.core.database.DatabaseInterface;
import org.pentaho.di.core.database.DatabaseMeta;
import org.pentaho.di.core.database.GenericDatabaseMeta;
import org.pentaho.di.core.database.HypersonicDatabaseMeta;
import org.pentaho.di.core.exception.KettleDatabaseException;
import org.pentaho.reporting.engine.classic.core.designtime.DesignTimeContext;
import org.pentaho.reporting.ui.datasources.jdbc.DatabaseMapping;
import org.pentaho.reporting.ui.datasources.jdbc.connection.DriverConnectionDefinition;
import org.pentaho.reporting.ui.datasources.jdbc.connection.JdbcConnectionDefinition;
import org.pentaho.reporting.ui.datasources.jdbc.connection.JndiConnectionDefinition;
import org.pentaho.ui.database.Messages;
import org.pentaho.ui.xul.XulComponent;
import org.pentaho.ui.xul.XulDomContainer;
import org.pentaho.ui.xul.XulException;
import org.pentaho.ui.xul.containers.XulDialog;
import org.pentaho.ui.xul.dom.Document;
import org.pentaho.ui.xul.swing.SwingXulLoader;

import java.awt.Window;
import java.text.MessageFormat;
import java.util.Iterator;
import java.util.Map;
import java.util.Properties;

/**
 * Managing class for instance of Xul Commons Database Dialog. This class handles the translation between DatabaseMeta
 * objects and types of @{link JdbcConnectionDefinition}.
 * <p/>
 * The dialog is always modal.
 *
 * @author NBaker
 */
public class XulDatabaseDialog {
    private static final Log log = LogFactory.getLog(XulDatabaseDialog.class);
    private static final String DIALOG_DEFINITION_FILE = "org/pentaho/ui/database/databasedialog.xul"; //$NON-NLS-1$
    private static final String OVERLAY_DEFINITION_FILE = "org/pentaho/reporting/ui/datasources/jdbc/ui/databasedialogOverlay.xul"; //$NON-NLS-1$
    private XulDialog dialog;
    private XulDatabaseHandler handler;
    private DatabaseMeta meta;
    private static final String HSQLDB_PREFIX = "jdbc:hsqldb:hsql://";
    private static final String HSQLDB_MEM_PREFIX = "jdbc:hsqldb:mem:";
    private static final String HSQLDB_LOCAL_PREFIX = "jdbc:hsqldb:.";
    private DesignTimeContext designTimeContext;

    public XulDatabaseDialog(final Window parent, final DesignTimeContext designTimeContext) throws XulException {
        this.designTimeContext = designTimeContext;
        final SwingXulLoader loader = new SwingXulLoader();

        if (parent != null) {
            loader.setOuterContext(parent);
        }
        final XulDomContainer container = loader.loadXul(DIALOG_DEFINITION_FILE, Messages.getBundle());
        container.getDocumentRoot().addOverlay(OVERLAY_DEFINITION_FILE);
        container.initialize();

        handler = new XulDatabaseHandler();
        container.addEventHandler(handler); //$NON-NLS-1$

        final Document documentRoot = container.getDocumentRoot();
        final XulComponent root = documentRoot.getRootElement();

        if (root instanceof XulDialog) {
            dialog = (XulDialog) root;
            dialog.setResizable(Boolean.TRUE);
        } else {
            throw new XulException("Error getting Xul Database Dialog root, element of type: " + root);
        }
    }

    private void setData(final JdbcConnectionDefinition def) {
        if (def instanceof DriverConnectionDefinition) {
            final DriverConnectionDefinition jdbcDef = (DriverConnectionDefinition) def;
            this.meta = new DatabaseMeta();
            this.meta.setUsername(jdbcDef.getUsername());
            this.meta.setPassword(jdbcDef.getPassword());
            this.meta.setName(jdbcDef.getName());

            if (jdbcDef.getDatabaseType() != null) {
                log.debug("Database type is known: " + jdbcDef.getDatabaseType());
                try {
                    this.meta.setDatabaseType(jdbcDef.getDatabaseType());
                } catch (RuntimeException re) {
                    // sic!
                }
                this.meta.setDBName(jdbcDef.getDatabaseName());
                this.meta.setHostname(jdbcDef.getHostName());
                this.meta.setDBPort(jdbcDef.getPort());
                this.meta.getAttributes().setProperty(GenericDatabaseMeta.ATRRIBUTE_CUSTOM_URL,
                        jdbcDef.getConnectionString());
                this.meta.getAttributes().setProperty(GenericDatabaseMeta.ATRRIBUTE_CUSTOM_DRIVER_CLASS,
                        jdbcDef.getDriverClass());
            } else if (String.valueOf(jdbcDef.getConnectionString()).startsWith(HSQLDB_MEM_PREFIX)) {
                this.meta.setDatabaseType(DatabaseMapping.getGenericInterface().getPluginId());
                this.meta.getAttributes().put(GenericDatabaseMeta.ATRRIBUTE_CUSTOM_URL,
                        jdbcDef.getConnectionString());
                this.meta.getAttributes().put(GenericDatabaseMeta.ATRRIBUTE_CUSTOM_DRIVER_CLASS,
                        jdbcDef.getDriverClass());
            } else if (String.valueOf(jdbcDef.getConnectionString()).startsWith(HSQLDB_LOCAL_PREFIX)) {
                this.meta.setDatabaseType(DatabaseMapping.getGenericInterface().getPluginId());
                this.meta.getAttributes().put(GenericDatabaseMeta.ATRRIBUTE_CUSTOM_URL,
                        jdbcDef.getConnectionString());
                this.meta.getAttributes().put(GenericDatabaseMeta.ATRRIBUTE_CUSTOM_DRIVER_CLASS,
                        jdbcDef.getDriverClass());
            } else {
                final DatabaseInterface databaseInterface = DatabaseMapping
                        .getMappingForDriver(jdbcDef.getDriverClass());
                this.meta.setDatabaseType(databaseInterface.getPluginId());
                log.debug("Database type is unknown, using " + databaseInterface);
                try {
                    final String pattern;
                    if (databaseInterface instanceof HypersonicDatabaseMeta) {
                        final String connectionString = jdbcDef.getConnectionString();
                        if (connectionString.startsWith(HSQLDB_PREFIX)) {
                            if (connectionString.indexOf(':', HSQLDB_PREFIX.length()) == -1) {
                                pattern = HSQLDB_PREFIX + "{0}/{2}";
                            } else {
                                pattern = HSQLDB_PREFIX + "{0}:{1}/{2}";
                            }
                        } else {
                            pattern = databaseInterface.getURL("{0}", "{1}", "{2}");
                        }
                    } else {
                        pattern = databaseInterface.getURL("{0}", "{1}", "{2}");
                    }
                    // knowing that most databases are written in C, we can be sure that the zero-character
                    // is not a common value.
                    if (pattern != null && pattern.length() > 0) {
                        final MessageFormat format = new MessageFormat(pattern);
                        final Object[] objects = format.parse(jdbcDef.getConnectionString());
                        if (objects[0] != null) {
                            this.meta.setHostname(String.valueOf(objects[0]));
                        }
                        if (objects[1] != null) {
                            this.meta.setDBPort(String.valueOf(objects[1]));
                        }
                        if (objects[2] != null) {
                            this.meta.setDBName(String.valueOf(objects[2]));
                        }
                    }
                } catch (Exception e) {
                    designTimeContext.error(new XulException(
                            "Unable to parse database-URL, please report "
                                    + "your database driver to Pentaho to include it in our list of databases.",
                            e));
                    this.meta.setDatabaseType(DatabaseMapping.getGenericInterface().getPluginId());
                    this.meta.getAttributes().put(GenericDatabaseMeta.ATRRIBUTE_CUSTOM_URL,
                            jdbcDef.getConnectionString());
                    this.meta.getAttributes().put(GenericDatabaseMeta.ATRRIBUTE_CUSTOM_DRIVER_CLASS,
                            jdbcDef.getDriverClass());
                }
            }

            final Properties properties = jdbcDef.getProperties();
            final Iterator entryIterator = properties.entrySet().iterator();
            while (entryIterator.hasNext()) {
                final Map.Entry entry = (Map.Entry) entryIterator.next();
                final String key = (String) entry.getKey();
                if (key.startsWith("::pentaho-reporting::")) {
                    continue;
                }
                if ("user".equals(key) || "password".equals(key)) {
                    continue;
                }
                // This line makes the database dialog crash later. This seems to be a Swing/Xul issue.
                this.meta.addExtraOption(meta.getPluginId(), key, (String) entry.getValue());
            }
        } else if (def instanceof JndiConnectionDefinition) {
            final JndiConnectionDefinition jndiDef = (JndiConnectionDefinition) def;
            this.meta = new DatabaseMeta();
            this.meta.setDBName(jndiDef.getJndiName()); //JNDI name stored in DBname
            this.meta.setName(jndiDef.getName());
            try {
                if (jndiDef.getDatabaseType() != null) {
                    this.meta.setDatabaseType(jndiDef.getDatabaseType());
                }
            } catch (RuntimeException re) {
                // even invalid values should not kill us.
                // sic! Kettle throws generic Exceptions.
            }
            this.meta.setAccessType(DatabaseMeta.TYPE_ACCESS_JNDI);
        } else {
            this.meta = null;
        }
    }

    public JdbcConnectionDefinition open(final JdbcConnectionDefinition definition) {
        setData(definition);
        try {
            log.debug("showing database dialog");
            if (meta != null) {
                handler.setData(meta);
            }
            dialog.show(); //Blocks current thread
            log.debug("dialog closed, getting DabaseMeta");
            if (handler.isConfirmed() == false) {
                return null;
            }

            final DatabaseMeta database = (DatabaseMeta) handler.getData(); //$NON-NLS-1$
            if (database == null) {
                log.debug("DatabaseMeta is null");
                return null;
            }

            return convertDbMeta(database);
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            return null;
        }
    }

    private JdbcConnectionDefinition convertDbMeta(final DatabaseMeta meta) throws KettleDatabaseException {
        if (meta.getAccessType() == DatabaseMeta.TYPE_ACCESS_JNDI) {
            return new JndiConnectionDefinition(meta.getName(), meta.getDatabaseName(),
                    meta.getDatabaseInterface().getPluginName(), null, null);
        } else {
            final Map<String, String> map = meta.getExtraOptions();
            final Properties properties = new Properties();
            final Iterator<Map.Entry<String, String>> entryIterator = map.entrySet().iterator();
            while (entryIterator.hasNext()) {
                final Map.Entry<String, String> entry = entryIterator.next();
                final String key = entry.getKey();
                final String realKey = key.substring(meta.getPluginId().length() + 1);
                final String value = entry.getValue();
                if (DatabaseMeta.EMPTY_OPTIONS_STRING.equals(value)) {
                    properties.put(realKey, "");
                } else {
                    properties.put(realKey, value);
                }
            }

            return new DriverConnectionDefinition(meta.getName(), meta.getDriverClass(), meta.getURL(),
                    meta.getUsername(), meta.getPassword(), meta.getHostname(), meta.getDatabaseName(),
                    meta.getDatabaseInterface().getPluginId(), meta.getDatabasePortNumberString(), properties);
        }
    }

}