diff options
author | Christian W. Damus | 2013-10-21 21:14:25 +0000 |
---|---|---|
committer | Christian W. Damus | 2013-10-21 21:14:25 +0000 |
commit | 37bc1f362d15f240675e6bfa9ec5b930c81e9fc6 (patch) | |
tree | 0812937ca8702638d13fa4f9387d9872ef24dfdc | |
parent | 1e3c85bc9f9514eb98628b86e9e17ec63a9a9e74 (diff) | |
parent | 022e354b2a93624a8046710a79e1b1c75525d3e2 (diff) | |
download | cdo-37bc1f362d15f240675e6bfa9ec5b930c81e9fc6.tar.gz cdo-37bc1f362d15f240675e6bfa9ec5b930c81e9fc6.tar.xz cdo-37bc1f362d15f240675e6bfa9ec5b930c81e9fc6.zip |
Merge branch 'refs/heads/committers/cdamus/security-editor' into committers/cdamus/passwords
Conflicts:
features/org.eclipse.emf.cdo-feature/feature.xml
plugins/org.eclipse.emf.cdo.security.ui/.project
plugins/org.eclipse.emf.cdo.security.ui/.settings/org.eclipse.jdt.core.prefs
plugins/org.eclipse.emf.cdo.security.ui/.settings/org.eclipse.pde.prefs
plugins/org.eclipse.emf.cdo.security.ui/META-INF/MANIFEST.MF
plugins/org.eclipse.emf.cdo.security.ui/build.properties
plugins/org.eclipse.emf.cdo.security.ui/copyright.txt
plugins/org.eclipse.emf.cdo.security.ui/plugin.properties
plugins/org.eclipse.emf.cdo.security.ui/plugin.xml
plugins/org.eclipse.emf.cdo.ui/src/org/eclipse/emf/cdo/ui/CDOItemProvider.java
46 files changed, 4682 insertions, 60 deletions
diff --git a/features/org.eclipse.emf.cdo-feature/feature.xml b/features/org.eclipse.emf.cdo-feature/feature.xml index 78812d268e..23e95d3e70 100644 --- a/features/org.eclipse.emf.cdo-feature/feature.xml +++ b/features/org.eclipse.emf.cdo-feature/feature.xml @@ -8,7 +8,7 @@ Contributors: Eike Stepper - initial API and implementation - Christian W. Damus (CEA LIST) - 399306 + Christian W. Damus (CEA LIST) - 399306, 418452 --> <feature id="org.eclipse.emf.cdo" @@ -260,4 +260,11 @@ fragment="true" unpack="false"/> + <plugin + id="org.eclipse.emf.cdo.security.ui" + download-size="0" + install-size="0" + version="0.0.0" + unpack="false"/> + </feature> diff --git a/plugins/org.eclipse.emf.cdo.security.ui/.settings/org.eclipse.core.resources.prefs b/plugins/org.eclipse.emf.cdo.security.ui/.settings/org.eclipse.core.resources.prefs new file mode 100644 index 0000000000..484c63108e --- /dev/null +++ b/plugins/org.eclipse.emf.cdo.security.ui/.settings/org.eclipse.core.resources.prefs @@ -0,0 +1,2 @@ +eclipse.preferences.version=1 +encoding//src/org/eclipse/emf/cdo/internal/security/ui/messages/messages.properties=ISO-8859-1 diff --git a/plugins/org.eclipse.emf.cdo.security.ui/.settings/org.eclipse.jdt.core.prefs b/plugins/org.eclipse.emf.cdo.security.ui/.settings/org.eclipse.jdt.core.prefs index 303d2d75e1..04ae31da78 100644 --- a/plugins/org.eclipse.emf.cdo.security.ui/.settings/org.eclipse.jdt.core.prefs +++ b/plugins/org.eclipse.emf.cdo.security.ui/.settings/org.eclipse.jdt.core.prefs @@ -1,27 +1,3 @@ -eclipse.preferences.version=1 -org.eclipse.jdt.core.builder.cleanOutputFolder=clean -org.eclipse.jdt.core.builder.duplicateResourceTask=warning -org.eclipse.jdt.core.builder.invalidClasspath=abort -org.eclipse.jdt.core.builder.recreateModifiedClassFileInOutputFolder=ignore -org.eclipse.jdt.core.builder.resourceCopyExclusionFilter=*.launch,*.ucls,doc-files/,package.html,package-info.java -org.eclipse.jdt.core.circularClasspath=error -org.eclipse.jdt.core.classpath.exclusionPatterns=enabled -org.eclipse.jdt.core.classpath.multipleOutputLocations=enabled -org.eclipse.jdt.core.codeComplete.argumentPrefixes= -org.eclipse.jdt.core.codeComplete.argumentSuffixes= -org.eclipse.jdt.core.codeComplete.fieldPrefixes= -org.eclipse.jdt.core.codeComplete.fieldSuffixes= -org.eclipse.jdt.core.codeComplete.localPrefixes= -org.eclipse.jdt.core.codeComplete.localSuffixes= -org.eclipse.jdt.core.codeComplete.staticFieldPrefixes= -org.eclipse.jdt.core.codeComplete.staticFieldSuffixes= -org.eclipse.jdt.core.codeComplete.staticFinalFieldPrefixes= -org.eclipse.jdt.core.codeComplete.staticFinalFieldSuffixes= -org.eclipse.jdt.core.compiler.annotation.missingNonNullByDefaultAnnotation=ignore -org.eclipse.jdt.core.compiler.annotation.nonnull=org.eclipse.jdt.annotation.NonNull -org.eclipse.jdt.core.compiler.annotation.nonnullbydefault=org.eclipse.jdt.annotation.NonNullByDefault -org.eclipse.jdt.core.compiler.annotation.nullable=org.eclipse.jdt.annotation.Nullable -org.eclipse.jdt.core.compiler.annotation.nullanalysis=disabled org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.5 org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve @@ -42,7 +18,6 @@ org.eclipse.jdt.core.compiler.problem.deprecationWhenOverridingDeprecatedMethod= org.eclipse.jdt.core.compiler.problem.discouragedReference=warning org.eclipse.jdt.core.compiler.problem.emptyStatement=warning org.eclipse.jdt.core.compiler.problem.enumIdentifier=error -org.eclipse.jdt.core.compiler.problem.explicitlyClosedAutoCloseable=ignore org.eclipse.jdt.core.compiler.problem.fallthroughCase=warning org.eclipse.jdt.core.compiler.problem.fatalOptionalError=disabled org.eclipse.jdt.core.compiler.problem.fieldHiding=ignore @@ -61,9 +36,7 @@ org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsNotVisibleRef=disabled org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsVisibility=public org.eclipse.jdt.core.compiler.problem.localVariableHiding=ignore org.eclipse.jdt.core.compiler.problem.methodWithConstructorName=warning -org.eclipse.jdt.core.compiler.problem.missingDefaultCase=ignore org.eclipse.jdt.core.compiler.problem.missingDeprecatedAnnotation=warning -org.eclipse.jdt.core.compiler.problem.missingEnumCaseDespiteDefault=disabled org.eclipse.jdt.core.compiler.problem.missingHashCodeMethod=warning org.eclipse.jdt.core.compiler.problem.missingJavadocComments=ignore org.eclipse.jdt.core.compiler.problem.missingJavadocCommentsOverriding=disabled @@ -79,35 +52,25 @@ org.eclipse.jdt.core.compiler.problem.missingSynchronizedOnInheritedMethod=warni org.eclipse.jdt.core.compiler.problem.noEffectAssignment=warning org.eclipse.jdt.core.compiler.problem.noImplicitStringConversion=warning org.eclipse.jdt.core.compiler.problem.nonExternalizedStringLiteral=ignore -org.eclipse.jdt.core.compiler.problem.nullAnnotationInferenceConflict=error org.eclipse.jdt.core.compiler.problem.nullReference=warning -org.eclipse.jdt.core.compiler.problem.nullSpecViolation=error -org.eclipse.jdt.core.compiler.problem.nullUncheckedConversion=warning org.eclipse.jdt.core.compiler.problem.overridingPackageDefaultMethod=warning org.eclipse.jdt.core.compiler.problem.parameterAssignment=ignore org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment=warning org.eclipse.jdt.core.compiler.problem.potentialNullReference=ignore -org.eclipse.jdt.core.compiler.problem.potentiallyUnclosedCloseable=ignore org.eclipse.jdt.core.compiler.problem.rawTypeReference=warning -org.eclipse.jdt.core.compiler.problem.redundantNullAnnotation=warning org.eclipse.jdt.core.compiler.problem.redundantNullCheck=warning -org.eclipse.jdt.core.compiler.problem.redundantSpecificationOfTypeArguments=ignore org.eclipse.jdt.core.compiler.problem.redundantSuperinterface=warning -org.eclipse.jdt.core.compiler.problem.reportMethodCanBePotentiallyStatic=ignore -org.eclipse.jdt.core.compiler.problem.reportMethodCanBeStatic=ignore org.eclipse.jdt.core.compiler.problem.specialParameterHidingField=disabled org.eclipse.jdt.core.compiler.problem.staticAccessReceiver=warning org.eclipse.jdt.core.compiler.problem.suppressOptionalErrors=disabled org.eclipse.jdt.core.compiler.problem.suppressWarnings=enabled org.eclipse.jdt.core.compiler.problem.syntheticAccessEmulation=ignore org.eclipse.jdt.core.compiler.problem.typeParameterHiding=warning -org.eclipse.jdt.core.compiler.problem.unavoidableGenericTypeProblems=enabled org.eclipse.jdt.core.compiler.problem.uncheckedTypeOperation=warning -org.eclipse.jdt.core.compiler.problem.unclosedCloseable=warning org.eclipse.jdt.core.compiler.problem.undocumentedEmptyBlock=ignore org.eclipse.jdt.core.compiler.problem.unhandledWarningToken=warning -org.eclipse.jdt.core.compiler.problem.unnecessaryElse=ignore -org.eclipse.jdt.core.compiler.problem.unnecessaryTypeCheck=ignore +org.eclipse.jdt.core.compiler.problem.unnecessaryElse=warning +org.eclipse.jdt.core.compiler.problem.unnecessaryTypeCheck=warning org.eclipse.jdt.core.compiler.problem.unqualifiedFieldAccess=ignore org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownException=ignore org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionExemptExceptionAndThrowable=enabled diff --git a/plugins/org.eclipse.emf.cdo.security.ui/.settings/org.eclipse.pde.prefs b/plugins/org.eclipse.emf.cdo.security.ui/.settings/org.eclipse.pde.prefs index fe01bb701d..494f76278b 100644 --- a/plugins/org.eclipse.emf.cdo.security.ui/.settings/org.eclipse.pde.prefs +++ b/plugins/org.eclipse.emf.cdo.security.ui/.settings/org.eclipse.pde.prefs @@ -1,9 +1,10 @@ -#Thu Feb 04 09:44:24 CET 2010 compilers.f.unresolved-features=1 compilers.f.unresolved-plugins=1 compilers.incompatible-environment=1 compilers.p.build=1 compilers.p.build.bin.includes=1 +compilers.p.build.encodings=2 +compilers.p.build.java.compiler=2 compilers.p.build.java.compliance=1 compilers.p.build.missing.output=2 compilers.p.build.output.library=1 @@ -20,7 +21,7 @@ compilers.p.no-required-att=0 compilers.p.not-externalized-att=2 compilers.p.unknown-attribute=1 compilers.p.unknown-class=1 -compilers.p.unknown-element=1 +compilers.p.unknown-element=2 compilers.p.unknown-identifier=1 compilers.p.unknown-resource=1 compilers.p.unresolved-ex-points=0 diff --git a/plugins/org.eclipse.emf.cdo.security.ui/META-INF/MANIFEST.MF b/plugins/org.eclipse.emf.cdo.security.ui/META-INF/MANIFEST.MF index 5183f356ab..4407ca8280 100644 --- a/plugins/org.eclipse.emf.cdo.security.ui/META-INF/MANIFEST.MF +++ b/plugins/org.eclipse.emf.cdo.security.ui/META-INF/MANIFEST.MF @@ -7,9 +7,22 @@ Bundle-Name: %pluginName Bundle-Vendor: %providerName Bundle-ClassPath: . Bundle-RequiredExecutionEnvironment: J2SE-1.5 -Export-Package: org.eclipse.emf.cdo.security.internal.ui.actions;version="1.0.0";x-internal:=true -Require-Bundle: org.eclipse.emf.cdo.security.edit;bundle-version="[4.1.0,5.0.0)", +Bundle-ActivationPolicy: lazy +Require-Bundle: org.eclipse.emf.cdo.security;bundle-version="[4.3.0,5.0.0)", + org.eclipse.emf.cdo.security.edit;bundle-version="[4.3.0,5.0.0)", + org.eclipse.emf.cdo.ui;bundle-version="[4.3.0,5.0.0)", + org.eclipse.emf.cdo.ui.shared;bundle-version="[4.2.0,5.0.0)", org.eclipse.net4j.util.ui;bundle-version="[3.4.0,4.0.0)", + org.eclipse.ui.forms;bundle-version="[3.6.100,4.0.0)", org.eclipse.core.expressions;bundle-version="[3.4.0,4.0.0)";resolution:=optional, - org.eclipse.emf.cdo.ui.shared;bundle-version="[4.0.0,5.0.0)" -Bundle-ActivationPolicy: lazy + org.eclipse.emf.databinding.edit;bundle-version="[1.3.0,2.0.0)", + org.eclipse.jface.databinding;bundle-version="[1.6.200,2.0.0)", + org.eclipse.core.databinding.beans;bundle-version="[1.2.200,2.0.0)" +Export-Package: org.eclipse.emf.cdo.internal.security.ui.actions;version="1.0.0";x-internal:=true, + org.eclipse.emf.cdo.internal.security.ui.bundle;version="1.0.0";x-internal:=true, + org.eclipse.emf.cdo.internal.security.ui.commands;version="1.0.0";x-internal:=true, + org.eclipse.emf.cdo.internal.security.ui.dialogs;version="1.0.0";x-internal:=true, + org.eclipse.emf.cdo.internal.security.ui.editor;version="1.0.0";x-internal:=true, + org.eclipse.emf.cdo.internal.security.ui.messages;version="1.0.0";x-internal:=true, + org.eclipse.emf.cdo.internal.security.ui.util;version="1.0.0";x-internal:=true, + org.eclipse.emf.cdo.security.ui;version="1.0.0" diff --git a/plugins/org.eclipse.emf.cdo.security.ui/build.properties b/plugins/org.eclipse.emf.cdo.security.ui/build.properties index 8fd7da0473..a21ee0c57f 100644 --- a/plugins/org.eclipse.emf.cdo.security.ui/build.properties +++ b/plugins/org.eclipse.emf.cdo.security.ui/build.properties @@ -7,18 +7,22 @@ # Contributors: # Christian W. Damus (CEA LIST) - initial API and implementation -# NLS_MESSAGEFORMAT_VAR - -bin.includes = .,\ - META-INF/,\ - plugin.xml,\ - plugin.properties,\ - about.html,\ - copyright.txt jars.compile.order = . source.. = src/ output.. = bin/ -src.includes = about.html,\ - copyright.txt +bin.includes = META-INF/,\ + .,\ + about.html,\ + plugin.properties,\ + copyright.txt,\ + plugin.xml,\ + icons/ +src.includes = copyright.txt,\ + about.html + +bin.excludes = icons/**/*.pxm + +doc.project = org.eclipse.emf.cdo.doc generateSourceReferences = true + diff --git a/plugins/org.eclipse.emf.cdo.security.ui/icons/full/ctool16/ManageSecurity.png b/plugins/org.eclipse.emf.cdo.security.ui/icons/full/ctool16/ManageSecurity.png Binary files differnew file mode 100644 index 0000000000..c1641fc8bb --- /dev/null +++ b/plugins/org.eclipse.emf.cdo.security.ui/icons/full/ctool16/ManageSecurity.png diff --git a/plugins/org.eclipse.emf.cdo.security.ui/icons/full/elcl16/advanced.gif b/plugins/org.eclipse.emf.cdo.security.ui/icons/full/elcl16/advanced.gif Binary files differnew file mode 100644 index 0000000000..6fe6f0e10a --- /dev/null +++ b/plugins/org.eclipse.emf.cdo.security.ui/icons/full/elcl16/advanced.gif diff --git a/plugins/org.eclipse.emf.cdo.security.ui/icons/full/elcl16/revert.gif b/plugins/org.eclipse.emf.cdo.security.ui/icons/full/elcl16/revert.gif Binary files differnew file mode 100644 index 0000000000..c0648993b8 --- /dev/null +++ b/plugins/org.eclipse.emf.cdo.security.ui/icons/full/elcl16/revert.gif diff --git a/plugins/org.eclipse.emf.cdo.security.ui/icons/full/obj16/SecurityRealmResource.png b/plugins/org.eclipse.emf.cdo.security.ui/icons/full/obj16/SecurityRealmResource.png Binary files differnew file mode 100644 index 0000000000..c1641fc8bb --- /dev/null +++ b/plugins/org.eclipse.emf.cdo.security.ui/icons/full/obj16/SecurityRealmResource.png diff --git a/plugins/org.eclipse.emf.cdo.security.ui/icons/full/obj16/SecurityRealmResource.pxm b/plugins/org.eclipse.emf.cdo.security.ui/icons/full/obj16/SecurityRealmResource.pxm Binary files differnew file mode 100644 index 0000000000..7ce3655569 --- /dev/null +++ b/plugins/org.eclipse.emf.cdo.security.ui/icons/full/obj16/SecurityRealmResource.pxm diff --git a/plugins/org.eclipse.emf.cdo.security.ui/plugin.properties b/plugins/org.eclipse.emf.cdo.security.ui/plugin.properties index dfa691910d..7ccbf8ef6f 100644 --- a/plugins/org.eclipse.emf.cdo.security.ui/plugin.properties +++ b/plugins/org.eclipse.emf.cdo.security.ui/plugin.properties @@ -11,4 +11,8 @@ pluginName = CDO Model Repository Security UI providerName = Eclipse Modeling Project action.label = Reset Password... -action.tooltip = Reset the user's password (must be an administrator)
\ No newline at end of file +action.tooltip = Reset the user's password (must be an administrator) +editor.name = CDO Security Manager +command.label = Manage Security +category.name = CDO Security Management +command.name = Manage Security diff --git a/plugins/org.eclipse.emf.cdo.security.ui/plugin.xml b/plugins/org.eclipse.emf.cdo.security.ui/plugin.xml index ba68f2bc2d..7b217f02bf 100644 --- a/plugins/org.eclipse.emf.cdo.security.ui/plugin.xml +++ b/plugins/org.eclipse.emf.cdo.security.ui/plugin.xml @@ -30,5 +30,55 @@ </enablement> </objectContribution> </extension> + <extension + point="org.eclipse.ui.editors"> + <editor + class="org.eclipse.emf.cdo.internal.security.ui.editor.CDOSecurityFormEditor" + contributorClass="org.eclipse.emf.cdo.internal.security.ui.editor.CDOSecurityFormActionBarContributor" + default="false" + icon="icons/full/obj16/SecurityRealmResource.png" + id="org.eclipse.emf.cdo.security.ui.CDOSecurityFormEditor" + name="%editor.name"> + </editor> + </extension> + <extension + point="org.eclipse.ui.menus"> + <menuContribution + locationURI="popup:org.eclipse.ui.popup.any?after=additions"> + <command + commandId="org.eclipse.emf.cdo.security.ui.openEditor" + icon="$nl$/icons/full/ctool16/ManageSecurity.png" + label="%command.label" + style="push"> + <visibleWhen + checkEnabled="false"> + <with + variable="activeMenuSelection"> + <count + value="1"> + </count> + <iterate > + <adapt + type="org.eclipse.emf.cdo.session.CDOSession"> + </adapt> + </iterate> + </with> + </visibleWhen> + </command> + </menuContribution> + </extension> + <extension + point="org.eclipse.ui.commands"> + <category + id="org.eclipse.emf.cdo.security.ui.management" + name="%category.name"> + </category> + <command + id="org.eclipse.emf.cdo.security.ui.openEditor" + name="%command.name" + categoryId="org.eclipse.emf.cdo.security.ui.management" + defaultHandler="org.eclipse.emf.cdo.internal.security.ui.commands.ManageSecurityHandler"> + </command> + </extension> </plugin> diff --git a/plugins/org.eclipse.emf.cdo.security.ui/src/org/eclipse/emf/cdo/internal/security/ui/actions/SelectionListenerAction.java b/plugins/org.eclipse.emf.cdo.security.ui/src/org/eclipse/emf/cdo/internal/security/ui/actions/SelectionListenerAction.java new file mode 100644 index 0000000000..4e55af9e16 --- /dev/null +++ b/plugins/org.eclipse.emf.cdo.security.ui/src/org/eclipse/emf/cdo/internal/security/ui/actions/SelectionListenerAction.java @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2004-2013 Eike Stepper (Berlin, Germany), CEA LIST, 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: + * Christian W. Damus (CEA LIST) - initial API and implementation + */ +package org.eclipse.emf.cdo.internal.security.ui.actions; + +import org.eclipse.emf.ecore.EObject; + +import org.eclipse.jface.resource.ImageDescriptor; +import org.eclipse.jface.viewers.IStructuredSelection; +import org.eclipse.ui.actions.BaseSelectionListenerAction; + +/** + * + */ +public class SelectionListenerAction extends BaseSelectionListenerAction +{ + + private EObject selectedObject; + + public SelectionListenerAction(String text) + { + super(text); + } + + public SelectionListenerAction(String text, ImageDescriptor imageDescriptor) + { + this(text); + + setImageDescriptor(imageDescriptor); + } + + @Override + protected boolean updateSelection(IStructuredSelection selection) + { + boolean result = !selection.isEmpty(); + + if (result) + { + Object first = selection.getFirstElement(); + result = first instanceof EObject; + if (result) + { + selectedObject = (EObject)first; + } + } + + return super.updateSelection(selection) && result; + } + + protected EObject getSelectedObject() + { + return selectedObject; + } +} diff --git a/plugins/org.eclipse.emf.cdo.security.ui/src/org/eclipse/emf/cdo/internal/security/ui/bundle/OM.java b/plugins/org.eclipse.emf.cdo.security.ui/src/org/eclipse/emf/cdo/internal/security/ui/bundle/OM.java new file mode 100644 index 0000000000..16c8757390 --- /dev/null +++ b/plugins/org.eclipse.emf.cdo.security.ui/src/org/eclipse/emf/cdo/internal/security/ui/bundle/OM.java @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2007-2013 Eike Stepper (Berlin, Germany), CEA LIST, 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 + * Christian W. Damus (CEA LIST) - adapt for new bundle + */ +package org.eclipse.emf.cdo.internal.security.ui.bundle; + +import org.eclipse.net4j.util.om.OMBundle; +import org.eclipse.net4j.util.om.OMPlatform; +import org.eclipse.net4j.util.om.log.OMLogger; +import org.eclipse.net4j.util.om.pref.OMPreferences; +import org.eclipse.net4j.util.om.trace.OMTracer; +import org.eclipse.net4j.util.ui.UIActivator; + +/** + * The <em>Operations & Maintenance</em> class of this bundle. + */ +public abstract class OM +{ + public static final String BUNDLE_ID = "org.eclipse.emf.cdo.security.ui"; //$NON-NLS-1$ + + public static final OMBundle BUNDLE = OMPlatform.INSTANCE.bundle(BUNDLE_ID, OM.class); + + public static final OMTracer DEBUG = BUNDLE.tracer("debug"); //$NON-NLS-1$ + + public static final OMTracer TEST = BUNDLE.tracer("test"); //$NON-NLS-1$ + + public static final OMLogger LOG = BUNDLE.logger(); + + public static final OMPreferences PREFS = BUNDLE.preferences(); + + /** + * The OSGi bundle activator. + */ + public static final class Activator extends UIActivator + { + public static Activator INSTANCE; + + public Activator() + { + super(BUNDLE); + INSTANCE = this; + } + } +} diff --git a/plugins/org.eclipse.emf.cdo.security.ui/src/org/eclipse/emf/cdo/internal/security/ui/commands/ManageSecurityHandler.java b/plugins/org.eclipse.emf.cdo.security.ui/src/org/eclipse/emf/cdo/internal/security/ui/commands/ManageSecurityHandler.java new file mode 100644 index 0000000000..bdf846973d --- /dev/null +++ b/plugins/org.eclipse.emf.cdo.security.ui/src/org/eclipse/emf/cdo/internal/security/ui/commands/ManageSecurityHandler.java @@ -0,0 +1,226 @@ +/* + * Copyright (c) 2004-2013 Eike Stepper (Berlin, Germany), CEA LIST, 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: + * Christian W. Damus (CEA LIST) - initial API and implementation + */ +package org.eclipse.emf.cdo.internal.security.ui.commands; + +import org.eclipse.emf.cdo.eresource.CDOResource; +import org.eclipse.emf.cdo.internal.security.ui.editor.CDOSecurityFormEditor; +import org.eclipse.emf.cdo.internal.security.ui.messages.Messages; +import org.eclipse.emf.cdo.security.ui.ISecurityManagementContext; +import org.eclipse.emf.cdo.session.CDOSession; +import org.eclipse.emf.cdo.ui.CDOEditorInput; +import org.eclipse.emf.cdo.ui.CDOEditorUtil; +import org.eclipse.emf.cdo.view.CDOView; + +import org.eclipse.net4j.util.ui.UIUtil; + +import org.eclipse.core.commands.AbstractHandler; +import org.eclipse.core.commands.ExecutionEvent; +import org.eclipse.core.commands.ExecutionException; +import org.eclipse.jface.dialogs.MessageDialog; +import org.eclipse.jface.viewers.ISelection; +import org.eclipse.ui.IEditorInput; +import org.eclipse.ui.IEditorPart; +import org.eclipse.ui.IEditorReference; +import org.eclipse.ui.IPartListener; +import org.eclipse.ui.IWorkbenchPage; +import org.eclipse.ui.IWorkbenchPart; +import org.eclipse.ui.PartInitException; +import org.eclipse.ui.handlers.HandlerUtil; +import org.eclipse.ui.statushandlers.StatusManager; + +import java.util.Set; + +/** + * + */ +public class ManageSecurityHandler extends AbstractHandler +{ + + public ManageSecurityHandler() + { + } + + public Object execute(ExecutionEvent event) throws ExecutionException + { + ISelection selection = HandlerUtil.getCurrentSelection(event); + CDOSession session = UIUtil.adaptElement(selection, CDOSession.class); + if (session != null && !session.isClosed()) + { + IWorkbenchPart part = HandlerUtil.getActivePart(event); + if (part != null) + { + final IWorkbenchPage page = part.getSite().getPage(); + + IEditorPart existing = findEditor(page, session); + if (existing != null) + { + // activate this editor + page.activate(existing); + } + else + { + // open a new security editor + ISecurityManagementContext context = getContext(event); + CDOView view = context.connect(session); + if (view == null || view.isClosed()) + { + MessageDialog.openWarning(HandlerUtil.getActiveShell(event), Messages.ManageSecurityHandler_0, + Messages.ManageSecurityHandler_1); + } + else + { + try + { + CDOResource resource = context.getSecurityResource(view); + if (resource == null) + { + MessageDialog.openWarning(HandlerUtil.getActiveShell(event), Messages.ManageSecurityHandler_0, + Messages.ManageSecurityHandler_2); + } + else + { + IEditorInput input = CDOEditorUtil.createCDOEditorInput(view, resource.getPath(), false); + + try + { + IEditorPart editor = page.openEditor(input, CDOSecurityFormEditor.ID); + if (editor != null) + { + hookCloseListener(editor, context, view); + view = null; // don't disconnect it until later + } + } + catch (PartInitException e) + { + StatusManager.getManager().handle(e.getStatus(), StatusManager.SHOW); + } + } + } + finally + { + if (view != null) + { + context.disconnect(view); + } + } + } + } + } + } + + return null; + } + + IEditorPart findEditor(IWorkbenchPage page, CDOSession session) + { + IEditorPart result = null; + + for (IEditorReference next : page.getEditorReferences()) + { + if (CDOSecurityFormEditor.ID.equals(next.getId())) + { + IEditorPart candidate = next.getEditor(false); + + if (candidate != null) + { + IEditorInput input = candidate.getEditorInput(); + + if (input instanceof CDOEditorInput) + { + CDOView view = ((CDOEditorInput)input).getView(); + + if (view != null && !view.isClosed() && session.equals(view.getSession())) + { + result = candidate; + break; + } + } + } + } + } + + return result; + } + + ISecurityManagementContext getContext(ExecutionEvent event) + { + ISecurityManagementContext result = null; + + IWorkbenchPart part = HandlerUtil.getActivePart(event); + if (part != null) + { + result = (ISecurityManagementContext)part.getAdapter(ISecurityManagementContext.class); + } + + if (result == null) + { + result = ISecurityManagementContext.DEFAULT; + } + + return result; + } + + private void hookCloseListener(final IEditorPart editor, final ISecurityManagementContext context, final CDOView view) + { + final IWorkbenchPage page = editor.getSite().getPage(); + + page.addPartListener(new IPartListener() + { + + private final IEditorInput input = editor.getEditorInput(); + + private final Set<IEditorPart> openEditors = new java.util.HashSet<IEditorPart>(); + + { + openEditors.add(editor); + } + + public void partClosed(IWorkbenchPart part) + { + openEditors.remove(part); + if (openEditors.isEmpty()) + { + // no more editors using this view + context.disconnect(view); + page.removePartListener(this); + } + } + + public void partOpened(IWorkbenchPart part) + { + if (part instanceof IEditorPart) + { + IEditorPart editor = (IEditorPart)part; + if (input.equals(editor.getEditorInput())) + { + // the user opened the advanced-mode editor from the form editor + openEditors.add(editor); + } + } + } + + public void partDeactivated(IWorkbenchPart part) + { + // pass + } + + public void partBroughtToTop(IWorkbenchPart part) + { + // pass + } + + public void partActivated(IWorkbenchPart part) + { + // pass + } + }); + } +} diff --git a/plugins/org.eclipse.emf.cdo.security.ui/src/org/eclipse/emf/cdo/internal/security/ui/dialogs/FilterTreeSelectionDialog.java b/plugins/org.eclipse.emf.cdo.security.ui/src/org/eclipse/emf/cdo/internal/security/ui/dialogs/FilterTreeSelectionDialog.java new file mode 100644 index 0000000000..8448c5e412 --- /dev/null +++ b/plugins/org.eclipse.emf.cdo.security.ui/src/org/eclipse/emf/cdo/internal/security/ui/dialogs/FilterTreeSelectionDialog.java @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2004-2013 Eike Stepper (Berlin, Germany), CEA LIST, 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: + * Christian W. Damus (CEA LIST) - initial API and implementation + */ +package org.eclipse.emf.cdo.internal.security.ui.dialogs; + +import org.eclipse.jface.viewers.ILabelProvider; +import org.eclipse.jface.viewers.ITreeContentProvider; +import org.eclipse.jface.viewers.TreeViewer; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Shell; +import org.eclipse.ui.dialogs.ElementTreeSelectionDialog; +import org.eclipse.ui.dialogs.FilteredTree; +import org.eclipse.ui.dialogs.PatternFilter; + +/** + * A tree selection dialog that offers the user a filter field. + */ +public class FilterTreeSelectionDialog extends ElementTreeSelectionDialog +{ + + private PatternFilter filter = new PatternFilter(); + + public FilterTreeSelectionDialog(Shell parent, ILabelProvider labelProvider, ITreeContentProvider contentProvider) + { + super(parent, labelProvider, contentProvider); + } + + @Override + protected TreeViewer doCreateTreeViewer(Composite parent, int style) + { + FilteredTree tree = new FilteredTree(parent, style, filter, true); + tree.setLayoutData(new GridData(GridData.FILL_BOTH)); + tree.setQuickSelectionMode(false); + + applyDialogFont(tree); + + return tree.getViewer(); + } + +} diff --git a/plugins/org.eclipse.emf.cdo.security.ui/src/org/eclipse/emf/cdo/internal/security/ui/editor/AbstractDetailsPage.java b/plugins/org.eclipse.emf.cdo.security.ui/src/org/eclipse/emf/cdo/internal/security/ui/editor/AbstractDetailsPage.java new file mode 100644 index 0000000000..e66967026c --- /dev/null +++ b/plugins/org.eclipse.emf.cdo.security.ui/src/org/eclipse/emf/cdo/internal/security/ui/editor/AbstractDetailsPage.java @@ -0,0 +1,383 @@ +/* + * Copyright (c) 2004-2013 Eike Stepper (Berlin, Germany), CEA LIST, 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: + * Christian W. Damus (CEA LIST) - initial API and implementation + */ +package org.eclipse.emf.cdo.internal.security.ui.editor; + +import org.eclipse.emf.cdo.internal.security.ui.bundle.OM; +import org.eclipse.emf.cdo.internal.security.ui.messages.Messages; +import org.eclipse.emf.cdo.internal.security.ui.util.ObjectExistsConverter; +import org.eclipse.emf.cdo.internal.security.ui.util.OneToManyBlock; +import org.eclipse.emf.cdo.internal.security.ui.util.OneToManyTableBlock; +import org.eclipse.emf.cdo.security.provider.SecurityEditPlugin; + +import org.eclipse.emf.common.command.Command; +import org.eclipse.emf.common.notify.AdapterFactory; +import org.eclipse.emf.common.util.URI; +import org.eclipse.emf.databinding.edit.EMFEditObservables; +import org.eclipse.emf.ecore.EAttribute; +import org.eclipse.emf.ecore.EClass; +import org.eclipse.emf.ecore.EObject; +import org.eclipse.emf.ecore.EReference; +import org.eclipse.emf.ecore.EStructuralFeature; +import org.eclipse.emf.edit.command.SetCommand; +import org.eclipse.emf.edit.domain.EditingDomain; +import org.eclipse.emf.edit.ui.provider.AdapterFactoryLabelProvider; +import org.eclipse.emf.edit.ui.provider.ExtendedImageRegistry; + +import org.eclipse.jface.databinding.swt.SWTObservables; +import org.eclipse.jface.databinding.viewers.ViewersObservables; +import org.eclipse.jface.fieldassist.ControlDecoration; +import org.eclipse.jface.viewers.ArrayContentProvider; +import org.eclipse.jface.viewers.ComboViewer; +import org.eclipse.jface.viewers.IFilter; +import org.eclipse.osgi.util.NLS; +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.MouseEvent; +import org.eclipse.swt.events.MouseTrackAdapter; +import org.eclipse.swt.events.MouseTrackListener; +import org.eclipse.swt.events.SelectionAdapter; +import org.eclipse.swt.events.SelectionEvent; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Button; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; +import org.eclipse.swt.widgets.Text; +import org.eclipse.ui.forms.IDetailsPage; +import org.eclipse.ui.forms.widgets.FormToolkit; +import org.eclipse.ui.forms.widgets.TableWrapData; + +/** + * + */ +public abstract class AbstractDetailsPage<T extends EObject> extends AbstractSectionPart<T> implements IDetailsPage +{ + + public AbstractDetailsPage(Class<T> elementType, EClass elementEClass, EditingDomain domain, + AdapterFactory adapterFactory) + { + super(elementType, elementEClass, domain, adapterFactory); + } + + @Override + protected String getTitle() + { + return NLS.bind(Messages.AbstractDetailsPage_0, + SecurityEditPlugin.INSTANCE.getString(String.format("_UI_%s_type", getInputEClass().getName()))); //$NON-NLS-1$ + } + + @Override + public void createContents(Composite parent) + { + GridLayout layout = new GridLayout(); + parent.setLayout(layout); + + super.createContents(parent); + } + + @Override + protected void createContents(Composite parent, FormToolkit toolkit) + { + GridLayout layout = new GridLayout(); + layout.numColumns = 2; + parent.setLayout(layout); + } + + protected void execute(Command command) + { + if (command.canExecute()) + { + getEditingDomain().getCommandStack().execute(command); + } + } + + protected Text text(Composite parent, FormToolkit toolkit, String label, EAttribute attribute) + { + toolkit.createLabel(parent, label); + Text result = toolkit.createText( + createDecorationComposite(parent, toolkit, layoutData(parent, SWT.FILL, false, 1)), ""); //$NON-NLS-1$ + getContext().bindValue(observeText(result), + EMFEditObservables.observeDetailValue(getRealm(), getEditingDomain(), getValue(), attribute)); + getContext().bindValue(SWTObservables.observeEnabled(result), getValue(), null, + ObjectExistsConverter.createUpdateValueStrategy()); + + addRevertDecoration(result, attribute); + + return result; + } + + private static GridData horzAlign(GridData gridData, int align, boolean grab, int span) + { + gridData.horizontalAlignment = align; + gridData.grabExcessHorizontalSpace = grab; + gridData.horizontalSpan = span; + return gridData; + } + + private static GridData vertAlign(GridData gridData, int align, boolean grab, int span) + { + gridData.verticalAlignment = align; + gridData.grabExcessVerticalSpace = grab; + gridData.verticalSpan = span; + return gridData; + } + + private static TableWrapData horzAlign(TableWrapData tableData, int align, boolean grab, int span) + { + int tableWrapAlign = 0; + switch (align) + { + case SWT.LEFT: + tableWrapAlign = TableWrapData.LEFT; + break; + case SWT.CENTER: + tableWrapAlign = TableWrapData.CENTER; + break; + case SWT.RIGHT: + tableWrapAlign = TableWrapData.RIGHT; + break; + case SWT.FILL: + tableWrapAlign = TableWrapData.FILL; + break; + } + + tableData.align = tableWrapAlign; + tableData.grabHorizontal = grab; + tableData.colspan = span; + return tableData; + } + + private static TableWrapData vertAlign(TableWrapData tableData, int align, boolean grab, int span) + { + int tableWrapAlign = 0; + switch (align) + { + case SWT.TOP: + tableWrapAlign = TableWrapData.TOP; + break; + case SWT.CENTER: + tableWrapAlign = TableWrapData.MIDDLE; + break; + case SWT.BOTTOM: + tableWrapAlign = TableWrapData.BOTTOM; + break; + case SWT.FILL: + tableWrapAlign = TableWrapData.FILL; + break; + } + + tableData.valign = tableWrapAlign; + tableData.grabVertical = grab; + tableData.rowspan = span; + return tableData; + } + + protected static Object layoutData(Composite parent, int horzAlign, boolean horzGrab, int horzSpan) + { + Object result; + + if (parent.getLayout() instanceof GridLayout) + { + result = horzAlign(new GridData(), horzAlign, horzGrab, horzSpan); + } + else + { + result = horzAlign(new TableWrapData(), horzAlign, horzGrab, horzSpan); + } + + return result; + } + + protected static Object layoutData(Composite parent, int horzAlign, boolean horzGrab, int horzSpan, int vertAlign, + boolean vertGrab, int vertSpan) + { + Object result; + + if (parent.getLayout() instanceof GridLayout) + { + result = vertAlign(horzAlign(new GridData(), horzAlign, horzGrab, horzSpan), vertAlign, vertGrab, vertSpan); + } + else + { + result = vertAlign(horzAlign(new TableWrapData(), horzAlign, horzGrab, horzSpan), vertAlign, vertGrab, vertSpan); + } + + return result; + } + + protected static <T> T heightHint(T layoutData, int hint) + { + if (layoutData instanceof GridData) + { + ((GridData)layoutData).heightHint = hint; + } + else + { + ((TableWrapData)layoutData).heightHint = hint; + } + + return layoutData; + } + + protected Control space(Composite parent, FormToolkit toolkit) + { + Control result = toolkit.createComposite(parent); + result.setLayoutData(heightHint(layoutData(parent, SWT.FILL, false, 2), 15)); + return result; + } + + protected OneToManyBlock oneToMany(Composite parent, FormToolkit toolkit, String label, EReference reference) + { + return oneToMany(parent, toolkit, label, reference, reference.getEReferenceType()); + } + + protected OneToManyBlock oneToMany(Composite parent, FormToolkit toolkit, String label, EReference reference, + EClass itemType) + { + return oneToMany(parent, toolkit, label, reference, itemType, null); + } + + protected OneToManyBlock oneToMany(Composite parent, FormToolkit toolkit, String label, EReference reference, + EClass itemType, IFilter itemFilter) + { + toolkit.createLabel(parent, label).setLayoutData(layoutData(parent, SWT.LEFT, false, 2)); + Composite blockParent = toolkit.createComposite(parent); + blockParent.setLayoutData(layoutData(parent, SWT.FILL, true, 2, SWT.FILL, true, 1)); + + OneToManyBlock result = new OneToManyBlock(getContext(), getEditingDomain(), getAdapterFactory(), + new OneToManyBlock.OneToManyConfiguration(reference, itemType, itemFilter)); + + result.setEditorActionBars(getEditorActionBars()); + result.setInput(getValue()); + result.createControl(blockParent, toolkit); + return result; + } + + protected OneToManyTableBlock table(Composite parent, FormToolkit toolkit, String label, + OneToManyTableBlock.ITableConfiguration config) + { + toolkit.createLabel(parent, label).setLayoutData(layoutData(parent, SWT.LEFT, false, 2)); + Composite blockParent = toolkit.createComposite(parent); + blockParent.setLayoutData(layoutData(parent, SWT.FILL, true, 2, SWT.FILL, true, 1)); + + OneToManyTableBlock result = new OneToManyTableBlock(getContext(), getEditingDomain(), getAdapterFactory(), config); + + result.setEditorActionBars(getEditorActionBars()); + result.setInput(getValue()); + result.createControl(blockParent, toolkit); + return result; + } + + protected Button checkbox(Composite parent, FormToolkit toolkit, String label, EAttribute attribute) + { + Button result = toolkit.createButton( + createDecorationComposite(parent, toolkit, layoutData(parent, SWT.LEFT, false, 2)), label, SWT.CHECK); + getContext().bindValue(SWTObservables.observeSelection(result), + EMFEditObservables.observeDetailValue(getRealm(), getEditingDomain(), getValue(), attribute)); + getContext().bindValue(SWTObservables.observeEnabled(result), getValue(), null, + ObjectExistsConverter.createUpdateValueStrategy()); + + addRevertDecoration(result, attribute); + + return result; + } + + protected ComboViewer combo(Composite parent, FormToolkit toolkit, String label, EAttribute attribute) + { + toolkit.createLabel(parent, label); + ComboViewer result = new ComboViewer(createDecorationComposite(parent, toolkit, + layoutData(parent, SWT.LEFT, false, 1)), SWT.READ_ONLY | SWT.DROP_DOWN); + result.setLabelProvider(new AdapterFactoryLabelProvider(getAdapterFactory())); + result.setContentProvider(new ArrayContentProvider()); + result.setInput(attribute.getEAttributeType().getInstanceClass().getEnumConstants()); + + getContext().bindValue(ViewersObservables.observeSingleSelection(result), + EMFEditObservables.observeDetailValue(getRealm(), getEditingDomain(), getValue(), attribute)); + getContext().bindValue(SWTObservables.observeEnabled(result.getControl()), getValue(), null, + ObjectExistsConverter.createUpdateValueStrategy()); + + addRevertDecoration(result.getControl(), attribute); + + return result; + } + + protected Composite createDecorationComposite(Composite parent, FormToolkit toolkit, Object layoutData) + { + Composite result = toolkit.createComposite(parent); + result.setLayoutData(layoutData); + + GridLayout layout = new GridLayout(); + layout.marginHeight = 0; + layout.marginWidth = 0; + layout.marginRight = 18; // 16 for image and 2 for offset + result.setLayout(layout); + + return result; + } + + protected void addRevertDecoration(final Control control, final EStructuralFeature feature) + { + final ControlDecoration decoration = new ControlDecoration(control, SWT.RIGHT | SWT.CENTER); + decoration.hide(); + decoration.setDescriptionText(Messages.AbstractDetailsPage_3); + decoration.setImage(ExtendedImageRegistry.getInstance().getImage( + URI.createPlatformPluginURI(OM.BUNDLE_ID + "/icons/full/elcl16/revert.gif", true))); //$NON-NLS-1$ + decoration.setMarginWidth(2); + + decoration.addSelectionListener(new SelectionAdapter() + { + @Override + public void widgetSelected(SelectionEvent e) + { + Command command = SetCommand.create(getEditingDomain(), getInput(), feature, SetCommand.UNSET_VALUE); + if (command.canExecute()) + { + getEditingDomain().getCommandStack().execute(command); + } + } + }); + + control.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, false)); + + // show the decoration when the user hovers over the control and auto-hide after leaving the control + MouseTrackListener showHideListener = new MouseTrackAdapter() + { + private Runnable hideRunnable; + + @Override + public void mouseHover(MouseEvent e) + { + hideRunnable = null; + decoration.show(); + } + + @Override + public void mouseExit(MouseEvent e) + { + hideRunnable = new Runnable() + { + + public void run() + { + if (hideRunnable == this) + { + hideRunnable = null; + decoration.hide(); + } + } + }; + control.getDisplay().timerExec(1000, hideRunnable); + } + }; + control.addMouseTrackListener(showHideListener); + control.getParent().addMouseTrackListener(showHideListener); + } + +} diff --git a/plugins/org.eclipse.emf.cdo.security.ui/src/org/eclipse/emf/cdo/internal/security/ui/editor/AbstractSectionPart.java b/plugins/org.eclipse.emf.cdo.security.ui/src/org/eclipse/emf/cdo/internal/security/ui/editor/AbstractSectionPart.java new file mode 100644 index 0000000000..cc949ae0ea --- /dev/null +++ b/plugins/org.eclipse.emf.cdo.security.ui/src/org/eclipse/emf/cdo/internal/security/ui/editor/AbstractSectionPart.java @@ -0,0 +1,213 @@ +/* + * Copyright (c) 2004-2013 Eike Stepper (Berlin, Germany), CEA LIST, 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: + * Christian W. Damus (CEA LIST) - initial API and implementation + */ +package org.eclipse.emf.cdo.internal.security.ui.editor; + +import org.eclipse.emf.common.notify.AdapterFactory; +import org.eclipse.emf.databinding.EMFDataBindingContext; +import org.eclipse.emf.ecore.EClass; +import org.eclipse.emf.ecore.EObject; +import org.eclipse.emf.edit.domain.EditingDomain; + +import org.eclipse.core.databinding.DataBindingContext; +import org.eclipse.core.databinding.observable.Realm; +import org.eclipse.core.databinding.observable.value.IObservableValue; +import org.eclipse.core.databinding.observable.value.WritableValue; +import org.eclipse.jface.databinding.swt.ISWTObservableValue; +import org.eclipse.jface.databinding.swt.SWTObservables; +import org.eclipse.jface.viewers.ISelection; +import org.eclipse.jface.viewers.IStructuredSelection; +import org.eclipse.swt.SWT; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Text; +import org.eclipse.ui.IActionBars; +import org.eclipse.ui.forms.AbstractFormPart; +import org.eclipse.ui.forms.IFormPart; +import org.eclipse.ui.forms.IManagedForm; +import org.eclipse.ui.forms.widgets.FormToolkit; +import org.eclipse.ui.forms.widgets.Section; +import org.eclipse.ui.forms.widgets.TableWrapData; +import org.eclipse.ui.forms.widgets.TableWrapLayout; + +/** + * + */ +public abstract class AbstractSectionPart<T extends EObject> extends AbstractFormPart +{ + + private final EditingDomain domain; + + private final AdapterFactory adapterFactory; + + private final Class<T> inputType; + + private final EClass inputEClass; + + private T input; + + private DataBindingContext context; + + private WritableValue value; + + private IActionBars editorActionBars; + + public AbstractSectionPart(Class<T> inputType, EClass inputEClass, EditingDomain domain, AdapterFactory adapterFactory) + { + this.inputType = inputType; + this.inputEClass = inputEClass; + this.domain = domain; + this.adapterFactory = adapterFactory; + } + + @Override + public void initialize(IManagedForm form) + { + super.initialize(form); + + initDatabindings(); + } + + public void setEditorActionBars(IActionBars actionBars) + { + this.editorActionBars = actionBars; + } + + protected IActionBars getEditorActionBars() + { + return editorActionBars; + } + + protected void initDatabindings() + { + context = new EMFDataBindingContext(); + value = new WritableValue(context.getValidationRealm()); + } + + @Override + public void dispose() + { + if (context != null) + { + context.dispose(); + } + + super.dispose(); + } + + @Override + public boolean setFormInput(Object input) + { + boolean result = false; + + this.input = null; + + if (inputType.isInstance(input)) + { + this.input = inputType.cast(input); + result = true; + } + + value.setValue(this.input); + + return result; + } + + public void selectionChanged(IFormPart part, ISelection selection) + { + if (selection instanceof IStructuredSelection) + { + IStructuredSelection sel = (IStructuredSelection)selection; + if (!sel.isEmpty()) + { + setFormInput(sel.getFirstElement()); + } + } + } + + public final Class<T> getInputType() + { + return inputType; + } + + public final EClass getInputEClass() + { + return inputEClass; + } + + protected T getInput() + { + return input; + } + + protected EditingDomain getEditingDomain() + { + return domain; + } + + protected AdapterFactory getAdapterFactory() + { + return adapterFactory; + } + + protected Realm getRealm() + { + return getContext().getValidationRealm(); + } + + protected DataBindingContext getContext() + { + return context; + } + + protected IObservableValue getValue() + { + return value; + } + + protected ISWTObservableValue observeText(Text text) + { + return SWTObservables.observeText(text, new int[] { SWT.DefaultSelection, SWT.FocusOut }); + } + + public void createContents(Composite parent) + { + FormToolkit toolkit = getManagedForm().getToolkit(); + + Section section = toolkit.createSection(parent, Section.SHORT_TITLE_BAR); + section.setText(getTitle()); + + if (parent.getLayout() instanceof TableWrapLayout) + { + section.setLayoutData(new TableWrapData(TableWrapData.FILL_GRAB, TableWrapData.FILL_GRAB)); + } + else if (parent.getLayout() instanceof GridLayout) + { + section.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); + } + + Composite body = toolkit.createComposite(section); + section.setClient(body); + + createContents(body, toolkit); + + createActionToolbar(section, toolkit); + } + + protected abstract String getTitle(); + + protected abstract void createContents(Composite parent, FormToolkit toolkit); + + protected void createActionToolbar(Section section, FormToolkit toolkit) + { + // pass + } +} diff --git a/plugins/org.eclipse.emf.cdo.security.ui/src/org/eclipse/emf/cdo/internal/security/ui/editor/CDOSecurityFormActionBarContributor.java b/plugins/org.eclipse.emf.cdo.security.ui/src/org/eclipse/emf/cdo/internal/security/ui/editor/CDOSecurityFormActionBarContributor.java new file mode 100644 index 0000000000..aaac81ebfb --- /dev/null +++ b/plugins/org.eclipse.emf.cdo.security.ui/src/org/eclipse/emf/cdo/internal/security/ui/editor/CDOSecurityFormActionBarContributor.java @@ -0,0 +1,120 @@ +/* + * Copyright (c) 2004-2013 Eike Stepper (Berlin, Germany), CEA LIST, 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: + * Christian W. Damus (CEA LIST) - initial API and implementation + */ +package org.eclipse.emf.cdo.internal.security.ui.editor; + +import org.eclipse.emf.edit.domain.IEditingDomainProvider; +import org.eclipse.emf.edit.ui.action.RedoAction; +import org.eclipse.emf.edit.ui.action.UndoAction; + +import org.eclipse.ui.IActionBars; +import org.eclipse.ui.IEditorPart; +import org.eclipse.ui.IPropertyListener; +import org.eclipse.ui.ISharedImages; +import org.eclipse.ui.PlatformUI; +import org.eclipse.ui.actions.ActionFactory; +import org.eclipse.ui.part.EditorActionBarContributor; + +/** + * + */ +public class CDOSecurityFormActionBarContributor extends EditorActionBarContributor implements IPropertyListener +{ + private IEditorPart activeEditor; + + private UndoAction undoAction; + + private RedoAction redoAction; + + public CDOSecurityFormActionBarContributor() + { + } + + @Override + public void init(IActionBars actionBars) + { + super.init(actionBars); + + ISharedImages sharedImages = PlatformUI.getWorkbench().getSharedImages(); + + undoAction = new UndoAction(); + undoAction.setImageDescriptor(sharedImages.getImageDescriptor(ISharedImages.IMG_TOOL_UNDO)); + actionBars.setGlobalActionHandler(ActionFactory.UNDO.getId(), undoAction); + + redoAction = new RedoAction(); + redoAction.setImageDescriptor(sharedImages.getImageDescriptor(ISharedImages.IMG_TOOL_REDO)); + actionBars.setGlobalActionHandler(ActionFactory.REDO.getId(), redoAction); + } + + @Override + public void setActiveEditor(IEditorPart targetEditor) + { + if (activeEditor != null) + { + deactivate(); + } + + activeEditor = targetEditor; + + if (activeEditor instanceof IEditingDomainProvider) + { + activate(); + } + } + + protected void activate() + { + activeEditor.addPropertyListener(this); + + if (undoAction != null) + { + undoAction.setActiveWorkbenchPart(activeEditor); + } + if (redoAction != null) + { + redoAction.setActiveWorkbenchPart(activeEditor); + } + + update(); + } + + protected void deactivate() + { + activeEditor.removePropertyListener(this); + + if (undoAction != null) + { + undoAction.setActiveWorkbenchPart(null); + } + if (redoAction != null) + { + redoAction.setActiveWorkbenchPart(null); + } + + update(); + } + + protected void update() + { + if (undoAction != null) + { + undoAction.update(); + } + if (redoAction != null) + { + redoAction.update(); + } + } + + public void propertyChanged(Object source, int propId) + { + update(); + } +} diff --git a/plugins/org.eclipse.emf.cdo.security.ui/src/org/eclipse/emf/cdo/internal/security/ui/editor/CDOSecurityFormEditor.java b/plugins/org.eclipse.emf.cdo.security.ui/src/org/eclipse/emf/cdo/internal/security/ui/editor/CDOSecurityFormEditor.java new file mode 100644 index 0000000000..3c5a8a0de9 --- /dev/null +++ b/plugins/org.eclipse.emf.cdo.security.ui/src/org/eclipse/emf/cdo/internal/security/ui/editor/CDOSecurityFormEditor.java @@ -0,0 +1,245 @@ +/* + * Copyright (c) 2004-2013 Eike Stepper (Berlin, Germany), CEA LIST, 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: + * Christian W. Damus (CEA LIST) - initial API and implementation + */ +package org.eclipse.emf.cdo.internal.security.ui.editor; + +import org.eclipse.emf.cdo.eresource.CDOResource; +import org.eclipse.emf.cdo.internal.security.ui.bundle.OM; +import org.eclipse.emf.cdo.internal.security.ui.messages.Messages; +import org.eclipse.emf.cdo.security.provider.SecurityItemProviderAdapterFactory; +import org.eclipse.emf.cdo.transaction.CDOTransaction; +import org.eclipse.emf.cdo.ui.CDOEditorInput; +import org.eclipse.emf.cdo.util.CommitException; +import org.eclipse.emf.cdo.view.CDOView; + +import org.eclipse.emf.common.command.BasicCommandStack; +import org.eclipse.emf.common.command.CommandStack; +import org.eclipse.emf.common.command.CommandStackListener; +import org.eclipse.emf.common.notify.AdapterFactory; +import org.eclipse.emf.ecore.resource.ResourceSet; +import org.eclipse.emf.edit.EMFEditPlugin; +import org.eclipse.emf.edit.domain.AdapterFactoryEditingDomain; +import org.eclipse.emf.edit.domain.EditingDomain; +import org.eclipse.emf.edit.domain.IEditingDomainProvider; +import org.eclipse.emf.edit.provider.ComposedAdapterFactory; +import org.eclipse.emf.edit.provider.ReflectiveItemProviderAdapterFactory; +import org.eclipse.emf.edit.provider.resource.ResourceItemProviderAdapterFactory; + +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Status; +import org.eclipse.swt.widgets.Display; +import org.eclipse.ui.IActionBars; +import org.eclipse.ui.IEditorInput; +import org.eclipse.ui.IEditorPart; +import org.eclipse.ui.IEditorSite; +import org.eclipse.ui.PartInitException; +import org.eclipse.ui.forms.editor.FormEditor; +import org.eclipse.ui.forms.editor.IFormPage; +import org.eclipse.ui.statushandlers.IStatusAdapterConstants; +import org.eclipse.ui.statushandlers.StatusAdapter; +import org.eclipse.ui.statushandlers.StatusManager; + +import java.util.EventObject; + +/** + * + */ +public class CDOSecurityFormEditor extends FormEditor implements IEditingDomainProvider +{ + + public static final String ID = "org.eclipse.emf.cdo.security.ui.CDOSecurityFormEditor"; //$NON-NLS-1$ + + private ComposedAdapterFactory adapterFactory; + + private CDOView view; + + private EditingDomain editingDomain; + + private CDOSecurityPage mainPage; + + public CDOSecurityFormEditor() + { + } + + @Override + protected void addPages() + { + try + { + mainPage = new CDOSecurityPage(this); + addPage(mainPage); + } + catch (PartInitException e) + { + OM.LOG.error(e); + } + } + + @Override + public boolean isDirty() + { + return view != null && view.isDirty(); + } + + @Override + public void doSave(IProgressMonitor monitor) + { + if (view instanceof CDOTransaction) + { + try + { + ((CDOTransaction)view).commit(monitor); + fireDirtyStateChanged(); + } + catch (CommitException e) + { + StatusAdapter status = new StatusAdapter(new Status(IStatus.ERROR, OM.BUNDLE_ID, + Messages.CDOSecurityFormEditor_0, e)); + status.setProperty(IStatusAdapterConstants.TITLE_PROPERTY, Messages.CDOSecurityFormEditor_1); + status.setProperty(IStatusAdapterConstants.TIMESTAMP_PROPERTY, System.currentTimeMillis()); + StatusManager.getManager().handle(status, StatusManager.SHOW); + } + } + } + + protected void fireDirtyStateChanged() + { + Display display = getContainer().getDisplay(); + if (display == Display.getCurrent()) + { + firePropertyChange(IEditorPart.PROP_DIRTY); + } + else + { + display.asyncExec(new Runnable() + { + public void run() + { + fireDirtyStateChanged(); + } + }); + } + } + + @Override + public void doSaveAs() + { + } + + @Override + public boolean isSaveAsAllowed() + { + // cannot create new security realms using Save As + return false; + } + + boolean isReadOnly() + { + return view == null || view.isReadOnly(); + } + + @Override + public void init(IEditorSite site, IEditorInput input) throws PartInitException + { + super.init(site, input); + + initializeEditingDomain(); + } + + protected void initializeEditingDomain() + { + try + { + CDOResource resource = getResource(); + view = resource.cdoView(); + + BasicCommandStack commandStack = new BasicCommandStack(); + commandStack.addCommandStackListener(new CommandStackListener() + { + public void commandStackChanged(final EventObject event) + { + fireDirtyStateChanged(); + } + }); + + ResourceSet resourceSet = view.getResourceSet(); + editingDomain = createEditingDomain(commandStack, resourceSet); + + // This adapter provides the EditingDomain of the Editor + resourceSet.eAdapters().add(new AdapterFactoryEditingDomain.EditingDomainProvider(editingDomain)); + } + catch (RuntimeException ex) + { + OM.LOG.error(ex); + throw ex; + } + } + + protected EditingDomain createEditingDomain(CommandStack commandStack, ResourceSet resourceSet) + { + ComposedAdapterFactory.Descriptor.Registry registry = EMFEditPlugin.getComposedAdapterFactoryDescriptorRegistry(); + adapterFactory = new ComposedAdapterFactory(registry); + adapterFactory.addAdapterFactory(new SecurityItemProviderAdapterFactory()); + adapterFactory.addAdapterFactory(new ResourceItemProviderAdapterFactory()); + adapterFactory.addAdapterFactory(new ReflectiveItemProviderAdapterFactory()); + + return new AdapterFactoryEditingDomain(adapterFactory, commandStack, resourceSet); + } + + protected CDOResource getResource() + { + CDOResource result = null; + + IEditorInput input = getEditorInput(); + + if (input instanceof CDOEditorInput) + { + CDOEditorInput cdoInput = (CDOEditorInput)input; + result = cdoInput.getView().getResource(cdoInput.getResourcePath()); + } + + return result; + } + + protected CDOView getView() + { + return view; + } + + protected AdapterFactory getAdapterFactory() + { + return adapterFactory; + } + + public EditingDomain getEditingDomain() + { + return editingDomain; + } + + public IActionBars getActionBars() + { + return ((CDOSecurityFormActionBarContributor)getEditorSite().getActionBarContributor()).getActionBars(); + } + + @Override + public void setFocus() + { + super.setFocus(); + + IFormPage page = getActivePageInstance(); + if (page != null && page instanceof CDOSecurityPage) + { + // ensure that the first focusable part is focused so that the page's toolbar will not be focused (which shows + // ugly blue highlights on the toolbar buttons) + page.setFocus(); + } + } +} diff --git a/plugins/org.eclipse.emf.cdo.security.ui/src/org/eclipse/emf/cdo/internal/security/ui/editor/CDOSecurityPage.java b/plugins/org.eclipse.emf.cdo.security.ui/src/org/eclipse/emf/cdo/internal/security/ui/editor/CDOSecurityPage.java new file mode 100644 index 0000000000..59084ec738 --- /dev/null +++ b/plugins/org.eclipse.emf.cdo.security.ui/src/org/eclipse/emf/cdo/internal/security/ui/editor/CDOSecurityPage.java @@ -0,0 +1,362 @@ +/* + * Copyright (c) 2004-2013 Eike Stepper (Berlin, Germany), CEA LIST, 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: + * Christian W. Damus (CEA LIST) - initial API and implementation + */ +package org.eclipse.emf.cdo.internal.security.ui.editor; + +import org.eclipse.emf.cdo.CDOObject; +import org.eclipse.emf.cdo.common.id.CDOID; +import org.eclipse.emf.cdo.eresource.CDOResource; +import org.eclipse.emf.cdo.internal.security.ui.bundle.OM; +import org.eclipse.emf.cdo.internal.security.ui.messages.Messages; +import org.eclipse.emf.cdo.security.Realm; +import org.eclipse.emf.cdo.security.SecurityPackage; +import org.eclipse.emf.cdo.ui.CDOEditorUtil; +import org.eclipse.emf.cdo.util.CDOUtil; +import org.eclipse.emf.cdo.view.CDOView; +import org.eclipse.emf.cdo.view.CDOViewTargetChangedEvent; + +import org.eclipse.net4j.util.event.IEvent; +import org.eclipse.net4j.util.event.IListener; + +import org.eclipse.emf.common.notify.AdapterFactory; +import org.eclipse.emf.common.util.URI; +import org.eclipse.emf.ecore.EObject; +import org.eclipse.emf.ecore.EcoreFactory; +import org.eclipse.emf.ecore.EcorePackage; +import org.eclipse.emf.ecore.util.EcoreUtil; +import org.eclipse.emf.edit.domain.EditingDomain; +import org.eclipse.emf.edit.ui.provider.ExtendedImageRegistry; + +import org.eclipse.jface.action.Action; +import org.eclipse.jface.action.IAction; +import org.eclipse.jface.dialogs.IMessageProvider; +import org.eclipse.jface.viewers.ISelection; +import org.eclipse.jface.viewers.StructuredSelection; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Display; +import org.eclipse.ui.IActionBars; +import org.eclipse.ui.IEditorPart; +import org.eclipse.ui.IWorkbenchPage; +import org.eclipse.ui.PartInitException; +import org.eclipse.ui.forms.AbstractFormPart; +import org.eclipse.ui.forms.DetailsPart; +import org.eclipse.ui.forms.IFormPart; +import org.eclipse.ui.forms.IManagedForm; +import org.eclipse.ui.forms.IPartSelectionListener; +import org.eclipse.ui.forms.MasterDetailsBlock; +import org.eclipse.ui.forms.editor.FormEditor; +import org.eclipse.ui.forms.editor.FormPage; +import org.eclipse.ui.forms.widgets.FormToolkit; +import org.eclipse.ui.forms.widgets.ScrolledForm; + +/** + * + */ +public class CDOSecurityPage extends FormPage +{ + + private static final Object NO_INPUT = new Object(); + + private IListener viewTargetListener; + + private Object formInput; + + private IActionBars actionBars; + + CDOSecurityPage(CDOSecurityFormEditor editor) + { + super(editor, "securityForm", Messages.CDOSecurityPage_1); //$NON-NLS-1$ + } + + @Override + public void initialize(FormEditor editor) + { + super.initialize(editor); + + viewTargetListener = createViewTargetListener(); + getView().addListener(viewTargetListener); + + actionBars = getEditor().getActionBars(); + + CDOResource resource = getEditor().getResource(); + if (resource == null) + { + formInput = NO_INPUT; + } + else + { + formInput = EcoreUtil.getObjectByType(resource.getContents(), SecurityPackage.Literals.REALM); + } + } + + @Override + public CDOSecurityFormEditor getEditor() + { + return (CDOSecurityFormEditor)super.getEditor(); + } + + @Override + protected void createFormContent(IManagedForm managedForm) + { + final ScrolledForm form = managedForm.getForm(); + final FormToolkit toolkit = managedForm.getToolkit(); + toolkit.decorateFormHeading(form.getForm()); + form.getToolBarManager().add(createEditAdvancedAction()); + + class EmptySelectionForwarder extends AbstractFormPart implements IPartSelectionListener + { + private DetailsPart details; + + public void selectionChanged(IFormPart part, ISelection selection) + { + if (selection.isEmpty() && details != null) + { + forwardEmptySelection(); + } + } + + void setDetailsPart(DetailsPart detailsPart) + { + details = detailsPart; + } + + void forwardEmptySelection() + { + // show our preferred empty page + details.selectionChanged(this, new StructuredSelection(EcoreFactory.eINSTANCE.createEObject())); + } + } + + final EmptySelectionForwarder emptySelectionForwarder = new EmptySelectionForwarder(); + MasterDetailsBlock masterDetail = new MasterDetailsBlock() + { + @Override + protected void registerPages(DetailsPart detailsPart) + { + detailsPart.setPageProvider(EClassDetailsPageProvider.builder(actionBars) // + .page(SecurityPackage.Literals.GROUP, new GroupDetailsPage(getEditingDomain(), getAdapterFactory())) // + .page(SecurityPackage.Literals.USER, new UserDetailsPage(getEditingDomain(), getAdapterFactory())) // + .page(SecurityPackage.Literals.ROLE, new RoleDetailsPage(getEditingDomain(), getAdapterFactory())) // + .page(EcorePackage.Literals.EOBJECT, new EmptyDetailsPage()) // + .build()); + + emptySelectionForwarder.setDetailsPart(detailsPart); + } + + @Override + protected void createToolBarActions(IManagedForm managedForm) + { + } + + @Override + protected void createMasterPart(IManagedForm managedForm, Composite parent) + { + Composite body = managedForm.getToolkit().createComposite(parent); + GridLayout layout = new GridLayout(); + layout.numColumns = 1; + body.setLayout(layout); + + addSection(new GroupsSection(getEditingDomain(), getAdapterFactory()), managedForm, body); + addSection(new UsersSection(getEditingDomain(), getAdapterFactory()), managedForm, body); + addSection(new RolesSection(getEditingDomain(), getAdapterFactory()), managedForm, body); + } + }; + + form.setText(Messages.CDOSecurityPage_2); + masterDetail.createContent(managedForm); + + managedForm.setInput(formInput); + + // initialize the empty selection + managedForm.addPart(emptySelectionForwarder); + emptySelectionForwarder.forwardEmptySelection(); + + form.updateToolBar(); + + if (getEditor().isReadOnly()) + { + managedForm.getMessageManager().addMessage(this, Messages.CDOSecurityPage_3, null, IMessageProvider.INFORMATION); + } + else + { + // check for unsupported security constructs + checkForUnsupportedModelContent(); + } + + // update the message manager after the form's contents have been presented to ensure the heading's summary of + // problems is up-to-date + Display.getCurrent().asyncExec(new Runnable() + { + + public void run() + { + getManagedForm().getMessageManager().update(); + } + }); + } + + protected <S extends AbstractSectionPart<?>> S addSection(S section, IManagedForm managedForm, Composite parent) + { + section.setEditorActionBars(actionBars); + managedForm.addPart(section); + section.createContents(parent); + return section; + } + + @Override + public void dispose() + { + try + { + CDOView view = getView(); + + if (view != null) + { + view.removeListener(viewTargetListener); + } + } + finally + { + super.dispose(); + } + } + + protected AdapterFactory getAdapterFactory() + { + return getEditor().getAdapterFactory(); + } + + protected EditingDomain getEditingDomain() + { + return getEditor().getEditingDomain(); + } + + protected CDOView getView() + { + return getEditor().getView(); + } + + protected IListener createViewTargetListener() + { + return new IListener() + { + protected CDOID inputID; + + public void notifyEvent(IEvent event) + { + if (event instanceof CDOViewTargetChangedEvent) + { + final CDOViewTargetChangedEvent e = (CDOViewTargetChangedEvent)event; + getSite().getShell().getDisplay().asyncExec(new Runnable() + { + public void run() + { + Object input = getManagedForm().getInput(); + if (input == NO_INPUT) + { + if (inputID != null) + { + try + { + CDOObject object = getView().getObject(inputID); + getManagedForm().setInput(object); + inputID = null; + } + catch (Exception ex) + { + // Ignore + } + } + } + else if (input instanceof EObject) + { + CDOObject object = CDOUtil.getCDOObject((EObject)input); + if (object.cdoInvalid()) + { + if (e.getBranchPoint().getTimeStamp() == e.getOldBranchPoint().getTimeStamp()) + { + inputID = null; + closeEditor(); + } + else + { + inputID = object.cdoID(); + getManagedForm().setInput(NO_INPUT); + } + } + } + } + }); + } + } + }; + } + + protected void closeEditor() + { + try + { + getSite().getShell().getDisplay().asyncExec(new Runnable() + { + public void run() + { + try + { + getSite().getPage().closeEditor(getEditor(), false); + } + catch (Exception e) + { + OM.LOG.error(e); + } + } + }); + } + catch (Exception e) + { + OM.LOG.error(e); + } + } + + protected void checkForUnsupportedModelContent() + { + Object input = getManagedForm().getInput(); + if (!(input instanceof Realm)) + { + getManagedForm().getMessageManager().addMessage(this, Messages.CDOSecurityPage_4, null, IMessageProvider.ERROR); + } + } + + private IAction createEditAdvancedAction() + { + return new Action("Open Advanced Editor", ExtendedImageRegistry.getInstance().getImageDescriptor( + URI.createPlatformPluginURI(OM.BUNDLE_ID + "/icons/full/elcl16/advanced.gif", true))) + { + @Override + public void run() + { + try + { + IEditorPart advancedEditor = getSite().getPage().openEditor(getEditorInput(), CDOEditorUtil.getEditorID(), + true, IWorkbenchPage.MATCH_INPUT | IWorkbenchPage.MATCH_ID); + if (advancedEditor != null) + { + // close me + closeEditor(); + } + } + catch (PartInitException e) + { + OM.LOG.error(e); + } + } + }; + } +} diff --git a/plugins/org.eclipse.emf.cdo.security.ui/src/org/eclipse/emf/cdo/internal/security/ui/editor/EClassDetailsPageProvider.java b/plugins/org.eclipse.emf.cdo.security.ui/src/org/eclipse/emf/cdo/internal/security/ui/editor/EClassDetailsPageProvider.java new file mode 100644 index 0000000000..d5c0ae58ab --- /dev/null +++ b/plugins/org.eclipse.emf.cdo.security.ui/src/org/eclipse/emf/cdo/internal/security/ui/editor/EClassDetailsPageProvider.java @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2004-2013 Eike Stepper (Berlin, Germany), CEA LIST, 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: + * Christian W. Damus (CEA LIST) - initial API and implementation + */ +package org.eclipse.emf.cdo.internal.security.ui.editor; + +import org.eclipse.emf.ecore.EClass; +import org.eclipse.emf.ecore.EObject; + +import org.eclipse.ui.IActionBars; +import org.eclipse.ui.forms.IDetailsPage; +import org.eclipse.ui.forms.IDetailsPageProvider; + +import java.util.Map; + +/** + * + */ +public class EClassDetailsPageProvider implements IDetailsPageProvider +{ + + private final Map<EClass, IDetailsPage> pages = new java.util.HashMap<EClass, IDetailsPage>(); + + private EClassDetailsPageProvider() + { + } + + public static Builder builder(IActionBars editorActionBars) + { + return new Builder(editorActionBars); + } + + public Object getPageKey(Object object) + { + return object instanceof EObject ? ((EObject)object).eClass() : null; + } + + public IDetailsPage getPage(Object key) + { + return pages.get(key); + } + + // + // Nested types + // + + public static class Builder + { + private final Map<EClass, IDetailsPage> pages = new java.util.HashMap<EClass, IDetailsPage>(); + + private final IActionBars actionBars; + + private Builder(IActionBars actionBars) + { + this.actionBars = actionBars; + } + + public Builder page(EClass eclass, IDetailsPage page) + { + if (page instanceof AbstractSectionPart<?>) + { + ((AbstractSectionPart<?>)page).setEditorActionBars(actionBars); + } + + pages.put(eclass, page); + + return this; + } + + public EClassDetailsPageProvider build() + { + EClassDetailsPageProvider result = new EClassDetailsPageProvider(); + result.pages.putAll(pages); + return result; + } + } +} diff --git a/plugins/org.eclipse.emf.cdo.security.ui/src/org/eclipse/emf/cdo/internal/security/ui/editor/EmptyDetailsPage.java b/plugins/org.eclipse.emf.cdo.security.ui/src/org/eclipse/emf/cdo/internal/security/ui/editor/EmptyDetailsPage.java new file mode 100644 index 0000000000..fb8437fe3b --- /dev/null +++ b/plugins/org.eclipse.emf.cdo.security.ui/src/org/eclipse/emf/cdo/internal/security/ui/editor/EmptyDetailsPage.java @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2004-2013 Eike Stepper (Berlin, Germany), CEA LIST, 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: + * Christian W. Damus (CEA LIST) - initial API and implementation + */ +package org.eclipse.emf.cdo.internal.security.ui.editor; + +import org.eclipse.emf.cdo.internal.security.ui.messages.Messages; + +import org.eclipse.jface.viewers.ISelection; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Label; +import org.eclipse.ui.forms.AbstractFormPart; +import org.eclipse.ui.forms.IDetailsPage; +import org.eclipse.ui.forms.IFormPart; +import org.eclipse.ui.forms.widgets.FormToolkit; +import org.eclipse.ui.forms.widgets.Section; +import org.eclipse.ui.forms.widgets.TableWrapData; +import org.eclipse.ui.forms.widgets.TableWrapLayout; + +/** + * + */ +public class EmptyDetailsPage extends AbstractFormPart implements IDetailsPage +{ + + public EmptyDetailsPage() + { + } + + public void createContents(Composite parent) + { + parent.setLayout(new TableWrapLayout()); + FormToolkit toolkit = getManagedForm().getToolkit(); + + Section section = toolkit.createSection(parent, Section.SHORT_TITLE_BAR); + section.setLayoutData(new TableWrapData(TableWrapData.FILL_GRAB)); + + section.setText(Messages.EmptyDetailsPage_0); + Label label = toolkit.createLabel(section, Messages.EmptyDetailsPage_1); + section.setClient(label); + } + + public void selectionChanged(IFormPart part, ISelection selection) + { + // pass + } + +} diff --git a/plugins/org.eclipse.emf.cdo.security.ui/src/org/eclipse/emf/cdo/internal/security/ui/editor/GroupDetailsPage.java b/plugins/org.eclipse.emf.cdo.security.ui/src/org/eclipse/emf/cdo/internal/security/ui/editor/GroupDetailsPage.java new file mode 100644 index 0000000000..7cea227dc1 --- /dev/null +++ b/plugins/org.eclipse.emf.cdo.security.ui/src/org/eclipse/emf/cdo/internal/security/ui/editor/GroupDetailsPage.java @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2004-2013 Eike Stepper (Berlin, Germany), CEA LIST, 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: + * Christian W. Damus (CEA LIST) - initial API and implementation + */ +package org.eclipse.emf.cdo.internal.security.ui.editor; + +import org.eclipse.emf.cdo.internal.security.ui.messages.Messages; +import org.eclipse.emf.cdo.security.Group; +import org.eclipse.emf.cdo.security.SecurityPackage; + +import org.eclipse.emf.common.notify.AdapterFactory; +import org.eclipse.emf.edit.domain.EditingDomain; + +import org.eclipse.swt.widgets.Composite; +import org.eclipse.ui.forms.widgets.FormToolkit; + +/** + * + */ +public class GroupDetailsPage extends AbstractDetailsPage<Group> +{ + + public GroupDetailsPage(EditingDomain domain, AdapterFactory adapterFactory) + { + super(Group.class, SecurityPackage.Literals.GROUP, domain, adapterFactory); + } + + @Override + protected void createContents(Composite parent, FormToolkit toolkit) + { + super.createContents(parent, toolkit); + + text(parent, toolkit, Messages.GroupDetailsPage_0, SecurityPackage.Literals.ASSIGNEE__ID); + + space(parent, toolkit); + + oneToMany(parent, toolkit, Messages.GroupDetailsPage_1, SecurityPackage.Literals.GROUP__USERS); + + oneToMany(parent, toolkit, Messages.GroupDetailsPage_2, SecurityPackage.Literals.ASSIGNEE__ROLES); + } + +} diff --git a/plugins/org.eclipse.emf.cdo.security.ui/src/org/eclipse/emf/cdo/internal/security/ui/editor/GroupsSection.java b/plugins/org.eclipse.emf.cdo.security.ui/src/org/eclipse/emf/cdo/internal/security/ui/editor/GroupsSection.java new file mode 100644 index 0000000000..a6d831bc67 --- /dev/null +++ b/plugins/org.eclipse.emf.cdo.security.ui/src/org/eclipse/emf/cdo/internal/security/ui/editor/GroupsSection.java @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2004-2013 Eike Stepper (Berlin, Germany), CEA LIST, 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: + * Christian W. Damus (CEA LIST) - initial API and implementation + */ +package org.eclipse.emf.cdo.internal.security.ui.editor; + +import org.eclipse.emf.cdo.internal.security.ui.messages.Messages; +import org.eclipse.emf.cdo.security.Group; +import org.eclipse.emf.cdo.security.Role; +import org.eclipse.emf.cdo.security.SecurityPackage; +import org.eclipse.emf.cdo.security.User; + +import org.eclipse.emf.common.notify.AdapterFactory; +import org.eclipse.emf.ecore.EObject; +import org.eclipse.emf.ecore.EReference; +import org.eclipse.emf.edit.domain.EditingDomain; + +/** + * + */ +public class GroupsSection extends TableSection<Group> +{ + + public GroupsSection(EditingDomain domain, AdapterFactory adapterFactory) + { + super(Group.class, SecurityPackage.Literals.GROUP, domain, adapterFactory); + } + + @Override + protected String getTitle() + { + return Messages.GroupsSection_0; + } + + @Override + protected EReference getDropReference(EObject target, EObject objectToDrop) + { + EReference result = null; + + if (objectToDrop instanceof User) + { + result = SecurityPackage.Literals.GROUP__USERS; + } + else if (objectToDrop instanceof Role) + { + result = SecurityPackage.Literals.ASSIGNEE__ROLES; + } + + return result; + } +} diff --git a/plugins/org.eclipse.emf.cdo.security.ui/src/org/eclipse/emf/cdo/internal/security/ui/editor/RoleDetailsPage.java b/plugins/org.eclipse.emf.cdo.security.ui/src/org/eclipse/emf/cdo/internal/security/ui/editor/RoleDetailsPage.java new file mode 100644 index 0000000000..23307e03e8 --- /dev/null +++ b/plugins/org.eclipse.emf.cdo.security.ui/src/org/eclipse/emf/cdo/internal/security/ui/editor/RoleDetailsPage.java @@ -0,0 +1,387 @@ +/* + * Copyright (c) 2004-2013 Eike Stepper (Berlin, Germany), CEA LIST, 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: + * Christian W. Damus (CEA LIST) - initial API and implementation + */ +package org.eclipse.emf.cdo.internal.security.ui.editor; + +import static org.eclipse.emf.cdo.internal.security.ui.util.SecurityModelUtil.getTypeFilter; +import static org.eclipse.emf.cdo.internal.security.ui.util.SecurityModelUtil.viewerFilter; + +import org.eclipse.emf.cdo.eresource.CDOResourceNode; +import org.eclipse.emf.cdo.eresource.EresourcePackage; +import org.eclipse.emf.cdo.internal.security.ui.dialogs.FilterTreeSelectionDialog; +import org.eclipse.emf.cdo.internal.security.ui.messages.Messages; +import org.eclipse.emf.cdo.internal.security.ui.util.EditableDialogCellEditor; +import org.eclipse.emf.cdo.internal.security.ui.util.INewObjectConfigurator; +import org.eclipse.emf.cdo.internal.security.ui.util.OneToManyTableBlock; +import org.eclipse.emf.cdo.internal.security.ui.util.ResourceBasedPermissionFilter; +import org.eclipse.emf.cdo.security.Access; +import org.eclipse.emf.cdo.security.FilterPermission; +import org.eclipse.emf.cdo.security.PatternStyle; +import org.eclipse.emf.cdo.security.ResourceFilter; +import org.eclipse.emf.cdo.security.Role; +import org.eclipse.emf.cdo.security.SecurityFactory; +import org.eclipse.emf.cdo.security.SecurityPackage; +import org.eclipse.emf.cdo.security.provider.SecurityEditPlugin; +import org.eclipse.emf.cdo.ui.CDOItemProvider; +import org.eclipse.emf.cdo.view.CDOView; + +import org.eclipse.net4j.util.ObjectUtil; +import org.eclipse.net4j.util.container.IContainer; + +import org.eclipse.emf.common.command.Command; +import org.eclipse.emf.common.notify.AdapterFactory; +import org.eclipse.emf.edit.command.CommandParameter; +import org.eclipse.emf.edit.command.CreateChildCommand; +import org.eclipse.emf.edit.command.SetCommand; +import org.eclipse.emf.edit.domain.EditingDomain; +import org.eclipse.emf.edit.ui.provider.AdapterFactoryLabelProvider; + +import org.eclipse.jface.viewers.ArrayContentProvider; +import org.eclipse.jface.viewers.CellEditor; +import org.eclipse.jface.viewers.CellLabelProvider; +import org.eclipse.jface.viewers.ColumnLabelProvider; +import org.eclipse.jface.viewers.ComboBoxViewerCellEditor; +import org.eclipse.jface.viewers.TableViewer; +import org.eclipse.jface.window.Window; +import org.eclipse.swt.SWT; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; +import org.eclipse.ui.forms.widgets.FormToolkit; + +import java.util.Collections; + +/** + * + */ +public class RoleDetailsPage extends AbstractDetailsPage<Role> +{ + + public RoleDetailsPage(EditingDomain domain, AdapterFactory adapterFactory) + { + super(Role.class, SecurityPackage.Literals.ROLE, domain, adapterFactory); + } + + @Override + protected void createContents(Composite parent, FormToolkit toolkit) + { + super.createContents(parent, toolkit); + + text(parent, toolkit, Messages.RoleDetailsPage_0, SecurityPackage.Literals.ROLE__ID); + + space(parent, toolkit); + + OneToManyTableBlock perms = table(parent, toolkit, Messages.RoleDetailsPage_1, createTableConfiguration()); + perms.setNewObjectConfigurator(createNewPermissionConfigurator()); + + space(parent, toolkit); + + oneToMany(parent, toolkit, Messages.RoleDetailsPage_2, SecurityPackage.Literals.ROLE__ASSIGNEES, + SecurityPackage.Literals.GROUP); + + oneToMany(parent, toolkit, Messages.RoleDetailsPage_3, SecurityPackage.Literals.ROLE__ASSIGNEES, + SecurityPackage.Literals.USER); + } + + protected INewObjectConfigurator createNewPermissionConfigurator() + { + return new INewObjectConfigurator() + { + + public Command createConfigureCommand(Object newObject) + { + ResourceFilter filter = SecurityFactory.eINSTANCE.createResourceFilter("/home/${user}", PatternStyle.TREE); //$NON-NLS-1$ + Command result = CreateChildCommand.create(getEditingDomain(), newObject, new CommandParameter(newObject, + SecurityPackage.Literals.FILTER_PERMISSION__FILTERS, filter), Collections.singleton(newObject)); + result = result.chain(SetCommand.create(getEditingDomain(), newObject, + SecurityPackage.Literals.PERMISSION__ACCESS, Access.WRITE)); + return result; + } + }; + } + + protected OneToManyTableBlock.ITableConfiguration createTableConfiguration() + { + return new OneToManyTableBlock.TableConfiguration(SecurityPackage.Literals.ROLE__PERMISSIONS, + SecurityPackage.Literals.FILTER_PERMISSION, new ResourceBasedPermissionFilter()) + { + private static final int COL_ACCESS = 0; + + private static final int COL_PATTERN_STYLE = 1; + + private static final int COL_PATH = 2; + + private final String[] columnTitles = { Messages.RoleDetailsPage_5, Messages.RoleDetailsPage_6, + Messages.RoleDetailsPage_7 }; + + private final CellEditor[] cellEditors = new CellEditor[3]; + + public String[] getColumnTitles() + { + return columnTitles; + } + + public int getColumnWeight(int index) + { + switch (index) + { + case COL_ACCESS: + return 15; + case COL_PATTERN_STYLE: + return 15; + case COL_PATH: + return 70; + default: + throw new IllegalArgumentException("index"); //$NON-NLS-1$ + } + } + + public int getColumnMinimumSize(int index) + { + switch (index) + { + case COL_ACCESS: + return 30; + case COL_PATTERN_STYLE: + return 30; + case COL_PATH: + return 120; + default: + throw new IllegalArgumentException("index"); //$NON-NLS-1$ + } + } + + public boolean isColumnResizable(int index) + { + switch (index) + { + case COL_ACCESS: + return false; + case COL_PATTERN_STYLE: + return false; + case COL_PATH: + return true; + default: + throw new IllegalArgumentException("index"); //$NON-NLS-1$ + } + } + + public CellLabelProvider getLabelProvider(TableViewer viewer, final int columnIndex) + { + return new ColumnLabelProvider() + { + @Override + public String getText(Object element) + { + final FilterPermission perm = (FilterPermission)element; + final ResourceFilter filter = perm.getFilters().isEmpty() ? null : (ResourceFilter)perm.getFilters().get(0); + + switch (columnIndex) + { + case COL_ACCESS: + return SecurityEditPlugin.INSTANCE.getString(String.format("_UI_Access_%s_literal", perm.getAccess())); //$NON-NLS-1$ + case COL_PATTERN_STYLE: + { + String result = "=="; //$NON-NLS-1$ + if (filter != null && filter.getPatternStyle() != null) + { + switch (filter.getPatternStyle()) + { + case EXACT: + break; + case TREE: + result = ">="; //$NON-NLS-1$ + break; + default: + result = "~="; //$NON-NLS-1$ + break; + } + } + return result; + } + case COL_PATH: + return filter == null ? "" : filter.getPath(); //$NON-NLS-1$ + default: + throw new IllegalArgumentException("columnIndex"); //$NON-NLS-1$ + } + } + }; + } + + public boolean canEdit(TableViewer viewer, Object element, int columnIndex) + { + return true; + } + + public void setValue(TableViewer viewer, Object element, int columnIndex, Object value) + { + final FilterPermission perm = (FilterPermission)element; + final ResourceFilter filter = (ResourceFilter)perm.getFilters().get(0); + + switch (columnIndex) + { + case COL_ACCESS: + if (perm.getAccess() != value) + { + execute(SetCommand.create(getEditingDomain(), perm, SecurityPackage.Literals.PERMISSION__ACCESS, value)); + viewer.refresh(element); + } + break; + case COL_PATTERN_STYLE: + if (filter.getPatternStyle() != value) + { + execute(SetCommand.create(getEditingDomain(), filter, + SecurityPackage.Literals.RESOURCE_FILTER__PATTERN_STYLE, value)); + viewer.refresh(element); + } + break; + case COL_PATH: + if (!ObjectUtil.equals(filter.getPath(), value)) + { + execute(SetCommand + .create(getEditingDomain(), filter, SecurityPackage.Literals.RESOURCE_FILTER__PATH, value)); + viewer.refresh(element); + } + break; + default: + throw new IllegalArgumentException("columnIndex"); //$NON-NLS-1$ + } + } + + public Object getValue(TableViewer viewer, Object element, int columnIndex) + { + final FilterPermission perm = (FilterPermission)element; + final ResourceFilter filter = (ResourceFilter)perm.getFilters().get(0); + + switch (columnIndex) + { + case COL_ACCESS: + return perm.getAccess(); + case COL_PATTERN_STYLE: + return filter.getPatternStyle(); + case COL_PATH: + return filter.getPath(); + default: + throw new IllegalArgumentException("columnIndex"); //$NON-NLS-1$ + } + } + + public CellEditor getCellEditor(final TableViewer viewer, int columnIndex) + { + CellEditor result = cellEditors[columnIndex]; + if (result == null) + { + result = createCellEditor(viewer, columnIndex); + cellEditors[columnIndex] = result; + } + + return result; + } + + protected CellEditor createCellEditor(TableViewer viewer, int columnIndex) + { + Composite parent = (Composite)viewer.getControl(); + + switch (columnIndex) + { + case COL_ACCESS: + { + ComboBoxViewerCellEditor result = new ComboBoxViewerCellEditor(parent, SWT.DROP_DOWN | SWT.READ_ONLY); + result.setLabelProvider(new AdapterFactoryLabelProvider(getAdapterFactory())); + result.setContentProvider(new ArrayContentProvider()); + result.setInput(Access.VALUES); + return result; + } + case COL_PATTERN_STYLE: + { + ComboBoxViewerCellEditor result = new ComboBoxViewerCellEditor(parent, SWT.DROP_DOWN | SWT.READ_ONLY); + result.setLabelProvider(new AdapterFactoryLabelProvider(getAdapterFactory())); + result.setContentProvider(new ArrayContentProvider()); + result.setInput(PatternStyle.VALUES); + return result; + } + case COL_PATH: + return new EditableDialogCellEditor(parent) + { + + @Override + protected Object openDialogBox(Control cellEditorWindow) + { + final CDOView view = getInput().cdoView(); + @SuppressWarnings({ "rawtypes", "unchecked" }) + CDOItemProvider provider = new CDOItemProvider(null) + { + private boolean connected; + + { + // connect the input now, because the dialog will try to access the content provider before it has + // been set into the tree viewer + connectInput((IContainer)view); + } + + @Override + protected void connectInput(IContainer<Object> input) + { + if (!connected) + { + super.connectInput(input); + connected = true; + } + } + + @Override + protected void disconnectInput(IContainer<Object> input) + { + if (connected) + { + connected = false; + super.disconnectInput(input); + } + } + }; + + FilterTreeSelectionDialog dlg = new FilterTreeSelectionDialog(cellEditorWindow.getShell(), provider, + provider); + + dlg.setAllowMultiple(false); + dlg.setMessage(Messages.RoleDetailsPage_4); + dlg.setTitle(Messages.RoleDetailsPage_8); + dlg.setDoubleClickSelects(true); + dlg.addFilter(viewerFilter(getTypeFilter(EresourcePackage.Literals.CDO_RESOURCE_NODE))); + dlg.setBlockOnOpen(true); + + String current = (String)getValue(); + + dlg.setInput(view); + if (current != null && view.hasResource(current)) + { + dlg.setInitialSelection(view.getResourceNode(current)); + } + + String result = null; + + if (dlg.open() == Window.OK) + { + CDOResourceNode node = (CDOResourceNode)dlg.getFirstResult(); + if (node != null) + { + result = node.getPath(); + } + } + + return result; + } + }; + default: + throw new IllegalArgumentException("columnIndex"); //$NON-NLS-1$ + } + } + }; + } +} diff --git a/plugins/org.eclipse.emf.cdo.security.ui/src/org/eclipse/emf/cdo/internal/security/ui/editor/RolesSection.java b/plugins/org.eclipse.emf.cdo.security.ui/src/org/eclipse/emf/cdo/internal/security/ui/editor/RolesSection.java new file mode 100644 index 0000000000..3bbd8f1b52 --- /dev/null +++ b/plugins/org.eclipse.emf.cdo.security.ui/src/org/eclipse/emf/cdo/internal/security/ui/editor/RolesSection.java @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2004-2013 Eike Stepper (Berlin, Germany), CEA LIST, 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: + * Christian W. Damus (CEA LIST) - initial API and implementation + */ +package org.eclipse.emf.cdo.internal.security.ui.editor; + +import org.eclipse.emf.cdo.internal.security.ui.messages.Messages; +import org.eclipse.emf.cdo.security.Assignee; +import org.eclipse.emf.cdo.security.Role; +import org.eclipse.emf.cdo.security.SecurityPackage; + +import org.eclipse.emf.common.notify.AdapterFactory; +import org.eclipse.emf.ecore.EObject; +import org.eclipse.emf.ecore.EReference; +import org.eclipse.emf.edit.domain.EditingDomain; + +/** + * + */ +public class RolesSection extends TableSection<Role> +{ + + public RolesSection(EditingDomain domain, AdapterFactory adapterFactory) + { + super(Role.class, SecurityPackage.Literals.ROLE, domain, adapterFactory); + } + + @Override + protected String getTitle() + { + return Messages.RolesSection_0; + } + + @Override + protected EReference getDropReference(EObject target, EObject objectToDrop) + { + EReference result = null; + + if (objectToDrop instanceof Assignee) + { + result = SecurityPackage.Literals.ROLE__ASSIGNEES; + } + + return result; + } +} diff --git a/plugins/org.eclipse.emf.cdo.security.ui/src/org/eclipse/emf/cdo/internal/security/ui/editor/TableSection.java b/plugins/org.eclipse.emf.cdo.security.ui/src/org/eclipse/emf/cdo/internal/security/ui/editor/TableSection.java new file mode 100644 index 0000000000..953d781416 --- /dev/null +++ b/plugins/org.eclipse.emf.cdo.security.ui/src/org/eclipse/emf/cdo/internal/security/ui/editor/TableSection.java @@ -0,0 +1,416 @@ +/* + * Copyright (c) 2004-2013 Eike Stepper (Berlin, Germany), CEA LIST, 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: + * Christian W. Damus (CEA LIST) - initial API and implementation + */ +package org.eclipse.emf.cdo.internal.security.ui.editor; + +import org.eclipse.emf.cdo.internal.security.ui.actions.SelectionListenerAction; +import org.eclipse.emf.cdo.internal.security.ui.messages.Messages; +import org.eclipse.emf.cdo.internal.security.ui.util.ActionBarsHelper; +import org.eclipse.emf.cdo.internal.security.ui.util.ObjectExistsConverter; +import org.eclipse.emf.cdo.internal.security.ui.util.SecurityModelUtil; +import org.eclipse.emf.cdo.internal.security.ui.util.TableLabelProvider; +import org.eclipse.emf.cdo.security.Directory; +import org.eclipse.emf.cdo.security.Realm; +import org.eclipse.emf.cdo.security.SecurityFactory; +import org.eclipse.emf.cdo.security.SecurityPackage; +import org.eclipse.emf.cdo.ui.shared.SharedIcons; + +import org.eclipse.net4j.util.ui.UIUtil; + +import org.eclipse.emf.common.command.Command; +import org.eclipse.emf.common.notify.AdapterFactory; +import org.eclipse.emf.ecore.EClass; +import org.eclipse.emf.ecore.EClassifier; +import org.eclipse.emf.ecore.EObject; +import org.eclipse.emf.ecore.EReference; +import org.eclipse.emf.ecore.util.EcoreUtil; +import org.eclipse.emf.edit.command.AddCommand; +import org.eclipse.emf.edit.command.CommandActionDelegate; +import org.eclipse.emf.edit.command.CommandParameter; +import org.eclipse.emf.edit.command.CreateChildCommand; +import org.eclipse.emf.edit.command.DeleteCommand; +import org.eclipse.emf.edit.domain.EditingDomain; +import org.eclipse.emf.edit.ui.provider.AdapterFactoryContentProvider; +import org.eclipse.emf.edit.ui.provider.ExtendedImageRegistry; + +import org.eclipse.core.databinding.beans.PojoObservables; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.jface.action.Action; +import org.eclipse.jface.action.IAction; +import org.eclipse.jface.action.ToolBarManager; +import org.eclipse.jface.databinding.viewers.ViewersObservables; +import org.eclipse.jface.resource.ImageDescriptor; +import org.eclipse.jface.util.LocalSelectionTransfer; +import org.eclipse.jface.viewers.ISelectionChangedListener; +import org.eclipse.jface.viewers.IStructuredSelection; +import org.eclipse.jface.viewers.SelectionChangedEvent; +import org.eclipse.jface.viewers.StructuredSelection; +import org.eclipse.jface.viewers.StructuredViewer; +import org.eclipse.jface.viewers.TableViewer; +import org.eclipse.jface.viewers.Viewer; +import org.eclipse.jface.viewers.ViewerDropAdapter; +import org.eclipse.jface.viewers.ViewerFilter; +import org.eclipse.swt.SWT; +import org.eclipse.swt.dnd.DND; +import org.eclipse.swt.dnd.DragSourceAdapter; +import org.eclipse.swt.dnd.DragSourceEvent; +import org.eclipse.swt.dnd.Transfer; +import org.eclipse.swt.dnd.TransferData; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Table; +import org.eclipse.swt.widgets.ToolBar; +import org.eclipse.ui.actions.ActionFactory; +import org.eclipse.ui.forms.IManagedForm; +import org.eclipse.ui.forms.widgets.FormToolkit; +import org.eclipse.ui.forms.widgets.Section; + +import java.util.Collections; + +/** + * + */ +public abstract class TableSection<T extends EObject> extends AbstractSectionPart<Directory> +{ + + private final Class<T> elementType; + + private final EClass elementEClass; + + private TableViewer viewer; + + public TableSection(Class<T> elementType, EClass elementEClass, EditingDomain domain, AdapterFactory adapterFactory) + { + super(Directory.class, SecurityPackage.Literals.DIRECTORY, domain, adapterFactory); + + this.elementType = elementType; + this.elementEClass = elementEClass; + } + + @Override + protected void createContents(Composite parent, FormToolkit toolkit) + { + parent.setLayout(new GridLayout()); + Table table = toolkit.createTable(parent, SWT.H_SCROLL | SWT.V_SCROLL); + table.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); + viewer = new TableViewer(table); + + viewer.setContentProvider(new AdapterFactoryContentProvider(getAdapterFactory())); + viewer.setLabelProvider(new TableLabelProvider(getAdapterFactory())); + addFilters(viewer); + forwardSelection(viewer); + + getContext().bindValue(ViewersObservables.observeInput(viewer), getValue()); + + configureDragSupport(viewer); + configureDropSupport(viewer); + } + + @Override + public void setFocus() + { + if (viewer != null) + { + viewer.getControl().setFocus(); + } + else + { + super.setFocus(); + } + } + + protected void addFilters(TableViewer viewer) + { + viewer.addFilter(createTypeFilter(elementEClass)); + SecurityModelUtil.applyDefaultFilters(viewer, elementEClass); + } + + protected ViewerFilter createTypeFilter(final EClassifier type) + { + return new ViewerFilter() + { + + @Override + public boolean select(Viewer viewer, Object parentElement, Object element) + { + return type.isInstance(element); + } + }; + } + + @Override + public boolean setFormInput(Object input) + { + if (elementType.isInstance(input)) + { + viewer.setSelection(new StructuredSelection(input), true); + return true; + } + else if (input instanceof Directory && input == getDirectory(((Directory)input).getRealm())) + { + // it's my directory + boolean result = super.setFormInput(input); + + checkForUnsupportedModelContent(); + + return result; + } + else if (input instanceof Realm) + { + return setFormInput(getDirectory((Realm)input)); + } + + return false; + } + + protected Directory getDirectory(Realm realm) + { + return SecurityModelUtil.getDirectory(realm, elementEClass); + } + + @Override + protected void createActionToolbar(Section section, FormToolkit toolkit) + { + ToolBarManager mgr = new ToolBarManager(SWT.FLAT); + ToolBar toolbar = mgr.createControl(section); + toolbar.setCursor(section.getDisplay().getSystemCursor(SWT.CURSOR_HAND)); + + mgr.add(createAddNewAction()); + + IAction deleteAction = createDeleteAction(); + mgr.add(deleteAction); + if (deleteAction instanceof ISelectionChangedListener) + { + ISelectionChangedListener scl = (ISelectionChangedListener)deleteAction; + viewer.addSelectionChangedListener(scl); + scl.selectionChanged(new SelectionChangedEvent(viewer, viewer.getSelection())); + } + + mgr.update(true); + section.setTextClient(toolbar); + + new ActionBarsHelper(getEditorActionBars()).addGlobalAction(ActionFactory.DELETE.getId(), deleteAction).install( + viewer); + } + + protected IAction createAddNewAction() + { + Command dummy = createCreateNewCommand(); + ImageDescriptor image = null; + + if (dummy instanceof CommandActionDelegate) + { + image = ExtendedImageRegistry.getInstance().getImageDescriptor(((CommandActionDelegate)dummy).getImage()); + } + + IAction result = new Action(dummy.getLabel(), image) + { + @Override + public void run() + { + final Command command = createCreateNewCommand(); + if (command.canExecute()) + { + getEditingDomain().getCommandStack().execute(command); + viewer.getControl().getDisplay().asyncExec(new Runnable() + { + + public void run() + { + viewer.getControl().setFocus(); + viewer.setSelection(new StructuredSelection(command.getResult().toArray())); + } + }); + } + } + }; + + getContext().bindValue(PojoObservables.observeValue(getContext().getValidationRealm(), result, "enabled"), //$NON-NLS-1$ + getValue(), null, ObjectExistsConverter.createUpdateValueStrategy()); + + return result; + } + + protected Command createCreateNewCommand() + { + Object input = viewer.getInput(); + Directory parent = input instanceof Directory ? (Directory)input : SecurityFactory.eINSTANCE.createDirectory(); + Object child = EcoreUtil.create(elementEClass); + CommandParameter param = new CommandParameter(parent, SecurityPackage.Literals.DIRECTORY__ITEMS, child); + return CreateChildCommand.create(getEditingDomain(), parent, param, Collections.singleton(parent)); + } + + protected IAction createDeleteAction() + { + Command dummy = createDeleteCommand(EcoreUtil.create(elementEClass)); + + return new SelectionListenerAction(dummy.getLabel(), SharedIcons.getDescriptor("etool16/delete.gif")) //$NON-NLS-1$ + { + @Override + public void run() + { + Command delete = createDeleteCommand(getSelectedObject()); + if (delete.canExecute()) + { + getEditingDomain().getCommandStack().execute(delete); + } + } + + @Override + protected boolean updateSelection(IStructuredSelection selection) + { + return super.updateSelection(selection) && SecurityModelUtil.isEditable(getInput()); + } + }; + } + + protected Command createDeleteCommand(EObject toDelete) + { + return DeleteCommand.create(getEditingDomain(), toDelete); + } + + private void forwardSelection(StructuredViewer viewer) + { + viewer.addSelectionChangedListener(new ISelectionChangedListener() + { + + public void selectionChanged(SelectionChangedEvent event) + { + IManagedForm form = getManagedForm(); + if (form != null) + { + form.fireSelectionChanged(TableSection.this, event.getSelection()); + } + } + }); + } + + protected void configureDragSupport(final TableViewer viewer) + { + viewer.addDragSupport(DND.DROP_LINK | DND.DROP_MOVE | DND.DROP_COPY, + new Transfer[] { LocalSelectionTransfer.getTransfer() }, new DragSourceAdapter() + { + private long lastDragTime; + + @Override + public void dragStart(DragSourceEvent event) + { + lastDragTime = System.currentTimeMillis(); + LocalSelectionTransfer.getTransfer().setSelection(viewer.getSelection()); + LocalSelectionTransfer.getTransfer().setSelectionSetTime(lastDragTime); + } + + @Override + public void dragFinished(DragSourceEvent event) + { + if (LocalSelectionTransfer.getTransfer().getSelectionSetTime() == lastDragTime) + { + LocalSelectionTransfer.getTransfer().setSelection(null); + } + } + }); + } + + protected void configureDropSupport(final TableViewer viewer) + { + viewer.addDropSupport(DND.DROP_LINK | DND.DROP_MOVE | DND.DROP_COPY, + new Transfer[] { LocalSelectionTransfer.getTransfer() }, new ViewerDropAdapter(viewer) + { + + { + // we don't want it to look like you can insert new elements, only drop onto existing elements + setFeedbackEnabled(false); + } + + @Override + public boolean validateDrop(Object target, int operation, TransferData transferType) + { + boolean result = false; + + if (target instanceof EObject && LocalSelectionTransfer.getTransfer().isSupportedType(transferType)) + { + EObject objectToDrop = getObjectToDrop(transferType); + if (objectToDrop != null) + { + result = getDropReference((EObject)target, objectToDrop) != null; + + if (result && (getCurrentEvent().operations | DND.DROP_COPY) != 0) + { + overrideOperation(DND.DROP_COPY); + } + } + } + + return result; + } + + @Override + public boolean performDrop(Object data) + { + IStructuredSelection selection = (IStructuredSelection)data; + EObject objectToDrop = UIUtil.getElement(selection, EObject.class); + EObject target = (EObject)getCurrentTarget(); + + Command command = AddCommand.create(getEditingDomain(), target, getDropReference(target, objectToDrop), + selection.toList()); + + boolean result = execute(command); + if (result) + { + viewer.getControl().setFocus(); + viewer.setSelection(new StructuredSelection(target)); + } + + return result; + } + + private EObject getObjectToDrop(TransferData transferType) + { + return UIUtil.getElement(LocalSelectionTransfer.getTransfer().getSelection(), EObject.class); + } + }); + } + + protected EReference getDropReference(EObject target, EObject objectToDrop) + { + return null; + } + + protected boolean execute(Command command) + { + boolean result = command.canExecute(); + + if (result) + { + getEditingDomain().getCommandStack().execute(command); + } + + return result; + } + + protected void checkForUnsupportedModelContent() + { + if (getInput() == null) + { + getManagedForm().getMessageManager().addMessage(this, Messages.TableSection_2, null, IStatus.WARNING, + viewer.getControl()); + } + else + { + // anything not matching filters? + if (viewer.getTable().getItemCount() < getInput().getItems().size()) + { + getManagedForm().getMessageManager().addMessage(this, Messages.TableSection_3, null, IStatus.WARNING, + viewer.getControl()); + } + } + } +} diff --git a/plugins/org.eclipse.emf.cdo.security.ui/src/org/eclipse/emf/cdo/internal/security/ui/editor/UserDetailsPage.java b/plugins/org.eclipse.emf.cdo.security.ui/src/org/eclipse/emf/cdo/internal/security/ui/editor/UserDetailsPage.java new file mode 100644 index 0000000000..b5d6e29bcd --- /dev/null +++ b/plugins/org.eclipse.emf.cdo.security.ui/src/org/eclipse/emf/cdo/internal/security/ui/editor/UserDetailsPage.java @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2004-2013 Eike Stepper (Berlin, Germany), CEA LIST, 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: + * Christian W. Damus (CEA LIST) - initial API and implementation + */ +package org.eclipse.emf.cdo.internal.security.ui.editor; + +import org.eclipse.emf.cdo.internal.security.ui.messages.Messages; +import org.eclipse.emf.cdo.security.SecurityPackage; +import org.eclipse.emf.cdo.security.User; + +import org.eclipse.emf.common.notify.AdapterFactory; +import org.eclipse.emf.edit.domain.EditingDomain; + +import org.eclipse.swt.widgets.Composite; +import org.eclipse.ui.forms.widgets.FormToolkit; + +/** + * + */ +public class UserDetailsPage extends AbstractDetailsPage<User> +{ + + public UserDetailsPage(EditingDomain domain, AdapterFactory adapterFactory) + { + super(User.class, SecurityPackage.Literals.USER, domain, adapterFactory); + } + + @Override + protected void createContents(Composite parent, FormToolkit toolkit) + { + super.createContents(parent, toolkit); + + text(parent, toolkit, Messages.UserDetailsPage_0, SecurityPackage.Literals.ASSIGNEE__ID); + + text(parent, toolkit, Messages.UserDetailsPage_1, SecurityPackage.Literals.USER__FIRST_NAME); + text(parent, toolkit, Messages.UserDetailsPage_2, SecurityPackage.Literals.USER__LAST_NAME); + text(parent, toolkit, Messages.UserDetailsPage_3, SecurityPackage.Literals.USER__LABEL); + text(parent, toolkit, Messages.UserDetailsPage_4, SecurityPackage.Literals.USER__EMAIL); + + space(parent, toolkit); + + checkbox(parent, toolkit, Messages.UserDetailsPage_5, SecurityPackage.Literals.USER__LOCKED); + + space(parent, toolkit); + + combo(parent, toolkit, Messages.UserDetailsPage_6, SecurityPackage.Literals.USER__DEFAULT_ACCESS_OVERRIDE); + + space(parent, toolkit); + + oneToMany(parent, toolkit, Messages.UserDetailsPage_7, SecurityPackage.Literals.USER__GROUPS); + + oneToMany(parent, toolkit, Messages.UserDetailsPage_8, SecurityPackage.Literals.ASSIGNEE__ROLES); + } + +} diff --git a/plugins/org.eclipse.emf.cdo.security.ui/src/org/eclipse/emf/cdo/internal/security/ui/editor/UsersSection.java b/plugins/org.eclipse.emf.cdo.security.ui/src/org/eclipse/emf/cdo/internal/security/ui/editor/UsersSection.java new file mode 100644 index 0000000000..e12a7e56d6 --- /dev/null +++ b/plugins/org.eclipse.emf.cdo.security.ui/src/org/eclipse/emf/cdo/internal/security/ui/editor/UsersSection.java @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2004-2013 Eike Stepper (Berlin, Germany), CEA LIST, 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: + * Christian W. Damus (CEA LIST) - initial API and implementation + */ +package org.eclipse.emf.cdo.internal.security.ui.editor; + +import org.eclipse.emf.cdo.internal.security.ui.messages.Messages; +import org.eclipse.emf.cdo.security.Group; +import org.eclipse.emf.cdo.security.Role; +import org.eclipse.emf.cdo.security.SecurityPackage; +import org.eclipse.emf.cdo.security.User; + +import org.eclipse.emf.common.notify.AdapterFactory; +import org.eclipse.emf.ecore.EObject; +import org.eclipse.emf.ecore.EReference; +import org.eclipse.emf.edit.domain.EditingDomain; + +/** + * + */ +public class UsersSection extends TableSection<User> +{ + + public UsersSection(EditingDomain domain, AdapterFactory adapterFactory) + { + super(User.class, SecurityPackage.Literals.USER, domain, adapterFactory); + } + + @Override + protected String getTitle() + { + return Messages.UsersSection_0; + } + + @Override + protected EReference getDropReference(EObject target, EObject objectToDrop) + { + EReference result = null; + + if (objectToDrop instanceof Group) + { + result = SecurityPackage.Literals.USER__GROUPS; + } + else if (objectToDrop instanceof Role) + { + result = SecurityPackage.Literals.ASSIGNEE__ROLES; + } + + return result; + } +} diff --git a/plugins/org.eclipse.emf.cdo.security.ui/src/org/eclipse/emf/cdo/internal/security/ui/messages/Messages.java b/plugins/org.eclipse.emf.cdo.security.ui/src/org/eclipse/emf/cdo/internal/security/ui/messages/Messages.java new file mode 100644 index 0000000000..00a58d1469 --- /dev/null +++ b/plugins/org.eclipse.emf.cdo.security.ui/src/org/eclipse/emf/cdo/internal/security/ui/messages/Messages.java @@ -0,0 +1,116 @@ +/* + * Copyright (c) 2004-2013 Eike Stepper (Berlin, Germany), CEA LIST, 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: + * Christian W. Damus (CEA LIST) - initial API and implementation + */ +package org.eclipse.emf.cdo.internal.security.ui.messages; + +import org.eclipse.osgi.util.NLS; + +/** + * + */ +public class Messages extends NLS +{ + private static final String BUNDLE_NAME = "org.eclipse.emf.cdo.internal.security.ui.messages.messages"; //$NON-NLS-1$ + + public static String AbstractDetailsPage_0; + + public static String AbstractDetailsPage_3; + + public static String CDOSecurityFormEditor_0; + + public static String CDOSecurityFormEditor_1; + + public static String CDOSecurityPage_1; + + public static String CDOSecurityPage_2; + + public static String CDOSecurityPage_3; + + public static String CDOSecurityPage_4; + + public static String EmptyDetailsPage_0; + + public static String EmptyDetailsPage_1; + + public static String GroupDetailsPage_0; + + public static String GroupDetailsPage_1; + + public static String GroupDetailsPage_2; + + public static String GroupsSection_0; + + public static String ManageSecurityHandler_0; + + public static String ManageSecurityHandler_1; + + public static String ManageSecurityHandler_2; + + public static String OneToManyBlock_0; + + public static String OneToManyBlock_1; + + public static String OneToManyBlock_2; + + public static String OneToManyBlock_3; + + public static String RoleDetailsPage_0; + + public static String RoleDetailsPage_1; + + public static String RoleDetailsPage_2; + + public static String RoleDetailsPage_3; + + public static String RoleDetailsPage_4; + + public static String RoleDetailsPage_5; + + public static String RoleDetailsPage_6; + + public static String RoleDetailsPage_7; + + public static String RoleDetailsPage_8; + + public static String RolesSection_0; + + public static String TableSection_2; + + public static String TableSection_3; + + public static String UserDetailsPage_0; + + public static String UserDetailsPage_1; + + public static String UserDetailsPage_2; + + public static String UserDetailsPage_3; + + public static String UserDetailsPage_4; + + public static String UserDetailsPage_5; + + public static String UserDetailsPage_6; + + public static String UserDetailsPage_7; + + public static String UserDetailsPage_8; + + public static String UsersSection_0; + static + { + // initialize resource bundle + NLS.initializeMessages(BUNDLE_NAME, Messages.class); + } + + private Messages() + { + } +} diff --git a/plugins/org.eclipse.emf.cdo.security.ui/src/org/eclipse/emf/cdo/internal/security/ui/messages/messages.properties b/plugins/org.eclipse.emf.cdo.security.ui/src/org/eclipse/emf/cdo/internal/security/ui/messages/messages.properties new file mode 100644 index 0000000000..e49344fb43 --- /dev/null +++ b/plugins/org.eclipse.emf.cdo.security.ui/src/org/eclipse/emf/cdo/internal/security/ui/messages/messages.properties @@ -0,0 +1,52 @@ +# Copyright (c) 2013 Eike Stepper (Berlin, Germany), CEA LIST, 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: +# Christian W. Damus (CEA LIST) - initial API and implementation + +AbstractDetailsPage_0={0} Details +AbstractDetailsPage_3=Revert to default +CDOSecurityFormEditor_0=Save Failed +CDOSecurityFormEditor_1=Error committing changes to the repository. +CDOSecurityPage_1=Manage Security +CDOSecurityPage_2=Security Management +CDOSecurityPage_3=The security resource or the current repository view is read-only. +CDOSecurityPage_4=No security model found. +EmptyDetailsPage_0=Selection Details +EmptyDetailsPage_1=No object is currently selected. +GroupDetailsPage_0=Group ID: +GroupDetailsPage_1=Users: +GroupDetailsPage_2=Roles: +GroupsSection_0=Groups +ManageSecurityHandler_0=Manage Security +ManageSecurityHandler_1=Cannot open a view to edit the security model. +ManageSecurityHandler_2=No security model resource available in this repository. +OneToManyBlock_0=New +OneToManyBlock_1=Add... +OneToManyBlock_2=Remove +OneToManyBlock_3=Add {0} +RoleDetailsPage_0=Role Name: +RoleDetailsPage_1=Resource Permissions: +RoleDetailsPage_2=Groups: +RoleDetailsPage_3=Users: +RoleDetailsPage_4=Choose a resource node to which to grant access. +RoleDetailsPage_5=Access +RoleDetailsPage_6=Kind +RoleDetailsPage_7=Path Filter +RoleDetailsPage_8=Browse Resources +RolesSection_0=Roles +TableSection_2=Cannot find corresponding directory in the security model. +TableSection_3=Some items cannot be managed in this editor. They may be accessed using the generated tree editor. +UserDetailsPage_0=User ID: +UserDetailsPage_1=First Name: +UserDetailsPage_2=Last Name: +UserDetailsPage_3=Label: +UserDetailsPage_4=E-mail: +UserDetailsPage_5=Locked +UserDetailsPage_6=Access Override: +UserDetailsPage_7=Groups: +UserDetailsPage_8=Roles: +UsersSection_0=Users diff --git a/plugins/org.eclipse.emf.cdo.security.ui/src/org/eclipse/emf/cdo/internal/security/ui/util/ActionBarsHelper.java b/plugins/org.eclipse.emf.cdo.security.ui/src/org/eclipse/emf/cdo/internal/security/ui/util/ActionBarsHelper.java new file mode 100644 index 0000000000..16ecb92ab6 --- /dev/null +++ b/plugins/org.eclipse.emf.cdo.security.ui/src/org/eclipse/emf/cdo/internal/security/ui/util/ActionBarsHelper.java @@ -0,0 +1,130 @@ +/* + * Copyright (c) 2004-2013 Eike Stepper (Berlin, Germany), CEA LIST, 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: + * Christian W. Damus (CEA LIST) - initial API and implementation + */ +package org.eclipse.emf.cdo.internal.security.ui.util; + +import org.eclipse.jface.action.IAction; +import org.eclipse.jface.viewers.ISelectionChangedListener; +import org.eclipse.jface.viewers.ISelectionProvider; +import org.eclipse.jface.viewers.SelectionChangedEvent; +import org.eclipse.jface.viewers.Viewer; +import org.eclipse.swt.events.DisposeEvent; +import org.eclipse.swt.events.DisposeListener; +import org.eclipse.swt.events.FocusEvent; +import org.eclipse.swt.events.FocusListener; +import org.eclipse.swt.widgets.Control; +import org.eclipse.ui.IActionBars; + +import java.util.Map; + +/** + * + */ +public class ActionBarsHelper +{ + private final IActionBars bars; + + private final Map<String, IAction> globalActions = new java.util.HashMap<String, IAction>(); + + private final Map<String, IAction> previousActions = new java.util.HashMap<String, IAction>(); + + public ActionBarsHelper(IActionBars actionBars) + { + bars = actionBars; + } + + public ActionBarsHelper addGlobalAction(String actionID, IAction action) + { + globalActions.put(actionID, action); + return this; + } + + public ActionBarsHelper install(Viewer viewer) + { + return install(viewer.getControl(), viewer); + } + + public ActionBarsHelper install(Control control) + { + return install(control, null); + } + + private ActionBarsHelper install(Control control, final ISelectionProvider selectionProvider) + { + control.addFocusListener(new FocusListener() + { + + public void focusLost(FocusEvent e) + { + unsetGlobalActions(); + bars.updateActionBars(); + } + + public void focusGained(FocusEvent e) + { + updateActions(); + setGlobalActions(); + bars.updateActionBars(); + } + + private void updateActions() + { + if (selectionProvider != null) + { + SelectionChangedEvent selectionEvent = null; + + for (IAction next : globalActions.values()) + { + if (next instanceof ISelectionChangedListener) + { + if (selectionEvent == null) + { + selectionEvent = new SelectionChangedEvent(selectionProvider, selectionProvider.getSelection()); + } + ((ISelectionChangedListener)next).selectionChanged(selectionEvent); + } + } + } + } + }); + + control.addDisposeListener(new DisposeListener() + { + + public void widgetDisposed(DisposeEvent e) + { + globalActions.clear(); + previousActions.clear(); + } + }); + + return this; + } + + protected void setGlobalActions() + { + previousActions.clear(); + + for (Map.Entry<String, IAction> next : globalActions.entrySet()) + { + previousActions.put(next.getKey(), bars.getGlobalActionHandler(next.getKey())); + bars.setGlobalActionHandler(next.getKey(), next.getValue()); + } + } + + protected void unsetGlobalActions() + { + for (Map.Entry<String, IAction> next : previousActions.entrySet()) + { + bars.setGlobalActionHandler(next.getKey(), next.getValue()); + } + previousActions.clear(); + } +} diff --git a/plugins/org.eclipse.emf.cdo.security.ui/src/org/eclipse/emf/cdo/internal/security/ui/util/EditableDialogCellEditor.java b/plugins/org.eclipse.emf.cdo.security.ui/src/org/eclipse/emf/cdo/internal/security/ui/util/EditableDialogCellEditor.java new file mode 100644 index 0000000000..c5005c7381 --- /dev/null +++ b/plugins/org.eclipse.emf.cdo.security.ui/src/org/eclipse/emf/cdo/internal/security/ui/util/EditableDialogCellEditor.java @@ -0,0 +1,88 @@ +/* + * Copyright (c) 2004-2013 Eike Stepper (Berlin, Germany), CEA LIST, 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: + * Christian W. Damus (CEA LIST) - initial API and implementation + */ +package org.eclipse.emf.cdo.internal.security.ui.util; + +import org.eclipse.jface.viewers.DialogCellEditor; +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.SelectionAdapter; +import org.eclipse.swt.events.SelectionEvent; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; +import org.eclipse.swt.widgets.Text; + +import java.text.MessageFormat; + +/** + * A dialog cell editor in which the text field is editable: the user can directly edit the value without opening the dialog. + */ +public abstract class EditableDialogCellEditor extends DialogCellEditor +{ + + private Text text; + + public EditableDialogCellEditor() + { + } + + public EditableDialogCellEditor(Composite parent) + { + super(parent); + } + + public EditableDialogCellEditor(Composite parent, int style) + { + super(parent, style); + } + + @Override + protected Control createContents(Composite cell) + { + text = new Text(cell, SWT.SINGLE); + text.setFont(cell.getFont()); + text.setBackground(cell.getBackground()); + + text.addSelectionListener(new SelectionAdapter() + { + @Override + public void widgetDefaultSelected(SelectionEvent e) + { + String newValue = text.getText(); + + if (isCorrect(newValue)) + { + markDirty(); + doSetValue(newValue); + } + else + { + setErrorMessage(MessageFormat.format(getErrorMessage(), new Object[] { newValue.toString() })); + } + fireApplyEditorValue(); + deactivate(); + } + }); + + return text; + } + + @Override + protected void updateContents(Object value) + { + text.setText(value == null ? "" : value.toString()); //$NON-NLS-1$ + } + + @Override + public void setFocus() + { + text.setFocus(); + } + +} diff --git a/plugins/org.eclipse.emf.cdo.security.ui/src/org/eclipse/emf/cdo/internal/security/ui/util/INewObjectConfigurator.java b/plugins/org.eclipse.emf.cdo.security.ui/src/org/eclipse/emf/cdo/internal/security/ui/util/INewObjectConfigurator.java new file mode 100644 index 0000000000..a09cdc1d86 --- /dev/null +++ b/plugins/org.eclipse.emf.cdo.security.ui/src/org/eclipse/emf/cdo/internal/security/ui/util/INewObjectConfigurator.java @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2004-2013 Eike Stepper (Berlin, Germany), CEA LIST, 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: + * Christian W. Damus (CEA LIST) - initial API and implementation + */ +package org.eclipse.emf.cdo.internal.security.ui.util; + +import org.eclipse.emf.common.command.Command; + +/** + * + */ +public interface INewObjectConfigurator +{ + Command createConfigureCommand(Object newObject); +} diff --git a/plugins/org.eclipse.emf.cdo.security.ui/src/org/eclipse/emf/cdo/internal/security/ui/util/ObjectExistsConverter.java b/plugins/org.eclipse.emf.cdo.security.ui/src/org/eclipse/emf/cdo/internal/security/ui/util/ObjectExistsConverter.java new file mode 100644 index 0000000000..20a6938451 --- /dev/null +++ b/plugins/org.eclipse.emf.cdo.security.ui/src/org/eclipse/emf/cdo/internal/security/ui/util/ObjectExistsConverter.java @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2004-2013 Eike Stepper (Berlin, Germany), CEA LIST, 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: + * Christian W. Damus (CEA LIST) - initial API and implementation + */ +package org.eclipse.emf.cdo.internal.security.ui.util; + +import org.eclipse.core.databinding.UpdateValueStrategy; +import org.eclipse.core.databinding.conversion.Converter; + +/** + * + */ +public class ObjectExistsConverter extends Converter +{ + + public ObjectExistsConverter() + { + super(Object.class, Boolean.class); + } + + public Object convert(Object fromObject) + { + return fromObject != null && SecurityModelUtil.isEditable(fromObject); + } + + public static UpdateValueStrategy createUpdateValueStrategy() + { + UpdateValueStrategy result = new UpdateValueStrategy(); + result.setConverter(new ObjectExistsConverter()); + return result; + } +} diff --git a/plugins/org.eclipse.emf.cdo.security.ui/src/org/eclipse/emf/cdo/internal/security/ui/util/OneToManyBlock.java b/plugins/org.eclipse.emf.cdo.security.ui/src/org/eclipse/emf/cdo/internal/security/ui/util/OneToManyBlock.java new file mode 100644 index 0000000000..72886879e5 --- /dev/null +++ b/plugins/org.eclipse.emf.cdo.security.ui/src/org/eclipse/emf/cdo/internal/security/ui/util/OneToManyBlock.java @@ -0,0 +1,569 @@ +/* + * Copyright (c) 2004-2013 Eike Stepper (Berlin, Germany), CEA LIST, 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: + * Christian W. Damus (CEA LIST) - initial API and implementation + */ +package org.eclipse.emf.cdo.internal.security.ui.util; + +import static org.eclipse.emf.cdo.internal.security.ui.util.SecurityModelUtil.applyTypeFilter; +import static org.eclipse.emf.cdo.internal.security.ui.util.SecurityModelUtil.viewerFilter; + +import org.eclipse.emf.cdo.internal.security.ui.actions.SelectionListenerAction; +import org.eclipse.emf.cdo.internal.security.ui.messages.Messages; +import org.eclipse.emf.cdo.security.Directory; +import org.eclipse.emf.cdo.security.Realm; +import org.eclipse.emf.cdo.security.SecurityItem; +import org.eclipse.emf.cdo.security.SecurityPackage; +import org.eclipse.emf.cdo.security.provider.SecurityEditPlugin; +import org.eclipse.emf.cdo.ui.shared.SharedIcons; + +import org.eclipse.emf.common.command.Command; +import org.eclipse.emf.common.command.IdentityCommand; +import org.eclipse.emf.common.notify.AdapterFactory; +import org.eclipse.emf.databinding.edit.EMFEditObservables; +import org.eclipse.emf.ecore.EClass; +import org.eclipse.emf.ecore.EReference; +import org.eclipse.emf.ecore.util.EcoreUtil; +import org.eclipse.emf.edit.command.AddCommand; +import org.eclipse.emf.edit.command.CommandParameter; +import org.eclipse.emf.edit.command.CreateChildCommand; +import org.eclipse.emf.edit.command.DeleteCommand; +import org.eclipse.emf.edit.command.RemoveCommand; +import org.eclipse.emf.edit.domain.AdapterFactoryEditingDomain; +import org.eclipse.emf.edit.domain.EditingDomain; +import org.eclipse.emf.edit.ui.celleditor.FeatureEditorDialog; + +import org.eclipse.core.databinding.DataBindingContext; +import org.eclipse.core.databinding.observable.Observables; +import org.eclipse.core.databinding.observable.list.IObservableList; +import org.eclipse.core.databinding.observable.value.IObservableValue; +import org.eclipse.core.databinding.observable.value.WritableValue; +import org.eclipse.jface.databinding.swt.SWTObservables; +import org.eclipse.jface.databinding.viewers.ObservableListContentProvider; +import org.eclipse.jface.databinding.viewers.ViewersObservables; +import org.eclipse.jface.layout.TableColumnLayout; +import org.eclipse.jface.util.LocalSelectionTransfer; +import org.eclipse.jface.viewers.IFilter; +import org.eclipse.jface.viewers.ISelection; +import org.eclipse.jface.viewers.IStructuredSelection; +import org.eclipse.jface.viewers.StructuredSelection; +import org.eclipse.jface.viewers.TableViewer; +import org.eclipse.jface.window.Window; +import org.eclipse.osgi.util.NLS; +import org.eclipse.swt.SWT; +import org.eclipse.swt.dnd.DND; +import org.eclipse.swt.dnd.DropTargetAdapter; +import org.eclipse.swt.dnd.DropTargetEvent; +import org.eclipse.swt.dnd.Transfer; +import org.eclipse.swt.events.SelectionAdapter; +import org.eclipse.swt.events.SelectionEvent; +import org.eclipse.swt.layout.FillLayout; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Button; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Table; +import org.eclipse.ui.IActionBars; +import org.eclipse.ui.actions.ActionFactory; +import org.eclipse.ui.forms.widgets.FormToolkit; + +import java.util.Collections; +import java.util.Iterator; +import java.util.List; + +/** + * + */ +public class OneToManyBlock +{ + + private final EditingDomain domain; + + private final AdapterFactory adapterFactory; + + private final DataBindingContext context; + + private final IObservableValue input; + + private final IOneToManyConfiguration configuration; + + private IObservableList value; + + private TableViewer viewer; + + private INewObjectConfigurator newObjectConfigurator; + + private IActionBars editorActionBars; + + public OneToManyBlock(DataBindingContext context, EditingDomain domain, AdapterFactory adapterFactory, + EReference reference) + { + this(context, domain, adapterFactory, new OneToManyConfiguration(reference)); + } + + public OneToManyBlock(DataBindingContext context, EditingDomain domain, AdapterFactory adapterFactory, + EReference reference, EClass itemType) + { + + this(context, domain, adapterFactory, new OneToManyConfiguration(reference, itemType)); + } + + public OneToManyBlock(DataBindingContext context, EditingDomain domain, AdapterFactory adapterFactory, + IOneToManyConfiguration blockConfig) + { + this.context = context; + this.domain = domain; + this.adapterFactory = adapterFactory; + configuration = blockConfig; + input = new WritableValue(context.getValidationRealm()); + } + + protected IOneToManyConfiguration getConfiguration() + { + return configuration; + } + + protected boolean isTable() + { + return false; + } + + public void setEditorActionBars(IActionBars actionBars) + { + editorActionBars = actionBars; + } + + public void createControl(Composite parent, FormToolkit toolkit) + { + final EReference reference = getConfiguration().getModelReference(); + final EClass itemType = getConfiguration().getItemType(); + + parent.setLayout(new GridLayout(2, false)); + + Composite tableParent; + TableColumnLayout tableLayout = null; + if (isTable()) + { + tableParent = toolkit.createComposite(parent); + tableLayout = new TableColumnLayout(); + tableParent.setLayout(tableLayout); + } + else + { + tableParent = parent; + } + + Table table = toolkit.createTable(tableParent, SWT.H_SCROLL | SWT.V_SCROLL | SWT.SINGLE); + viewer = new TableViewer(table); + + if (isTable()) + { + tableParent.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); + configureColumns(viewer, tableLayout); + } + else + { + table.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); + viewer.setLabelProvider(new TableLabelProvider(adapterFactory)); + } + + viewer.setContentProvider(new ObservableListContentProvider()); + SecurityModelUtil.applyDefaultFilters(viewer, itemType); + if (itemType != reference.getEReferenceType()) + { + applyTypeFilter(viewer, itemType); + } + if (getConfiguration().getItemFilter() != null) + { + viewer.addFilter(viewerFilter(getConfiguration().getItemFilter())); + } + + viewer.setInput(value); + + if (!reference.isContainment()) + { + configureDropSupport(viewer); + } + + context.bindValue(SWTObservables.observeEnabled(viewer.getControl()), input, null, + ObjectExistsConverter.createUpdateValueStrategy()); + + Composite buttons = toolkit.createComposite(parent); + FillLayout fill = new FillLayout(SWT.VERTICAL); + fill.spacing = 5; + buttons.setLayout(fill); + buttons.setLayoutData(new GridData(SWT.LEFT, SWT.TOP, false, false)); + + Button newButton = null; + Button addButton = null; + Button removeButton = null; + + newButton = toolkit.createButton(buttons, Messages.OneToManyBlock_0, SWT.PUSH); + if (!reference.isContainment()) + { + addButton = toolkit.createButton(buttons, Messages.OneToManyBlock_1, SWT.PUSH); + } + removeButton = toolkit.createButton(buttons, Messages.OneToManyBlock_2, SWT.PUSH); + + final IObservableValue selection = ViewersObservables.observeSingleSelection(viewer); + + context.bindValue(SWTObservables.observeEnabled(newButton), input, null, + ObjectExistsConverter.createUpdateValueStrategy()); + if (addButton != null) + { + context.bindValue(SWTObservables.observeEnabled(addButton), input, null, + ObjectExistsConverter.createUpdateValueStrategy()); + } + context.bindValue(SWTObservables.observeEnabled(removeButton), selection, null, + ObjectExistsConverter.createUpdateValueStrategy()); + + newButton.addSelectionListener(new SelectionAdapter() + { + @Override + public void widgetSelected(SelectionEvent e) + { + Realm realm = ((SecurityItem)input.getValue()).getRealm(); + + Object owner; + if (reference.isContainment()) + { + owner = input.getValue(); + } + else + { + owner = SecurityModelUtil.getDirectory(realm, itemType); + } + + if (owner != null) + { + // create a new object in the appropriate owner and add it to the reference list if that's not the containment + Object child = EcoreUtil.create(itemType); + + CommandParameter param; + Command addToReference; + + if (reference.isContainment()) + { + param = new CommandParameter(owner, reference, child); + addToReference = IdentityCommand.INSTANCE; + } + else + { + param = new CommandParameter(owner, SecurityPackage.Literals.DIRECTORY__ITEMS, child); + addToReference = AddCommand.create(domain, input.getValue(), reference, Collections.singleton(child)); + } + + Command command = CreateChildCommand.create(domain, owner, param, Collections.singleton(owner)); + command = command.chain(addToReference); + + if (getNewObjectConfigurator() != null) + { + command = command.chain(getNewObjectConfigurator().createConfigureCommand(child)); + } + + if (execute(command)) + { + viewer.setSelection(new StructuredSelection(child)); + viewer.getControl().setFocus(); + viewer.refresh(child); + } + } + } + }); + + if (addButton != null) + { + addButton.addSelectionListener(new SelectionAdapter() + { + @Override + public void widgetSelected(SelectionEvent e) + { + Realm realm = ((SecurityItem)input.getValue()).getRealm(); + Directory directory = SecurityModelUtil.getDirectory(realm, itemType); + if (directory != null) + { + // get the available items not already in our input's reference list + List<?> available = new java.util.ArrayList<Object>(EcoreUtil.getObjectsByType(directory.getItems(), + itemType)); + available.removeAll(value); + SecurityModelUtil.applyDefaultFilters(available, itemType); + + String label = NLS.bind(Messages.OneToManyBlock_3, SecurityEditPlugin.INSTANCE.getString(String.format( + "_UI_%s_%s_feature", reference.getEContainingClass().getName(), reference.getName()))); //$NON-NLS-1$ + FeatureEditorDialog dlg = new FeatureEditorDialog(viewer.getControl().getShell(), new TableLabelProvider( + adapterFactory), input.getValue(), reference.getEContainingClass(), Collections.EMPTY_LIST, label, + available, false, true, true); + if (dlg.open() == Window.OK && !dlg.getResult().isEmpty()) + { + Command command = AddCommand.create(domain, input.getValue(), reference, dlg.getResult()); + if (execute(command)) + { + viewer.setSelection(new StructuredSelection(dlg.getResult())); + viewer.getControl().setFocus(); + } + } + } + } + }); + } + + final SelectionListenerAction removeAction = new SelectionListenerAction(Messages.OneToManyBlock_2, + SharedIcons.getDescriptor("etool16/delete.gif")) //$NON-NLS-1$ + { + @Override + public void run() + { + Object selected = selection.getValue(); + if (selected != null) + { + Command command; + + if (reference.isContainment()) + { + command = DeleteCommand.create(domain, selection.getValue()); + } + else + { + command = RemoveCommand.create(domain, input.getValue(), reference, selection.getValue()); + } + + execute(command); + } + } + + @Override + protected boolean updateSelection(IStructuredSelection selection) + { + return super.updateSelection(selection) && SecurityModelUtil.isEditable(input.getValue()); + } + }; + removeButton.addSelectionListener(new SelectionAdapter() + { + @Override + public void widgetSelected(SelectionEvent e) + { + if (removeAction.isEnabled()) + { + removeAction.run(); + } + } + }); + viewer.addSelectionChangedListener(removeAction); + + new ActionBarsHelper(editorActionBars).addGlobalAction(ActionFactory.DELETE.getId(), removeAction).install(viewer); + } + + public void setInput(IObservableValue input) + { + if (input != null) + { + Observables.pipe(input, this.input); + } + + if (value != null) + { + if (viewer != null) + { + viewer.setInput(null); + } + value.dispose(); + } + + value = EMFEditObservables.observeDetailList(context.getValidationRealm(), domain, input, getConfiguration() + .getModelReference()); + + if (viewer != null) + { + viewer.setInput(value); + } + } + + protected boolean execute(Command command) + { + boolean result = command.canExecute(); + + if (result) + { + domain.getCommandStack().execute(command); + } + + return result; + } + + public void setNewObjectConfigurator(INewObjectConfigurator newObjectConfigurator) + { + this.newObjectConfigurator = newObjectConfigurator; + } + + public INewObjectConfigurator getNewObjectConfigurator() + { + return newObjectConfigurator; + } + + protected void configureColumns(TableViewer viewer, TableColumnLayout layout) + { + // pass + } + + private boolean canPresent(Object object) + { + IOneToManyConfiguration config = getConfiguration(); + boolean result = config.getItemType().isInstance(object); + + if (result && config.getItemFilter() != null) + { + result = config.getItemFilter().select(object); + } + + if (result) + { + // last check: cannot drop something from a different editing domain + result = AdapterFactoryEditingDomain.getEditingDomainFor(object) == domain; + } + + return result; + } + + private boolean canPresentAll(ISelection selection) + { + boolean result = selection != null && !selection.isEmpty(); + + if (result && selection instanceof IStructuredSelection) + { + for (Iterator<?> iter = ((IStructuredSelection)selection).iterator(); result && iter.hasNext();) + { + result = canPresent(iter.next()); + } + } + + return result; + } + + protected void configureDropSupport(final TableViewer viewer) + { + viewer.addDropSupport(DND.DROP_LINK | DND.DROP_MOVE | DND.DROP_COPY, + new Transfer[] { LocalSelectionTransfer.getTransfer() }, new DropTargetAdapter() + { + @Override + public void dragEnter(DropTargetEvent event) + { + if (!canDrop(event)) + { + // reject this drop + event.detail = DND.DROP_NONE; + } + else if ((event.operations | DND.DROP_COPY) != 0) + { + event.detail = DND.DROP_COPY; + } + } + + private boolean canDrop(DropTargetEvent event) + { + boolean result = false; + + if (LocalSelectionTransfer.getTransfer().isSupportedType(event.currentDataType)) + { + result = canPresentAll(LocalSelectionTransfer.getTransfer().getSelection()); + } + + return result; + } + + @Override + public void dropAccept(DropTargetEvent event) + { + if (!canDrop(event)) + { + // reject this drop + event.detail = DND.DROP_NONE; + } + else if ((event.operations | DND.DROP_COPY) != 0) + { + event.detail = DND.DROP_COPY; + } + } + + @Override + public void drop(DropTargetEvent event) + { + if (canDrop(event)) + { + IStructuredSelection selection = (IStructuredSelection)LocalSelectionTransfer.getTransfer() + .getSelection(); + Command command = AddCommand.create(domain, input.getValue(), getConfiguration().getModelReference(), + selection.toList()); + if (execute(command)) + { + viewer.setSelection(selection); + viewer.getControl().setFocus(); + } + } + } + }); + } + + // + // Nested types + // + + public static interface IOneToManyConfiguration + { + EReference getModelReference(); + + EClass getItemType(); + + IFilter getItemFilter(); + } + + public static class OneToManyConfiguration implements IOneToManyConfiguration + { + private final EReference reference; + + private final EClass itemType; + + private final IFilter filter; + + public OneToManyConfiguration(EReference reference) + { + this(reference, reference.getEReferenceType(), null); + } + + public OneToManyConfiguration(EReference reference, EClass itemType) + { + this(reference, itemType, null); + } + + public OneToManyConfiguration(EReference reference, IFilter filter) + { + this(reference, reference.getEReferenceType(), filter); + } + + public OneToManyConfiguration(EReference reference, EClass itemType, IFilter filter) + { + this.reference = reference; + this.itemType = itemType; + this.filter = filter; + } + + public EReference getModelReference() + { + return reference; + } + + public EClass getItemType() + { + return itemType; + } + + public IFilter getItemFilter() + { + return filter; + } + } +} diff --git a/plugins/org.eclipse.emf.cdo.security.ui/src/org/eclipse/emf/cdo/internal/security/ui/util/OneToManyTableBlock.java b/plugins/org.eclipse.emf.cdo.security.ui/src/org/eclipse/emf/cdo/internal/security/ui/util/OneToManyTableBlock.java new file mode 100644 index 0000000000..9177c5af18 --- /dev/null +++ b/plugins/org.eclipse.emf.cdo.security.ui/src/org/eclipse/emf/cdo/internal/security/ui/util/OneToManyTableBlock.java @@ -0,0 +1,157 @@ +/* + * Copyright (c) 2004-2013 Eike Stepper (Berlin, Germany), CEA LIST, 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: + * Christian W. Damus (CEA LIST) - initial API and implementation + */ +package org.eclipse.emf.cdo.internal.security.ui.util; + +import org.eclipse.emf.common.notify.AdapterFactory; +import org.eclipse.emf.ecore.EClass; +import org.eclipse.emf.ecore.EReference; +import org.eclipse.emf.edit.domain.EditingDomain; + +import org.eclipse.core.databinding.DataBindingContext; +import org.eclipse.jface.layout.TableColumnLayout; +import org.eclipse.jface.viewers.CellEditor; +import org.eclipse.jface.viewers.CellLabelProvider; +import org.eclipse.jface.viewers.ColumnWeightData; +import org.eclipse.jface.viewers.EditingSupport; +import org.eclipse.jface.viewers.IFilter; +import org.eclipse.jface.viewers.TableViewer; +import org.eclipse.jface.viewers.TableViewerColumn; +import org.eclipse.swt.SWT; + +/** + * + */ +public class OneToManyTableBlock extends OneToManyBlock +{ + + public OneToManyTableBlock(DataBindingContext context, EditingDomain domain, AdapterFactory adapterFactory, + ITableConfiguration tableConfig) + { + super(context, domain, adapterFactory, tableConfig); + } + + @Override + protected ITableConfiguration getConfiguration() + { + return (ITableConfiguration)super.getConfiguration(); + } + + @Override + protected boolean isTable() + { + return true; + } + + @Override + protected void configureColumns(final TableViewer viewer, TableColumnLayout layout) + { + super.configureColumns(viewer, layout); + + viewer.getTable().setHeaderVisible(true); + viewer.getTable().setLinesVisible(true); + + final ITableConfiguration tableConfig = getConfiguration(); + + String[] columnTitles = tableConfig.getColumnTitles(); + + for (int i = 0; i < columnTitles.length; i++) + { + TableViewerColumn column = new TableViewerColumn(viewer, SWT.LEFT); + column.getColumn().setText(columnTitles[i]); + layout.setColumnData( + column.getColumn(), + new ColumnWeightData(tableConfig.getColumnWeight(i), tableConfig.getColumnMinimumSize(i), tableConfig + .isColumnResizable(i))); + + final int columnIndex = i; + + column.setLabelProvider(tableConfig.getLabelProvider(viewer, columnIndex)); + + column.setEditingSupport(new EditingSupport(viewer) + { + + @Override + protected void setValue(Object element, Object value) + { + tableConfig.setValue(viewer, element, columnIndex, value); + } + + @Override + protected Object getValue(Object element) + { + return tableConfig.getValue(viewer, element, columnIndex); + } + + @Override + protected boolean canEdit(Object element) + { + return tableConfig.canEdit(viewer, element, columnIndex); + } + + @Override + protected CellEditor getCellEditor(Object element) + { + return tableConfig.getCellEditor(viewer, columnIndex); + } + }); + } + } + + // + // Nested types + // + + public static interface ITableConfiguration extends IOneToManyConfiguration + { + String[] getColumnTitles(); + + int getColumnWeight(int index); + + int getColumnMinimumSize(int index); + + boolean isColumnResizable(int index); + + CellLabelProvider getLabelProvider(TableViewer viewer, int columnIndex); + + boolean canEdit(TableViewer viewer, Object element, int columnIndex); + + void setValue(TableViewer viewer, Object element, int columnIndex, Object value); + + Object getValue(TableViewer viewer, Object element, int columnIndex); + + CellEditor getCellEditor(TableViewer viewer, int columnIndex); + } + + public static abstract class TableConfiguration extends OneToManyConfiguration implements ITableConfiguration + { + + public TableConfiguration(EReference reference, EClass itemType, IFilter filter) + { + super(reference, itemType, filter); + } + + public TableConfiguration(EReference reference, EClass itemType) + { + super(reference, itemType); + } + + public TableConfiguration(EReference reference, IFilter filter) + { + super(reference, filter); + } + + public TableConfiguration(EReference reference) + { + super(reference); + } + + } +} diff --git a/plugins/org.eclipse.emf.cdo.security.ui/src/org/eclipse/emf/cdo/internal/security/ui/util/ResourceBasedPermissionFilter.java b/plugins/org.eclipse.emf.cdo.security.ui/src/org/eclipse/emf/cdo/internal/security/ui/util/ResourceBasedPermissionFilter.java new file mode 100644 index 0000000000..4daeaa9a5c --- /dev/null +++ b/plugins/org.eclipse.emf.cdo.security.ui/src/org/eclipse/emf/cdo/internal/security/ui/util/ResourceBasedPermissionFilter.java @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2004-2013 Eike Stepper (Berlin, Germany), CEA LIST, 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: + * Christian W. Damus (CEA LIST) - initial API and implementation + */ +package org.eclipse.emf.cdo.internal.security.ui.util; + +import org.eclipse.emf.cdo.security.CombinedFilter; +import org.eclipse.emf.cdo.security.FilterPermission; +import org.eclipse.emf.cdo.security.PermissionFilter; +import org.eclipse.emf.cdo.security.ResourceFilter; + +import org.eclipse.jface.viewers.IFilter; + +/** + * + */ +public class ResourceBasedPermissionFilter implements IFilter +{ + + public ResourceBasedPermissionFilter() + { + } + + public boolean select(Object element) + { + boolean result = element instanceof FilterPermission; + + if (result) + { + FilterPermission perm = (FilterPermission)element; + for (PermissionFilter filter : perm.getFilters()) + { + if (!isResourceFilter(filter)) + { + result = false; + } + } + } + + return result; + } + + protected boolean isResourceFilter(PermissionFilter filter) + { + boolean result = filter instanceof ResourceFilter; + + if (!result && filter instanceof CombinedFilter) + { + result = true; // assume all operations are OK + CombinedFilter combined = (CombinedFilter)filter; + for (PermissionFilter next : combined.getOperands()) + { + result = isResourceFilter(next); + if (!result) + { + break; + } + } + } + + return result; + } +} diff --git a/plugins/org.eclipse.emf.cdo.security.ui/src/org/eclipse/emf/cdo/internal/security/ui/util/ResourceBasedRoleFilter.java b/plugins/org.eclipse.emf.cdo.security.ui/src/org/eclipse/emf/cdo/internal/security/ui/util/ResourceBasedRoleFilter.java new file mode 100644 index 0000000000..da98ab3ed1 --- /dev/null +++ b/plugins/org.eclipse.emf.cdo.security.ui/src/org/eclipse/emf/cdo/internal/security/ui/util/ResourceBasedRoleFilter.java @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2004-2013 Eike Stepper (Berlin, Germany), CEA LIST, 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: + * Christian W. Damus (CEA LIST) - initial API and implementation + */ +package org.eclipse.emf.cdo.internal.security.ui.util; + +import org.eclipse.emf.cdo.security.Permission; +import org.eclipse.emf.cdo.security.Role; + +import org.eclipse.jface.viewers.IFilter; + +/** + * + */ +public class ResourceBasedRoleFilter implements IFilter +{ + + private final ResourceBasedPermissionFilter permFilter = new ResourceBasedPermissionFilter(); + + public ResourceBasedRoleFilter() + { + } + + public boolean select(Object element) + { + boolean result = element instanceof Role; + + if (result) + { + Role role = (Role)element; + for (Permission next : role.getPermissions()) + { + if (!permFilter.select(next)) + { + result = false; + } + } + } + + return result; + } +} diff --git a/plugins/org.eclipse.emf.cdo.security.ui/src/org/eclipse/emf/cdo/internal/security/ui/util/SecurityModelUtil.java b/plugins/org.eclipse.emf.cdo.security.ui/src/org/eclipse/emf/cdo/internal/security/ui/util/SecurityModelUtil.java new file mode 100644 index 0000000000..b66b8a97ac --- /dev/null +++ b/plugins/org.eclipse.emf.cdo.security.ui/src/org/eclipse/emf/cdo/internal/security/ui/util/SecurityModelUtil.java @@ -0,0 +1,186 @@ +/* + * Copyright (c) 2004-2013 Eike Stepper (Berlin, Germany), CEA LIST, 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: + * Christian W. Damus (CEA LIST) - initial API and implementation + */ +package org.eclipse.emf.cdo.internal.security.ui.util; + +import org.eclipse.emf.cdo.CDOObject; +import org.eclipse.emf.cdo.security.Directory; +import org.eclipse.emf.cdo.security.Realm; +import org.eclipse.emf.cdo.security.SecurityItem; +import org.eclipse.emf.cdo.security.SecurityPackage; +import org.eclipse.emf.cdo.view.CDOView; + +import org.eclipse.emf.ecore.EClass; + +import org.eclipse.jface.viewers.IFilter; +import org.eclipse.jface.viewers.StructuredViewer; +import org.eclipse.jface.viewers.Viewer; +import org.eclipse.jface.viewers.ViewerFilter; + +import java.util.Arrays; +import java.util.Collection; +import java.util.Iterator; +import java.util.List; + +/** + * + */ +public class SecurityModelUtil +{ + + private SecurityModelUtil() + { + } + + public static Directory getDirectory(Realm realm, EClass itemType) + { + Directory result = null; + + String preferredName = itemType == SecurityPackage.Literals.GROUP ? "Groups" //$NON-NLS-1$ + : itemType == SecurityPackage.Literals.USER ? "Users" //$NON-NLS-1$ + : itemType == SecurityPackage.Literals.ROLE ? "Roles" //$NON-NLS-1$ + : ""; //$NON-NLS-1$ + + for (SecurityItem next : realm.getItems()) + { + if (next instanceof Directory) + { + Directory directory = (Directory)next; + if (preferredName.equals(directory.getName())) + { + result = (Directory)next; + break; + } + } + } + + return result; + } + + public static void applyDefaultFilters(StructuredViewer viewer, EClass itemType) + { + for (ViewerFilter next : getDefaultViewerFilters(itemType)) + { + viewer.addFilter(next); + } + } + + private static IFilter[] getDefaultFilters(EClass itemType) + { + IFilter[] result; + + if (itemType == SecurityPackage.Literals.ROLE) + { + result = new IFilter[] { new ResourceBasedRoleFilter() }; + } + else + { + result = new IFilter[0]; + } + + return result; + } + + private static IFilter filter(EClass itemType) + { + final IFilter[] filters = getDefaultFilters(itemType); + + return filters.length == 0 ? null : new IFilter() + { + public boolean select(Object toTest) + { + boolean result = true; + + for (int i = 0; i < filters.length && result; i++) + { + result = filters[i].select(toTest); + } + return result; + } + }; + } + + private static List<ViewerFilter> getDefaultViewerFilters(EClass itemType) + { + IFilter[] filters = getDefaultFilters(itemType); + + ViewerFilter[] result = new ViewerFilter[filters.length]; + for (int i = 0; i < filters.length; i++) + { + result[i] = viewerFilter(filters[i]); + } + + return Arrays.asList(result); + } + + public static ViewerFilter viewerFilter(final IFilter filter) + { + return new ViewerFilter() + { + + @Override + public boolean select(Viewer viewer, Object parentElement, Object element) + { + return filter.select(element); + } + }; + } + + public static void applyDefaultFilters(Collection<?> elements, EClass itemType) + { + IFilter filter = filter(itemType); + if (filter != null) + { + for (Iterator<?> iter = elements.iterator(); iter.hasNext();) + { + if (!filter.select(iter.next())) + { + iter.remove(); + } + } + } + } + + public static IFilter getTypeFilter(final EClass itemType) + { + return new IFilter() + { + public boolean select(Object toTest) + { + return itemType.isInstance(toTest); + } + }; + } + + public static void applyTypeFilter(StructuredViewer viewer, final EClass itemType) + { + viewer.addFilter(new ViewerFilter() + { + + @Override + public boolean select(Viewer viewer, Object parentElement, Object element) + { + return itemType.isInstance(element); + } + }); + } + + public static boolean isEditable(Object object) + { + return object instanceof CDOObject && isEditable((CDOObject)object); + } + + public static boolean isEditable(CDOObject object) + { + CDOView view = object.cdoView(); + return view == null || !view.isReadOnly(); + } + +} diff --git a/plugins/org.eclipse.emf.cdo.security.ui/src/org/eclipse/emf/cdo/internal/security/ui/util/TableLabelProvider.java b/plugins/org.eclipse.emf.cdo.security.ui/src/org/eclipse/emf/cdo/internal/security/ui/util/TableLabelProvider.java new file mode 100644 index 0000000000..b1cf0d4045 --- /dev/null +++ b/plugins/org.eclipse.emf.cdo.security.ui/src/org/eclipse/emf/cdo/internal/security/ui/util/TableLabelProvider.java @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2004-2013 Eike Stepper (Berlin, Germany), CEA LIST, 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: + * Christian W. Damus (CEA LIST) - initial API and implementation + */ +package org.eclipse.emf.cdo.internal.security.ui.util; + +import org.eclipse.emf.common.notify.AdapterFactory; +import org.eclipse.emf.edit.ui.provider.AdapterFactoryLabelProvider; + +import org.eclipse.swt.graphics.Image; + +/** + * + */ +public class TableLabelProvider extends AdapterFactoryLabelProvider +{ + + private int defaultColumnIndex; + + public TableLabelProvider(AdapterFactory adapterFactory) + { + this(adapterFactory, 0); + } + + public TableLabelProvider(AdapterFactory adapterFactory, int defaultColumnIndex) + { + super(adapterFactory); + this.defaultColumnIndex = defaultColumnIndex; + } + + protected final int defaultColumnIndex() + { + return 0; + } + + @Override + public String getColumnText(Object object, int columnIndex) + { + return columnIndex == defaultColumnIndex ? getText(object) : super.getColumnText(object, columnIndex); + } + + @Override + public Image getColumnImage(Object object, int columnIndex) + { + return columnIndex == defaultColumnIndex ? getImage(object) : super.getColumnImage(object, columnIndex); + } + +} diff --git a/plugins/org.eclipse.emf.cdo.security.ui/src/org/eclipse/emf/cdo/security/ui/ISecurityManagementContext.java b/plugins/org.eclipse.emf.cdo.security.ui/src/org/eclipse/emf/cdo/security/ui/ISecurityManagementContext.java new file mode 100644 index 0000000000..03d563fa47 --- /dev/null +++ b/plugins/org.eclipse.emf.cdo.security.ui/src/org/eclipse/emf/cdo/security/ui/ISecurityManagementContext.java @@ -0,0 +1,96 @@ +/* + * Copyright (c) 2004-2013 Eike Stepper (Berlin, Germany), CEA LIST, 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: + * Christian W. Damus (CEA LIST) - initial API and implementation + */ +package org.eclipse.emf.cdo.security.ui; + +import org.eclipse.emf.cdo.eresource.CDOResource; +import org.eclipse.emf.cdo.internal.security.ui.bundle.OM; +import org.eclipse.emf.cdo.security.User; +import org.eclipse.emf.cdo.session.CDOSession; +import org.eclipse.emf.cdo.transaction.CDOTransaction; +import org.eclipse.emf.cdo.view.CDOView; + +import org.eclipse.core.runtime.IAdaptable; + +/** + * An optional security-management context that may be provided as an {@linkplain IAdaptable adapter} + * by the view part to which the "Manage Security" command is contributed. + */ +public interface ISecurityManagementContext +{ + + ISecurityManagementContext DEFAULT = new Default(); + + /** + * Obtains a view in which to open the security resource for editing. If at all possible, this + * should be a writable {@linkplain CDOTransaction transaction}. If necessary, implementors are + * welcome to open a new session logged in as the Administrator for this purpose. + * + * @see #getSecurityResource(CDOView) + * @see #disconnect(CDOView) + */ + CDOView connect(CDOSession session); + + /** + * Releases a {@code view} previously {@linkplain #connect(CDOSession) obtained} from this context. + * The caller must not attempt to use the {@code view} after this point because in all likelihood + * it will be closed. + * + * @see #connect(CDOSession) + */ + void disconnect(CDOView view); + + /** + * Obtains the resource containing the security model for presentation in the Security Management + * editor. + */ + CDOResource getSecurityResource(CDOView view); + + // + // Nested types + // + + class Default implements ISecurityManagementContext + { + public CDOView connect(CDOSession session) + { + if (session.isClosed()) + { + return null; + } + if (User.ADMINISTRATOR.equals(session.getUserID())) + { + return session.openTransaction(); + } + return session.openView(); + } + + public void disconnect(CDOView view) + { + view.close(); + } + + public CDOResource getSecurityResource(CDOView view) + { + CDOResource result = null; + + try + { + result = view.getResource("/security"); //$NON-NLS-1$ + } + catch (Exception e) + { + OM.LOG.warn("Security model resource not available.", e); //$NON-NLS-1$ + } + + return result; + } + } +} diff --git a/plugins/org.eclipse.emf.cdo.ui/src/org/eclipse/emf/cdo/ui/CDOItemProvider.java b/plugins/org.eclipse.emf.cdo.ui/src/org/eclipse/emf/cdo/ui/CDOItemProvider.java index d7ea7e37af..e5127627ba 100644 --- a/plugins/org.eclipse.emf.cdo.ui/src/org/eclipse/emf/cdo/ui/CDOItemProvider.java +++ b/plugins/org.eclipse.emf.cdo.ui/src/org/eclipse/emf/cdo/ui/CDOItemProvider.java @@ -8,7 +8,7 @@ * Contributors: * Eike Stepper - initial API and implementation * Victor Roldan Betancort - maintenance - * Christian W. Damus (CEA LIST) - 399306 + * Christian W. Damus (CEA LIST) - 399306, 419805 */ package org.eclipse.emf.cdo.ui; @@ -182,7 +182,12 @@ public class CDOItemProvider extends ContainerItemProvider<IContainer<Object>> if (element instanceof CDOResourceFolder) { - return ((CDOResourceFolder)element).getNodes().toArray(); + CDOResourceFolder folder = (CDOResourceFolder)element; + if (folder.cdoPermission() == CDOPermission.NONE) + { + return NO_ELEMENTS; + } + return folder.getNodes().toArray(); } return super.getChildren(element); diff --git a/plugins/org.eclipse.net4j.util.ui/src/org/eclipse/net4j/util/ui/UIUtil.java b/plugins/org.eclipse.net4j.util.ui/src/org/eclipse/net4j/util/ui/UIUtil.java index 69de2b690b..1efd9a3c4d 100644 --- a/plugins/org.eclipse.net4j.util.ui/src/org/eclipse/net4j/util/ui/UIUtil.java +++ b/plugins/org.eclipse.net4j.util.ui/src/org/eclipse/net4j/util/ui/UIUtil.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007-2013 Eike Stepper (Berlin, Germany) and others. + * Copyright (c) 2007-2013 Eike Stepper (Berlin, Germany), CEA LIST, 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 @@ -8,6 +8,7 @@ * Contributors: * Eike Stepper - initial API and implementation * Victor Roldan Betancort - maintenance + * Christian W. Damus (CEA LIST) - 418452 */ package org.eclipse.net4j.util.ui; @@ -15,6 +16,7 @@ import org.eclipse.net4j.util.internal.ui.bundle.OM; import org.eclipse.net4j.util.security.IPasswordCredentialsProvider; import org.eclipse.net4j.util.ui.security.InteractiveCredentialsProvider; +import org.eclipse.core.runtime.IAdaptable; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.jface.fieldassist.FieldDecoration; import org.eclipse.jface.fieldassist.FieldDecorationRegistry; @@ -260,6 +262,29 @@ public final class UIUtil } /** + * Like {@link #getElement(ISelection, Class)} except that it attempts to adaptable + * {@link IAdaptable}s to the required {@code type}, if necessary. + * + * @since 3.4 + */ + public static <T> T adaptElement(ISelection selection, Class<T> type) + { + T result = null; + + Object element = getElement(selection); + if (type.isInstance(element)) + { + result = type.cast(element); + } + else if (element instanceof IAdaptable) + { + result = type.cast(((IAdaptable)element).getAdapter(type)); + } + + return result; + } + + /** * @since 2.0 */ public static <T> List<T> getElements(ISelection selection, Class<T> type) |