/*!
* Copyright 2010 - 2017 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 org.pentaho.di.ui.repository.pur.repositoryexplorer.controller;
import java.util.Collection;
import java.util.Enumeration;
import java.util.List;
import java.util.ResourceBundle;
import org.pentaho.di.core.exception.KettleException;
import org.pentaho.di.i18n.BaseMessages;
import org.pentaho.di.repository.Repository;
import org.pentaho.di.repository.pur.PurRepository;
import org.pentaho.di.repository.pur.PurRepositoryMeta;
import org.pentaho.di.ui.repository.pur.repositoryexplorer.ILockObject;
import org.pentaho.di.ui.repository.pur.repositoryexplorer.IUIEEUser;
import org.pentaho.di.ui.repository.pur.services.ILockService;
import org.pentaho.di.ui.repository.repositoryexplorer.ControllerInitializationException;
import org.pentaho.di.ui.repository.repositoryexplorer.IUISupportController;
import org.pentaho.di.ui.repository.repositoryexplorer.controllers.BrowseController;
import org.pentaho.di.ui.repository.repositoryexplorer.model.UIRepositoryContent;
import org.pentaho.di.ui.repository.repositoryexplorer.model.UIRepositoryDirectory;
import org.pentaho.di.ui.repository.repositoryexplorer.model.UIRepositoryObject;
import org.pentaho.di.ui.repository.repositoryexplorer.model.UIRepositoryObjects;
import org.pentaho.ui.xul.XulComponent;
import org.pentaho.ui.xul.XulException;
import org.pentaho.ui.xul.binding.Binding.Type;
import org.pentaho.ui.xul.binding.BindingConvertor;
import org.pentaho.ui.xul.binding.BindingFactory;
import org.pentaho.ui.xul.binding.DefaultBindingFactory;
import org.pentaho.ui.xul.components.XulMenuitem;
import org.pentaho.ui.xul.components.XulMessageBox;
import org.pentaho.ui.xul.components.XulPromptBox;
import org.pentaho.ui.xul.containers.XulTree;
import org.pentaho.ui.xul.dnd.DropEvent;
import org.pentaho.ui.xul.impl.AbstractXulEventHandler;
import org.pentaho.ui.xul.impl.XulEventHandler;
import org.pentaho.ui.xul.swt.custom.DialogConstant;
import org.pentaho.ui.xul.util.XulDialogCallback;
public class RepositoryLockController extends AbstractXulEventHandler implements IUISupportController,
java.io.Serializable {
private static final long serialVersionUID = -1770253263177354811L; /* EESOURCE: UPDATE SERIALVERUID */
private static final Class<?> PKG = IUIEEUser.class;
private BrowseController browseController = null;
private BindingFactory bindingFactory = null;
private XulMessageBox messageBox;
private ILockService service = null;
private Repository repository = null;
private XulMenuitem lockFileMenuItem;
private XulMenuitem deleteFileMenuItem;
private XulMenuitem renameFileMenuItem;
private XulTree fileTable;
private XulTree folderTree;
protected ResourceBundle messages = new ResourceBundle() {
@Override
public Enumeration<String> getKeys() {
return null;
}
@Override
protected Object handleGetObject( String key ) {
return BaseMessages.getString( PKG, key );
}
};
public void init( Repository rep ) throws ControllerInitializationException {
try {
if ( rep != null && rep.hasService( ILockService.class ) ) {
repository = rep;
service = (ILockService) rep.getService( ILockService.class );
} else {
throw new ControllerInitializationException( BaseMessages.getString( PKG,
"RepositoryLockController.ERROR_0001_UNABLE_TO_INITIAL_REPOSITORY_SERVICE", ILockService.class ) ); //$NON-NLS-1$
}
bindingFactory = new DefaultBindingFactory();
bindingFactory.setDocument( getXulDomContainer().getDocumentRoot() );
XulEventHandler eventHandler = getXulDomContainer().getEventHandler( "browseController" ); //$NON-NLS-1$
if ( eventHandler instanceof BrowseController ) {
browseController = (BrowseController) eventHandler;
}
// Disable row dragging if it is locked and the user does not have permissions
fileTable = (XulTree) getXulDomContainer().getDocumentRoot().getElementById( "file-table" ); //$NON-NLS-1$
folderTree = (XulTree) document.getElementById( "folder-tree" ); //$NON-NLS-1$
lockFileMenuItem = (XulMenuitem) getXulDomContainer().getDocumentRoot().getElementById( "file-context-lock" ); //$NON-NLS-1$
deleteFileMenuItem = (XulMenuitem) getXulDomContainer().getDocumentRoot().getElementById( "file-context-delete" ); //$NON-NLS-1$
renameFileMenuItem = (XulMenuitem) getXulDomContainer().getDocumentRoot().getElementById( "file-context-rename" ); //$NON-NLS-1$
messageBox = (XulMessageBox) document.createElement( "messagebox" ); //$NON-NLS-1$
createBindings();
} catch ( Exception e ) {
throw new RuntimeException( e );
}
}
public void onDragFromGlobalTree( DropEvent event ) {
Collection<Object> selectedItems = folderTree.getSelectedItems();
if ( selectedItems.size() > 0 ) {
for ( Object object : selectedItems ) {
if ( object instanceof UIRepositoryDirectory ) {
try {
if ( !( repositoryDirectoryHasLockedObject( event, (UIRepositoryDirectory) object ) ) ) {
// All the contents in the folder are not locked, check default permissions
browseController.onDragFromGlobalTree( event );
}
} catch ( KettleException e ) {
throw new RuntimeException( e );
}
}
}
}
}
private boolean repositoryDirectoryHasLockedObject( DropEvent event, UIRepositoryDirectory dir )
throws KettleException {
if ( areAnyRepositoryObjectsLocked( event, dir.getRepositoryObjects() ) ) {
return true;
}
for ( UIRepositoryObject ro : dir.getChildren() ) {
if ( ro instanceof UIRepositoryDirectory ) {
UIRepositoryDirectory directory = (UIRepositoryDirectory) ro;
repositoryDirectoryHasLockedObject( event, directory );
}
}
return false;
}
private boolean areAnyRepositoryObjectsLocked( DropEvent event, UIRepositoryObjects repositoryObjects )
throws KettleException {
for ( UIRepositoryObject ro : repositoryObjects ) {
if ( ro instanceof ILockObject ) {
final UIRepositoryContent contentToLock = (UIRepositoryContent) ro;
if ( ( (ILockObject) contentToLock ).isLocked() ) {
// Content is locked, move is not allowed.
event.setAccepted( false );
messageBox.setTitle( BaseMessages.getString( PKG, "Dialog.Error" ) ); //$NON-NLS-1$
messageBox.setAcceptLabel( BaseMessages.getString( PKG, "Dialog.Ok" ) ); //$NON-NLS-1$
messageBox.setMessage( BaseMessages.getString( PKG, "BrowseController.FolderMoveNotAllowed" ) ); //$NON-NLS-1$
messageBox.open();
return true;
}
}
}
return false;
}
// Object being dragged from the file listing table
public void onDragFromLocalTable( DropEvent event ) {
try {
Collection<Object> selectedRepoObjects = fileTable.getSelectedItems();
if ( selectedRepoObjects.size() > 0 ) {
for ( Object ro : selectedRepoObjects ) {
if ( ro instanceof UIRepositoryObject && ro instanceof ILockObject ) {
final UIRepositoryContent contentToLock = (UIRepositoryContent) ro;
if ( ( (ILockObject) contentToLock ).isLocked() ) {
// Content is locked, not allowed to move
event.setAccepted( false );
messageBox.setTitle( BaseMessages.getString( PKG, "Dialog.Error" ) ); //$NON-NLS-1$
messageBox.setAcceptLabel( BaseMessages.getString( PKG, "Dialog.Ok" ) ); //$NON-NLS-1$
messageBox.setMessage( BaseMessages.getString( PKG, "BrowseController.MoveNotAllowed" ) ); //$NON-NLS-1$
messageBox.open();
break;
} else {
// Content is not locked, check default permissions
browseController.onDragFromLocalTable( event );
}
} else if ( ro instanceof UIRepositoryDirectory
&& repositoryDirectoryHasLockedObject( event, (UIRepositoryDirectory) ro ) ) {
// locked content nested in this directory. move not allowed.
event.setAccepted( false );
break;
}
}
}
} catch ( Exception e ) {
throw new RuntimeException( e );
}
}
private BindingConvertor<List<UIRepositoryObject>, Boolean> checkLockPermissions =
new BindingConvertor<List<UIRepositoryObject>, Boolean>() {
@Override
public Boolean sourceToTarget( List<UIRepositoryObject> selectedRepoObjects ) {
boolean result = false;
try {
if ( selectedRepoObjects.size() == 1 && selectedRepoObjects.get( 0 ) instanceof UIRepositoryDirectory ) {
return true;
} else if ( selectedRepoObjects.size() == 1 && selectedRepoObjects.get( 0 ) instanceof ILockObject ) {
final UIRepositoryContent contentToLock = (UIRepositoryContent) selectedRepoObjects.get( 0 );
if ( ( (ILockObject) contentToLock ).isLocked() ) {
if ( repository instanceof PurRepository
//repository can be Proxy of repository and first part condition will fail
|| repository.getRepositoryMeta() instanceof PurRepositoryMeta ) {
result = service.canUnlockFileById( contentToLock.getObjectId() );
} else {
result =
( (ILockObject) contentToLock ).getRepositoryLock().getLogin().equalsIgnoreCase(
repository.getUserInfo().getLogin() );
}
} else {
// Content is not locked, permit locking
result = true;
}
}
} catch ( Exception e ) {
throw new RuntimeException( e );
}
return result;
}
@Override
public List<UIRepositoryObject> targetToSource( Boolean arg0 ) {
return null;
}
};
private BindingConvertor<List<UIRepositoryObject>, Boolean> forButtons =
new BindingConvertor<List<UIRepositoryObject>, Boolean>() {
@Override
public Boolean sourceToTarget( List<UIRepositoryObject> value ) {
return value != null && value.size() == 1;
}
@Override
public List<UIRepositoryObject> targetToSource( Boolean value ) {
return null;
}
};
public String getName() {
return "repositoryLockController"; //$NON-NLS-1$
}
private BindingConvertor<List<UIRepositoryObject>, Boolean> checkLockedStateBool =
new BindingConvertor<List<UIRepositoryObject>, Boolean>() {
@Override
public Boolean sourceToTarget( List<UIRepositoryObject> value ) {
boolean result = false;
try {
if ( value != null && value.size() == 1 && value.get( 0 ) != null ) {
if ( value.get( 0 ) instanceof ILockObject ) {
result = ( (ILockObject) value.get( 0 ) ).isLocked();
}
}
} catch ( KettleException e ) {
throw new RuntimeException( e );
}
return result;
}
@Override
public List<UIRepositoryObject> targetToSource( Boolean value ) {
return null;
}
};
// This needs to exist until we have better method override support in the DefaultBinding
private BindingConvertor<List<UIRepositoryObject>, Boolean> checkLockedState =
new BindingConvertor<List<UIRepositoryObject>, Boolean>() {
@Override
public Boolean sourceToTarget( List<UIRepositoryObject> value ) {
boolean result = false;
try {
if ( value != null && value.size() == 1 && value.get( 0 ) != null ) {
if ( value.get( 0 ) instanceof ILockObject ) {
result = ( (ILockObject) value.get( 0 ) ).isLocked();
}
}
} catch ( KettleException e ) {
throw new RuntimeException( e );
}
return result;
}
@Override
public List<UIRepositoryObject> targetToSource( Boolean value ) {
return null;
}
};
protected void createBindings() {
// Lock bindings
bindingFactory.setBindingType( Type.ONE_WAY );
bindingFactory.createBinding( browseController, "repositoryObjects", "lock-menu", "!disabled", forButtons ); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
bindingFactory.createBinding( browseController,
"repositoryObjects", "file-context-lock", "selected", checkLockedState ); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
bindingFactory.createBinding( browseController, "repositoryObjects", this, "menuItemEnabledState" ); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
bindingFactory.createBinding( browseController,
"repositoryObjects", "file-context-locknotes", "!disabled", checkLockedStateBool ); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
bindingFactory.createBinding( browseController,
"repositoryObjects", "lock-context-lock", "selected", checkLockedState ); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
bindingFactory.createBinding( browseController,
"repositoryObjects", "lock-context-lock", "!disabled", checkLockPermissions ); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
bindingFactory.createBinding( browseController,
"repositoryObjects", "lock-context-locknotes", "!disabled", checkLockedStateBool ); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
}
public void lockContent() throws Exception {
List<UIRepositoryObject> selectedRepoObjects = browseController.getSelectedFileItems();
if ( selectedRepoObjects.size() > 0 && selectedRepoObjects.get( 0 ) instanceof UIRepositoryContent ) {
final UIRepositoryContent contentToLock = (UIRepositoryContent) selectedRepoObjects.get( 0 );
if ( ( (ILockObject) contentToLock ).isLocked() ) {
// Unlock the item
( (ILockObject) contentToLock ).unlock();
browseController.getSelectedItemsBinding().fireSourceChanged();
} else {
// Lock the item
XulPromptBox lockNotePrompt = promptLockMessage( document, messages, null );
lockNotePrompt.addDialogCallback( new XulDialogCallback<String>() {
public void onClose( XulComponent component, Status status, String value ) {
if ( !status.equals( Status.CANCEL ) ) {
try {
( (ILockObject) contentToLock ).lock( value );
browseController.getSelectedItemsBinding().fireSourceChanged();
} catch ( Exception e ) {
// convert to runtime exception so it bubbles up through the UI
throw new RuntimeException( e );
}
} else {
XulMenuitem lockMenuItem = (XulMenuitem) document.getElementById( "lock-context-lock" ); //$NON-NLS-1$
lockMenuItem.setSelected( false );
lockMenuItem = (XulMenuitem) document.getElementById( "file-context-lock" ); //$NON-NLS-1$
lockMenuItem.setSelected( false );
}
}
public void onError( XulComponent component, Throwable err ) {
throw new RuntimeException( err );
}
} );
lockNotePrompt.open();
}
}
}
public void viewLockNote() throws Exception {
List<UIRepositoryObject> selectedRepoObjects = browseController.getSelectedFileItems();
if ( selectedRepoObjects.size() > 0 && selectedRepoObjects.get( 0 ) instanceof UIRepositoryContent ) {
final UIRepositoryContent contentToLock = (UIRepositoryContent) selectedRepoObjects.get( 0 );
XulMessageBox msgBox = (XulMessageBox) document.createElement( "messagebox" ); //$NON-NLS-1$
msgBox.setTitle( BaseMessages.getString( PKG, "PurRepository.LockNote.Title" ) ); //$NON-NLS-1$
msgBox.setMessage( ( (ILockObject) contentToLock ).getLockMessage() );
msgBox.open();
}
}
private XulPromptBox promptLockMessage( org.pentaho.ui.xul.dom.Document document, ResourceBundle messages,
String defaultMessage ) throws XulException {
XulPromptBox prompt = (XulPromptBox) document.createElement( "promptbox" ); //$NON-NLS-1$
prompt.setTitle( BaseMessages.getString( PKG, "RepositoryExplorer.LockMessage.Title" ) ); //$NON-NLS-1$
prompt.setButtons( new DialogConstant[] { DialogConstant.OK, DialogConstant.CANCEL } );
prompt.setMessage( BaseMessages.getString( PKG, "RepositoryExplorer.LockMessage.Label" ) ); //$NON-NLS-1$
prompt.setValue( defaultMessage == null
? BaseMessages.getString( PKG, "RepositoryExplorer.DefaultLockMessage" ) : defaultMessage ); //$NON-NLS-1$
return prompt;
}
public void setMenuItemEnabledState( List<UIRepositoryObject> selectedRepoObjects ) {
try {
boolean result = false;
if ( selectedRepoObjects.size() == 1 && selectedRepoObjects.get( 0 ) instanceof UIRepositoryDirectory ) {
lockFileMenuItem.setDisabled( true );
deleteFileMenuItem.setDisabled( false );
renameFileMenuItem.setDisabled( false );
} else if ( selectedRepoObjects.size() == 1 && selectedRepoObjects.get( 0 ) instanceof ILockObject ) {
final UIRepositoryContent contentToLock = (UIRepositoryContent) selectedRepoObjects.get( 0 );
if ( ( (ILockObject) contentToLock ).isLocked() ) {
if ( repository instanceof PurRepository
//repository can be Proxy of repository and first part condition will fail
|| repository.getRepositoryMeta() instanceof PurRepositoryMeta ) {
result = service.canUnlockFileById( contentToLock.getObjectId() );
} else {
result =
( (ILockObject) contentToLock ).getRepositoryLock().getLogin().equalsIgnoreCase(
repository.getUserInfo().getLogin() );
}
lockFileMenuItem.setDisabled( !result );
deleteFileMenuItem.setDisabled( !result );
renameFileMenuItem.setDisabled( !result );
} else {
lockFileMenuItem.setDisabled( false );
deleteFileMenuItem.setDisabled( false );
renameFileMenuItem.setDisabled( false );
}
} else {
lockFileMenuItem.setDisabled( true );
deleteFileMenuItem.setDisabled( true );
renameFileMenuItem.setDisabled( true );
}
} catch ( Exception e ) {
throw new RuntimeException( e );
}
}
}