/*!
* 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) 2002-2013 Pentaho Corporation.. All rights reserved.
*/
package org.pentaho.test.platform.repository2.unified;
import static org.pentaho.platform.api.repository2.unified.RepositoryFilePermission.READ;
import static org.pentaho.platform.api.repository2.unified.RepositoryFilePermission.WRITE;
import static org.pentaho.platform.api.repository2.unified.RepositoryFileSid.Type.ROLE;
import static org.pentaho.platform.api.repository2.unified.RepositoryFileSid.Type.USER;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Date;
import java.util.EnumSet;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import java.util.UUID;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.Validate;
import org.pentaho.platform.api.locale.IPentahoLocale;
import org.pentaho.platform.api.mt.ITenantedPrincipleNameResolver;
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.RepositoryFileAce;
import org.pentaho.platform.api.repository2.unified.RepositoryFileAcl;
import org.pentaho.platform.api.repository2.unified.RepositoryFilePermission;
import org.pentaho.platform.api.repository2.unified.RepositoryFileSid;
import org.pentaho.platform.api.repository2.unified.RepositoryFileTree;
import org.pentaho.platform.api.repository2.unified.RepositoryRequest;
import org.pentaho.platform.api.repository2.unified.UnifiedRepositoryException;
import org.pentaho.platform.api.repository2.unified.VersionSummary;
import org.pentaho.platform.api.repository2.unified.data.node.DataNode;
import org.pentaho.platform.api.repository2.unified.data.node.DataNode.DataPropertyType;
import org.pentaho.platform.api.repository2.unified.data.node.DataProperty;
import org.pentaho.platform.api.repository2.unified.data.node.NodeRepositoryFileData;
import org.pentaho.platform.api.repository2.unified.data.simple.SimpleRepositoryFileData;
import org.pentaho.platform.core.mt.Tenant;
import org.pentaho.platform.security.userroledao.DefaultTenantedPrincipleNameResolver;
import org.springframework.security.AccessDeniedException;
import org.springframework.security.GrantedAuthority;
import org.springframework.security.context.SecurityContextHolder;
/**
* Mock implementation of the {@link IUnifiedRepository} for unit testing.
*
* @author dkincade
* @author mlowery
*/
@SuppressWarnings( "nls" )
public class MockUnifiedRepository implements IUnifiedRepository {
// ~ Static fields/initializers
// ======================================================================================
// ~ Instance fields
// =================================================================================================
private IdManager idManager = new IdManager();
private VersionManager versionManager = new VersionManager();
private DeleteManager deleteManager = new DeleteManager();
private LockManager lockManager = new LockManager();
private ReferralManager referralManager = new ReferralManager();
private ICurrentUserProvider currentUserProvider = new SpringSecurityCurrentUserProvider();
private FileRecord root;
private static ITenantedPrincipleNameResolver userNameUtils = new DefaultTenantedPrincipleNameResolver();
// ~ Constructors
// ====================================================================================================
/**
* Creates a mock.
*
* @param currentUserProvider
* create your own or use {@link SpringSecurityCurrentUserProvider}.
*/
public MockUnifiedRepository( final ICurrentUserProvider currentUserProvider ) {
super();
init();
this.currentUserProvider = currentUserProvider;
}
// ~ Methods
// =========================================================================================================
public static RepositoryFileSid everyone() {
return new RepositoryFileSid( userNameUtils.getPrincipleId( null, "__everyone__" ), ROLE );
}
public static RepositoryFileSid root() {
return new RepositoryFileSid( userNameUtils.getPrincipleId( null, "__root__" ), USER );
}
protected void init() {
RepositoryFile rootFolder =
new RepositoryFile.Builder( "" ).path( RepositoryFile.SEPARATOR ).folder( true ).build();
RepositoryFileAcl rootFolderAcl =
new RepositoryFileAcl.Builder( root() ).entriesInheriting( false ).ace( everyone(), READ ).build();
root = new FileRecord( rootFolder, rootFolderAcl );
idManager.register( root );
RepositoryFile publicFolder =
new RepositoryFile.Builder( "public" ).path( RepositoryFile.SEPARATOR + "public" ).folder( true ).build();
RepositoryFileAcl publicFolderAcl =
new RepositoryFileAcl.Builder( root() ).entriesInheriting( false ).ace( everyone(), READ, WRITE ).build();
FileRecord pub = new FileRecord( publicFolder, publicFolderAcl );
root.addChild( pub );
idManager.register( pub );
RepositoryFile etcFolder =
new RepositoryFile.Builder( "etc" ).path( RepositoryFile.SEPARATOR + "etc" ).folder( true ).build();
RepositoryFileAcl etcFolderAcl = new RepositoryFileAcl.Builder( root() ).entriesInheriting( true ).build();
FileRecord etc = new FileRecord( etcFolder, etcFolderAcl );
root.addChild( etc );
idManager.register( etc );
}
@Override
public RepositoryFile getFile( final String path ) {
FileRecord r = root.getFileRecord( path );
if ( r != null ) {
if ( !hasAccess( r.getFile().getId(), EnumSet.of( READ ) ) ) {
return null;
}
return r.getFile();
}
return null;
}
@Override
public RepositoryFileTree getTree( RepositoryRequest repositoryRequest ) {
return getTree( repositoryRequest.getPath(), repositoryRequest.getDepth(), repositoryRequest.getChildNodeFilter(),
repositoryRequest.isShowHidden() );
}
@Override
public RepositoryFileTree getTree( final String path, final int depth, final String filter,
final boolean showHidden ) {
FileRecord r = root.getFileRecord( path );
RepositoryFile rootFile = r.getFile();
if ( !showHidden && rootFile.isHidden() ) {
return null;
}
List<RepositoryFileTree> children;
if ( depth != 0 ) {
children = new ArrayList<RepositoryFileTree>();
if ( rootFile.isFolder() ) {
List<RepositoryFile> childrenTmp = getChildren( rootFile.getId(), filter );
for ( RepositoryFile child : childrenTmp ) {
RepositoryFileTree repositoryFileTree = getTree( child.getPath(), depth - 1, filter, showHidden );
if ( repositoryFileTree != null ) {
children.add( repositoryFileTree );
}
}
}
Collections.sort( children );
} else {
children = null;
}
return new RepositoryFileTree( rootFile, children );
}
@Override
public RepositoryFile getFileAtVersion( final Serializable fileId, final Serializable versionId ) {
return versionManager.getFileAtVersion( fileId, versionId ).getFile();
}
@Override
public RepositoryFile getFileById( final Serializable fileId ) {
if ( idManager.hasId( fileId ) ) {
if ( !hasAccess( fileId, EnumSet.of( READ ) ) ) {
return null;
}
return idManager.getFileById( fileId ).getFile();
}
return null;
}
@Override
public RepositoryFile getFile( final String path, final boolean loadLocaleMaps ) {
return getFile( path );
}
@Override
public RepositoryFile getFileById( final Serializable fileId, final boolean loadLocaleMaps ) {
return getFileById( fileId );
}
@Override
public RepositoryFile getFile( String path, IPentahoLocale locale ) {
return getFile( path );
}
@Override
public RepositoryFile getFileById( Serializable fileId, IPentahoLocale locale ) {
return getFileById( fileId );
}
@Override
public RepositoryFile getFile( String path, boolean loadLocaleMaps, IPentahoLocale locale ) {
return getFile( path );
}
@Override
public RepositoryFile getFileById( Serializable fileId, boolean loadLocaleMaps, IPentahoLocale locale ) {
return getFileById( fileId );
}
@Override
@SuppressWarnings( "unchecked" )
public <T extends IRepositoryFileData> T getDataForRead( final Serializable fileId, final Class<T> dataClass ) {
FileRecord r = idManager.getFileById( fileId );
return (T) r.getData();
}
@Override
@SuppressWarnings( "unchecked" )
public <T extends IRepositoryFileData> T getDataAtVersionForRead( final Serializable fileId,
final Serializable versionId, final Class<T> dataClass ) {
if ( versionId == null ) {
return (T) versionManager.getLatestVersion( fileId ).getData();
}
return (T) versionManager.getFileAtVersion( fileId, versionId ).getData();
}
@Override
public <T extends IRepositoryFileData> T getDataForExecute( final Serializable fileId, final Class<T> dataClass ) {
return getDataForRead( fileId, dataClass );
}
@Override
public <T extends IRepositoryFileData> T getDataAtVersionForExecute( final Serializable fileId,
final Serializable versionId, final Class<T> dataClass ) {
return getDataAtVersionForRead( fileId, versionId, dataClass );
}
@Override
public <T extends IRepositoryFileData> List<T> getDataForReadInBatch( final List<RepositoryFile> files,
final Class<T> dataClass ) {
List<T> datas = new ArrayList<T>();
for ( RepositoryFile file : files ) {
if ( file.getVersionId() != null ) {
datas.add( getDataAtVersionForRead( file.getId(), file.getVersionId(), dataClass ) );
} else {
datas.add( getDataForRead( file.getId(), dataClass ) );
}
}
return datas;
}
@Override
public <T extends IRepositoryFileData> List<T> getDataForExecuteInBatch( final List<RepositoryFile> files,
final Class<T> dataClass ) {
List<T> datas = new ArrayList<T>();
for ( RepositoryFile file : files ) {
if ( file.getVersionId() != null ) {
datas.add( getDataAtVersionForExecute( file.getId(), file.getVersionId(), dataClass ) );
} else {
datas.add( getDataForExecute( file.getId(), dataClass ) );
}
}
return datas;
}
@Override
public RepositoryFile createFile( final Serializable parentFolderId, final RepositoryFile file,
final IRepositoryFileData data, final String versionMessage ) {
return createFile( parentFolderId, file, data, createDefaultAcl(), versionMessage );
}
private RepositoryFileAcl createDefaultAcl() {
RepositoryFileAcl.Builder builder =
new RepositoryFileAcl.Builder( userNameUtils.getPrincipleId( new Tenant( "/pentaho", true ),
currentUserProvider.getUser() ) );
builder.entriesInheriting( true );
return builder.build();
}
@Override
public RepositoryFile createFile( final Serializable parentFolderId, final RepositoryFile file,
final IRepositoryFileData data, final RepositoryFileAcl acl, final String versionMessage ) {
Validate.isTrue( !file.isFolder() );
if ( !hasAccess( parentFolderId, EnumSet.of( WRITE ) ) ) {
throw new AccessDeniedException( "access denied" );
}
FileRecord parentFolder = idManager.getFileById( parentFolderId );
RepositoryFile fileFromRepo =
new RepositoryFile.Builder( file ).path( parentFolder.getPath() + RepositoryFile.SEPARATOR + file.getName() )
.title( findTitle( file ) ).description( findDesc( file ) ).build();
RepositoryFileAcl aclFromRepo = new RepositoryFileAcl.Builder( acl ).build();
FileRecord fileRecord = new FileRecord( fileFromRepo, data, aclFromRepo, new HashMap<String, Serializable>() );
idManager.register( fileRecord );
process( fileRecord, null );
parentFolder.addChild( fileRecord );
if ( file.isVersioned() ) {
versionManager.createVersion( fileRecord.getFile().getId(), currentUserProvider.getUser(), versionMessage,
new Date() );
}
return fileRecord.getFile();
}
private void process( final FileRecord r, final IRepositoryFileData oldData ) {
IRepositoryFileData data = r.getData();
if ( data instanceof SimpleRepositoryFileData ) {
r.setData( new ReusableSimpleRepositoryFileData( (SimpleRepositoryFileData) data ) );
} else if ( data instanceof NodeRepositoryFileData ) {
DataNode node = ( (NodeRepositoryFileData) data ).getNode();
referralManager.process( r.getFile().getId(), oldData != null ? ( (NodeRepositoryFileData) oldData ).getNode()
: null, node );
r.setData( new NodeRepositoryFileData( idManager.process( node ) ) );
}
}
private static String findTitle( final RepositoryFile file ) {
String title = null;
if ( file.getLocalePropertiesMap() != null ) {
Properties properties = file.getLocalePropertiesMap().get( Locale.getDefault().toString() );
if ( properties == null ) {
properties = file.getLocalePropertiesMap().get( RepositoryFile.DEFAULT_LOCALE );
if ( properties != null ) {
title = properties.getProperty( RepositoryFile.FILE_TITLE );
if ( StringUtils.isBlank( title ) ) {
title = properties.getProperty( RepositoryFile.TITLE );
}
}
}
}
return title;
}
private static String findDesc( final RepositoryFile file ) {
String desc = null;
if ( file.getLocalePropertiesMap() != null ) {
Properties properties = file.getLocalePropertiesMap().get( Locale.getDefault().toString() );
if ( properties == null ) {
properties = file.getLocalePropertiesMap().get( RepositoryFile.DEFAULT_LOCALE );
if ( properties != null ) {
desc = properties.getProperty( RepositoryFile.FILE_DESCRIPTION );
if ( StringUtils.isBlank( desc ) ) {
desc = properties.getProperty( RepositoryFile.DESCRIPTION );
}
}
}
}
return desc;
}
@Override
public RepositoryFile createFolder( final Serializable parentFolderId, final RepositoryFile file,
final String versionMessage ) {
return createFolder( parentFolderId, file, createDefaultAcl(), versionMessage );
}
@Override
public RepositoryFile createFolder( final Serializable parentFolderId, final RepositoryFile file,
final RepositoryFileAcl acl, final String versionMessage ) {
Validate.isTrue( file.isFolder() );
Validate.isTrue( !file.isVersioned() );
if ( !hasAccess( parentFolderId, EnumSet.of( WRITE ) ) ) {
throw new AccessDeniedException( "access denied" );
}
FileRecord parentFolder = idManager.getFileById( parentFolderId );
RepositoryFile fileFromRepo =
new RepositoryFile.Builder( file ).path(
parentFolder.getPath()
+ ( parentFolder.getPath().endsWith( RepositoryFile.SEPARATOR ) ? "" : RepositoryFile.SEPARATOR )
+ file.getName() ).title( findTitle( file ) ).description( findDesc( file ) ).build();
RepositoryFileAcl aclFromRepo = new RepositoryFileAcl.Builder( acl ).build();
FileRecord fileRecord = new FileRecord( fileFromRepo, null, aclFromRepo, new HashMap<String, Serializable>() );
idManager.register( fileRecord );
parentFolder.addChild( fileRecord );
return fileRecord.getFile();
}
@Override
public List<RepositoryFile> getChildren( RepositoryRequest repositoryRequest ) {
return getChildren( repositoryRequest.getPath(), repositoryRequest.getChildNodeFilter(), repositoryRequest.isShowHidden() );
}
@Override
public List<RepositoryFile> getChildren( final Serializable folderId ) {
return getChildren( folderId, null );
}
@Override
public List<RepositoryFile> getChildren( final Serializable folderId, final String filter ) {
return getChildren( folderId, filter, null );
}
@Override
public List<RepositoryFile> getChildren( final Serializable folderId, final String filter, final Boolean showHiddenFiles ) {
FileRecord r = idManager.getFileById( folderId );
List<RepositoryFile> children = new ArrayList<RepositoryFile>();
for ( FileRecord child : r.getChildren() ) {
if ( filter != null ) {
if ( matches( child.getFile().getName(), filter ) ) {
if ( hasAccess( child.getFile().getId(), EnumSet.of( READ ) ) ) {
children.add( child.getFile() );
}
}
} else {
if ( hasAccess( child.getFile().getId(), EnumSet.of( READ ) ) ) {
children.add( child.getFile() );
}
}
}
return children;
}
private static boolean matches( final String in, final String pattern ) {
StringBuilder buf = new StringBuilder();
// build a regex
String[] patterns = pattern.split( "\\|" );
for ( int i = 0; i < patterns.length; i++ ) {
if ( i > 0 ) {
buf.append( "|" );
}
String tmp = patterns[i].trim();
tmp = tmp.replace( ".", "\\." );
tmp = tmp.replace( "*", ".*" );
buf.append( tmp );
}
Pattern p = Pattern.compile( buf.toString() );
Matcher m = p.matcher( in );
return m.matches();
}
@Override
public RepositoryFile updateFile( final RepositoryFile file, final IRepositoryFileData data,
final String versionMessage ) {
Validate.isTrue( !file.isFolder() );
if ( !hasAccess( file.getId(), EnumSet.of( WRITE ) ) ) {
throw new AccessDeniedException( "access denied" );
}
FileRecord fileRecord = idManager.getFileById( file.getId() );
fileRecord.setFile( new RepositoryFile.Builder( file ).title( findTitle( file ) ).description( findDesc( file ) )
.build() );
IRepositoryFileData oldData = fileRecord.getData();
fileRecord.setData( data );
process( fileRecord, oldData );
if ( file.isVersioned() ) {
versionManager.createVersion( fileRecord.getFile().getId(), currentUserProvider.getUser(), versionMessage,
new Date() );
}
return fileRecord.getFile();
}
@Override
public void deleteFile( final Serializable fileId, final boolean permanent, final String versionMessage ) {
FileRecord r = idManager.getFileById( fileId );
FileRecord parentFolder = r.getParent();
orphanFile( fileId );
if ( !permanent ) {
deleteManager.trash( parentFolder.getPath(), r );
} else {
idManager.deregister( fileId );
}
}
private void orphanFile( final Serializable fileId ) {
FileRecord r = idManager.getFileById( fileId );
FileRecord parentFolder = r.getParent();
if ( !hasAccess( parentFolder.getFile().getId(), EnumSet.of( WRITE ) ) ) {
throw new AccessDeniedException( "access denied" );
}
parentFolder.orphan( r.getFile().getName() );
}
@Override
public void deleteFile( final Serializable fileId, final String versionMessage ) {
deleteFile( fileId, false, versionMessage );
}
@Override
public void moveFile( final Serializable fileId, final String destAbsPath, final String versionMessage ) {
copyMoveFile( fileId, destAbsPath, true );
}
@Override
public void copyFile( final Serializable fileId, final String destAbsPath, final String versionMessage ) {
copyMoveFile( fileId, destAbsPath, false );
}
private void copyMoveFile( final Serializable fileId, final String destAbsPath, final boolean move ) {
FileRecord src = idManager.getFileById( fileId );
FileRecord dest = root.getFileRecord( destAbsPath );
String newName = src.getFile().getName();
if ( dest != null ) {
if ( !dest.getFile().isFolder() ) {
throw new UnifiedRepositoryException( "file already exists" );
}
} else {
// find parent folder
String parentPath = StringUtils.substringBeforeLast( destAbsPath, RepositoryFile.SEPARATOR );
FileRecord parent = root.getFileRecord( parentPath );
if ( parent == null ) {
throw new UnifiedRepositoryException( "invalid destination path" );
}
dest = parent;
newName = StringUtils.substringAfterLast( destAbsPath, RepositoryFile.SEPARATOR );
}
String newPath =
dest.getPath()
+ ( dest.getPath().endsWith( RepositoryFile.SEPARATOR ) ? newName : RepositoryFile.SEPARATOR + newName );
FileRecord newChild =
new FileRecord( new RepositoryFile.Builder( src.getFile() ).name( newName ).path( newPath ).build(), src
.getData(), src.getAcl(), src.getMetadata() );
if ( !move ) {
idManager.register( newChild );
}
dest.addChild( newChild );
if ( move ) {
orphanFile( fileId );
}
}
@Override
public void undeleteFile( final Serializable fileId, final String versionMessage ) {
FileRecord r = idManager.getFileById( fileId );
FileRecord parentFolder = r.getParent();
if ( !hasAccess( parentFolder.getFile().getId(), EnumSet.of( WRITE ) ) ) {
throw new AccessDeniedException( "access denied" );
}
deleteManager.restore( fileId );
}
@Override
public List<RepositoryFile> getDeletedFiles( final String origParentFolderPath ) {
return getDeletedFiles( origParentFolderPath, null );
}
@Override
public List<RepositoryFile> getDeletedFiles( final String origParentFolderPath, final String filter ) {
List<RepositoryFile> deletedFiles = new ArrayList<RepositoryFile>();
List<FileRecord> d = deleteManager.getTrashedFiles( origParentFolderPath, filter );
for ( FileRecord r : d ) {
deletedFiles.add( r.getFile() );
}
return deletedFiles;
}
@Override
public List<RepositoryFile> getDeletedFiles() {
List<RepositoryFile> deletedFiles = new ArrayList<RepositoryFile>();
List<FileRecord> d = deleteManager.getTrashedFiles();
for ( FileRecord r : d ) {
deletedFiles.add( r.getFile() );
}
return deletedFiles;
}
@Override
public boolean canUnlockFile( final Serializable fileId ) {
return lockManager.canUnlockFile( fileId );
}
@Override
public void lockFile( final Serializable fileId, final String message ) {
lockManager.lockFile( fileId, message );
}
@Override
public void unlockFile( final Serializable fileId ) {
lockManager.unlockFile( fileId );
}
@Override
public RepositoryFileAcl getAcl( final Serializable fileId ) {
if ( !hasAccess( fileId, EnumSet.of( READ ) ) ) {
throw new AccessDeniedException( "access denied" );
}
FileRecord r = idManager.getFileById( fileId );
return r.getAcl();
}
@Override
public RepositoryFileAcl updateAcl( final RepositoryFileAcl acl ) {
if ( !hasAccess( acl.getId(), EnumSet.of( WRITE ) ) ) {
throw new AccessDeniedException( "access denied" );
}
FileRecord r = idManager.getFileById( acl.getId() );
r.setAcl( acl );
return acl;
}
@Override
public boolean hasAccess( final String path, final EnumSet<RepositoryFilePermission> permissions ) {
FileRecord r = root.getFileRecord( path );
if ( r != null ) {
return hasAccess( r.getFile().getId(), permissions );
}
return false;
}
private boolean hasAccess( final Serializable fileId, final EnumSet<RepositoryFilePermission> permissions ) {
String username = currentUserProvider.getUser();
List<String> roles = currentUserProvider.getRoles();
RepositoryFileAcl acl = idManager.getFileById( fileId ).getAcl();
if ( acl.getOwner().getType() == USER && acl.getOwner().getName().equals( username ) ) {
return true; // owner can do anything
}
List<RepositoryFileAce> aces = internalGetEffectiveAces( fileId );
for ( RepositoryFileAce ace : aces ) {
if ( ace.getSid().equals( everyone() ) && ace.getPermissions().containsAll( permissions ) ) {
return true; // match special everyone role
} else if ( ace.getSid().getType() == USER && ace.getSid().getName().equals( username )
&& ace.getPermissions().containsAll( permissions ) ) {
return true; // match on user
}
for ( String role : roles ) {
if ( ace.getSid().getType() == ROLE && ace.getSid().getName().equals( role )
&& ace.getPermissions().containsAll( permissions ) ) {
return true; // match on role
}
}
}
return false;
}
@Override
public List<RepositoryFileAce> getEffectiveAces( final Serializable fileId ) {
if ( !hasAccess( fileId, EnumSet.of( READ ) ) ) {
throw new AccessDeniedException( "access denied" );
}
return internalGetEffectiveAces( fileId );
}
private List<RepositoryFileAce> internalGetEffectiveAces( final Serializable fileId ) {
FileRecord r = idManager.getFileById( fileId );
if ( r.getParent() == null ) {
return r.getAcl().getAces();
} else if ( r.getAcl().isEntriesInheriting() == false ) {
return r.getAcl().getAces();
} else {
return getEffectiveAces( r.getParent().getFile().getId() );
}
}
@Override
public List<RepositoryFileAce> getEffectiveAces( final Serializable fileId, final boolean forceEntriesInheriting ) {
FileRecord r = idManager.getFileById( fileId );
if ( r.getParent() != null ) {
return getEffectiveAces( r.getParent().getFile().getId() );
}
return r.getAcl().getAces();
}
@Override
public VersionSummary getVersionSummary( final Serializable fileId, final Serializable versionId ) {
FrozenFileRecord r = null;
if ( versionId == null ) {
r = versionManager.getLatestVersion( fileId );
} else {
r = versionManager.getFileAtVersion( fileId, versionId );
}
return new VersionSummary( r.getVersionId(), r.getFile().getId(), false, r.getDate(), r.getAuthor(), r
.getVersionMessage(), new ArrayList<String>( 0 ) );
}
@Override
public List<VersionSummary> getVersionSummaryInBatch( final List<RepositoryFile> files ) {
List<VersionSummary> sums = new ArrayList<VersionSummary>();
for ( RepositoryFile file : files ) {
if ( file.getVersionId() != null ) {
sums.add( getVersionSummary( file.getId(), file.getVersionId() ) );
} else {
sums.add( getVersionSummary( file.getId(), versionManager.getLatestVersion( file.getId() ).getVersionId() ) );
}
}
return sums;
}
@Override
public List<VersionSummary> getVersionSummaries( final Serializable fileId ) {
List<VersionSummary> sums = new ArrayList<VersionSummary>();
List<FrozenFileRecord> records = versionManager.getVersions( fileId );
for ( FrozenFileRecord record : records ) {
sums.add( new VersionSummary( record.getVersionId(), record.getFile().getId(), false, record.getDate(), record
.getAuthor(), record.getVersionMessage(), new ArrayList<String>( 0 ) ) );
}
return sums;
}
@Override
public void deleteFileAtVersion( final Serializable fileId, final Serializable versionId ) {
versionManager.deleteVersion( fileId, versionId );
}
@Override
public void
restoreFileAtVersion( final Serializable fileId, final Serializable versionId, final String versionMessage ) {
FrozenFileRecord restored =
versionManager.restoreVersion( fileId, versionId, currentUserProvider.getUser(), versionMessage, new Date() );
FileRecord fileRecord = idManager.getFileById( fileId );
fileRecord.setData( restored.getData() );
fileRecord.setMetadata( restored.getMetadata() );
// reset properties that aren't versioned
RepositoryFile orig = fileRecord.getFile();
fileRecord.setFile( new RepositoryFile.Builder( restored.getFile() ).locked( orig.isLocked() ).lockDate(
orig.getLockDate() ).lockMessage( orig.getLockMessage() ).lockOwner( orig.getLockOwner() ).build() );
}
@Override
public List<RepositoryFile> getReferrers( final Serializable fileId ) {
List<RepositoryFile> files = new ArrayList<RepositoryFile>();
for ( Serializable refFileId : referralManager.getReferrers( fileId ) ) {
files.add( idManager.getFileById( refFileId ).getFile() );
}
return files;
}
@Override
public void setFileMetadata( final Serializable fileId, final Map<String, Serializable> metadataMap ) {
// if (!hasAccess(fileId, EnumSet.of(WRITE))) {
// throw new AccessDeniedException("access denied");
// }
FileRecord r = idManager.getFileById( fileId );
r.setMetadata( metadataMap );
}
@Override
public Map<String, Serializable> getFileMetadata( final Serializable fileId ) {
if ( !hasAccess( fileId, EnumSet.of( READ ) ) ) {
throw new AccessDeniedException( "access denied" );
}
FileRecord r = idManager.getFileById( fileId );
return r.getMetadata();
}
// ~ Helper classes
// ==================================================================================================
@SuppressWarnings( "serial" )
private class ReusableSimpleRepositoryFileData extends SimpleRepositoryFileData {
private byte[] bytes;
public ReusableSimpleRepositoryFileData( final SimpleRepositoryFileData data ) {
super( null, data.getEncoding(), data.getMimeType() );
try {
bytes = IOUtils.toByteArray( data.getStream() );
} catch ( IOException e ) {
throw new RuntimeException( e );
}
}
@Override
public InputStream getStream() {
return new ByteArrayInputStream( bytes );
}
}
private class FileRecord implements Comparable<FileRecord> {
public FileRecord( final RepositoryFile file, final IRepositoryFileData data, final RepositoryFileAcl acl,
final Map<String, Serializable> metadata ) {
this.file = file;
setData( data );
this.acl = acl;
setMetadata( metadata );
}
public FileRecord( final RepositoryFile file, final RepositoryFileAcl acl ) {
this( file, null, acl, new HashMap<String, Serializable>() );
}
public void setFile( final RepositoryFile file ) {
this.file = file;
}
public void setData( final IRepositoryFileData data ) {
this.data = data;
}
public void setAcl( final RepositoryFileAcl acl ) {
this.acl = acl;
}
public void setMetadata( final Map<String, Serializable> metadata ) {
this.metadata = new HashMap<String, Serializable>( metadata );
}
private void setParent( final FileRecord parent ) {
this.parent = parent;
}
private FileRecord getParent() {
return parent;
}
public RepositoryFileAcl getAcl() {
return acl;
}
public String getPath() {
if ( file.getName().equals( "" ) ) {
return RepositoryFile.SEPARATOR;
}
String parentPath = parent.getPath();
return parentPath + ( parentPath.endsWith( RepositoryFile.SEPARATOR ) ? "" : RepositoryFile.SEPARATOR )
+ file.getName();
}
public FileRecord getFileRecord( final String path ) {
String normalizedPath = path;
if ( path.startsWith( RepositoryFile.SEPARATOR ) ) {
normalizedPath = path.substring( 1 );
}
if ( normalizedPath.equals( "" ) ) {
return this;
}
String[] pathSegments = normalizedPath.split( RepositoryFile.SEPARATOR );
if ( hasChild( pathSegments[0] ) ) {
return getChild( pathSegments[0] ).getFileRecord(
1 <= pathSegments.length - 1 ? StringUtils.join(
Arrays.copyOfRange( pathSegments, 1, pathSegments.length ), RepositoryFile.SEPARATOR ) : "" );
}
return null;
}
public boolean hasChild( final String name ) {
return getChild( name ) != null;
}
public FileRecord getChild( final String name ) {
for ( FileRecord child : children ) {
if ( child.getFile().getName().equals( name ) ) {
return child;
}
}
return null;
}
private RepositoryFile file;
private IRepositoryFileData data;
private Map<String, Serializable> metadata;
public FileRecord parent;
public List<FileRecord> children = new ArrayList<FileRecord>();
public RepositoryFileAcl acl;
public void addChild( final FileRecord fileRecord ) {
// make sure no name collision
for ( FileRecord child : children ) {
if ( child.getFile().getName().equals( fileRecord.getFile().getName() ) ) {
throw new UnifiedRepositoryException( String.format( "file [%s] already exists", fileRecord.getFile()
.getName() ) );
}
}
children.add( fileRecord );
fileRecord.setParent( this );
Collections.sort( children );
}
public List<FileRecord> getChildren() {
return Collections.unmodifiableList( children );
}
public void orphan( final String name ) {
for ( Iterator<FileRecord> iter = children.iterator(); iter.hasNext(); ) {
FileRecord r = iter.next();
if ( r.getFile().getName().equals( name ) ) {
iter.remove();
return;
}
}
}
private RepositoryFile getFile() {
return file;
}
private IRepositoryFileData getData() {
return data;
}
private Map<String, Serializable> getMetadata() {
return Collections.unmodifiableMap( metadata );
}
@Override
public int compareTo( final FileRecord other ) {
return this.getFile().getName().compareTo( other.getFile().getName() );
}
}
private class IdManager {
private Map<Serializable, FileRecord> idMap = new HashMap<Serializable, FileRecord>();
public boolean hasId( final Serializable fileId ) {
return idMap.containsKey( fileId );
}
public FileRecord getFileById( final Serializable fileId ) {
FileRecord r = idMap.get( fileId );
if ( r == null ) {
throw new UnifiedRepositoryException( String.format( "file id [%s] does not exist", fileId ) );
}
return r;
}
public void register( final FileRecord fileRecord ) {
Serializable fileId = UUID.randomUUID().toString();
fileRecord.setFile( new RepositoryFile.Builder( fileRecord.getFile() ).id( fileId ).build() );
fileRecord.setAcl( new RepositoryFileAcl.Builder( fileRecord.getAcl() ).id( fileId ).build() );
idMap.put( fileId, fileRecord );
}
public DataNode process( final DataNode node ) {
node.setId( UUID.randomUUID().toString() );
for ( DataNode child : node.getNodes() ) {
process( child );
}
return node;
}
/**
* Removes file from this manager. Returns FileRecord mapped to fileId (null if no such fileId).
*/
public FileRecord deregister( final Serializable fileId ) {
return idMap.remove( fileId );
}
}
private class VersionManager {
private Map<Serializable, List<FrozenFileRecord>> versionMap = new HashMap<Serializable, List<FrozenFileRecord>>();
public FrozenFileRecord getLatestVersion( final Serializable fileId ) {
List<FrozenFileRecord> history = versionMap.get( fileId );
if ( history == null ) {
throw new UnifiedRepositoryException( String.format( "version history for [%s] does not exist", fileId ) );
}
return history.get( history.size() - 1 );
}
public void createVersion( final Serializable fileId, final String author, final String versionMessage,
final Date date ) {
List<FrozenFileRecord> history = versionMap.get( fileId );
if ( history == null ) {
history = new ArrayList<FrozenFileRecord>();
versionMap.put( fileId, history );
}
FileRecord fileRecord = idManager.getFileById( fileId );
fileRecord.setFile( new RepositoryFile.Builder( fileRecord.getFile() ).versionId( history.size() ).build() );
history.add( new FrozenFileRecord( history.size(), fileRecord.getFile(), fileRecord.getData(), fileRecord
.getMetadata(), author, versionMessage, date ) );
}
public void deleteVersion( final Serializable fileId, final Serializable versionId ) {
List<FrozenFileRecord> history = versionMap.get( fileId );
if ( history == null ) {
throw new UnifiedRepositoryException( String.format( "version history for [%s] does not exist", fileId ) );
}
Integer versionNumber = versionNumber( versionId );
if ( versionNumber >= 0 && versionNumber < history.size() ) {
FrozenFileRecord r = history.get( versionNumber );
if ( r == null ) {
throw new UnifiedRepositoryException( String.format( "version [%s] does not exist", versionId ) );
}
history.set( versionNumber, null );
} else {
throw new UnifiedRepositoryException( String.format( "unknown version [%s]", fileId ) );
}
}
public FrozenFileRecord restoreVersion( final Serializable fileId, final Serializable versionId,
final String author, final String versionMessage, final Date date ) {
List<FrozenFileRecord> history = versionMap.get( fileId );
if ( history == null ) {
throw new UnifiedRepositoryException( String.format( "version history for [%s] does not exist", fileId ) );
}
Integer versionNumber = versionNumber( versionId );
if ( versionNumber >= 0 && versionNumber < history.size() ) {
FrozenFileRecord r = history.get( versionNumber );
if ( r == null ) {
throw new UnifiedRepositoryException( String.format( "version [%s] does not exist", versionId ) );
}
history.add( new FrozenFileRecord( history.size(), new RepositoryFile.Builder( r.getFile() ).versionId(
history.size() ).build(), r.getData(), r.getMetadata(), author, versionMessage, date ) );
return history.get( history.size() - 1 );
}
throw new UnifiedRepositoryException( String.format( "unknown version [%s]", fileId ) );
}
public List<FrozenFileRecord> getVersions( final Serializable fileId ) {
List<FrozenFileRecord> history = versionMap.get( fileId );
if ( history == null ) {
throw new UnifiedRepositoryException( String.format( "version history for [%s] does not exist", fileId ) );
}
List<FrozenFileRecord> cleanedHistory = new ArrayList<FrozenFileRecord>( history );
for ( Iterator<FrozenFileRecord> iter = cleanedHistory.iterator(); iter.hasNext(); ) {
FrozenFileRecord r = iter.next();
if ( r == null ) {
iter.remove();
}
}
return cleanedHistory;
}
public FrozenFileRecord getFileAtVersion( final Serializable fileId, final Serializable versionId ) {
List<FrozenFileRecord> history = versionMap.get( fileId );
if ( history == null ) {
throw new UnifiedRepositoryException( String.format( "version history for [%s] does not exist", fileId ) );
}
Integer versionNumber = versionNumber( versionId );
FrozenFileRecord r = history.get( versionNumber );
if ( r == null ) {
throw new UnifiedRepositoryException( String.format( "version [%s] does not exist", versionId ) );
}
return r;
}
private int versionNumber( final Serializable versionId ) {
if ( versionId instanceof Integer ) {
return (Integer) versionId;
} else if ( versionId instanceof String ) {
return Integer.parseInt( (String) versionId );
} else {
return Integer.parseInt( versionId.toString() );
}
}
}
public class FrozenFileRecord {
private Serializable versionId;
private RepositoryFile file;
private IRepositoryFileData data;
private Map<String, Serializable> metadata;
private String author;
private String versionMessage;
private Date date;
public FrozenFileRecord( final Serializable versionId, final RepositoryFile file, final IRepositoryFileData data,
final Map<String, Serializable> metadata, final String author, final String versionMessage, final Date date ) {
super();
this.versionId = versionId;
this.file = file;
this.data = data;
this.metadata = metadata;
this.author = author;
this.versionMessage = versionMessage;
this.date = date;
}
public Serializable getVersionId() {
return versionId;
}
public RepositoryFile getFile() {
return file;
}
public IRepositoryFileData getData() {
return data;
}
public Map<String, Serializable> getMetadata() {
return metadata;
}
private String getAuthor() {
return author;
}
private String getVersionMessage() {
return versionMessage;
}
private Date getDate() {
return date;
}
}
private class DeleteManager {
Map<String, Trash> userToTrashMap = new HashMap<String, Trash>();
private class Trash {
private Map<String, List<FileRecord>> origPathToFilesMap = new HashMap<String, List<FileRecord>>();
private Map<Serializable, String> idToOrigPathMap = new HashMap<Serializable, String>();
private Map<String, List<FileRecord>> getOrigPathToFilesMap() {
return origPathToFilesMap;
}
private Map<Serializable, String> getIdToOrigPathMap() {
return idToOrigPathMap;
}
}
public void trash( final String origPath, final FileRecord deletedRecord ) {
Trash trash = userToTrashMap.get( currentUserProvider.getUser() );
if ( trash == null ) {
trash = new Trash();
userToTrashMap.put( currentUserProvider.getUser(), trash );
}
RepositoryFile popFile =
new RepositoryFile.Builder( deletedRecord.getFile() ).originalParentFolderPath( origPath ).deletedDate(
new Date() ).build();
deletedRecord.setFile( popFile );
List<FileRecord> dels = trash.getOrigPathToFilesMap().get( origPath );
if ( dels == null ) {
dels = new ArrayList<FileRecord>();
trash.getOrigPathToFilesMap().put( origPath, dels );
}
dels.add( deletedRecord );
trash.getIdToOrigPathMap().put( deletedRecord.getFile().getId(), origPath );
}
public void restore( final Serializable fileId ) {
Trash trash = userToTrashMap.get( currentUserProvider.getUser() );
if ( trash == null ) {
throw new UnifiedRepositoryException( "no trash found for user" );
}
String origPath = trash.getIdToOrigPathMap().get( fileId );
List<FileRecord> dels = trash.getOrigPathToFilesMap().get( origPath );
FileRecord found = null;
for ( Iterator<FileRecord> iter = dels.iterator(); iter.hasNext(); ) {
FileRecord r = iter.next();
if ( r.getFile().getId().equals( fileId ) ) {
iter.remove();
found = r;
}
}
FileRecord parentFolder = root.getFileRecord( origPath );
parentFolder.addChild( found );
trash.getIdToOrigPathMap().remove( fileId );
RepositoryFile popFile =
new RepositoryFile.Builder( found.getFile() ).originalParentFolderPath( null ).deletedDate( null ).build();
found.setFile( popFile );
}
public List<FileRecord> getTrashedFiles( final String path, final String filter ) {
Trash trash = userToTrashMap.get( currentUserProvider.getUser() );
if ( trash == null ) {
return Collections.emptyList();
}
List<FileRecord> filtered = new ArrayList<FileRecord>();
List<FileRecord> dels = trash.getOrigPathToFilesMap().get( path );
if ( dels == null ) {
return Collections.emptyList();
}
for ( FileRecord d : dels ) {
if ( filter != null ) {
if ( matches( d.getFile().getName(), filter ) ) {
filtered.add( d );
}
} else {
filtered.add( d );
}
}
return filtered;
}
public List<FileRecord> getTrashedFiles() {
Trash trash = userToTrashMap.get( currentUserProvider.getUser() );
if ( trash == null ) {
return Collections.emptyList();
}
List<FileRecord> deletedRecords = new ArrayList<FileRecord>();
for ( List<FileRecord> list : trash.getOrigPathToFilesMap().values() ) {
deletedRecords.addAll( list );
}
Collections.sort( deletedRecords );
return deletedRecords;
}
}
private class LockManager {
public boolean canUnlockFile( final Serializable fileId ) {
return hasAccess( fileId, EnumSet.of( WRITE ) );
}
public void lockFile( final Serializable fileId, final String message ) {
if ( !hasAccess( fileId, EnumSet.of( WRITE ) ) ) {
throw new UnifiedRepositoryException( "access denied" );
}
FileRecord r = idManager.getFileById( fileId );
if ( r.getFile().getLockOwner() != null ) {
throw new IllegalStateException( "file is already locked" );
}
r.setFile( new RepositoryFile.Builder( r.getFile() ).lockOwner( currentUserProvider.getUser() ).lockDate(
new Date() ).lockMessage( message ).locked( true ).build() );
}
public void unlockFile( final Serializable fileId ) {
if ( !hasAccess( fileId, EnumSet.of( WRITE ) ) ) {
throw new UnifiedRepositoryException( "access denied" );
}
FileRecord r = idManager.getFileById( fileId );
if ( r.getFile().getLockOwner() == null ) {
throw new IllegalStateException( "file is not locked" );
}
r.setFile( new RepositoryFile.Builder( r.getFile() ).lockOwner( null ).lockDate( null ).lockMessage( null )
.locked( false ).build() );
}
}
private class ReferralManager {
private Map<Serializable, Set<Serializable>> referrersMap = new HashMap<Serializable, Set<Serializable>>();
public void process( final Serializable fileId, final DataNode oldNode, final DataNode newNode ) {
if ( oldNode != null ) {
process( fileId, oldNode, true );
}
process( fileId, newNode, false );
}
private void process( final Serializable fileId, final DataNode node, final boolean clean ) {
for ( DataProperty property : node.getProperties() ) {
if ( property.getType() == DataPropertyType.REF ) {
Set<Serializable> referrers = referrersMap.get( property.getRef().getId() );
if ( referrers == null ) {
referrers = new HashSet<Serializable>();
referrersMap.put( property.getRef().getId(), referrers );
}
if ( clean ) {
referrers.remove( fileId );
} else {
referrers.add( fileId );
}
}
}
for ( DataNode child : node.getNodes() ) {
process( fileId, child, clean );
}
}
public Set<Serializable> getReferrers( final Serializable fileId ) {
Set<Serializable> refs = referrersMap.get( fileId );
if ( refs == null ) {
return Collections.emptySet();
}
return Collections.unmodifiableSet( refs );
}
}
public static interface ICurrentUserProvider {
public String getUser();
public List<String> getRoles();
}
public static class SpringSecurityCurrentUserProvider implements ICurrentUserProvider {
@Override
public String getUser() {
return SecurityContextHolder.getContext().getAuthentication().getName();
}
@Override
public List<String> getRoles() {
GrantedAuthority[] auths = SecurityContextHolder.getContext().getAuthentication().getAuthorities();
List<String> roles = new ArrayList<String>();
for ( GrantedAuthority auth : auths ) {
roles.add( auth.getAuthority() );
}
return roles;
}
}
@Override
public List<Character> getReservedChars() {
return Collections.emptyList();
}
@Override
public List<Locale> getAvailableLocalesForFileById( Serializable fileId ) {
return Collections.emptyList();
}
@Override
public List<Locale> getAvailableLocalesForFileByPath( String relPath ) {
return Collections.emptyList();
}
@Override
public List<Locale> getAvailableLocalesForFile( RepositoryFile repositoryFile ) {
return Collections.emptyList();
}
@Override
public Properties getLocalePropertiesForFileById( Serializable fileId, String locale ) {
return new Properties();
}
@Override
public Properties getLocalePropertiesForFileByPath( String relPath, String locale ) {
return new Properties();
}
@Override
public Properties getLocalePropertiesForFile( RepositoryFile repositoryFile, String locale ) {
return new Properties();
}
@Override
public void setLocalePropertiesForFileById( Serializable fileId, String locale, Properties properties ) {
}
@Override
public void setLocalePropertiesForFileByPath( String relPath, String locale, Properties properties ) {
}
@Override
public void setLocalePropertiesForFile( RepositoryFile repositoryFile, String locale, Properties properties ) {
}
@Override
public void deleteLocalePropertiesForFile( RepositoryFile repositoryFile, String locale ) {
}
@Override
public RepositoryFile updateFolder( RepositoryFile folder, String versionMessage ) {
Validate.isTrue( folder.isFolder() );
if ( !hasAccess( folder.getId(), EnumSet.of( WRITE ) ) ) {
throw new AccessDeniedException( "access denied" );
}
FileRecord fileRecord = idManager.getFileById( folder.getId() );
fileRecord.setFile( new RepositoryFile.Builder( folder ).hidden( folder.isHidden() ).title( findTitle( folder ) )
.description( findDesc( folder ) ).build() );
if ( folder.isVersioned() ) {
versionManager.createVersion( fileRecord.getFile().getId(), currentUserProvider.getUser(), versionMessage,
new Date() );
}
return fileRecord.getFile();
}
// public static void main(final String[] args) throws Exception {
// MockUnifiedRepository repo = new MockUnifiedRepository();
// t(repo.getFile("/").getId() != null);
// t(repo.getFile("/").getPath().equals("/"));
// t(repo.getFile("/public").getId() != null);
// t(repo.getFile("/public").getPath().equals("/public"));
// repo.createFile(repo.getFile("/public").getId(), new
// RepositoryFile.Builder("file.txt").versioned(true).build(),
// new SimpleRepositoryFileData(new ByteArrayInputStream("hello world".getBytes("UTF-8")), "UTF-8",
// "text/plain"),
// "hello world");
// t(repo.getFile("/public/file.txt").getId() != null);
// t(repo.getVersionSummaries(repo.getFile("/public/file.txt").getId()).size() == 1);
//
// repo.updateFile(repo.getFile("/public/file.txt"), new SimpleRepositoryFileData(new ByteArrayInputStream(
// "caio world".getBytes("UTF-8")), "UTF-8", "text/plain"), "caio world");
// t(repo.getVersionSummaries(repo.getFile("/public/file.txt").getId()).size() == 2);
// List<VersionSummary> sums = repo.getVersionSummaries(repo.getFile("/public/file.txt").getId());
// t(repo.getFileAtVersion(sums.get(0).getVersionedFileId(), sums.get(0).getId()) != null);
// t(repo.getFileAtVersion(sums.get(1).getVersionedFileId(), sums.get(1).getId()) != null);
// SimpleRepositoryFileData d = repo.getDataForRead(repo.getFile("/public/file.txt").getId(),
// SimpleRepositoryFileData.class);
// SimpleRepositoryFileData d0 = repo.getDataAtVersionForRead(repo.getFile("/public/file.txt").getId(),
// sums.get(0)
// .getId(), SimpleRepositoryFileData.class);
// SimpleRepositoryFileData d1 = repo.getDataAtVersionForRead(repo.getFile("/public/file.txt").getId(),
// sums.get(1)
// .getId(), SimpleRepositoryFileData.class);
// t(Arrays.equals(IOUtils.toByteArray(d.getStream()), IOUtils.toByteArray(d1.getStream())));
// t(Arrays.equals(IOUtils.toByteArray(d0.getStream()), "hello world".getBytes("UTF-8")));
// t(Arrays.equals(IOUtils.toByteArray(d1.getStream()), "caio world".getBytes("UTF-8")));
//
// repo.restoreFileAtVersion(repo.getFile("/public/file.txt").getId(), sums.get(0).getId(), null);
// List<VersionSummary> sums2 = repo.getVersionSummaries(repo.getFile("/public/file.txt").getId());
// t(sums2.size() == 3);
// SimpleRepositoryFileData d2 = repo.getDataForRead(repo.getFile("/public/file.txt").getId(),
// SimpleRepositoryFileData.class);
// t(Arrays.equals(IOUtils.toByteArray(d2.getStream()), "hello world".getBytes("UTF-8")));
// repo.deleteFileAtVersion(repo.getFile("/public/file.txt").getId(), sums2.get(2).getId());
// t(repo.getVersionSummaries(repo.getFile("/public/file.txt").getId()).size() == 2);
//
// t(repo.getAcl(repo.getFile("/public/file.txt").getId()) != null);
// RepositoryFileAcl newAcl = new
// RepositoryFileAcl.Builder(repo.getAcl(repo.getFile("/public/file.txt").getId()))
// .ace(new RepositoryFileSid("larry", USER), READ).build();
// t(repo.updateAcl(newAcl).getId() != null);
// t(repo.getAcl(repo.getFile("/public/file.txt").getId()).getAces().get(0).getSid()
// .equals(new RepositoryFileSid("larry", USER)));
//
// t(repo.createFolder(repo.getFile("/public").getId(), new
// RepositoryFile.Builder("testFolder").folder(true).build(),
// null).getId() != null);
//
// t(repo.getChildren(repo.getFile("/public").getId()).size() == 2);
// t(repo.getChildren(repo.getFile("/public").getId(), "*.txt").size() == 1);
//
// RepositoryFileTree tree = repo.getTree("/public", -1, null, true);
// t(tree.getFile().getName().equals("public"));
// t(tree.getChildren().size() == 2);
// t(tree.getChildren().get(1).getFile().getName().equals("testFolder"));
//
// repo.copyFile(repo.getFile("/public/file.txt").getId(), "/public/testFolder", null);
// t(repo.getFile("/public/file.txt") != null);
// t(repo.getFile("/public/testFolder/file.txt") != null);
// t(!repo.getFile("/public/file.txt").getId().equals(repo.getFile("/public/testFolder/file.txt").getId()));
// Serializable testFolderFileId = repo.getFile("/public/testFolder/file.txt").getId();
// repo.moveFile(testFolderFileId, "/public/file2.txt", null);
// t(repo.getFile("/public/testFolder/file.txt") == null);
// t(repo.getFile("/public/file2.txt").getId().equals(testFolderFileId));
//
// t(repo.canUnlockFile(repo.getFile("/public/file.txt").getId()));
// t(!repo.getFile("/public/file.txt").isLocked());
// repo.lockFile(repo.getFile("/public/file.txt").getId(), "blah");
// t(repo.getFile("/public/file.txt").isLocked());
// t(repo.getFile("/public/file.txt").getLockMessage().equals("blah"));
// repo.unlockFile(repo.getFile("/public/file.txt").getId());
// t(!repo.getFile("/public/file.txt").isLocked());
//
// t(repo.getDeletedFiles().isEmpty());
// Serializable fileTxtId = repo.getFile("/public/file.txt").getId();
// repo.deleteFile(repo.getFile("/public/file.txt").getId(), null);
// t(repo.getDeletedFiles().size() == 1);
// t(repo.getDeletedFiles("/public").size() == 1);
// t(repo.getDeletedFiles("/public", "*.txt").size() == 1);
// repo.undeleteFile(fileTxtId, null);
// t(repo.getDeletedFiles().isEmpty());
// repo.deleteFile(repo.getFile("/public/file.txt").getId(), true, null);
// t(repo.getDeletedFiles().isEmpty());
// }
//
// private static void t(boolean test) {
// if (!test) {
// throw new RuntimeException();
// }
// }
}