/*! ****************************************************************************** * * Pentaho Data Integration * * Copyright (C) 2002-2016 by Pentaho : http://www.pentaho.com * ******************************************************************************* * * 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.pentaho.di.metastore; import java.util.ArrayList; import java.util.Enumeration; import java.util.List; import java.util.Properties; import org.pentaho.di.core.Const; import org.pentaho.di.core.util.Utils; import org.pentaho.di.core.database.DatabaseInterface; import org.pentaho.di.core.database.DatabaseMeta; import org.pentaho.di.core.exception.KettlePluginException; import org.pentaho.di.core.plugins.DatabasePluginType; import org.pentaho.di.core.plugins.PluginInterface; import org.pentaho.di.core.plugins.PluginRegistry; import org.pentaho.di.repository.StringObjectId; import org.pentaho.metastore.api.IMetaStore; import org.pentaho.metastore.api.IMetaStoreAttribute; import org.pentaho.metastore.api.IMetaStoreElement; import org.pentaho.metastore.api.IMetaStoreElementType; import org.pentaho.metastore.api.exceptions.MetaStoreException; import org.pentaho.metastore.util.MetaStoreUtil; import org.pentaho.metastore.util.PentahoDefaults; public class DatabaseMetaStoreUtil extends MetaStoreUtil { public static List<DatabaseMeta> getDatabaseElements( IMetaStore metaStore ) throws MetaStoreException { List<DatabaseMeta> databases = new ArrayList<DatabaseMeta>(); // If the data type doesn't exist, it's an empty list... // IMetaStoreElementType elementType = metaStore.getElementTypeByName( PentahoDefaults.NAMESPACE, PentahoDefaults.DATABASE_CONNECTION_ELEMENT_TYPE_NAME ); if ( elementType == null ) { return databases; } List<IMetaStoreElement> elements = metaStore.getElements( PentahoDefaults.NAMESPACE, elementType ); for ( IMetaStoreElement element : elements ) { try { DatabaseMeta databaseMeta = loadDatabaseMetaFromDatabaseElement( metaStore, element ); databases.add( databaseMeta ); } catch ( Exception e ) { throw new MetaStoreException( "Unable to load database from element with name '" + element.getName() + "' and type '" + elementType.getName() + "'", e ); } } return databases; } public static void createDatabaseElement( IMetaStore metaStore, DatabaseMeta databaseMeta ) throws MetaStoreException { // If the Pentaho namespace doesn't exist, create it! // if ( !metaStore.namespaceExists( PentahoDefaults.NAMESPACE ) ) { metaStore.createNamespace( PentahoDefaults.NAMESPACE ); } // If the database connection element type doesn't exist, create it // IMetaStoreElementType elementType = metaStore.getElementTypeByName( PentahoDefaults.NAMESPACE, PentahoDefaults.DATABASE_CONNECTION_ELEMENT_TYPE_NAME ); if ( elementType == null ) { elementType = populateDatabaseElementType( metaStore ); metaStore.createElementType( PentahoDefaults.NAMESPACE, elementType ); } // populate an element, store it. // IMetaStoreElement databaseElement = populateDatabaseElement( metaStore, databaseMeta ); // Store the element physically // metaStore.createElement( PentahoDefaults.NAMESPACE, databaseElement.getElementType(), databaseElement ); } public static IMetaStoreElementType populateDatabaseElementType( IMetaStore metaStore ) throws MetaStoreException { // The new type will typically have an ID so all we need to do is give the type a name and a description. // IMetaStoreElementType elementType = metaStore.newElementType( PentahoDefaults.NAMESPACE ); // Name and description... // elementType.setName( PentahoDefaults.DATABASE_CONNECTION_ELEMENT_TYPE_NAME ); elementType.setDescription( PentahoDefaults.DATABASE_CONNECTION_ELEMENT_TYPE_DESCRIPTION ); return elementType; } public static IMetaStoreElement populateDatabaseElement( IMetaStore metaStore, DatabaseMeta databaseMeta ) throws MetaStoreException { if ( !metaStore.namespaceExists( PentahoDefaults.NAMESPACE ) ) { throw new MetaStoreException( "Namespace '" + PentahoDefaults.NAMESPACE + "' doesn't exist." ); } // If the data type doesn't exist, error out... // IMetaStoreElementType elementType = metaStore.getElementTypeByName( PentahoDefaults.NAMESPACE, PentahoDefaults.DATABASE_CONNECTION_ELEMENT_TYPE_NAME ); if ( elementType == null ) { throw new MetaStoreException( "Unable to find the database connection type" ); } elementType = populateDatabaseElementType( metaStore ); // generate a new database element and populate it with metadata // IMetaStoreElement element = metaStore.newElement( elementType, databaseMeta.getName(), null ); element.addChild( metaStore.newAttribute( MetaStoreConst.DB_ATTR_ID_PLUGIN_ID, databaseMeta.getPluginId() ) ); element.setName( databaseMeta.getName() ); element.addChild( metaStore .newAttribute( MetaStoreConst.DB_ATTR_ID_DESCRIPTION, databaseMeta.getDescription() ) ); element.addChild( metaStore.newAttribute( MetaStoreConst.DB_ATTR_ID_ACCESS_TYPE, databaseMeta .getAccessTypeDesc() ) ); element.addChild( metaStore.newAttribute( MetaStoreConst.DB_ATTR_ID_HOSTNAME, databaseMeta.getHostname() ) ); element.addChild( metaStore.newAttribute( MetaStoreConst.DB_ATTR_ID_PORT, databaseMeta .getDatabasePortNumberString() ) ); element.addChild( metaStore.newAttribute( MetaStoreConst.DB_ATTR_ID_DATABASE_NAME, databaseMeta .getDatabaseName() ) ); element.addChild( metaStore.newAttribute( MetaStoreConst.DB_ATTR_ID_USERNAME, databaseMeta.getUsername() ) ); element.addChild( metaStore.newAttribute( MetaStoreConst.DB_ATTR_ID_PASSWORD, metaStore .getTwoWayPasswordEncoder().encode( databaseMeta.getPassword() ) ) ); element .addChild( metaStore.newAttribute( MetaStoreConst.DB_ATTR_ID_SERVERNAME, databaseMeta.getServername() ) ); element.addChild( metaStore.newAttribute( MetaStoreConst.DB_ATTR_ID_DATA_TABLESPACE, databaseMeta .getDataTablespace() ) ); element.addChild( metaStore.newAttribute( MetaStoreConst.DB_ATTR_ID_INDEX_TABLESPACE, databaseMeta .getIndexTablespace() ) ); IMetaStoreAttribute attributesChild = metaStore.newAttribute( MetaStoreConst.DB_ATTR_ID_ATTRIBUTES, null ); element.addChild( attributesChild ); // Now add a list of all the attributes set on the database connection... // Properties attributes = databaseMeta.getAttributes(); Enumeration<Object> keys = databaseMeta.getAttributes().keys(); while ( keys.hasMoreElements() ) { String code = (String) keys.nextElement(); String attribute = (String) attributes.get( code ); // Add it to the attributes child // attributesChild.addChild( metaStore.newAttribute( code, attribute ) ); } // Extra information for 3rd-party tools: // // The driver class // element .addChild( metaStore.newAttribute( MetaStoreConst.DB_ATTR_DRIVER_CLASS, databaseMeta.getDriverClass() ) ); // The URL // try { element.addChild( metaStore.newAttribute( MetaStoreConst.DB_ATTR_JDBC_URL, databaseMeta.getURL() ) ); } catch ( Exception e ) { throw new MetaStoreException( "Unable to assemble URL from database '" + databaseMeta.getName() + "'", e ); } return element; } public static DatabaseMeta loadDatabaseMetaFromDatabaseElement( IMetaStore metaStore, IMetaStoreElement element ) throws KettlePluginException { DatabaseMeta databaseMeta = new DatabaseMeta(); PluginRegistry pluginRegistry = PluginRegistry.getInstance(); // Load the appropriate database plugin (database interface) // String pluginId = getChildString( element, MetaStoreConst.DB_ATTR_ID_PLUGIN_ID ); String driverClassName = getChildString( element, MetaStoreConst.DB_ATTR_DRIVER_CLASS ); if ( Utils.isEmpty( pluginId ) && Utils.isEmpty( driverClassName ) ) { throw new KettlePluginException( "The attributes 'plugin_id' and 'driver_class' can't be both empty" ); } if ( Utils.isEmpty( pluginId ) ) { // Determine pluginId using the plugin registry. // List<PluginInterface> plugins = pluginRegistry.getPlugins( DatabasePluginType.class ); for ( PluginInterface plugin : plugins ) { DatabaseInterface databaseInterface = (DatabaseInterface) pluginRegistry.loadClass( plugin ); if ( driverClassName.equalsIgnoreCase( databaseInterface.getDriverClass() ) ) { pluginId = plugin.getIds()[0]; } } } if ( Utils.isEmpty( pluginId ) ) { throw new KettlePluginException( "The 'plugin_id' attribute could not be determined using 'driver_class' value '" + driverClassName + "'" ); } // Look for the plugin // PluginInterface plugin = PluginRegistry.getInstance().getPlugin( DatabasePluginType.class, pluginId ); DatabaseInterface databaseInterface = (DatabaseInterface) PluginRegistry.getInstance().loadClass( plugin ); databaseInterface.setPluginId( pluginId ); databaseMeta.setDatabaseInterface( databaseInterface ); databaseMeta.setObjectId( new StringObjectId( element.getId() ) ); databaseMeta.setName( element.getName() ); databaseMeta.setDescription( getChildString( element, MetaStoreConst.DB_ATTR_ID_DESCRIPTION ) ); String accessTypeString = getChildString( element, MetaStoreConst.DB_ATTR_ID_ACCESS_TYPE ); if ( Utils.isEmpty( accessTypeString ) ) { accessTypeString = DatabaseMeta.getAccessTypeDesc( DatabaseMeta.TYPE_ACCESS_NATIVE ); } databaseMeta.setAccessType( DatabaseMeta.getAccessType( accessTypeString ) ); databaseMeta.setHostname( getChildString( element, MetaStoreConst.DB_ATTR_ID_HOSTNAME ) ); databaseMeta.setDBPort( getChildString( element, MetaStoreConst.DB_ATTR_ID_PORT ) ); databaseMeta.setDBName( getChildString( element, MetaStoreConst.DB_ATTR_ID_DATABASE_NAME ) ); databaseMeta.setUsername( getChildString( element, MetaStoreConst.DB_ATTR_ID_USERNAME ) ); databaseMeta.setPassword( metaStore.getTwoWayPasswordEncoder().decode( getChildString( element, MetaStoreConst.DB_ATTR_ID_PASSWORD ) ) ); databaseMeta.setServername( getChildString( element, MetaStoreConst.DB_ATTR_ID_SERVERNAME ) ); databaseMeta.setDataTablespace( getChildString( element, MetaStoreConst.DB_ATTR_ID_DATA_TABLESPACE ) ); databaseMeta.setIndexTablespace( getChildString( element, MetaStoreConst.DB_ATTR_ID_INDEX_TABLESPACE ) ); IMetaStoreAttribute attributesChild = element.getChild( MetaStoreConst.DB_ATTR_ID_ATTRIBUTES ); if ( attributesChild != null ) { // Now add a list of all the attributes set on the database connection... // Properties attributes = databaseMeta.getAttributes(); for ( IMetaStoreAttribute attr : attributesChild.getChildren() ) { String code = attr.getId(); String value = getAttributeString( attr ); attributes.put( code, Const.NVL( value, "" ) ); } } return databaseMeta; } }