| /* |
| * Copyright (c) 2015, 2016, 2019, 2020 Eike Stepper (Loehne, Germany) and others. |
| * All rights reserved. This program and the accompanying materials |
| * are made available under the terms of the Eclipse Public License v1.0 |
| * which accompanies this distribution, and is available at |
| * http://www.eclipse.org/legal/epl-v10.html |
| * |
| * Contributors: |
| * Eike Stepper - initial API and implementation |
| */ |
| package org.eclipse.emf.cdo.explorer.ui.repositories; |
| |
| import org.eclipse.emf.cdo.eresource.CDOResource; |
| import org.eclipse.emf.cdo.explorer.CDOExplorerUtil; |
| import org.eclipse.emf.cdo.explorer.checkouts.CDOCheckout; |
| import org.eclipse.emf.cdo.explorer.repositories.CDORepository; |
| import org.eclipse.emf.cdo.explorer.repositories.CDORepository.IDGeneration; |
| import org.eclipse.emf.cdo.explorer.repositories.CDORepository.State; |
| import org.eclipse.emf.cdo.explorer.repositories.CDORepository.VersioningMode; |
| import org.eclipse.emf.cdo.explorer.ui.bundle.OM; |
| import org.eclipse.emf.cdo.explorer.ui.checkouts.actions.ShowInActionProvider; |
| import org.eclipse.emf.cdo.explorer.ui.handlers.RepositoryCheckoutHandlerQuick; |
| import org.eclipse.emf.cdo.explorer.ui.repositories.wizards.NewRepositoryWizard; |
| import org.eclipse.emf.cdo.internal.explorer.repositories.CDORepositoryImpl; |
| import org.eclipse.emf.cdo.internal.explorer.repositories.CDORepositoryManagerImpl; |
| import org.eclipse.emf.cdo.internal.explorer.repositories.LocalCDORepository; |
| import org.eclipse.emf.cdo.session.CDOSession; |
| import org.eclipse.emf.cdo.transaction.CDOTransaction; |
| import org.eclipse.emf.cdo.util.CDOUtil; |
| import org.eclipse.emf.cdo.util.CommitException; |
| import org.eclipse.emf.cdo.util.ConcurrentAccessException; |
| |
| import org.eclipse.net4j.util.container.IContainer; |
| import org.eclipse.net4j.util.security.PasswordCredentials; |
| import org.eclipse.net4j.util.ui.UIUtil; |
| import org.eclipse.net4j.util.ui.actions.LongRunningAction; |
| import org.eclipse.net4j.util.ui.views.ContainerItemProvider; |
| import org.eclipse.net4j.util.ui.views.ContainerView; |
| |
| import org.eclipse.emf.common.util.EList; |
| import org.eclipse.emf.ecore.EClass; |
| import org.eclipse.emf.ecore.EObject; |
| import org.eclipse.emf.ecore.EPackage; |
| import org.eclipse.emf.ecore.util.EcoreUtil; |
| |
| import org.eclipse.core.runtime.IProgressMonitor; |
| import org.eclipse.jface.action.Action; |
| import org.eclipse.jface.action.GroupMarker; |
| import org.eclipse.jface.action.IMenuManager; |
| import org.eclipse.jface.action.IToolBarManager; |
| import org.eclipse.jface.action.MenuManager; |
| import org.eclipse.jface.action.Separator; |
| import org.eclipse.jface.dialogs.MessageDialog; |
| import org.eclipse.jface.viewers.ITreeSelection; |
| import org.eclipse.jface.viewers.ITreeViewerListener; |
| import org.eclipse.jface.viewers.TreeExpansionEvent; |
| import org.eclipse.jface.viewers.TreeViewer; |
| import org.eclipse.jface.wizard.WizardDialog; |
| import org.eclipse.swt.events.KeyEvent; |
| import org.eclipse.swt.events.KeyListener; |
| import org.eclipse.swt.events.MouseEvent; |
| import org.eclipse.swt.events.MouseListener; |
| import org.eclipse.swt.widgets.Composite; |
| import org.eclipse.swt.widgets.Control; |
| import org.eclipse.swt.widgets.Shell; |
| import org.eclipse.swt.widgets.Tree; |
| import org.eclipse.ui.IWorkbenchActionConstants; |
| import org.eclipse.ui.IWorkbenchCommandConstants; |
| import org.eclipse.ui.IWorkbenchPage; |
| import org.eclipse.ui.dialogs.PropertyDialogAction; |
| import org.eclipse.ui.navigator.ICommonMenuConstants; |
| |
| import java.util.Properties; |
| |
| /** |
| * @author Eike Stepper |
| */ |
| public class CDORepositoriesView extends ContainerView |
| { |
| public static final String ID = "org.eclipse.emf.cdo.explorer.ui.CDORepositoriesView"; |
| |
| public static final String SHOW_IN_MENU_ID = ID + ".ShowInMenu"; |
| |
| private static final String GROUP_SECURITY = "group.security"; |
| |
| private final ActivityDetector activityDetector = new ActivityDetector(); |
| |
| private CDORepositoryItemProvider itemProvider; |
| |
| private NewRepositoryAction newAction; |
| |
| private PropertyDialogAction propertiesAction; |
| |
| public CDORepositoriesView() |
| { |
| } |
| |
| private static int getRepositoryTimeoutMillis() |
| { |
| return OM.PREF_REPOSITORY_TIMEOUT_MINUTES.getValue() * 60 * 1000; |
| } |
| |
| @Override |
| protected IContainer<?> getContainer() |
| { |
| return CDOExplorerUtil.getRepositoryManager(); |
| } |
| |
| @Override |
| protected ContainerItemProvider<IContainer<Object>> createContainerItemProvider() |
| { |
| itemProvider = new CDORepositoryItemProvider(this); |
| return itemProvider; |
| } |
| |
| @Override |
| protected Control createUI(Composite parent) |
| { |
| newAction = new NewRepositoryAction(); |
| return super.createUI(parent); |
| } |
| |
| @Override |
| protected void initViewer() |
| { |
| super.initViewer(); |
| |
| TreeViewer viewer = getViewer(); |
| viewer.addTreeListener(activityDetector); |
| viewer.setComparator(null); |
| UIUtil.addDragSupport(viewer); |
| |
| Tree tree = viewer.getTree(); |
| tree.addMouseListener(activityDetector); |
| tree.addKeyListener(activityDetector); |
| |
| tree.getDisplay().timerExec(getRepositoryTimeoutMillis(), activityDetector); |
| |
| propertiesAction = new PropertyDialogAction(() -> getShell(), viewer); |
| propertiesAction.setActionDefinitionId(IWorkbenchCommandConstants.FILE_PROPERTIES); |
| } |
| |
| @Override |
| protected void fillLocalPullDown(IMenuManager manager) |
| { |
| // Do nothing. |
| } |
| |
| @Override |
| protected void fillLocalToolBar(IToolBarManager manager) |
| { |
| addCollapseAllAction(manager); |
| |
| if (Boolean.getBoolean("cdo.explorer.testRepo")) |
| { |
| manager.add(new Action("Test") |
| { |
| @Override |
| public void run() |
| { |
| Properties properties = new Properties(); |
| properties.setProperty(LocalCDORepository.PROP_TYPE, CDORepository.TYPE_LOCAL); |
| properties.setProperty(LocalCDORepository.PROP_LABEL, "repo2"); |
| properties.setProperty(LocalCDORepository.PROP_NAME, "repo2"); |
| properties.setProperty(CDORepositoryImpl.PROP_VERSIONING_MODE, VersioningMode.Branching.toString()); |
| properties.setProperty(CDORepositoryImpl.PROP_ID_GENERATION, IDGeneration.Counter.toString()); |
| properties.setProperty(LocalCDORepository.PROP_TCP_DISABLED, "false"); |
| properties.setProperty(LocalCDORepository.PROP_TCP_PORT, "2037"); |
| |
| CDORepository repository = CDOExplorerUtil.getRepositoryManager().addRepository(properties); |
| repository.connect(); |
| |
| CDOSession session = repository.getSession(); |
| CDOTransaction transaction = session.openTransaction(); |
| CDOUtil.configureView(transaction); |
| |
| try |
| { |
| EPackage ePackage = EPackage.Registry.INSTANCE.getEPackage("http://www.eclipse.org/emf/CDO/examples/company/1.0.0"); |
| EClass eClass = (EClass)ePackage.getEClassifier("Company"); |
| |
| EObject company = EcoreUtil.create(eClass); |
| addChild(company, "categories", "Category"); |
| addChild(company, "suppliers", "Supplier"); |
| addChild(company, "customers", "Customer"); |
| addChild(company, "purchaseOrders", "PurchaseOrder"); |
| addChild(company, "salesOrders", "SalesOrder"); |
| |
| CDOResource resource = transaction.createResource("model1"); |
| resource.getContents().add(company); |
| |
| transaction.commit(); |
| |
| RepositoryCheckoutHandlerQuick.checkout(repository, CDOCheckout.TYPE_ONLINE_TRANSACTIONAL); |
| |
| } |
| catch (ConcurrentAccessException ex) |
| { |
| ex.printStackTrace(); |
| } |
| catch (CommitException ex) |
| { |
| ex.printStackTrace(); |
| } |
| finally |
| { |
| transaction.close(); |
| } |
| } |
| |
| private void addChild(EObject company, String featureName, String className) |
| { |
| EClass companyClass = company.eClass(); |
| EObject object = EcoreUtil.create((EClass)companyClass.getEPackage().getEClassifier(className)); |
| |
| @SuppressWarnings("unchecked") |
| EList<EObject> list = (EList<EObject>)company.eGet(companyClass.getEStructuralFeature(featureName)); |
| list.add(object); |
| } |
| }); |
| } |
| |
| manager.add(newAction); |
| } |
| |
| @Override |
| protected void fillContextMenu(IMenuManager manager, ITreeSelection selection) |
| { |
| super.fillContextMenu(manager, selection); |
| |
| manager.add(new Separator("group.new")); |
| manager.add(new GroupMarker("group.new.branch")); |
| manager.add(new Separator()); |
| manager.add(new Separator("group.open")); |
| manager.add(new GroupMarker("group.openWith")); |
| manager.add(new Separator()); |
| manager.add(new Separator("group.checkout")); |
| manager.add(new Separator("group.edit")); |
| manager.add(new Separator("group.port")); |
| manager.add(new Separator("group.build")); |
| manager.add(new Separator(IWorkbenchActionConstants.MB_ADDITIONS)); |
| manager.add(new Separator(GROUP_SECURITY)); |
| manager.add(new Separator("group.close")); |
| manager.add(new Separator("group.properties")); |
| |
| IWorkbenchPage page = getSite().getPage(); |
| Object selectedElement = selection.size() == 1 ? selection.getFirstElement() : null; |
| |
| IMenuManager showInMenu = new MenuManager(ShowInActionProvider.TITLE, SHOW_IN_MENU_ID); |
| showInMenu.add(new GroupMarker(ICommonMenuConstants.GROUP_TOP)); |
| |
| if (ShowInActionProvider.fillMenu(page, null, showInMenu, selectedElement)) |
| { |
| showInMenu.add(new GroupMarker(ICommonMenuConstants.GROUP_ADDITIONS)); |
| manager.appendToGroup(ICommonMenuConstants.GROUP_OPEN, showInMenu); |
| } |
| |
| if (selectedElement instanceof CDORepository) |
| { |
| CDORepository repository = (CDORepository)selectedElement; |
| CDOSession session = repository.getSession(); |
| if (session != null) |
| { |
| manager.appendToGroup(GROUP_SECURITY, new ChangeServerPasswordAction(page, repository)); |
| } |
| } |
| |
| if (propertiesAction.isApplicableForSelection()) |
| { |
| manager.appendToGroup("group.properties", propertiesAction); |
| } |
| } |
| |
| @Override |
| protected void doubleClicked(Object object) |
| { |
| if (object instanceof CDORepository) |
| { |
| final CDORepository repository = (CDORepository)object; |
| if (repository.getState() == State.Disconnected) |
| { |
| connectRepository(repository); |
| return; |
| } |
| } |
| |
| super.doubleClicked(object); |
| } |
| |
| public void connectRepository(CDORepository repository) |
| { |
| itemProvider.connectRepository(repository); |
| } |
| |
| public static void newRepository(Shell shell) |
| { |
| try |
| { |
| WizardDialog dialog = new WizardDialog(shell, new NewRepositoryWizard()); |
| dialog.open(); |
| } |
| catch (RuntimeException ex) |
| { |
| OM.LOG.error(ex); |
| throw ex; |
| } |
| } |
| |
| /** |
| * @author Eike Stepper |
| */ |
| private final class ActivityDetector implements ITreeViewerListener, MouseListener, KeyListener, Runnable |
| { |
| private long lastActivity; |
| |
| public ActivityDetector() |
| { |
| detect(); |
| } |
| |
| @Override |
| public void treeCollapsed(TreeExpansionEvent event) |
| { |
| detect(); |
| } |
| |
| @Override |
| public void treeExpanded(TreeExpansionEvent event) |
| { |
| detect(); |
| } |
| |
| @Override |
| public void mouseDoubleClick(MouseEvent e) |
| { |
| detect(); |
| } |
| |
| @Override |
| public void mouseDown(MouseEvent e) |
| { |
| detect(); |
| } |
| |
| @Override |
| public void mouseUp(MouseEvent e) |
| { |
| detect(); |
| } |
| |
| @Override |
| public void keyPressed(KeyEvent e) |
| { |
| detect(); |
| } |
| |
| @Override |
| public void keyReleased(KeyEvent e) |
| { |
| detect(); |
| } |
| |
| private void detect() |
| { |
| lastActivity = System.currentTimeMillis(); |
| } |
| |
| @Override |
| public void run() |
| { |
| Tree tree = getViewer().getTree(); |
| if (tree.isDisposed()) |
| { |
| return; |
| } |
| |
| long now = System.currentTimeMillis(); |
| int timeout = CDORepositoriesView.getRepositoryTimeoutMillis(); |
| int wait = timeout; |
| |
| if (lastActivity <= now - timeout) |
| { |
| if (!OM.PREF_REPOSITORY_TIMEOUT_DISABLED.getValue()) |
| { |
| CDORepositoryManagerImpl repositoryManager = (CDORepositoryManagerImpl)getContainer(); |
| repositoryManager.disconnectUnusedRepositories(); |
| } |
| } |
| else |
| { |
| // TODO React to changed timeout preference. |
| wait = (int)(timeout - (now - lastActivity)); |
| } |
| |
| tree.getDisplay().timerExec(wait, this); |
| } |
| } |
| |
| /** |
| * @author Eike Stepper |
| */ |
| private final class NewRepositoryAction extends Action |
| { |
| public NewRepositoryAction() |
| { |
| setText("New Repository"); |
| setToolTipText("Add a new repository"); |
| setImageDescriptor(OM.getImageDescriptor("icons/add.gif")); |
| } |
| |
| @Override |
| public void run() |
| { |
| Shell shell = getSite().getShell(); |
| newRepository(shell); |
| } |
| } |
| |
| /** |
| * @author Eike Stepper |
| */ |
| private static final class ChangeServerPasswordAction extends LongRunningAction |
| { |
| private static final String TITLE = "Change Server Password"; |
| |
| private final CDORepository repository; |
| |
| public ChangeServerPasswordAction(IWorkbenchPage page, CDORepository repository) |
| { |
| super(page, TITLE + INTERACTIVE); |
| this.repository = repository; |
| } |
| |
| @Override |
| protected void doRun(IProgressMonitor progressMonitor) throws Exception |
| { |
| CDOSession session = repository.getSession(); |
| if (session != null) |
| { |
| // Opens the org.eclipse.net4j.util.ui.security.CredentialsUpdateDialog. |
| char[] newPassword = session.changeServerPassword(); |
| |
| UIUtil.asyncExec(getDisplay(), () -> { |
| if (MessageDialog.openQuestion(getShell(), TITLE, "Adjust login credentials, accordingly?")) |
| { |
| String userID = repository.getCredentials().getUserID(); |
| repository.setCredentials(new PasswordCredentials(userID, newPassword)); |
| } |
| }); |
| } |
| } |
| } |
| } |