/*!
* 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.di.purge;
import java.io.Serializable;
import java.util.Arrays;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import org.pentaho.di.core.exception.KettleException;
import org.pentaho.di.repository.RepositoryElementInterface;
import org.pentaho.di.ui.repository.pur.services.IPurgeService;
import org.pentaho.platform.api.repository2.unified.IUnifiedRepository;
import org.pentaho.platform.api.repository2.unified.RepositoryRequest;
import org.pentaho.platform.api.repository2.unified.RepositoryRequest.FILES_TYPE_FILTER;
import org.pentaho.platform.api.repository2.unified.VersionSummary;
import org.pentaho.platform.repository2.unified.webservices.DefaultUnifiedRepositoryWebService;
import org.pentaho.platform.repository2.unified.webservices.RepositoryFileDto;
import org.pentaho.platform.repository2.unified.webservices.RepositoryFileTreeDto;
/**
* Created by tkafalas 7/14/14.
*/
public class UnifiedRepositoryPurgeService implements IPurgeService {
private final IUnifiedRepository unifiedRepository;
public static DefaultUnifiedRepositoryWebService repoWs; // Scoped public only so that test class can set mock
private static String[] sharedObjectFolders = new String[] { "/etc/pdi/databases", "/etc/pdi/clusterSchemas",
"/etc/pdi/partitionSchemas", "/etc/pdi/slaveServers" };
public UnifiedRepositoryPurgeService( IUnifiedRepository unifiedRepository ) {
this.unifiedRepository = unifiedRepository;
}
@Override
public void deleteVersionsBeforeDate( RepositoryElementInterface element, Date beforeDate ) throws KettleException {
try {
Serializable fileId = element.getObjectId().getId();
deleteVersionsBeforeDate( fileId, beforeDate );
} catch ( Exception e ) {
processDeleteException( e );
}
}
@Override
public void deleteVersionsBeforeDate( Serializable fileId, Date beforeDate ) {
List<VersionSummary> versionList = unifiedRepository.getVersionSummaries( fileId );
int listSize = versionList.size();
int removedCount = 0;
for ( VersionSummary versionSummary : versionList ) {
if ( listSize - removedCount <= 1 ) {
break; // Don't delete the last instance of this file.
}
if ( versionSummary.getDate().before( beforeDate ) ) {
Serializable versionId = versionSummary.getId();
getLogger().debug( "removing version " + versionId.toString() );
unifiedRepository.deleteFileAtVersion( fileId, versionId );
removedCount++;
}
}
}
@Override
public void deleteAllVersions( RepositoryElementInterface element ) throws KettleException {
Serializable fileId = element.getObjectId().getId();
deleteAllVersions( fileId );
}
@Override
public void deleteAllVersions( Serializable fileId ) {
keepNumberOfVersions( fileId, 1 );
}
@Override
public void deleteVersion( RepositoryElementInterface element, String versionId ) throws KettleException {
String fileId = element.getObjectId().getId();
deleteVersion( fileId, versionId );
}
@Override
public void deleteVersion( Serializable fileId, Serializable versionId ) {
unifiedRepository.deleteFileAtVersion( fileId, versionId );
}
@Override
public void keepNumberOfVersions( RepositoryElementInterface element, int versionCount ) throws KettleException {
String fileId = element.getObjectId().getId();
keepNumberOfVersions( fileId, versionCount );
}
@Override
public void keepNumberOfVersions( Serializable fileId, int versionCount ) {
List<VersionSummary> versionList = unifiedRepository.getVersionSummaries( fileId );
int i = 0;
int listSize = versionList.size();
if ( listSize > versionCount ) {
getLogger().info( "version count: removing versions" );
}
for ( VersionSummary versionSummary : versionList ) {
if ( i < listSize - versionCount ) {
Serializable versionId = versionSummary.getId();
getLogger().debug( "removing version " + versionId.toString() );
unifiedRepository.deleteFileAtVersion( fileId, versionId );
i++;
} else {
break;
}
}
}
private void processDeleteException( Throwable e ) throws KettleException {
throw new KettleException( "Unable to complete revision deletion", e );
}
public void doDeleteRevisions( PurgeUtilitySpecification purgeSpecification ) throws PurgeDeletionException {
if ( purgeSpecification != null ) {
getLogger().setCurrentFilePath( purgeSpecification.getPath() );
logConfiguration( purgeSpecification );
if ( purgeSpecification.getPath() != null && !purgeSpecification.getPath().isEmpty() ) {
processRevisionDeletion( purgeSpecification );
}
// Now do shared objects if required
if ( purgeSpecification.isSharedObjects() ) {
if ( purgeSpecification.isPurgeFiles() ) {
for ( String sharedObjectpath : sharedObjectFolders ) {
purgeSpecification.fileFilter = "*";
purgeSpecification.setPath( sharedObjectpath );
processRevisionDeletion( purgeSpecification );
}
} else {
throw new PurgeDeletionException( "Must purge files before shared objects" );
}
}
}
}
private void processRevisionDeletion( PurgeUtilitySpecification purgeSpecification ) throws PurgeDeletionException {
RepositoryRequest repositoryRequest =
new RepositoryRequest( purgeSpecification.getPath(), true, -1, purgeSpecification.getFileFilter() );
repositoryRequest.setTypes( FILES_TYPE_FILTER.FILES_FOLDERS );
repositoryRequest.setIncludeMemberSet( new HashSet<String>( Arrays.asList( new String[] { "name", "id", "folder",
"path", "versioned", "versionId", "locked" } ) ) );
getLogger().debug( "Creating file list" );
RepositoryFileTreeDto tree = getRepoWs().getTreeFromRequest( repositoryRequest );
processPurgeForTree( tree, purgeSpecification );
}
private void processPurgeForTree( RepositoryFileTreeDto tree, PurgeUtilitySpecification purgeSpecification ) {
for ( RepositoryFileTreeDto child : tree.getChildren() ) {
try {
if ( !child.getChildren().isEmpty() ) {
processPurgeForTree( child, purgeSpecification );
}
RepositoryFileDto file = child.getFile();
getLogger().setCurrentFilePath( file.getPath() );
if ( file.isVersioned() ) {
if ( purgeSpecification.isPurgeFiles() ) {
getLogger().info( "Purge File" );
keepNumberOfVersions( file.getId(), 1 ); // the latest version will be removed with deleteFileWithPermanentFlag
getRepoWs().deleteFileWithPermanentFlag( file.getId(), true, "purge utility" );
} else if ( purgeSpecification.isPurgeRevisions() ) {
getLogger().info( "Purging Revisions" );
deleteAllVersions( file.getId() );
} else {
if ( purgeSpecification.getBeforeDate() != null ) {
getLogger().info( "Checking/purging by Revision date" );
deleteVersionsBeforeDate( file.getId(), purgeSpecification.getBeforeDate() );
}
if ( purgeSpecification.getVersionCount() >= 0 ) {
getLogger().info( "Checking/purging by number of Revisions" );
keepNumberOfVersions( file.getId(), purgeSpecification.getVersionCount() );
}
}
}
} catch ( Exception e ) {
getLogger().error( e );
}
}
}
public static DefaultUnifiedRepositoryWebService getRepoWs() {
if ( repoWs == null ) {
repoWs = new DefaultUnifiedRepositoryWebService();
}
return repoWs;
}
/**
* Get the formal logger ( or create one that just logs regularly )
*/
private PurgeUtilityLogger getLogger() {
return PurgeUtilityLogger.getPurgeUtilityLogger();
}
private void logConfiguration( PurgeUtilitySpecification purgeSpecification ) {
if ( purgeSpecification.getFileFilter() != null && purgeSpecification.getFileFilter().isEmpty() ) {
getLogger().info( "Configure File Filter" + purgeSpecification.getFileFilter() );
}
if ( purgeSpecification.isPurgeFiles() ) {
getLogger().info( "Configure PurgeAllFiles: true" );
}
if ( purgeSpecification.isPurgeRevisions() ) {
getLogger().info( "Configure PurgeAllRevisions: true" );
}
if ( purgeSpecification.isSharedObjects() ) {
getLogger().info( "Configure ShareObjects: true" );
}
if ( purgeSpecification.getBeforeDate() != null ) {
getLogger().info( "Configure purgeBeforeDate: " + purgeSpecification.getBeforeDate().toString() );
}
if ( purgeSpecification.getVersionCount() != -1 ) {
getLogger().info( "Configure versionCount: " + purgeSpecification.getVersionCount() );
}
}
}