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

Back to the top