/*! * Copyright 2010 - 2016 Pentaho Corporation. All rights reserved. * * 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 com.pentaho.repository.importexport; import java.io.ByteArrayInputStream; import java.io.InputStream; import java.io.Serializable; import java.util.ArrayList; import java.util.Arrays; import java.util.Iterator; import java.util.List; import java.util.Set; import org.apache.commons.lang.StringUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.pentaho.di.cluster.ClusterSchema; import org.pentaho.di.cluster.SlaveServer; import org.pentaho.di.core.database.DatabaseMeta; import org.pentaho.di.core.exception.KettleException; import org.pentaho.di.core.extension.ExtensionPointHandler; import org.pentaho.di.core.extension.KettleExtensionPoint; import org.pentaho.di.core.logging.LogChannel; import org.pentaho.di.partition.PartitionSchema; import org.pentaho.di.repository.Repository; import org.pentaho.di.repository.RepositoryElementInterface; import org.pentaho.di.repository.StringObjectId; import org.pentaho.di.repository.pur.TransDelegate; import org.pentaho.di.trans.TransMeta; import org.pentaho.platform.api.repository2.unified.Converter; import org.pentaho.platform.api.repository2.unified.IRepositoryFileData; import org.pentaho.platform.api.repository2.unified.IUnifiedRepository; import org.pentaho.platform.api.repository2.unified.RepositoryFile; import org.pentaho.platform.api.repository2.unified.data.node.NodeRepositoryFileData; import org.pentaho.platform.api.repository2.unified.data.simple.SimpleRepositoryFileData; import org.w3c.dom.Document; /** * Converts stream of binary or character data. * * @author rmansoor */ public class StreamToTransNodeConverter implements Converter { IUnifiedRepository unifiedRepository; private static final Log logger = LogFactory.getLog( StreamToTransNodeConverter.class ); public StreamToTransNodeConverter( IUnifiedRepository unifiedRepository ) { this.unifiedRepository = unifiedRepository; } public InputStream convert( final IRepositoryFileData data ) { throw new UnsupportedOperationException(); } /** * * @param fileId * @return */ public InputStream convert( final Serializable fileId ) { try { // this will change in the future if PDI no longer has its // own repository. For now, get the reference if ( fileId != null ) { Repository repository = connectToRepository(); RepositoryFile file = unifiedRepository.getFileById( fileId ); if ( file != null ) { try { TransMeta transMeta = repository.loadTransformation( new StringObjectId( fileId.toString() ), null ); if ( transMeta != null ) { Set<String> privateDatabases = transMeta.getPrivateDatabases(); if ( privateDatabases != null ) { // keep only private transformation databases for ( Iterator<DatabaseMeta> it = transMeta.getDatabases().iterator(); it.hasNext(); ) { String databaseName = it.next().getName(); if ( !privateDatabases.contains( databaseName ) ) { it.remove(); } } } return new ByteArrayInputStream( transMeta.getXML().getBytes() ); } } catch ( KettleException e ) { logger.error( e ); // file is there and may be legacy, attempt simple export SimpleRepositoryFileData fileData = unifiedRepository.getDataForRead( fileId, SimpleRepositoryFileData.class ); if ( fileData != null ) { logger.warn( "Reading as legacy CE tranformation " + file.getName() + "." ); return fileData.getInputStream(); } } } } } catch ( Exception e ) { logger.error( e ); } return null; } // package-local visibility for testing purposes Repository connectToRepository() throws KettleException { return PDIImportUtil.connectToRepository( null ); } public IRepositoryFileData convert( final InputStream inputStream, final String charset, final String mimeType ) { try { long size = inputStream.available(); TransMeta transMeta = new TransMeta(); Repository repository = connectToRepository(); Document doc = PDIImportUtil.loadXMLFrom( inputStream ); transMeta.loadXML( doc.getDocumentElement(), repository, false ); TransDelegate delegate = new TransDelegate( repository, this.unifiedRepository ); saveSharedObjects( repository, transMeta ); return new NodeRepositoryFileData( delegate.elementToDataNode( transMeta ), size ); } catch ( Exception e ) { logger.error( e ); return null; } } private void saveSharedObjects( final Repository repo, final RepositoryElementInterface element ) throws KettleException { TransMeta transMeta = (TransMeta) element; // First store the databases and other depending objects in the transformation. List<String> databaseNames = Arrays.asList( repo.getDatabaseNames( true ) ); int dbIndex = 0; boolean updateMeta = Boolean.FALSE; List<Integer> transMetaDatabasesToUpdate = new ArrayList<Integer>(); for ( DatabaseMeta databaseMeta : transMeta.getDatabases() ) { if ( !databaseNames.contains( databaseMeta.getName() ) ) { if ( databaseMeta.getObjectId() == null || !StringUtils.isEmpty( databaseMeta.getHostname() ) ) { repo.save( databaseMeta, null, null ); } } else if ( databaseMeta.getObjectId() == null ) { // add this to the list to update object Ids later transMetaDatabasesToUpdate.add( dbIndex ); updateMeta = Boolean.TRUE; } dbIndex++; } if ( updateMeta ) { // make sure to update object ids in the transmeta db collection for ( Integer databaseMetaIndex : transMetaDatabasesToUpdate ) { transMeta.getDatabase( databaseMetaIndex ).setObjectId( repo.getDatabaseID( transMeta.getDatabase( databaseMetaIndex ).getName() ) ); } } // Store the slave servers... // for ( SlaveServer slaveServer : transMeta.getSlaveServers() ) { if ( slaveServer.hasChanged() || slaveServer.getObjectId() == null ) { repo.save( slaveServer, null, null ); } } // Store the cluster schemas // for ( ClusterSchema clusterSchema : transMeta.getClusterSchemas() ) { if ( clusterSchema.hasChanged() || clusterSchema.getObjectId() == null ) { repo.save( clusterSchema, null, null ); } } // Save the partition schemas // for ( PartitionSchema partitionSchema : transMeta.getPartitionSchemas() ) { if ( partitionSchema.hasChanged() || partitionSchema.getObjectId() == null ) { repo.save( partitionSchema, null, null ); } } } public void convertPostRepoSave( RepositoryFile repositoryFile ) { if ( repositoryFile != null ) { try { Repository repo = connectToRepository(); if ( repo != null ) { TransMeta transMeta = repo.loadTransformation( new StringObjectId( repositoryFile.getId().toString() ), null ); ExtensionPointHandler.callExtensionPoint( new LogChannel( this ), KettleExtensionPoint.TransImportAfterSaveToRepo.id, transMeta ); } } catch ( Exception e ) { logger.error( KettleExtensionPoint.TransImportAfterSaveToRepo.id, e ); } } } }