/*
* This program is free software; you can redistribute it and/or modify it under the
* terms of the GNU General Public License, version 2 as published by the Free Software
* Foundation.
*
* You should have received a copy of the GNU General Public License along with this
* program; if not, you can obtain a copy at http://www.gnu.org/licenses/gpl-2.0.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 General Public License for more details.
*
*
* Copyright 2006 - 2013 Pentaho Corporation. All rights reserved.
*/
package org.pentaho.platform.repository2.unified.webservices;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Properties;
import javax.jws.WebService;
import org.pentaho.platform.api.engine.IAuthorizationPolicy;
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.RepositoryFileTree;
import org.pentaho.platform.api.repository2.unified.RepositoryRequest;
import org.pentaho.platform.api.repository2.unified.VersionSummary;
import org.pentaho.platform.api.repository2.unified.data.node.NodeRepositoryFileData;
import org.pentaho.platform.engine.core.system.PentahoSystem;
import org.pentaho.platform.repository2.locale.PentahoLocale;
import org.pentaho.platform.security.policy.rolebased.actions.AdministerSecurityAction;
/**
* Implementation of {@link IUnifiedRepositoryWebService} that delegates to an {@link IUnifiedRepository} instance.
*
* @author mlowery
*/
@WebService( endpointInterface = "org.pentaho.platform.repository2.unified.webservices.IUnifiedRepositoryWebService",
serviceName = "unifiedRepository", portName = "unifiedRepositoryPort",
targetNamespace = "http://www.pentaho.org/ws/1.0" )
public class DefaultUnifiedRepositoryWebService implements IUnifiedRepositoryWebService {
protected IUnifiedRepository repo;
protected RepositoryFileAdapter repositoryFileAdapter = new RepositoryFileAdapter();
protected NodeRepositoryFileDataAdapter nodeRepositoryFileDataAdapter = new NodeRepositoryFileDataAdapter();
protected RepositoryFileAclAdapter repositoryFileAclAdapter = new RepositoryFileAclAdapter();
protected RepositoryFileAclAceAdapter repositoryFileAclAceAdapter = new RepositoryFileAclAceAdapter();
protected VersionSummaryAdapter versionSummaryAdapter = new VersionSummaryAdapter();
protected RepositoryFileTreeAdapter repositoryFileTreeAdapter;
// ~ Constructors
// ====================================================================================================
/**
* No-arg constructor for when in Pentaho BI Server.
*/
public DefaultUnifiedRepositoryWebService() {
super();
// repo = new MockUnifiedRepository();
repo = PentahoSystem.get( IUnifiedRepository.class );
if ( repo == null ) {
throw new IllegalStateException();
}
}
public DefaultUnifiedRepositoryWebService( final IUnifiedRepository repo ) {
super();
this.repo = repo;
}
@Override
public List<RepositoryFileDto> getChildrenFromRequest( RepositoryRequest repositoryRequest ) {
return marshalFiles( repo.getChildren( repositoryRequest ), repositoryRequest );
}
@Deprecated
public List<RepositoryFileDto> getChildren( String folderId ) {
return getChildrenWithFilter( folderId, null );
}
@Deprecated
public List<RepositoryFileDto> getChildrenWithFilter( String folderId, String filter ) {
return getChildrenWithFilterAndHidden( folderId, filter, false );
}
@Deprecated
public List<RepositoryFileDto>
getChildrenWithFilterAndHidden( String folderId, String filter, Boolean showHiddenFiles ) {
return marshalFiles( repo.getChildren( new RepositoryRequest( folderId, showHiddenFiles, 0, filter ) ) );
}
public NodeRepositoryFileDataDto getDataAsNodeForRead( final String fileId ) {
NodeRepositoryFileData fileData = repo.getDataForRead( fileId, NodeRepositoryFileData.class );
return fileData != null ? nodeRepositoryFileDataAdapter.marshal( fileData ) : null;
}
public List<NodeRepositoryFileDataDto> getDataAsNodeForReadInBatch( final List<RepositoryFileDto> files ) {
List<NodeRepositoryFileDataDto> data = new ArrayList<NodeRepositoryFileDataDto>( files.size() );
for ( RepositoryFileDto f : files ) {
if ( f.getVersionId() == null ) {
data.add( nodeRepositoryFileDataAdapter
.marshal( repo.getDataForRead( f.getId(), NodeRepositoryFileData.class ) ) );
} else {
data.add( nodeRepositoryFileDataAdapter.marshal( repo.getDataAtVersionForRead( f.getId(), f.getVersionId(),
NodeRepositoryFileData.class ) ) );
}
}
return data;
}
public RepositoryFileDto getFile( String path ) {
validateEtcReadAccess( path );
RepositoryFile file = repo.getFile( path );
return file != null ? repositoryFileAdapter.marshal( file ) : null;
}
public RepositoryFileDto getFileById( String fileId ) {
RepositoryFile file = repo.getFileById( fileId );
return file != null ? repositoryFileAdapter.marshal( file ) : null;
}
@Override
public RepositoryFileDto getFile( String path, boolean loadLocaleMaps, PentahoLocale locale ) {
RepositoryFile file = this.repo.getFile( path, loadLocaleMaps, locale );
return file != null ? this.repositoryFileAdapter.marshal( file ) : null;
}
@Override
public RepositoryFileDto getFileById( String fileId, boolean loadLocaleMaps, PentahoLocale locale ) {
RepositoryFile file = this.repo.getFileById( fileId, loadLocaleMaps, locale );
return file != null ? this.repositoryFileAdapter.marshal( file ) : null;
}
public RepositoryFileTreeDto getTree( final String path, final int depth, final String filter,
final boolean showHidden ) {
RepositoryRequest repositoryRequest = new RepositoryRequest( path, showHidden, depth, filter );
return getTreeFromRequest( repositoryRequest );
}
public RepositoryFileTreeDto getTreeFromRequest( final RepositoryRequest repositoryRequest ) {
// RepositoryFileTree tree = repo.getTree( path, depth, filter, showHidden );
RepositoryFileTree tree = repo.getTree( repositoryRequest );
// Filter system folders from non-admin users.
// PDI uses this web-service and system folders must be returned to admin repository database connections.
List<RepositoryFileTree> files = new ArrayList<RepositoryFileTree>();
IAuthorizationPolicy policy = PentahoSystem.get( IAuthorizationPolicy.class );
boolean isAdmin = policy.isAllowed( AdministerSecurityAction.NAME );
for ( RepositoryFileTree file : tree.getChildren() ) {
Map<String, Serializable> fileMeta = repo.getFileMetadata( file.getFile().getId() );
boolean isSystemFolder =
fileMeta.containsKey( IUnifiedRepository.SYSTEM_FOLDER ) ? (Boolean) fileMeta
.get( IUnifiedRepository.SYSTEM_FOLDER ) : false;
if ( !isAdmin && isSystemFolder ) {
continue;
}
files.add( file );
}
tree = new RepositoryFileTree( tree.getFile(), files );
if ( tree == null ) {
return null;
}
return new RepositoryFileTreeAdapter( repositoryRequest ).marshal( tree );
}
private List<RepositoryFileDto> marshalFiles( List<RepositoryFile> files ) {
ArrayList<RepositoryFileDto> fileDtos = new ArrayList<RepositoryFileDto>();
for ( RepositoryFile file : files ) {
fileDtos.add( repositoryFileAdapter.marshal( file ) );
}
return fileDtos;
}
private List<RepositoryFileDto> marshalFiles( List<RepositoryFile> files, RepositoryRequest repositoryRequest ) {
ArrayList<RepositoryFileDto> fileDtos = new ArrayList<RepositoryFileDto>();
RepositoryFileAdapter filteringRepositoryFileAdapter = new RepositoryFileAdapter( repositoryRequest );
for ( RepositoryFile file : files ) {
fileDtos.add( filteringRepositoryFileAdapter.marshal( file ) );
}
return fileDtos;
}
private List<RepositoryFileAclAceDto> marshalAces( List<RepositoryFileAce> aces ) {
ArrayList<RepositoryFileAclAceDto> aceDtos = new ArrayList<RepositoryFileAclAceDto>();
for ( RepositoryFileAce ace : aces ) {
aceDtos.add( repositoryFileAclAceAdapter.marshal( ace ) );
}
return aceDtos;
}
public RepositoryFileDto createFolder( String parentFolderId, RepositoryFileDto file, String versionMessage ) {
RepositoryFile newFile =
repo.createFolder( parentFolderId, repositoryFileAdapter.unmarshal( file ), versionMessage );
return newFile != null ? repositoryFileAdapter.marshal( newFile ) : null;
}
public RepositoryFileDto createFolderWithAcl( String parentFolderId, RepositoryFileDto file,
RepositoryFileAclDto acl, String versionMessage ) {
RepositoryFile newFile =
repo.createFolder( parentFolderId, repositoryFileAdapter.unmarshal( file ), repositoryFileAclAdapter
.unmarshal( acl ), versionMessage );
return newFile != null ? repositoryFileAdapter.marshal( newFile ) : null;
}
public void deleteFile( String fileId, String versionMessage ) {
repo.deleteFile( fileId, versionMessage );
}
public void deleteFileAtVersion( String fileId, String versionId ) {
repo.deleteFileAtVersion( fileId, versionId );
}
public void deleteFileWithPermanentFlag( String fileId, boolean permanent, String versionMessage ) {
repo.deleteFile( fileId, permanent, versionMessage );
}
public List<RepositoryFileDto> getDeletedFiles() {
return marshalFiles( repo.getDeletedFiles() );
}
public List<RepositoryFileDto> getDeletedFilesInFolder( String folderPath ) {
return marshalFiles( repo.getDeletedFiles( folderPath ) );
}
public List<RepositoryFileDto> getDeletedFilesInFolderWithFilter( String folderPath, String filter ) {
return marshalFiles( repo.getDeletedFiles( folderPath, filter ) );
}
public void lockFile( String fileId, String message ) {
repo.lockFile( fileId, message );
}
public void moveFile( String fileId, String destAbsPath, String versionMessage ) {
repo.moveFile( fileId, destAbsPath, versionMessage );
}
public void copyFile( String fileId, String destAbsPath, String versionMessage ) {
repo.copyFile( fileId, destAbsPath, versionMessage );
}
public void undeleteFile( String fileId, String versionMessage ) {
repo.undeleteFile( fileId, versionMessage );
}
public void unlockFile( String fileId ) {
repo.unlockFile( fileId );
}
public RepositoryFileDto createFile( String parentFolderId, RepositoryFileDto file, NodeRepositoryFileDataDto data,
String versionMessage ) {
validateEtcWriteAccess( parentFolderId );
return repositoryFileAdapter.marshal( repo.createFile( parentFolderId, repositoryFileAdapter.unmarshal( file ),
nodeRepositoryFileDataAdapter.unmarshal( data ), versionMessage ) );
}
public RepositoryFileDto createFileWithAcl( String parentFolderId, RepositoryFileDto file,
NodeRepositoryFileDataDto data, RepositoryFileAclDto acl, String versionMessage ) {
validateEtcWriteAccess( parentFolderId );
return repositoryFileAdapter.marshal( repo.createFile( parentFolderId, repositoryFileAdapter.unmarshal( file ),
nodeRepositoryFileDataAdapter.unmarshal( data ), repositoryFileAclAdapter.unmarshal( acl ), versionMessage ) );
}
public RepositoryFileDto updateFile( RepositoryFileDto file, NodeRepositoryFileDataDto data, String versionMessage ) {
return repositoryFileAdapter.marshal( repo.updateFile( repositoryFileAdapter.unmarshal( file ),
nodeRepositoryFileDataAdapter.unmarshal( data ), versionMessage ) );
}
public boolean canUnlockFile( String fileId ) {
return repo.canUnlockFile( fileId );
}
public RepositoryFileAclDto getAcl( String fileId ) {
return repositoryFileAclAdapter.marshal( repo.getAcl( fileId ) );
}
public NodeRepositoryFileDataDto getDataAsNodeForReadAtVersion( String fileId, String versionId ) {
return nodeRepositoryFileDataAdapter.marshal( repo.getDataAtVersionForRead( fileId, versionId,
NodeRepositoryFileData.class ) );
}
public List<RepositoryFileAclAceDto> getEffectiveAces( String fileId ) {
return marshalAces( repo.getEffectiveAces( fileId ) );
}
public List<RepositoryFileAclAceDto> getEffectiveAcesWithForceFlag( String fileId, boolean forceEntriesInheriting ) {
return marshalAces( repo.getEffectiveAces( fileId, forceEntriesInheriting ) );
}
public RepositoryFileDto getFileAtVersion( String fileId, String versionId ) {
return repositoryFileAdapter.marshal( repo.getFileAtVersion( fileId, versionId ) );
}
public void restoreFileAtVersion( String fileId, String versionId, String versionMessage ) {
repo.restoreFileAtVersion( fileId, versionId, versionMessage );
}
public RepositoryFileAclDto updateAcl( RepositoryFileAclDto acl ) {
return repositoryFileAclAdapter.marshal( repo.updateAcl( repositoryFileAclAdapter.unmarshal( acl ) ) );
}
public List<VersionSummaryDto> getVersionSummaries( String fileId ) {
return marshalVersionSummaries( repo.getVersionSummaries( fileId ) );
}
private List<VersionSummaryDto> marshalVersionSummaries( List<VersionSummary> versionSummaries ) {
List<VersionSummaryDto> versionSummaryDtos = new ArrayList<VersionSummaryDto>();
for ( VersionSummary versionSummary : versionSummaries ) {
versionSummaryDtos.add( versionSummaryAdapter.marshal( versionSummary ) );
}
return versionSummaryDtos;
}
public VersionSummaryDto getVersionSummary( String fileId, String versionId ) {
return versionSummaryAdapter.marshal( repo.getVersionSummary( fileId, versionId ) );
}
public List<VersionSummaryDto> getVersionSummaryInBatch( final List<RepositoryFileDto> files ) {
List<VersionSummaryDto> versions = new ArrayList<VersionSummaryDto>( files.size() );
for ( RepositoryFileDto file : files ) {
versions.add( versionSummaryAdapter.marshal( repo.getVersionSummary( file.getId(), file.getVersionId() ) ) );
}
return versions;
}
public boolean hasAccess( String path, List<Integer> permissions ) {
return repo.hasAccess( path, RepositoryFileAclAceAdapter.toPerms( permissions ) );
}
public List<RepositoryFileDto> getReferrers( String fileId ) {
List<RepositoryFileDto> fileList = new ArrayList<RepositoryFileDto>();
for ( RepositoryFile file : repo.getReferrers( fileId ) ) {
fileList.add( repositoryFileAdapter.marshal( file ) );
}
return fileList;
}
@Override
public void setFileMetadata( final String fileId, final List<StringKeyStringValueDto> fileMetadataMap ) {
Map<String, Serializable> metadataMap = new HashMap<String, Serializable>( fileMetadataMap.size() );
for ( final StringKeyStringValueDto dto : fileMetadataMap ) {
metadataMap.put( dto.getKey(), dto.getValue() );
}
repo.setFileMetadata( fileId, metadataMap );
}
@Override
public List<StringKeyStringValueDto> getFileMetadata( final String fileId ) {
final Map<String, Serializable> metadataMap = repo.getFileMetadata( fileId );
final List<StringKeyStringValueDto> fileMetadataMap = new ArrayList<StringKeyStringValueDto>( metadataMap.size() );
for ( final String key : metadataMap.keySet() ) {
fileMetadataMap.add( new StringKeyStringValueDto( key, metadataMap.get( key ).toString() ) );
}
return fileMetadataMap;
}
@Override
public List<Character> getReservedChars() {
return repo.getReservedChars();
}
protected void validateEtcWriteAccess( String parentFolderId ) {
RepositoryFile etcFolder = repo.getFile( "/etc" );
if ( etcFolder != null ) {
String etcFolderId = etcFolder.getId().toString();
if ( etcFolderId.equals( parentFolderId ) ) {
throw new RuntimeException( "This service is not allowed to access the ETC folder in JCR." );
}
}
}
protected void validateEtcReadAccess( String path ) {
IAuthorizationPolicy policy = PentahoSystem.get( IAuthorizationPolicy.class );
boolean isAdmin = policy.isAllowed( AdministerSecurityAction.NAME );
if ( !isAdmin && path.startsWith( "/etc" ) ) {
throw new RuntimeException( "This user is not allowed to access the ETC folder in JCR." );
}
}
@Override
public List<PentahoLocale> getAvailableLocalesForFileById( String fileId ) {
List<PentahoLocale> pentahoLocales = new ArrayList<PentahoLocale>();
List<Locale> locales = repo.getAvailableLocalesForFileById( fileId );
if ( locales != null && !locales.isEmpty() ) {
for ( Locale locale : locales ) {
pentahoLocales.add( new PentahoLocale( locale ) );
}
}
return pentahoLocales;
}
@Override
public PropertiesWrapper getLocalePropertiesForFileById( String fileId, String locale ) {
return new PropertiesWrapper( repo.getLocalePropertiesForFileById( fileId, locale ) );
}
@Override
public void setLocalePropertiesForFileByFileId( String fileId, String locale, Properties properties ) {
repo.setLocalePropertiesForFileById( fileId, locale, properties );
}
@Override
public void deleteLocalePropertiesForFile( String fileId, String locale ) {
repo.deleteLocalePropertiesForFile( repo.getFileById( fileId ), locale );
}
@Override
public RepositoryFileDto updateFolder( RepositoryFileDto folder, String versionMessage ) {
// TODO Auto-generated method stub
return repositoryFileAdapter
.marshal( repo.updateFolder( repositoryFileAdapter.unmarshal( folder ), versionMessage ) );
}
}