Skip to main content

This CGIT instance is deprecated, and repositories have been moved to Gitlab or Github. See the repository descriptions for specific locations.

summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChristian W. Damus2013-10-07 19:56:43 +0000
committerChristian W. Damus2013-10-25 20:54:55 +0000
commitb05dd88cb83225a8ff396d1ef12d3e5babdebb10 (patch)
tree313a161822e455a86a8cc83bb818c6ac9d9f0f0b /plugins/org.eclipse.emf.cdo.security.ui
parent5cf78af376366ec14722da2109f25aa552e9a00e (diff)
downloadcdo-b05dd88cb83225a8ff396d1ef12d3e5babdebb10.tar.gz
cdo-b05dd88cb83225a8ff396d1ef12d3e5babdebb10.tar.xz
cdo-b05dd88cb83225a8ff396d1ef12d3e5babdebb10.zip
[418452] [Security] Simplified security model editor
https://bugs.eclipse.org/bugs/show_bug.cgi?id=418452 Initial implementation of a simplified forms-based editor for the security realm.
Diffstat (limited to 'plugins/org.eclipse.emf.cdo.security.ui')
-rw-r--r--plugins/org.eclipse.emf.cdo.security.ui/.settings/org.eclipse.core.resources.prefs2
-rw-r--r--plugins/org.eclipse.emf.cdo.security.ui/.settings/org.eclipse.jdt.core.prefs22
-rw-r--r--plugins/org.eclipse.emf.cdo.security.ui/.settings/org.eclipse.pde.prefs5
-rw-r--r--plugins/org.eclipse.emf.cdo.security.ui/META-INF/MANIFEST.MF20
-rw-r--r--plugins/org.eclipse.emf.cdo.security.ui/build.properties24
-rw-r--r--plugins/org.eclipse.emf.cdo.security.ui/copyright.txt2
-rw-r--r--plugins/org.eclipse.emf.cdo.security.ui/icons/full/ctool16/ManageSecurity.pngbin0 -> 600 bytes
-rw-r--r--plugins/org.eclipse.emf.cdo.security.ui/icons/full/elcl16/advanced.gifbin0 -> 219 bytes
-rw-r--r--plugins/org.eclipse.emf.cdo.security.ui/icons/full/elcl16/revert.gifbin0 -> 582 bytes
-rw-r--r--plugins/org.eclipse.emf.cdo.security.ui/icons/full/obj16/SecurityRealmResource.pngbin0 -> 600 bytes
-rw-r--r--plugins/org.eclipse.emf.cdo.security.ui/icons/full/obj16/SecurityRealmResource.pxmbin0 -> 36867 bytes
-rw-r--r--plugins/org.eclipse.emf.cdo.security.ui/plugin.properties2
-rw-r--r--plugins/org.eclipse.emf.cdo.security.ui/plugin.xml39
-rw-r--r--plugins/org.eclipse.emf.cdo.security.ui/src/org/eclipse/emf/cdo/security/internal/ui/actions/SelectionListenerAction.java61
-rw-r--r--plugins/org.eclipse.emf.cdo.security.ui/src/org/eclipse/emf/cdo/security/internal/ui/bundle/OM.java51
-rw-r--r--plugins/org.eclipse.emf.cdo.security.ui/src/org/eclipse/emf/cdo/security/internal/ui/dialogs/FilterTreeSelectionDialog.java50
-rw-r--r--plugins/org.eclipse.emf.cdo.security.ui/src/org/eclipse/emf/cdo/security/internal/ui/editor/AbstractDetailsPage.java400
-rw-r--r--plugins/org.eclipse.emf.cdo.security.ui/src/org/eclipse/emf/cdo/security/internal/ui/editor/AbstractSectionPart.java216
-rw-r--r--plugins/org.eclipse.emf.cdo.security.ui/src/org/eclipse/emf/cdo/security/internal/ui/editor/CDOSecurityFormActionBarContributor.java122
-rw-r--r--plugins/org.eclipse.emf.cdo.security.ui/src/org/eclipse/emf/cdo/security/internal/ui/editor/CDOSecurityFormEditor.java247
-rw-r--r--plugins/org.eclipse.emf.cdo.security.ui/src/org/eclipse/emf/cdo/security/internal/ui/editor/CDOSecurityPage.java364
-rw-r--r--plugins/org.eclipse.emf.cdo.security.ui/src/org/eclipse/emf/cdo/security/internal/ui/editor/EClassDetailsPageProvider.java88
-rw-r--r--plugins/org.eclipse.emf.cdo.security.ui/src/org/eclipse/emf/cdo/security/internal/ui/editor/EmptyDetailsPage.java56
-rw-r--r--plugins/org.eclipse.emf.cdo.security.ui/src/org/eclipse/emf/cdo/security/internal/ui/editor/GroupDetailsPage.java50
-rw-r--r--plugins/org.eclipse.emf.cdo.security.ui/src/org/eclipse/emf/cdo/security/internal/ui/editor/GroupsSection.java59
-rw-r--r--plugins/org.eclipse.emf.cdo.security.ui/src/org/eclipse/emf/cdo/security/internal/ui/editor/RoleDetailsPage.java390
-rw-r--r--plugins/org.eclipse.emf.cdo.security.ui/src/org/eclipse/emf/cdo/security/internal/ui/editor/RolesSection.java54
-rw-r--r--plugins/org.eclipse.emf.cdo.security.ui/src/org/eclipse/emf/cdo/security/internal/ui/editor/TableSection.java422
-rw-r--r--plugins/org.eclipse.emf.cdo.security.ui/src/org/eclipse/emf/cdo/security/internal/ui/editor/UserDetailsPage.java101
-rw-r--r--plugins/org.eclipse.emf.cdo.security.ui/src/org/eclipse/emf/cdo/security/internal/ui/editor/UsersSection.java59
-rw-r--r--plugins/org.eclipse.emf.cdo.security.ui/src/org/eclipse/emf/cdo/security/internal/ui/handlers/ManageSecurityHandler.java230
-rw-r--r--plugins/org.eclipse.emf.cdo.security.ui/src/org/eclipse/emf/cdo/security/internal/ui/messages/Messages.java122
-rw-r--r--plugins/org.eclipse.emf.cdo.security.ui/src/org/eclipse/emf/cdo/security/internal/ui/messages/messages.properties54
-rw-r--r--plugins/org.eclipse.emf.cdo.security.ui/src/org/eclipse/emf/cdo/security/internal/ui/util/ActionBarsHelper.java133
-rw-r--r--plugins/org.eclipse.emf.cdo.security.ui/src/org/eclipse/emf/cdo/security/internal/ui/util/EditableDialogCellEditor.java91
-rw-r--r--plugins/org.eclipse.emf.cdo.security.ui/src/org/eclipse/emf/cdo/security/internal/ui/util/INewObjectConfigurator.java23
-rw-r--r--plugins/org.eclipse.emf.cdo.security.ui/src/org/eclipse/emf/cdo/security/internal/ui/util/ObjectExistsConverter.java67
-rw-r--r--plugins/org.eclipse.emf.cdo.security.ui/src/org/eclipse/emf/cdo/security/internal/ui/util/OneToManyBlock.java587
-rw-r--r--plugins/org.eclipse.emf.cdo.security.ui/src/org/eclipse/emf/cdo/security/internal/ui/util/OneToManyTableBlock.java172
-rw-r--r--plugins/org.eclipse.emf.cdo.security.ui/src/org/eclipse/emf/cdo/security/internal/ui/util/ResourceBasedPermissionFilter.java74
-rw-r--r--plugins/org.eclipse.emf.cdo.security.ui/src/org/eclipse/emf/cdo/security/internal/ui/util/ResourceBasedRoleFilter.java51
-rw-r--r--plugins/org.eclipse.emf.cdo.security.ui/src/org/eclipse/emf/cdo/security/internal/ui/util/SecurityModelUtil.java189
-rw-r--r--plugins/org.eclipse.emf.cdo.security.ui/src/org/eclipse/emf/cdo/security/internal/ui/util/TableLabelProvider.java59
-rw-r--r--plugins/org.eclipse.emf.cdo.security.ui/src/org/eclipse/emf/cdo/security/ui/ISecurityManagementContext.java98
44 files changed, 4820 insertions, 36 deletions
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..ab01176fde
--- /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/security/internal/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..e8d729090c 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
@@ -17,11 +17,6 @@ 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 +37,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 +55,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 +71,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 3ca0b085d6..874d109622 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,23 @@ Bundle-Name: %pluginName
Bundle-Vendor: %providerName
Bundle-ClassPath: .
Bundle-RequiredExecutionEnvironment: J2SE-1.5
-Export-Package: org.eclipse.emf.cdo.security.internal.ui.handlers;version="4.3.0";x-internal:=true
-Require-Bundle: org.eclipse.emf.cdo.security.edit;bundle-version="[4.1.0,5.0.0)",
+Export-Package: org.eclipse.emf.cdo.security.internal.ui.actions;version="4.3.0";x-internal:=true,
+ org.eclipse.emf.cdo.security.internal.ui.bundle;version="4.3.0";x-internal:=true,
+ org.eclipse.emf.cdo.security.internal.ui.dialogs;version="4.3.0";x-internal:=true,
+ org.eclipse.emf.cdo.security.internal.ui.editor;version="4.3.0";x-internal:=true,
+ org.eclipse.emf.cdo.security.internal.ui.handlers;version="4.3.0";x-internal:=true,
+ org.eclipse.emf.cdo.security.internal.ui.messages;version="4.3.0";x-internal:=true,
+ org.eclipse.emf.cdo.security.internal.ui.util;version="4.3.0";x-internal:=true,
+ org.eclipse.emf.cdo.security.ui;version="4.3.0"
+Require-Bundle: org.eclipse.emf.cdo.security;bundle-version="[4.3.0,5.0.0)",
+ org.eclipse.emf.cdo.security.edit;bundle-version="[4.1.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.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)"
+ org.eclipse.ui.forms;bundle-version="[3.6.100,4.0.0)",
+ 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)"
Bundle-ActivationPolicy: lazy
+Bundle-Activator: org.eclipse.emf.cdo.security.internal.ui.bundle.OM$Activator
diff --git a/plugins/org.eclipse.emf.cdo.security.ui/build.properties b/plugins/org.eclipse.emf.cdo.security.ui/build.properties
index 6817fd0c88..475402b4d9 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
+ \ No newline at end of file
diff --git a/plugins/org.eclipse.emf.cdo.security.ui/copyright.txt b/plugins/org.eclipse.emf.cdo.security.ui/copyright.txt
index 4109ec2dea..58d7c01a6a 100644
--- a/plugins/org.eclipse.emf.cdo.security.ui/copyright.txt
+++ b/plugins/org.eclipse.emf.cdo.security.ui/copyright.txt
@@ -1,4 +1,4 @@
-Copyright (c) 2013 Eike Stepper (Berlin, Germany) and others.
+Copyright (c) 2004-2013 Eike Stepper (Berlin, Germany) and others.
All rights reserved. This program and the accompanying materials
are made available under the terms of the Eclipse Public License v1.0
which accompanies this distribution, and is available at
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
new file mode 100644
index 0000000000..c1641fc8bb
--- /dev/null
+++ b/plugins/org.eclipse.emf.cdo.security.ui/icons/full/ctool16/ManageSecurity.png
Binary files differ
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
new file mode 100644
index 0000000000..6fe6f0e10a
--- /dev/null
+++ b/plugins/org.eclipse.emf.cdo.security.ui/icons/full/elcl16/advanced.gif
Binary files differ
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
new file mode 100644
index 0000000000..c0648993b8
--- /dev/null
+++ b/plugins/org.eclipse.emf.cdo.security.ui/icons/full/elcl16/revert.gif
Binary files differ
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
new file mode 100644
index 0000000000..c1641fc8bb
--- /dev/null
+++ b/plugins/org.eclipse.emf.cdo.security.ui/icons/full/obj16/SecurityRealmResource.png
Binary files differ
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
new file mode 100644
index 0000000000..7ce3655569
--- /dev/null
+++ b/plugins/org.eclipse.emf.cdo.security.ui/icons/full/obj16/SecurityRealmResource.pxm
Binary files differ
diff --git a/plugins/org.eclipse.emf.cdo.security.ui/plugin.properties b/plugins/org.eclipse.emf.cdo.security.ui/plugin.properties
index fe8fad889c..3ceaaed667 100644
--- a/plugins/org.eclipse.emf.cdo.security.ui/plugin.properties
+++ b/plugins/org.eclipse.emf.cdo.security.ui/plugin.properties
@@ -15,3 +15,5 @@ action.tooltip = Reset the user's password (must be an administrator)
category.name = CDO Security Management
command.name = Reset Password
command.description = Reset the selected user's password. Must be an administrator to reset passwords.
+action.label.1 = Manage Security
+editor.name = CDO Security Manager
diff --git a/plugins/org.eclipse.emf.cdo.security.ui/plugin.xml b/plugins/org.eclipse.emf.cdo.security.ui/plugin.xml
index 35d7e9b783..ac57e190e5 100644
--- a/plugins/org.eclipse.emf.cdo.security.ui/plugin.xml
+++ b/plugins/org.eclipse.emf.cdo.security.ui/plugin.xml
@@ -14,6 +14,18 @@
<plugin>
<extension
+ point="org.eclipse.ui.editors">
+ <editor
+ class="org.eclipse.emf.cdo.security.internal.ui.editor.CDOSecurityFormEditor"
+ contributorClass="org.eclipse.emf.cdo.security.internal.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">
@@ -38,8 +50,29 @@
</with>
</visibleWhen>
</command>
+ <command
+ commandId="org.eclipse.emf.cdo.security.ui.openEditor"
+ icon="$nl$/icons/full/ctool16/ManageSecurity.png"
+ label="%action.label.1"
+ 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
@@ -53,5 +86,11 @@
description="%command.description"
defaultHandler="org.eclipse.emf.cdo.security.internal.ui.handlers.ResetPasswordHandler">
</command>
+ <command
+ id="org.eclipse.emf.cdo.security.ui.openEditor"
+ name="%action.label.1"
+ categoryId="org.eclipse.emf.cdo.security.ui.management"
+ defaultHandler="org.eclipse.emf.cdo.security.internal.ui.handlers.ManageSecurityHandler">
+ </command>
</extension>
</plugin>
diff --git a/plugins/org.eclipse.emf.cdo.security.ui/src/org/eclipse/emf/cdo/security/internal/ui/actions/SelectionListenerAction.java b/plugins/org.eclipse.emf.cdo.security.ui/src/org/eclipse/emf/cdo/security/internal/ui/actions/SelectionListenerAction.java
new file mode 100644
index 0000000000..e137bc66b7
--- /dev/null
+++ b/plugins/org.eclipse.emf.cdo.security.ui/src/org/eclipse/emf/cdo/security/internal/ui/actions/SelectionListenerAction.java
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2013 Eike Stepper (Berlin, Germany) and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Christian W. Damus (CEA LIST) - initial API and implementation
+ */
+package org.eclipse.emf.cdo.security.internal.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;
+
+/**
+ * @author Christian W. Damus (CEA LIST)
+ */
+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/security/internal/ui/bundle/OM.java b/plugins/org.eclipse.emf.cdo.security.ui/src/org/eclipse/emf/cdo/security/internal/ui/bundle/OM.java
new file mode 100644
index 0000000000..3026457872
--- /dev/null
+++ b/plugins/org.eclipse.emf.cdo.security.ui/src/org/eclipse/emf/cdo/security/internal/ui/bundle/OM.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2007-2013 Eike Stepper (Berlin, Germany) and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Eike Stepper - initial API and implementation
+ * Christian W. Damus (CEA LIST) - bug 418452: adapt for new bundle
+ */
+package org.eclipse.emf.cdo.security.internal.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/security/internal/ui/dialogs/FilterTreeSelectionDialog.java b/plugins/org.eclipse.emf.cdo.security.ui/src/org/eclipse/emf/cdo/security/internal/ui/dialogs/FilterTreeSelectionDialog.java
new file mode 100644
index 0000000000..d9c277801a
--- /dev/null
+++ b/plugins/org.eclipse.emf.cdo.security.ui/src/org/eclipse/emf/cdo/security/internal/ui/dialogs/FilterTreeSelectionDialog.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2013 Eike Stepper (Berlin, Germany) and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Christian W. Damus (CEA LIST) - initial API and implementation
+ */
+package org.eclipse.emf.cdo.security.internal.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.
+ *
+ * @author Christian W. Damus (CEA LIST)
+ */
+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/security/internal/ui/editor/AbstractDetailsPage.java b/plugins/org.eclipse.emf.cdo.security.ui/src/org/eclipse/emf/cdo/security/internal/ui/editor/AbstractDetailsPage.java
new file mode 100644
index 0000000000..56fcc5a888
--- /dev/null
+++ b/plugins/org.eclipse.emf.cdo.security.ui/src/org/eclipse/emf/cdo/security/internal/ui/editor/AbstractDetailsPage.java
@@ -0,0 +1,400 @@
+/*
+ * Copyright (c) 2013 Eike Stepper (Berlin, Germany) and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Christian W. Damus (CEA LIST) - initial API and implementation
+ */
+package org.eclipse.emf.cdo.security.internal.ui.editor;
+
+import org.eclipse.emf.cdo.security.internal.ui.bundle.OM;
+import org.eclipse.emf.cdo.security.internal.ui.messages.Messages;
+import org.eclipse.emf.cdo.security.internal.ui.util.ObjectExistsConverter.ObjectWritableConverter;
+import org.eclipse.emf.cdo.security.internal.ui.util.OneToManyBlock;
+import org.eclipse.emf.cdo.security.internal.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.events.SelectionListener;
+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;
+
+/**
+ * Common framework for the right-hand side object details pages of the
+ * master/detail form.
+ *
+ * @author Christian W. Damus (CEA LIST)
+ */
+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,
+ ObjectWritableConverter.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,
+ ObjectWritableConverter.createUpdateValueStrategy());
+
+ addRevertDecoration(result, attribute);
+
+ return result;
+ }
+
+ protected Button button(Composite parent, FormToolkit toolkit, String label, SelectionListener selectionListener)
+ {
+ Button result = toolkit.createButton(parent, label, SWT.PUSH);
+ result.setLayoutData(layoutData(parent, SWT.LEFT, false, 2));
+
+ getContext().bindValue(SWTObservables.observeEnabled(result), getValue(), null,
+ ObjectWritableConverter.createUpdateValueStrategy());
+
+ result.addSelectionListener(selectionListener);
+
+ 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,
+ ObjectWritableConverter.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/security/internal/ui/editor/AbstractSectionPart.java b/plugins/org.eclipse.emf.cdo.security.ui/src/org/eclipse/emf/cdo/security/internal/ui/editor/AbstractSectionPart.java
new file mode 100644
index 0000000000..07dbab277a
--- /dev/null
+++ b/plugins/org.eclipse.emf.cdo.security.ui/src/org/eclipse/emf/cdo/security/internal/ui/editor/AbstractSectionPart.java
@@ -0,0 +1,216 @@
+/*
+ * Copyright (c) 2013 Eike Stepper (Berlin, Germany) and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Christian W. Damus (CEA LIST) - initial API and implementation
+ */
+package org.eclipse.emf.cdo.security.internal.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;
+
+/**
+ * Common framework for a part of a form page that is an SWT {@link Section}
+ * presenting some object, list/table of objects, or attributes of an object.
+ *
+ * @author Christian W. Damus (CEA LIST)
+ */
+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/security/internal/ui/editor/CDOSecurityFormActionBarContributor.java b/plugins/org.eclipse.emf.cdo.security.ui/src/org/eclipse/emf/cdo/security/internal/ui/editor/CDOSecurityFormActionBarContributor.java
new file mode 100644
index 0000000000..ea37d01101
--- /dev/null
+++ b/plugins/org.eclipse.emf.cdo.security.ui/src/org/eclipse/emf/cdo/security/internal/ui/editor/CDOSecurityFormActionBarContributor.java
@@ -0,0 +1,122 @@
+/*
+ * Copyright (c) 2013 Eike Stepper (Berlin, Germany) and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Christian W. Damus (CEA LIST) - initial API and implementation
+ */
+package org.eclipse.emf.cdo.security.internal.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;
+
+/**
+ * The editor action-bar contributor for the Security Manager editor.
+ *
+ * @author Christian W. Damus (CEA LIST)
+ */
+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/security/internal/ui/editor/CDOSecurityFormEditor.java b/plugins/org.eclipse.emf.cdo.security.ui/src/org/eclipse/emf/cdo/security/internal/ui/editor/CDOSecurityFormEditor.java
new file mode 100644
index 0000000000..709a53a343
--- /dev/null
+++ b/plugins/org.eclipse.emf.cdo.security.ui/src/org/eclipse/emf/cdo/security/internal/ui/editor/CDOSecurityFormEditor.java
@@ -0,0 +1,247 @@
+/*
+ * Copyright (c) 2013 Eike Stepper (Berlin, Germany) and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Christian W. Damus (CEA LIST) - initial API and implementation
+ */
+package org.eclipse.emf.cdo.security.internal.ui.editor;
+
+import org.eclipse.emf.cdo.eresource.CDOResource;
+import org.eclipse.emf.cdo.security.internal.ui.bundle.OM;
+import org.eclipse.emf.cdo.security.internal.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;
+
+/**
+ * The "Security Manager" editor.
+ *
+ * @author Christian W. Damus (CEA LIST)
+ */
+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, at least on Mac OS X)
+ page.setFocus();
+ }
+ }
+}
diff --git a/plugins/org.eclipse.emf.cdo.security.ui/src/org/eclipse/emf/cdo/security/internal/ui/editor/CDOSecurityPage.java b/plugins/org.eclipse.emf.cdo.security.ui/src/org/eclipse/emf/cdo/security/internal/ui/editor/CDOSecurityPage.java
new file mode 100644
index 0000000000..1d3bccfda8
--- /dev/null
+++ b/plugins/org.eclipse.emf.cdo.security.ui/src/org/eclipse/emf/cdo/security/internal/ui/editor/CDOSecurityPage.java
@@ -0,0 +1,364 @@
+/*
+ * Copyright (c) 2013 Eike Stepper (Berlin, Germany) and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Christian W. Damus (CEA LIST) - initial API and implementation
+ */
+package org.eclipse.emf.cdo.security.internal.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.security.Realm;
+import org.eclipse.emf.cdo.security.SecurityPackage;
+import org.eclipse.emf.cdo.security.internal.ui.bundle.OM;
+import org.eclipse.emf.cdo.security.internal.ui.messages.Messages;
+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;
+
+/**
+ * The main page of the "Security Manager" form editor.
+ *
+ * @author Christian W. Damus (CEA LIST)
+ */
+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(Messages.CDOSecurityPage_0, ExtendedImageRegistry.getInstance().getImageDescriptor(
+ URI.createPlatformPluginURI(OM.BUNDLE_ID + "/icons/full/elcl16/advanced.gif", true))) //$NON-NLS-1$
+ {
+ @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/security/internal/ui/editor/EClassDetailsPageProvider.java b/plugins/org.eclipse.emf.cdo.security.ui/src/org/eclipse/emf/cdo/security/internal/ui/editor/EClassDetailsPageProvider.java
new file mode 100644
index 0000000000..a12eda7ab2
--- /dev/null
+++ b/plugins/org.eclipse.emf.cdo.security.ui/src/org/eclipse/emf/cdo/security/internal/ui/editor/EClassDetailsPageProvider.java
@@ -0,0 +1,88 @@
+/*
+ * Copyright (c) 2013 Eike Stepper (Berlin, Germany) and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Christian W. Damus (CEA LIST) - initial API and implementation
+ */
+package org.eclipse.emf.cdo.security.internal.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;
+
+/**
+ * A master/details-block details page provider that maps details pages
+ * simply by {@link EClass}.
+ *
+ * @author Christian W. Damus (CEA LIST)
+ *
+ * @see #builder(IActionBars)
+ */
+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/security/internal/ui/editor/EmptyDetailsPage.java b/plugins/org.eclipse.emf.cdo.security.ui/src/org/eclipse/emf/cdo/security/internal/ui/editor/EmptyDetailsPage.java
new file mode 100644
index 0000000000..dde9cb923c
--- /dev/null
+++ b/plugins/org.eclipse.emf.cdo.security.ui/src/org/eclipse/emf/cdo/security/internal/ui/editor/EmptyDetailsPage.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2013 Eike Stepper (Berlin, Germany) and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Christian W. Damus (CEA LIST) - initial API and implementation
+ */
+package org.eclipse.emf.cdo.security.internal.ui.editor;
+
+import org.eclipse.emf.cdo.security.internal.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;
+
+/**
+ * The page presented when there is no selection for which to show details.
+ *
+ * @author Christian W. Damus (CEA LIST)
+ */
+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/security/internal/ui/editor/GroupDetailsPage.java b/plugins/org.eclipse.emf.cdo.security.ui/src/org/eclipse/emf/cdo/security/internal/ui/editor/GroupDetailsPage.java
new file mode 100644
index 0000000000..8ebfed5163
--- /dev/null
+++ b/plugins/org.eclipse.emf.cdo.security.ui/src/org/eclipse/emf/cdo/security/internal/ui/editor/GroupDetailsPage.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2013 Eike Stepper (Berlin, Germany) and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Christian W. Damus (CEA LIST) - initial API and implementation
+ */
+package org.eclipse.emf.cdo.security.internal.ui.editor;
+
+import org.eclipse.emf.cdo.security.Group;
+import org.eclipse.emf.cdo.security.SecurityPackage;
+import org.eclipse.emf.cdo.security.internal.ui.messages.Messages;
+
+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;
+
+/**
+ * The details page for a {@link Group} selection.
+ *
+ * @author Christian W. Damus (CEA LIST)
+ */
+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/security/internal/ui/editor/GroupsSection.java b/plugins/org.eclipse.emf.cdo.security.ui/src/org/eclipse/emf/cdo/security/internal/ui/editor/GroupsSection.java
new file mode 100644
index 0000000000..6d1ef1ac6a
--- /dev/null
+++ b/plugins/org.eclipse.emf.cdo.security.ui/src/org/eclipse/emf/cdo/security/internal/ui/editor/GroupsSection.java
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2013 Eike Stepper (Berlin, Germany) and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Christian W. Damus (CEA LIST) - initial API and implementation
+ */
+package org.eclipse.emf.cdo.security.internal.ui.editor;
+
+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.cdo.security.internal.ui.messages.Messages;
+
+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;
+
+/**
+ * The section presenting the {@link Group}s defined in the security realm.
+ *
+ * @author Christian W. Damus (CEA LIST)
+ */
+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/security/internal/ui/editor/RoleDetailsPage.java b/plugins/org.eclipse.emf.cdo.security.ui/src/org/eclipse/emf/cdo/security/internal/ui/editor/RoleDetailsPage.java
new file mode 100644
index 0000000000..d4520b10e4
--- /dev/null
+++ b/plugins/org.eclipse.emf.cdo.security.ui/src/org/eclipse/emf/cdo/security/internal/ui/editor/RoleDetailsPage.java
@@ -0,0 +1,390 @@
+/*
+ * Copyright (c) 2013 Eike Stepper (Berlin, Germany) and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Christian W. Damus (CEA LIST) - initial API and implementation
+ */
+package org.eclipse.emf.cdo.security.internal.ui.editor;
+
+import static org.eclipse.emf.cdo.security.internal.ui.util.SecurityModelUtil.getTypeFilter;
+import static org.eclipse.emf.cdo.security.internal.ui.util.SecurityModelUtil.viewerFilter;
+
+import org.eclipse.emf.cdo.eresource.CDOResourceNode;
+import org.eclipse.emf.cdo.eresource.EresourcePackage;
+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.internal.ui.dialogs.FilterTreeSelectionDialog;
+import org.eclipse.emf.cdo.security.internal.ui.messages.Messages;
+import org.eclipse.emf.cdo.security.internal.ui.util.EditableDialogCellEditor;
+import org.eclipse.emf.cdo.security.internal.ui.util.INewObjectConfigurator;
+import org.eclipse.emf.cdo.security.internal.ui.util.OneToManyTableBlock;
+import org.eclipse.emf.cdo.security.internal.ui.util.ResourceBasedPermissionFilter;
+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;
+
+/**
+ * The details page for {@link Role} master selections. Includes a table
+ * that provides in-line editing of resource-based permissions.
+ *
+ * @author Christian W. Damus (CEA LIST)
+ */
+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/security/internal/ui/editor/RolesSection.java b/plugins/org.eclipse.emf.cdo.security.ui/src/org/eclipse/emf/cdo/security/internal/ui/editor/RolesSection.java
new file mode 100644
index 0000000000..d44831ebde
--- /dev/null
+++ b/plugins/org.eclipse.emf.cdo.security.ui/src/org/eclipse/emf/cdo/security/internal/ui/editor/RolesSection.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2013 Eike Stepper (Berlin, Germany) and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Christian W. Damus (CEA LIST) - initial API and implementation
+ */
+package org.eclipse.emf.cdo.security.internal.ui.editor;
+
+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.cdo.security.internal.ui.messages.Messages;
+
+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;
+
+/**
+ * The form section part presenting the {@link Role}s defined in the security realm.
+ *
+ * @author Christian W. Damus (CEA LIST)
+ */
+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/security/internal/ui/editor/TableSection.java b/plugins/org.eclipse.emf.cdo.security.ui/src/org/eclipse/emf/cdo/security/internal/ui/editor/TableSection.java
new file mode 100644
index 0000000000..63229a8e0a
--- /dev/null
+++ b/plugins/org.eclipse.emf.cdo.security.ui/src/org/eclipse/emf/cdo/security/internal/ui/editor/TableSection.java
@@ -0,0 +1,422 @@
+/*
+ * Copyright (c) 2013 Eike Stepper (Berlin, Germany) and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Christian W. Damus (CEA LIST) - initial API and implementation
+ */
+package org.eclipse.emf.cdo.security.internal.ui.editor;
+
+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.security.internal.ui.actions.SelectionListenerAction;
+import org.eclipse.emf.cdo.security.internal.ui.messages.Messages;
+import org.eclipse.emf.cdo.security.internal.ui.util.ActionBarsHelper;
+import org.eclipse.emf.cdo.security.internal.ui.util.ObjectExistsConverter.ObjectWritableConverter;
+import org.eclipse.emf.cdo.security.internal.ui.util.SecurityModelUtil;
+import org.eclipse.emf.cdo.security.internal.ui.util.TableLabelProvider;
+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;
+
+/**
+ * Common framework for section parts of a form that present a list of
+ * similar objects. It presents buttons for adding and deleting
+ * objects in the list. The objects presented are the contents
+ * (of the appropriate type) of some {@link Directory} in the security
+ * realm model.
+ *
+ * @author Christian W. Damus (CEA LIST)
+ */
+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, ObjectWritableConverter.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/security/internal/ui/editor/UserDetailsPage.java b/plugins/org.eclipse.emf.cdo.security.ui/src/org/eclipse/emf/cdo/security/internal/ui/editor/UserDetailsPage.java
new file mode 100644
index 0000000000..fc22b6af6f
--- /dev/null
+++ b/plugins/org.eclipse.emf.cdo.security.ui/src/org/eclipse/emf/cdo/security/internal/ui/editor/UserDetailsPage.java
@@ -0,0 +1,101 @@
+/*
+ * Copyright (c) 2013 Eike Stepper (Berlin, Germany) and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Christian W. Damus (CEA LIST) - initial API and implementation
+ */
+package org.eclipse.emf.cdo.security.internal.ui.editor;
+
+import org.eclipse.emf.cdo.security.SecurityPackage;
+import org.eclipse.emf.cdo.security.User;
+import org.eclipse.emf.cdo.security.internal.ui.messages.Messages;
+import org.eclipse.emf.cdo.view.CDOView;
+
+import org.eclipse.emf.common.notify.AdapterFactory;
+import org.eclipse.emf.edit.domain.EditingDomain;
+import org.eclipse.emf.spi.cdo.InternalCDOSession;
+
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.core.runtime.jobs.Job;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.ui.forms.widgets.FormToolkit;
+
+/**
+ * Details page for selected {@link User} master objects.
+ *
+ * @author Christian W. Damus (CEA LIST)
+ */
+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);
+ button(parent, toolkit, Messages.UserDetailsPage_9, new SelectionAdapter()
+ {
+ @Override
+ public void widgetSelected(SelectionEvent e)
+ {
+ resetPassword(getInput());
+ }
+ });
+
+ 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);
+ }
+
+ private void resetPassword(final User user)
+ {
+ new Job(Messages.UserDetailsPage_9)
+ {
+
+ @Override
+ public IStatus run(IProgressMonitor monitor)
+ {
+ CDOView view = user.cdoView();
+ if (!view.isClosed())
+ {
+ InternalCDOSession session = (InternalCDOSession)view.getSession();
+ if (!session.isClosed())
+ {
+ session.resetCredentials(user.getId());
+ }
+ }
+
+ return Status.OK_STATUS;
+ }
+ }.schedule();
+ }
+}
diff --git a/plugins/org.eclipse.emf.cdo.security.ui/src/org/eclipse/emf/cdo/security/internal/ui/editor/UsersSection.java b/plugins/org.eclipse.emf.cdo.security.ui/src/org/eclipse/emf/cdo/security/internal/ui/editor/UsersSection.java
new file mode 100644
index 0000000000..652cb9d7ed
--- /dev/null
+++ b/plugins/org.eclipse.emf.cdo.security.ui/src/org/eclipse/emf/cdo/security/internal/ui/editor/UsersSection.java
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2013 Eike Stepper (Berlin, Germany) and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Christian W. Damus (CEA LIST) - initial API and implementation
+ */
+package org.eclipse.emf.cdo.security.internal.ui.editor;
+
+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.cdo.security.internal.ui.messages.Messages;
+
+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;
+
+/**
+ * The section form part presenting the {@link User}s defined in the security realm.
+ *
+ * @author Christian W. Damus (CEA LIST)
+ */
+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/security/internal/ui/handlers/ManageSecurityHandler.java b/plugins/org.eclipse.emf.cdo.security.ui/src/org/eclipse/emf/cdo/security/internal/ui/handlers/ManageSecurityHandler.java
new file mode 100644
index 0000000000..b0e5cdf15c
--- /dev/null
+++ b/plugins/org.eclipse.emf.cdo.security.ui/src/org/eclipse/emf/cdo/security/internal/ui/handlers/ManageSecurityHandler.java
@@ -0,0 +1,230 @@
+/*
+ * Copyright (c) 2013 Eike Stepper (Berlin, Germany) and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Christian W. Damus (CEA LIST) - initial API and implementation
+ */
+package org.eclipse.emf.cdo.security.internal.ui.handlers;
+
+import org.eclipse.emf.cdo.eresource.CDOResource;
+import org.eclipse.emf.cdo.security.internal.ui.editor.CDOSecurityFormEditor;
+import org.eclipse.emf.cdo.security.internal.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;
+
+/**
+ * "Manage Security" command handler, which opens the Security Manager editor
+ * in the context of the currently selected {@link CDOSession}, with the help
+ * of an optional {@link ISecurityManagementContext} adapter.
+ *
+ * @author Christian W. Damus (CEA LIST)
+ */
+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/security/internal/ui/messages/Messages.java b/plugins/org.eclipse.emf.cdo.security.ui/src/org/eclipse/emf/cdo/security/internal/ui/messages/Messages.java
new file mode 100644
index 0000000000..10d3407ca6
--- /dev/null
+++ b/plugins/org.eclipse.emf.cdo.security.ui/src/org/eclipse/emf/cdo/security/internal/ui/messages/Messages.java
@@ -0,0 +1,122 @@
+/*
+ * Copyright (c) 2013 Eike Stepper (Berlin, Germany) and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Christian W. Damus (CEA LIST) - initial API and implementation
+ */
+package org.eclipse.emf.cdo.security.internal.ui.messages;
+
+import org.eclipse.osgi.util.NLS;
+
+/**
+ * Localized messages bundle.
+ *
+ * @author Christian W. Damus (CEA LIST)
+ */
+public class Messages extends NLS
+{
+ private static final String BUNDLE_NAME = "org.eclipse.emf.cdo.security.internal.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_0;
+
+ 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 UserDetailsPage_9;
+
+ 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/security/internal/ui/messages/messages.properties b/plugins/org.eclipse.emf.cdo.security.ui/src/org/eclipse/emf/cdo/security/internal/ui/messages/messages.properties
new file mode 100644
index 0000000000..a9ac5d3339
--- /dev/null
+++ b/plugins/org.eclipse.emf.cdo.security.ui/src/org/eclipse/emf/cdo/security/internal/ui/messages/messages.properties
@@ -0,0 +1,54 @@
+# Copyright (c) 2013 Eike Stepper (Berlin, Germany) and others.
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+#
+# Contributors:
+# 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_0=Open Advanced Editor
+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:
+UserDetailsPage_9=Reset Password...
+UsersSection_0=Users
diff --git a/plugins/org.eclipse.emf.cdo.security.ui/src/org/eclipse/emf/cdo/security/internal/ui/util/ActionBarsHelper.java b/plugins/org.eclipse.emf.cdo.security.ui/src/org/eclipse/emf/cdo/security/internal/ui/util/ActionBarsHelper.java
new file mode 100644
index 0000000000..a41bd111e7
--- /dev/null
+++ b/plugins/org.eclipse.emf.cdo.security.ui/src/org/eclipse/emf/cdo/security/internal/ui/util/ActionBarsHelper.java
@@ -0,0 +1,133 @@
+/*
+ * Copyright (c) 2013 Eike Stepper (Berlin, Germany) and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Christian W. Damus (CEA LIST) - initial API and implementation
+ */
+package org.eclipse.emf.cdo.security.internal.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;
+
+/**
+ * A utility that manages the propagation of global actions from
+ * some nested part of an editor to the editor's action bars.
+ *
+ * @author Christian W. Damus (CEA LIST)
+ */
+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/security/internal/ui/util/EditableDialogCellEditor.java b/plugins/org.eclipse.emf.cdo.security.ui/src/org/eclipse/emf/cdo/security/internal/ui/util/EditableDialogCellEditor.java
new file mode 100644
index 0000000000..78610e928b
--- /dev/null
+++ b/plugins/org.eclipse.emf.cdo.security.ui/src/org/eclipse/emf/cdo/security/internal/ui/util/EditableDialogCellEditor.java
@@ -0,0 +1,91 @@
+/*
+ * Copyright (c) 2013 Eike Stepper (Berlin, Germany) and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Christian W. Damus (CEA LIST) - initial API and implementation
+ */
+package org.eclipse.emf.cdo.security.internal.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.
+ *
+ * @author Christian W. Damus (CEA LIST)
+ */
+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/security/internal/ui/util/INewObjectConfigurator.java b/plugins/org.eclipse.emf.cdo.security.ui/src/org/eclipse/emf/cdo/security/internal/ui/util/INewObjectConfigurator.java
new file mode 100644
index 0000000000..f757c7e0f1
--- /dev/null
+++ b/plugins/org.eclipse.emf.cdo.security.ui/src/org/eclipse/emf/cdo/security/internal/ui/util/INewObjectConfigurator.java
@@ -0,0 +1,23 @@
+/*
+ * Copyright (c) 2013 Eike Stepper (Berlin, Germany) and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Christian W. Damus (CEA LIST) - initial API and implementation
+ */
+package org.eclipse.emf.cdo.security.internal.ui.util;
+
+import org.eclipse.emf.common.command.Command;
+
+/**
+ * A protocol for the configuration of newly created elements in the editor.
+ *
+ * @author Christian W. Damus (CEA LIST)
+ */
+public interface INewObjectConfigurator
+{
+ public Command createConfigureCommand(Object newObject);
+}
diff --git a/plugins/org.eclipse.emf.cdo.security.ui/src/org/eclipse/emf/cdo/security/internal/ui/util/ObjectExistsConverter.java b/plugins/org.eclipse.emf.cdo.security.ui/src/org/eclipse/emf/cdo/security/internal/ui/util/ObjectExistsConverter.java
new file mode 100644
index 0000000000..7aa0566ccd
--- /dev/null
+++ b/plugins/org.eclipse.emf.cdo.security.ui/src/org/eclipse/emf/cdo/security/internal/ui/util/ObjectExistsConverter.java
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 2013 Eike Stepper (Berlin, Germany) and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Christian W. Damus (CEA LIST) - initial API and implementation
+ */
+package org.eclipse.emf.cdo.security.internal.ui.util;
+
+import org.eclipse.core.databinding.UpdateValueStrategy;
+import org.eclipse.core.databinding.conversion.Converter;
+
+/**
+ * A data-binding converter that converts an object (a reference or {@code null})
+ * to a boolean indicating the presence of the object ({@code true} for a present
+ * object, {@code false} for a {@code null}).
+ *
+ * @author Christian W. Damus (CEA LIST)
+ */
+public class ObjectExistsConverter extends Converter
+{
+
+ public ObjectExistsConverter()
+ {
+ super(Object.class, Boolean.class);
+ }
+
+ public Object convert(Object fromObject)
+ {
+ return doConvert(fromObject);
+ }
+
+ protected boolean doConvert(Object fromObject)
+ {
+ return fromObject != null;
+ }
+
+ //
+ // Nested types
+ //
+
+ // public static UpdateValueStrategy createUpdateValueStrategy()
+ // {
+ // UpdateValueStrategy result = new UpdateValueStrategy();
+ // result.setConverter(new ObjectExistsConverter());
+ // return result;
+ // }
+
+ public static class ObjectWritableConverter extends ObjectExistsConverter
+ {
+ @Override
+ protected boolean doConvert(Object fromObject)
+ {
+ return super.doConvert(fromObject) && SecurityModelUtil.isEditable(fromObject);
+ }
+
+ public static UpdateValueStrategy createUpdateValueStrategy()
+ {
+ UpdateValueStrategy result = new UpdateValueStrategy();
+ result.setConverter(new ObjectWritableConverter());
+ return result;
+ }
+ }
+}
diff --git a/plugins/org.eclipse.emf.cdo.security.ui/src/org/eclipse/emf/cdo/security/internal/ui/util/OneToManyBlock.java b/plugins/org.eclipse.emf.cdo.security.ui/src/org/eclipse/emf/cdo/security/internal/ui/util/OneToManyBlock.java
new file mode 100644
index 0000000000..4f65c709e0
--- /dev/null
+++ b/plugins/org.eclipse.emf.cdo.security.ui/src/org/eclipse/emf/cdo/security/internal/ui/util/OneToManyBlock.java
@@ -0,0 +1,587 @@
+/*
+ * Copyright (c) 2013 Eike Stepper (Berlin, Germany) and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Christian W. Damus (CEA LIST) - initial API and implementation
+ */
+package org.eclipse.emf.cdo.security.internal.ui.util;
+
+import static org.eclipse.emf.cdo.security.internal.ui.util.SecurityModelUtil.applyTypeFilter;
+import static org.eclipse.emf.cdo.security.internal.ui.util.SecurityModelUtil.viewerFilter;
+
+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.internal.ui.actions.SelectionListenerAction;
+import org.eclipse.emf.cdo.security.internal.ui.messages.Messages;
+import org.eclipse.emf.cdo.security.internal.ui.util.ObjectExistsConverter.ObjectWritableConverter;
+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.emf.edit.ui.provider.AdapterFactoryLabelProvider;
+
+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;
+
+/**
+ * An encapsulation of a block of controls in a form that edits a one-to-many
+ * reference in the security model.
+ *
+ * @author Christian W. Damus (CEA 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));
+ AdapterFactoryLabelProvider labels = new TableLabelProvider(adapterFactory);
+ labels.setFireLabelUpdateNotifications(true); // Needed to support the data-binding input
+ viewer.setLabelProvider(labels);
+ }
+
+ 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,
+ ObjectWritableConverter.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,
+ ObjectWritableConverter.createUpdateValueStrategy());
+ if (addButton != null)
+ {
+ context.bindValue(SWTObservables.observeEnabled(addButton), input, null,
+ ObjectWritableConverter.createUpdateValueStrategy());
+ }
+ context.bindValue(SWTObservables.observeEnabled(removeButton), selection, null,
+ ObjectWritableConverter.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
+ //
+
+ /**
+ * Specification of the configuration of a one-to-many block's contents.
+ *
+ * @author Christian W. Damus (CEA LIST)
+ */
+ public static interface IOneToManyConfiguration
+ {
+ public EReference getModelReference();
+
+ public EClass getItemType();
+
+ public IFilter getItemFilter();
+ }
+
+ /**
+ * Default one-to-many block configuration implementation.
+ *
+ * @author Christian W. Damus (CEA LIST)
+ */
+ 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/security/internal/ui/util/OneToManyTableBlock.java b/plugins/org.eclipse.emf.cdo.security.ui/src/org/eclipse/emf/cdo/security/internal/ui/util/OneToManyTableBlock.java
new file mode 100644
index 0000000000..64e1e39f82
--- /dev/null
+++ b/plugins/org.eclipse.emf.cdo.security.ui/src/org/eclipse/emf/cdo/security/internal/ui/util/OneToManyTableBlock.java
@@ -0,0 +1,172 @@
+/*
+ * Copyright (c) 2013 Eike Stepper (Berlin, Germany) and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Christian W. Damus (CEA LIST) - initial API and implementation
+ */
+package org.eclipse.emf.cdo.security.internal.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;
+
+/**
+ * A specialization of the encapsulated UI for one-to-many reference
+ * editing that presents a table with multiple columns and in-line
+ * editing support.
+ *
+ * @author Christian W. Damus (CEA LIST)
+ */
+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
+ //
+
+ /**
+ * Specialized one-to-many configuration that describes a multiple
+ * column presentation with in-line editing support.
+ *
+ * @author Christian W. Damus (CEA LIST)
+ */
+ public static interface ITableConfiguration extends IOneToManyConfiguration
+ {
+ public String[] getColumnTitles();
+
+ public int getColumnWeight(int index);
+
+ public int getColumnMinimumSize(int index);
+
+ public boolean isColumnResizable(int index);
+
+ public CellLabelProvider getLabelProvider(TableViewer viewer, int columnIndex);
+
+ public boolean canEdit(TableViewer viewer, Object element, int columnIndex);
+
+ public void setValue(TableViewer viewer, Object element, int columnIndex, Object value);
+
+ public Object getValue(TableViewer viewer, Object element, int columnIndex);
+
+ public CellEditor getCellEditor(TableViewer viewer, int columnIndex);
+ }
+
+ /**
+ * Partial implementation of the table configuration interface.
+ *
+ * @author Christian W. Damus (CEA LIST)
+ */
+ 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/security/internal/ui/util/ResourceBasedPermissionFilter.java b/plugins/org.eclipse.emf.cdo.security.ui/src/org/eclipse/emf/cdo/security/internal/ui/util/ResourceBasedPermissionFilter.java
new file mode 100644
index 0000000000..e39ef5602c
--- /dev/null
+++ b/plugins/org.eclipse.emf.cdo.security.ui/src/org/eclipse/emf/cdo/security/internal/ui/util/ResourceBasedPermissionFilter.java
@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) 2013 Eike Stepper (Berlin, Germany) and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Christian W. Damus (CEA LIST) - initial API and implementation
+ */
+package org.eclipse.emf.cdo.security.internal.ui.util;
+
+import org.eclipse.emf.cdo.security.CombinedFilter;
+import org.eclipse.emf.cdo.security.FilterPermission;
+import org.eclipse.emf.cdo.security.Permission;
+import org.eclipse.emf.cdo.security.PermissionFilter;
+import org.eclipse.emf.cdo.security.ResourceFilter;
+
+import org.eclipse.jface.viewers.IFilter;
+
+/**
+ * A UI filter that selects {@link Permission}s that are
+ * resource-based permissions.
+ *
+ * @author Christian W. Damus (CEA LIST)
+ */
+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 permission filters 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/security/internal/ui/util/ResourceBasedRoleFilter.java b/plugins/org.eclipse.emf.cdo.security.ui/src/org/eclipse/emf/cdo/security/internal/ui/util/ResourceBasedRoleFilter.java
new file mode 100644
index 0000000000..ab208187f2
--- /dev/null
+++ b/plugins/org.eclipse.emf.cdo.security.ui/src/org/eclipse/emf/cdo/security/internal/ui/util/ResourceBasedRoleFilter.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2013 Eike Stepper (Berlin, Germany) and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Christian W. Damus (CEA LIST) - initial API and implementation
+ */
+package org.eclipse.emf.cdo.security.internal.ui.util;
+
+import org.eclipse.emf.cdo.security.Permission;
+import org.eclipse.emf.cdo.security.Role;
+
+import org.eclipse.jface.viewers.IFilter;
+
+/**
+ * A UI filter that selects {@link Role}s that have only
+ * {@linkplain ResourceBasedPermissionFilter resource-based} permissions.
+ *
+ * @author Christian W. Damus (CEA LIST)
+ */
+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/security/internal/ui/util/SecurityModelUtil.java b/plugins/org.eclipse.emf.cdo.security.ui/src/org/eclipse/emf/cdo/security/internal/ui/util/SecurityModelUtil.java
new file mode 100644
index 0000000000..e6a19a1f59
--- /dev/null
+++ b/plugins/org.eclipse.emf.cdo.security.ui/src/org/eclipse/emf/cdo/security/internal/ui/util/SecurityModelUtil.java
@@ -0,0 +1,189 @@
+/*
+ * Copyright (c) 2013 Eike Stepper (Berlin, Germany) and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Christian W. Damus (CEA LIST) - initial API and implementation
+ */
+package org.eclipse.emf.cdo.security.internal.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;
+
+/**
+ * Various static utilities for working with the security model.
+ *
+ * @author Christian W. Damus (CEA LIST)
+ */
+public class SecurityModelUtil
+{
+
+ // Not instantiable by clients
+ 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/security/internal/ui/util/TableLabelProvider.java b/plugins/org.eclipse.emf.cdo.security.ui/src/org/eclipse/emf/cdo/security/internal/ui/util/TableLabelProvider.java
new file mode 100644
index 0000000000..3e14b2544c
--- /dev/null
+++ b/plugins/org.eclipse.emf.cdo.security.ui/src/org/eclipse/emf/cdo/security/internal/ui/util/TableLabelProvider.java
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2013 Eike Stepper (Berlin, Germany) and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Christian W. Damus (CEA LIST) - initial API and implementation
+ */
+package org.eclipse.emf.cdo.security.internal.ui.util;
+
+import org.eclipse.emf.common.notify.AdapterFactory;
+import org.eclipse.emf.edit.provider.IItemLabelProvider;
+import org.eclipse.emf.edit.ui.provider.AdapterFactoryLabelProvider;
+
+import org.eclipse.swt.graphics.Image;
+
+/**
+ * An {@link AdapterFactory}-based table label provider that defaults
+ * {@linkplain #defaultColumnIndex() some column}'s labels to the
+ * object's {@link IItemLabelProvider}.
+ *
+ * @author Christian W. Damus (CEA LIST)
+ */
+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..492d95a16c
--- /dev/null
+++ b/plugins/org.eclipse.emf.cdo.security.ui/src/org/eclipse/emf/cdo/security/ui/ISecurityManagementContext.java
@@ -0,0 +1,98 @@
+/*
+ * Copyright (c) 2013 Eike Stepper (Berlin, Germany) and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * 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.security.User;
+import org.eclipse.emf.cdo.security.internal.ui.bundle.OM;
+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.
+ *
+ * @author Christian W. Damus (CEA LIST)
+ */
+public interface ISecurityManagementContext
+{
+
+ public static final 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)
+ */
+ public 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)
+ */
+ public void disconnect(CDOView view);
+
+ /**
+ * Obtains the resource containing the security model for presentation in the Security Management
+ * editor.
+ */
+ public CDOResource getSecurityResource(CDOView view);
+
+ //
+ // Nested types
+ //
+
+ public static 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;
+ }
+ }
+}

Back to the top