/*! * Copyright 2010 - 2015 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.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.SlaveServer; import org.pentaho.di.core.database.DatabaseMeta; import org.pentaho.di.core.exception.KettleException; import org.pentaho.di.job.JobMeta; import org.pentaho.di.repository.Repository; import org.pentaho.di.repository.RepositoryElementInterface; import org.pentaho.di.repository.StringObjectId; import org.pentaho.di.repository.pur.JobDelegate; 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 mlowery */ public class StreamToJobNodeConverter implements Converter { IUnifiedRepository unifiedRepository; private static final Log logger = LogFactory.getLog( StreamToJobNodeConverter.class ); /** * * @param unifiedRepository */ public StreamToJobNodeConverter( IUnifiedRepository unifiedRepository ) { this.unifiedRepository = unifiedRepository; } /** * * @param data * @return */ public InputStream convert( final IRepositoryFileData data ) { throw new UnsupportedOperationException(); } /** * * @param fileId * @return */ public InputStream convert( final Serializable fileId ) { InputStream is = null; try { if ( fileId != null ) { Repository repository = connectToRepository(); RepositoryFile file = unifiedRepository.getFileById( fileId ); if ( file != null ) { try { JobMeta jobMeta = repository.loadJob( new StringObjectId( fileId.toString() ), null ); if ( jobMeta != null ) { Set<String> privateDatabases = jobMeta.getPrivateDatabases(); if ( privateDatabases != null ) { // keep only private transformation databases for ( Iterator<DatabaseMeta> it = jobMeta.getDatabases().iterator(); it.hasNext(); ) { String databaseName = it.next().getName(); if ( !privateDatabases.contains( databaseName ) ) { it.remove(); } } } return new ByteArrayInputStream( jobMeta.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 job " + file.getName() + "." ); return fileData.getInputStream(); } } } } } catch ( Exception e ) { logger.error( e ); } return is; } // package-local visibility for testing purposes Repository connectToRepository() throws KettleException { return PDIImportUtil.connectToRepository( null ); } /** * * @param inputStream * @param charset * @param mimeType * @return */ public IRepositoryFileData convert( final InputStream inputStream, final String charset, final String mimeType ) { try { long size = inputStream.available(); JobMeta jobMeta = new JobMeta(); Repository repository = connectToRepository(); Document doc = PDIImportUtil.loadXMLFrom( inputStream ); if ( doc != null ) { jobMeta.loadXML( doc.getDocumentElement(), repository, null ); JobDelegate delegate = new JobDelegate( repository, this.unifiedRepository ); delegate.saveSharedObjects( jobMeta, null ); return new NodeRepositoryFileData( delegate.elementToDataNode( jobMeta ), size ); } else { return null; } } catch ( Exception e ) { return null; } } public void saveSharedObjects( final Repository repo, final RepositoryElementInterface element ) throws KettleException { JobMeta jobMeta = (JobMeta) element; // First store the databases and other depending objects in the transformation. List<String> databaseNames = Arrays.asList( repo.getDatabaseNames( true ) ); int dbIndex = 0; int indexToReplace = 0; boolean updateMeta = Boolean.FALSE; for ( DatabaseMeta databaseMeta : jobMeta.getDatabases() ) { if ( !databaseNames.contains( databaseMeta.getName() ) ) { if ( databaseMeta.getObjectId() == null || !StringUtils.isEmpty( databaseMeta.getHostname() ) ) { repo.save( databaseMeta, null, null ); } } else if ( databaseMeta.getObjectId() == null ) { indexToReplace = dbIndex; updateMeta = Boolean.TRUE; } dbIndex++; } // if db already exists in repo, get that object id and put it // in the transMeta db collection if ( updateMeta ) { DatabaseMeta dbMetaToReplace = jobMeta.getDatabase( indexToReplace ); dbMetaToReplace.setObjectId( repo.getDatabaseID( dbMetaToReplace.getName() ) ); jobMeta.removeDatabase( indexToReplace ); jobMeta.addDatabase( dbMetaToReplace ); } // Store the slave servers... // for ( SlaveServer slaveServer : jobMeta.getSlaveServers() ) { if ( slaveServer.getObjectId() == null ) { repo.save( slaveServer, null, null ); } } } }