New project conventions (builds)
authorMathieu Baudier <mbaudier@argeo.org>
Tue, 25 Nov 2014 14:07:12 +0000 (14:07 +0000)
committerMathieu Baudier <mbaudier@argeo.org>
Tue, 25 Nov 2014 14:07:12 +0000 (14:07 +0000)
git-svn-id: https://svn.argeo.org/commons/trunk@7540 4cfe0d0a-d680-48aa-b62c-e0a02a3f76cc

286 files changed:
org.argeo.jcr.ui.explorer/.classpath
org.argeo.jcr.ui.explorer/.settings/org.eclipse.jdt.core.prefs [deleted file]
org.argeo.jcr.ui.explorer/build.properties
org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/JcrExplorerConstants.java [deleted file]
org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/JcrExplorerPerspective.java [deleted file]
org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/JcrExplorerPlugin.java [deleted file]
org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/JcrExplorerView.java [deleted file]
org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/browser/NodeContentProvider.java [deleted file]
org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/browser/NodeLabelProvider.java [deleted file]
org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/browser/PropertiesContentProvider.java [deleted file]
org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/commands/AddFolderNode.java [deleted file]
org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/commands/AddPrivileges.java [deleted file]
org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/commands/AddRemoteRepository.java [deleted file]
org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/commands/CreateWorkspace.java [deleted file]
org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/commands/DeleteNodes.java [deleted file]
org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/commands/DumpNode.java [deleted file]
org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/commands/EditNode.java [deleted file]
org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/commands/GetNodeSize.java [deleted file]
org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/commands/ImportFileSystem.java [deleted file]
org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/commands/OpenGenericNodeEditor.java [deleted file]
org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/commands/Refresh.java [deleted file]
org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/commands/RemoveRemoteRepository.java [deleted file]
org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/commands/SortChildNodes.java [deleted file]
org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/dialogs/ChooseNameDialog.java [deleted file]
org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/editors/ChildNodesPage.java [deleted file]
org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/editors/EmptyNodePage.java [deleted file]
org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/editors/GenericJcrQueryEditor.java [deleted file]
org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/editors/GenericNodeEditor.java [deleted file]
org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/editors/GenericNodeEditorInput.java [deleted file]
org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/editors/GenericNodePage.java [deleted file]
org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/editors/GenericPropertyPage.java [deleted file]
org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/editors/NodeRightsManagementPage.java [deleted file]
org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/editors/NodeVersionHistoryPage.java [deleted file]
org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/editors/StringNodeEditorInput.java [deleted file]
org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/model/MaintainedRepositoryElem.java [deleted file]
org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/model/RemoteRepositoryElem.java [deleted file]
org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/model/RepositoriesElem.java [deleted file]
org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/model/RepositoryElem.java [deleted file]
org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/model/SingleJcrNodeElem.java [deleted file]
org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/model/WorkspaceElem.java [deleted file]
org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/providers/FullVersioningTreeContentProvider.java [deleted file]
org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/providers/PropertyLabelProvider.java [deleted file]
org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/providers/SingleNodeAsTreeContentProvider.java [deleted file]
org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/providers/VersionLabelProvider.java [deleted file]
org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/utils/GenericNodeDoubleClickListener.java [deleted file]
org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/utils/JcrUiUtils.java [deleted file]
org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/utils/TreeObjectsComparator.java [deleted file]
org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/views/GenericJcrBrowser.java [deleted file]
org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/wizards/ChangeRightsWizard.java [deleted file]
org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/wizards/ChooseRightsPage.java [deleted file]
org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/wizards/ImportFileSystemWizard.java [deleted file]
org.argeo.jcr.ui.explorer/src/main/resources/org/argeo/jcr/ui/explorer/messages.properties [deleted file]
org.argeo.jcr.ui.explorer/src/org/argeo/jcr/ui/explorer/JcrExplorerConstants.java [new file with mode: 0644]
org.argeo.jcr.ui.explorer/src/org/argeo/jcr/ui/explorer/JcrExplorerPerspective.java [new file with mode: 0644]
org.argeo.jcr.ui.explorer/src/org/argeo/jcr/ui/explorer/JcrExplorerPlugin.java [new file with mode: 0644]
org.argeo.jcr.ui.explorer/src/org/argeo/jcr/ui/explorer/JcrExplorerView.java [new file with mode: 0644]
org.argeo.jcr.ui.explorer/src/org/argeo/jcr/ui/explorer/browser/NodeContentProvider.java [new file with mode: 0644]
org.argeo.jcr.ui.explorer/src/org/argeo/jcr/ui/explorer/browser/NodeLabelProvider.java [new file with mode: 0644]
org.argeo.jcr.ui.explorer/src/org/argeo/jcr/ui/explorer/browser/PropertiesContentProvider.java [new file with mode: 0644]
org.argeo.jcr.ui.explorer/src/org/argeo/jcr/ui/explorer/commands/AddFolderNode.java [new file with mode: 0644]
org.argeo.jcr.ui.explorer/src/org/argeo/jcr/ui/explorer/commands/AddPrivileges.java [new file with mode: 0644]
org.argeo.jcr.ui.explorer/src/org/argeo/jcr/ui/explorer/commands/AddRemoteRepository.java [new file with mode: 0644]
org.argeo.jcr.ui.explorer/src/org/argeo/jcr/ui/explorer/commands/CreateWorkspace.java [new file with mode: 0644]
org.argeo.jcr.ui.explorer/src/org/argeo/jcr/ui/explorer/commands/DeleteNodes.java [new file with mode: 0644]
org.argeo.jcr.ui.explorer/src/org/argeo/jcr/ui/explorer/commands/DumpNode.java [new file with mode: 0644]
org.argeo.jcr.ui.explorer/src/org/argeo/jcr/ui/explorer/commands/EditNode.java [new file with mode: 0644]
org.argeo.jcr.ui.explorer/src/org/argeo/jcr/ui/explorer/commands/GetNodeSize.java [new file with mode: 0644]
org.argeo.jcr.ui.explorer/src/org/argeo/jcr/ui/explorer/commands/ImportFileSystem.java [new file with mode: 0644]
org.argeo.jcr.ui.explorer/src/org/argeo/jcr/ui/explorer/commands/OpenGenericNodeEditor.java [new file with mode: 0644]
org.argeo.jcr.ui.explorer/src/org/argeo/jcr/ui/explorer/commands/Refresh.java [new file with mode: 0644]
org.argeo.jcr.ui.explorer/src/org/argeo/jcr/ui/explorer/commands/RemoveRemoteRepository.java [new file with mode: 0644]
org.argeo.jcr.ui.explorer/src/org/argeo/jcr/ui/explorer/commands/SortChildNodes.java [new file with mode: 0644]
org.argeo.jcr.ui.explorer/src/org/argeo/jcr/ui/explorer/dialogs/ChooseNameDialog.java [new file with mode: 0644]
org.argeo.jcr.ui.explorer/src/org/argeo/jcr/ui/explorer/editors/ChildNodesPage.java [new file with mode: 0644]
org.argeo.jcr.ui.explorer/src/org/argeo/jcr/ui/explorer/editors/EmptyNodePage.java [new file with mode: 0644]
org.argeo.jcr.ui.explorer/src/org/argeo/jcr/ui/explorer/editors/GenericJcrQueryEditor.java [new file with mode: 0644]
org.argeo.jcr.ui.explorer/src/org/argeo/jcr/ui/explorer/editors/GenericNodeEditor.java [new file with mode: 0644]
org.argeo.jcr.ui.explorer/src/org/argeo/jcr/ui/explorer/editors/GenericNodeEditorInput.java [new file with mode: 0644]
org.argeo.jcr.ui.explorer/src/org/argeo/jcr/ui/explorer/editors/GenericNodePage.java [new file with mode: 0644]
org.argeo.jcr.ui.explorer/src/org/argeo/jcr/ui/explorer/editors/GenericPropertyPage.java [new file with mode: 0644]
org.argeo.jcr.ui.explorer/src/org/argeo/jcr/ui/explorer/editors/NodeRightsManagementPage.java [new file with mode: 0644]
org.argeo.jcr.ui.explorer/src/org/argeo/jcr/ui/explorer/editors/NodeVersionHistoryPage.java [new file with mode: 0644]
org.argeo.jcr.ui.explorer/src/org/argeo/jcr/ui/explorer/editors/StringNodeEditorInput.java [new file with mode: 0644]
org.argeo.jcr.ui.explorer/src/org/argeo/jcr/ui/explorer/messages.properties [new file with mode: 0644]
org.argeo.jcr.ui.explorer/src/org/argeo/jcr/ui/explorer/model/MaintainedRepositoryElem.java [new file with mode: 0644]
org.argeo.jcr.ui.explorer/src/org/argeo/jcr/ui/explorer/model/RemoteRepositoryElem.java [new file with mode: 0644]
org.argeo.jcr.ui.explorer/src/org/argeo/jcr/ui/explorer/model/RepositoriesElem.java [new file with mode: 0644]
org.argeo.jcr.ui.explorer/src/org/argeo/jcr/ui/explorer/model/RepositoryElem.java [new file with mode: 0644]
org.argeo.jcr.ui.explorer/src/org/argeo/jcr/ui/explorer/model/SingleJcrNodeElem.java [new file with mode: 0644]
org.argeo.jcr.ui.explorer/src/org/argeo/jcr/ui/explorer/model/WorkspaceElem.java [new file with mode: 0644]
org.argeo.jcr.ui.explorer/src/org/argeo/jcr/ui/explorer/providers/FullVersioningTreeContentProvider.java [new file with mode: 0644]
org.argeo.jcr.ui.explorer/src/org/argeo/jcr/ui/explorer/providers/PropertyLabelProvider.java [new file with mode: 0644]
org.argeo.jcr.ui.explorer/src/org/argeo/jcr/ui/explorer/providers/SingleNodeAsTreeContentProvider.java [new file with mode: 0644]
org.argeo.jcr.ui.explorer/src/org/argeo/jcr/ui/explorer/providers/VersionLabelProvider.java [new file with mode: 0644]
org.argeo.jcr.ui.explorer/src/org/argeo/jcr/ui/explorer/utils/GenericNodeDoubleClickListener.java [new file with mode: 0644]
org.argeo.jcr.ui.explorer/src/org/argeo/jcr/ui/explorer/utils/JcrUiUtils.java [new file with mode: 0644]
org.argeo.jcr.ui.explorer/src/org/argeo/jcr/ui/explorer/utils/TreeObjectsComparator.java [new file with mode: 0644]
org.argeo.jcr.ui.explorer/src/org/argeo/jcr/ui/explorer/views/GenericJcrBrowser.java [new file with mode: 0644]
org.argeo.jcr.ui.explorer/src/org/argeo/jcr/ui/explorer/wizards/ChangeRightsWizard.java [new file with mode: 0644]
org.argeo.jcr.ui.explorer/src/org/argeo/jcr/ui/explorer/wizards/ChooseRightsPage.java [new file with mode: 0644]
org.argeo.jcr.ui.explorer/src/org/argeo/jcr/ui/explorer/wizards/ImportFileSystemWizard.java [new file with mode: 0644]
org.argeo.osgi.ui.explorer/.classpath
org.argeo.osgi.ui.explorer/src/main/java/org/argeo/osgi/ui/explorer/OsgiExplorerImages.java [deleted file]
org.argeo.osgi.ui.explorer/src/main/java/org/argeo/osgi/ui/explorer/OsgiExplorerPerspective.java [deleted file]
org.argeo.osgi.ui.explorer/src/main/java/org/argeo/osgi/ui/explorer/OsgiExplorerPlugin.java [deleted file]
org.argeo.osgi.ui.explorer/src/main/java/org/argeo/osgi/ui/explorer/views/BundlesView.java [deleted file]
org.argeo.osgi.ui.explorer/src/main/java/org/argeo/osgi/ui/explorer/views/ModulesView.java [deleted file]
org.argeo.osgi.ui.explorer/src/org/argeo/osgi/ui/explorer/OsgiExplorerImages.java [new file with mode: 0644]
org.argeo.osgi.ui.explorer/src/org/argeo/osgi/ui/explorer/OsgiExplorerPerspective.java [new file with mode: 0644]
org.argeo.osgi.ui.explorer/src/org/argeo/osgi/ui/explorer/OsgiExplorerPlugin.java [new file with mode: 0644]
org.argeo.osgi.ui.explorer/src/org/argeo/osgi/ui/explorer/views/BundlesView.java [new file with mode: 0644]
org.argeo.osgi.ui.explorer/src/org/argeo/osgi/ui/explorer/views/ModulesView.java [new file with mode: 0644]
org.argeo.security.equinox/.classpath
org.argeo.security.equinox/.settings/org.eclipse.pde.core.prefs [deleted file]
org.argeo.security.equinox/build.properties
org.argeo.security.equinox/src/main/java/org/argeo/security/equinox/OsSpringLoginModule.java [deleted file]
org.argeo.security.equinox/src/main/java/org/argeo/security/equinox/SpringLoginModule.java [deleted file]
org.argeo.security.equinox/src/org/argeo/security/equinox/OsSpringLoginModule.java [new file with mode: 0644]
org.argeo.security.equinox/src/org/argeo/security/equinox/SpringLoginModule.java [new file with mode: 0644]
org.argeo.security.ui.admin/.classpath
org.argeo.security.ui.admin/build.properties
org.argeo.security.ui.admin/src/main/java/org/argeo/security/ui/admin/SecurityAdminImages.java [deleted file]
org.argeo.security.ui.admin/src/main/java/org/argeo/security/ui/admin/SecurityAdminPerspective.java [deleted file]
org.argeo.security.ui.admin/src/main/java/org/argeo/security/ui/admin/SecurityAdminPlugin.java [deleted file]
org.argeo.security.ui.admin/src/main/java/org/argeo/security/ui/admin/UserTableComposite.java [deleted file]
org.argeo.security.ui.admin/src/main/java/org/argeo/security/ui/admin/commands/AddRole.java [deleted file]
org.argeo.security.ui.admin/src/main/java/org/argeo/security/ui/admin/commands/DeleteRole.java [deleted file]
org.argeo.security.ui.admin/src/main/java/org/argeo/security/ui/admin/commands/DeleteUser.java [deleted file]
org.argeo.security.ui.admin/src/main/java/org/argeo/security/ui/admin/commands/NewUser.java [deleted file]
org.argeo.security.ui.admin/src/main/java/org/argeo/security/ui/admin/commands/OpenArgeoUserEditor.java [deleted file]
org.argeo.security.ui.admin/src/main/java/org/argeo/security/ui/admin/commands/RefreshRoles.java [deleted file]
org.argeo.security.ui.admin/src/main/java/org/argeo/security/ui/admin/commands/RefreshUsersList.java [deleted file]
org.argeo.security.ui.admin/src/main/java/org/argeo/security/ui/admin/commands/SaveArgeoUser.java [deleted file]
org.argeo.security.ui.admin/src/main/java/org/argeo/security/ui/admin/commands/UserBatchUpdate.java [deleted file]
org.argeo.security.ui.admin/src/main/java/org/argeo/security/ui/admin/editors/ArgeoUserEditor.java [deleted file]
org.argeo.security.ui.admin/src/main/java/org/argeo/security/ui/admin/editors/ArgeoUserEditorInput.java [deleted file]
org.argeo.security.ui.admin/src/main/java/org/argeo/security/ui/admin/editors/DefaultUserMainPage.java [deleted file]
org.argeo.security.ui.admin/src/main/java/org/argeo/security/ui/admin/editors/UserRolesPage.java [deleted file]
org.argeo.security.ui.admin/src/main/java/org/argeo/security/ui/admin/views/RolesView.java [deleted file]
org.argeo.security.ui.admin/src/main/java/org/argeo/security/ui/admin/views/UsersView.java [deleted file]
org.argeo.security.ui.admin/src/main/java/org/argeo/security/ui/admin/wizards/MainUserInfoWizardPage.java [deleted file]
org.argeo.security.ui.admin/src/main/java/org/argeo/security/ui/admin/wizards/NewUserWizard.java [deleted file]
org.argeo.security.ui.admin/src/main/java/org/argeo/security/ui/admin/wizards/UserBatchUpdateWizard.java [deleted file]
org.argeo.security.ui.admin/src/org/argeo/security/ui/admin/SecurityAdminImages.java [new file with mode: 0644]
org.argeo.security.ui.admin/src/org/argeo/security/ui/admin/SecurityAdminPerspective.java [new file with mode: 0644]
org.argeo.security.ui.admin/src/org/argeo/security/ui/admin/SecurityAdminPlugin.java [new file with mode: 0644]
org.argeo.security.ui.admin/src/org/argeo/security/ui/admin/UserTableComposite.java [new file with mode: 0644]
org.argeo.security.ui.admin/src/org/argeo/security/ui/admin/commands/AddRole.java [new file with mode: 0644]
org.argeo.security.ui.admin/src/org/argeo/security/ui/admin/commands/DeleteRole.java [new file with mode: 0644]
org.argeo.security.ui.admin/src/org/argeo/security/ui/admin/commands/DeleteUser.java [new file with mode: 0644]
org.argeo.security.ui.admin/src/org/argeo/security/ui/admin/commands/NewUser.java [new file with mode: 0644]
org.argeo.security.ui.admin/src/org/argeo/security/ui/admin/commands/OpenArgeoUserEditor.java [new file with mode: 0644]
org.argeo.security.ui.admin/src/org/argeo/security/ui/admin/commands/RefreshRoles.java [new file with mode: 0644]
org.argeo.security.ui.admin/src/org/argeo/security/ui/admin/commands/RefreshUsersList.java [new file with mode: 0644]
org.argeo.security.ui.admin/src/org/argeo/security/ui/admin/commands/SaveArgeoUser.java [new file with mode: 0644]
org.argeo.security.ui.admin/src/org/argeo/security/ui/admin/commands/UserBatchUpdate.java [new file with mode: 0644]
org.argeo.security.ui.admin/src/org/argeo/security/ui/admin/editors/ArgeoUserEditor.java [new file with mode: 0644]
org.argeo.security.ui.admin/src/org/argeo/security/ui/admin/editors/ArgeoUserEditorInput.java [new file with mode: 0644]
org.argeo.security.ui.admin/src/org/argeo/security/ui/admin/editors/DefaultUserMainPage.java [new file with mode: 0644]
org.argeo.security.ui.admin/src/org/argeo/security/ui/admin/editors/UserRolesPage.java [new file with mode: 0644]
org.argeo.security.ui.admin/src/org/argeo/security/ui/admin/views/RolesView.java [new file with mode: 0644]
org.argeo.security.ui.admin/src/org/argeo/security/ui/admin/views/UsersView.java [new file with mode: 0644]
org.argeo.security.ui.admin/src/org/argeo/security/ui/admin/wizards/MainUserInfoWizardPage.java [new file with mode: 0644]
org.argeo.security.ui.admin/src/org/argeo/security/ui/admin/wizards/NewUserWizard.java [new file with mode: 0644]
org.argeo.security.ui.admin/src/org/argeo/security/ui/admin/wizards/UserBatchUpdateWizard.java [new file with mode: 0644]
org.argeo.security.ui.rap/.classpath
org.argeo.security.ui.rap/build.properties
org.argeo.security.ui.rap/src/main/java/org/argeo/security/ui/rap/AnonymousEntryPoint.java [deleted file]
org.argeo.security.ui.rap/src/main/java/org/argeo/security/ui/rap/LogoutEntryPoint.java [deleted file]
org.argeo.security.ui.rap/src/main/java/org/argeo/security/ui/rap/NullEntryPoint.java [deleted file]
org.argeo.security.ui.rap/src/main/java/org/argeo/security/ui/rap/RapActionBarAdvisor.java [deleted file]
org.argeo.security.ui.rap/src/main/java/org/argeo/security/ui/rap/RapWindowAdvisor.java [deleted file]
org.argeo.security.ui.rap/src/main/java/org/argeo/security/ui/rap/RapWorkbenchAdvisor.java [deleted file]
org.argeo.security.ui.rap/src/main/java/org/argeo/security/ui/rap/SecureEntryPoint.java [deleted file]
org.argeo.security.ui.rap/src/main/java/org/argeo/security/ui/rap/SecureRapActivator.java [deleted file]
org.argeo.security.ui.rap/src/main/java/org/argeo/security/ui/rap/commands/UserMenu.java [deleted file]
org.argeo.security.ui.rap/src/org/argeo/security/ui/rap/AnonymousEntryPoint.java [new file with mode: 0644]
org.argeo.security.ui.rap/src/org/argeo/security/ui/rap/LogoutEntryPoint.java [new file with mode: 0644]
org.argeo.security.ui.rap/src/org/argeo/security/ui/rap/NullEntryPoint.java [new file with mode: 0644]
org.argeo.security.ui.rap/src/org/argeo/security/ui/rap/RapActionBarAdvisor.java [new file with mode: 0644]
org.argeo.security.ui.rap/src/org/argeo/security/ui/rap/RapWindowAdvisor.java [new file with mode: 0644]
org.argeo.security.ui.rap/src/org/argeo/security/ui/rap/RapWorkbenchAdvisor.java [new file with mode: 0644]
org.argeo.security.ui.rap/src/org/argeo/security/ui/rap/SecureEntryPoint.java [new file with mode: 0644]
org.argeo.security.ui.rap/src/org/argeo/security/ui/rap/SecureRapActivator.java [new file with mode: 0644]
org.argeo.security.ui.rap/src/org/argeo/security/ui/rap/commands/UserMenu.java [new file with mode: 0644]
org.argeo.security.ui.rcp/.classpath
org.argeo.security.ui.rcp/src/main/java/org/argeo/security/ui/rcp/AbstractSecureApplication.java [deleted file]
org.argeo.security.ui.rcp/src/main/java/org/argeo/security/ui/rcp/SecureActionBarAdvisor.java [deleted file]
org.argeo.security.ui.rcp/src/main/java/org/argeo/security/ui/rcp/SecureApplicationActivator.java [deleted file]
org.argeo.security.ui.rcp/src/main/java/org/argeo/security/ui/rcp/SecureRcp.java [deleted file]
org.argeo.security.ui.rcp/src/main/java/org/argeo/security/ui/rcp/SecureWorkbenchAdvisor.java [deleted file]
org.argeo.security.ui.rcp/src/main/java/org/argeo/security/ui/rcp/SecureWorkbenchWindowAdvisor.java [deleted file]
org.argeo.security.ui.rcp/src/org/argeo/security/ui/rcp/AbstractSecureApplication.java [new file with mode: 0644]
org.argeo.security.ui.rcp/src/org/argeo/security/ui/rcp/SecureActionBarAdvisor.java [new file with mode: 0644]
org.argeo.security.ui.rcp/src/org/argeo/security/ui/rcp/SecureApplicationActivator.java [new file with mode: 0644]
org.argeo.security.ui.rcp/src/org/argeo/security/ui/rcp/SecureRcp.java [new file with mode: 0644]
org.argeo.security.ui.rcp/src/org/argeo/security/ui/rcp/SecureWorkbenchAdvisor.java [new file with mode: 0644]
org.argeo.security.ui.rcp/src/org/argeo/security/ui/rcp/SecureWorkbenchWindowAdvisor.java [new file with mode: 0644]
org.argeo.security.ui/.classpath
org.argeo.security.ui/build.properties
org.argeo.security.ui/src/main/java/org/argeo/security/ui/MaintenancePerspective.java [deleted file]
org.argeo.security.ui/src/main/java/org/argeo/security/ui/PrivilegedJob.java [deleted file]
org.argeo.security.ui/src/main/java/org/argeo/security/ui/RolesSourceProvider.java [deleted file]
org.argeo.security.ui/src/main/java/org/argeo/security/ui/SecurityUiPlugin.java [deleted file]
org.argeo.security.ui/src/main/java/org/argeo/security/ui/UserHomePerspective.java [deleted file]
org.argeo.security.ui/src/main/java/org/argeo/security/ui/commands/OpenChangePasswordDialog.java [deleted file]
org.argeo.security.ui/src/main/java/org/argeo/security/ui/commands/OpenHomePerspective.java [deleted file]
org.argeo.security.ui/src/main/java/org/argeo/security/ui/dialogs/AbstractLoginDialog.java [deleted file]
org.argeo.security.ui/src/main/java/org/argeo/security/ui/dialogs/ChangePasswordDialog.java [deleted file]
org.argeo.security.ui/src/main/java/org/argeo/security/ui/dialogs/DefaultLoginDialog.java [deleted file]
org.argeo.security.ui/src/main/java/org/argeo/security/ui/internal/CurrentUser.java [deleted file]
org.argeo.security.ui/src/main/java/org/argeo/security/ui/views/AdminLogView.java [deleted file]
org.argeo.security.ui/src/main/java/org/argeo/security/ui/views/LogContentProvider.java [deleted file]
org.argeo.security.ui/src/main/java/org/argeo/security/ui/views/LogView.java [deleted file]
org.argeo.security.ui/src/main/java/org/argeo/security/ui/views/UserProfile.java [deleted file]
org.argeo.security.ui/src/org/argeo/security/ui/MaintenancePerspective.java [new file with mode: 0644]
org.argeo.security.ui/src/org/argeo/security/ui/PrivilegedJob.java [new file with mode: 0644]
org.argeo.security.ui/src/org/argeo/security/ui/RolesSourceProvider.java [new file with mode: 0644]
org.argeo.security.ui/src/org/argeo/security/ui/SecurityUiPlugin.java [new file with mode: 0644]
org.argeo.security.ui/src/org/argeo/security/ui/UserHomePerspective.java [new file with mode: 0644]
org.argeo.security.ui/src/org/argeo/security/ui/commands/OpenChangePasswordDialog.java [new file with mode: 0644]
org.argeo.security.ui/src/org/argeo/security/ui/commands/OpenHomePerspective.java [new file with mode: 0644]
org.argeo.security.ui/src/org/argeo/security/ui/dialogs/AbstractLoginDialog.java [new file with mode: 0644]
org.argeo.security.ui/src/org/argeo/security/ui/dialogs/ChangePasswordDialog.java [new file with mode: 0644]
org.argeo.security.ui/src/org/argeo/security/ui/dialogs/DefaultLoginDialog.java [new file with mode: 0644]
org.argeo.security.ui/src/org/argeo/security/ui/internal/CurrentUser.java [new file with mode: 0644]
org.argeo.security.ui/src/org/argeo/security/ui/views/AdminLogView.java [new file with mode: 0644]
org.argeo.security.ui/src/org/argeo/security/ui/views/LogContentProvider.java [new file with mode: 0644]
org.argeo.security.ui/src/org/argeo/security/ui/views/LogView.java [new file with mode: 0644]
org.argeo.security.ui/src/org/argeo/security/ui/views/UserProfile.java [new file with mode: 0644]
org.argeo.server.ads.server/bnd.bnd [new file with mode: 0644]
org.argeo.server.ads.server/pom.xml
org.argeo.server.ads/.classpath
org.argeo.server.ads/.settings/org.eclipse.jdt.core.prefs [deleted file]
org.argeo.server.ads/.settings/org.maven.ide.eclipse.prefs [deleted file]
org.argeo.server.ads/build.properties
org.argeo.server.ads/pom.xml
org.argeo.server.ads/src/main/java/org/argeo/server/ads/AdsContainer.java [deleted file]
org.argeo.server.ads/src/org/argeo/server/ads/AdsContainer.java [new file with mode: 0644]
org.argeo.server.jackrabbit/.classpath
org.argeo.server.jackrabbit/bnd.bnd [new file with mode: 0644]
org.argeo.server.jackrabbit/build.properties
org.argeo.server.jackrabbit/pom.xml
org.argeo.server.jackrabbit/src/main/java/org/argeo/jackrabbit/JackrabbitAuthorizations.java [deleted file]
org.argeo.server.jackrabbit/src/main/java/org/argeo/jackrabbit/JackrabbitContainer.java [deleted file]
org.argeo.server.jackrabbit/src/main/java/org/argeo/jackrabbit/JackrabbitDataModelMigration.java [deleted file]
org.argeo.server.jackrabbit/src/main/java/org/argeo/jackrabbit/JackrabbitRepositoryFactory.java [deleted file]
org.argeo.server.jackrabbit/src/main/java/org/argeo/jackrabbit/JackrabbitWrapper.java [deleted file]
org.argeo.server.jackrabbit/src/main/java/org/argeo/jackrabbit/OsgiJackrabbitRepositoryFactory.java [deleted file]
org.argeo.server.jackrabbit/src/main/java/org/argeo/jackrabbit/remote/AbstractJackrabbitHandlerMapping.java [deleted file]
org.argeo.server.jackrabbit/src/main/java/org/argeo/jackrabbit/remote/ExtendedDispatcherServlet.java [deleted file]
org.argeo.server.jackrabbit/src/main/java/org/argeo/jackrabbit/remote/IOHandlerWrapper.java [deleted file]
org.argeo.server.jackrabbit/src/main/java/org/argeo/jackrabbit/remote/IOManagerBean.java [deleted file]
org.argeo.server.jackrabbit/src/main/java/org/argeo/jackrabbit/remote/JcrRemotingHandlerMapping.java [deleted file]
org.argeo.server.jackrabbit/src/main/java/org/argeo/jackrabbit/remote/JcrRemotingServlet.java [deleted file]
org.argeo.server.jackrabbit/src/main/java/org/argeo/jackrabbit/remote/OpenInViewSessionProvider.java [deleted file]
org.argeo.server.jackrabbit/src/main/java/org/argeo/jackrabbit/remote/ScopedSessionProvider.java [deleted file]
org.argeo.server.jackrabbit/src/main/java/org/argeo/jackrabbit/remote/SimpleSessionProvider.java [deleted file]
org.argeo.server.jackrabbit/src/main/java/org/argeo/jackrabbit/remote/SimpleWebdavHandlerMapping.java [deleted file]
org.argeo.server.jackrabbit/src/main/java/org/argeo/jackrabbit/remote/SimpleWebdavServlet.java [deleted file]
org.argeo.server.jackrabbit/src/main/resources/org/argeo/jackrabbit/repository-fs.xml [deleted file]
org.argeo.server.jackrabbit/src/main/resources/org/argeo/jackrabbit/repository-h2.xml [deleted file]
org.argeo.server.jackrabbit/src/main/resources/org/argeo/jackrabbit/repository-memory.xml [deleted file]
org.argeo.server.jackrabbit/src/main/wikitext/design.mediawiki [deleted file]
org.argeo.server.jackrabbit/src/org/argeo/jackrabbit/JackrabbitAuthorizations.java [new file with mode: 0644]
org.argeo.server.jackrabbit/src/org/argeo/jackrabbit/JackrabbitContainer.java [new file with mode: 0644]
org.argeo.server.jackrabbit/src/org/argeo/jackrabbit/JackrabbitDataModelMigration.java [new file with mode: 0644]
org.argeo.server.jackrabbit/src/org/argeo/jackrabbit/JackrabbitRepositoryFactory.java [new file with mode: 0644]
org.argeo.server.jackrabbit/src/org/argeo/jackrabbit/JackrabbitWrapper.java [new file with mode: 0644]
org.argeo.server.jackrabbit/src/org/argeo/jackrabbit/OsgiJackrabbitRepositoryFactory.java [new file with mode: 0644]
org.argeo.server.jackrabbit/src/org/argeo/jackrabbit/remote/AbstractJackrabbitHandlerMapping.java [new file with mode: 0644]
org.argeo.server.jackrabbit/src/org/argeo/jackrabbit/remote/ExtendedDispatcherServlet.java [new file with mode: 0644]
org.argeo.server.jackrabbit/src/org/argeo/jackrabbit/remote/IOHandlerWrapper.java [new file with mode: 0644]
org.argeo.server.jackrabbit/src/org/argeo/jackrabbit/remote/IOManagerBean.java [new file with mode: 0644]
org.argeo.server.jackrabbit/src/org/argeo/jackrabbit/remote/JcrRemotingHandlerMapping.java [new file with mode: 0644]
org.argeo.server.jackrabbit/src/org/argeo/jackrabbit/remote/JcrRemotingServlet.java [new file with mode: 0644]
org.argeo.server.jackrabbit/src/org/argeo/jackrabbit/remote/OpenInViewSessionProvider.java [new file with mode: 0644]
org.argeo.server.jackrabbit/src/org/argeo/jackrabbit/remote/ScopedSessionProvider.java [new file with mode: 0644]
org.argeo.server.jackrabbit/src/org/argeo/jackrabbit/remote/SimpleSessionProvider.java [new file with mode: 0644]
org.argeo.server.jackrabbit/src/org/argeo/jackrabbit/remote/SimpleWebdavHandlerMapping.java [new file with mode: 0644]
org.argeo.server.jackrabbit/src/org/argeo/jackrabbit/remote/SimpleWebdavServlet.java [new file with mode: 0644]
org.argeo.server.jackrabbit/src/org/argeo/jackrabbit/repository-fs.xml [new file with mode: 0644]
org.argeo.server.jackrabbit/src/org/argeo/jackrabbit/repository-h2.xml [new file with mode: 0644]
org.argeo.server.jackrabbit/src/org/argeo/jackrabbit/repository-memory.xml [new file with mode: 0644]
org.argeo.server.rap.webapp/bnd.bnd [new file with mode: 0644]
org.argeo.server.rap.webapp/pom.xml

index 527d8ababf28abecdf0dfe86d86b977d6b54d39c..d2953a684d400476bf716ed6a6c3c3ae486fcd0e 100644 (file)
@@ -1,8 +1,9 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <classpath>
-       <classpathentry kind="src" path="src/main/java"/>
-       <classpathentry kind="src" path="src/main/resources"/>
-       <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6"/>>>
-       <classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
-       <classpathentry kind="output" path="target/classes"/>
+       <classpathentry kind="src" path="src" />
+       <classpathentry kind="con"
+               path="org.eclipse.pde.core.requiredPlugins" />
+       <classpathentry kind="con"
+               path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6" />
+       <classpathentry kind="output" path="bin" />
 </classpath>
diff --git a/org.argeo.jcr.ui.explorer/.settings/org.eclipse.jdt.core.prefs b/org.argeo.jcr.ui.explorer/.settings/org.eclipse.jdt.core.prefs
deleted file mode 100644 (file)
index 992c5d7..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-#Thu Feb 24 08:49:06 CET 2011
-eclipse.preferences.version=1
-org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
-org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.5
-org.eclipse.jdt.core.compiler.compliance=1.5
-org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
-org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
-org.eclipse.jdt.core.compiler.source=1.5
index 9b0c715ca5a3bf2ece7a2d0b5a0db483a2433f5b..410bf3a8bfc36d64c5a3ceb35f78c152022ea64c 100644 (file)
@@ -1,7 +1 @@
-source.. =     src/main/java/,\
-                       src/main/resources
-output.. = target/classes/
-bin.includes = META-INF/,\
-               .,\
-               plugin.xml,\
-               plugin.properties
+source.. =     src/
diff --git a/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/JcrExplorerConstants.java b/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/JcrExplorerConstants.java
deleted file mode 100644 (file)
index a9cb258..0000000
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * Copyright (C) 2007-2012 Argeo GmbH
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *         http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.argeo.jcr.ui.explorer;
-
-/** Constants used across the application. */
-public interface JcrExplorerConstants {
-       /*
-        * MISCEALLENEOUS
-        */
-       public final static String DATE_TIME_FORMAT = "dd/MM/yyyy, HH:mm";
-
-       public final static String PARAM_PATH = "org.argeo.jcr.ui.explorer.nodePath";
-
-}
diff --git a/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/JcrExplorerPerspective.java b/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/JcrExplorerPerspective.java
deleted file mode 100644 (file)
index 2626415..0000000
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * Copyright (C) 2007-2012 Argeo GmbH
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *         http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.argeo.jcr.ui.explorer;
-
-import org.eclipse.ui.IFolderLayout;
-import org.eclipse.ui.IPageLayout;
-import org.eclipse.ui.IPerspectiveFactory;
-
-/** Base perspective for JcrExplorer browser */
-public class JcrExplorerPerspective implements IPerspectiveFactory {
-       public static String BROWSER_VIEW_ID = JcrExplorerPlugin.ID
-                       + ".browserView";
-
-       public void createInitialLayout(IPageLayout layout) {
-               layout.setEditorAreaVisible(true);
-
-               IFolderLayout upperLeft = layout.createFolder(JcrExplorerPlugin.ID
-                               + ".upperLeft", IPageLayout.LEFT, 0.4f, layout.getEditorArea());
-               upperLeft.addView(BROWSER_VIEW_ID);
-
-//             String editorArea = layout.getEditorArea();
-//             String logViewId = "org.argeo.security.ui.logView";
-//             IFolderLayout bottom = layout.createFolder("bottom",
-//                             IPageLayout.BOTTOM, 0.50f, editorArea);
-//             bottom.addView(logViewId);
-       }
-
-}
diff --git a/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/JcrExplorerPlugin.java b/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/JcrExplorerPlugin.java
deleted file mode 100644 (file)
index 3bf9e7f..0000000
+++ /dev/null
@@ -1,107 +0,0 @@
-/*
- * Copyright (C) 2007-2012 Argeo GmbH
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *         http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.argeo.jcr.ui.explorer;
-
-import java.util.ResourceBundle;
-
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.eclipse.jface.resource.ImageDescriptor;
-import org.eclipse.ui.plugin.AbstractUIPlugin;
-import org.osgi.framework.BundleContext;
-
-/**
- * The activator class controls the plug-in life cycle
- */
-public class JcrExplorerPlugin extends AbstractUIPlugin {
-       private final static Log log = LogFactory.getLog(JcrExplorerPlugin.class);
-       private ResourceBundle messages;
-
-       // The plug-in ID
-       public static final String ID = "org.argeo.jcr.ui.explorer"; //$NON-NLS-1$
-
-       // The shared instance
-       private static JcrExplorerPlugin plugin;
-
-       /**
-        * The constructor
-        */
-       public JcrExplorerPlugin() {
-       }
-
-       /*
-        * (non-Javadoc)
-        * 
-        * @see
-        * org.eclipse.ui.plugin.AbstractUIPlugin#start(org.osgi.framework.BundleContext
-        * )
-        */
-       public void start(BundleContext context) throws Exception {
-               super.start(context);
-               plugin = this;
-               messages = ResourceBundle
-                               .getBundle("org.argeo.jcr.ui.explorer.messages");
-
-       }
-
-       /*
-        * (non-Javadoc)
-        * 
-        * @see
-        * org.eclipse.ui.plugin.AbstractUIPlugin#stop(org.osgi.framework.BundleContext
-        * )
-        */
-       public void stop(BundleContext context) throws Exception {
-               plugin = null;
-               super.stop(context);
-       }
-
-       /**
-        * Returns the shared instance
-        * 
-        * @return the shared instance
-        */
-       public static JcrExplorerPlugin getDefault() {
-               return plugin;
-       }
-
-       public static ImageDescriptor getImageDescriptor(String path) {
-               return imageDescriptorFromPlugin(ID, path);
-       }
-
-       /** Returns the internationalized label for the given key */
-       public static String getMessage(String key) {
-               try {
-                       return getDefault().messages.getString(key);
-               } catch (NullPointerException npe) {
-                       log.warn(key + " not found.");
-                       return key;
-               }
-       }
-
-       /**
-        * Gives access to the internationalization message bundle. Returns null in
-        * case the ClientUiPlugin is not started (for JUnit tests, by instance)
-        */
-       public static ResourceBundle getMessagesBundle() {
-               if (getDefault() != null)
-                       // To avoid NPE
-                       return getDefault().messages;
-               else
-                       return null;
-       }
-
-}
diff --git a/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/JcrExplorerView.java b/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/JcrExplorerView.java
deleted file mode 100644 (file)
index 01a957a..0000000
+++ /dev/null
@@ -1,22 +0,0 @@
-/*
- * Copyright (C) 2007-2012 Argeo GmbH
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *         http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.argeo.jcr.ui.explorer;
-
-import org.argeo.jcr.ui.explorer.views.GenericJcrBrowser;
-
-public class JcrExplorerView extends GenericJcrBrowser {
-
-}
diff --git a/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/browser/NodeContentProvider.java b/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/browser/NodeContentProvider.java
deleted file mode 100644 (file)
index fb6bd1a..0000000
+++ /dev/null
@@ -1,197 +0,0 @@
-/*
- * Copyright (C) 2007-2012 Argeo GmbH
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *         http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.argeo.jcr.ui.explorer.browser;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Comparator;
-import java.util.List;
-
-import javax.jcr.Node;
-import javax.jcr.RepositoryException;
-import javax.jcr.RepositoryFactory;
-import javax.jcr.Session;
-import javax.jcr.nodetype.NodeType;
-
-import org.argeo.eclipse.ui.TreeParent;
-import org.argeo.jcr.ArgeoJcrConstants;
-import org.argeo.jcr.RepositoryRegister;
-import org.argeo.jcr.UserJcrUtils;
-import org.argeo.jcr.ui.explorer.model.RepositoriesElem;
-import org.argeo.jcr.ui.explorer.model.SingleJcrNodeElem;
-import org.argeo.util.security.Keyring;
-import org.eclipse.jface.viewers.ITreeContentProvider;
-import org.eclipse.jface.viewers.Viewer;
-
-/**
- * Implementation of the {@code ITreeContentProvider} to display multiple
- * repository environment in a tree like structure
- * 
- */
-public class NodeContentProvider implements ITreeContentProvider {
-       final private RepositoryRegister repositoryRegister;
-       final private RepositoryFactory repositoryFactory;
-       /**
-        * A session of the logged in user on the default workspace of the node
-        * repository.
-        */
-       final private Session userSession;
-       final private Keyring keyring;
-       private boolean sortChildren;
-
-       // reference for cleaning
-       private SingleJcrNodeElem homeNode = null;
-       private RepositoriesElem repositoriesNode = null;
-
-       // Utils
-       private TreeBrowserComparator itemComparator = new TreeBrowserComparator();
-
-       public NodeContentProvider(Session userSession, Keyring keyring,
-                       RepositoryRegister repositoryRegister,
-                       RepositoryFactory repositoryFactory, Boolean sortChildren) {
-               this.userSession = userSession;
-               this.keyring = keyring;
-               this.repositoryRegister = repositoryRegister;
-               this.repositoryFactory = repositoryFactory;
-               this.sortChildren = sortChildren;
-       }
-
-       public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
-               if (newInput == null)// dispose
-                       return;
-
-               if (userSession != null) {
-                       Node userHome = UserJcrUtils.getUserHome(userSession);
-                       if (userHome != null) {
-                               // TODO : find a way to dynamically get alias for the node
-                               if (homeNode != null)
-                                       homeNode.dispose();
-                               homeNode = new SingleJcrNodeElem(null, userHome,
-                                               userSession.getUserID(), ArgeoJcrConstants.ALIAS_NODE);
-                       }
-               }
-               if (repositoryRegister != null) {
-                       if (repositoriesNode != null)
-                               repositoriesNode.dispose();
-                       repositoriesNode = new RepositoriesElem("Repositories",
-                                       repositoryRegister, repositoryFactory, null, userSession,
-                                       keyring);
-               }
-       }
-
-       /**
-        * Sends back the first level of the Tree. Independent from inputElement
-        * that can be null
-        */
-       public Object[] getElements(Object inputElement) {
-               List<Object> objs = new ArrayList<Object>();
-               if (homeNode != null)
-                       objs.add(homeNode);
-               if (repositoriesNode != null)
-                       objs.add(repositoriesNode);
-               return objs.toArray();
-       }
-
-       public Object[] getChildren(Object parentElement) {
-               if (parentElement instanceof TreeParent) {
-                       if (sortChildren) {
-                               // TreeParent[] arr = (TreeParent[]) ((TreeParent)
-                               // parentElement)
-                               // .getChildren();
-                               Object[] tmpArr = ((TreeParent) parentElement).getChildren();
-                               TreeParent[] arr = new TreeParent[tmpArr.length];
-                               for (int i = 0; i < tmpArr.length; i++)
-                                       arr[i] = (TreeParent) tmpArr[i];
-
-                               Arrays.sort(arr, itemComparator);
-                               return arr;
-                       } else
-                               return ((TreeParent) parentElement).getChildren();
-
-               } else {
-                       return new Object[0];
-               }
-       }
-
-       /**
-        * Sets whether the content provider should order the children nodes or not.
-        * It is user duty to call a full refresh of the tree after changing this
-        * parameter.
-        */
-       public void setSortChildren(boolean sortChildren) {
-               this.sortChildren = sortChildren;
-       }
-
-       public Object getParent(Object element) {
-               if (element instanceof TreeParent) {
-                       return ((TreeParent) element).getParent();
-               } else
-                       return null;
-       }
-
-       public boolean hasChildren(Object element) {
-               if (element instanceof RepositoriesElem) {
-                       RepositoryRegister rr = ((RepositoriesElem) element)
-                                       .getRepositoryRegister();
-                       return rr.getRepositories().size() > 0;
-               } else if (element instanceof TreeParent) {
-                       TreeParent tp = (TreeParent) element;
-                       return tp.hasChildren();
-               }
-               return false;
-       }
-
-       public void dispose() {
-               if (homeNode != null)
-                       homeNode.dispose();
-               if (repositoriesNode != null) {
-                       // logs out open sessions
-                       // see https://bugzilla.argeo.org/show_bug.cgi?id=23
-                       repositoriesNode.dispose();
-               }
-       }
-
-       /**
-        * Specific comparator for this view. See spec in BUG :
-        * https://www.argeo.org/bugzilla/show_bug.cgi?id=139
-        */
-       private class TreeBrowserComparator implements Comparator<TreeParent> {
-
-               public int category(TreeParent element) {
-                       if (element instanceof SingleJcrNodeElem) {
-                               Node node = ((SingleJcrNodeElem) element).getNode();
-                               try {
-                                       if (node.isNodeType(NodeType.NT_FOLDER))
-                                               return 5;
-                               } catch (RepositoryException e) {
-                                       // TODO Auto-generated catch block
-                                       e.printStackTrace();
-                               }
-                       }
-                       return 10;
-               }
-
-               public int compare(TreeParent o1, TreeParent o2) {
-                       int cat1 = category(o1);
-                       int cat2 = category(o2);
-
-                       if (cat1 != cat2) {
-                               return cat1 - cat2;
-                       }
-                       return o1.getName().compareTo(o2.getName());
-               }
-       }
-}
\ No newline at end of file
diff --git a/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/browser/NodeLabelProvider.java b/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/browser/NodeLabelProvider.java
deleted file mode 100644 (file)
index d6d593c..0000000
+++ /dev/null
@@ -1,86 +0,0 @@
-/*
- * Copyright (C) 2007-2012 Argeo GmbH
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *         http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.argeo.jcr.ui.explorer.browser;
-
-import javax.jcr.Node;
-import javax.jcr.RepositoryException;
-import javax.jcr.nodetype.NodeType;
-
-import org.argeo.ArgeoException;
-import org.argeo.eclipse.ui.jcr.DefaultNodeLabelProvider;
-import org.argeo.eclipse.ui.jcr.JcrImages;
-import org.argeo.jcr.ui.explorer.model.RemoteRepositoryElem;
-import org.argeo.jcr.ui.explorer.model.RepositoriesElem;
-import org.argeo.jcr.ui.explorer.model.RepositoryElem;
-import org.argeo.jcr.ui.explorer.model.SingleJcrNodeElem;
-import org.argeo.jcr.ui.explorer.model.WorkspaceElem;
-import org.eclipse.swt.graphics.Image;
-
-public class NodeLabelProvider extends DefaultNodeLabelProvider {
-       // Images
-
-       public String getText(Object element) {
-               try {
-                       if (element instanceof SingleJcrNodeElem) {
-                               SingleJcrNodeElem sjn = (SingleJcrNodeElem) element;
-                               return getText(sjn.getNode());
-                       } else
-                               return super.getText(element);
-               } catch (RepositoryException e) {
-                       throw new ArgeoException(
-                                       "Unexpected JCR error while getting node name.");
-               }
-       }
-
-       protected String getText(Node node) throws RepositoryException {
-               String label = node.getName();
-               StringBuffer mixins = new StringBuffer("");
-               for (NodeType type : node.getMixinNodeTypes())
-                       mixins.append(' ').append(type.getName());
-
-               return label + " [" + node.getPrimaryNodeType().getName() + mixins
-                               + "]";
-       }
-
-       @Override
-       public Image getImage(Object element) {
-               if (element instanceof RemoteRepositoryElem) {
-                       if (((RemoteRepositoryElem) element).isConnected())
-                               return JcrImages.REMOTE_CONNECTED;
-                       else
-                               return JcrImages.REMOTE_DISCONNECTED;
-               } else if (element instanceof RepositoryElem) {
-                       if (((RepositoryElem) element).isConnected())
-                               return JcrImages.REPOSITORY_CONNECTED;
-                       else
-                               return JcrImages.REPOSITORY_DISCONNECTED;
-               } else if (element instanceof WorkspaceElem) {
-                       if (((WorkspaceElem) element).isConnected())
-                               return JcrImages.WORKSPACE_CONNECTED;
-                       else
-                               return JcrImages.WORKSPACE_DISCONNECTED;
-               } else if (element instanceof RepositoriesElem) {
-                       return JcrImages.REPOSITORIES;
-               } else if (element instanceof SingleJcrNodeElem)
-                       try {
-                               return super.getImage(((SingleJcrNodeElem) element).getNode());
-                       } catch (RepositoryException e) {
-                               return null;
-                       }
-               return super.getImage(element);
-       }
-
-}
diff --git a/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/browser/PropertiesContentProvider.java b/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/browser/PropertiesContentProvider.java
deleted file mode 100644 (file)
index d39f319..0000000
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * Copyright (C) 2007-2012 Argeo GmbH
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *         http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.argeo.jcr.ui.explorer.browser;
-
-import java.util.Set;
-import java.util.TreeSet;
-
-import javax.jcr.Node;
-import javax.jcr.Property;
-import javax.jcr.PropertyIterator;
-import javax.jcr.RepositoryException;
-
-import org.argeo.ArgeoException;
-import org.argeo.eclipse.ui.jcr.utils.JcrItemsComparator;
-import org.eclipse.jface.viewers.IStructuredContentProvider;
-import org.eclipse.jface.viewers.Viewer;
-
-public class PropertiesContentProvider implements IStructuredContentProvider {
-       private JcrItemsComparator itemComparator = new JcrItemsComparator();
-
-       public void dispose() {
-       }
-
-       public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
-       }
-
-       public Object[] getElements(Object inputElement) {
-               try {
-                       if (inputElement instanceof Node) {
-                               Set<Property> props = new TreeSet<Property>(itemComparator);
-                               PropertyIterator pit = ((Node) inputElement).getProperties();
-                               while (pit.hasNext())
-                                       props.add(pit.nextProperty());
-                               return props.toArray();
-                       }
-                       return new Object[] {};
-               } catch (RepositoryException e) {
-                       throw new ArgeoException("Cannot get element for " + inputElement,
-                                       e);
-               }
-       }
-
-}
diff --git a/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/commands/AddFolderNode.java b/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/commands/AddFolderNode.java
deleted file mode 100644 (file)
index 0389aee..0000000
+++ /dev/null
@@ -1,101 +0,0 @@
-/*
- * Copyright (C) 2007-2012 Argeo GmbH
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *         http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.argeo.jcr.ui.explorer.commands;
-
-import javax.jcr.Node;
-import javax.jcr.RepositoryException;
-import javax.jcr.nodetype.NodeType;
-
-import org.argeo.eclipse.ui.ErrorFeedback;
-import org.argeo.eclipse.ui.TreeParent;
-import org.argeo.eclipse.ui.dialogs.SingleValue;
-import org.argeo.eclipse.ui.jcr.JcrUiPlugin;
-import org.argeo.jcr.ui.explorer.JcrExplorerPlugin;
-import org.argeo.jcr.ui.explorer.model.SingleJcrNodeElem;
-import org.argeo.jcr.ui.explorer.model.WorkspaceElem;
-import org.argeo.jcr.ui.explorer.views.GenericJcrBrowser;
-import org.eclipse.core.commands.AbstractHandler;
-import org.eclipse.core.commands.ExecutionEvent;
-import org.eclipse.core.commands.ExecutionException;
-import org.eclipse.jface.viewers.ISelection;
-import org.eclipse.jface.viewers.IStructuredSelection;
-import org.eclipse.ui.handlers.HandlerUtil;
-
-/**
- * Adds a node of type nt:folder, only on {@link SingleJcrNodeElem} and
- * {@link WorkspaceElem} TreeObject types.
- * 
- * 
- * This handler assumes that a selection provider is available and picks only
- * first selected item. It is UI's job to enable the command only when the
- * selection contains one and only one element. Thus no parameter is passed
- * through the command.
- * 
- * This handler is still 'hard linked' to a GenericJcrBrowser view to enable
- * correct tree refresh when a node is added. This must be corrected in future
- * versions.
- */
-public class AddFolderNode extends AbstractHandler {
-
-       public final static String ID = JcrExplorerPlugin.ID + ".addFolderNode";
-
-       // public final static String DEFAULT_LABEL = JcrExplorerPlugin
-       // .getMessage("addFolderNodeCmdLbl");
-       // public final static String DEFAULT_ICON_REL_PATH = "icons/addRepo.gif";
-
-       public Object execute(ExecutionEvent event) throws ExecutionException {
-
-               ISelection selection = HandlerUtil.getActiveWorkbenchWindow(event)
-                               .getActivePage().getSelection();
-
-               GenericJcrBrowser view = (GenericJcrBrowser) HandlerUtil
-                               .getActiveWorkbenchWindow(event).getActivePage()
-                               .findView(HandlerUtil.getActivePartId(event));
-
-               if (selection != null && !selection.isEmpty()
-                               && selection instanceof IStructuredSelection) {
-                       Object obj = ((IStructuredSelection) selection).getFirstElement();
-                       TreeParent treeParentNode = null;
-                       Node jcrParentNode = null;
-
-                       if (obj instanceof SingleJcrNodeElem) {
-                               treeParentNode = (TreeParent) obj;
-                               jcrParentNode = ((SingleJcrNodeElem) treeParentNode).getNode();
-                       } else if (obj instanceof WorkspaceElem) {
-                               treeParentNode = (TreeParent) obj;
-                               jcrParentNode = ((WorkspaceElem) treeParentNode).getRootNode();
-                       } else
-                               return null;
-
-                       String folderName = SingleValue.ask("Folder name",
-                                       "Enter folder name");
-                       if (folderName != null) {
-                               try {
-                                       jcrParentNode.addNode(folderName, NodeType.NT_FOLDER);
-                                       jcrParentNode.getSession().save();
-                                       view.nodeAdded(treeParentNode);
-                               } catch (RepositoryException e) {
-                                       ErrorFeedback.show("Cannot create folder " + folderName
-                                                       + " under " + treeParentNode, e);
-                               }
-                       }
-               } else {
-                       ErrorFeedback.show(JcrUiPlugin
-                                       .getMessage("errorUnvalidNtFolderNodeType"));
-               }
-               return null;
-       }
-}
diff --git a/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/commands/AddPrivileges.java b/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/commands/AddPrivileges.java
deleted file mode 100644 (file)
index 829290e..0000000
+++ /dev/null
@@ -1,79 +0,0 @@
-/*
- * Copyright (C) 2007-2012 Argeo GmbH
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *         http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.argeo.jcr.ui.explorer.commands;
-
-import javax.jcr.Node;
-import javax.jcr.RepositoryException;
-
-import org.argeo.ArgeoException;
-import org.argeo.eclipse.ui.ErrorFeedback;
-import org.argeo.eclipse.ui.TreeParent;
-import org.argeo.jcr.ui.explorer.JcrExplorerPlugin;
-import org.argeo.jcr.ui.explorer.model.SingleJcrNodeElem;
-import org.argeo.jcr.ui.explorer.model.WorkspaceElem;
-import org.argeo.jcr.ui.explorer.wizards.ChangeRightsWizard;
-import org.eclipse.core.commands.AbstractHandler;
-import org.eclipse.core.commands.ExecutionEvent;
-import org.eclipse.core.commands.ExecutionException;
-import org.eclipse.jface.viewers.ISelection;
-import org.eclipse.jface.viewers.IStructuredSelection;
-import org.eclipse.jface.wizard.WizardDialog;
-import org.eclipse.ui.handlers.HandlerUtil;
-
-/**
- * Open a dialog to change rights on the selected node.
- */
-
-public class AddPrivileges extends AbstractHandler {
-       public final static String ID = JcrExplorerPlugin.ID + ".addPrivileges";
-
-       public Object execute(ExecutionEvent event) throws ExecutionException {
-
-               ISelection selection = HandlerUtil.getActiveWorkbenchWindow(event)
-                               .getActivePage().getSelection();
-               if (selection != null && !selection.isEmpty()
-                               && selection instanceof IStructuredSelection) {
-                       Object obj = ((IStructuredSelection) selection).getFirstElement();
-                       TreeParent treeParentNode = null;
-                       Node jcrParentNode = null;
-
-                       if (obj instanceof SingleJcrNodeElem) {
-                               treeParentNode = (TreeParent) obj;
-                               jcrParentNode = ((SingleJcrNodeElem) treeParentNode).getNode();
-                       } else if (obj instanceof WorkspaceElem) {
-                               treeParentNode = (TreeParent) obj;
-                               jcrParentNode = ((WorkspaceElem) treeParentNode).getRootNode();
-                       } else
-                               return null;
-
-                       try {
-                               ChangeRightsWizard wizard = new ChangeRightsWizard(
-                                               jcrParentNode.getSession(), jcrParentNode.getPath());
-                               WizardDialog dialog = new WizardDialog(
-                                               HandlerUtil.getActiveShell(event), wizard);
-                               dialog.open();
-                               return null;
-                       } catch (RepositoryException re) {
-                               throw new ArgeoException(
-                                               "Unexpected error while creating the new workspace.",
-                                               re);
-                       }
-               } else {
-                       ErrorFeedback.show("Cannot add privileges");
-               }
-               return null;
-       }
-}
\ No newline at end of file
diff --git a/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/commands/AddRemoteRepository.java b/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/commands/AddRemoteRepository.java
deleted file mode 100644 (file)
index e41edfc..0000000
+++ /dev/null
@@ -1,230 +0,0 @@
-/*
- * Copyright (C) 2007-2012 Argeo GmbH
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *         http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.argeo.jcr.ui.explorer.commands;
-
-import java.net.URI;
-import java.util.Hashtable;
-
-import javax.jcr.Node;
-import javax.jcr.Repository;
-import javax.jcr.RepositoryFactory;
-import javax.jcr.Session;
-import javax.jcr.SimpleCredentials;
-
-import org.argeo.ArgeoException;
-import org.argeo.eclipse.ui.ErrorFeedback;
-import org.argeo.eclipse.ui.utils.CommandUtils;
-import org.argeo.jcr.ArgeoJcrConstants;
-import org.argeo.jcr.ArgeoNames;
-import org.argeo.jcr.ArgeoTypes;
-import org.argeo.jcr.JcrUtils;
-import org.argeo.jcr.UserJcrUtils;
-import org.argeo.jcr.ui.explorer.JcrExplorerConstants;
-import org.argeo.util.security.Keyring;
-import org.eclipse.core.commands.AbstractHandler;
-import org.eclipse.core.commands.ExecutionEvent;
-import org.eclipse.core.commands.ExecutionException;
-import org.eclipse.jface.dialogs.Dialog;
-import org.eclipse.jface.dialogs.IMessageProvider;
-import org.eclipse.jface.dialogs.MessageDialog;
-import org.eclipse.jface.dialogs.TitleAreaDialog;
-import org.eclipse.swt.SWT;
-import org.eclipse.swt.events.SelectionAdapter;
-import org.eclipse.swt.events.SelectionEvent;
-import org.eclipse.swt.graphics.Point;
-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.Display;
-import org.eclipse.swt.widgets.Label;
-import org.eclipse.swt.widgets.Shell;
-import org.eclipse.swt.widgets.Text;
-
-/**
- * Connect to a remote repository and, if successful publish it as an OSGi
- * service.
- */
-public class AddRemoteRepository extends AbstractHandler implements
-               JcrExplorerConstants, ArgeoNames {
-
-       private RepositoryFactory repositoryFactory;
-       private Repository nodeRepository;
-       private Keyring keyring;
-
-       public Object execute(ExecutionEvent event) throws ExecutionException {
-               RemoteRepositoryLoginDialog dlg = new RemoteRepositoryLoginDialog(
-                               Display.getDefault().getActiveShell());
-               if (dlg.open() == Dialog.OK) {
-                       CommandUtils.callCommand(Refresh.ID);
-               }
-               return null;
-       }
-
-       public void setRepositoryFactory(RepositoryFactory repositoryFactory) {
-               this.repositoryFactory = repositoryFactory;
-       }
-
-       public void setKeyring(Keyring keyring) {
-               this.keyring = keyring;
-       }
-
-       public void setNodeRepository(Repository nodeRepository) {
-               this.nodeRepository = nodeRepository;
-       }
-
-       class RemoteRepositoryLoginDialog extends TitleAreaDialog {
-               private Text name;
-               private Text uri;
-               private Text username;
-               private Text password;
-               private Button saveInKeyring;
-
-               public RemoteRepositoryLoginDialog(Shell parentShell) {
-                       super(parentShell);
-               }
-
-               protected Point getInitialSize() {
-                       return new Point(600, 400);
-               }
-
-               protected Control createDialogArea(Composite parent) {
-                       Composite dialogarea = (Composite) super.createDialogArea(parent);
-                       dialogarea.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true,
-                                       true));
-                       Composite composite = new Composite(dialogarea, SWT.NONE);
-                       composite.setLayout(new GridLayout(2, false));
-                       composite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true,
-                                       false));
-                       setMessage("Login to remote repository", IMessageProvider.NONE);
-                       name = createLT(composite, "Name", "remoteRepository");
-                       uri = createLT(composite, "URI",
-                                       "http://localhost:7070/data/jcr/node");
-                       username = createLT(composite, "User", "");
-                       password = createLP(composite, "Password");
-
-                       saveInKeyring = createLC(composite, "Remember password", false);
-                       parent.pack();
-                       return composite;
-               }
-
-               @Override
-               protected void createButtonsForButtonBar(Composite parent) {
-                       super.createButtonsForButtonBar(parent);
-                       Button test = createButton(parent, 2, "Test", false);
-                       test.addSelectionListener(new SelectionAdapter() {
-                               public void widgetSelected(SelectionEvent arg0) {
-                                       testConnection();
-                               }
-                       });
-               }
-
-               void testConnection() {
-                       Session session = null;
-                       try {
-                               URI checkedUri = new URI(uri.getText());
-                               String checkedUriStr = checkedUri.toString();
-
-                               Hashtable<String, String> params = new Hashtable<String, String>();
-                               params.put(ArgeoJcrConstants.JCR_REPOSITORY_URI, checkedUriStr);
-                               Repository repository = repositoryFactory.getRepository(params);
-                               if (username.getText().trim().equals("")) {// anonymous
-                                       session = repository.login();
-                               } else {
-                                       // FIXME use getTextChars() when upgrading to 3.7
-                                       // see https://bugs.eclipse.org/bugs/show_bug.cgi?id=297412
-                                       char[] pwd = password.getText().toCharArray();
-                                       SimpleCredentials sc = new SimpleCredentials(
-                                                       username.getText(), pwd);
-                                       session = repository.login(sc);
-                                       MessageDialog.openInformation(getParentShell(), "Success",
-                                                       "Connection to '" + uri.getText() + "' successful");
-                               }
-                       } catch (Exception e) {
-                               ErrorFeedback.show(
-                                               "Connection test failed for " + uri.getText(), e);
-                       } finally {
-                               JcrUtils.logoutQuietly(session);
-                       }
-               }
-
-               @Override
-               protected void okPressed() {
-                       Session nodeSession = null;
-                       try {
-                               nodeSession = nodeRepository.login();
-                               Node home = UserJcrUtils.getUserHome(nodeSession);
-
-                               Node remote = home.hasNode(ARGEO_REMOTE) ? home
-                                               .getNode(ARGEO_REMOTE) : home.addNode(ARGEO_REMOTE);
-                               if (remote.hasNode(name.getText()))
-                                       throw new ArgeoException(
-                                                       "There is already a remote repository named "
-                                                                       + name.getText());
-                               Node remoteRepository = remote.addNode(name.getText(),
-                                               ArgeoTypes.ARGEO_REMOTE_REPOSITORY);
-                               remoteRepository.setProperty(ARGEO_URI, uri.getText());
-                               remoteRepository.setProperty(ARGEO_USER_ID, username.getText());
-                               nodeSession.save();
-                               if (saveInKeyring.getSelection()) {
-                                       String pwdPath = remoteRepository.getPath() + '/'
-                                                       + ARGEO_PASSWORD;
-                                       keyring.set(pwdPath, password.getText().toCharArray());
-                               }
-                               nodeSession.save();
-                               MessageDialog.openInformation(
-                                               getParentShell(),
-                                               "Repository Added",
-                                               "Remote repository '" + username.getText() + "@"
-                                                               + uri.getText() + "' added");
-
-                               super.okPressed();
-                       } catch (Exception e) {
-                               ErrorFeedback.show("Cannot add remote repository", e);
-                       } finally {
-                               JcrUtils.logoutQuietly(nodeSession);
-                       }
-               }
-
-               /** Creates label and text. */
-               protected Text createLT(Composite parent, String label, String initial) {
-                       new Label(parent, SWT.NONE).setText(label);
-                       Text text = new Text(parent, SWT.SINGLE | SWT.LEAD | SWT.BORDER);
-                       text.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
-                       text.setText(initial);
-                       return text;
-               }
-
-               /** Creates label and check. */
-               protected Button createLC(Composite parent, String label,
-                               Boolean initial) {
-                       new Label(parent, SWT.NONE).setText(label);
-                       Button check = new Button(parent, SWT.CHECK);
-                       check.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
-                       check.setSelection(initial);
-                       return check;
-               }
-
-               protected Text createLP(Composite parent, String label) {
-                       new Label(parent, SWT.NONE).setText(label);
-                       Text text = new Text(parent, SWT.SINGLE | SWT.LEAD | SWT.BORDER
-                                       | SWT.PASSWORD);
-                       text.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
-                       return text;
-               }
-       }
-}
diff --git a/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/commands/CreateWorkspace.java b/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/commands/CreateWorkspace.java
deleted file mode 100644 (file)
index e579630..0000000
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * Copyright (C) 2007-2012 Argeo GmbH
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *         http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.argeo.jcr.ui.explorer.commands;
-
-import java.util.Arrays;
-
-import org.argeo.eclipse.ui.ErrorFeedback;
-import org.argeo.eclipse.ui.dialogs.SingleValue;
-import org.argeo.jcr.ui.explorer.JcrExplorerPlugin;
-import org.argeo.jcr.ui.explorer.model.RepositoryElem;
-import org.argeo.jcr.ui.explorer.views.GenericJcrBrowser;
-import org.eclipse.core.commands.AbstractHandler;
-import org.eclipse.core.commands.ExecutionEvent;
-import org.eclipse.core.commands.ExecutionException;
-import org.eclipse.jface.viewers.ISelection;
-import org.eclipse.jface.viewers.IStructuredSelection;
-import org.eclipse.ui.handlers.HandlerUtil;
-
-/** Creates a new JCR workspace */
-public class CreateWorkspace extends AbstractHandler {
-
-       public final static String ID = JcrExplorerPlugin.ID + ".addFolderNode";
-
-       public Object execute(ExecutionEvent event) throws ExecutionException {
-
-               ISelection selection = HandlerUtil.getActiveWorkbenchWindow(event)
-                               .getActivePage().getSelection();
-
-               GenericJcrBrowser view = (GenericJcrBrowser) HandlerUtil
-                               .getActiveWorkbenchWindow(event).getActivePage()
-                               .findView(HandlerUtil.getActivePartId(event));
-
-               if (selection != null && !selection.isEmpty()
-                               && selection instanceof IStructuredSelection) {
-                       Object obj = ((IStructuredSelection) selection).getFirstElement();
-                       if (!(obj instanceof RepositoryElem))
-                               return null;
-
-                       RepositoryElem repositoryNode = (RepositoryElem) obj;
-                       String workspaceName = SingleValue.ask("Workspace name",
-                                       "Enter workspace name");
-                       if (workspaceName != null) {
-                               if (Arrays.asList(repositoryNode.getAccessibleWorkspaceNames())
-                                               .contains(workspaceName)) {
-                                       ErrorFeedback.show("Workspace " + workspaceName
-                                                       + " already exists.");
-                               } else {
-                                       repositoryNode.createWorkspace(workspaceName);
-                                       view.nodeAdded(repositoryNode);
-                               }
-                       }
-               } else {
-                       ErrorFeedback.show("Cannot create workspace");
-               }
-               return null;
-       }
-}
diff --git a/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/commands/DeleteNodes.java b/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/commands/DeleteNodes.java
deleted file mode 100644 (file)
index 26d4cdd..0000000
+++ /dev/null
@@ -1,118 +0,0 @@
-/*
- * Copyright (C) 2007-2012 Argeo GmbH
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *         http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.argeo.jcr.ui.explorer.commands;
-
-import java.util.Iterator;
-
-import javax.jcr.Node;
-import javax.jcr.RepositoryException;
-
-import org.argeo.ArgeoException;
-import org.argeo.eclipse.ui.ErrorFeedback;
-import org.argeo.eclipse.ui.TreeParent;
-import org.argeo.jcr.ui.explorer.model.SingleJcrNodeElem;
-import org.argeo.jcr.ui.explorer.model.WorkspaceElem;
-import org.argeo.jcr.ui.explorer.views.GenericJcrBrowser;
-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.jface.viewers.IStructuredSelection;
-import org.eclipse.ui.handlers.HandlerUtil;
-
-/**
- * Deletes the selected nodes: both in the JCR repository and in the UI view.
- * Warning no check is done, except implementation dependent native checks,
- * handle with care.
- * 
- * This handler is still 'hard linked' to a GenericJcrBrowser view to enable
- * correct tree refresh when a node is added. This must be corrected in future
- * versions.
- */
-public class DeleteNodes extends AbstractHandler {
-       public Object execute(ExecutionEvent event) throws ExecutionException {
-               ISelection selection = HandlerUtil.getActiveWorkbenchWindow(event)
-                               .getActivePage().getSelection();
-               if (selection == null || !(selection instanceof IStructuredSelection))
-                       return null;
-
-               GenericJcrBrowser view = (GenericJcrBrowser) HandlerUtil
-                               .getActiveWorkbenchWindow(event).getActivePage()
-                               .findView(HandlerUtil.getActivePartId(event));
-
-               // confirmation
-               StringBuffer buf = new StringBuffer("");
-               Iterator<?> lst = ((IStructuredSelection) selection).iterator();
-               while (lst.hasNext()) {
-                       SingleJcrNodeElem sjn = ((SingleJcrNodeElem) lst.next());
-                       buf.append(sjn.getName()).append(' ');
-               }
-               Boolean ok = MessageDialog.openConfirm(
-                               HandlerUtil.getActiveShell(event), "Confirm deletion",
-                               "Do you want to delete " + buf + "?");
-
-               // operation
-               if (ok) {
-                       Iterator<?> it = ((IStructuredSelection) selection).iterator();
-                       Object obj = null;
-                       SingleJcrNodeElem ancestor = null;
-                       WorkspaceElem rootAncestor = null;
-                       try {
-                               while (it.hasNext()) {
-                                       obj = it.next();
-                                       if (obj instanceof SingleJcrNodeElem) {
-                                               // Cache objects
-                                               SingleJcrNodeElem sjn = (SingleJcrNodeElem) obj;
-                                               TreeParent tp = (TreeParent) sjn.getParent();
-                                               Node node = sjn.getNode();
-
-                                               // Jcr Remove
-                                               node.remove();
-                                               node.getSession().save();
-                                               // UI remove
-                                               tp.removeChild(sjn);
-
-                                               // Check if the parent is the root node
-                                               if (tp instanceof WorkspaceElem)
-                                                       rootAncestor = (WorkspaceElem) tp;
-                                               else
-                                                       ancestor = getOlder(ancestor, (SingleJcrNodeElem) tp);
-                                       }
-                               }
-                               if (rootAncestor != null)
-                                       view.nodeRemoved(rootAncestor);
-                               else if (ancestor != null)
-                                       view.nodeRemoved(ancestor);
-                       } catch (Exception e) {
-                               ErrorFeedback.show("Cannot delete selected node ", e);
-                       }
-               }
-               return null;
-       }
-
-       private SingleJcrNodeElem getOlder(SingleJcrNodeElem A, SingleJcrNodeElem B) {
-               try {
-                       if (A == null)
-                               return B == null ? null : B;
-                       // Todo enhanced this method
-                       else
-                               return A.getNode().getDepth() <= B.getNode().getDepth() ? A : B;
-               } catch (RepositoryException re) {
-                       throw new ArgeoException("Cannot find ancestor", re);
-               }
-       }
-}
diff --git a/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/commands/DumpNode.java b/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/commands/DumpNode.java
deleted file mode 100644 (file)
index c8a235d..0000000
+++ /dev/null
@@ -1,110 +0,0 @@
-/*
- * Copyright (C) 2007-2012 Argeo GmbH
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *         http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.argeo.jcr.ui.explorer.commands;
-
-import java.io.File;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.text.DateFormat;
-import java.text.SimpleDateFormat;
-import java.util.GregorianCalendar;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.Map;
-
-import javax.jcr.Node;
-import javax.jcr.RepositoryException;
-
-import org.argeo.ArgeoException;
-import org.argeo.eclipse.ui.specific.OpenFile;
-import org.argeo.eclipse.ui.utils.CommandUtils;
-import org.argeo.jcr.JcrUtils;
-import org.argeo.jcr.ui.explorer.JcrExplorerPlugin;
-import org.argeo.jcr.ui.explorer.model.SingleJcrNodeElem;
-import org.eclipse.core.commands.AbstractHandler;
-import org.eclipse.core.commands.ExecutionEvent;
-import org.eclipse.core.commands.ExecutionException;
-import org.eclipse.jface.viewers.ISelection;
-import org.eclipse.jface.viewers.IStructuredSelection;
-import org.eclipse.ui.handlers.HandlerUtil;
-
-/**
- * If the method
- * <code> HandlerUtil.getActiveWorkbenchWindow(event).getActivePage().getSelection() </code>
- * exits and has a SingleJcrNodeElem as first element, it canonically calls the
- * JCR Session.exportSystemView() method on the underlying node with both
- * skipBinary & noRecurse boolean flags set to false.
- * 
- * Resulting stream is saved in a tmp file and opened via the "open file"
- * single-sourced command.
- */
-public class DumpNode extends AbstractHandler {
-       public final static String ID = JcrExplorerPlugin.ID + ".dumpNode";
-
-       private final static DateFormat df = new SimpleDateFormat(
-                       "yyyy-MM-dd_HH-mm");
-
-       public Object execute(ExecutionEvent event) throws ExecutionException {
-               ISelection selection = HandlerUtil.getActiveWorkbenchWindow(event)
-                               .getActivePage().getSelection();
-               if (selection == null || !(selection instanceof IStructuredSelection))
-                       return null;
-
-               Iterator<?> lst = ((IStructuredSelection) selection).iterator();
-               if (lst.hasNext()) {
-                       Object element = lst.next();
-                       if (element instanceof SingleJcrNodeElem) {
-                               SingleJcrNodeElem sjn = (SingleJcrNodeElem) element;
-                               Node node = sjn.getNode();
-
-                               // TODO add a dialog to configure the export and ask for
-                               // confirmation
-                               // Boolean ok = MessageDialog.openConfirm(
-                               // HandlerUtil.getActiveShell(event), "Confirm deletion",
-                               // "Do you want to delete " + buf + "?");
-
-                               File tmpFile;
-                               FileOutputStream fos;
-                               try {
-                                       tmpFile = File.createTempFile("JcrExport", ".xml");
-                                       tmpFile.deleteOnExit();
-                                       fos = new FileOutputStream(tmpFile);
-                                       String dateVal = df.format(new GregorianCalendar()
-                                                       .getTime());
-                                       node.getSession().exportSystemView(node.getPath(), fos,
-                                                       true, false);
-                                       openGeneratedFile(tmpFile.getAbsolutePath(),
-                                                       "Dump-" + JcrUtils.replaceInvalidChars(node.getName())+ "-" + dateVal + ".xml");
-                               } catch (RepositoryException e) {
-                                       throw new ArgeoException(
-                                                       "Unable to perform SystemExport on " + node, e);
-                               } catch (IOException e) {
-                                       throw new ArgeoException("Unable to SystemExport " + node,
-                                                       e);
-                               }
-                       }
-               }
-               return null;
-       }
-
-       private synchronized void openGeneratedFile(String path, String fileName) {
-               Map<String, String> params = new HashMap<String, String>();
-               params.put(OpenFile.PARAM_FILE_NAME, fileName);
-               params.put(OpenFile.PARAM_FILE_URI, "file://" + path);
-               CommandUtils.callCommand("org.argeo.security.ui.specific.openFile",
-                               params);
-       }
-}
diff --git a/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/commands/EditNode.java b/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/commands/EditNode.java
deleted file mode 100644 (file)
index e98973e..0000000
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * Copyright (C) 2007-2012 Argeo GmbH
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *         http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.argeo.jcr.ui.explorer.commands;
-
-import java.util.HashMap;
-import java.util.Map;
-
-import javax.jcr.Property;
-import javax.jcr.nodetype.NodeType;
-
-import org.argeo.eclipse.ui.ErrorFeedback;
-import org.argeo.eclipse.ui.jcr.editors.NodeEditorInput;
-import org.eclipse.core.commands.AbstractHandler;
-import org.eclipse.core.commands.ExecutionEvent;
-import org.eclipse.core.commands.ExecutionException;
-import org.eclipse.ui.PartInitException;
-import org.eclipse.ui.handlers.HandlerUtil;
-
-/** Generic command to open a path in an editor. */
-public class EditNode extends AbstractHandler {
-       public final static String EDITOR_PARAM = "editor";
-
-       private String defaultEditorId;
-
-       private Map<String, String> nodeTypeToEditor = new HashMap<String, String>();
-
-       public Object execute(ExecutionEvent event) throws ExecutionException {
-               String path = event.getParameter(Property.JCR_PATH);
-
-               String type = event.getParameter(NodeType.NT_NODE_TYPE);
-               if (type == null)
-                       type = NodeType.NT_UNSTRUCTURED;
-
-               String editorId = event.getParameter(NodeType.NT_NODE_TYPE);
-               if (editorId == null)
-                       editorId = nodeTypeToEditor.containsKey(type) ? nodeTypeToEditor
-                                       .get(type) : defaultEditorId;
-                                       
-               NodeEditorInput nei = new NodeEditorInput(path);
-
-               try {
-                       HandlerUtil.getActiveWorkbenchWindow(event).getActivePage()
-                                       .openEditor(nei, editorId);
-               } catch (PartInitException e) {
-                       ErrorFeedback.show("Cannot open " + editorId + " with " + path
-                                       + " of type " + type, e);
-               }
-               // TODO Auto-generated method stub
-               return null;
-       }
-
-       public void setDefaultEditorId(String defaultEditorId) {
-               this.defaultEditorId = defaultEditorId;
-       }
-
-}
diff --git a/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/commands/GetNodeSize.java b/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/commands/GetNodeSize.java
deleted file mode 100644 (file)
index cfcac13..0000000
+++ /dev/null
@@ -1,113 +0,0 @@
-/*
- * Copyright (C) 2007-2012 Argeo GmbH
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *         http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.argeo.jcr.ui.explorer.commands;
-
-import java.util.ArrayList;
-import java.util.Iterator;
-import java.util.List;
-
-import javax.jcr.Node;
-
-import org.argeo.eclipse.ui.ErrorFeedback;
-import org.argeo.jcr.JcrUtils;
-import org.argeo.jcr.ui.explorer.JcrExplorerPlugin;
-import org.argeo.jcr.ui.explorer.model.SingleJcrNodeElem;
-import org.argeo.jcr.ui.explorer.model.WorkspaceElem;
-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.jface.viewers.IStructuredSelection;
-import org.eclipse.swt.widgets.Shell;
-import org.eclipse.ui.handlers.HandlerUtil;
-
-/** Opens the generic node editor. */
-public class GetNodeSize extends AbstractHandler {
-       // private final static Log log = LogFactory.getLog(GetNodeSize.class);
-
-       public final static String ID = JcrExplorerPlugin.ID + ".getNodeSize";
-
-       // public final static String DEFAULT_ICON_REL_PATH = "icons/getSize.gif";
-       // public final static String DEFAULT_LABEL = JcrExplorerPlugin
-       // .getMessage("getNodeSizeCmdLbl");
-
-       public Object execute(ExecutionEvent event) throws ExecutionException {
-               // JcrUtils.getRepositoryByAlias(repositoryRegister,
-               // ArgeoJcrConstants.ALIAS_NODE);
-
-               ISelection selection = HandlerUtil.getActiveWorkbenchWindow(event)
-                               .getActivePage().getSelection();
-
-               if (selection != null && !selection.isEmpty()
-                               && selection instanceof IStructuredSelection) {
-
-                       // IStructuredSelection iss = (IStructuredSelection) selection;
-                       // if (iss.size() > 1)
-                       // ErrorFeedback.show(JcrExplorerPlugin
-                       // .getMessage("warningInvalidMultipleSelection"), null);
-
-                       long size = 0;
-
-                       Iterator<?> it = ((IStructuredSelection) selection).iterator();
-
-                       // as the size method is recursive, we keep track of nodes for which
-                       // we already have computed size so that we don't count them twice.
-                       // In a first approximation, we assume that the structure selection
-                       // keep the nodes ordered.
-                       // TODO : enhance that.
-                       List<String> importedPathes = new ArrayList<String>();
-                       try {
-                               nodesIt: while (it.hasNext()) {
-                                       Object obj = it.next();
-                                       String curPath;
-                                       Node node;
-                                       if (obj instanceof SingleJcrNodeElem) {
-                                               node = ((SingleJcrNodeElem) obj).getNode();
-                                               curPath = node.getSession().getWorkspace().getName();
-                                               curPath += "/" + node.getPath();
-                                       } else if (obj instanceof WorkspaceElem) {
-                                               node = ((WorkspaceElem) obj).getRootNode();
-                                               curPath = node.getSession().getWorkspace().getName();
-                                       } else
-                                               // unvalid object type
-                                               continue nodesIt;
-
-                                       Iterator<String> itPath = importedPathes.iterator();
-                                       while (itPath.hasNext()) {
-                                               String refPath = itPath.next();
-                                               if (curPath.startsWith(refPath))
-                                                       // Already done : skip node
-                                                       continue nodesIt;
-                                       }
-                                       size += JcrUtils.getNodeApproxSize(node);
-                                       importedPathes.add(curPath);
-                               }
-                       } catch (Exception e) {
-                               ErrorFeedback.show("Cannot Get size of selected node ", e);
-                       }
-
-                       String[] labels = { "OK" };
-                       Shell shell = HandlerUtil.getActiveWorkbenchWindow(event)
-                                       .getShell();
-                       MessageDialog md = new MessageDialog(shell, "Node size", null,
-                                       "Node size is: " + size / 1024 + " KB",
-                                       MessageDialog.INFORMATION, labels, 0);
-                       md.open();
-               }
-               return null;
-       }
-}
diff --git a/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/commands/ImportFileSystem.java b/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/commands/ImportFileSystem.java
deleted file mode 100644 (file)
index 5c4bf7e..0000000
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * Copyright (C) 2007-2012 Argeo GmbH
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *         http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.argeo.jcr.ui.explorer.commands;
-
-import javax.jcr.Node;
-
-import org.argeo.eclipse.ui.ErrorFeedback;
-import org.argeo.eclipse.ui.TreeParent;
-import org.argeo.jcr.ui.explorer.JcrExplorerPlugin;
-import org.argeo.jcr.ui.explorer.model.SingleJcrNodeElem;
-import org.argeo.jcr.ui.explorer.model.WorkspaceElem;
-import org.argeo.jcr.ui.explorer.views.GenericJcrBrowser;
-import org.argeo.jcr.ui.explorer.wizards.ImportFileSystemWizard;
-import org.eclipse.core.commands.AbstractHandler;
-import org.eclipse.core.commands.ExecutionEvent;
-import org.eclipse.core.commands.ExecutionException;
-import org.eclipse.jface.viewers.ISelection;
-import org.eclipse.jface.viewers.IStructuredSelection;
-import org.eclipse.jface.wizard.WizardDialog;
-import org.eclipse.ui.handlers.HandlerUtil;
-
-/** Import a local file system directory tree. */
-public class ImportFileSystem extends AbstractHandler {
-       public Object execute(ExecutionEvent event) throws ExecutionException {
-               ISelection selection = HandlerUtil.getActiveWorkbenchWindow(event)
-                               .getActivePage().getSelection();
-               GenericJcrBrowser view = (GenericJcrBrowser) HandlerUtil
-                               .getActiveWorkbenchWindow(event).getActivePage()
-                               .findView(HandlerUtil.getActivePartId(event));
-               if (selection != null && !selection.isEmpty()
-                               && selection instanceof IStructuredSelection) {
-                       Object obj = ((IStructuredSelection) selection).getFirstElement();
-                       try {
-                               Node folder = null;
-                               if (obj instanceof SingleJcrNodeElem) {
-                                       folder = ((SingleJcrNodeElem) obj).getNode();
-                               } else if (obj instanceof WorkspaceElem) {
-                                       folder = ((WorkspaceElem) obj).getRootNode();
-                               } else {
-                                       ErrorFeedback.show(JcrExplorerPlugin
-                                                       .getMessage("warningInvalidNodeToImport"));
-                               }
-                               if (folder != null) {
-                                       ImportFileSystemWizard wizard = new ImportFileSystemWizard(
-                                                       folder);
-                                       WizardDialog dialog = new WizardDialog(
-                                                       HandlerUtil.getActiveShell(event), wizard);
-                                       dialog.open();
-                                       view.nodeAdded((TreeParent) obj);
-                               }
-                       } catch (Exception e) {
-                               ErrorFeedback.show("Cannot import files to " + obj, e);
-                       }
-               }
-               return null;
-       }
-}
diff --git a/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/commands/OpenGenericNodeEditor.java b/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/commands/OpenGenericNodeEditor.java
deleted file mode 100644 (file)
index 6799d17..0000000
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * Copyright (C) 2007-2012 Argeo GmbH
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *         http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.argeo.jcr.ui.explorer.commands;
-
-import org.argeo.ArgeoException;
-import org.argeo.eclipse.ui.jcr.editors.NodeEditorInput;
-import org.argeo.jcr.ui.explorer.JcrExplorerConstants;
-import org.argeo.jcr.ui.explorer.JcrExplorerPlugin;
-import org.argeo.jcr.ui.explorer.editors.GenericNodeEditor;
-import org.eclipse.core.commands.AbstractHandler;
-import org.eclipse.core.commands.ExecutionEvent;
-import org.eclipse.core.commands.ExecutionException;
-import org.eclipse.ui.handlers.HandlerUtil;
-
-/** Opens the generic node editor. */
-public class OpenGenericNodeEditor extends AbstractHandler {
-       public final static String ID = JcrExplorerPlugin.ID + ".openGenericNodeEditor";
-
-       public Object execute(ExecutionEvent event) throws ExecutionException {
-               String path = event.getParameter(JcrExplorerConstants.PARAM_PATH);
-               try {
-                       NodeEditorInput nei = new NodeEditorInput(path);
-                       HandlerUtil.getActiveWorkbenchWindow(event).getActivePage()
-                                       .openEditor(nei, GenericNodeEditor.ID);
-               } catch (Exception e) {
-                       throw new ArgeoException("Cannot open editor", e);
-               }
-               return null;
-       }
-
-}
diff --git a/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/commands/Refresh.java b/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/commands/Refresh.java
deleted file mode 100644 (file)
index 21ce256..0000000
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * Copyright (C) 2007-2012 Argeo GmbH
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *         http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.argeo.jcr.ui.explorer.commands;
-
-import java.util.Iterator;
-
-import org.argeo.eclipse.ui.TreeParent;
-import org.argeo.eclipse.ui.jcr.views.AbstractJcrBrowser;
-import org.argeo.jcr.ui.explorer.JcrExplorerPlugin;
-import org.argeo.jcr.ui.explorer.utils.JcrUiUtils;
-import org.argeo.jcr.ui.explorer.views.GenericJcrBrowser;
-import org.eclipse.core.commands.AbstractHandler;
-import org.eclipse.core.commands.ExecutionEvent;
-import org.eclipse.core.commands.ExecutionException;
-import org.eclipse.jface.viewers.ISelection;
-import org.eclipse.jface.viewers.IStructuredSelection;
-
-/**
- * Force the selected objects of the active view to be refreshed doing the
- * following:
- * <ol>
- * <li>The model objects are recomputed</li>
- * <li>the view is refreshed</li>
- * </ol>
- */
-public class Refresh extends AbstractHandler {
-
-       public final static String ID = JcrExplorerPlugin.ID + ".refresh";
-
-       public Object execute(ExecutionEvent event) throws ExecutionException {
-
-               AbstractJcrBrowser view = (AbstractJcrBrowser) JcrExplorerPlugin
-                               .getDefault().getWorkbench().getActiveWorkbenchWindow()
-                               .getActivePage().getActivePart();//
-
-               ISelection selection = JcrExplorerPlugin.getDefault().getWorkbench()
-                               .getActiveWorkbenchWindow().getActivePage().getSelection();
-
-               if (selection != null && selection instanceof IStructuredSelection
-                               && !selection.isEmpty()) {
-                       Iterator<?> it = ((IStructuredSelection) selection).iterator();
-                       while (it.hasNext()) {
-                               Object obj = it.next();
-                               if (obj instanceof TreeParent) {
-                                       TreeParent tp = (TreeParent) obj;
-                                       JcrUiUtils.forceRefreshIfNeeded(tp);
-                                       view.refresh(obj);
-                               }
-                       }
-               } else if (view instanceof GenericJcrBrowser)
-                       ((GenericJcrBrowser) view).refresh(null); // force full refresh
-
-               return null;
-       }
-}
diff --git a/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/commands/RemoveRemoteRepository.java b/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/commands/RemoveRemoteRepository.java
deleted file mode 100644 (file)
index ec23dd0..0000000
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * Copyright (C) 2007-2012 Argeo GmbH
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *         http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.argeo.jcr.ui.explorer.commands;
-
-import org.argeo.jcr.ui.explorer.model.RemoteRepositoryElem;
-import org.argeo.jcr.ui.explorer.views.GenericJcrBrowser;
-import org.eclipse.core.commands.AbstractHandler;
-import org.eclipse.core.commands.ExecutionEvent;
-import org.eclipse.core.commands.ExecutionException;
-import org.eclipse.jface.viewers.ISelection;
-import org.eclipse.jface.viewers.IStructuredSelection;
-import org.eclipse.ui.handlers.HandlerUtil;
-
-/** Remove a registered remote repository */
-public class RemoveRemoteRepository extends AbstractHandler {
-
-       public Object execute(ExecutionEvent event) throws ExecutionException {
-
-               ISelection selection = HandlerUtil.getActiveWorkbenchWindow(event)
-                               .getActivePage().getSelection();
-
-               GenericJcrBrowser view = (GenericJcrBrowser) HandlerUtil
-                               .getActiveWorkbenchWindow(event).getActivePage()
-                               .findView(HandlerUtil.getActivePartId(event));
-
-               if (selection != null && !selection.isEmpty()
-                               && selection instanceof IStructuredSelection) {
-                       Object obj = ((IStructuredSelection) selection).getFirstElement();
-
-                       if (obj instanceof RemoteRepositoryElem) {
-                               ((RemoteRepositoryElem) obj).remove();
-                               view.refresh(null);
-                       }
-               }
-               return null;
-       }
-
-}
diff --git a/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/commands/SortChildNodes.java b/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/commands/SortChildNodes.java
deleted file mode 100644 (file)
index 2961529..0000000
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * Copyright (C) 2007-2012 Argeo GmbH
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *         http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.argeo.jcr.ui.explorer.commands;
-
-import org.argeo.jcr.ui.explorer.JcrExplorerPlugin;
-import org.argeo.jcr.ui.explorer.views.GenericJcrBrowser;
-import org.eclipse.core.commands.AbstractHandler;
-import org.eclipse.core.commands.Command;
-import org.eclipse.core.commands.ExecutionEvent;
-import org.eclipse.core.commands.ExecutionException;
-import org.eclipse.core.commands.State;
-import org.eclipse.ui.PlatformUI;
-import org.eclipse.ui.commands.ICommandService;
-import org.eclipse.ui.handlers.HandlerUtil;
-
-/**
- * Change isSorted state of the JcrExplorer Browser
- */
-public class SortChildNodes extends AbstractHandler {
-       public final static String ID = JcrExplorerPlugin.ID + ".sortChildNodes";
-
-       public Object execute(ExecutionEvent event) throws ExecutionException {
-               GenericJcrBrowser view = (GenericJcrBrowser) HandlerUtil
-                               .getActiveWorkbenchWindow(event).getActivePage()
-                               .findView(GenericJcrBrowser.ID);
-
-               ICommandService service = (ICommandService) PlatformUI.getWorkbench()
-                               .getService(ICommandService.class);
-               Command command = service.getCommand(ID);
-               State state = command.getState(ID + ".toggleState");
-
-               boolean wasSorted = (Boolean) state.getValue();
-               view.setSortChildNodes(!wasSorted);
-               state.setValue(!wasSorted);
-               return null;
-       }
-}
diff --git a/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/dialogs/ChooseNameDialog.java b/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/dialogs/ChooseNameDialog.java
deleted file mode 100644 (file)
index d4a5cc7..0000000
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- * Copyright (C) 2007-2012 Argeo GmbH
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *         http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.argeo.jcr.ui.explorer.dialogs;
-
-import org.eclipse.jface.dialogs.IMessageProvider;
-import org.eclipse.jface.dialogs.TitleAreaDialog;
-import org.eclipse.swt.SWT;
-import org.eclipse.swt.graphics.Point;
-import org.eclipse.swt.layout.GridData;
-import org.eclipse.swt.layout.GridLayout;
-import org.eclipse.swt.widgets.Composite;
-import org.eclipse.swt.widgets.Control;
-import org.eclipse.swt.widgets.Label;
-import org.eclipse.swt.widgets.Shell;
-import org.eclipse.swt.widgets.Text;
-
-/** Dialog to change the current user password */
-public class ChooseNameDialog extends TitleAreaDialog {
-       private Text nameT;
-
-       public ChooseNameDialog(Shell parentShell) {
-               super(parentShell);
-               setTitle("Choose name");
-       }
-
-       protected Point getInitialSize() {
-               return new Point(300, 250);
-       }
-
-       protected Control createDialogArea(Composite parent) {
-               Composite dialogarea = (Composite) super.createDialogArea(parent);
-               dialogarea.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
-               Composite composite = new Composite(dialogarea, SWT.NONE);
-               composite.setLayout(new GridLayout(2, false));
-               composite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
-               nameT = createLT(composite, "Name");
-
-               setMessage("Choose name", IMessageProvider.INFORMATION);
-               parent.pack();
-               return composite;
-       }
-
-       /** Creates label and text. */
-       protected Text createLT(Composite parent, String label) {
-               new Label(parent, SWT.NONE).setText(label);
-               Text text = new Text(parent, SWT.SINGLE | SWT.LEAD | SWT.BORDER);
-               text.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
-               return text;
-       }
-
-       public String getName() {
-               return nameT.getText();
-       }
-}
diff --git a/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/editors/ChildNodesPage.java b/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/editors/ChildNodesPage.java
deleted file mode 100644 (file)
index 682254a..0000000
+++ /dev/null
@@ -1,93 +0,0 @@
-/*
- * Copyright (C) 2007-2012 Argeo GmbH
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *         http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.argeo.jcr.ui.explorer.editors;
-
-import javax.jcr.Node;
-
-import org.argeo.ArgeoException;
-import org.argeo.jcr.ui.explorer.JcrExplorerPlugin;
-import org.argeo.jcr.ui.explorer.browser.NodeLabelProvider;
-import org.argeo.jcr.ui.explorer.providers.SingleNodeAsTreeContentProvider;
-import org.argeo.jcr.ui.explorer.utils.GenericNodeDoubleClickListener;
-import org.eclipse.jface.viewers.ITreeContentProvider;
-import org.eclipse.jface.viewers.TreeViewer;
-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.ui.forms.IManagedForm;
-import org.eclipse.ui.forms.editor.FormEditor;
-import org.eclipse.ui.forms.editor.FormPage;
-import org.eclipse.ui.forms.widgets.ScrolledForm;
-
-/**
- * List all childs of the current node and brings some browsing capabilities
- * accross the repository
- */
-public class ChildNodesPage extends FormPage {
-       // private final static Log log = LogFactory.getLog(ChildNodesPage.class);
-
-       // business objects
-       private Node currentNode;
-
-       // this page UI components
-       private SingleNodeAsTreeContentProvider nodeContentProvider;
-       private TreeViewer nodesViewer;
-
-       public ChildNodesPage(FormEditor editor, String title, Node currentNode) {
-               super(editor, "ChildNodesPage", title);
-               this.currentNode = currentNode;
-       }
-
-       protected void createFormContent(IManagedForm managedForm) {
-               try {
-                       ScrolledForm form = managedForm.getForm();
-                       form.setText(JcrExplorerPlugin.getMessage("childNodesPageTitle"));
-                       Composite body = form.getBody();
-                       GridLayout twt = new GridLayout(1, false);
-                       twt.marginWidth = twt.marginHeight = 5;
-                       body.setLayout(twt);
-                       if (!currentNode.hasNodes()) {
-                               managedForm.getToolkit().createLabel(body,
-                                               JcrExplorerPlugin.getMessage("warningNoChildNode"));
-                       } else {
-
-                               nodeContentProvider = new SingleNodeAsTreeContentProvider();
-                               nodesViewer = createNodeViewer(body, nodeContentProvider);
-                               nodesViewer.setInput(currentNode);
-                       }
-               } catch (Exception e) {
-                       throw new ArgeoException(
-                                       "Unexpected error while creating child node page", e);
-               }
-       }
-
-       protected TreeViewer createNodeViewer(Composite parent,
-                       final ITreeContentProvider nodeContentProvider) {
-
-               final TreeViewer tmpNodeViewer = new TreeViewer(parent, SWT.MULTI);
-
-               tmpNodeViewer.getTree().setLayoutData(
-                               new GridData(SWT.FILL, SWT.FILL, true, true));
-
-               tmpNodeViewer.setContentProvider(nodeContentProvider);
-               tmpNodeViewer.setLabelProvider(new NodeLabelProvider());
-               tmpNodeViewer
-                               .addDoubleClickListener(new GenericNodeDoubleClickListener(
-                                               tmpNodeViewer));
-               return tmpNodeViewer;
-       }
-}
diff --git a/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/editors/EmptyNodePage.java b/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/editors/EmptyNodePage.java
deleted file mode 100644 (file)
index 322c7eb..0000000
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * Copyright (C) 2007-2012 Argeo GmbH
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *         http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.argeo.jcr.ui.explorer.editors;
-
-import org.eclipse.swt.SWT;
-import org.eclipse.swt.layout.GridLayout;
-import org.eclipse.swt.widgets.Label;
-import org.eclipse.ui.forms.IManagedForm;
-import org.eclipse.ui.forms.editor.FormEditor;
-import org.eclipse.ui.forms.editor.FormPage;
-import org.eclipse.ui.forms.widgets.ScrolledForm;
-
-/**
- * This page is only used at editor's creation time when current node has not
- * yet been set
- */
-public class EmptyNodePage extends FormPage {
-       // private final static Log log = LogFactory.getLog(EmptyNodePage.class);
-
-       public EmptyNodePage(FormEditor editor, String title) {
-               super(editor, "Empty Page", title);
-       }
-
-       protected void createFormContent(IManagedForm managedForm) {
-               try {
-                       ScrolledForm form = managedForm.getForm();
-                       GridLayout twt = new GridLayout(1, false);
-                       twt.marginWidth = twt.marginHeight = 0;
-                       form.getBody().setLayout(twt);
-                       Label lbl = new Label(form.getBody(), SWT.NONE);
-                       lbl.setText("Empty page");
-               } catch (Exception e) {
-                       e.printStackTrace();
-               }
-       }
-}
diff --git a/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/editors/GenericJcrQueryEditor.java b/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/editors/GenericJcrQueryEditor.java
deleted file mode 100644 (file)
index 3b98ed1..0000000
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- * Copyright (C) 2007-2012 Argeo GmbH
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *         http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.argeo.jcr.ui.explorer.editors;
-
-import org.argeo.eclipse.ui.jcr.editors.AbstractJcrQueryEditor;
-import org.argeo.jcr.ui.explorer.JcrExplorerPlugin;
-import org.eclipse.swt.SWT;
-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.Event;
-import org.eclipse.swt.widgets.Listener;
-import org.eclipse.swt.widgets.Text;
-
-/** Enables end user to type and execute any JCR query. */
-public class GenericJcrQueryEditor extends AbstractJcrQueryEditor {
-       public final static String ID = JcrExplorerPlugin.ID + ".genericJcrQueryEditor";
-
-       private Text queryField;
-
-       @Override
-       public void createQueryForm(Composite parent) {
-               parent.setLayout(new GridLayout(1, false));
-
-               queryField = new Text(parent, SWT.BORDER | SWT.MULTI | SWT.WRAP);
-               queryField.setText(initialQuery);
-               queryField.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
-
-               Button execute = new Button(parent, SWT.PUSH);
-               execute.setText("Execute");
-
-               Listener executeListener = new Listener() {
-                       public void handleEvent(Event event) {
-                               executeQuery(queryField.getText());
-                       }
-               };
-
-               execute.addListener(SWT.Selection, executeListener);
-               // queryField.addListener(SWT.DefaultSelection, executeListener);
-       }
-
-       @Override
-       public void setFocus() {
-               queryField.setFocus();
-       }
-}
diff --git a/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/editors/GenericNodeEditor.java b/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/editors/GenericNodeEditor.java
deleted file mode 100644 (file)
index 57f3aa2..0000000
+++ /dev/null
@@ -1,113 +0,0 @@
-/*
- * Copyright (C) 2007-2012 Argeo GmbH
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *         http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.argeo.jcr.ui.explorer.editors;
-
-import javax.jcr.Node;
-
-import org.argeo.ArgeoException;
-import org.argeo.jcr.JcrUtils;
-import org.argeo.jcr.ui.explorer.JcrExplorerPlugin;
-import org.eclipse.core.runtime.IProgressMonitor;
-import org.eclipse.ui.IEditorInput;
-import org.eclipse.ui.IEditorSite;
-import org.eclipse.ui.PartInitException;
-import org.eclipse.ui.forms.editor.FormEditor;
-
-/**
- * Container for the node editor page. At creation time, it takes a JCR Node
- * that cannot be changed afterwards.
- */
-public class GenericNodeEditor extends FormEditor {
-
-       // private final static Log log =
-       // LogFactory.getLog(GenericNodeEditor.class);
-       public final static String ID = JcrExplorerPlugin.ID + ".genericNodeEditor";
-
-       private Node currentNode;
-
-       private GenericPropertyPage genericPropertyPage;
-       private ChildNodesPage childNodesPage;
-       private NodeRightsManagementPage nodeRightsManagementPage;
-       private NodeVersionHistoryPage nodeVersionHistoryPage;
-
-       public void init(IEditorSite site, IEditorInput input)
-                       throws PartInitException {
-               super.init(site, input);
-               GenericNodeEditorInput nei = (GenericNodeEditorInput) getEditorInput();
-               currentNode = nei.getCurrentNode();
-               this.setPartName(JcrUtils.lastPathElement(nei.getPath()));
-       }
-
-       @Override
-       protected void addPages() {
-               try {
-                       // genericNodePage = new GenericNodePage(this,
-                       // JcrExplorerPlugin.getMessage("genericNodePageTitle"),
-                       // currentNode);
-                       // addPage(genericNodePage);
-
-                       genericPropertyPage = new GenericPropertyPage(this,
-                                       JcrExplorerPlugin.getMessage("genericNodePageTitle"),
-                                       currentNode);
-                       addPage(genericPropertyPage);
-
-                       childNodesPage = new ChildNodesPage(this,
-                                       JcrExplorerPlugin.getMessage("childNodesPageTitle"),
-                                       currentNode);
-                       addPage(childNodesPage);
-
-                       nodeRightsManagementPage = new NodeRightsManagementPage(this,
-                                       JcrExplorerPlugin
-                                                       .getMessage("nodeRightsManagementPageTitle"),
-                                       currentNode);
-                       addPage(nodeRightsManagementPage);
-
-                       nodeVersionHistoryPage = new NodeVersionHistoryPage(
-                                       this,
-                                       JcrExplorerPlugin.getMessage("nodeVersionHistoryPageTitle"),
-                                       currentNode);
-                       addPage(nodeVersionHistoryPage);
-               } catch (PartInitException e) {
-                       throw new ArgeoException("Not able to add an empty page ", e);
-               }
-       }
-
-       @Override
-       public void doSaveAs() {
-               // unused compulsory method
-       }
-
-       @Override
-       public void doSave(IProgressMonitor monitor) {
-               try {
-                       // Automatically commit all pages of the editor
-                       commitPages(true);
-                       firePropertyChange(PROP_DIRTY);
-               } catch (Exception e) {
-                       throw new ArgeoException("Error while saving node", e);
-               }
-
-       }
-
-       @Override
-       public boolean isSaveAsAllowed() {
-               return true;
-       }
-
-       Node getCurrentNode() {
-               return currentNode;
-       }
-}
diff --git a/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/editors/GenericNodeEditorInput.java b/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/editors/GenericNodeEditorInput.java
deleted file mode 100644 (file)
index 45e337e..0000000
+++ /dev/null
@@ -1,111 +0,0 @@
-/*
- * Copyright (C) 2007-2012 Argeo GmbH
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *         http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.argeo.jcr.ui.explorer.editors;
-
-import javax.jcr.Node;
-import javax.jcr.RepositoryException;
-
-import org.argeo.ArgeoException;
-import org.eclipse.jface.resource.ImageDescriptor;
-import org.eclipse.ui.IEditorInput;
-import org.eclipse.ui.IPersistableElement;
-
-/**
- * An editor input based the JCR node object.
- * */
-
-public class GenericNodeEditorInput implements IEditorInput {
-       private final Node currentNode;
-
-       // cache key properties at creation time to avoid Exception at recoring time
-       // when the session has been closed
-       private String path;
-       private String uid;
-       private String name;
-
-       public GenericNodeEditorInput(Node currentNode) {
-               this.currentNode = currentNode;
-               try {
-                       name = currentNode.getName();
-                       uid = currentNode.getIdentifier();
-                       path = currentNode.getPath();
-               } catch (RepositoryException re) {
-                       throw new ArgeoException(
-                                       "unexpected error while getting node key values at creation time",
-                                       re);
-               }
-       }
-
-       public Node getCurrentNode() {
-               return currentNode;
-       }
-
-       public Object getAdapter(@SuppressWarnings("rawtypes") Class adapter) {
-               return null;
-       }
-
-       public boolean exists() {
-               return true;
-       }
-
-       public ImageDescriptor getImageDescriptor() {
-               return null;
-       }
-
-       public String getName() {
-               return name;
-       }
-
-       public String getUid() {
-               return uid;
-       }
-
-       public String getToolTipText() {
-               return path;
-       }
-
-       public String getPath() {
-               return path;
-       }
-
-       public IPersistableElement getPersistable() {
-               return null;
-       }
-
-       /**
-        * equals method based on UID that is unique within a workspace and path of
-        * the node, thus 2 shared node that have same UID as defined in the spec
-        * but 2 different pathes will open two distinct editors.
-        * 
-        * TODO enhance this method to support multirepository and multiworkspace
-        * environments
-        */
-       public boolean equals(Object obj) {
-               if (this == obj)
-                       return true;
-               if (obj == null)
-                       return false;
-               if (getClass() != obj.getClass())
-                       return false;
-
-               GenericNodeEditorInput other = (GenericNodeEditorInput) obj;
-               if (!getUid().equals(other.getUid()))
-                       return false;
-               if (!getPath().equals(other.getPath()))
-                       return false;
-               return true;
-       }
-}
diff --git a/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/editors/GenericNodePage.java b/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/editors/GenericNodePage.java
deleted file mode 100644 (file)
index fd4dafe..0000000
+++ /dev/null
@@ -1,211 +0,0 @@
-/*
- * Copyright (C) 2007-2012 Argeo GmbH
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *         http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.argeo.jcr.ui.explorer.editors;
-
-import java.text.DateFormat;
-import java.text.SimpleDateFormat;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.List;
-import java.util.ListIterator;
-
-import javax.jcr.Node;
-import javax.jcr.Property;
-import javax.jcr.PropertyIterator;
-import javax.jcr.PropertyType;
-import javax.jcr.RepositoryException;
-
-import org.argeo.ArgeoException;
-import org.argeo.jcr.JcrUtils;
-import org.argeo.jcr.ui.explorer.JcrExplorerConstants;
-import org.eclipse.swt.events.ModifyEvent;
-import org.eclipse.swt.events.ModifyListener;
-import org.eclipse.swt.layout.GridData;
-import org.eclipse.swt.layout.GridLayout;
-import org.eclipse.swt.widgets.Composite;
-import org.eclipse.swt.widgets.Control;
-import org.eclipse.swt.widgets.Text;
-import org.eclipse.ui.forms.AbstractFormPart;
-import org.eclipse.ui.forms.IManagedForm;
-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;
-
-/**
- * Main node editor page. Lists all properties of the current node and enable
- * access and editing for some of them.
- */
-
-public class GenericNodePage extends FormPage implements JcrExplorerConstants {
-       // private final static Log log = LogFactory.getLog(GenericNodePage.class);
-
-       // local constants
-       private final static String JCR_PROPERTY_NAME = "jcr:name";
-
-       // Utils
-       protected DateFormat timeFormatter = new SimpleDateFormat(DATE_TIME_FORMAT);
-
-       // Main business Objects
-       private Node currentNode;
-
-       // This page widgets
-       private FormToolkit tk;
-       private List<Control> modifyableProperties = new ArrayList<Control>();
-
-       public GenericNodePage(FormEditor editor, String title, Node currentNode) {
-               super(editor, "id", title);
-               this.currentNode = currentNode;
-       }
-
-       protected void createFormContent(IManagedForm managedForm) {
-               tk = managedForm.getToolkit();
-               ScrolledForm form = managedForm.getForm();
-               GridLayout twt = new GridLayout(3, false);
-               twt.marginWidth = twt.marginHeight = 5;
-
-               form.getBody().setLayout(twt);
-               createPropertiesPart(form.getBody());
-       }
-
-       private void createPropertiesPart(Composite parent) {
-               try {
-
-                       PropertyIterator pi = currentNode.getProperties();
-
-                       // Initializes form part
-                       AbstractFormPart part = new AbstractFormPart() {
-                               public void commit(boolean onSave) {
-                                       try {
-                                               if (onSave) {
-                                                       ListIterator<Control> it = modifyableProperties
-                                                                       .listIterator();
-                                                       while (it.hasNext()) {
-                                                               // we only support Text controls for the time
-                                                               // being
-                                                               Text curControl = (Text) it.next();
-                                                               String value = curControl.getText();
-                                                               currentNode.setProperty((String) curControl
-                                                                               .getData(JCR_PROPERTY_NAME), value);
-                                                       }
-
-                                                       // We only commit when onSave = true,
-                                                       // thus it is still possible to save after a tab
-                                                       // change.
-                                                       super.commit(onSave);
-                                               }
-                                       } catch (RepositoryException re) {
-                                               throw new ArgeoException(
-                                                               "Unexpected error while saving properties", re);
-                                       }
-                               }
-                       };
-
-                       while (pi.hasNext()) {
-                               Property prop = pi.nextProperty();
-                               addPropertyLine(parent, part, prop);
-                       }
-
-                       getManagedForm().addPart(part);
-               } catch (RepositoryException re) {
-                       throw new ArgeoException(
-                                       "Error during creation of network details section", re);
-               }
-
-       }
-
-       private void addPropertyLine(Composite parent, AbstractFormPart part,
-                       Property prop) {
-               try {
-                       tk.createLabel(parent, prop.getName());
-                       tk.createLabel(parent,
-                                       "[" + JcrUtils.getPropertyDefinitionAsString(prop) + "]");
-
-                       if (prop.getDefinition().isProtected()) {
-                               tk.createLabel(parent, formatReadOnlyPropertyValue(prop));
-                       } else
-                               addModifyableValueWidget(parent, part, prop);
-               } catch (RepositoryException re) {
-                       throw new ArgeoException("Cannot get property " + prop, re);
-               }
-       }
-
-       private String formatReadOnlyPropertyValue(Property prop) {
-               try {
-                       String strValue;
-
-                       if (prop.getType() == PropertyType.BINARY)
-                               strValue = "<binary>";
-                       else if (prop.isMultiple())
-                               strValue = Arrays.asList(prop.getValues()).toString();
-                       else if (prop.getType() == PropertyType.DATE)
-                               strValue = timeFormatter.format(prop.getValue().getDate()
-                                               .getTime());
-                       else
-                               strValue = prop.getValue().getString();
-
-                       return strValue;
-               } catch (RepositoryException re) {
-                       throw new ArgeoException(
-                                       "Unexpected error while formatting read only property value",
-                                       re);
-               }
-       }
-
-       private Control addModifyableValueWidget(Composite parent,
-                       AbstractFormPart part, Property prop) {
-               GridData gd;
-               try {
-                       if (prop.getType() == PropertyType.STRING) {
-                               Text txt = tk.createText(parent, prop.getString());
-                               gd = new GridData(GridData.FILL_HORIZONTAL);
-                               txt.setLayoutData(gd);
-                               txt.addModifyListener(new ModifiedFieldListener(part));
-                               txt.setData(JCR_PROPERTY_NAME, prop.getName());
-                               modifyableProperties.add(txt);
-                       } else {
-                               // unsupported property type for editing, we create a read only
-                               // label.
-                               return tk
-                                               .createLabel(parent, formatReadOnlyPropertyValue(prop));
-                       }
-                       return null;
-               } catch (RepositoryException re) {
-                       throw new ArgeoException(
-                                       "Unexpected error while formatting read only property value",
-                                       re);
-               }
-
-       }
-
-       //
-       // LISTENERS
-       //
-
-       private class ModifiedFieldListener implements ModifyListener {
-
-               private AbstractFormPart formPart;
-
-               public ModifiedFieldListener(AbstractFormPart generalPart) {
-                       this.formPart = generalPart;
-               }
-
-               public void modifyText(ModifyEvent e) {
-                       formPart.markDirty();
-               }
-       }
-
-}
diff --git a/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/editors/GenericPropertyPage.java b/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/editors/GenericPropertyPage.java
deleted file mode 100644 (file)
index 3aec453..0000000
+++ /dev/null
@@ -1,306 +0,0 @@
-/*
- * Copyright (C) 2007-2012 Argeo GmbH
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *         http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.argeo.jcr.ui.explorer.editors;
-
-import java.util.ArrayList;
-import java.util.List;
-
-import javax.jcr.Node;
-import javax.jcr.Property;
-import javax.jcr.PropertyIterator;
-import javax.jcr.RepositoryException;
-import javax.jcr.Value;
-
-import org.argeo.ArgeoException;
-import org.argeo.jcr.ui.explorer.JcrExplorerConstants;
-import org.argeo.jcr.ui.explorer.JcrExplorerPlugin;
-import org.argeo.jcr.ui.explorer.providers.PropertyLabelProvider;
-import org.eclipse.jface.viewers.ITreeContentProvider;
-import org.eclipse.jface.viewers.TreeViewer;
-import org.eclipse.jface.viewers.Viewer;
-import org.eclipse.swt.SWT;
-import org.eclipse.swt.layout.FillLayout;
-import org.eclipse.swt.widgets.Composite;
-import org.eclipse.swt.widgets.Tree;
-import org.eclipse.swt.widgets.TreeColumn;
-import org.eclipse.ui.forms.IManagedForm;
-import org.eclipse.ui.forms.editor.FormEditor;
-import org.eclipse.ui.forms.editor.FormPage;
-import org.eclipse.ui.forms.widgets.ScrolledForm;
-
-/**
- * Generic editor property page. Lists all properties of current node as a
- * complex tree. TODO: enable editing
- */
-
-public class GenericPropertyPage extends FormPage implements
-               JcrExplorerConstants {
-       // private final static Log log =
-       // LogFactory.getLog(GenericPropertyPage.class);
-
-       // Main business Objects
-       private Node currentNode;
-
-       public GenericPropertyPage(FormEditor editor, String title, Node currentNode) {
-               super(editor, "id", title);
-               this.currentNode = currentNode;
-       }
-
-       protected void createFormContent(IManagedForm managedForm) {
-               ScrolledForm form = managedForm.getForm();
-               form.setText(JcrExplorerPlugin.getMessage("genericNodePageTitle"));
-               FillLayout layout = new FillLayout();
-               layout.marginHeight = 5;
-               layout.marginWidth = 5;
-               form.getBody().setLayout(layout);
-
-               createComplexTree(form.getBody());
-
-               // TODO remove following
-               // createPropertiesPart(form.getBody());
-       }
-
-       private TreeViewer createComplexTree(Composite parent) {
-               int style = SWT.BORDER | SWT.MULTI | SWT.FULL_SELECTION;
-               Tree tree = new Tree(parent, style);
-               createColumn(tree, "Property", SWT.LEFT, 200);
-               createColumn(tree, "Value(s)", SWT.LEFT, 300);
-               createColumn(tree, "Attributes", SWT.LEFT, 65);
-               tree.setLinesVisible(true);
-               tree.setHeaderVisible(true);
-
-               TreeViewer result = new TreeViewer(tree);
-               result.setContentProvider(new TreeContentProvider());
-               result.setLabelProvider(new PropertyLabelProvider());
-               result.setInput(currentNode);
-               result.expandAll();
-               return result;
-       }
-
-       private static TreeColumn createColumn(Tree parent, String name, int style,
-                       int width) {
-               TreeColumn result = new TreeColumn(parent, style);
-               result.setText(name);
-               result.setWidth(width);
-               result.setMoveable(true);
-               result.setResizable(true);
-               return result;
-       }
-
-       //
-       // private void createPropertiesPart(Composite parent) {
-       // try {
-       //
-       // PropertyIterator pi = currentNode.getProperties();
-       //
-       // // Initializes form part
-       // AbstractFormPart part = new AbstractFormPart() {
-       // public void commit(boolean onSave) {
-       // try {
-       // if (onSave) {
-       // ListIterator<Control> it = modifyableProperties
-       // .listIterator();
-       // while (it.hasNext()) {
-       // // we only support Text controls for the time
-       // // being
-       // Text curControl = (Text) it.next();
-       // String value = curControl.getText();
-       // currentNode.setProperty((String) curControl
-       // .getData(JCR_PROPERTY_NAME), value);
-       // }
-       //
-       // // We only commit when onSave = true,
-       // // thus it is still possible to save after a tab
-       // // change.
-       // super.commit(onSave);
-       // }
-       // } catch (RepositoryException re) {
-       // throw new ArgeoException(
-       // "Unexpected error while saving properties", re);
-       // }
-       // }
-       // };
-       //
-       // while (pi.hasNext()) {
-       // Property prop = pi.nextProperty();
-       // addPropertyLine(parent, part, prop);
-       // }
-       //
-       // getManagedForm().addPart(part);
-       // } catch (RepositoryException re) {
-       // throw new ArgeoException(
-       // "Error during creation of network details section", re);
-       // }
-       //
-       // }
-       //
-       // private void addPropertyLine(Composite parent, AbstractFormPart part,
-       // Property prop) {
-       // try {
-       // tk.createLabel(parent, prop.getName());
-       // tk.createLabel(parent,
-       // "[" + JcrUtils.getPropertyDefinitionAsString(prop) + "]");
-       //
-       // if (prop.getDefinition().isProtected()) {
-       // tk.createLabel(parent, formatReadOnlyPropertyValue(prop));
-       // } else
-       // addModifyableValueWidget(parent, part, prop);
-       // } catch (RepositoryException re) {
-       // throw new ArgeoException("Cannot get property " + prop, re);
-       // }
-       // }
-       //
-       // private String formatReadOnlyPropertyValue(Property prop) {
-       // try {
-       // String strValue;
-       //
-       // if (prop.getType() == PropertyType.BINARY)
-       // strValue = "<binary>";
-       // else if (prop.isMultiple())
-       // strValue = Arrays.asList(prop.getValues()).toString();
-       // else if (prop.getType() == PropertyType.DATE)
-       // strValue = timeFormatter.format(prop.getValue().getDate()
-       // .getTime());
-       // else
-       // strValue = prop.getValue().getString();
-       //
-       // return strValue;
-       // } catch (RepositoryException re) {
-       // throw new ArgeoException(
-       // "Unexpected error while formatting read only property value",
-       // re);
-       // }
-       // }
-       //
-       // private Control addModifyableValueWidget(Composite parent,
-       // AbstractFormPart part, Property prop) {
-       // GridData gd;
-       // try {
-       // if (prop.getType() == PropertyType.STRING) {
-       // Text txt = tk.createText(parent, prop.getString());
-       // gd = new GridData(GridData.FILL_HORIZONTAL);
-       // txt.setLayoutData(gd);
-       // txt.addModifyListener(new ModifiedFieldListener(part));
-       // txt.setData(JCR_PROPERTY_NAME, prop.getName());
-       // modifyableProperties.add(txt);
-       // } else {
-       // // unsupported property type for editing, we create a read only
-       // // label.
-       // return tk
-       // .createLabel(parent, formatReadOnlyPropertyValue(prop));
-       // }
-       // return null;
-       // } catch (RepositoryException re) {
-       // throw new ArgeoException(
-       // "Unexpected error while formatting read only property value",
-       // re);
-       // }
-       //
-       // }
-
-       // Multiple Value Model
-       // protected class MultipleValueItem {
-       // private int index;
-       // private Value value;
-       //
-       // public MultipleValueItem(int index, Value value) {
-       // this.index = index;
-       // this.value = value;
-       // }
-       //
-       // public int getIndex() {
-       // return index;
-       // }
-       //
-       // public Object getValue() {
-       // return value;
-       // }
-       // }
-
-       private class TreeContentProvider implements ITreeContentProvider {
-               public Object[] getElements(Object parent) {
-                       Object[] props = null;
-                       try {
-
-                               if (parent instanceof Node) {
-                                       Node node = (Node) parent;
-                                       PropertyIterator pi;
-                                       pi = node.getProperties();
-                                       List<Property> propList = new ArrayList<Property>();
-                                       while (pi.hasNext()) {
-                                               propList.add(pi.nextProperty());
-                                       }
-                                       props = propList.toArray();
-                               }
-                       } catch (RepositoryException e) {
-                               throw new ArgeoException(
-                                               "Unexpected exception while listing node properties", e);
-                       }
-                       return props;
-               }
-
-               public Object getParent(Object child) {
-                       return null;
-               }
-
-               public Object[] getChildren(Object parent) {
-                       Object[] result = null;
-                       if (parent instanceof Property) {
-                               Property prop = (Property) parent;
-                               try {
-
-                                       if (prop.isMultiple()) {
-                                               Value[] values = prop.getValues();
-                                               // List<MultipleValueItem> list = new
-                                               // ArrayList<MultipleValueItem>();
-                                               // for (int i = 0; i < values.length; i++) {
-                                               // MultipleValueItem mvi = new MultipleValueItem(i,
-                                               // values[i]);
-                                               // list.add(mvi);
-                                               // }
-
-                                               return values;
-                                       }
-                               } catch (RepositoryException e) {
-                                       throw new ArgeoException(
-                                                       "Unexpected error getting multiple values property.",
-                                                       e);
-                               }
-                       }
-                       return result;
-               }
-
-               public boolean hasChildren(Object parent) {
-                       try {
-                               if (parent instanceof Property
-                                               && ((Property) parent).isMultiple()) {
-                                       return true;
-                               }
-                       } catch (RepositoryException e) {
-                               throw new ArgeoException(
-                                               "Unexpected exception while checking if property is multiple",
-                                               e);
-                       }
-                       return false;
-               }
-
-               public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
-               }
-
-               public void dispose() {
-               }
-       }
-}
diff --git a/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/editors/NodeRightsManagementPage.java b/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/editors/NodeRightsManagementPage.java
deleted file mode 100644 (file)
index cc5efb5..0000000
+++ /dev/null
@@ -1,138 +0,0 @@
-/*
- * Copyright (C) 2007-2012 Argeo GmbH
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *         http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.argeo.jcr.ui.explorer.editors;
-
-import javax.jcr.Node;
-import javax.jcr.security.AccessControlManager;
-import javax.jcr.security.Privilege;
-
-import org.argeo.ArgeoException;
-import org.argeo.jcr.ui.explorer.JcrExplorerPlugin;
-import org.eclipse.jface.viewers.ColumnLabelProvider;
-import org.eclipse.jface.viewers.IStructuredContentProvider;
-import org.eclipse.jface.viewers.TableViewer;
-import org.eclipse.jface.viewers.TableViewerColumn;
-import org.eclipse.jface.viewers.Viewer;
-import org.eclipse.swt.SWT;
-import org.eclipse.swt.graphics.Image;
-import org.eclipse.swt.layout.FillLayout;
-import org.eclipse.swt.widgets.Composite;
-import org.eclipse.swt.widgets.Table;
-import org.eclipse.swt.widgets.TableColumn;
-import org.eclipse.ui.forms.IManagedForm;
-import org.eclipse.ui.forms.editor.FormEditor;
-import org.eclipse.ui.forms.editor.FormPage;
-import org.eclipse.ui.forms.widgets.ScrolledForm;
-
-/**
- * This comments will be nicely fill by mbaudier in.
- */
-public class NodeRightsManagementPage extends FormPage {
-       // private final static Log log =
-       // LogFactory.getLog(NodeRightsManagementPage.class);
-
-       private Node currentNode;
-
-       private TableViewer viewer;
-
-       public NodeRightsManagementPage(FormEditor editor, String title,
-                       Node currentNode) {
-               super(editor, "NodeRightsManagementPage", title);
-               this.currentNode = currentNode;
-       }
-
-       protected void createFormContent(IManagedForm managedForm) {
-               ScrolledForm form = managedForm.getForm();
-               form.setText(JcrExplorerPlugin
-                               .getMessage("nodeRightsManagementPageTitle"));
-               FillLayout layout = new FillLayout();
-               layout.marginHeight = 5;
-               layout.marginWidth = 5;
-               form.getBody().setLayout(layout);
-               createRightsPart(form.getBody());
-       }
-
-       /** Creates the rights part */
-       protected void createRightsPart(Composite parent) {
-               Table table = new Table(parent, SWT.MULTI | SWT.H_SCROLL | SWT.V_SCROLL);
-               table.setLinesVisible(true);
-               table.setHeaderVisible(true);
-               viewer = new TableViewer(table);
-
-               // check column
-               TableViewerColumn column = createTableViewerColumn(viewer, "checked",
-                               20);
-               column.setLabelProvider(new ColumnLabelProvider() {
-                       public String getText(Object element) {
-                               return null;
-                       }
-
-                       public Image getImage(Object element) {
-                               return null;
-                       }
-               });
-               // column.setEditingSupport(new RoleEditingSupport(rolesViewer, part));
-
-               // role column
-               column = createTableViewerColumn(viewer, "Role", 200);
-               column.setLabelProvider(new ColumnLabelProvider() {
-                       public String getText(Object element) {
-                               Privilege p = (Privilege) element;
-                               return p.getName();
-                       }
-
-                       public Image getImage(Object element) {
-                               return null;
-                       }
-               });
-               viewer.setContentProvider(new RightsContentProvider());
-               viewer.setInput(getEditorSite());
-       }
-
-       protected TableViewerColumn createTableViewerColumn(TableViewer viewer,
-                       String title, int bound) {
-               final TableViewerColumn viewerColumn = new TableViewerColumn(viewer,
-                               SWT.NONE);
-               final TableColumn column = viewerColumn.getColumn();
-               column.setText(title);
-               column.setWidth(bound);
-               column.setResizable(true);
-               column.setMoveable(true);
-               return viewerColumn;
-       }
-
-       private class RightsContentProvider implements IStructuredContentProvider {
-
-               public void dispose() {
-               }
-
-               public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
-               }
-
-               public Object[] getElements(Object inputElement) {
-                       try {
-                               AccessControlManager accessControlManager = currentNode
-                                               .getSession().getAccessControlManager();
-                               Privilege[] privileges = accessControlManager
-                                               .getPrivileges(currentNode.getPath());
-                               return privileges;
-                       } catch (Exception e) {
-                               throw new ArgeoException("Cannot retrieve rights", e);
-                       }
-               }
-
-       }
-}
diff --git a/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/editors/NodeVersionHistoryPage.java b/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/editors/NodeVersionHistoryPage.java
deleted file mode 100644 (file)
index 59fff5e..0000000
+++ /dev/null
@@ -1,319 +0,0 @@
-/*
- * Copyright (C) 2007-2012 Argeo GmbH
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *         http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.argeo.jcr.ui.explorer.editors;
-
-import java.text.DateFormat;
-import java.text.SimpleDateFormat;
-import java.util.ArrayList;
-import java.util.Calendar;
-import java.util.List;
-import java.util.Map;
-
-import javax.jcr.Node;
-import javax.jcr.Property;
-import javax.jcr.PropertyType;
-import javax.jcr.RepositoryException;
-import javax.jcr.Value;
-import javax.jcr.nodetype.NodeType;
-import javax.jcr.version.Version;
-import javax.jcr.version.VersionHistory;
-import javax.jcr.version.VersionIterator;
-import javax.jcr.version.VersionManager;
-
-import org.argeo.ArgeoException;
-import org.argeo.jcr.JcrUtils;
-import org.argeo.jcr.PropertyDiff;
-import org.argeo.jcr.VersionDiff;
-import org.argeo.jcr.ui.explorer.JcrExplorerConstants;
-import org.argeo.jcr.ui.explorer.JcrExplorerPlugin;
-import org.argeo.jcr.ui.explorer.providers.FullVersioningTreeContentProvider;
-import org.argeo.jcr.ui.explorer.providers.VersionLabelProvider;
-import org.argeo.jcr.ui.explorer.utils.GenericNodeDoubleClickListener;
-import org.eclipse.jface.viewers.ITreeContentProvider;
-import org.eclipse.jface.viewers.TreeViewer;
-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.forms.AbstractFormPart;
-import org.eclipse.ui.forms.IManagedForm;
-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;
-import org.eclipse.ui.forms.widgets.Section;
-import org.eclipse.ui.forms.widgets.TableWrapData;
-import org.eclipse.ui.forms.widgets.TableWrapLayout;
-
-/**
- * Offers two main sections : one to display a text area with a summary of all
- * variations between a version and its predecessor and one tree view that
- * enable browsing
- * */
-public class NodeVersionHistoryPage extends FormPage implements
-               JcrExplorerConstants {
-       // private final static Log log = LogFactory
-       // .getLog(NodeVersionHistoryPage.class);
-
-       // Utils
-       protected DateFormat timeFormatter = new SimpleDateFormat(DATE_TIME_FORMAT);
-
-       // business objects
-       private Node currentNode;
-
-       // this page UI components
-       private FullVersioningTreeContentProvider nodeContentProvider;
-       private TreeViewer nodesViewer;
-       private FormToolkit tk;
-
-       public NodeVersionHistoryPage(FormEditor editor, String title,
-                       Node currentNode) {
-               super(editor, "NodeVersionHistoryPage", title);
-               this.currentNode = currentNode;
-       }
-
-       protected void createFormContent(IManagedForm managedForm) {
-               ScrolledForm form = managedForm.getForm();
-               form.setText(JcrExplorerPlugin
-                               .getMessage("nodeVersionHistoryPageTitle"));
-               tk = managedForm.getToolkit();
-               GridLayout twt = new GridLayout(1, false);
-               twt.marginWidth = twt.marginHeight = 5;
-               Composite body = form.getBody();
-               body.setLayout(twt);
-
-               try {
-                       if (!currentNode.isNodeType(NodeType.MIX_VERSIONABLE)) {
-                               tk.createLabel(body, JcrExplorerPlugin
-                                               .getMessage("warningUnversionableNode"));
-                       } else {
-                               createHistorySection(form.getBody());
-                               createTreeSection(form.getBody());
-                       }
-               } catch (RepositoryException e) {
-                       throw new ArgeoException(
-                                       "Unexpected error while checking if node is versionable", e);
-               }
-       }
-
-       protected void createTreeSection(Composite parent) {
-               // Section Layout & MetaData
-               Section section = tk.createSection(parent, Section.TWISTIE);
-               section.setLayoutData(new GridData(GridData.FILL_BOTH));
-               section.setText(JcrExplorerPlugin.getMessage("versionTreeSectionTitle"));
-
-               // Section Body
-               Composite body = tk.createComposite(section, SWT.FILL);
-               // WARNING : 2 following lines are compulsory or body won't be
-               // displayed.
-               body.setLayout(new GridLayout());
-               section.setClient(body);
-
-               body.setLayoutData(new GridData(GridData.FILL_BOTH));
-               section.setExpanded(true);
-
-               nodeContentProvider = new FullVersioningTreeContentProvider();
-               nodesViewer = createNodeViewer(body, nodeContentProvider);
-               nodesViewer.setInput(currentNode);
-       }
-
-       protected TreeViewer createNodeViewer(Composite parent,
-                       final ITreeContentProvider nodeContentProvider) {
-
-               final TreeViewer tmpNodeViewer = new TreeViewer(parent, SWT.MULTI);
-
-               tmpNodeViewer.getTree().setLayoutData(
-                               new GridData(SWT.FILL, SWT.FILL, true, true));
-
-               tmpNodeViewer.setContentProvider(nodeContentProvider);
-               tmpNodeViewer.setLabelProvider(new VersionLabelProvider());
-               tmpNodeViewer
-                               .addDoubleClickListener(new GenericNodeDoubleClickListener(
-                                               tmpNodeViewer));
-               return tmpNodeViewer;
-       }
-
-       protected void createHistorySection(Composite parent) {
-
-               // Section Layout
-               Section section = tk.createSection(parent, Section.TWISTIE);
-               section.setLayoutData(new GridData(TableWrapData.FILL_GRAB));
-               TableWrapLayout twt = new TableWrapLayout();
-               section.setLayout(twt);
-
-               // Set title of the section
-               section.setText(JcrExplorerPlugin
-                               .getMessage("versionHistorySectionTitle"));
-
-               final Text styledText = tk.createText(section, "", SWT.FULL_SELECTION
-                               | SWT.BORDER | SWT.MULTI | SWT.WRAP | SWT.V_SCROLL);
-               styledText.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
-               section.setClient(styledText);
-               refreshHistory(styledText);
-               styledText.setEditable(false);
-               section.setExpanded(false);
-
-               AbstractFormPart part = new AbstractFormPart() {
-                       public void commit(boolean onSave) {
-                       }
-
-                       public void refresh() {
-                               super.refresh();
-                               refreshHistory(styledText);
-                       }
-               };
-               getManagedForm().addPart(part);
-       }
-
-       protected void refreshHistory(Text styledText) {
-               try {
-                       List<VersionDiff> lst = listHistoryDiff();
-                       StringBuffer main = new StringBuffer("");
-
-                       for (int i = lst.size() - 1; i >= 0; i--) {
-                               if (i == 0)
-                                       main.append("Creation (");
-                               else
-                                       main.append("Update " + i + " (");
-
-                               if (lst.get(i).getUserId() != null)
-                                       main.append("UserId : " + lst.get(i).getUserId());
-
-                               if (lst.get(i).getUserId() != null
-                                               && lst.get(i).getUpdateTime() != null)
-                                       main.append(", ");
-
-                               if (lst.get(i).getUpdateTime() != null)
-                                       main.append("Date : "
-                                                       + timeFormatter.format(lst.get(i).getUpdateTime()
-                                                                       .getTime()) + ")\n");
-
-                               StringBuffer buf = new StringBuffer("");
-                               Map<String, PropertyDiff> diffs = lst.get(i).getDiffs();
-                               for (String prop : diffs.keySet()) {
-                                       PropertyDiff pd = diffs.get(prop);
-                                       // String propName = pd.getRelPath();
-                                       Value refValue = pd.getReferenceValue();
-                                       Value newValue = pd.getNewValue();
-                                       String refValueStr = "";
-                                       String newValueStr = "";
-
-                                       if (refValue != null) {
-                                               if (refValue.getType() == PropertyType.DATE) {
-                                                       refValueStr = timeFormatter.format(refValue
-                                                                       .getDate().getTime());
-                                               } else
-                                                       refValueStr = refValue.getString();
-                                       }
-                                       if (newValue != null) {
-                                               if (newValue.getType() == PropertyType.DATE) {
-                                                       newValueStr = timeFormatter.format(newValue
-                                                                       .getDate().getTime());
-                                               } else
-                                                       newValueStr = newValue.getString();
-                                       }
-
-                                       if (pd.getType() == PropertyDiff.MODIFIED) {
-                                               buf.append(prop).append(": ");
-                                               buf.append(refValueStr);
-                                               buf.append(" > ");
-                                               buf.append(newValueStr);
-                                               buf.append("\n");
-                                       } else if (pd.getType() == PropertyDiff.ADDED
-                                                       && !"".equals(newValueStr)) {
-                                               // we don't list property that have been added with an
-                                               // empty string as value
-                                               buf.append(prop).append(": ");
-                                               buf.append(" + ");
-                                               buf.append(newValueStr);
-                                               buf.append("\n");
-                                       } else if (pd.getType() == PropertyDiff.REMOVED) {
-                                               buf.append(prop).append(": ");
-                                               buf.append(" - ");
-                                               buf.append(refValueStr);
-                                               buf.append("\n");
-                                       }
-                               }
-                               buf.append("\n");
-                               main.append(buf);
-                       }
-                       styledText.setText(main.toString());
-               } catch (RepositoryException e) {
-                       throw new ArgeoException("Cannot generate history for node", e);
-               }
-
-       }
-
-       public List<VersionDiff> listHistoryDiff() {
-               try {
-                       List<VersionDiff> res = new ArrayList<VersionDiff>();
-                       VersionManager versionManager = currentNode.getSession()
-                                       .getWorkspace().getVersionManager();
-                       VersionHistory versionHistory = versionManager
-                                       .getVersionHistory(currentNode.getPath());
-
-                       VersionIterator vit = versionHistory.getAllLinearVersions();
-                       while (vit.hasNext()) {
-                               Version version = vit.nextVersion();
-                               Node node = version.getFrozenNode();
-                               Version predecessor = null;
-                               try {
-                                       predecessor = version.getLinearPredecessor();
-                               } catch (Exception e) {
-                                       // no predecessor seems to throw an exception even if it
-                                       // shouldn't...
-                               }
-                               if (predecessor == null) {// original
-                               } else {
-                                       Map<String, PropertyDiff> diffs = JcrUtils.diffProperties(
-                                                       predecessor.getFrozenNode(), node);
-                                       if (!diffs.isEmpty()) {
-                                               String lastUserName = null;
-                                               Calendar lastUpdate = null;
-                                               try {
-                                                       if (currentNode
-                                                                       .isNodeType(NodeType.MIX_LAST_MODIFIED)) {
-                                                               lastUserName = node.getProperty(
-                                                                               Property.JCR_LAST_MODIFIED_BY)
-                                                                               .getString();
-                                                               lastUpdate = node.getProperty(
-                                                                               Property.JCR_LAST_MODIFIED).getDate();
-                                                       } else
-                                                               lastUpdate = version.getProperty(
-                                                                               Property.JCR_CREATED).getDate();
-
-                                               } catch (Exception e) {
-                                                       // Silent that info is optional
-                                               }
-                                               VersionDiff vd = new VersionDiff(lastUserName,
-                                                               lastUpdate, diffs);
-                                               res.add(vd);
-                                       }
-                               }
-                       }
-                       return res;
-               } catch (RepositoryException e) {
-                       throw new ArgeoException("Cannot generate history for node ");
-               }
-
-       }
-
-       @Override
-       public void setActive(boolean active) {
-               super.setActive(active);
-       }
-}
diff --git a/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/editors/StringNodeEditorInput.java b/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/editors/StringNodeEditorInput.java
deleted file mode 100644 (file)
index 654b2ae..0000000
+++ /dev/null
@@ -1,120 +0,0 @@
-/*
- * Copyright (C) 2007-2012 Argeo GmbH
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *         http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.argeo.jcr.ui.explorer.editors;
-
-import org.eclipse.jface.resource.ImageDescriptor;
-import org.eclipse.ui.IEditorInput;
-import org.eclipse.ui.IPersistableElement;
-
-/**
- * An editor input based on three strings define a node :
- * <ul>
- * <li>complete path to the node</li>
- * <li>the workspace name</li>
- * <li>the repository alias</li>
- * </ul>
- * In a single workspace and/or repository environment, name and alias can be
- * null.
- * 
- * Note : unused for the time being.
- */
-
-public class StringNodeEditorInput implements IEditorInput {
-       private final String path;
-       private final String repositoryAlias;
-       private final String workspaceName;
-
-       /**
-        * In order to implement a generic explorer that supports remote and multi
-        * workspaces repositories, node path can be detailed by these strings.
-        * 
-        * @param repositoryAlias
-        *            : can be null
-        * @param workspaceName
-        *            : can be null
-        * @param path
-        */
-       public StringNodeEditorInput(String repositoryAlias, String workspaceName,
-                       String path) {
-               this.path = path;
-               this.repositoryAlias = repositoryAlias;
-               this.workspaceName = workspaceName;
-       }
-
-       public Object getAdapter(@SuppressWarnings("rawtypes") Class adapter) {
-               return null;
-       }
-
-       public boolean exists() {
-               return true;
-       }
-
-       public ImageDescriptor getImageDescriptor() {
-               return null;
-       }
-
-       public String getName() {
-               return path;
-       }
-
-       public String getRepositoryAlias() {
-               return repositoryAlias;
-       }
-
-       public String getWorkspaceName() {
-               return workspaceName;
-       }
-
-       public IPersistableElement getPersistable() {
-               return null;
-       }
-
-       public String getToolTipText() {
-               return path;
-       }
-
-       public String getPath() {
-               return path;
-       }
-
-       public boolean equals(Object obj) {
-               if (this == obj)
-                       return true;
-               if (obj == null)
-                       return false;
-               if (getClass() != obj.getClass())
-                       return false;
-
-               StringNodeEditorInput other = (StringNodeEditorInput) obj;
-
-               if (!path.equals(other.getPath()))
-                       return false;
-
-               String own = other.getWorkspaceName();
-               if ((workspaceName == null && own != null)
-                               || (workspaceName != null && (own == null || !workspaceName
-                                               .equals(own))))
-                       return false;
-
-               String ora = other.getRepositoryAlias();
-               if ((repositoryAlias == null && ora != null)
-                               || (repositoryAlias != null && (ora == null || !repositoryAlias
-                                               .equals(ora))))
-                       return false;
-
-               return true;
-       }
-}
diff --git a/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/model/MaintainedRepositoryElem.java b/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/model/MaintainedRepositoryElem.java
deleted file mode 100644 (file)
index abb97a9..0000000
+++ /dev/null
@@ -1,24 +0,0 @@
-package org.argeo.jcr.ui.explorer.model;
-
-import javax.jcr.Repository;
-
-import org.argeo.ArgeoException;
-import org.argeo.eclipse.ui.TreeParent;
-import org.argeo.jcr.MaintainedRepository;
-
-/** Wraps a {@link MaintainedRepository} */
-public class MaintainedRepositoryElem extends RepositoryElem {
-
-       public MaintainedRepositoryElem(String alias, Repository repository,
-                       TreeParent parent) {
-               super(alias, repository, parent);
-               if (!(repository instanceof MaintainedRepository)) {
-                       throw new ArgeoException("Repository " + alias
-                                       + " is not amiantained repository");
-               }
-       }
-
-       protected MaintainedRepository getMaintainedRepository() {
-               return (MaintainedRepository) getRepository();
-       }
-}
diff --git a/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/model/RemoteRepositoryElem.java b/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/model/RemoteRepositoryElem.java
deleted file mode 100644 (file)
index 0be6978..0000000
+++ /dev/null
@@ -1,94 +0,0 @@
-/*
- * Copyright (C) 2007-2012 Argeo GmbH
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *         http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.argeo.jcr.ui.explorer.model;
-
-import java.util.Arrays;
-
-import javax.jcr.Node;
-import javax.jcr.Repository;
-import javax.jcr.RepositoryException;
-import javax.jcr.RepositoryFactory;
-import javax.jcr.Session;
-import javax.jcr.SimpleCredentials;
-
-import org.argeo.ArgeoException;
-import org.argeo.eclipse.ui.TreeParent;
-import org.argeo.jcr.ArgeoJcrUtils;
-import org.argeo.jcr.ArgeoNames;
-import org.argeo.util.security.Keyring;
-
-/** Root of a remote repository */
-public class RemoteRepositoryElem extends RepositoryElem {
-       private final Keyring keyring;
-       /**
-        * A session of the logged in user on the default workspace of the node
-        * repository.
-        */
-       private final Session userSession;
-       private final String remoteNodePath;
-
-       private final RepositoryFactory repositoryFactory;
-       private final String uri;
-
-       public RemoteRepositoryElem(String alias,
-                       RepositoryFactory repositoryFactory, String uri, TreeParent parent,
-                       Session userSession, Keyring keyring, String remoteNodePath) {
-               super(alias, null, parent);
-               this.repositoryFactory = repositoryFactory;
-               this.uri = uri;
-               this.keyring = keyring;
-               this.userSession = userSession;
-               this.remoteNodePath = remoteNodePath;
-       }
-
-       @Override
-       protected Session repositoryLogin(String workspaceName)
-                       throws RepositoryException {
-               Node remoteRepository = userSession.getNode(remoteNodePath);
-               String userID = remoteRepository.getProperty(ArgeoNames.ARGEO_USER_ID)
-                               .getString();
-               String pwdPath = remoteRepository.getPath() + '/'
-                               + ArgeoNames.ARGEO_PASSWORD;
-               char[] password = keyring.getAsChars(pwdPath);
-
-               try {
-                       SimpleCredentials credentials = new SimpleCredentials(userID,
-                                       password);
-                       return getRepository().login(credentials, workspaceName);
-               } finally {
-                       Arrays.fill(password, 0, password.length, ' ');
-               }
-       }
-
-       @Override
-       public Repository getRepository() {
-               if (repository == null)
-                       repository = ArgeoJcrUtils.getRepositoryByUri(repositoryFactory,
-                                       uri);
-               return super.getRepository();
-       }
-
-       public void remove() {
-               try {
-                       Node remoteNode = userSession.getNode(remoteNodePath);
-                       remoteNode.remove();
-                       remoteNode.getSession().save();
-               } catch (RepositoryException e) {
-                       throw new ArgeoException("Cannot remove " + remoteNodePath, e);
-               }
-       }
-
-}
diff --git a/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/model/RepositoriesElem.java b/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/model/RepositoriesElem.java
deleted file mode 100644 (file)
index b123727..0000000
+++ /dev/null
@@ -1,134 +0,0 @@
-/*
- * Copyright (C) 2007-2012 Argeo GmbH
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *         http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.argeo.jcr.ui.explorer.model;
-
-import java.util.Map;
-
-import javax.jcr.Node;
-import javax.jcr.NodeIterator;
-import javax.jcr.Repository;
-import javax.jcr.RepositoryException;
-import javax.jcr.RepositoryFactory;
-import javax.jcr.Session;
-
-import org.argeo.ArgeoException;
-import org.argeo.eclipse.ui.ErrorFeedback;
-import org.argeo.eclipse.ui.TreeParent;
-import org.argeo.jcr.ArgeoNames;
-import org.argeo.jcr.MaintainedRepository;
-import org.argeo.jcr.RepositoryRegister;
-import org.argeo.jcr.UserJcrUtils;
-import org.argeo.util.security.Keyring;
-
-/**
- * UI Tree component. Implements the Argeo abstraction of a
- * {@link RepositoryFactory} that enable a user to "mount" various repositories
- * in a single Tree like View. It is usually meant to be at the root of the UI
- * Tree and thus {@link getParent()} method will return null.
- * 
- * The {@link RepositoryFactory} is injected at instantiation time and must be
- * use get or register new {@link Repository} objects upon which a reference is
- * kept here.
- */
-
-public class RepositoriesElem extends TreeParent implements ArgeoNames {
-       private final RepositoryRegister repositoryRegister;
-       private final RepositoryFactory repositoryFactory;
-
-       /**
-        * A session of the logged in user on the default workspace of the node
-        * repository.
-        */
-       private final Session userSession;
-       private final Keyring keyring;
-
-       public RepositoriesElem(String name, RepositoryRegister repositoryRegister,
-                       RepositoryFactory repositoryFactory, TreeParent parent,
-                       Session userSession, Keyring keyring) {
-               super(name);
-               this.repositoryRegister = repositoryRegister;
-               this.repositoryFactory = repositoryFactory;
-               this.userSession = userSession;
-               this.keyring = keyring;
-       }
-
-       /**
-        * Override normal behavior to initialize the various repositories only at
-        * request time
-        */
-       @Override
-       public synchronized Object[] getChildren() {
-               if (isLoaded()) {
-                       return super.getChildren();
-               } else {
-                       // initialize current object
-                       Map<String, Repository> refRepos = repositoryRegister
-                                       .getRepositories();
-                       for (String name : refRepos.keySet()) {
-                               Repository repository = refRepos.get(name);
-                               if (repository instanceof MaintainedRepository)
-                                       super.addChild(new MaintainedRepositoryElem(name,
-                                                       repository, this));
-                               else
-                                       super.addChild(new RepositoryElem(name, repository, this));
-                       }
-
-                       // remote
-                       if (keyring != null) {
-                               try {
-                                       addRemoteRepositories(keyring);
-                               } catch (RepositoryException e) {
-                                       throw new ArgeoException(
-                                                       "Cannot browse remote repositories", e);
-                               }
-                       }
-                       return super.getChildren();
-               }
-       }
-
-       protected void addRemoteRepositories(Keyring jcrKeyring)
-                       throws RepositoryException {
-               Node userHome = UserJcrUtils.getUserHome(userSession);
-               if (userHome != null && userHome.hasNode(ARGEO_REMOTE)) {
-                       NodeIterator it = userHome.getNode(ARGEO_REMOTE).getNodes();
-                       while (it.hasNext()) {
-                               Node remoteNode = it.nextNode();
-                               String uri = remoteNode.getProperty(ARGEO_URI).getString();
-                               try {
-                                       RemoteRepositoryElem remoteRepositoryNode = new RemoteRepositoryElem(
-                                                       remoteNode.getName(), repositoryFactory, uri, this,
-                                                       userSession, jcrKeyring, remoteNode.getPath());
-                                       super.addChild(remoteRepositoryNode);
-                               } catch (Exception e) {
-                                       ErrorFeedback.show("Cannot add remote repository "
-                                                       + remoteNode, e);
-                               }
-                       }
-               }
-       }
-
-       public void registerNewRepository(String alias, Repository repository) {
-               // TODO: implement this
-               // Create a new RepositoryNode Object
-               // add it
-               // super.addChild(new RepositoriesNode(...));
-       }
-
-       /** Returns the {@link RepositoryRegister} wrapped by this object. */
-       public RepositoryRegister getRepositoryRegister() {
-               return repositoryRegister;
-       }
-}
diff --git a/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/model/RepositoryElem.java b/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/model/RepositoryElem.java
deleted file mode 100644 (file)
index 935bac1..0000000
+++ /dev/null
@@ -1,103 +0,0 @@
-/*
- * Copyright (C) 2007-2012 Argeo GmbH
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *         http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.argeo.jcr.ui.explorer.model;
-
-import javax.jcr.Repository;
-import javax.jcr.RepositoryException;
-import javax.jcr.Session;
-
-import org.argeo.ArgeoException;
-import org.argeo.eclipse.ui.TreeParent;
-
-/**
- * UI Tree component. Wraps a JCR {@link Repository}. It also keeps a reference
- * to its parent Tree Ui component; typically the unique {@link Repositories}
- * object of the current view to enable bi-directionnal browsing in the tree.
- */
-
-public class RepositoryElem extends TreeParent {
-       private String alias;
-       protected Repository repository;
-       private Session defaultSession = null;
-
-       /** Create a new repository with distinct name & alias */
-       public RepositoryElem(String alias, Repository repository, TreeParent parent) {
-               super(alias);
-               this.repository = repository;
-               setParent(parent);
-               this.alias = alias;
-       }
-
-       public void login() {
-               try {
-                       defaultSession = repositoryLogin(null);
-                       String[] wkpNames = defaultSession.getWorkspace()
-                                       .getAccessibleWorkspaceNames();
-                       for (String wkpName : wkpNames) {
-                               if (wkpName.equals(defaultSession.getWorkspace().getName()))
-                                       addChild(new WorkspaceElem(this, wkpName, defaultSession));
-                               else
-                                       addChild(new WorkspaceElem(this, wkpName));
-                       }
-               } catch (RepositoryException e) {
-                       throw new ArgeoException("Cannot connect to repository " + alias, e);
-               }
-       }
-
-       /**
-        * Actual call to the
-        * {@link Repository#login(javax.jcr.Credentials, String)} method. To be
-        * overridden.
-        */
-       protected Session repositoryLogin(String workspaceName)
-                       throws RepositoryException {
-               return repository.login(workspaceName);
-       }
-
-       public String[] getAccessibleWorkspaceNames() {
-               try {
-                       return defaultSession.getWorkspace().getAccessibleWorkspaceNames();
-               } catch (RepositoryException e) {
-                       throw new ArgeoException("Cannot retrieve workspace names", e);
-               }
-       }
-
-       public void createWorkspace(String workspaceName) {
-               if (!isConnected())
-                       login();
-               try {
-                       defaultSession.getWorkspace().createWorkspace(workspaceName);
-               } catch (RepositoryException e) {
-                       throw new ArgeoException("Cannot create workspace", e);
-               }
-       }
-
-       /** returns the {@link Repository} referenced by the current UI Node */
-       public Repository getRepository() {
-               return repository;
-       }
-
-       public String getAlias() {
-               return alias;
-       }
-
-       public Boolean isConnected() {
-               if (defaultSession != null && defaultSession.isLive())
-                       return true;
-               else
-                       return false;
-       }
-}
diff --git a/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/model/SingleJcrNodeElem.java b/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/model/SingleJcrNodeElem.java
deleted file mode 100644 (file)
index 7b588f8..0000000
+++ /dev/null
@@ -1,108 +0,0 @@
-/*
- * Copyright (C) 2007-2012 Argeo GmbH
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *         http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.argeo.jcr.ui.explorer.model;
-
-import javax.jcr.Node;
-import javax.jcr.NodeIterator;
-import javax.jcr.RepositoryException;
-import javax.jcr.Workspace;
-
-import org.argeo.ArgeoException;
-import org.argeo.eclipse.ui.TreeParent;
-
-/**
- * UI Tree component. Wraps a node of a JCR {@link Workspace}. It also keeps a
- * reference to its parent node that can either be a {@link WorkspaceElem}, a
- * {@link SingleJcrNodeElem} or null if the node is "mounted" as the root of the UI
- * tree.
- */
-
-public class SingleJcrNodeElem extends TreeParent {
-
-       private final Node node;
-       private String alias = null;
-
-       // keeps a local reference to the node's name to avoid exception when the
-       // session is lost
-       // private final String name;
-
-       /** Creates a new UiNode in the UI Tree */
-       public SingleJcrNodeElem(TreeParent parent, Node node, String name) {
-               super(name);
-               setParent(parent);
-               this.node = node;
-       }
-
-       /**
-        * Creates a new UiNode in the UI Tree, keeping a reference to the alias of
-        * the corresponding repository in the current UI environment. It is useful
-        * to be able to mount nodes as roots of the UI tree.
-        */
-       public SingleJcrNodeElem(TreeParent parent, Node node, String name, String alias) {
-               super(name);
-               setParent(parent);
-               this.node = node;
-               this.alias = alias;
-       }
-
-       /** returns the node wrapped by the current Ui object */
-       public Node getNode() {
-               return node;
-       }
-
-       protected String getRepositoryAlias() {
-               return alias;
-       }
-
-       /**
-        * Override normal behavior to initialize children only when first requested
-        */
-       @Override
-       public synchronized Object[] getChildren() {
-               if (isLoaded()) {
-                       return super.getChildren();
-               } else {
-                       // initialize current object
-                       try {
-                               NodeIterator ni = node.getNodes();
-                               while (ni.hasNext()) {
-                                       Node curNode = ni.nextNode();
-                                       addChild(new SingleJcrNodeElem(this, curNode, curNode.getName()));
-                               }
-                               return super.getChildren();
-                       } catch (RepositoryException re) {
-                               throw new ArgeoException(
-                                               "Unexcpected error while initializing children SingleJcrNode",
-                                               re);
-                       }
-               }
-       }
-
-       @Override
-       public boolean hasChildren() {
-               try {
-                       if (node.getSession().isLive())
-                               return node.hasNodes();
-                       else
-                               return false;
-               } catch (RepositoryException re) {
-                       throw new ArgeoException(
-                                       "Unexpected error while checking children node existence",
-                                       re);
-               }
-       }
-
-}
diff --git a/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/model/WorkspaceElem.java b/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/model/WorkspaceElem.java
deleted file mode 100644 (file)
index bb9b69c..0000000
+++ /dev/null
@@ -1,130 +0,0 @@
-/*
- * Copyright (C) 2007-2012 Argeo GmbH
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *         http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.argeo.jcr.ui.explorer.model;
-
-import javax.jcr.Node;
-import javax.jcr.NodeIterator;
-import javax.jcr.RepositoryException;
-import javax.jcr.Session;
-import javax.jcr.Workspace;
-
-import org.argeo.ArgeoException;
-import org.argeo.eclipse.ui.TreeParent;
-import org.argeo.jcr.JcrUtils;
-
-/**
- * UI Tree component. Wraps the root node of a JCR {@link Workspace}. It also
- * keeps a reference to its parent {@link RepositoryElem}, to be able to
- * retrieve alias of the current used repository
- */
-public class WorkspaceElem extends TreeParent {
-       private Session session = null;
-
-       public WorkspaceElem(RepositoryElem parent, String name) {
-               this(parent, name, null);
-       }
-
-       public WorkspaceElem(RepositoryElem parent, String name, Session session) {
-               super(name);
-               this.session = session;
-               setParent(parent);
-       }
-
-       public Session getSession() {
-               return session;
-       }
-
-       public Node getRootNode() {
-               try {
-                       if (session != null)
-                               return session.getRootNode();
-                       else
-                               return null;
-               } catch (RepositoryException e) {
-                       throw new ArgeoException("Cannot get root node of workspace "
-                                       + getName(), e);
-               }
-       }
-
-       public void login() {
-               try {
-                       session = ((RepositoryElem) getParent()).repositoryLogin(getName());
-               } catch (RepositoryException e) {
-                       throw new ArgeoException("Cannot connect to repository "
-                                       + getName(), e);
-               }
-       }
-
-       public Boolean isConnected() {
-               if (session != null && session.isLive())
-                       return true;
-               else
-                       return false;
-       }
-
-       @Override
-       public synchronized void dispose() {
-               logout();
-               super.dispose();
-       }
-
-       /** Logouts the session, does not nothing if there is no live session. */
-       public void logout() {
-               clearChildren();
-               JcrUtils.logoutQuietly(session);
-       }
-
-       @Override
-       public boolean hasChildren() {
-               try {
-                       if (isConnected())
-                               return session.getRootNode().hasNodes();
-                       else
-                               return false;
-               } catch (RepositoryException re) {
-                       throw new ArgeoException(
-                                       "Unexpected error while checking children node existence",
-                                       re);
-               }
-       }
-
-       /** Override normal behaviour to initialize display of the workspace */
-       @Override
-       public synchronized Object[] getChildren() {
-               if (isLoaded()) {
-                       return super.getChildren();
-               } else {
-                       // initialize current object
-                       try {
-                               Node rootNode;
-                               if (session == null)
-                                       return null;
-                               else
-                                       rootNode = session.getRootNode();
-                               NodeIterator ni = rootNode.getNodes();
-                               while (ni.hasNext()) {
-                                       Node node = ni.nextNode();
-                                       addChild(new SingleJcrNodeElem(this, node, node.getName()));
-                               }
-                               return super.getChildren();
-                       } catch (RepositoryException e) {
-                               throw new ArgeoException(
-                                               "Cannot initialize WorkspaceNode UI object."
-                                                               + getName(), e);
-                       }
-               }
-       }
-}
diff --git a/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/providers/FullVersioningTreeContentProvider.java b/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/providers/FullVersioningTreeContentProvider.java
deleted file mode 100644 (file)
index 736a5aa..0000000
+++ /dev/null
@@ -1,115 +0,0 @@
-/*
- * Copyright (C) 2007-2012 Argeo GmbH
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *         http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.argeo.jcr.ui.explorer.providers;
-
-import java.util.ArrayList;
-import java.util.List;
-
-import javax.jcr.Node;
-import javax.jcr.RepositoryException;
-import javax.jcr.nodetype.NodeType;
-import javax.jcr.version.Version;
-import javax.jcr.version.VersionHistory;
-import javax.jcr.version.VersionIterator;
-import javax.jcr.version.VersionManager;
-
-import org.argeo.ArgeoException;
-import org.eclipse.jface.viewers.ITreeContentProvider;
-import org.eclipse.jface.viewers.Viewer;
-
-/**
- * Implementation of the {@code ITreeContentProvider} in order to display some
- * version informations of a JCR full versionable node in a tree like structure
- * 
- */
-public class FullVersioningTreeContentProvider implements ITreeContentProvider {
-       // private Node rootNode;
-       // private ItemComparator itemComparator = new ItemComparator();
-
-       /**
-        * Sends back the first level of the Tree. input element must be a single
-        * node object
-        */
-       public Object[] getElements(Object inputElement) {
-               try {
-                       Node rootNode = (Node) inputElement;
-                       String curPath = rootNode.getPath();
-                       VersionManager vm = rootNode.getSession().getWorkspace()
-                                       .getVersionManager();
-
-                       VersionHistory vh = vm.getVersionHistory(curPath);
-                       List<Version> result = new ArrayList<Version>();
-                       VersionIterator vi = vh.getAllLinearVersions();
-
-                       while (vi.hasNext()) {
-                               result.add(vi.nextVersion());
-                       }
-                       return result.toArray();
-               } catch (RepositoryException re) {
-                       throw new ArgeoException(
-                                       "Unexpected error while getting version elements", re);
-               }
-       }
-
-       public Object[] getChildren(Object parentElement) {
-               try {
-                       if (parentElement instanceof Version) {
-                               List<Node> tmp = new ArrayList<Node>();
-                               tmp.add(((Version) parentElement).getFrozenNode());
-                               return tmp.toArray();
-                       }
-               } catch (RepositoryException re) {
-                       throw new ArgeoException("Unexpected error while getting child "
-                                       + "node for version element", re);
-               }
-               return null;
-       }
-
-       public Object getParent(Object element) {
-               try {
-                       // this will not work in a simpleVersionning environment, parent is
-                       // not a node.
-                       if (element instanceof Node
-                                       && ((Node) element).isNodeType(NodeType.NT_FROZEN_NODE)) {
-                               Node node = (Node) element;
-                               return node.getParent();
-                       } else
-                               return null;
-               } catch (RepositoryException e) {
-                       return null;
-               }
-       }
-
-       public boolean hasChildren(Object element) {
-               try {
-                       if (element instanceof Version)
-                               return true;
-                       else if (element instanceof Node)
-                               return ((Node) element).hasNodes();
-                       else
-                               return false;
-               } catch (RepositoryException e) {
-                       throw new ArgeoException("Cannot check children of " + element, e);
-               }
-       }
-
-       public void dispose() {
-       }
-
-       public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
-       }
-
-}
diff --git a/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/providers/PropertyLabelProvider.java b/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/providers/PropertyLabelProvider.java
deleted file mode 100644 (file)
index decbe63..0000000
+++ /dev/null
@@ -1,116 +0,0 @@
-/*
- * Copyright (C) 2007-2012 Argeo GmbH
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *         http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.argeo.jcr.ui.explorer.providers;
-
-import java.text.DateFormat;
-import java.text.SimpleDateFormat;
-
-import javax.jcr.Property;
-import javax.jcr.PropertyType;
-import javax.jcr.RepositoryException;
-import javax.jcr.Value;
-
-import org.argeo.ArgeoException;
-import org.argeo.jcr.JcrUtils;
-import org.argeo.jcr.ui.explorer.JcrExplorerConstants;
-import org.eclipse.jface.viewers.ColumnLabelProvider;
-import org.eclipse.jface.viewers.ViewerCell;
-
-public class PropertyLabelProvider extends ColumnLabelProvider implements
-               JcrExplorerConstants {
-
-       // To be able to change column order easily
-       public static final int COLUMN_PROPERTY = 0;
-       public static final int COLUMN_VALUE = 1;
-       public static final int COLUMN_ATTRIBUTES = 2;
-
-       // Utils
-       protected DateFormat timeFormatter = new SimpleDateFormat(DATE_TIME_FORMAT);
-
-       public void update(ViewerCell cell) {
-               Object element = cell.getElement();
-               cell.setText(getColumnText(element, cell.getColumnIndex()));
-               // Image image = getImage(element);
-               // cell.setImage(image);
-               // cell.setBackground(getBackground(element));
-               // cell.setForeground(getForeground(element));
-               // cell.setFont(getFont(element));
-       }
-
-       public String getColumnText(Object element, int columnIndex) {
-               try {
-                       if (element instanceof Property) {
-                               Property prop = (Property) element;
-                               if (prop.isMultiple()) {
-                                       switch (columnIndex) {
-                                       case COLUMN_PROPERTY:
-                                               return prop.getName();
-                                       case COLUMN_VALUE:
-                                               // Corresponding values are listed on children
-                                               return "";
-                                       case COLUMN_ATTRIBUTES:
-                                               return JcrUtils.getPropertyDefinitionAsString(prop);
-                                       }
-                               } else {
-                                       switch (columnIndex) {
-                                       case COLUMN_PROPERTY:
-                                               return prop.getName();
-                                       case COLUMN_VALUE:
-                                               return formatValueAsString(prop.getValue());
-                                       case COLUMN_ATTRIBUTES:
-                                               return JcrUtils.getPropertyDefinitionAsString(prop);
-                                       }
-                               }
-                       } else if (element instanceof Value) {
-                               Value val = (Value) element;
-
-                               switch (columnIndex) {
-                               case COLUMN_PROPERTY:
-                                       // Nothing to show
-                                       return "";
-                               case COLUMN_VALUE:
-                                       return formatValueAsString(val);
-                               case COLUMN_ATTRIBUTES:
-                                       // Corresponding attributes are listed on the parent
-                                       return "";
-                               }
-                       }
-
-               } catch (RepositoryException re) {
-                       throw new ArgeoException(
-                                       "Unexepected error while getting property values", re);
-               }
-               return null;
-       }
-
-       private String formatValueAsString(Value value) {
-               // TODO enhance this method
-               try {
-                       String strValue;
-
-                       if (value.getType() == PropertyType.BINARY)
-                               strValue = "<binary>";
-                       else if (value.getType() == PropertyType.DATE)
-                               strValue = timeFormatter.format(value.getDate().getTime());
-                       else
-                               strValue = value.getString();
-                       return strValue;
-               } catch (RepositoryException e) {
-                       throw new ArgeoException("unexpected error while formatting value",
-                                       e);
-               }
-       }
-}
diff --git a/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/providers/SingleNodeAsTreeContentProvider.java b/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/providers/SingleNodeAsTreeContentProvider.java
deleted file mode 100644 (file)
index 8c69b6b..0000000
+++ /dev/null
@@ -1,106 +0,0 @@
-/*
- * Copyright (C) 2007-2012 Argeo GmbH
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *         http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.argeo.jcr.ui.explorer.providers;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.List;
-
-import javax.jcr.Node;
-import javax.jcr.NodeIterator;
-import javax.jcr.RepositoryException;
-
-import org.argeo.ArgeoException;
-import org.argeo.eclipse.ui.jcr.utils.JcrItemsComparator;
-import org.eclipse.jface.viewers.ITreeContentProvider;
-import org.eclipse.jface.viewers.Viewer;
-
-/**
- * Implementation of the {@code ITreeContentProvider} in order to display a
- * single JCR node and its children in a tree like structure
- * 
- */
-public class SingleNodeAsTreeContentProvider implements ITreeContentProvider {
-       // private Node rootNode;
-       private JcrItemsComparator itemComparator = new JcrItemsComparator();
-
-       /**
-        * Sends back the first level of the Tree. input element must be a single
-        * node object
-        */
-       public Object[] getElements(Object inputElement) {
-               try {
-                       Node rootNode = (Node) inputElement;
-                       List<Node> result = new ArrayList<Node>();
-                       NodeIterator ni = rootNode.getNodes();
-                       while (ni.hasNext()) {
-                               result.add(ni.nextNode());
-                       }
-
-                       return result.toArray();
-               } catch (RepositoryException re) {
-                       throw new ArgeoException(
-                                       "Unexpected error while getting child nodes for children editor page ",
-                                       re);
-               }
-       }
-
-       public Object[] getChildren(Object parentElement) {
-               return childrenNodes((Node) parentElement);
-       }
-
-       public Object getParent(Object element) {
-               try {
-                       Node node = (Node) element;
-                       if (!node.getPath().equals("/"))
-                               return node.getParent();
-                       else
-                               return null;
-               } catch (RepositoryException e) {
-                       return null;
-               }
-       }
-
-       public boolean hasChildren(Object element) {
-               try {
-                       return ((Node) element).hasNodes();
-               } catch (RepositoryException e) {
-                       throw new ArgeoException("Cannot check children of " + element, e);
-               }
-       }
-
-       public void dispose() {
-       }
-
-       public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
-       }
-
-       protected Object[] childrenNodes(Node parentNode) {
-               try {
-                       List<Node> children = new ArrayList<Node>();
-                       NodeIterator nit = parentNode.getNodes();
-                       while (nit.hasNext()) {
-                               Node node = nit.nextNode();
-                               children.add(node);
-                       }
-                       Node[] arr = children.toArray(new Node[children.size()]);
-                       Arrays.sort(arr, itemComparator);
-                       return arr;
-               } catch (RepositoryException e) {
-                       throw new ArgeoException("Cannot list children of " + parentNode, e);
-               }
-       }
-}
diff --git a/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/providers/VersionLabelProvider.java b/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/providers/VersionLabelProvider.java
deleted file mode 100644 (file)
index 69b35eb..0000000
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * Copyright (C) 2007-2012 Argeo GmbH
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *         http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.argeo.jcr.ui.explorer.providers;
-
-import javax.jcr.Node;
-import javax.jcr.RepositoryException;
-import javax.jcr.version.Version;
-
-import org.argeo.ArgeoException;
-import org.eclipse.jface.viewers.ColumnLabelProvider;
-
-/**
- * simple wrapping of the ColumnLabelProvider class to provide text display in
- * order to build a tree for version. The Get text method does not assume that
- * Version extends Node class to respect JCR 2.0 specification
- * 
- */
-public class VersionLabelProvider extends ColumnLabelProvider {
-
-       public String getText(Object element) {
-               try {
-                       if (element instanceof Version) {
-                               Version version = (Version) element;
-                               return version.getName();
-                       } else if (element instanceof Node) {
-                               return ((Node) element).getName();
-                       }
-               } catch (RepositoryException re) {
-                       throw new ArgeoException(
-                                       "Unexpected error while getting element name", re);
-               }
-               return super.getText(element);
-       }
-}
diff --git a/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/utils/GenericNodeDoubleClickListener.java b/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/utils/GenericNodeDoubleClickListener.java
deleted file mode 100644 (file)
index 0f93450..0000000
+++ /dev/null
@@ -1,109 +0,0 @@
-/*
- * Copyright (C) 2007-2012 Argeo GmbH
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *         http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.argeo.jcr.ui.explorer.utils;
-
-import javax.jcr.Node;
-import javax.jcr.RepositoryException;
-import javax.jcr.nodetype.NodeType;
-
-import org.argeo.ArgeoException;
-import org.argeo.eclipse.ui.jcr.utils.JcrFileProvider;
-import org.argeo.eclipse.ui.specific.FileHandler;
-import org.argeo.jcr.ui.explorer.JcrExplorerPlugin;
-import org.argeo.jcr.ui.explorer.editors.GenericNodeEditor;
-import org.argeo.jcr.ui.explorer.editors.GenericNodeEditorInput;
-import org.argeo.jcr.ui.explorer.model.RepositoryElem;
-import org.argeo.jcr.ui.explorer.model.SingleJcrNodeElem;
-import org.argeo.jcr.ui.explorer.model.WorkspaceElem;
-import org.eclipse.jface.viewers.DoubleClickEvent;
-import org.eclipse.jface.viewers.IDoubleClickListener;
-import org.eclipse.jface.viewers.IStructuredSelection;
-import org.eclipse.jface.viewers.TreeViewer;
-import org.eclipse.ui.PartInitException;
-
-/**
- * Centralizes the management of double click on a NodeTreeViewer
- */
-public class GenericNodeDoubleClickListener implements IDoubleClickListener {
-
-       // private final static Log log = LogFactory
-       // .getLog(GenericNodeDoubleClickListener.class);
-
-       private TreeViewer nodeViewer;
-       private JcrFileProvider jfp;
-       private FileHandler fileHandler;
-
-       public GenericNodeDoubleClickListener(TreeViewer nodeViewer) {
-               this.nodeViewer = nodeViewer;
-               jfp = new JcrFileProvider();
-               // Commented out. see https://www.argeo.org/bugzilla/show_bug.cgi?id=188
-               fileHandler = null;
-               // fileHandler = new FileHandler(jfp);
-       }
-
-       public void doubleClick(DoubleClickEvent event) {
-               if (event.getSelection() == null || event.getSelection().isEmpty())
-                       return;
-               Object obj = ((IStructuredSelection) event.getSelection())
-                               .getFirstElement();
-               if (obj instanceof RepositoryElem) {
-                       RepositoryElem rpNode = (RepositoryElem) obj;
-                       if (!rpNode.isConnected()) {
-                               rpNode.login();
-                               nodeViewer.refresh(obj);
-                       }
-                       // else do nothing
-               } else if (obj instanceof WorkspaceElem) {
-                       WorkspaceElem wn = (WorkspaceElem) obj;
-                       if (wn.isConnected())
-                               wn.logout();
-                       else
-                               wn.login();
-                       nodeViewer.refresh(obj);
-               } else if (obj instanceof SingleJcrNodeElem) {
-                       SingleJcrNodeElem sjn = (SingleJcrNodeElem) obj;
-                       Node node = sjn.getNode();
-                       try {
-                               if (node.isNodeType(NodeType.NT_FILE)) {
-                                       // double click on a file node triggers its opening
-                                       String name = node.getName();
-                                       String id = node.getIdentifier();
-
-                                       // For the file provider to be able to browse the
-                                       // various
-                                       // repository.
-                                       // TODO : enhanced that.
-                                       // ITreeContentProvider itcp = (ITreeContentProvider)
-                                       // nodeViewer
-                                       // .getContentProvider();
-                                       jfp.setReferenceNode(node);
-                                       if (fileHandler != null)
-                                               fileHandler.openFile(name, id);
-                               }
-                               GenericNodeEditorInput gnei = new GenericNodeEditorInput(node);
-                               JcrExplorerPlugin.getDefault().getWorkbench()
-                                               .getActiveWorkbenchWindow().getActivePage()
-                                               .openEditor(gnei, GenericNodeEditor.ID);
-                       } catch (RepositoryException re) {
-                               throw new ArgeoException(
-                                               "Repository error while getting node info", re);
-                       } catch (PartInitException pie) {
-                               throw new ArgeoException(
-                                               "Unexepected exception while opening node editor", pie);
-                       }
-               }
-       }
-}
diff --git a/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/utils/JcrUiUtils.java b/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/utils/JcrUiUtils.java
deleted file mode 100644 (file)
index ca32113..0000000
+++ /dev/null
@@ -1,179 +0,0 @@
-/*
- * Copyright (C) 2007-2012 Argeo GmbH
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *         http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.argeo.jcr.ui.explorer.utils;
-
-import javax.jcr.Node;
-import javax.jcr.RepositoryException;
-
-import org.argeo.ArgeoException;
-import org.argeo.eclipse.ui.TreeParent;
-import org.argeo.jcr.ui.explorer.model.RepositoriesElem;
-import org.argeo.jcr.ui.explorer.model.RepositoryElem;
-import org.argeo.jcr.ui.explorer.model.SingleJcrNodeElem;
-import org.argeo.jcr.ui.explorer.model.WorkspaceElem;
-
-/** Centralizes some useful methods to build UIs with JCR */
-public class JcrUiUtils {
-
-       /** Insure that the UI component is not stale, refresh if needed */
-       public static void forceRefreshIfNeeded(TreeParent element) {
-               Node curNode = null;
-
-               boolean doRefresh = false;
-
-               try {
-                       if (element instanceof SingleJcrNodeElem) {
-                               curNode = ((SingleJcrNodeElem) element).getNode();
-                       } else if (element instanceof WorkspaceElem) {
-                               curNode = ((WorkspaceElem) element).getRootNode();
-                       }
-
-                       if (curNode != null
-                                       && element.getChildren().length != curNode.getNodes()
-                                                       .getSize())
-                               doRefresh = true;
-                       else if (element instanceof RepositoryElem) {
-                               RepositoryElem rn = (RepositoryElem) element;
-                               if (rn.isConnected()) {
-                                       String[] wkpNames = rn.getAccessibleWorkspaceNames();
-                                       if (element.getChildren().length != wkpNames.length)
-                                               doRefresh = true;
-                               }
-                       } else if (element instanceof RepositoriesElem) {
-                               doRefresh = true;
-                               // Always force refresh for RepositoriesElem : the condition
-                               // below does not take remote repository into account and it is
-                               // not trivial to do so.
-
-                               // RepositoriesElem rn = (RepositoriesElem) element;
-                               // if (element.getChildren().length !=
-                               // rn.getRepositoryRegister()
-                               // .getRepositories().size())
-                               // doRefresh = true;
-                       }
-                       if (doRefresh) {
-                               element.clearChildren();
-                               element.getChildren();
-                       }
-               } catch (RepositoryException re) {
-                       throw new ArgeoException(
-                                       "Unexpected error while synchronising the UI with the JCR repository",
-                                       re);
-               }
-       }
-
-       /**
-        * Insure that a model element is inline with the underlying data by
-        * cleaning the corresponding subtree and building it again.
-        */
-       public static void forceRebuild(TreeParent element) {
-               // TODO implement this method if needed.
-       }
-       /**
-        * Workaround to get the alias of the repository that contains the given
-        * element. As we cannot browse the UI tree upward we recursively browse it
-        * downward until we find the given element
-        * */
-       // public static String getRepositoryAliasFromITreeElement(
-       // NodeContentProvider ncp, Object element) {
-       // RepositoryNode repositoryNode = null;
-       // if (element instanceof RepositoryNode)
-       // return ((RepositoryNode) element).getName();
-       // else if (element instanceof RepositoryRegister)
-       // throw new ArgeoException(
-       // "Cannot get alias for a repository register");
-       //
-       // // Get root elements
-       // Object[] elements = ncp.getElements(null);
-       //
-       // try {
-       // for (int i = 0; i < elements.length; i++) {
-       // if (elements[i] instanceof Node) {
-       // Node curNode = (Node) elements[i];
-       // if (curNode.isNodeType(ArgeoTypes.ARGEO_USER_HOME)) {
-       // // Do nothing, we'll find the node in the "normal" tree
-       // // and
-       // // get corresponding alias this way round
-       // } else
-       // throw new ArgeoException(
-       // "Normal nodes should not be at the root of NodeTreeViewer");
-       // } else if (elements[i] instanceof RepositoryRegister) {
-       // RepositoryRegister repositoryRegister = (RepositoryRegister) elements[i];
-       // Map<String, Repository> repositories = repositoryRegister
-       // .getRepositories();
-       //
-       // for (String name : repositories.keySet()) {
-       // boolean found = isElementInCurrentTreePart(
-       // ncp,
-       // new RepositoryNode(name, repositories.get(name)),
-       // (Node) element);
-       // if (found)
-       // return name;
-       // }
-       // } else
-       // throw new ArgeoException(
-       // "Unexpected object class at the root of NodeTreeViewer");
-       // }
-       // } catch (RepositoryException re) {
-       // throw new ArgeoException(
-       // "Unexpected error while retrieving Alias name", re);
-       // }
-       // return null;
-       // }
-       //
-       // /** implements the recursivity */
-       // private static boolean isElementInCurrentTreePart(NodeContentProvider
-       // ncp,
-       // Object parentElement, NodParente searchedElement) {
-       // boolean found = false;
-       // if (parentElement instanceof WorkspaceNode) {
-       // WorkspaceNode wn = (WorkspaceNode) parentElement;
-       // Object[] children = wn.getChildren();
-       // int i = children.length - 1;
-       // while (!found && i >= 0) {
-       // found = isElementInCurrentTreePart(ncp, children[i],
-       // searchedElement);
-       // }
-       // return found;
-       // } else if (parentElement instanceof RepositoryNode) {
-       // RepositoryNode rn = (RepositoryNode) parentElement;
-       // Object[] children = rn.getChildren();
-       // int i = children.length - 1;
-       // while (!found && i >= 0) {
-       // found = isElementInCurrentTreePart(ncp, children[i],
-       // searchedElement);
-       // }
-       // return found;
-       // } else {
-       // Node node = (Node) parentElement;
-       // if (node.equals(searchedElement))
-       // return true;
-       // NodeIterator ni;
-       // try {
-       // ni = node.getNodes();
-       // while (!found && ni.hasNext()) {
-       // found = isElementInCurrentTreePart(ncp, ni.nextNode(),
-       // searchedElement);
-       // }
-       // } catch (RepositoryException e) {
-       // throw new ArgeoException("unexpected erreur while recursively"
-       // + " recovering RepositoryNode for selected object", e);
-       // }
-       //
-       // return found;
-       // }
-       // }
-}
diff --git a/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/utils/TreeObjectsComparator.java b/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/utils/TreeObjectsComparator.java
deleted file mode 100644 (file)
index 02450d6..0000000
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * Copyright (C) 2007-2012 Argeo GmbH
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *         http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.argeo.jcr.ui.explorer.utils;
-
-import java.util.Comparator;
-
-import org.argeo.eclipse.ui.TreeParent;
-
-public class TreeObjectsComparator implements Comparator<TreeParent> {
-       public int compare(TreeParent o1, TreeParent o2) {
-               return o1.getName().compareTo(o2.getName());
-       }
-}
\ No newline at end of file
diff --git a/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/views/GenericJcrBrowser.java b/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/views/GenericJcrBrowser.java
deleted file mode 100644 (file)
index f401ae8..0000000
+++ /dev/null
@@ -1,357 +0,0 @@
-/*
- * Copyright (C) 2007-2012 Argeo GmbH
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *         http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.argeo.jcr.ui.explorer.views;
-
-import java.util.List;
-
-import javax.jcr.Property;
-import javax.jcr.PropertyType;
-import javax.jcr.Repository;
-import javax.jcr.RepositoryException;
-import javax.jcr.RepositoryFactory;
-import javax.jcr.Session;
-import javax.jcr.Value;
-import javax.jcr.observation.Event;
-import javax.jcr.observation.EventListener;
-import javax.jcr.observation.ObservationManager;
-
-import org.argeo.ArgeoException;
-import org.argeo.eclipse.ui.TreeParent;
-import org.argeo.eclipse.ui.jcr.AsyncUiEventListener;
-import org.argeo.eclipse.ui.jcr.utils.NodeViewerComparer;
-import org.argeo.eclipse.ui.jcr.views.AbstractJcrBrowser;
-import org.argeo.jcr.RepositoryRegister;
-import org.argeo.jcr.ui.explorer.JcrExplorerPlugin;
-import org.argeo.jcr.ui.explorer.browser.NodeContentProvider;
-import org.argeo.jcr.ui.explorer.browser.NodeLabelProvider;
-import org.argeo.jcr.ui.explorer.browser.PropertiesContentProvider;
-import org.argeo.jcr.ui.explorer.model.SingleJcrNodeElem;
-import org.argeo.jcr.ui.explorer.utils.GenericNodeDoubleClickListener;
-import org.argeo.jcr.ui.explorer.utils.JcrUiUtils;
-import org.argeo.util.security.Keyring;
-import org.eclipse.jface.action.MenuManager;
-import org.eclipse.jface.viewers.ColumnLabelProvider;
-import org.eclipse.jface.viewers.ISelectionChangedListener;
-import org.eclipse.jface.viewers.IStructuredSelection;
-import org.eclipse.jface.viewers.ITreeContentProvider;
-import org.eclipse.jface.viewers.SelectionChangedEvent;
-import org.eclipse.jface.viewers.StructuredSelection;
-import org.eclipse.jface.viewers.TableViewer;
-import org.eclipse.jface.viewers.TableViewerColumn;
-import org.eclipse.jface.viewers.TreeViewer;
-import org.eclipse.swt.SWT;
-import org.eclipse.swt.custom.SashForm;
-import org.eclipse.swt.layout.FillLayout;
-import org.eclipse.swt.layout.GridData;
-import org.eclipse.swt.layout.GridLayout;
-import org.eclipse.swt.widgets.Composite;
-import org.eclipse.swt.widgets.Display;
-import org.eclipse.swt.widgets.Menu;
-
-/**
- * Basic View to display a sash form to browse a JCR compliant multirepository
- * environment
- */
-public class GenericJcrBrowser extends AbstractJcrBrowser {
-       public final static String ID = JcrExplorerPlugin.ID + ".browserView";
-       private boolean sortChildNodes = true;
-
-       /* DEPENDENCY INJECTION */
-       private Keyring keyring;
-       private RepositoryRegister repositoryRegister;
-       private RepositoryFactory repositoryFactory;
-       private Repository nodeRepository;
-       /**
-        * A session of the logged in user on the default workspace of the node
-        * repository.
-        */
-       private Session userSession;
-
-       // This page widgets
-       private TreeViewer nodesViewer;
-       private NodeContentProvider nodeContentProvider;
-       private TableViewer propertiesViewer;
-       private EventListener resultsObserver;
-
-       @Override
-       public void createPartControl(Composite parent) {
-               parent.setLayout(new FillLayout());
-               SashForm sashForm = new SashForm(parent, SWT.VERTICAL);
-               sashForm.setSashWidth(4);
-               sashForm.setLayout(new FillLayout());
-
-               // Create the tree on top of the view
-               Composite top = new Composite(sashForm, SWT.NONE);
-               GridLayout gl = new GridLayout(1, false);
-               top.setLayout(gl);
-
-               try {
-                       this.userSession = this.nodeRepository.login();
-               } catch (RepositoryException e) {
-                       throw new ArgeoException("Cannot open user session", e);
-               }
-
-               nodeContentProvider = new NodeContentProvider(userSession, keyring,
-                               repositoryRegister, repositoryFactory, sortChildNodes);
-
-               // nodes viewer
-               nodesViewer = createNodeViewer(top, nodeContentProvider);
-
-               // context menu : it is completely defined in the plugin.xml file.
-               MenuManager menuManager = new MenuManager();
-               Menu menu = menuManager.createContextMenu(nodesViewer.getTree());
-
-               nodesViewer.getTree().setMenu(menu);
-               getSite().registerContextMenu(menuManager, nodesViewer);
-               getSite().setSelectionProvider(nodesViewer);
-
-               nodesViewer.setInput(getViewSite());
-
-               // Create the property viewer on the bottom
-               Composite bottom = new Composite(sashForm, SWT.NONE);
-               bottom.setLayout(new GridLayout(1, false));
-               propertiesViewer = createPropertiesViewer(bottom);
-
-               sashForm.setWeights(getWeights());
-               nodesViewer.setComparer(new NodeViewerComparer());
-       }
-
-       @Override
-       public void refresh(Object obj) {
-               // Enable full refresh from a command when no element of the tree is
-               // selected
-               if (obj == null) {
-                       Object[] elements = nodeContentProvider.getElements(null);
-                       for (Object el : elements) {
-                               if (el instanceof TreeParent)
-                                       JcrUiUtils.forceRefreshIfNeeded((TreeParent) el);
-                               getNodeViewer().refresh(el);
-                       }
-               }
-               super.refresh(obj);
-       }
-
-       /**
-        * To be overridden to adapt size of form and result frames.
-        */
-       protected int[] getWeights() {
-               return new int[] { 70, 30 };
-       }
-
-       protected TreeViewer createNodeViewer(Composite parent,
-                       final ITreeContentProvider nodeContentProvider) {
-
-               final TreeViewer tmpNodeViewer = new TreeViewer(parent, SWT.MULTI);
-
-               tmpNodeViewer.getTree().setLayoutData(
-                               new GridData(SWT.FILL, SWT.FILL, true, true));
-
-               tmpNodeViewer.setContentProvider(nodeContentProvider);
-               tmpNodeViewer.setLabelProvider(new NodeLabelProvider());
-               tmpNodeViewer
-                               .addSelectionChangedListener(new ISelectionChangedListener() {
-                                       public void selectionChanged(SelectionChangedEvent event) {
-                                               if (!event.getSelection().isEmpty()) {
-                                                       IStructuredSelection sel = (IStructuredSelection) event
-                                                                       .getSelection();
-                                                       Object firstItem = sel.getFirstElement();
-                                                       if (firstItem instanceof SingleJcrNodeElem)
-                                                               propertiesViewer
-                                                                               .setInput(((SingleJcrNodeElem) firstItem)
-                                                                                               .getNode());
-                                               } else {
-                                                       propertiesViewer.setInput(getViewSite());
-                                               }
-                                       }
-                               });
-
-               resultsObserver = new TreeObserver(tmpNodeViewer.getTree().getDisplay());
-               if (keyring != null)
-                       try {
-                               ObservationManager observationManager = userSession
-                                               .getWorkspace().getObservationManager();
-                               observationManager.addEventListener(resultsObserver,
-                                               Event.PROPERTY_ADDED | Event.PROPERTY_CHANGED, "/",
-                                               true, null, null, false);
-                       } catch (RepositoryException e) {
-                               throw new ArgeoException("Cannot register listeners", e);
-                       }
-
-               tmpNodeViewer
-                               .addDoubleClickListener(new GenericNodeDoubleClickListener(
-                                               tmpNodeViewer));
-               return tmpNodeViewer;
-       }
-
-       protected TableViewer createPropertiesViewer(Composite parent) {
-               propertiesViewer = new TableViewer(parent);
-               propertiesViewer.getTable().setLayoutData(
-                               new GridData(SWT.FILL, SWT.FILL, true, true));
-               propertiesViewer.getTable().setHeaderVisible(true);
-               propertiesViewer.setContentProvider(new PropertiesContentProvider());
-               TableViewerColumn col = new TableViewerColumn(propertiesViewer,
-                               SWT.NONE);
-               col.getColumn().setText("Name");
-               col.getColumn().setWidth(200);
-               col.setLabelProvider(new ColumnLabelProvider() {
-                       public String getText(Object element) {
-                               try {
-                                       return ((Property) element).getName();
-                               } catch (RepositoryException e) {
-                                       throw new ArgeoException(
-                                                       "Unexpected exception in label provider", e);
-                               }
-                       }
-               });
-               col = new TableViewerColumn(propertiesViewer, SWT.NONE);
-               col.getColumn().setText("Value");
-               col.getColumn().setWidth(400);
-               col.setLabelProvider(new ColumnLabelProvider() {
-                       public String getText(Object element) {
-                               try {
-                                       Property property = (Property) element;
-                                       if (property.getType() == PropertyType.BINARY)
-                                               return "<binary>";
-                                       else if (property.isMultiple()) {
-                                               StringBuffer buf = new StringBuffer("[");
-                                               Value[] values = property.getValues();
-                                               for (int i = 0; i < values.length; i++) {
-                                                       if (i != 0)
-                                                               buf.append(", ");
-                                                       buf.append(values[i].getString());
-                                               }
-                                               buf.append(']');
-                                               return buf.toString();
-                                       } else
-                                               return property.getValue().getString();
-                               } catch (RepositoryException e) {
-                                       throw new ArgeoException(
-                                                       "Unexpected exception in label provider", e);
-                               }
-                       }
-               });
-               col = new TableViewerColumn(propertiesViewer, SWT.NONE);
-               col.getColumn().setText("Type");
-               col.getColumn().setWidth(200);
-               col.setLabelProvider(new ColumnLabelProvider() {
-                       public String getText(Object element) {
-                               try {
-                                       return PropertyType.nameFromValue(((Property) element)
-                                                       .getType());
-                               } catch (RepositoryException e) {
-                                       throw new ArgeoException(
-                                                       "Unexpected exception in label provider", e);
-                               }
-                       }
-               });
-               propertiesViewer.setInput(getViewSite());
-               return propertiesViewer;
-       }
-
-       @Override
-       public void dispose() {
-               super.dispose();
-       }
-
-       @Override
-       protected TreeViewer getNodeViewer() {
-               return nodesViewer;
-       }
-
-       /**
-        * Resets the tree content provider
-        * 
-        * @param sortChildNodes
-        *            if true the content provider will use a comparer to sort nodes
-        *            that might slow down the display
-        * */
-       public void setSortChildNodes(boolean sortChildNodes) {
-               this.sortChildNodes = sortChildNodes;
-               ((NodeContentProvider) nodesViewer.getContentProvider())
-                               .setSortChildren(sortChildNodes);
-               nodesViewer.setInput(getViewSite());
-       }
-
-       /** Notifies the current view that a node has been added */
-       public void nodeAdded(TreeParent parentNode) {
-               // insure that Ui objects have been correctly created:
-               JcrUiUtils.forceRefreshIfNeeded(parentNode);
-               getNodeViewer().refresh(parentNode);
-               getNodeViewer().expandToLevel(parentNode, 1);
-       }
-
-       /** Notifies the current view that a node has been removed */
-       public void nodeRemoved(TreeParent parentNode) {
-               IStructuredSelection newSel = new StructuredSelection(parentNode);
-               getNodeViewer().setSelection(newSel, true);
-               // Force refresh
-               IStructuredSelection tmpSel = (IStructuredSelection) getNodeViewer()
-                               .getSelection();
-               getNodeViewer().refresh(tmpSel.getFirstElement());
-       }
-
-       class TreeObserver extends AsyncUiEventListener {
-
-               public TreeObserver(Display display) {
-                       super(display);
-               }
-
-               @Override
-               protected Boolean willProcessInUiThread(List<Event> events)
-                               throws RepositoryException {
-                       for (Event event : events) {
-                               if (getLog().isTraceEnabled())
-                                       getLog().debug("Received event " + event);
-                               String path = event.getPath();
-                               int index = path.lastIndexOf('/');
-                               String propertyName = path.substring(index + 1);
-                               if (getLog().isTraceEnabled())
-                                       getLog().debug("Concerned property " + propertyName);
-                       }
-                       return false;
-               }
-
-               protected void onEventInUiThread(List<Event> events)
-                               throws RepositoryException {
-                       if (getLog().isTraceEnabled())
-                               getLog().trace("Refresh result list");
-                       nodesViewer.refresh();
-               }
-
-       }
-
-       public boolean getSortChildNodes() {
-               return sortChildNodes;
-       }
-
-       /* DEPENDENCY INJECTION */
-       public void setRepositoryRegister(RepositoryRegister repositoryRegister) {
-               this.repositoryRegister = repositoryRegister;
-       }
-
-       public void setKeyring(Keyring keyring) {
-               this.keyring = keyring;
-       }
-
-       public void setRepositoryFactory(RepositoryFactory repositoryFactory) {
-               this.repositoryFactory = repositoryFactory;
-       }
-
-       public void setNodeRepository(Repository nodeRepository) {
-               this.nodeRepository = nodeRepository;
-       }
-
-}
diff --git a/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/wizards/ChangeRightsWizard.java b/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/wizards/ChangeRightsWizard.java
deleted file mode 100644 (file)
index 4381837..0000000
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- * Copyright (C) 2007-2012 Argeo GmbH
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *         http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.argeo.jcr.ui.explorer.wizards;
-
-import javax.jcr.RepositoryException;
-import javax.jcr.Session;
-
-import org.argeo.ArgeoException;
-import org.argeo.jcr.JcrUtils;
-import org.eclipse.jface.wizard.Wizard;
-
-/**
- * Small wizard to manage authorizations on the root node of the current
- * workspace
- */
-public class ChangeRightsWizard extends Wizard {
-
-       private Session currentSession;
-       private String path;
-
-       // This page widget
-       private ChooseRightsPage page;
-
-       public ChangeRightsWizard(Session currentSession, String path) {
-               super();
-               this.currentSession = currentSession;
-               this.path = path;
-       }
-
-       @Override
-       public void addPages() {
-               try {
-                       page = new ChooseRightsPage(path);
-                       addPage(page);
-               } catch (Exception e) {
-                       throw new ArgeoException("Cannot add page to wizard ", e);
-               }
-       }
-
-       @Override
-       public boolean performFinish() {
-               if (!canFinish())
-                       return false;
-               try {
-                       JcrUtils.addPrivilege(currentSession, path, page.getGroupName(),
-                                       page.getAuthTypeStr());
-               } catch (RepositoryException re) {
-                       throw new ArgeoException(
-                                       "Unexpected error while setting privileges", re);
-               }
-               return true;
-       }
-}
diff --git a/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/wizards/ChooseRightsPage.java b/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/wizards/ChooseRightsPage.java
deleted file mode 100644 (file)
index 69948ce..0000000
+++ /dev/null
@@ -1,101 +0,0 @@
-/*
- * Copyright (C) 2007-2012 Argeo GmbH
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *         http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.argeo.jcr.ui.explorer.wizards;
-
-import javax.jcr.security.Privilege;
-
-import org.eclipse.jface.wizard.WizardPage;
-import org.eclipse.swt.SWT;
-import org.eclipse.swt.events.ModifyEvent;
-import org.eclipse.swt.events.ModifyListener;
-import org.eclipse.swt.layout.GridData;
-import org.eclipse.swt.layout.GridLayout;
-import org.eclipse.swt.widgets.Combo;
-import org.eclipse.swt.widgets.Composite;
-import org.eclipse.swt.widgets.Label;
-import org.eclipse.swt.widgets.Text;
-
-public class ChooseRightsPage extends WizardPage implements ModifyListener {
-
-       // This page widget
-       private Text groupNameTxt;
-       private Combo authorizationCmb;
-
-       // USABLE SHORTCUTS
-       protected final static String[] validAuthType = { Privilege.JCR_READ,
-                       Privilege.JCR_WRITE, Privilege.JCR_ALL };
-
-       public ChooseRightsPage(String path) {
-               super("Main");
-               setTitle("Add privilege to " + path);
-       }
-
-       public void createControl(Composite parent) {
-               // specify subject
-               Composite composite = new Composite(parent, SWT.NONE);
-               composite.setLayout(new GridLayout(2, false));
-               Label lbl = new Label(composite, SWT.LEAD);
-               lbl.setText("Group or user name (no blank, no special chars)");
-               lbl.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, false, false));
-               groupNameTxt = new Text(composite, SWT.LEAD | SWT.BORDER);
-               groupNameTxt.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true,
-                               false));
-               if (groupNameTxt != null)
-                       groupNameTxt.addModifyListener(this);
-
-               // Choose rigths
-               new Label(composite, SWT.NONE).setText("Choose corresponding rights");
-               authorizationCmb = new Combo(composite, SWT.BORDER | SWT.V_SCROLL);
-               authorizationCmb.setItems(validAuthType);
-               GridData gd = new GridData(GridData.FILL_HORIZONTAL);
-               authorizationCmb.setLayoutData(gd);
-
-               authorizationCmb.select(0);
-
-               // Compulsory
-               setControl(composite);
-       }
-
-       protected String getGroupName() {
-               return groupNameTxt.getText();
-       }
-
-       protected String getAuthTypeStr() {
-               return authorizationCmb.getItem(authorizationCmb.getSelectionIndex());
-       }
-
-       public void modifyText(ModifyEvent event) {
-               String message = checkComplete();
-               if (message != null)
-                       setMessage(message, WizardPage.ERROR);
-               else {
-                       setMessage("Complete", WizardPage.INFORMATION);
-                       setPageComplete(true);
-               }
-       }
-
-       /** @return error message or null if complete */
-       protected String checkComplete() {
-               String groupStr = groupNameTxt.getText();
-               if (groupStr == null || "".equals(groupStr))
-                       return "Please enter the name of the corresponding group.";
-               // Remove regexp check for the time being.
-               // else if (!match(groupStr))
-               // return
-               // "Please use only alphanumerical chars for the short technical name.";
-               return null;
-       }
-}
diff --git a/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/wizards/ImportFileSystemWizard.java b/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/wizards/ImportFileSystemWizard.java
deleted file mode 100644 (file)
index 127c2cd..0000000
+++ /dev/null
@@ -1,237 +0,0 @@
-/*
- * Copyright (C) 2007-2012 Argeo GmbH
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *         http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.argeo.jcr.ui.explorer.wizards;
-
-import java.io.File;
-import java.io.FileInputStream;
-
-import javax.jcr.Binary;
-import javax.jcr.Node;
-import javax.jcr.Property;
-import javax.jcr.nodetype.NodeType;
-
-import org.apache.commons.io.FileUtils;
-import org.apache.commons.io.IOUtils;
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.argeo.ArgeoException;
-import org.argeo.eclipse.ui.ErrorFeedback;
-import org.argeo.eclipse.ui.specific.ImportToServerWizardPage;
-import org.argeo.eclipse.ui.specific.UploadFileWizardPage;
-import org.eclipse.core.runtime.IProgressMonitor;
-import org.eclipse.jface.dialogs.MessageDialog;
-import org.eclipse.jface.operation.IRunnableWithProgress;
-import org.eclipse.jface.wizard.Wizard;
-
-public class ImportFileSystemWizard extends Wizard {
-       private final static Log log = LogFactory
-                       .getLog(ImportFileSystemWizard.class);
-
-       private UploadFileWizardPage importPage;
-       private final Node folder;
-
-       public ImportFileSystemWizard(Node folder) {
-               this.folder = folder;
-               setWindowTitle("Import from file system");
-       }
-
-       @Override
-       public void addPages() {
-               importPage = new UploadFileWizardPage();
-               addPage(importPage);
-               setNeedsProgressMonitor(importPage.getNeedsProgressMonitor());
-       }
-
-       /**
-        * Called when the user click on 'Finish' in the wizard. The real upload to
-        * the JCR repository is done here.
-        */
-       @Override
-       public boolean performFinish() {
-
-               // Initialization
-               final String objectType = importPage.getObjectType();
-               final String objectPath = importPage.getObjectPath();
-
-               // We do not display a progress bar for one file only
-               if (ImportToServerWizardPage.FILE_ITEM_TYPE.equals(objectType)) {
-                       // In Rap we must force the "real" upload of the file
-                       importPage.performFinish();
-                       try {
-                               Node fileNode = folder.addNode(importPage.getObjectName(),
-                                               NodeType.NT_FILE);
-                               Node resNode = fileNode.addNode(Property.JCR_CONTENT,
-                                               NodeType.NT_RESOURCE);
-                               Binary binary = null;
-                               try {
-                                       binary = folder.getSession().getValueFactory()
-                                                       .createBinary(importPage.getFileInputStream());
-                                       resNode.setProperty(Property.JCR_DATA, binary);
-                               } finally {
-                                       if (binary != null)
-                                               binary.dispose();
-                                       IOUtils.closeQuietly(importPage.getFileInputStream());
-                               }
-                               folder.getSession().save();
-                       } catch (Exception e) {
-                               e.printStackTrace();
-                               return false;
-                       }
-                       return true;
-               } else if (ImportToServerWizardPage.FOLDER_ITEM_TYPE.equals(objectType)) {
-                       if (objectPath == null || !new File(objectPath).exists()) {
-                               ErrorFeedback.show("Directory " + objectPath
-                                               + " does not exist");
-                               return false;
-                       }
-
-                       Boolean failed = false;
-                       final File dir = new File(objectPath).getAbsoluteFile();
-                       final Long sizeB = directorySize(dir, 0l);
-                       final Stats stats = new Stats();
-                       Long begin = System.currentTimeMillis();
-                       try {
-                               getContainer().run(true, true, new IRunnableWithProgress() {
-                                       public void run(IProgressMonitor monitor) {
-                                               try {
-                                                       Integer sizeKB = (int) (sizeB / FileUtils.ONE_KB);
-                                                       monitor.beginTask("", sizeKB);
-                                                       importDirectory(folder, dir, monitor, stats);
-                                                       monitor.done();
-                                               } catch (Exception e) {
-                                                       if (e instanceof RuntimeException)
-                                                               throw (RuntimeException) e;
-                                                       else
-                                                               throw new ArgeoException("Cannot import "
-                                                                               + objectPath, e);
-                                               }
-                                       }
-                               });
-                       } catch (Exception e) {
-                               ErrorFeedback.show("Cannot import " + objectPath, e);
-                               failed = true;
-                       }
-
-                       Long duration = System.currentTimeMillis() - begin;
-                       Long durationS = duration / 1000l;
-                       String durationStr = (durationS / 60) + " min " + (durationS % 60)
-                                       + " s";
-                       StringBuffer message = new StringBuffer("Imported\n");
-                       message.append(stats.fileCount).append(" files\n");
-                       message.append(stats.dirCount).append(" directories\n");
-                       message.append(FileUtils.byteCountToDisplaySize(stats.sizeB));
-                       if (failed)
-                               message.append(" of planned ").append(
-                                               FileUtils.byteCountToDisplaySize(sizeB));
-                       message.append("\n");
-                       message.append("in ").append(durationStr).append("\n");
-                       if (failed)
-                               MessageDialog.openError(getShell(), "Import failed",
-                                               message.toString());
-                       else
-                               MessageDialog.openInformation(getShell(), "Import successful",
-                                               message.toString());
-
-                       return true;
-               }
-               return false;
-
-       }
-
-       /** Recursively computes the size of the directory in bytes. */
-       protected Long directorySize(File dir, Long currentSize) {
-               Long size = currentSize;
-               File[] files = dir.listFiles();
-               for (File file : files) {
-                       if (file.isDirectory()) {
-                               size = directorySize(file, size);
-                       } else {
-                               size = size + file.length();
-                       }
-               }
-               return size;
-       }
-
-       /**
-        * Import recursively a directory and its content to the repository.
-        */
-       protected void importDirectory(Node folder, File dir,
-                       IProgressMonitor monitor, Stats stats) {
-               try {
-                       File[] files = dir.listFiles();
-                       for (File file : files) {
-                               if (file.isDirectory()) {
-                                       Node childFolder = folder.addNode(file.getName(),
-                                                       NodeType.NT_FOLDER);
-                                       importDirectory(childFolder, file, monitor, stats);
-                                       folder.getSession().save();
-                                       stats.dirCount++;
-                               } else {
-                                       Long fileSize = file.length();
-
-                                       // we skip tempory files that are created by apps when a
-                                       // file is being edited.
-                                       // TODO : make this configurable.
-                                       if (file.getName().lastIndexOf('~') != file.getName()
-                                                       .length() - 1) {
-
-                                               monitor.subTask(file.getName() + " ("
-                                                               + FileUtils.byteCountToDisplaySize(fileSize)
-                                                               + ") " + file.getCanonicalPath());
-                                               try {
-                                                       Node fileNode = folder.addNode(file.getName(),
-                                                                       NodeType.NT_FILE);
-                                                       Node resNode = fileNode.addNode(
-                                                                       Property.JCR_CONTENT, NodeType.NT_RESOURCE);
-                                                       Binary binary = null;
-                                                       try {
-                                                               binary = folder
-                                                                               .getSession()
-                                                                               .getValueFactory()
-                                                                               .createBinary(new FileInputStream(file));
-                                                               resNode.setProperty(Property.JCR_DATA, binary);
-                                                       } finally {
-                                                               if (binary != null)
-                                                                       binary.dispose();
-                                                       }
-                                                       folder.getSession().save();
-                                                       stats.fileCount++;
-                                                       stats.sizeB = stats.sizeB + fileSize;
-                                               } catch (Exception e) {
-                                                       log.warn("Import of "
-                                                                       + file
-                                                                       + " ("
-                                                                       + FileUtils
-                                                                                       .byteCountToDisplaySize(fileSize)
-                                                                       + ") failed: " + e);
-                                                       folder.getSession().refresh(false);
-                                               }
-                                               monitor.worked((int) (fileSize / FileUtils.ONE_KB));
-                                       }
-                               }
-                       }
-               } catch (Exception e) {
-                       throw new ArgeoException("Cannot import " + dir + " to " + folder,
-                                       e);
-               }
-       }
-
-       static class Stats {
-               public Long fileCount = 0l;
-               public Long dirCount = 0l;
-               public Long sizeB = 0l;
-       }
-}
diff --git a/org.argeo.jcr.ui.explorer/src/main/resources/org/argeo/jcr/ui/explorer/messages.properties b/org.argeo.jcr.ui.explorer/src/main/resources/org/argeo/jcr/ui/explorer/messages.properties
deleted file mode 100644 (file)
index 3023c52..0000000
+++ /dev/null
@@ -1,28 +0,0 @@
-## English labels for Agreo JCR UI application 
-
-## Generic labels 
-
-## Errors & warnings 
-errorUnvalidNtFolderNodeType= Error: folder can only be created on a Jcr Node
-warningInvalidNodeToImport=Can only import to a node
-warningInvalidMultipleSelection=This functionality is implemented only on a single node for the time being.
-warningUnversionableNode= Current node is not versionable.
-warningNoChildNode= Current node has no child.
-
-## Commands 
-getNodeSizeCmdLbl= Get approx. size
-addFolderNodeCmdLbl= Add Folder
-
-## GenericNodeEditor 
-nodeEditorLbl=Generic node editor
-genericNodePageTitle=Properties
-childNodesPageTitle=Children
-nodeRightsManagementPageTitle=Rights
-nodeVersionHistoryPageTitle=History
-
-# History 
-versionTreeSectionTitle=Version list
-versionHistorySectionTitle=History
-## Dummy ones 
-testLbl=Internationalizations of messages seems to work properly.
diff --git a/org.argeo.jcr.ui.explorer/src/org/argeo/jcr/ui/explorer/JcrExplorerConstants.java b/org.argeo.jcr.ui.explorer/src/org/argeo/jcr/ui/explorer/JcrExplorerConstants.java
new file mode 100644 (file)
index 0000000..a9cb258
--- /dev/null
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2007-2012 Argeo GmbH
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *         http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.argeo.jcr.ui.explorer;
+
+/** Constants used across the application. */
+public interface JcrExplorerConstants {
+       /*
+        * MISCEALLENEOUS
+        */
+       public final static String DATE_TIME_FORMAT = "dd/MM/yyyy, HH:mm";
+
+       public final static String PARAM_PATH = "org.argeo.jcr.ui.explorer.nodePath";
+
+}
diff --git a/org.argeo.jcr.ui.explorer/src/org/argeo/jcr/ui/explorer/JcrExplorerPerspective.java b/org.argeo.jcr.ui.explorer/src/org/argeo/jcr/ui/explorer/JcrExplorerPerspective.java
new file mode 100644 (file)
index 0000000..2626415
--- /dev/null
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2007-2012 Argeo GmbH
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *         http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.argeo.jcr.ui.explorer;
+
+import org.eclipse.ui.IFolderLayout;
+import org.eclipse.ui.IPageLayout;
+import org.eclipse.ui.IPerspectiveFactory;
+
+/** Base perspective for JcrExplorer browser */
+public class JcrExplorerPerspective implements IPerspectiveFactory {
+       public static String BROWSER_VIEW_ID = JcrExplorerPlugin.ID
+                       + ".browserView";
+
+       public void createInitialLayout(IPageLayout layout) {
+               layout.setEditorAreaVisible(true);
+
+               IFolderLayout upperLeft = layout.createFolder(JcrExplorerPlugin.ID
+                               + ".upperLeft", IPageLayout.LEFT, 0.4f, layout.getEditorArea());
+               upperLeft.addView(BROWSER_VIEW_ID);
+
+//             String editorArea = layout.getEditorArea();
+//             String logViewId = "org.argeo.security.ui.logView";
+//             IFolderLayout bottom = layout.createFolder("bottom",
+//                             IPageLayout.BOTTOM, 0.50f, editorArea);
+//             bottom.addView(logViewId);
+       }
+
+}
diff --git a/org.argeo.jcr.ui.explorer/src/org/argeo/jcr/ui/explorer/JcrExplorerPlugin.java b/org.argeo.jcr.ui.explorer/src/org/argeo/jcr/ui/explorer/JcrExplorerPlugin.java
new file mode 100644 (file)
index 0000000..3bf9e7f
--- /dev/null
@@ -0,0 +1,107 @@
+/*
+ * Copyright (C) 2007-2012 Argeo GmbH
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *         http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.argeo.jcr.ui.explorer;
+
+import java.util.ResourceBundle;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.eclipse.jface.resource.ImageDescriptor;
+import org.eclipse.ui.plugin.AbstractUIPlugin;
+import org.osgi.framework.BundleContext;
+
+/**
+ * The activator class controls the plug-in life cycle
+ */
+public class JcrExplorerPlugin extends AbstractUIPlugin {
+       private final static Log log = LogFactory.getLog(JcrExplorerPlugin.class);
+       private ResourceBundle messages;
+
+       // The plug-in ID
+       public static final String ID = "org.argeo.jcr.ui.explorer"; //$NON-NLS-1$
+
+       // The shared instance
+       private static JcrExplorerPlugin plugin;
+
+       /**
+        * The constructor
+        */
+       public JcrExplorerPlugin() {
+       }
+
+       /*
+        * (non-Javadoc)
+        * 
+        * @see
+        * org.eclipse.ui.plugin.AbstractUIPlugin#start(org.osgi.framework.BundleContext
+        * )
+        */
+       public void start(BundleContext context) throws Exception {
+               super.start(context);
+               plugin = this;
+               messages = ResourceBundle
+                               .getBundle("org.argeo.jcr.ui.explorer.messages");
+
+       }
+
+       /*
+        * (non-Javadoc)
+        * 
+        * @see
+        * org.eclipse.ui.plugin.AbstractUIPlugin#stop(org.osgi.framework.BundleContext
+        * )
+        */
+       public void stop(BundleContext context) throws Exception {
+               plugin = null;
+               super.stop(context);
+       }
+
+       /**
+        * Returns the shared instance
+        * 
+        * @return the shared instance
+        */
+       public static JcrExplorerPlugin getDefault() {
+               return plugin;
+       }
+
+       public static ImageDescriptor getImageDescriptor(String path) {
+               return imageDescriptorFromPlugin(ID, path);
+       }
+
+       /** Returns the internationalized label for the given key */
+       public static String getMessage(String key) {
+               try {
+                       return getDefault().messages.getString(key);
+               } catch (NullPointerException npe) {
+                       log.warn(key + " not found.");
+                       return key;
+               }
+       }
+
+       /**
+        * Gives access to the internationalization message bundle. Returns null in
+        * case the ClientUiPlugin is not started (for JUnit tests, by instance)
+        */
+       public static ResourceBundle getMessagesBundle() {
+               if (getDefault() != null)
+                       // To avoid NPE
+                       return getDefault().messages;
+               else
+                       return null;
+       }
+
+}
diff --git a/org.argeo.jcr.ui.explorer/src/org/argeo/jcr/ui/explorer/JcrExplorerView.java b/org.argeo.jcr.ui.explorer/src/org/argeo/jcr/ui/explorer/JcrExplorerView.java
new file mode 100644 (file)
index 0000000..01a957a
--- /dev/null
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) 2007-2012 Argeo GmbH
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *         http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.argeo.jcr.ui.explorer;
+
+import org.argeo.jcr.ui.explorer.views.GenericJcrBrowser;
+
+public class JcrExplorerView extends GenericJcrBrowser {
+
+}
diff --git a/org.argeo.jcr.ui.explorer/src/org/argeo/jcr/ui/explorer/browser/NodeContentProvider.java b/org.argeo.jcr.ui.explorer/src/org/argeo/jcr/ui/explorer/browser/NodeContentProvider.java
new file mode 100644 (file)
index 0000000..fb6bd1a
--- /dev/null
@@ -0,0 +1,197 @@
+/*
+ * Copyright (C) 2007-2012 Argeo GmbH
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *         http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.argeo.jcr.ui.explorer.browser;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Comparator;
+import java.util.List;
+
+import javax.jcr.Node;
+import javax.jcr.RepositoryException;
+import javax.jcr.RepositoryFactory;
+import javax.jcr.Session;
+import javax.jcr.nodetype.NodeType;
+
+import org.argeo.eclipse.ui.TreeParent;
+import org.argeo.jcr.ArgeoJcrConstants;
+import org.argeo.jcr.RepositoryRegister;
+import org.argeo.jcr.UserJcrUtils;
+import org.argeo.jcr.ui.explorer.model.RepositoriesElem;
+import org.argeo.jcr.ui.explorer.model.SingleJcrNodeElem;
+import org.argeo.util.security.Keyring;
+import org.eclipse.jface.viewers.ITreeContentProvider;
+import org.eclipse.jface.viewers.Viewer;
+
+/**
+ * Implementation of the {@code ITreeContentProvider} to display multiple
+ * repository environment in a tree like structure
+ * 
+ */
+public class NodeContentProvider implements ITreeContentProvider {
+       final private RepositoryRegister repositoryRegister;
+       final private RepositoryFactory repositoryFactory;
+       /**
+        * A session of the logged in user on the default workspace of the node
+        * repository.
+        */
+       final private Session userSession;
+       final private Keyring keyring;
+       private boolean sortChildren;
+
+       // reference for cleaning
+       private SingleJcrNodeElem homeNode = null;
+       private RepositoriesElem repositoriesNode = null;
+
+       // Utils
+       private TreeBrowserComparator itemComparator = new TreeBrowserComparator();
+
+       public NodeContentProvider(Session userSession, Keyring keyring,
+                       RepositoryRegister repositoryRegister,
+                       RepositoryFactory repositoryFactory, Boolean sortChildren) {
+               this.userSession = userSession;
+               this.keyring = keyring;
+               this.repositoryRegister = repositoryRegister;
+               this.repositoryFactory = repositoryFactory;
+               this.sortChildren = sortChildren;
+       }
+
+       public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
+               if (newInput == null)// dispose
+                       return;
+
+               if (userSession != null) {
+                       Node userHome = UserJcrUtils.getUserHome(userSession);
+                       if (userHome != null) {
+                               // TODO : find a way to dynamically get alias for the node
+                               if (homeNode != null)
+                                       homeNode.dispose();
+                               homeNode = new SingleJcrNodeElem(null, userHome,
+                                               userSession.getUserID(), ArgeoJcrConstants.ALIAS_NODE);
+                       }
+               }
+               if (repositoryRegister != null) {
+                       if (repositoriesNode != null)
+                               repositoriesNode.dispose();
+                       repositoriesNode = new RepositoriesElem("Repositories",
+                                       repositoryRegister, repositoryFactory, null, userSession,
+                                       keyring);
+               }
+       }
+
+       /**
+        * Sends back the first level of the Tree. Independent from inputElement
+        * that can be null
+        */
+       public Object[] getElements(Object inputElement) {
+               List<Object> objs = new ArrayList<Object>();
+               if (homeNode != null)
+                       objs.add(homeNode);
+               if (repositoriesNode != null)
+                       objs.add(repositoriesNode);
+               return objs.toArray();
+       }
+
+       public Object[] getChildren(Object parentElement) {
+               if (parentElement instanceof TreeParent) {
+                       if (sortChildren) {
+                               // TreeParent[] arr = (TreeParent[]) ((TreeParent)
+                               // parentElement)
+                               // .getChildren();
+                               Object[] tmpArr = ((TreeParent) parentElement).getChildren();
+                               TreeParent[] arr = new TreeParent[tmpArr.length];
+                               for (int i = 0; i < tmpArr.length; i++)
+                                       arr[i] = (TreeParent) tmpArr[i];
+
+                               Arrays.sort(arr, itemComparator);
+                               return arr;
+                       } else
+                               return ((TreeParent) parentElement).getChildren();
+
+               } else {
+                       return new Object[0];
+               }
+       }
+
+       /**
+        * Sets whether the content provider should order the children nodes or not.
+        * It is user duty to call a full refresh of the tree after changing this
+        * parameter.
+        */
+       public void setSortChildren(boolean sortChildren) {
+               this.sortChildren = sortChildren;
+       }
+
+       public Object getParent(Object element) {
+               if (element instanceof TreeParent) {
+                       return ((TreeParent) element).getParent();
+               } else
+                       return null;
+       }
+
+       public boolean hasChildren(Object element) {
+               if (element instanceof RepositoriesElem) {
+                       RepositoryRegister rr = ((RepositoriesElem) element)
+                                       .getRepositoryRegister();
+                       return rr.getRepositories().size() > 0;
+               } else if (element instanceof TreeParent) {
+                       TreeParent tp = (TreeParent) element;
+                       return tp.hasChildren();
+               }
+               return false;
+       }
+
+       public void dispose() {
+               if (homeNode != null)
+                       homeNode.dispose();
+               if (repositoriesNode != null) {
+                       // logs out open sessions
+                       // see https://bugzilla.argeo.org/show_bug.cgi?id=23
+                       repositoriesNode.dispose();
+               }
+       }
+
+       /**
+        * Specific comparator for this view. See spec in BUG :
+        * https://www.argeo.org/bugzilla/show_bug.cgi?id=139
+        */
+       private class TreeBrowserComparator implements Comparator<TreeParent> {
+
+               public int category(TreeParent element) {
+                       if (element instanceof SingleJcrNodeElem) {
+                               Node node = ((SingleJcrNodeElem) element).getNode();
+                               try {
+                                       if (node.isNodeType(NodeType.NT_FOLDER))
+                                               return 5;
+                               } catch (RepositoryException e) {
+                                       // TODO Auto-generated catch block
+                                       e.printStackTrace();
+                               }
+                       }
+                       return 10;
+               }
+
+               public int compare(TreeParent o1, TreeParent o2) {
+                       int cat1 = category(o1);
+                       int cat2 = category(o2);
+
+                       if (cat1 != cat2) {
+                               return cat1 - cat2;
+                       }
+                       return o1.getName().compareTo(o2.getName());
+               }
+       }
+}
\ No newline at end of file
diff --git a/org.argeo.jcr.ui.explorer/src/org/argeo/jcr/ui/explorer/browser/NodeLabelProvider.java b/org.argeo.jcr.ui.explorer/src/org/argeo/jcr/ui/explorer/browser/NodeLabelProvider.java
new file mode 100644 (file)
index 0000000..d6d593c
--- /dev/null
@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) 2007-2012 Argeo GmbH
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *         http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.argeo.jcr.ui.explorer.browser;
+
+import javax.jcr.Node;
+import javax.jcr.RepositoryException;
+import javax.jcr.nodetype.NodeType;
+
+import org.argeo.ArgeoException;
+import org.argeo.eclipse.ui.jcr.DefaultNodeLabelProvider;
+import org.argeo.eclipse.ui.jcr.JcrImages;
+import org.argeo.jcr.ui.explorer.model.RemoteRepositoryElem;
+import org.argeo.jcr.ui.explorer.model.RepositoriesElem;
+import org.argeo.jcr.ui.explorer.model.RepositoryElem;
+import org.argeo.jcr.ui.explorer.model.SingleJcrNodeElem;
+import org.argeo.jcr.ui.explorer.model.WorkspaceElem;
+import org.eclipse.swt.graphics.Image;
+
+public class NodeLabelProvider extends DefaultNodeLabelProvider {
+       // Images
+
+       public String getText(Object element) {
+               try {
+                       if (element instanceof SingleJcrNodeElem) {
+                               SingleJcrNodeElem sjn = (SingleJcrNodeElem) element;
+                               return getText(sjn.getNode());
+                       } else
+                               return super.getText(element);
+               } catch (RepositoryException e) {
+                       throw new ArgeoException(
+                                       "Unexpected JCR error while getting node name.");
+               }
+       }
+
+       protected String getText(Node node) throws RepositoryException {
+               String label = node.getName();
+               StringBuffer mixins = new StringBuffer("");
+               for (NodeType type : node.getMixinNodeTypes())
+                       mixins.append(' ').append(type.getName());
+
+               return label + " [" + node.getPrimaryNodeType().getName() + mixins
+                               + "]";
+       }
+
+       @Override
+       public Image getImage(Object element) {
+               if (element instanceof RemoteRepositoryElem) {
+                       if (((RemoteRepositoryElem) element).isConnected())
+                               return JcrImages.REMOTE_CONNECTED;
+                       else
+                               return JcrImages.REMOTE_DISCONNECTED;
+               } else if (element instanceof RepositoryElem) {
+                       if (((RepositoryElem) element).isConnected())
+                               return JcrImages.REPOSITORY_CONNECTED;
+                       else
+                               return JcrImages.REPOSITORY_DISCONNECTED;
+               } else if (element instanceof WorkspaceElem) {
+                       if (((WorkspaceElem) element).isConnected())
+                               return JcrImages.WORKSPACE_CONNECTED;
+                       else
+                               return JcrImages.WORKSPACE_DISCONNECTED;
+               } else if (element instanceof RepositoriesElem) {
+                       return JcrImages.REPOSITORIES;
+               } else if (element instanceof SingleJcrNodeElem)
+                       try {
+                               return super.getImage(((SingleJcrNodeElem) element).getNode());
+                       } catch (RepositoryException e) {
+                               return null;
+                       }
+               return super.getImage(element);
+       }
+
+}
diff --git a/org.argeo.jcr.ui.explorer/src/org/argeo/jcr/ui/explorer/browser/PropertiesContentProvider.java b/org.argeo.jcr.ui.explorer/src/org/argeo/jcr/ui/explorer/browser/PropertiesContentProvider.java
new file mode 100644 (file)
index 0000000..d39f319
--- /dev/null
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2007-2012 Argeo GmbH
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *         http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.argeo.jcr.ui.explorer.browser;
+
+import java.util.Set;
+import java.util.TreeSet;
+
+import javax.jcr.Node;
+import javax.jcr.Property;
+import javax.jcr.PropertyIterator;
+import javax.jcr.RepositoryException;
+
+import org.argeo.ArgeoException;
+import org.argeo.eclipse.ui.jcr.utils.JcrItemsComparator;
+import org.eclipse.jface.viewers.IStructuredContentProvider;
+import org.eclipse.jface.viewers.Viewer;
+
+public class PropertiesContentProvider implements IStructuredContentProvider {
+       private JcrItemsComparator itemComparator = new JcrItemsComparator();
+
+       public void dispose() {
+       }
+
+       public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
+       }
+
+       public Object[] getElements(Object inputElement) {
+               try {
+                       if (inputElement instanceof Node) {
+                               Set<Property> props = new TreeSet<Property>(itemComparator);
+                               PropertyIterator pit = ((Node) inputElement).getProperties();
+                               while (pit.hasNext())
+                                       props.add(pit.nextProperty());
+                               return props.toArray();
+                       }
+                       return new Object[] {};
+               } catch (RepositoryException e) {
+                       throw new ArgeoException("Cannot get element for " + inputElement,
+                                       e);
+               }
+       }
+
+}
diff --git a/org.argeo.jcr.ui.explorer/src/org/argeo/jcr/ui/explorer/commands/AddFolderNode.java b/org.argeo.jcr.ui.explorer/src/org/argeo/jcr/ui/explorer/commands/AddFolderNode.java
new file mode 100644 (file)
index 0000000..0389aee
--- /dev/null
@@ -0,0 +1,101 @@
+/*
+ * Copyright (C) 2007-2012 Argeo GmbH
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *         http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.argeo.jcr.ui.explorer.commands;
+
+import javax.jcr.Node;
+import javax.jcr.RepositoryException;
+import javax.jcr.nodetype.NodeType;
+
+import org.argeo.eclipse.ui.ErrorFeedback;
+import org.argeo.eclipse.ui.TreeParent;
+import org.argeo.eclipse.ui.dialogs.SingleValue;
+import org.argeo.eclipse.ui.jcr.JcrUiPlugin;
+import org.argeo.jcr.ui.explorer.JcrExplorerPlugin;
+import org.argeo.jcr.ui.explorer.model.SingleJcrNodeElem;
+import org.argeo.jcr.ui.explorer.model.WorkspaceElem;
+import org.argeo.jcr.ui.explorer.views.GenericJcrBrowser;
+import org.eclipse.core.commands.AbstractHandler;
+import org.eclipse.core.commands.ExecutionEvent;
+import org.eclipse.core.commands.ExecutionException;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.ui.handlers.HandlerUtil;
+
+/**
+ * Adds a node of type nt:folder, only on {@link SingleJcrNodeElem} and
+ * {@link WorkspaceElem} TreeObject types.
+ * 
+ * 
+ * This handler assumes that a selection provider is available and picks only
+ * first selected item. It is UI's job to enable the command only when the
+ * selection contains one and only one element. Thus no parameter is passed
+ * through the command.
+ * 
+ * This handler is still 'hard linked' to a GenericJcrBrowser view to enable
+ * correct tree refresh when a node is added. This must be corrected in future
+ * versions.
+ */
+public class AddFolderNode extends AbstractHandler {
+
+       public final static String ID = JcrExplorerPlugin.ID + ".addFolderNode";
+
+       // public final static String DEFAULT_LABEL = JcrExplorerPlugin
+       // .getMessage("addFolderNodeCmdLbl");
+       // public final static String DEFAULT_ICON_REL_PATH = "icons/addRepo.gif";
+
+       public Object execute(ExecutionEvent event) throws ExecutionException {
+
+               ISelection selection = HandlerUtil.getActiveWorkbenchWindow(event)
+                               .getActivePage().getSelection();
+
+               GenericJcrBrowser view = (GenericJcrBrowser) HandlerUtil
+                               .getActiveWorkbenchWindow(event).getActivePage()
+                               .findView(HandlerUtil.getActivePartId(event));
+
+               if (selection != null && !selection.isEmpty()
+                               && selection instanceof IStructuredSelection) {
+                       Object obj = ((IStructuredSelection) selection).getFirstElement();
+                       TreeParent treeParentNode = null;
+                       Node jcrParentNode = null;
+
+                       if (obj instanceof SingleJcrNodeElem) {
+                               treeParentNode = (TreeParent) obj;
+                               jcrParentNode = ((SingleJcrNodeElem) treeParentNode).getNode();
+                       } else if (obj instanceof WorkspaceElem) {
+                               treeParentNode = (TreeParent) obj;
+                               jcrParentNode = ((WorkspaceElem) treeParentNode).getRootNode();
+                       } else
+                               return null;
+
+                       String folderName = SingleValue.ask("Folder name",
+                                       "Enter folder name");
+                       if (folderName != null) {
+                               try {
+                                       jcrParentNode.addNode(folderName, NodeType.NT_FOLDER);
+                                       jcrParentNode.getSession().save();
+                                       view.nodeAdded(treeParentNode);
+                               } catch (RepositoryException e) {
+                                       ErrorFeedback.show("Cannot create folder " + folderName
+                                                       + " under " + treeParentNode, e);
+                               }
+                       }
+               } else {
+                       ErrorFeedback.show(JcrUiPlugin
+                                       .getMessage("errorUnvalidNtFolderNodeType"));
+               }
+               return null;
+       }
+}
diff --git a/org.argeo.jcr.ui.explorer/src/org/argeo/jcr/ui/explorer/commands/AddPrivileges.java b/org.argeo.jcr.ui.explorer/src/org/argeo/jcr/ui/explorer/commands/AddPrivileges.java
new file mode 100644 (file)
index 0000000..829290e
--- /dev/null
@@ -0,0 +1,79 @@
+/*
+ * Copyright (C) 2007-2012 Argeo GmbH
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *         http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.argeo.jcr.ui.explorer.commands;
+
+import javax.jcr.Node;
+import javax.jcr.RepositoryException;
+
+import org.argeo.ArgeoException;
+import org.argeo.eclipse.ui.ErrorFeedback;
+import org.argeo.eclipse.ui.TreeParent;
+import org.argeo.jcr.ui.explorer.JcrExplorerPlugin;
+import org.argeo.jcr.ui.explorer.model.SingleJcrNodeElem;
+import org.argeo.jcr.ui.explorer.model.WorkspaceElem;
+import org.argeo.jcr.ui.explorer.wizards.ChangeRightsWizard;
+import org.eclipse.core.commands.AbstractHandler;
+import org.eclipse.core.commands.ExecutionEvent;
+import org.eclipse.core.commands.ExecutionException;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.jface.wizard.WizardDialog;
+import org.eclipse.ui.handlers.HandlerUtil;
+
+/**
+ * Open a dialog to change rights on the selected node.
+ */
+
+public class AddPrivileges extends AbstractHandler {
+       public final static String ID = JcrExplorerPlugin.ID + ".addPrivileges";
+
+       public Object execute(ExecutionEvent event) throws ExecutionException {
+
+               ISelection selection = HandlerUtil.getActiveWorkbenchWindow(event)
+                               .getActivePage().getSelection();
+               if (selection != null && !selection.isEmpty()
+                               && selection instanceof IStructuredSelection) {
+                       Object obj = ((IStructuredSelection) selection).getFirstElement();
+                       TreeParent treeParentNode = null;
+                       Node jcrParentNode = null;
+
+                       if (obj instanceof SingleJcrNodeElem) {
+                               treeParentNode = (TreeParent) obj;
+                               jcrParentNode = ((SingleJcrNodeElem) treeParentNode).getNode();
+                       } else if (obj instanceof WorkspaceElem) {
+                               treeParentNode = (TreeParent) obj;
+                               jcrParentNode = ((WorkspaceElem) treeParentNode).getRootNode();
+                       } else
+                               return null;
+
+                       try {
+                               ChangeRightsWizard wizard = new ChangeRightsWizard(
+                                               jcrParentNode.getSession(), jcrParentNode.getPath());
+                               WizardDialog dialog = new WizardDialog(
+                                               HandlerUtil.getActiveShell(event), wizard);
+                               dialog.open();
+                               return null;
+                       } catch (RepositoryException re) {
+                               throw new ArgeoException(
+                                               "Unexpected error while creating the new workspace.",
+                                               re);
+                       }
+               } else {
+                       ErrorFeedback.show("Cannot add privileges");
+               }
+               return null;
+       }
+}
\ No newline at end of file
diff --git a/org.argeo.jcr.ui.explorer/src/org/argeo/jcr/ui/explorer/commands/AddRemoteRepository.java b/org.argeo.jcr.ui.explorer/src/org/argeo/jcr/ui/explorer/commands/AddRemoteRepository.java
new file mode 100644 (file)
index 0000000..e41edfc
--- /dev/null
@@ -0,0 +1,230 @@
+/*
+ * Copyright (C) 2007-2012 Argeo GmbH
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *         http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.argeo.jcr.ui.explorer.commands;
+
+import java.net.URI;
+import java.util.Hashtable;
+
+import javax.jcr.Node;
+import javax.jcr.Repository;
+import javax.jcr.RepositoryFactory;
+import javax.jcr.Session;
+import javax.jcr.SimpleCredentials;
+
+import org.argeo.ArgeoException;
+import org.argeo.eclipse.ui.ErrorFeedback;
+import org.argeo.eclipse.ui.utils.CommandUtils;
+import org.argeo.jcr.ArgeoJcrConstants;
+import org.argeo.jcr.ArgeoNames;
+import org.argeo.jcr.ArgeoTypes;
+import org.argeo.jcr.JcrUtils;
+import org.argeo.jcr.UserJcrUtils;
+import org.argeo.jcr.ui.explorer.JcrExplorerConstants;
+import org.argeo.util.security.Keyring;
+import org.eclipse.core.commands.AbstractHandler;
+import org.eclipse.core.commands.ExecutionEvent;
+import org.eclipse.core.commands.ExecutionException;
+import org.eclipse.jface.dialogs.Dialog;
+import org.eclipse.jface.dialogs.IMessageProvider;
+import org.eclipse.jface.dialogs.MessageDialog;
+import org.eclipse.jface.dialogs.TitleAreaDialog;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.graphics.Point;
+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.Display;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.swt.widgets.Text;
+
+/**
+ * Connect to a remote repository and, if successful publish it as an OSGi
+ * service.
+ */
+public class AddRemoteRepository extends AbstractHandler implements
+               JcrExplorerConstants, ArgeoNames {
+
+       private RepositoryFactory repositoryFactory;
+       private Repository nodeRepository;
+       private Keyring keyring;
+
+       public Object execute(ExecutionEvent event) throws ExecutionException {
+               RemoteRepositoryLoginDialog dlg = new RemoteRepositoryLoginDialog(
+                               Display.getDefault().getActiveShell());
+               if (dlg.open() == Dialog.OK) {
+                       CommandUtils.callCommand(Refresh.ID);
+               }
+               return null;
+       }
+
+       public void setRepositoryFactory(RepositoryFactory repositoryFactory) {
+               this.repositoryFactory = repositoryFactory;
+       }
+
+       public void setKeyring(Keyring keyring) {
+               this.keyring = keyring;
+       }
+
+       public void setNodeRepository(Repository nodeRepository) {
+               this.nodeRepository = nodeRepository;
+       }
+
+       class RemoteRepositoryLoginDialog extends TitleAreaDialog {
+               private Text name;
+               private Text uri;
+               private Text username;
+               private Text password;
+               private Button saveInKeyring;
+
+               public RemoteRepositoryLoginDialog(Shell parentShell) {
+                       super(parentShell);
+               }
+
+               protected Point getInitialSize() {
+                       return new Point(600, 400);
+               }
+
+               protected Control createDialogArea(Composite parent) {
+                       Composite dialogarea = (Composite) super.createDialogArea(parent);
+                       dialogarea.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true,
+                                       true));
+                       Composite composite = new Composite(dialogarea, SWT.NONE);
+                       composite.setLayout(new GridLayout(2, false));
+                       composite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true,
+                                       false));
+                       setMessage("Login to remote repository", IMessageProvider.NONE);
+                       name = createLT(composite, "Name", "remoteRepository");
+                       uri = createLT(composite, "URI",
+                                       "http://localhost:7070/data/jcr/node");
+                       username = createLT(composite, "User", "");
+                       password = createLP(composite, "Password");
+
+                       saveInKeyring = createLC(composite, "Remember password", false);
+                       parent.pack();
+                       return composite;
+               }
+
+               @Override
+               protected void createButtonsForButtonBar(Composite parent) {
+                       super.createButtonsForButtonBar(parent);
+                       Button test = createButton(parent, 2, "Test", false);
+                       test.addSelectionListener(new SelectionAdapter() {
+                               public void widgetSelected(SelectionEvent arg0) {
+                                       testConnection();
+                               }
+                       });
+               }
+
+               void testConnection() {
+                       Session session = null;
+                       try {
+                               URI checkedUri = new URI(uri.getText());
+                               String checkedUriStr = checkedUri.toString();
+
+                               Hashtable<String, String> params = new Hashtable<String, String>();
+                               params.put(ArgeoJcrConstants.JCR_REPOSITORY_URI, checkedUriStr);
+                               Repository repository = repositoryFactory.getRepository(params);
+                               if (username.getText().trim().equals("")) {// anonymous
+                                       session = repository.login();
+                               } else {
+                                       // FIXME use getTextChars() when upgrading to 3.7
+                                       // see https://bugs.eclipse.org/bugs/show_bug.cgi?id=297412
+                                       char[] pwd = password.getText().toCharArray();
+                                       SimpleCredentials sc = new SimpleCredentials(
+                                                       username.getText(), pwd);
+                                       session = repository.login(sc);
+                                       MessageDialog.openInformation(getParentShell(), "Success",
+                                                       "Connection to '" + uri.getText() + "' successful");
+                               }
+                       } catch (Exception e) {
+                               ErrorFeedback.show(
+                                               "Connection test failed for " + uri.getText(), e);
+                       } finally {
+                               JcrUtils.logoutQuietly(session);
+                       }
+               }
+
+               @Override
+               protected void okPressed() {
+                       Session nodeSession = null;
+                       try {
+                               nodeSession = nodeRepository.login();
+                               Node home = UserJcrUtils.getUserHome(nodeSession);
+
+                               Node remote = home.hasNode(ARGEO_REMOTE) ? home
+                                               .getNode(ARGEO_REMOTE) : home.addNode(ARGEO_REMOTE);
+                               if (remote.hasNode(name.getText()))
+                                       throw new ArgeoException(
+                                                       "There is already a remote repository named "
+                                                                       + name.getText());
+                               Node remoteRepository = remote.addNode(name.getText(),
+                                               ArgeoTypes.ARGEO_REMOTE_REPOSITORY);
+                               remoteRepository.setProperty(ARGEO_URI, uri.getText());
+                               remoteRepository.setProperty(ARGEO_USER_ID, username.getText());
+                               nodeSession.save();
+                               if (saveInKeyring.getSelection()) {
+                                       String pwdPath = remoteRepository.getPath() + '/'
+                                                       + ARGEO_PASSWORD;
+                                       keyring.set(pwdPath, password.getText().toCharArray());
+                               }
+                               nodeSession.save();
+                               MessageDialog.openInformation(
+                                               getParentShell(),
+                                               "Repository Added",
+                                               "Remote repository '" + username.getText() + "@"
+                                                               + uri.getText() + "' added");
+
+                               super.okPressed();
+                       } catch (Exception e) {
+                               ErrorFeedback.show("Cannot add remote repository", e);
+                       } finally {
+                               JcrUtils.logoutQuietly(nodeSession);
+                       }
+               }
+
+               /** Creates label and text. */
+               protected Text createLT(Composite parent, String label, String initial) {
+                       new Label(parent, SWT.NONE).setText(label);
+                       Text text = new Text(parent, SWT.SINGLE | SWT.LEAD | SWT.BORDER);
+                       text.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
+                       text.setText(initial);
+                       return text;
+               }
+
+               /** Creates label and check. */
+               protected Button createLC(Composite parent, String label,
+                               Boolean initial) {
+                       new Label(parent, SWT.NONE).setText(label);
+                       Button check = new Button(parent, SWT.CHECK);
+                       check.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
+                       check.setSelection(initial);
+                       return check;
+               }
+
+               protected Text createLP(Composite parent, String label) {
+                       new Label(parent, SWT.NONE).setText(label);
+                       Text text = new Text(parent, SWT.SINGLE | SWT.LEAD | SWT.BORDER
+                                       | SWT.PASSWORD);
+                       text.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
+                       return text;
+               }
+       }
+}
diff --git a/org.argeo.jcr.ui.explorer/src/org/argeo/jcr/ui/explorer/commands/CreateWorkspace.java b/org.argeo.jcr.ui.explorer/src/org/argeo/jcr/ui/explorer/commands/CreateWorkspace.java
new file mode 100644 (file)
index 0000000..e579630
--- /dev/null
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2007-2012 Argeo GmbH
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *         http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.argeo.jcr.ui.explorer.commands;
+
+import java.util.Arrays;
+
+import org.argeo.eclipse.ui.ErrorFeedback;
+import org.argeo.eclipse.ui.dialogs.SingleValue;
+import org.argeo.jcr.ui.explorer.JcrExplorerPlugin;
+import org.argeo.jcr.ui.explorer.model.RepositoryElem;
+import org.argeo.jcr.ui.explorer.views.GenericJcrBrowser;
+import org.eclipse.core.commands.AbstractHandler;
+import org.eclipse.core.commands.ExecutionEvent;
+import org.eclipse.core.commands.ExecutionException;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.ui.handlers.HandlerUtil;
+
+/** Creates a new JCR workspace */
+public class CreateWorkspace extends AbstractHandler {
+
+       public final static String ID = JcrExplorerPlugin.ID + ".addFolderNode";
+
+       public Object execute(ExecutionEvent event) throws ExecutionException {
+
+               ISelection selection = HandlerUtil.getActiveWorkbenchWindow(event)
+                               .getActivePage().getSelection();
+
+               GenericJcrBrowser view = (GenericJcrBrowser) HandlerUtil
+                               .getActiveWorkbenchWindow(event).getActivePage()
+                               .findView(HandlerUtil.getActivePartId(event));
+
+               if (selection != null && !selection.isEmpty()
+                               && selection instanceof IStructuredSelection) {
+                       Object obj = ((IStructuredSelection) selection).getFirstElement();
+                       if (!(obj instanceof RepositoryElem))
+                               return null;
+
+                       RepositoryElem repositoryNode = (RepositoryElem) obj;
+                       String workspaceName = SingleValue.ask("Workspace name",
+                                       "Enter workspace name");
+                       if (workspaceName != null) {
+                               if (Arrays.asList(repositoryNode.getAccessibleWorkspaceNames())
+                                               .contains(workspaceName)) {
+                                       ErrorFeedback.show("Workspace " + workspaceName
+                                                       + " already exists.");
+                               } else {
+                                       repositoryNode.createWorkspace(workspaceName);
+                                       view.nodeAdded(repositoryNode);
+                               }
+                       }
+               } else {
+                       ErrorFeedback.show("Cannot create workspace");
+               }
+               return null;
+       }
+}
diff --git a/org.argeo.jcr.ui.explorer/src/org/argeo/jcr/ui/explorer/commands/DeleteNodes.java b/org.argeo.jcr.ui.explorer/src/org/argeo/jcr/ui/explorer/commands/DeleteNodes.java
new file mode 100644 (file)
index 0000000..26d4cdd
--- /dev/null
@@ -0,0 +1,118 @@
+/*
+ * Copyright (C) 2007-2012 Argeo GmbH
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *         http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.argeo.jcr.ui.explorer.commands;
+
+import java.util.Iterator;
+
+import javax.jcr.Node;
+import javax.jcr.RepositoryException;
+
+import org.argeo.ArgeoException;
+import org.argeo.eclipse.ui.ErrorFeedback;
+import org.argeo.eclipse.ui.TreeParent;
+import org.argeo.jcr.ui.explorer.model.SingleJcrNodeElem;
+import org.argeo.jcr.ui.explorer.model.WorkspaceElem;
+import org.argeo.jcr.ui.explorer.views.GenericJcrBrowser;
+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.jface.viewers.IStructuredSelection;
+import org.eclipse.ui.handlers.HandlerUtil;
+
+/**
+ * Deletes the selected nodes: both in the JCR repository and in the UI view.
+ * Warning no check is done, except implementation dependent native checks,
+ * handle with care.
+ * 
+ * This handler is still 'hard linked' to a GenericJcrBrowser view to enable
+ * correct tree refresh when a node is added. This must be corrected in future
+ * versions.
+ */
+public class DeleteNodes extends AbstractHandler {
+       public Object execute(ExecutionEvent event) throws ExecutionException {
+               ISelection selection = HandlerUtil.getActiveWorkbenchWindow(event)
+                               .getActivePage().getSelection();
+               if (selection == null || !(selection instanceof IStructuredSelection))
+                       return null;
+
+               GenericJcrBrowser view = (GenericJcrBrowser) HandlerUtil
+                               .getActiveWorkbenchWindow(event).getActivePage()
+                               .findView(HandlerUtil.getActivePartId(event));
+
+               // confirmation
+               StringBuffer buf = new StringBuffer("");
+               Iterator<?> lst = ((IStructuredSelection) selection).iterator();
+               while (lst.hasNext()) {
+                       SingleJcrNodeElem sjn = ((SingleJcrNodeElem) lst.next());
+                       buf.append(sjn.getName()).append(' ');
+               }
+               Boolean ok = MessageDialog.openConfirm(
+                               HandlerUtil.getActiveShell(event), "Confirm deletion",
+                               "Do you want to delete " + buf + "?");
+
+               // operation
+               if (ok) {
+                       Iterator<?> it = ((IStructuredSelection) selection).iterator();
+                       Object obj = null;
+                       SingleJcrNodeElem ancestor = null;
+                       WorkspaceElem rootAncestor = null;
+                       try {
+                               while (it.hasNext()) {
+                                       obj = it.next();
+                                       if (obj instanceof SingleJcrNodeElem) {
+                                               // Cache objects
+                                               SingleJcrNodeElem sjn = (SingleJcrNodeElem) obj;
+                                               TreeParent tp = (TreeParent) sjn.getParent();
+                                               Node node = sjn.getNode();
+
+                                               // Jcr Remove
+                                               node.remove();
+                                               node.getSession().save();
+                                               // UI remove
+                                               tp.removeChild(sjn);
+
+                                               // Check if the parent is the root node
+                                               if (tp instanceof WorkspaceElem)
+                                                       rootAncestor = (WorkspaceElem) tp;
+                                               else
+                                                       ancestor = getOlder(ancestor, (SingleJcrNodeElem) tp);
+                                       }
+                               }
+                               if (rootAncestor != null)
+                                       view.nodeRemoved(rootAncestor);
+                               else if (ancestor != null)
+                                       view.nodeRemoved(ancestor);
+                       } catch (Exception e) {
+                               ErrorFeedback.show("Cannot delete selected node ", e);
+                       }
+               }
+               return null;
+       }
+
+       private SingleJcrNodeElem getOlder(SingleJcrNodeElem A, SingleJcrNodeElem B) {
+               try {
+                       if (A == null)
+                               return B == null ? null : B;
+                       // Todo enhanced this method
+                       else
+                               return A.getNode().getDepth() <= B.getNode().getDepth() ? A : B;
+               } catch (RepositoryException re) {
+                       throw new ArgeoException("Cannot find ancestor", re);
+               }
+       }
+}
diff --git a/org.argeo.jcr.ui.explorer/src/org/argeo/jcr/ui/explorer/commands/DumpNode.java b/org.argeo.jcr.ui.explorer/src/org/argeo/jcr/ui/explorer/commands/DumpNode.java
new file mode 100644 (file)
index 0000000..c8a235d
--- /dev/null
@@ -0,0 +1,110 @@
+/*
+ * Copyright (C) 2007-2012 Argeo GmbH
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *         http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.argeo.jcr.ui.explorer.commands;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.text.DateFormat;
+import java.text.SimpleDateFormat;
+import java.util.GregorianCalendar;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+
+import javax.jcr.Node;
+import javax.jcr.RepositoryException;
+
+import org.argeo.ArgeoException;
+import org.argeo.eclipse.ui.specific.OpenFile;
+import org.argeo.eclipse.ui.utils.CommandUtils;
+import org.argeo.jcr.JcrUtils;
+import org.argeo.jcr.ui.explorer.JcrExplorerPlugin;
+import org.argeo.jcr.ui.explorer.model.SingleJcrNodeElem;
+import org.eclipse.core.commands.AbstractHandler;
+import org.eclipse.core.commands.ExecutionEvent;
+import org.eclipse.core.commands.ExecutionException;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.ui.handlers.HandlerUtil;
+
+/**
+ * If the method
+ * <code> HandlerUtil.getActiveWorkbenchWindow(event).getActivePage().getSelection() </code>
+ * exits and has a SingleJcrNodeElem as first element, it canonically calls the
+ * JCR Session.exportSystemView() method on the underlying node with both
+ * skipBinary & noRecurse boolean flags set to false.
+ * 
+ * Resulting stream is saved in a tmp file and opened via the "open file"
+ * single-sourced command.
+ */
+public class DumpNode extends AbstractHandler {
+       public final static String ID = JcrExplorerPlugin.ID + ".dumpNode";
+
+       private final static DateFormat df = new SimpleDateFormat(
+                       "yyyy-MM-dd_HH-mm");
+
+       public Object execute(ExecutionEvent event) throws ExecutionException {
+               ISelection selection = HandlerUtil.getActiveWorkbenchWindow(event)
+                               .getActivePage().getSelection();
+               if (selection == null || !(selection instanceof IStructuredSelection))
+                       return null;
+
+               Iterator<?> lst = ((IStructuredSelection) selection).iterator();
+               if (lst.hasNext()) {
+                       Object element = lst.next();
+                       if (element instanceof SingleJcrNodeElem) {
+                               SingleJcrNodeElem sjn = (SingleJcrNodeElem) element;
+                               Node node = sjn.getNode();
+
+                               // TODO add a dialog to configure the export and ask for
+                               // confirmation
+                               // Boolean ok = MessageDialog.openConfirm(
+                               // HandlerUtil.getActiveShell(event), "Confirm deletion",
+                               // "Do you want to delete " + buf + "?");
+
+                               File tmpFile;
+                               FileOutputStream fos;
+                               try {
+                                       tmpFile = File.createTempFile("JcrExport", ".xml");
+                                       tmpFile.deleteOnExit();
+                                       fos = new FileOutputStream(tmpFile);
+                                       String dateVal = df.format(new GregorianCalendar()
+                                                       .getTime());
+                                       node.getSession().exportSystemView(node.getPath(), fos,
+                                                       true, false);
+                                       openGeneratedFile(tmpFile.getAbsolutePath(),
+                                                       "Dump-" + JcrUtils.replaceInvalidChars(node.getName())+ "-" + dateVal + ".xml");
+                               } catch (RepositoryException e) {
+                                       throw new ArgeoException(
+                                                       "Unable to perform SystemExport on " + node, e);
+                               } catch (IOException e) {
+                                       throw new ArgeoException("Unable to SystemExport " + node,
+                                                       e);
+                               }
+                       }
+               }
+               return null;
+       }
+
+       private synchronized void openGeneratedFile(String path, String fileName) {
+               Map<String, String> params = new HashMap<String, String>();
+               params.put(OpenFile.PARAM_FILE_NAME, fileName);
+               params.put(OpenFile.PARAM_FILE_URI, "file://" + path);
+               CommandUtils.callCommand("org.argeo.security.ui.specific.openFile",
+                               params);
+       }
+}
diff --git a/org.argeo.jcr.ui.explorer/src/org/argeo/jcr/ui/explorer/commands/EditNode.java b/org.argeo.jcr.ui.explorer/src/org/argeo/jcr/ui/explorer/commands/EditNode.java
new file mode 100644 (file)
index 0000000..e98973e
--- /dev/null
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2007-2012 Argeo GmbH
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *         http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.argeo.jcr.ui.explorer.commands;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.jcr.Property;
+import javax.jcr.nodetype.NodeType;
+
+import org.argeo.eclipse.ui.ErrorFeedback;
+import org.argeo.eclipse.ui.jcr.editors.NodeEditorInput;
+import org.eclipse.core.commands.AbstractHandler;
+import org.eclipse.core.commands.ExecutionEvent;
+import org.eclipse.core.commands.ExecutionException;
+import org.eclipse.ui.PartInitException;
+import org.eclipse.ui.handlers.HandlerUtil;
+
+/** Generic command to open a path in an editor. */
+public class EditNode extends AbstractHandler {
+       public final static String EDITOR_PARAM = "editor";
+
+       private String defaultEditorId;
+
+       private Map<String, String> nodeTypeToEditor = new HashMap<String, String>();
+
+       public Object execute(ExecutionEvent event) throws ExecutionException {
+               String path = event.getParameter(Property.JCR_PATH);
+
+               String type = event.getParameter(NodeType.NT_NODE_TYPE);
+               if (type == null)
+                       type = NodeType.NT_UNSTRUCTURED;
+
+               String editorId = event.getParameter(NodeType.NT_NODE_TYPE);
+               if (editorId == null)
+                       editorId = nodeTypeToEditor.containsKey(type) ? nodeTypeToEditor
+                                       .get(type) : defaultEditorId;
+                                       
+               NodeEditorInput nei = new NodeEditorInput(path);
+
+               try {
+                       HandlerUtil.getActiveWorkbenchWindow(event).getActivePage()
+                                       .openEditor(nei, editorId);
+               } catch (PartInitException e) {
+                       ErrorFeedback.show("Cannot open " + editorId + " with " + path
+                                       + " of type " + type, e);
+               }
+               // TODO Auto-generated method stub
+               return null;
+       }
+
+       public void setDefaultEditorId(String defaultEditorId) {
+               this.defaultEditorId = defaultEditorId;
+       }
+
+}
diff --git a/org.argeo.jcr.ui.explorer/src/org/argeo/jcr/ui/explorer/commands/GetNodeSize.java b/org.argeo.jcr.ui.explorer/src/org/argeo/jcr/ui/explorer/commands/GetNodeSize.java
new file mode 100644 (file)
index 0000000..cfcac13
--- /dev/null
@@ -0,0 +1,113 @@
+/*
+ * Copyright (C) 2007-2012 Argeo GmbH
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *         http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.argeo.jcr.ui.explorer.commands;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import javax.jcr.Node;
+
+import org.argeo.eclipse.ui.ErrorFeedback;
+import org.argeo.jcr.JcrUtils;
+import org.argeo.jcr.ui.explorer.JcrExplorerPlugin;
+import org.argeo.jcr.ui.explorer.model.SingleJcrNodeElem;
+import org.argeo.jcr.ui.explorer.model.WorkspaceElem;
+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.jface.viewers.IStructuredSelection;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.ui.handlers.HandlerUtil;
+
+/** Opens the generic node editor. */
+public class GetNodeSize extends AbstractHandler {
+       // private final static Log log = LogFactory.getLog(GetNodeSize.class);
+
+       public final static String ID = JcrExplorerPlugin.ID + ".getNodeSize";
+
+       // public final static String DEFAULT_ICON_REL_PATH = "icons/getSize.gif";
+       // public final static String DEFAULT_LABEL = JcrExplorerPlugin
+       // .getMessage("getNodeSizeCmdLbl");
+
+       public Object execute(ExecutionEvent event) throws ExecutionException {
+               // JcrUtils.getRepositoryByAlias(repositoryRegister,
+               // ArgeoJcrConstants.ALIAS_NODE);
+
+               ISelection selection = HandlerUtil.getActiveWorkbenchWindow(event)
+                               .getActivePage().getSelection();
+
+               if (selection != null && !selection.isEmpty()
+                               && selection instanceof IStructuredSelection) {
+
+                       // IStructuredSelection iss = (IStructuredSelection) selection;
+                       // if (iss.size() > 1)
+                       // ErrorFeedback.show(JcrExplorerPlugin
+                       // .getMessage("warningInvalidMultipleSelection"), null);
+
+                       long size = 0;
+
+                       Iterator<?> it = ((IStructuredSelection) selection).iterator();
+
+                       // as the size method is recursive, we keep track of nodes for which
+                       // we already have computed size so that we don't count them twice.
+                       // In a first approximation, we assume that the structure selection
+                       // keep the nodes ordered.
+                       // TODO : enhance that.
+                       List<String> importedPathes = new ArrayList<String>();
+                       try {
+                               nodesIt: while (it.hasNext()) {
+                                       Object obj = it.next();
+                                       String curPath;
+                                       Node node;
+                                       if (obj instanceof SingleJcrNodeElem) {
+                                               node = ((SingleJcrNodeElem) obj).getNode();
+                                               curPath = node.getSession().getWorkspace().getName();
+                                               curPath += "/" + node.getPath();
+                                       } else if (obj instanceof WorkspaceElem) {
+                                               node = ((WorkspaceElem) obj).getRootNode();
+                                               curPath = node.getSession().getWorkspace().getName();
+                                       } else
+                                               // unvalid object type
+                                               continue nodesIt;
+
+                                       Iterator<String> itPath = importedPathes.iterator();
+                                       while (itPath.hasNext()) {
+                                               String refPath = itPath.next();
+                                               if (curPath.startsWith(refPath))
+                                                       // Already done : skip node
+                                                       continue nodesIt;
+                                       }
+                                       size += JcrUtils.getNodeApproxSize(node);
+                                       importedPathes.add(curPath);
+                               }
+                       } catch (Exception e) {
+                               ErrorFeedback.show("Cannot Get size of selected node ", e);
+                       }
+
+                       String[] labels = { "OK" };
+                       Shell shell = HandlerUtil.getActiveWorkbenchWindow(event)
+                                       .getShell();
+                       MessageDialog md = new MessageDialog(shell, "Node size", null,
+                                       "Node size is: " + size / 1024 + " KB",
+                                       MessageDialog.INFORMATION, labels, 0);
+                       md.open();
+               }
+               return null;
+       }
+}
diff --git a/org.argeo.jcr.ui.explorer/src/org/argeo/jcr/ui/explorer/commands/ImportFileSystem.java b/org.argeo.jcr.ui.explorer/src/org/argeo/jcr/ui/explorer/commands/ImportFileSystem.java
new file mode 100644 (file)
index 0000000..5c4bf7e
--- /dev/null
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2007-2012 Argeo GmbH
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *         http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.argeo.jcr.ui.explorer.commands;
+
+import javax.jcr.Node;
+
+import org.argeo.eclipse.ui.ErrorFeedback;
+import org.argeo.eclipse.ui.TreeParent;
+import org.argeo.jcr.ui.explorer.JcrExplorerPlugin;
+import org.argeo.jcr.ui.explorer.model.SingleJcrNodeElem;
+import org.argeo.jcr.ui.explorer.model.WorkspaceElem;
+import org.argeo.jcr.ui.explorer.views.GenericJcrBrowser;
+import org.argeo.jcr.ui.explorer.wizards.ImportFileSystemWizard;
+import org.eclipse.core.commands.AbstractHandler;
+import org.eclipse.core.commands.ExecutionEvent;
+import org.eclipse.core.commands.ExecutionException;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.jface.wizard.WizardDialog;
+import org.eclipse.ui.handlers.HandlerUtil;
+
+/** Import a local file system directory tree. */
+public class ImportFileSystem extends AbstractHandler {
+       public Object execute(ExecutionEvent event) throws ExecutionException {
+               ISelection selection = HandlerUtil.getActiveWorkbenchWindow(event)
+                               .getActivePage().getSelection();
+               GenericJcrBrowser view = (GenericJcrBrowser) HandlerUtil
+                               .getActiveWorkbenchWindow(event).getActivePage()
+                               .findView(HandlerUtil.getActivePartId(event));
+               if (selection != null && !selection.isEmpty()
+                               && selection instanceof IStructuredSelection) {
+                       Object obj = ((IStructuredSelection) selection).getFirstElement();
+                       try {
+                               Node folder = null;
+                               if (obj instanceof SingleJcrNodeElem) {
+                                       folder = ((SingleJcrNodeElem) obj).getNode();
+                               } else if (obj instanceof WorkspaceElem) {
+                                       folder = ((WorkspaceElem) obj).getRootNode();
+                               } else {
+                                       ErrorFeedback.show(JcrExplorerPlugin
+                                                       .getMessage("warningInvalidNodeToImport"));
+                               }
+                               if (folder != null) {
+                                       ImportFileSystemWizard wizard = new ImportFileSystemWizard(
+                                                       folder);
+                                       WizardDialog dialog = new WizardDialog(
+                                                       HandlerUtil.getActiveShell(event), wizard);
+                                       dialog.open();
+                                       view.nodeAdded((TreeParent) obj);
+                               }
+                       } catch (Exception e) {
+                               ErrorFeedback.show("Cannot import files to " + obj, e);
+                       }
+               }
+               return null;
+       }
+}
diff --git a/org.argeo.jcr.ui.explorer/src/org/argeo/jcr/ui/explorer/commands/OpenGenericNodeEditor.java b/org.argeo.jcr.ui.explorer/src/org/argeo/jcr/ui/explorer/commands/OpenGenericNodeEditor.java
new file mode 100644 (file)
index 0000000..6799d17
--- /dev/null
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2007-2012 Argeo GmbH
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *         http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.argeo.jcr.ui.explorer.commands;
+
+import org.argeo.ArgeoException;
+import org.argeo.eclipse.ui.jcr.editors.NodeEditorInput;
+import org.argeo.jcr.ui.explorer.JcrExplorerConstants;
+import org.argeo.jcr.ui.explorer.JcrExplorerPlugin;
+import org.argeo.jcr.ui.explorer.editors.GenericNodeEditor;
+import org.eclipse.core.commands.AbstractHandler;
+import org.eclipse.core.commands.ExecutionEvent;
+import org.eclipse.core.commands.ExecutionException;
+import org.eclipse.ui.handlers.HandlerUtil;
+
+/** Opens the generic node editor. */
+public class OpenGenericNodeEditor extends AbstractHandler {
+       public final static String ID = JcrExplorerPlugin.ID + ".openGenericNodeEditor";
+
+       public Object execute(ExecutionEvent event) throws ExecutionException {
+               String path = event.getParameter(JcrExplorerConstants.PARAM_PATH);
+               try {
+                       NodeEditorInput nei = new NodeEditorInput(path);
+                       HandlerUtil.getActiveWorkbenchWindow(event).getActivePage()
+                                       .openEditor(nei, GenericNodeEditor.ID);
+               } catch (Exception e) {
+                       throw new ArgeoException("Cannot open editor", e);
+               }
+               return null;
+       }
+
+}
diff --git a/org.argeo.jcr.ui.explorer/src/org/argeo/jcr/ui/explorer/commands/Refresh.java b/org.argeo.jcr.ui.explorer/src/org/argeo/jcr/ui/explorer/commands/Refresh.java
new file mode 100644 (file)
index 0000000..21ce256
--- /dev/null
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2007-2012 Argeo GmbH
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *         http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.argeo.jcr.ui.explorer.commands;
+
+import java.util.Iterator;
+
+import org.argeo.eclipse.ui.TreeParent;
+import org.argeo.eclipse.ui.jcr.views.AbstractJcrBrowser;
+import org.argeo.jcr.ui.explorer.JcrExplorerPlugin;
+import org.argeo.jcr.ui.explorer.utils.JcrUiUtils;
+import org.argeo.jcr.ui.explorer.views.GenericJcrBrowser;
+import org.eclipse.core.commands.AbstractHandler;
+import org.eclipse.core.commands.ExecutionEvent;
+import org.eclipse.core.commands.ExecutionException;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.IStructuredSelection;
+
+/**
+ * Force the selected objects of the active view to be refreshed doing the
+ * following:
+ * <ol>
+ * <li>The model objects are recomputed</li>
+ * <li>the view is refreshed</li>
+ * </ol>
+ */
+public class Refresh extends AbstractHandler {
+
+       public final static String ID = JcrExplorerPlugin.ID + ".refresh";
+
+       public Object execute(ExecutionEvent event) throws ExecutionException {
+
+               AbstractJcrBrowser view = (AbstractJcrBrowser) JcrExplorerPlugin
+                               .getDefault().getWorkbench().getActiveWorkbenchWindow()
+                               .getActivePage().getActivePart();//
+
+               ISelection selection = JcrExplorerPlugin.getDefault().getWorkbench()
+                               .getActiveWorkbenchWindow().getActivePage().getSelection();
+
+               if (selection != null && selection instanceof IStructuredSelection
+                               && !selection.isEmpty()) {
+                       Iterator<?> it = ((IStructuredSelection) selection).iterator();
+                       while (it.hasNext()) {
+                               Object obj = it.next();
+                               if (obj instanceof TreeParent) {
+                                       TreeParent tp = (TreeParent) obj;
+                                       JcrUiUtils.forceRefreshIfNeeded(tp);
+                                       view.refresh(obj);
+                               }
+                       }
+               } else if (view instanceof GenericJcrBrowser)
+                       ((GenericJcrBrowser) view).refresh(null); // force full refresh
+
+               return null;
+       }
+}
diff --git a/org.argeo.jcr.ui.explorer/src/org/argeo/jcr/ui/explorer/commands/RemoveRemoteRepository.java b/org.argeo.jcr.ui.explorer/src/org/argeo/jcr/ui/explorer/commands/RemoveRemoteRepository.java
new file mode 100644 (file)
index 0000000..ec23dd0
--- /dev/null
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2007-2012 Argeo GmbH
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *         http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.argeo.jcr.ui.explorer.commands;
+
+import org.argeo.jcr.ui.explorer.model.RemoteRepositoryElem;
+import org.argeo.jcr.ui.explorer.views.GenericJcrBrowser;
+import org.eclipse.core.commands.AbstractHandler;
+import org.eclipse.core.commands.ExecutionEvent;
+import org.eclipse.core.commands.ExecutionException;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.ui.handlers.HandlerUtil;
+
+/** Remove a registered remote repository */
+public class RemoveRemoteRepository extends AbstractHandler {
+
+       public Object execute(ExecutionEvent event) throws ExecutionException {
+
+               ISelection selection = HandlerUtil.getActiveWorkbenchWindow(event)
+                               .getActivePage().getSelection();
+
+               GenericJcrBrowser view = (GenericJcrBrowser) HandlerUtil
+                               .getActiveWorkbenchWindow(event).getActivePage()
+                               .findView(HandlerUtil.getActivePartId(event));
+
+               if (selection != null && !selection.isEmpty()
+                               && selection instanceof IStructuredSelection) {
+                       Object obj = ((IStructuredSelection) selection).getFirstElement();
+
+                       if (obj instanceof RemoteRepositoryElem) {
+                               ((RemoteRepositoryElem) obj).remove();
+                               view.refresh(null);
+                       }
+               }
+               return null;
+       }
+
+}
diff --git a/org.argeo.jcr.ui.explorer/src/org/argeo/jcr/ui/explorer/commands/SortChildNodes.java b/org.argeo.jcr.ui.explorer/src/org/argeo/jcr/ui/explorer/commands/SortChildNodes.java
new file mode 100644 (file)
index 0000000..2961529
--- /dev/null
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2007-2012 Argeo GmbH
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *         http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.argeo.jcr.ui.explorer.commands;
+
+import org.argeo.jcr.ui.explorer.JcrExplorerPlugin;
+import org.argeo.jcr.ui.explorer.views.GenericJcrBrowser;
+import org.eclipse.core.commands.AbstractHandler;
+import org.eclipse.core.commands.Command;
+import org.eclipse.core.commands.ExecutionEvent;
+import org.eclipse.core.commands.ExecutionException;
+import org.eclipse.core.commands.State;
+import org.eclipse.ui.PlatformUI;
+import org.eclipse.ui.commands.ICommandService;
+import org.eclipse.ui.handlers.HandlerUtil;
+
+/**
+ * Change isSorted state of the JcrExplorer Browser
+ */
+public class SortChildNodes extends AbstractHandler {
+       public final static String ID = JcrExplorerPlugin.ID + ".sortChildNodes";
+
+       public Object execute(ExecutionEvent event) throws ExecutionException {
+               GenericJcrBrowser view = (GenericJcrBrowser) HandlerUtil
+                               .getActiveWorkbenchWindow(event).getActivePage()
+                               .findView(GenericJcrBrowser.ID);
+
+               ICommandService service = (ICommandService) PlatformUI.getWorkbench()
+                               .getService(ICommandService.class);
+               Command command = service.getCommand(ID);
+               State state = command.getState(ID + ".toggleState");
+
+               boolean wasSorted = (Boolean) state.getValue();
+               view.setSortChildNodes(!wasSorted);
+               state.setValue(!wasSorted);
+               return null;
+       }
+}
diff --git a/org.argeo.jcr.ui.explorer/src/org/argeo/jcr/ui/explorer/dialogs/ChooseNameDialog.java b/org.argeo.jcr.ui.explorer/src/org/argeo/jcr/ui/explorer/dialogs/ChooseNameDialog.java
new file mode 100644 (file)
index 0000000..d4a5cc7
--- /dev/null
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2007-2012 Argeo GmbH
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *         http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.argeo.jcr.ui.explorer.dialogs;
+
+import org.eclipse.jface.dialogs.IMessageProvider;
+import org.eclipse.jface.dialogs.TitleAreaDialog;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.swt.widgets.Text;
+
+/** Dialog to change the current user password */
+public class ChooseNameDialog extends TitleAreaDialog {
+       private Text nameT;
+
+       public ChooseNameDialog(Shell parentShell) {
+               super(parentShell);
+               setTitle("Choose name");
+       }
+
+       protected Point getInitialSize() {
+               return new Point(300, 250);
+       }
+
+       protected Control createDialogArea(Composite parent) {
+               Composite dialogarea = (Composite) super.createDialogArea(parent);
+               dialogarea.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
+               Composite composite = new Composite(dialogarea, SWT.NONE);
+               composite.setLayout(new GridLayout(2, false));
+               composite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
+               nameT = createLT(composite, "Name");
+
+               setMessage("Choose name", IMessageProvider.INFORMATION);
+               parent.pack();
+               return composite;
+       }
+
+       /** Creates label and text. */
+       protected Text createLT(Composite parent, String label) {
+               new Label(parent, SWT.NONE).setText(label);
+               Text text = new Text(parent, SWT.SINGLE | SWT.LEAD | SWT.BORDER);
+               text.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
+               return text;
+       }
+
+       public String getName() {
+               return nameT.getText();
+       }
+}
diff --git a/org.argeo.jcr.ui.explorer/src/org/argeo/jcr/ui/explorer/editors/ChildNodesPage.java b/org.argeo.jcr.ui.explorer/src/org/argeo/jcr/ui/explorer/editors/ChildNodesPage.java
new file mode 100644 (file)
index 0000000..682254a
--- /dev/null
@@ -0,0 +1,93 @@
+/*
+ * Copyright (C) 2007-2012 Argeo GmbH
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *         http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.argeo.jcr.ui.explorer.editors;
+
+import javax.jcr.Node;
+
+import org.argeo.ArgeoException;
+import org.argeo.jcr.ui.explorer.JcrExplorerPlugin;
+import org.argeo.jcr.ui.explorer.browser.NodeLabelProvider;
+import org.argeo.jcr.ui.explorer.providers.SingleNodeAsTreeContentProvider;
+import org.argeo.jcr.ui.explorer.utils.GenericNodeDoubleClickListener;
+import org.eclipse.jface.viewers.ITreeContentProvider;
+import org.eclipse.jface.viewers.TreeViewer;
+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.ui.forms.IManagedForm;
+import org.eclipse.ui.forms.editor.FormEditor;
+import org.eclipse.ui.forms.editor.FormPage;
+import org.eclipse.ui.forms.widgets.ScrolledForm;
+
+/**
+ * List all childs of the current node and brings some browsing capabilities
+ * accross the repository
+ */
+public class ChildNodesPage extends FormPage {
+       // private final static Log log = LogFactory.getLog(ChildNodesPage.class);
+
+       // business objects
+       private Node currentNode;
+
+       // this page UI components
+       private SingleNodeAsTreeContentProvider nodeContentProvider;
+       private TreeViewer nodesViewer;
+
+       public ChildNodesPage(FormEditor editor, String title, Node currentNode) {
+               super(editor, "ChildNodesPage", title);
+               this.currentNode = currentNode;
+       }
+
+       protected void createFormContent(IManagedForm managedForm) {
+               try {
+                       ScrolledForm form = managedForm.getForm();
+                       form.setText(JcrExplorerPlugin.getMessage("childNodesPageTitle"));
+                       Composite body = form.getBody();
+                       GridLayout twt = new GridLayout(1, false);
+                       twt.marginWidth = twt.marginHeight = 5;
+                       body.setLayout(twt);
+                       if (!currentNode.hasNodes()) {
+                               managedForm.getToolkit().createLabel(body,
+                                               JcrExplorerPlugin.getMessage("warningNoChildNode"));
+                       } else {
+
+                               nodeContentProvider = new SingleNodeAsTreeContentProvider();
+                               nodesViewer = createNodeViewer(body, nodeContentProvider);
+                               nodesViewer.setInput(currentNode);
+                       }
+               } catch (Exception e) {
+                       throw new ArgeoException(
+                                       "Unexpected error while creating child node page", e);
+               }
+       }
+
+       protected TreeViewer createNodeViewer(Composite parent,
+                       final ITreeContentProvider nodeContentProvider) {
+
+               final TreeViewer tmpNodeViewer = new TreeViewer(parent, SWT.MULTI);
+
+               tmpNodeViewer.getTree().setLayoutData(
+                               new GridData(SWT.FILL, SWT.FILL, true, true));
+
+               tmpNodeViewer.setContentProvider(nodeContentProvider);
+               tmpNodeViewer.setLabelProvider(new NodeLabelProvider());
+               tmpNodeViewer
+                               .addDoubleClickListener(new GenericNodeDoubleClickListener(
+                                               tmpNodeViewer));
+               return tmpNodeViewer;
+       }
+}
diff --git a/org.argeo.jcr.ui.explorer/src/org/argeo/jcr/ui/explorer/editors/EmptyNodePage.java b/org.argeo.jcr.ui.explorer/src/org/argeo/jcr/ui/explorer/editors/EmptyNodePage.java
new file mode 100644 (file)
index 0000000..322c7eb
--- /dev/null
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2007-2012 Argeo GmbH
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *         http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.argeo.jcr.ui.explorer.editors;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.ui.forms.IManagedForm;
+import org.eclipse.ui.forms.editor.FormEditor;
+import org.eclipse.ui.forms.editor.FormPage;
+import org.eclipse.ui.forms.widgets.ScrolledForm;
+
+/**
+ * This page is only used at editor's creation time when current node has not
+ * yet been set
+ */
+public class EmptyNodePage extends FormPage {
+       // private final static Log log = LogFactory.getLog(EmptyNodePage.class);
+
+       public EmptyNodePage(FormEditor editor, String title) {
+               super(editor, "Empty Page", title);
+       }
+
+       protected void createFormContent(IManagedForm managedForm) {
+               try {
+                       ScrolledForm form = managedForm.getForm();
+                       GridLayout twt = new GridLayout(1, false);
+                       twt.marginWidth = twt.marginHeight = 0;
+                       form.getBody().setLayout(twt);
+                       Label lbl = new Label(form.getBody(), SWT.NONE);
+                       lbl.setText("Empty page");
+               } catch (Exception e) {
+                       e.printStackTrace();
+               }
+       }
+}
diff --git a/org.argeo.jcr.ui.explorer/src/org/argeo/jcr/ui/explorer/editors/GenericJcrQueryEditor.java b/org.argeo.jcr.ui.explorer/src/org/argeo/jcr/ui/explorer/editors/GenericJcrQueryEditor.java
new file mode 100644 (file)
index 0000000..3b98ed1
--- /dev/null
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2007-2012 Argeo GmbH
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *         http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.argeo.jcr.ui.explorer.editors;
+
+import org.argeo.eclipse.ui.jcr.editors.AbstractJcrQueryEditor;
+import org.argeo.jcr.ui.explorer.JcrExplorerPlugin;
+import org.eclipse.swt.SWT;
+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.Event;
+import org.eclipse.swt.widgets.Listener;
+import org.eclipse.swt.widgets.Text;
+
+/** Enables end user to type and execute any JCR query. */
+public class GenericJcrQueryEditor extends AbstractJcrQueryEditor {
+       public final static String ID = JcrExplorerPlugin.ID + ".genericJcrQueryEditor";
+
+       private Text queryField;
+
+       @Override
+       public void createQueryForm(Composite parent) {
+               parent.setLayout(new GridLayout(1, false));
+
+               queryField = new Text(parent, SWT.BORDER | SWT.MULTI | SWT.WRAP);
+               queryField.setText(initialQuery);
+               queryField.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
+
+               Button execute = new Button(parent, SWT.PUSH);
+               execute.setText("Execute");
+
+               Listener executeListener = new Listener() {
+                       public void handleEvent(Event event) {
+                               executeQuery(queryField.getText());
+                       }
+               };
+
+               execute.addListener(SWT.Selection, executeListener);
+               // queryField.addListener(SWT.DefaultSelection, executeListener);
+       }
+
+       @Override
+       public void setFocus() {
+               queryField.setFocus();
+       }
+}
diff --git a/org.argeo.jcr.ui.explorer/src/org/argeo/jcr/ui/explorer/editors/GenericNodeEditor.java b/org.argeo.jcr.ui.explorer/src/org/argeo/jcr/ui/explorer/editors/GenericNodeEditor.java
new file mode 100644 (file)
index 0000000..57f3aa2
--- /dev/null
@@ -0,0 +1,113 @@
+/*
+ * Copyright (C) 2007-2012 Argeo GmbH
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *         http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.argeo.jcr.ui.explorer.editors;
+
+import javax.jcr.Node;
+
+import org.argeo.ArgeoException;
+import org.argeo.jcr.JcrUtils;
+import org.argeo.jcr.ui.explorer.JcrExplorerPlugin;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.ui.IEditorInput;
+import org.eclipse.ui.IEditorSite;
+import org.eclipse.ui.PartInitException;
+import org.eclipse.ui.forms.editor.FormEditor;
+
+/**
+ * Container for the node editor page. At creation time, it takes a JCR Node
+ * that cannot be changed afterwards.
+ */
+public class GenericNodeEditor extends FormEditor {
+
+       // private final static Log log =
+       // LogFactory.getLog(GenericNodeEditor.class);
+       public final static String ID = JcrExplorerPlugin.ID + ".genericNodeEditor";
+
+       private Node currentNode;
+
+       private GenericPropertyPage genericPropertyPage;
+       private ChildNodesPage childNodesPage;
+       private NodeRightsManagementPage nodeRightsManagementPage;
+       private NodeVersionHistoryPage nodeVersionHistoryPage;
+
+       public void init(IEditorSite site, IEditorInput input)
+                       throws PartInitException {
+               super.init(site, input);
+               GenericNodeEditorInput nei = (GenericNodeEditorInput) getEditorInput();
+               currentNode = nei.getCurrentNode();
+               this.setPartName(JcrUtils.lastPathElement(nei.getPath()));
+       }
+
+       @Override
+       protected void addPages() {
+               try {
+                       // genericNodePage = new GenericNodePage(this,
+                       // JcrExplorerPlugin.getMessage("genericNodePageTitle"),
+                       // currentNode);
+                       // addPage(genericNodePage);
+
+                       genericPropertyPage = new GenericPropertyPage(this,
+                                       JcrExplorerPlugin.getMessage("genericNodePageTitle"),
+                                       currentNode);
+                       addPage(genericPropertyPage);
+
+                       childNodesPage = new ChildNodesPage(this,
+                                       JcrExplorerPlugin.getMessage("childNodesPageTitle"),
+                                       currentNode);
+                       addPage(childNodesPage);
+
+                       nodeRightsManagementPage = new NodeRightsManagementPage(this,
+                                       JcrExplorerPlugin
+                                                       .getMessage("nodeRightsManagementPageTitle"),
+                                       currentNode);
+                       addPage(nodeRightsManagementPage);
+
+                       nodeVersionHistoryPage = new NodeVersionHistoryPage(
+                                       this,
+                                       JcrExplorerPlugin.getMessage("nodeVersionHistoryPageTitle"),
+                                       currentNode);
+                       addPage(nodeVersionHistoryPage);
+               } catch (PartInitException e) {
+                       throw new ArgeoException("Not able to add an empty page ", e);
+               }
+       }
+
+       @Override
+       public void doSaveAs() {
+               // unused compulsory method
+       }
+
+       @Override
+       public void doSave(IProgressMonitor monitor) {
+               try {
+                       // Automatically commit all pages of the editor
+                       commitPages(true);
+                       firePropertyChange(PROP_DIRTY);
+               } catch (Exception e) {
+                       throw new ArgeoException("Error while saving node", e);
+               }
+
+       }
+
+       @Override
+       public boolean isSaveAsAllowed() {
+               return true;
+       }
+
+       Node getCurrentNode() {
+               return currentNode;
+       }
+}
diff --git a/org.argeo.jcr.ui.explorer/src/org/argeo/jcr/ui/explorer/editors/GenericNodeEditorInput.java b/org.argeo.jcr.ui.explorer/src/org/argeo/jcr/ui/explorer/editors/GenericNodeEditorInput.java
new file mode 100644 (file)
index 0000000..45e337e
--- /dev/null
@@ -0,0 +1,111 @@
+/*
+ * Copyright (C) 2007-2012 Argeo GmbH
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *         http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.argeo.jcr.ui.explorer.editors;
+
+import javax.jcr.Node;
+import javax.jcr.RepositoryException;
+
+import org.argeo.ArgeoException;
+import org.eclipse.jface.resource.ImageDescriptor;
+import org.eclipse.ui.IEditorInput;
+import org.eclipse.ui.IPersistableElement;
+
+/**
+ * An editor input based the JCR node object.
+ * */
+
+public class GenericNodeEditorInput implements IEditorInput {
+       private final Node currentNode;
+
+       // cache key properties at creation time to avoid Exception at recoring time
+       // when the session has been closed
+       private String path;
+       private String uid;
+       private String name;
+
+       public GenericNodeEditorInput(Node currentNode) {
+               this.currentNode = currentNode;
+               try {
+                       name = currentNode.getName();
+                       uid = currentNode.getIdentifier();
+                       path = currentNode.getPath();
+               } catch (RepositoryException re) {
+                       throw new ArgeoException(
+                                       "unexpected error while getting node key values at creation time",
+                                       re);
+               }
+       }
+
+       public Node getCurrentNode() {
+               return currentNode;
+       }
+
+       public Object getAdapter(@SuppressWarnings("rawtypes") Class adapter) {
+               return null;
+       }
+
+       public boolean exists() {
+               return true;
+       }
+
+       public ImageDescriptor getImageDescriptor() {
+               return null;
+       }
+
+       public String getName() {
+               return name;
+       }
+
+       public String getUid() {
+               return uid;
+       }
+
+       public String getToolTipText() {
+               return path;
+       }
+
+       public String getPath() {
+               return path;
+       }
+
+       public IPersistableElement getPersistable() {
+               return null;
+       }
+
+       /**
+        * equals method based on UID that is unique within a workspace and path of
+        * the node, thus 2 shared node that have same UID as defined in the spec
+        * but 2 different pathes will open two distinct editors.
+        * 
+        * TODO enhance this method to support multirepository and multiworkspace
+        * environments
+        */
+       public boolean equals(Object obj) {
+               if (this == obj)
+                       return true;
+               if (obj == null)
+                       return false;
+               if (getClass() != obj.getClass())
+                       return false;
+
+               GenericNodeEditorInput other = (GenericNodeEditorInput) obj;
+               if (!getUid().equals(other.getUid()))
+                       return false;
+               if (!getPath().equals(other.getPath()))
+                       return false;
+               return true;
+       }
+}
diff --git a/org.argeo.jcr.ui.explorer/src/org/argeo/jcr/ui/explorer/editors/GenericNodePage.java b/org.argeo.jcr.ui.explorer/src/org/argeo/jcr/ui/explorer/editors/GenericNodePage.java
new file mode 100644 (file)
index 0000000..fd4dafe
--- /dev/null
@@ -0,0 +1,211 @@
+/*
+ * Copyright (C) 2007-2012 Argeo GmbH
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *         http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.argeo.jcr.ui.explorer.editors;
+
+import java.text.DateFormat;
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.ListIterator;
+
+import javax.jcr.Node;
+import javax.jcr.Property;
+import javax.jcr.PropertyIterator;
+import javax.jcr.PropertyType;
+import javax.jcr.RepositoryException;
+
+import org.argeo.ArgeoException;
+import org.argeo.jcr.JcrUtils;
+import org.argeo.jcr.ui.explorer.JcrExplorerConstants;
+import org.eclipse.swt.events.ModifyEvent;
+import org.eclipse.swt.events.ModifyListener;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Text;
+import org.eclipse.ui.forms.AbstractFormPart;
+import org.eclipse.ui.forms.IManagedForm;
+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;
+
+/**
+ * Main node editor page. Lists all properties of the current node and enable
+ * access and editing for some of them.
+ */
+
+public class GenericNodePage extends FormPage implements JcrExplorerConstants {
+       // private final static Log log = LogFactory.getLog(GenericNodePage.class);
+
+       // local constants
+       private final static String JCR_PROPERTY_NAME = "jcr:name";
+
+       // Utils
+       protected DateFormat timeFormatter = new SimpleDateFormat(DATE_TIME_FORMAT);
+
+       // Main business Objects
+       private Node currentNode;
+
+       // This page widgets
+       private FormToolkit tk;
+       private List<Control> modifyableProperties = new ArrayList<Control>();
+
+       public GenericNodePage(FormEditor editor, String title, Node currentNode) {
+               super(editor, "id", title);
+               this.currentNode = currentNode;
+       }
+
+       protected void createFormContent(IManagedForm managedForm) {
+               tk = managedForm.getToolkit();
+               ScrolledForm form = managedForm.getForm();
+               GridLayout twt = new GridLayout(3, false);
+               twt.marginWidth = twt.marginHeight = 5;
+
+               form.getBody().setLayout(twt);
+               createPropertiesPart(form.getBody());
+       }
+
+       private void createPropertiesPart(Composite parent) {
+               try {
+
+                       PropertyIterator pi = currentNode.getProperties();
+
+                       // Initializes form part
+                       AbstractFormPart part = new AbstractFormPart() {
+                               public void commit(boolean onSave) {
+                                       try {
+                                               if (onSave) {
+                                                       ListIterator<Control> it = modifyableProperties
+                                                                       .listIterator();
+                                                       while (it.hasNext()) {
+                                                               // we only support Text controls for the time
+                                                               // being
+                                                               Text curControl = (Text) it.next();
+                                                               String value = curControl.getText();
+                                                               currentNode.setProperty((String) curControl
+                                                                               .getData(JCR_PROPERTY_NAME), value);
+                                                       }
+
+                                                       // We only commit when onSave = true,
+                                                       // thus it is still possible to save after a tab
+                                                       // change.
+                                                       super.commit(onSave);
+                                               }
+                                       } catch (RepositoryException re) {
+                                               throw new ArgeoException(
+                                                               "Unexpected error while saving properties", re);
+                                       }
+                               }
+                       };
+
+                       while (pi.hasNext()) {
+                               Property prop = pi.nextProperty();
+                               addPropertyLine(parent, part, prop);
+                       }
+
+                       getManagedForm().addPart(part);
+               } catch (RepositoryException re) {
+                       throw new ArgeoException(
+                                       "Error during creation of network details section", re);
+               }
+
+       }
+
+       private void addPropertyLine(Composite parent, AbstractFormPart part,
+                       Property prop) {
+               try {
+                       tk.createLabel(parent, prop.getName());
+                       tk.createLabel(parent,
+                                       "[" + JcrUtils.getPropertyDefinitionAsString(prop) + "]");
+
+                       if (prop.getDefinition().isProtected()) {
+                               tk.createLabel(parent, formatReadOnlyPropertyValue(prop));
+                       } else
+                               addModifyableValueWidget(parent, part, prop);
+               } catch (RepositoryException re) {
+                       throw new ArgeoException("Cannot get property " + prop, re);
+               }
+       }
+
+       private String formatReadOnlyPropertyValue(Property prop) {
+               try {
+                       String strValue;
+
+                       if (prop.getType() == PropertyType.BINARY)
+                               strValue = "<binary>";
+                       else if (prop.isMultiple())
+                               strValue = Arrays.asList(prop.getValues()).toString();
+                       else if (prop.getType() == PropertyType.DATE)
+                               strValue = timeFormatter.format(prop.getValue().getDate()
+                                               .getTime());
+                       else
+                               strValue = prop.getValue().getString();
+
+                       return strValue;
+               } catch (RepositoryException re) {
+                       throw new ArgeoException(
+                                       "Unexpected error while formatting read only property value",
+                                       re);
+               }
+       }
+
+       private Control addModifyableValueWidget(Composite parent,
+                       AbstractFormPart part, Property prop) {
+               GridData gd;
+               try {
+                       if (prop.getType() == PropertyType.STRING) {
+                               Text txt = tk.createText(parent, prop.getString());
+                               gd = new GridData(GridData.FILL_HORIZONTAL);
+                               txt.setLayoutData(gd);
+                               txt.addModifyListener(new ModifiedFieldListener(part));
+                               txt.setData(JCR_PROPERTY_NAME, prop.getName());
+                               modifyableProperties.add(txt);
+                       } else {
+                               // unsupported property type for editing, we create a read only
+                               // label.
+                               return tk
+                                               .createLabel(parent, formatReadOnlyPropertyValue(prop));
+                       }
+                       return null;
+               } catch (RepositoryException re) {
+                       throw new ArgeoException(
+                                       "Unexpected error while formatting read only property value",
+                                       re);
+               }
+
+       }
+
+       //
+       // LISTENERS
+       //
+
+       private class ModifiedFieldListener implements ModifyListener {
+
+               private AbstractFormPart formPart;
+
+               public ModifiedFieldListener(AbstractFormPart generalPart) {
+                       this.formPart = generalPart;
+               }
+
+               public void modifyText(ModifyEvent e) {
+                       formPart.markDirty();
+               }
+       }
+
+}
diff --git a/org.argeo.jcr.ui.explorer/src/org/argeo/jcr/ui/explorer/editors/GenericPropertyPage.java b/org.argeo.jcr.ui.explorer/src/org/argeo/jcr/ui/explorer/editors/GenericPropertyPage.java
new file mode 100644 (file)
index 0000000..3aec453
--- /dev/null
@@ -0,0 +1,306 @@
+/*
+ * Copyright (C) 2007-2012 Argeo GmbH
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *         http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.argeo.jcr.ui.explorer.editors;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.jcr.Node;
+import javax.jcr.Property;
+import javax.jcr.PropertyIterator;
+import javax.jcr.RepositoryException;
+import javax.jcr.Value;
+
+import org.argeo.ArgeoException;
+import org.argeo.jcr.ui.explorer.JcrExplorerConstants;
+import org.argeo.jcr.ui.explorer.JcrExplorerPlugin;
+import org.argeo.jcr.ui.explorer.providers.PropertyLabelProvider;
+import org.eclipse.jface.viewers.ITreeContentProvider;
+import org.eclipse.jface.viewers.TreeViewer;
+import org.eclipse.jface.viewers.Viewer;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.layout.FillLayout;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Tree;
+import org.eclipse.swt.widgets.TreeColumn;
+import org.eclipse.ui.forms.IManagedForm;
+import org.eclipse.ui.forms.editor.FormEditor;
+import org.eclipse.ui.forms.editor.FormPage;
+import org.eclipse.ui.forms.widgets.ScrolledForm;
+
+/**
+ * Generic editor property page. Lists all properties of current node as a
+ * complex tree. TODO: enable editing
+ */
+
+public class GenericPropertyPage extends FormPage implements
+               JcrExplorerConstants {
+       // private final static Log log =
+       // LogFactory.getLog(GenericPropertyPage.class);
+
+       // Main business Objects
+       private Node currentNode;
+
+       public GenericPropertyPage(FormEditor editor, String title, Node currentNode) {
+               super(editor, "id", title);
+               this.currentNode = currentNode;
+       }
+
+       protected void createFormContent(IManagedForm managedForm) {
+               ScrolledForm form = managedForm.getForm();
+               form.setText(JcrExplorerPlugin.getMessage("genericNodePageTitle"));
+               FillLayout layout = new FillLayout();
+               layout.marginHeight = 5;
+               layout.marginWidth = 5;
+               form.getBody().setLayout(layout);
+
+               createComplexTree(form.getBody());
+
+               // TODO remove following
+               // createPropertiesPart(form.getBody());
+       }
+
+       private TreeViewer createComplexTree(Composite parent) {
+               int style = SWT.BORDER | SWT.MULTI | SWT.FULL_SELECTION;
+               Tree tree = new Tree(parent, style);
+               createColumn(tree, "Property", SWT.LEFT, 200);
+               createColumn(tree, "Value(s)", SWT.LEFT, 300);
+               createColumn(tree, "Attributes", SWT.LEFT, 65);
+               tree.setLinesVisible(true);
+               tree.setHeaderVisible(true);
+
+               TreeViewer result = new TreeViewer(tree);
+               result.setContentProvider(new TreeContentProvider());
+               result.setLabelProvider(new PropertyLabelProvider());
+               result.setInput(currentNode);
+               result.expandAll();
+               return result;
+       }
+
+       private static TreeColumn createColumn(Tree parent, String name, int style,
+                       int width) {
+               TreeColumn result = new TreeColumn(parent, style);
+               result.setText(name);
+               result.setWidth(width);
+               result.setMoveable(true);
+               result.setResizable(true);
+               return result;
+       }
+
+       //
+       // private void createPropertiesPart(Composite parent) {
+       // try {
+       //
+       // PropertyIterator pi = currentNode.getProperties();
+       //
+       // // Initializes form part
+       // AbstractFormPart part = new AbstractFormPart() {
+       // public void commit(boolean onSave) {
+       // try {
+       // if (onSave) {
+       // ListIterator<Control> it = modifyableProperties
+       // .listIterator();
+       // while (it.hasNext()) {
+       // // we only support Text controls for the time
+       // // being
+       // Text curControl = (Text) it.next();
+       // String value = curControl.getText();
+       // currentNode.setProperty((String) curControl
+       // .getData(JCR_PROPERTY_NAME), value);
+       // }
+       //
+       // // We only commit when onSave = true,
+       // // thus it is still possible to save after a tab
+       // // change.
+       // super.commit(onSave);
+       // }
+       // } catch (RepositoryException re) {
+       // throw new ArgeoException(
+       // "Unexpected error while saving properties", re);
+       // }
+       // }
+       // };
+       //
+       // while (pi.hasNext()) {
+       // Property prop = pi.nextProperty();
+       // addPropertyLine(parent, part, prop);
+       // }
+       //
+       // getManagedForm().addPart(part);
+       // } catch (RepositoryException re) {
+       // throw new ArgeoException(
+       // "Error during creation of network details section", re);
+       // }
+       //
+       // }
+       //
+       // private void addPropertyLine(Composite parent, AbstractFormPart part,
+       // Property prop) {
+       // try {
+       // tk.createLabel(parent, prop.getName());
+       // tk.createLabel(parent,
+       // "[" + JcrUtils.getPropertyDefinitionAsString(prop) + "]");
+       //
+       // if (prop.getDefinition().isProtected()) {
+       // tk.createLabel(parent, formatReadOnlyPropertyValue(prop));
+       // } else
+       // addModifyableValueWidget(parent, part, prop);
+       // } catch (RepositoryException re) {
+       // throw new ArgeoException("Cannot get property " + prop, re);
+       // }
+       // }
+       //
+       // private String formatReadOnlyPropertyValue(Property prop) {
+       // try {
+       // String strValue;
+       //
+       // if (prop.getType() == PropertyType.BINARY)
+       // strValue = "<binary>";
+       // else if (prop.isMultiple())
+       // strValue = Arrays.asList(prop.getValues()).toString();
+       // else if (prop.getType() == PropertyType.DATE)
+       // strValue = timeFormatter.format(prop.getValue().getDate()
+       // .getTime());
+       // else
+       // strValue = prop.getValue().getString();
+       //
+       // return strValue;
+       // } catch (RepositoryException re) {
+       // throw new ArgeoException(
+       // "Unexpected error while formatting read only property value",
+       // re);
+       // }
+       // }
+       //
+       // private Control addModifyableValueWidget(Composite parent,
+       // AbstractFormPart part, Property prop) {
+       // GridData gd;
+       // try {
+       // if (prop.getType() == PropertyType.STRING) {
+       // Text txt = tk.createText(parent, prop.getString());
+       // gd = new GridData(GridData.FILL_HORIZONTAL);
+       // txt.setLayoutData(gd);
+       // txt.addModifyListener(new ModifiedFieldListener(part));
+       // txt.setData(JCR_PROPERTY_NAME, prop.getName());
+       // modifyableProperties.add(txt);
+       // } else {
+       // // unsupported property type for editing, we create a read only
+       // // label.
+       // return tk
+       // .createLabel(parent, formatReadOnlyPropertyValue(prop));
+       // }
+       // return null;
+       // } catch (RepositoryException re) {
+       // throw new ArgeoException(
+       // "Unexpected error while formatting read only property value",
+       // re);
+       // }
+       //
+       // }
+
+       // Multiple Value Model
+       // protected class MultipleValueItem {
+       // private int index;
+       // private Value value;
+       //
+       // public MultipleValueItem(int index, Value value) {
+       // this.index = index;
+       // this.value = value;
+       // }
+       //
+       // public int getIndex() {
+       // return index;
+       // }
+       //
+       // public Object getValue() {
+       // return value;
+       // }
+       // }
+
+       private class TreeContentProvider implements ITreeContentProvider {
+               public Object[] getElements(Object parent) {
+                       Object[] props = null;
+                       try {
+
+                               if (parent instanceof Node) {
+                                       Node node = (Node) parent;
+                                       PropertyIterator pi;
+                                       pi = node.getProperties();
+                                       List<Property> propList = new ArrayList<Property>();
+                                       while (pi.hasNext()) {
+                                               propList.add(pi.nextProperty());
+                                       }
+                                       props = propList.toArray();
+                               }
+                       } catch (RepositoryException e) {
+                               throw new ArgeoException(
+                                               "Unexpected exception while listing node properties", e);
+                       }
+                       return props;
+               }
+
+               public Object getParent(Object child) {
+                       return null;
+               }
+
+               public Object[] getChildren(Object parent) {
+                       Object[] result = null;
+                       if (parent instanceof Property) {
+                               Property prop = (Property) parent;
+                               try {
+
+                                       if (prop.isMultiple()) {
+                                               Value[] values = prop.getValues();
+                                               // List<MultipleValueItem> list = new
+                                               // ArrayList<MultipleValueItem>();
+                                               // for (int i = 0; i < values.length; i++) {
+                                               // MultipleValueItem mvi = new MultipleValueItem(i,
+                                               // values[i]);
+                                               // list.add(mvi);
+                                               // }
+
+                                               return values;
+                                       }
+                               } catch (RepositoryException e) {
+                                       throw new ArgeoException(
+                                                       "Unexpected error getting multiple values property.",
+                                                       e);
+                               }
+                       }
+                       return result;
+               }
+
+               public boolean hasChildren(Object parent) {
+                       try {
+                               if (parent instanceof Property
+                                               && ((Property) parent).isMultiple()) {
+                                       return true;
+                               }
+                       } catch (RepositoryException e) {
+                               throw new ArgeoException(
+                                               "Unexpected exception while checking if property is multiple",
+                                               e);
+                       }
+                       return false;
+               }
+
+               public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
+               }
+
+               public void dispose() {
+               }
+       }
+}
diff --git a/org.argeo.jcr.ui.explorer/src/org/argeo/jcr/ui/explorer/editors/NodeRightsManagementPage.java b/org.argeo.jcr.ui.explorer/src/org/argeo/jcr/ui/explorer/editors/NodeRightsManagementPage.java
new file mode 100644 (file)
index 0000000..cc5efb5
--- /dev/null
@@ -0,0 +1,138 @@
+/*
+ * Copyright (C) 2007-2012 Argeo GmbH
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *         http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.argeo.jcr.ui.explorer.editors;
+
+import javax.jcr.Node;
+import javax.jcr.security.AccessControlManager;
+import javax.jcr.security.Privilege;
+
+import org.argeo.ArgeoException;
+import org.argeo.jcr.ui.explorer.JcrExplorerPlugin;
+import org.eclipse.jface.viewers.ColumnLabelProvider;
+import org.eclipse.jface.viewers.IStructuredContentProvider;
+import org.eclipse.jface.viewers.TableViewer;
+import org.eclipse.jface.viewers.TableViewerColumn;
+import org.eclipse.jface.viewers.Viewer;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.layout.FillLayout;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Table;
+import org.eclipse.swt.widgets.TableColumn;
+import org.eclipse.ui.forms.IManagedForm;
+import org.eclipse.ui.forms.editor.FormEditor;
+import org.eclipse.ui.forms.editor.FormPage;
+import org.eclipse.ui.forms.widgets.ScrolledForm;
+
+/**
+ * This comments will be nicely fill by mbaudier in.
+ */
+public class NodeRightsManagementPage extends FormPage {
+       // private final static Log log =
+       // LogFactory.getLog(NodeRightsManagementPage.class);
+
+       private Node currentNode;
+
+       private TableViewer viewer;
+
+       public NodeRightsManagementPage(FormEditor editor, String title,
+                       Node currentNode) {
+               super(editor, "NodeRightsManagementPage", title);
+               this.currentNode = currentNode;
+       }
+
+       protected void createFormContent(IManagedForm managedForm) {
+               ScrolledForm form = managedForm.getForm();
+               form.setText(JcrExplorerPlugin
+                               .getMessage("nodeRightsManagementPageTitle"));
+               FillLayout layout = new FillLayout();
+               layout.marginHeight = 5;
+               layout.marginWidth = 5;
+               form.getBody().setLayout(layout);
+               createRightsPart(form.getBody());
+       }
+
+       /** Creates the rights part */
+       protected void createRightsPart(Composite parent) {
+               Table table = new Table(parent, SWT.MULTI | SWT.H_SCROLL | SWT.V_SCROLL);
+               table.setLinesVisible(true);
+               table.setHeaderVisible(true);
+               viewer = new TableViewer(table);
+
+               // check column
+               TableViewerColumn column = createTableViewerColumn(viewer, "checked",
+                               20);
+               column.setLabelProvider(new ColumnLabelProvider() {
+                       public String getText(Object element) {
+                               return null;
+                       }
+
+                       public Image getImage(Object element) {
+                               return null;
+                       }
+               });
+               // column.setEditingSupport(new RoleEditingSupport(rolesViewer, part));
+
+               // role column
+               column = createTableViewerColumn(viewer, "Role", 200);
+               column.setLabelProvider(new ColumnLabelProvider() {
+                       public String getText(Object element) {
+                               Privilege p = (Privilege) element;
+                               return p.getName();
+                       }
+
+                       public Image getImage(Object element) {
+                               return null;
+                       }
+               });
+               viewer.setContentProvider(new RightsContentProvider());
+               viewer.setInput(getEditorSite());
+       }
+
+       protected TableViewerColumn createTableViewerColumn(TableViewer viewer,
+                       String title, int bound) {
+               final TableViewerColumn viewerColumn = new TableViewerColumn(viewer,
+                               SWT.NONE);
+               final TableColumn column = viewerColumn.getColumn();
+               column.setText(title);
+               column.setWidth(bound);
+               column.setResizable(true);
+               column.setMoveable(true);
+               return viewerColumn;
+       }
+
+       private class RightsContentProvider implements IStructuredContentProvider {
+
+               public void dispose() {
+               }
+
+               public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
+               }
+
+               public Object[] getElements(Object inputElement) {
+                       try {
+                               AccessControlManager accessControlManager = currentNode
+                                               .getSession().getAccessControlManager();
+                               Privilege[] privileges = accessControlManager
+                                               .getPrivileges(currentNode.getPath());
+                               return privileges;
+                       } catch (Exception e) {
+                               throw new ArgeoException("Cannot retrieve rights", e);
+                       }
+               }
+
+       }
+}
diff --git a/org.argeo.jcr.ui.explorer/src/org/argeo/jcr/ui/explorer/editors/NodeVersionHistoryPage.java b/org.argeo.jcr.ui.explorer/src/org/argeo/jcr/ui/explorer/editors/NodeVersionHistoryPage.java
new file mode 100644 (file)
index 0000000..59fff5e
--- /dev/null
@@ -0,0 +1,319 @@
+/*
+ * Copyright (C) 2007-2012 Argeo GmbH
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *         http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.argeo.jcr.ui.explorer.editors;
+
+import java.text.DateFormat;
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.Calendar;
+import java.util.List;
+import java.util.Map;
+
+import javax.jcr.Node;
+import javax.jcr.Property;
+import javax.jcr.PropertyType;
+import javax.jcr.RepositoryException;
+import javax.jcr.Value;
+import javax.jcr.nodetype.NodeType;
+import javax.jcr.version.Version;
+import javax.jcr.version.VersionHistory;
+import javax.jcr.version.VersionIterator;
+import javax.jcr.version.VersionManager;
+
+import org.argeo.ArgeoException;
+import org.argeo.jcr.JcrUtils;
+import org.argeo.jcr.PropertyDiff;
+import org.argeo.jcr.VersionDiff;
+import org.argeo.jcr.ui.explorer.JcrExplorerConstants;
+import org.argeo.jcr.ui.explorer.JcrExplorerPlugin;
+import org.argeo.jcr.ui.explorer.providers.FullVersioningTreeContentProvider;
+import org.argeo.jcr.ui.explorer.providers.VersionLabelProvider;
+import org.argeo.jcr.ui.explorer.utils.GenericNodeDoubleClickListener;
+import org.eclipse.jface.viewers.ITreeContentProvider;
+import org.eclipse.jface.viewers.TreeViewer;
+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.forms.AbstractFormPart;
+import org.eclipse.ui.forms.IManagedForm;
+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;
+import org.eclipse.ui.forms.widgets.Section;
+import org.eclipse.ui.forms.widgets.TableWrapData;
+import org.eclipse.ui.forms.widgets.TableWrapLayout;
+
+/**
+ * Offers two main sections : one to display a text area with a summary of all
+ * variations between a version and its predecessor and one tree view that
+ * enable browsing
+ * */
+public class NodeVersionHistoryPage extends FormPage implements
+               JcrExplorerConstants {
+       // private final static Log log = LogFactory
+       // .getLog(NodeVersionHistoryPage.class);
+
+       // Utils
+       protected DateFormat timeFormatter = new SimpleDateFormat(DATE_TIME_FORMAT);
+
+       // business objects
+       private Node currentNode;
+
+       // this page UI components
+       private FullVersioningTreeContentProvider nodeContentProvider;
+       private TreeViewer nodesViewer;
+       private FormToolkit tk;
+
+       public NodeVersionHistoryPage(FormEditor editor, String title,
+                       Node currentNode) {
+               super(editor, "NodeVersionHistoryPage", title);
+               this.currentNode = currentNode;
+       }
+
+       protected void createFormContent(IManagedForm managedForm) {
+               ScrolledForm form = managedForm.getForm();
+               form.setText(JcrExplorerPlugin
+                               .getMessage("nodeVersionHistoryPageTitle"));
+               tk = managedForm.getToolkit();
+               GridLayout twt = new GridLayout(1, false);
+               twt.marginWidth = twt.marginHeight = 5;
+               Composite body = form.getBody();
+               body.setLayout(twt);
+
+               try {
+                       if (!currentNode.isNodeType(NodeType.MIX_VERSIONABLE)) {
+                               tk.createLabel(body, JcrExplorerPlugin
+                                               .getMessage("warningUnversionableNode"));
+                       } else {
+                               createHistorySection(form.getBody());
+                               createTreeSection(form.getBody());
+                       }
+               } catch (RepositoryException e) {
+                       throw new ArgeoException(
+                                       "Unexpected error while checking if node is versionable", e);
+               }
+       }
+
+       protected void createTreeSection(Composite parent) {
+               // Section Layout & MetaData
+               Section section = tk.createSection(parent, Section.TWISTIE);
+               section.setLayoutData(new GridData(GridData.FILL_BOTH));
+               section.setText(JcrExplorerPlugin.getMessage("versionTreeSectionTitle"));
+
+               // Section Body
+               Composite body = tk.createComposite(section, SWT.FILL);
+               // WARNING : 2 following lines are compulsory or body won't be
+               // displayed.
+               body.setLayout(new GridLayout());
+               section.setClient(body);
+
+               body.setLayoutData(new GridData(GridData.FILL_BOTH));
+               section.setExpanded(true);
+
+               nodeContentProvider = new FullVersioningTreeContentProvider();
+               nodesViewer = createNodeViewer(body, nodeContentProvider);
+               nodesViewer.setInput(currentNode);
+       }
+
+       protected TreeViewer createNodeViewer(Composite parent,
+                       final ITreeContentProvider nodeContentProvider) {
+
+               final TreeViewer tmpNodeViewer = new TreeViewer(parent, SWT.MULTI);
+
+               tmpNodeViewer.getTree().setLayoutData(
+                               new GridData(SWT.FILL, SWT.FILL, true, true));
+
+               tmpNodeViewer.setContentProvider(nodeContentProvider);
+               tmpNodeViewer.setLabelProvider(new VersionLabelProvider());
+               tmpNodeViewer
+                               .addDoubleClickListener(new GenericNodeDoubleClickListener(
+                                               tmpNodeViewer));
+               return tmpNodeViewer;
+       }
+
+       protected void createHistorySection(Composite parent) {
+
+               // Section Layout
+               Section section = tk.createSection(parent, Section.TWISTIE);
+               section.setLayoutData(new GridData(TableWrapData.FILL_GRAB));
+               TableWrapLayout twt = new TableWrapLayout();
+               section.setLayout(twt);
+
+               // Set title of the section
+               section.setText(JcrExplorerPlugin
+                               .getMessage("versionHistorySectionTitle"));
+
+               final Text styledText = tk.createText(section, "", SWT.FULL_SELECTION
+                               | SWT.BORDER | SWT.MULTI | SWT.WRAP | SWT.V_SCROLL);
+               styledText.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
+               section.setClient(styledText);
+               refreshHistory(styledText);
+               styledText.setEditable(false);
+               section.setExpanded(false);
+
+               AbstractFormPart part = new AbstractFormPart() {
+                       public void commit(boolean onSave) {
+                       }
+
+                       public void refresh() {
+                               super.refresh();
+                               refreshHistory(styledText);
+                       }
+               };
+               getManagedForm().addPart(part);
+       }
+
+       protected void refreshHistory(Text styledText) {
+               try {
+                       List<VersionDiff> lst = listHistoryDiff();
+                       StringBuffer main = new StringBuffer("");
+
+                       for (int i = lst.size() - 1; i >= 0; i--) {
+                               if (i == 0)
+                                       main.append("Creation (");
+                               else
+                                       main.append("Update " + i + " (");
+
+                               if (lst.get(i).getUserId() != null)
+                                       main.append("UserId : " + lst.get(i).getUserId());
+
+                               if (lst.get(i).getUserId() != null
+                                               && lst.get(i).getUpdateTime() != null)
+                                       main.append(", ");
+
+                               if (lst.get(i).getUpdateTime() != null)
+                                       main.append("Date : "
+                                                       + timeFormatter.format(lst.get(i).getUpdateTime()
+                                                                       .getTime()) + ")\n");
+
+                               StringBuffer buf = new StringBuffer("");
+                               Map<String, PropertyDiff> diffs = lst.get(i).getDiffs();
+                               for (String prop : diffs.keySet()) {
+                                       PropertyDiff pd = diffs.get(prop);
+                                       // String propName = pd.getRelPath();
+                                       Value refValue = pd.getReferenceValue();
+                                       Value newValue = pd.getNewValue();
+                                       String refValueStr = "";
+                                       String newValueStr = "";
+
+                                       if (refValue != null) {
+                                               if (refValue.getType() == PropertyType.DATE) {
+                                                       refValueStr = timeFormatter.format(refValue
+                                                                       .getDate().getTime());
+                                               } else
+                                                       refValueStr = refValue.getString();
+                                       }
+                                       if (newValue != null) {
+                                               if (newValue.getType() == PropertyType.DATE) {
+                                                       newValueStr = timeFormatter.format(newValue
+                                                                       .getDate().getTime());
+                                               } else
+                                                       newValueStr = newValue.getString();
+                                       }
+
+                                       if (pd.getType() == PropertyDiff.MODIFIED) {
+                                               buf.append(prop).append(": ");
+                                               buf.append(refValueStr);
+                                               buf.append(" > ");
+                                               buf.append(newValueStr);
+                                               buf.append("\n");
+                                       } else if (pd.getType() == PropertyDiff.ADDED
+                                                       && !"".equals(newValueStr)) {
+                                               // we don't list property that have been added with an
+                                               // empty string as value
+                                               buf.append(prop).append(": ");
+                                               buf.append(" + ");
+                                               buf.append(newValueStr);
+                                               buf.append("\n");
+                                       } else if (pd.getType() == PropertyDiff.REMOVED) {
+                                               buf.append(prop).append(": ");
+                                               buf.append(" - ");
+                                               buf.append(refValueStr);
+                                               buf.append("\n");
+                                       }
+                               }
+                               buf.append("\n");
+                               main.append(buf);
+                       }
+                       styledText.setText(main.toString());
+               } catch (RepositoryException e) {
+                       throw new ArgeoException("Cannot generate history for node", e);
+               }
+
+       }
+
+       public List<VersionDiff> listHistoryDiff() {
+               try {
+                       List<VersionDiff> res = new ArrayList<VersionDiff>();
+                       VersionManager versionManager = currentNode.getSession()
+                                       .getWorkspace().getVersionManager();
+                       VersionHistory versionHistory = versionManager
+                                       .getVersionHistory(currentNode.getPath());
+
+                       VersionIterator vit = versionHistory.getAllLinearVersions();
+                       while (vit.hasNext()) {
+                               Version version = vit.nextVersion();
+                               Node node = version.getFrozenNode();
+                               Version predecessor = null;
+                               try {
+                                       predecessor = version.getLinearPredecessor();
+                               } catch (Exception e) {
+                                       // no predecessor seems to throw an exception even if it
+                                       // shouldn't...
+                               }
+                               if (predecessor == null) {// original
+                               } else {
+                                       Map<String, PropertyDiff> diffs = JcrUtils.diffProperties(
+                                                       predecessor.getFrozenNode(), node);
+                                       if (!diffs.isEmpty()) {
+                                               String lastUserName = null;
+                                               Calendar lastUpdate = null;
+                                               try {
+                                                       if (currentNode
+                                                                       .isNodeType(NodeType.MIX_LAST_MODIFIED)) {
+                                                               lastUserName = node.getProperty(
+                                                                               Property.JCR_LAST_MODIFIED_BY)
+                                                                               .getString();
+                                                               lastUpdate = node.getProperty(
+                                                                               Property.JCR_LAST_MODIFIED).getDate();
+                                                       } else
+                                                               lastUpdate = version.getProperty(
+                                                                               Property.JCR_CREATED).getDate();
+
+                                               } catch (Exception e) {
+                                                       // Silent that info is optional
+                                               }
+                                               VersionDiff vd = new VersionDiff(lastUserName,
+                                                               lastUpdate, diffs);
+                                               res.add(vd);
+                                       }
+                               }
+                       }
+                       return res;
+               } catch (RepositoryException e) {
+                       throw new ArgeoException("Cannot generate history for node ");
+               }
+
+       }
+
+       @Override
+       public void setActive(boolean active) {
+               super.setActive(active);
+       }
+}
diff --git a/org.argeo.jcr.ui.explorer/src/org/argeo/jcr/ui/explorer/editors/StringNodeEditorInput.java b/org.argeo.jcr.ui.explorer/src/org/argeo/jcr/ui/explorer/editors/StringNodeEditorInput.java
new file mode 100644 (file)
index 0000000..654b2ae
--- /dev/null
@@ -0,0 +1,120 @@
+/*
+ * Copyright (C) 2007-2012 Argeo GmbH
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *         http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.argeo.jcr.ui.explorer.editors;
+
+import org.eclipse.jface.resource.ImageDescriptor;
+import org.eclipse.ui.IEditorInput;
+import org.eclipse.ui.IPersistableElement;
+
+/**
+ * An editor input based on three strings define a node :
+ * <ul>
+ * <li>complete path to the node</li>
+ * <li>the workspace name</li>
+ * <li>the repository alias</li>
+ * </ul>
+ * In a single workspace and/or repository environment, name and alias can be
+ * null.
+ * 
+ * Note : unused for the time being.
+ */
+
+public class StringNodeEditorInput implements IEditorInput {
+       private final String path;
+       private final String repositoryAlias;
+       private final String workspaceName;
+
+       /**
+        * In order to implement a generic explorer that supports remote and multi
+        * workspaces repositories, node path can be detailed by these strings.
+        * 
+        * @param repositoryAlias
+        *            : can be null
+        * @param workspaceName
+        *            : can be null
+        * @param path
+        */
+       public StringNodeEditorInput(String repositoryAlias, String workspaceName,
+                       String path) {
+               this.path = path;
+               this.repositoryAlias = repositoryAlias;
+               this.workspaceName = workspaceName;
+       }
+
+       public Object getAdapter(@SuppressWarnings("rawtypes") Class adapter) {
+               return null;
+       }
+
+       public boolean exists() {
+               return true;
+       }
+
+       public ImageDescriptor getImageDescriptor() {
+               return null;
+       }
+
+       public String getName() {
+               return path;
+       }
+
+       public String getRepositoryAlias() {
+               return repositoryAlias;
+       }
+
+       public String getWorkspaceName() {
+               return workspaceName;
+       }
+
+       public IPersistableElement getPersistable() {
+               return null;
+       }
+
+       public String getToolTipText() {
+               return path;
+       }
+
+       public String getPath() {
+               return path;
+       }
+
+       public boolean equals(Object obj) {
+               if (this == obj)
+                       return true;
+               if (obj == null)
+                       return false;
+               if (getClass() != obj.getClass())
+                       return false;
+
+               StringNodeEditorInput other = (StringNodeEditorInput) obj;
+
+               if (!path.equals(other.getPath()))
+                       return false;
+
+               String own = other.getWorkspaceName();
+               if ((workspaceName == null && own != null)
+                               || (workspaceName != null && (own == null || !workspaceName
+                                               .equals(own))))
+                       return false;
+
+               String ora = other.getRepositoryAlias();
+               if ((repositoryAlias == null && ora != null)
+                               || (repositoryAlias != null && (ora == null || !repositoryAlias
+                                               .equals(ora))))
+                       return false;
+
+               return true;
+       }
+}
diff --git a/org.argeo.jcr.ui.explorer/src/org/argeo/jcr/ui/explorer/messages.properties b/org.argeo.jcr.ui.explorer/src/org/argeo/jcr/ui/explorer/messages.properties
new file mode 100644 (file)
index 0000000..3023c52
--- /dev/null
@@ -0,0 +1,28 @@
+## English labels for Agreo JCR UI application 
+
+## Generic labels 
+
+## Errors & warnings 
+errorUnvalidNtFolderNodeType= Error: folder can only be created on a Jcr Node
+warningInvalidNodeToImport=Can only import to a node
+warningInvalidMultipleSelection=This functionality is implemented only on a single node for the time being.
+warningUnversionableNode= Current node is not versionable.
+warningNoChildNode= Current node has no child.
+
+## Commands 
+getNodeSizeCmdLbl= Get approx. size
+addFolderNodeCmdLbl= Add Folder
+
+## GenericNodeEditor 
+nodeEditorLbl=Generic node editor
+genericNodePageTitle=Properties
+childNodesPageTitle=Children
+nodeRightsManagementPageTitle=Rights
+nodeVersionHistoryPageTitle=History
+
+# History 
+versionTreeSectionTitle=Version list
+versionHistorySectionTitle=History
+## Dummy ones 
+testLbl=Internationalizations of messages seems to work properly.
diff --git a/org.argeo.jcr.ui.explorer/src/org/argeo/jcr/ui/explorer/model/MaintainedRepositoryElem.java b/org.argeo.jcr.ui.explorer/src/org/argeo/jcr/ui/explorer/model/MaintainedRepositoryElem.java
new file mode 100644 (file)
index 0000000..abb97a9
--- /dev/null
@@ -0,0 +1,24 @@
+package org.argeo.jcr.ui.explorer.model;
+
+import javax.jcr.Repository;
+
+import org.argeo.ArgeoException;
+import org.argeo.eclipse.ui.TreeParent;
+import org.argeo.jcr.MaintainedRepository;
+
+/** Wraps a {@link MaintainedRepository} */
+public class MaintainedRepositoryElem extends RepositoryElem {
+
+       public MaintainedRepositoryElem(String alias, Repository repository,
+                       TreeParent parent) {
+               super(alias, repository, parent);
+               if (!(repository instanceof MaintainedRepository)) {
+                       throw new ArgeoException("Repository " + alias
+                                       + " is not amiantained repository");
+               }
+       }
+
+       protected MaintainedRepository getMaintainedRepository() {
+               return (MaintainedRepository) getRepository();
+       }
+}
diff --git a/org.argeo.jcr.ui.explorer/src/org/argeo/jcr/ui/explorer/model/RemoteRepositoryElem.java b/org.argeo.jcr.ui.explorer/src/org/argeo/jcr/ui/explorer/model/RemoteRepositoryElem.java
new file mode 100644 (file)
index 0000000..0be6978
--- /dev/null
@@ -0,0 +1,94 @@
+/*
+ * Copyright (C) 2007-2012 Argeo GmbH
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *         http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.argeo.jcr.ui.explorer.model;
+
+import java.util.Arrays;
+
+import javax.jcr.Node;
+import javax.jcr.Repository;
+import javax.jcr.RepositoryException;
+import javax.jcr.RepositoryFactory;
+import javax.jcr.Session;
+import javax.jcr.SimpleCredentials;
+
+import org.argeo.ArgeoException;
+import org.argeo.eclipse.ui.TreeParent;
+import org.argeo.jcr.ArgeoJcrUtils;
+import org.argeo.jcr.ArgeoNames;
+import org.argeo.util.security.Keyring;
+
+/** Root of a remote repository */
+public class RemoteRepositoryElem extends RepositoryElem {
+       private final Keyring keyring;
+       /**
+        * A session of the logged in user on the default workspace of the node
+        * repository.
+        */
+       private final Session userSession;
+       private final String remoteNodePath;
+
+       private final RepositoryFactory repositoryFactory;
+       private final String uri;
+
+       public RemoteRepositoryElem(String alias,
+                       RepositoryFactory repositoryFactory, String uri, TreeParent parent,
+                       Session userSession, Keyring keyring, String remoteNodePath) {
+               super(alias, null, parent);
+               this.repositoryFactory = repositoryFactory;
+               this.uri = uri;
+               this.keyring = keyring;
+               this.userSession = userSession;
+               this.remoteNodePath = remoteNodePath;
+       }
+
+       @Override
+       protected Session repositoryLogin(String workspaceName)
+                       throws RepositoryException {
+               Node remoteRepository = userSession.getNode(remoteNodePath);
+               String userID = remoteRepository.getProperty(ArgeoNames.ARGEO_USER_ID)
+                               .getString();
+               String pwdPath = remoteRepository.getPath() + '/'
+                               + ArgeoNames.ARGEO_PASSWORD;
+               char[] password = keyring.getAsChars(pwdPath);
+
+               try {
+                       SimpleCredentials credentials = new SimpleCredentials(userID,
+                                       password);
+                       return getRepository().login(credentials, workspaceName);
+               } finally {
+                       Arrays.fill(password, 0, password.length, ' ');
+               }
+       }
+
+       @Override
+       public Repository getRepository() {
+               if (repository == null)
+                       repository = ArgeoJcrUtils.getRepositoryByUri(repositoryFactory,
+                                       uri);
+               return super.getRepository();
+       }
+
+       public void remove() {
+               try {
+                       Node remoteNode = userSession.getNode(remoteNodePath);
+                       remoteNode.remove();
+                       remoteNode.getSession().save();
+               } catch (RepositoryException e) {
+                       throw new ArgeoException("Cannot remove " + remoteNodePath, e);
+               }
+       }
+
+}
diff --git a/org.argeo.jcr.ui.explorer/src/org/argeo/jcr/ui/explorer/model/RepositoriesElem.java b/org.argeo.jcr.ui.explorer/src/org/argeo/jcr/ui/explorer/model/RepositoriesElem.java
new file mode 100644 (file)
index 0000000..b123727
--- /dev/null
@@ -0,0 +1,134 @@
+/*
+ * Copyright (C) 2007-2012 Argeo GmbH
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *         http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.argeo.jcr.ui.explorer.model;
+
+import java.util.Map;
+
+import javax.jcr.Node;
+import javax.jcr.NodeIterator;
+import javax.jcr.Repository;
+import javax.jcr.RepositoryException;
+import javax.jcr.RepositoryFactory;
+import javax.jcr.Session;
+
+import org.argeo.ArgeoException;
+import org.argeo.eclipse.ui.ErrorFeedback;
+import org.argeo.eclipse.ui.TreeParent;
+import org.argeo.jcr.ArgeoNames;
+import org.argeo.jcr.MaintainedRepository;
+import org.argeo.jcr.RepositoryRegister;
+import org.argeo.jcr.UserJcrUtils;
+import org.argeo.util.security.Keyring;
+
+/**
+ * UI Tree component. Implements the Argeo abstraction of a
+ * {@link RepositoryFactory} that enable a user to "mount" various repositories
+ * in a single Tree like View. It is usually meant to be at the root of the UI
+ * Tree and thus {@link getParent()} method will return null.
+ * 
+ * The {@link RepositoryFactory} is injected at instantiation time and must be
+ * use get or register new {@link Repository} objects upon which a reference is
+ * kept here.
+ */
+
+public class RepositoriesElem extends TreeParent implements ArgeoNames {
+       private final RepositoryRegister repositoryRegister;
+       private final RepositoryFactory repositoryFactory;
+
+       /**
+        * A session of the logged in user on the default workspace of the node
+        * repository.
+        */
+       private final Session userSession;
+       private final Keyring keyring;
+
+       public RepositoriesElem(String name, RepositoryRegister repositoryRegister,
+                       RepositoryFactory repositoryFactory, TreeParent parent,
+                       Session userSession, Keyring keyring) {
+               super(name);
+               this.repositoryRegister = repositoryRegister;
+               this.repositoryFactory = repositoryFactory;
+               this.userSession = userSession;
+               this.keyring = keyring;
+       }
+
+       /**
+        * Override normal behavior to initialize the various repositories only at
+        * request time
+        */
+       @Override
+       public synchronized Object[] getChildren() {
+               if (isLoaded()) {
+                       return super.getChildren();
+               } else {
+                       // initialize current object
+                       Map<String, Repository> refRepos = repositoryRegister
+                                       .getRepositories();
+                       for (String name : refRepos.keySet()) {
+                               Repository repository = refRepos.get(name);
+                               if (repository instanceof MaintainedRepository)
+                                       super.addChild(new MaintainedRepositoryElem(name,
+                                                       repository, this));
+                               else
+                                       super.addChild(new RepositoryElem(name, repository, this));
+                       }
+
+                       // remote
+                       if (keyring != null) {
+                               try {
+                                       addRemoteRepositories(keyring);
+                               } catch (RepositoryException e) {
+                                       throw new ArgeoException(
+                                                       "Cannot browse remote repositories", e);
+                               }
+                       }
+                       return super.getChildren();
+               }
+       }
+
+       protected void addRemoteRepositories(Keyring jcrKeyring)
+                       throws RepositoryException {
+               Node userHome = UserJcrUtils.getUserHome(userSession);
+               if (userHome != null && userHome.hasNode(ARGEO_REMOTE)) {
+                       NodeIterator it = userHome.getNode(ARGEO_REMOTE).getNodes();
+                       while (it.hasNext()) {
+                               Node remoteNode = it.nextNode();
+                               String uri = remoteNode.getProperty(ARGEO_URI).getString();
+                               try {
+                                       RemoteRepositoryElem remoteRepositoryNode = new RemoteRepositoryElem(
+                                                       remoteNode.getName(), repositoryFactory, uri, this,
+                                                       userSession, jcrKeyring, remoteNode.getPath());
+                                       super.addChild(remoteRepositoryNode);
+                               } catch (Exception e) {
+                                       ErrorFeedback.show("Cannot add remote repository "
+                                                       + remoteNode, e);
+                               }
+                       }
+               }
+       }
+
+       public void registerNewRepository(String alias, Repository repository) {
+               // TODO: implement this
+               // Create a new RepositoryNode Object
+               // add it
+               // super.addChild(new RepositoriesNode(...));
+       }
+
+       /** Returns the {@link RepositoryRegister} wrapped by this object. */
+       public RepositoryRegister getRepositoryRegister() {
+               return repositoryRegister;
+       }
+}
diff --git a/org.argeo.jcr.ui.explorer/src/org/argeo/jcr/ui/explorer/model/RepositoryElem.java b/org.argeo.jcr.ui.explorer/src/org/argeo/jcr/ui/explorer/model/RepositoryElem.java
new file mode 100644 (file)
index 0000000..935bac1
--- /dev/null
@@ -0,0 +1,103 @@
+/*
+ * Copyright (C) 2007-2012 Argeo GmbH
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *         http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.argeo.jcr.ui.explorer.model;
+
+import javax.jcr.Repository;
+import javax.jcr.RepositoryException;
+import javax.jcr.Session;
+
+import org.argeo.ArgeoException;
+import org.argeo.eclipse.ui.TreeParent;
+
+/**
+ * UI Tree component. Wraps a JCR {@link Repository}. It also keeps a reference
+ * to its parent Tree Ui component; typically the unique {@link Repositories}
+ * object of the current view to enable bi-directionnal browsing in the tree.
+ */
+
+public class RepositoryElem extends TreeParent {
+       private String alias;
+       protected Repository repository;
+       private Session defaultSession = null;
+
+       /** Create a new repository with distinct name & alias */
+       public RepositoryElem(String alias, Repository repository, TreeParent parent) {
+               super(alias);
+               this.repository = repository;
+               setParent(parent);
+               this.alias = alias;
+       }
+
+       public void login() {
+               try {
+                       defaultSession = repositoryLogin(null);
+                       String[] wkpNames = defaultSession.getWorkspace()
+                                       .getAccessibleWorkspaceNames();
+                       for (String wkpName : wkpNames) {
+                               if (wkpName.equals(defaultSession.getWorkspace().getName()))
+                                       addChild(new WorkspaceElem(this, wkpName, defaultSession));
+                               else
+                                       addChild(new WorkspaceElem(this, wkpName));
+                       }
+               } catch (RepositoryException e) {
+                       throw new ArgeoException("Cannot connect to repository " + alias, e);
+               }
+       }
+
+       /**
+        * Actual call to the
+        * {@link Repository#login(javax.jcr.Credentials, String)} method. To be
+        * overridden.
+        */
+       protected Session repositoryLogin(String workspaceName)
+                       throws RepositoryException {
+               return repository.login(workspaceName);
+       }
+
+       public String[] getAccessibleWorkspaceNames() {
+               try {
+                       return defaultSession.getWorkspace().getAccessibleWorkspaceNames();
+               } catch (RepositoryException e) {
+                       throw new ArgeoException("Cannot retrieve workspace names", e);
+               }
+       }
+
+       public void createWorkspace(String workspaceName) {
+               if (!isConnected())
+                       login();
+               try {
+                       defaultSession.getWorkspace().createWorkspace(workspaceName);
+               } catch (RepositoryException e) {
+                       throw new ArgeoException("Cannot create workspace", e);
+               }
+       }
+
+       /** returns the {@link Repository} referenced by the current UI Node */
+       public Repository getRepository() {
+               return repository;
+       }
+
+       public String getAlias() {
+               return alias;
+       }
+
+       public Boolean isConnected() {
+               if (defaultSession != null && defaultSession.isLive())
+                       return true;
+               else
+                       return false;
+       }
+}
diff --git a/org.argeo.jcr.ui.explorer/src/org/argeo/jcr/ui/explorer/model/SingleJcrNodeElem.java b/org.argeo.jcr.ui.explorer/src/org/argeo/jcr/ui/explorer/model/SingleJcrNodeElem.java
new file mode 100644 (file)
index 0000000..7b588f8
--- /dev/null
@@ -0,0 +1,108 @@
+/*
+ * Copyright (C) 2007-2012 Argeo GmbH
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *         http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.argeo.jcr.ui.explorer.model;
+
+import javax.jcr.Node;
+import javax.jcr.NodeIterator;
+import javax.jcr.RepositoryException;
+import javax.jcr.Workspace;
+
+import org.argeo.ArgeoException;
+import org.argeo.eclipse.ui.TreeParent;
+
+/**
+ * UI Tree component. Wraps a node of a JCR {@link Workspace}. It also keeps a
+ * reference to its parent node that can either be a {@link WorkspaceElem}, a
+ * {@link SingleJcrNodeElem} or null if the node is "mounted" as the root of the UI
+ * tree.
+ */
+
+public class SingleJcrNodeElem extends TreeParent {
+
+       private final Node node;
+       private String alias = null;
+
+       // keeps a local reference to the node's name to avoid exception when the
+       // session is lost
+       // private final String name;
+
+       /** Creates a new UiNode in the UI Tree */
+       public SingleJcrNodeElem(TreeParent parent, Node node, String name) {
+               super(name);
+               setParent(parent);
+               this.node = node;
+       }
+
+       /**
+        * Creates a new UiNode in the UI Tree, keeping a reference to the alias of
+        * the corresponding repository in the current UI environment. It is useful
+        * to be able to mount nodes as roots of the UI tree.
+        */
+       public SingleJcrNodeElem(TreeParent parent, Node node, String name, String alias) {
+               super(name);
+               setParent(parent);
+               this.node = node;
+               this.alias = alias;
+       }
+
+       /** returns the node wrapped by the current Ui object */
+       public Node getNode() {
+               return node;
+       }
+
+       protected String getRepositoryAlias() {
+               return alias;
+       }
+
+       /**
+        * Override normal behavior to initialize children only when first requested
+        */
+       @Override
+       public synchronized Object[] getChildren() {
+               if (isLoaded()) {
+                       return super.getChildren();
+               } else {
+                       // initialize current object
+                       try {
+                               NodeIterator ni = node.getNodes();
+                               while (ni.hasNext()) {
+                                       Node curNode = ni.nextNode();
+                                       addChild(new SingleJcrNodeElem(this, curNode, curNode.getName()));
+                               }
+                               return super.getChildren();
+                       } catch (RepositoryException re) {
+                               throw new ArgeoException(
+                                               "Unexcpected error while initializing children SingleJcrNode",
+                                               re);
+                       }
+               }
+       }
+
+       @Override
+       public boolean hasChildren() {
+               try {
+                       if (node.getSession().isLive())
+                               return node.hasNodes();
+                       else
+                               return false;
+               } catch (RepositoryException re) {
+                       throw new ArgeoException(
+                                       "Unexpected error while checking children node existence",
+                                       re);
+               }
+       }
+
+}
diff --git a/org.argeo.jcr.ui.explorer/src/org/argeo/jcr/ui/explorer/model/WorkspaceElem.java b/org.argeo.jcr.ui.explorer/src/org/argeo/jcr/ui/explorer/model/WorkspaceElem.java
new file mode 100644 (file)
index 0000000..bb9b69c
--- /dev/null
@@ -0,0 +1,130 @@
+/*
+ * Copyright (C) 2007-2012 Argeo GmbH
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *         http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.argeo.jcr.ui.explorer.model;
+
+import javax.jcr.Node;
+import javax.jcr.NodeIterator;
+import javax.jcr.RepositoryException;
+import javax.jcr.Session;
+import javax.jcr.Workspace;
+
+import org.argeo.ArgeoException;
+import org.argeo.eclipse.ui.TreeParent;
+import org.argeo.jcr.JcrUtils;
+
+/**
+ * UI Tree component. Wraps the root node of a JCR {@link Workspace}. It also
+ * keeps a reference to its parent {@link RepositoryElem}, to be able to
+ * retrieve alias of the current used repository
+ */
+public class WorkspaceElem extends TreeParent {
+       private Session session = null;
+
+       public WorkspaceElem(RepositoryElem parent, String name) {
+               this(parent, name, null);
+       }
+
+       public WorkspaceElem(RepositoryElem parent, String name, Session session) {
+               super(name);
+               this.session = session;
+               setParent(parent);
+       }
+
+       public Session getSession() {
+               return session;
+       }
+
+       public Node getRootNode() {
+               try {
+                       if (session != null)
+                               return session.getRootNode();
+                       else
+                               return null;
+               } catch (RepositoryException e) {
+                       throw new ArgeoException("Cannot get root node of workspace "
+                                       + getName(), e);
+               }
+       }
+
+       public void login() {
+               try {
+                       session = ((RepositoryElem) getParent()).repositoryLogin(getName());
+               } catch (RepositoryException e) {
+                       throw new ArgeoException("Cannot connect to repository "
+                                       + getName(), e);
+               }
+       }
+
+       public Boolean isConnected() {
+               if (session != null && session.isLive())
+                       return true;
+               else
+                       return false;
+       }
+
+       @Override
+       public synchronized void dispose() {
+               logout();
+               super.dispose();
+       }
+
+       /** Logouts the session, does not nothing if there is no live session. */
+       public void logout() {
+               clearChildren();
+               JcrUtils.logoutQuietly(session);
+       }
+
+       @Override
+       public boolean hasChildren() {
+               try {
+                       if (isConnected())
+                               return session.getRootNode().hasNodes();
+                       else
+                               return false;
+               } catch (RepositoryException re) {
+                       throw new ArgeoException(
+                                       "Unexpected error while checking children node existence",
+                                       re);
+               }
+       }
+
+       /** Override normal behaviour to initialize display of the workspace */
+       @Override
+       public synchronized Object[] getChildren() {
+               if (isLoaded()) {
+                       return super.getChildren();
+               } else {
+                       // initialize current object
+                       try {
+                               Node rootNode;
+                               if (session == null)
+                                       return null;
+                               else
+                                       rootNode = session.getRootNode();
+                               NodeIterator ni = rootNode.getNodes();
+                               while (ni.hasNext()) {
+                                       Node node = ni.nextNode();
+                                       addChild(new SingleJcrNodeElem(this, node, node.getName()));
+                               }
+                               return super.getChildren();
+                       } catch (RepositoryException e) {
+                               throw new ArgeoException(
+                                               "Cannot initialize WorkspaceNode UI object."
+                                                               + getName(), e);
+                       }
+               }
+       }
+}
diff --git a/org.argeo.jcr.ui.explorer/src/org/argeo/jcr/ui/explorer/providers/FullVersioningTreeContentProvider.java b/org.argeo.jcr.ui.explorer/src/org/argeo/jcr/ui/explorer/providers/FullVersioningTreeContentProvider.java
new file mode 100644 (file)
index 0000000..736a5aa
--- /dev/null
@@ -0,0 +1,115 @@
+/*
+ * Copyright (C) 2007-2012 Argeo GmbH
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *         http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.argeo.jcr.ui.explorer.providers;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.jcr.Node;
+import javax.jcr.RepositoryException;
+import javax.jcr.nodetype.NodeType;
+import javax.jcr.version.Version;
+import javax.jcr.version.VersionHistory;
+import javax.jcr.version.VersionIterator;
+import javax.jcr.version.VersionManager;
+
+import org.argeo.ArgeoException;
+import org.eclipse.jface.viewers.ITreeContentProvider;
+import org.eclipse.jface.viewers.Viewer;
+
+/**
+ * Implementation of the {@code ITreeContentProvider} in order to display some
+ * version informations of a JCR full versionable node in a tree like structure
+ * 
+ */
+public class FullVersioningTreeContentProvider implements ITreeContentProvider {
+       // private Node rootNode;
+       // private ItemComparator itemComparator = new ItemComparator();
+
+       /**
+        * Sends back the first level of the Tree. input element must be a single
+        * node object
+        */
+       public Object[] getElements(Object inputElement) {
+               try {
+                       Node rootNode = (Node) inputElement;
+                       String curPath = rootNode.getPath();
+                       VersionManager vm = rootNode.getSession().getWorkspace()
+                                       .getVersionManager();
+
+                       VersionHistory vh = vm.getVersionHistory(curPath);
+                       List<Version> result = new ArrayList<Version>();
+                       VersionIterator vi = vh.getAllLinearVersions();
+
+                       while (vi.hasNext()) {
+                               result.add(vi.nextVersion());
+                       }
+                       return result.toArray();
+               } catch (RepositoryException re) {
+                       throw new ArgeoException(
+                                       "Unexpected error while getting version elements", re);
+               }
+       }
+
+       public Object[] getChildren(Object parentElement) {
+               try {
+                       if (parentElement instanceof Version) {
+                               List<Node> tmp = new ArrayList<Node>();
+                               tmp.add(((Version) parentElement).getFrozenNode());
+                               return tmp.toArray();
+                       }
+               } catch (RepositoryException re) {
+                       throw new ArgeoException("Unexpected error while getting child "
+                                       + "node for version element", re);
+               }
+               return null;
+       }
+
+       public Object getParent(Object element) {
+               try {
+                       // this will not work in a simpleVersionning environment, parent is
+                       // not a node.
+                       if (element instanceof Node
+                                       && ((Node) element).isNodeType(NodeType.NT_FROZEN_NODE)) {
+                               Node node = (Node) element;
+                               return node.getParent();
+                       } else
+                               return null;
+               } catch (RepositoryException e) {
+                       return null;
+               }
+       }
+
+       public boolean hasChildren(Object element) {
+               try {
+                       if (element instanceof Version)
+                               return true;
+                       else if (element instanceof Node)
+                               return ((Node) element).hasNodes();
+                       else
+                               return false;
+               } catch (RepositoryException e) {
+                       throw new ArgeoException("Cannot check children of " + element, e);
+               }
+       }
+
+       public void dispose() {
+       }
+
+       public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
+       }
+
+}
diff --git a/org.argeo.jcr.ui.explorer/src/org/argeo/jcr/ui/explorer/providers/PropertyLabelProvider.java b/org.argeo.jcr.ui.explorer/src/org/argeo/jcr/ui/explorer/providers/PropertyLabelProvider.java
new file mode 100644 (file)
index 0000000..decbe63
--- /dev/null
@@ -0,0 +1,116 @@
+/*
+ * Copyright (C) 2007-2012 Argeo GmbH
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *         http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.argeo.jcr.ui.explorer.providers;
+
+import java.text.DateFormat;
+import java.text.SimpleDateFormat;
+
+import javax.jcr.Property;
+import javax.jcr.PropertyType;
+import javax.jcr.RepositoryException;
+import javax.jcr.Value;
+
+import org.argeo.ArgeoException;
+import org.argeo.jcr.JcrUtils;
+import org.argeo.jcr.ui.explorer.JcrExplorerConstants;
+import org.eclipse.jface.viewers.ColumnLabelProvider;
+import org.eclipse.jface.viewers.ViewerCell;
+
+public class PropertyLabelProvider extends ColumnLabelProvider implements
+               JcrExplorerConstants {
+
+       // To be able to change column order easily
+       public static final int COLUMN_PROPERTY = 0;
+       public static final int COLUMN_VALUE = 1;
+       public static final int COLUMN_ATTRIBUTES = 2;
+
+       // Utils
+       protected DateFormat timeFormatter = new SimpleDateFormat(DATE_TIME_FORMAT);
+
+       public void update(ViewerCell cell) {
+               Object element = cell.getElement();
+               cell.setText(getColumnText(element, cell.getColumnIndex()));
+               // Image image = getImage(element);
+               // cell.setImage(image);
+               // cell.setBackground(getBackground(element));
+               // cell.setForeground(getForeground(element));
+               // cell.setFont(getFont(element));
+       }
+
+       public String getColumnText(Object element, int columnIndex) {
+               try {
+                       if (element instanceof Property) {
+                               Property prop = (Property) element;
+                               if (prop.isMultiple()) {
+                                       switch (columnIndex) {
+                                       case COLUMN_PROPERTY:
+                                               return prop.getName();
+                                       case COLUMN_VALUE:
+                                               // Corresponding values are listed on children
+                                               return "";
+                                       case COLUMN_ATTRIBUTES:
+                                               return JcrUtils.getPropertyDefinitionAsString(prop);
+                                       }
+                               } else {
+                                       switch (columnIndex) {
+                                       case COLUMN_PROPERTY:
+                                               return prop.getName();
+                                       case COLUMN_VALUE:
+                                               return formatValueAsString(prop.getValue());
+                                       case COLUMN_ATTRIBUTES:
+                                               return JcrUtils.getPropertyDefinitionAsString(prop);
+                                       }
+                               }
+                       } else if (element instanceof Value) {
+                               Value val = (Value) element;
+
+                               switch (columnIndex) {
+                               case COLUMN_PROPERTY:
+                                       // Nothing to show
+                                       return "";
+                               case COLUMN_VALUE:
+                                       return formatValueAsString(val);
+                               case COLUMN_ATTRIBUTES:
+                                       // Corresponding attributes are listed on the parent
+                                       return "";
+                               }
+                       }
+
+               } catch (RepositoryException re) {
+                       throw new ArgeoException(
+                                       "Unexepected error while getting property values", re);
+               }
+               return null;
+       }
+
+       private String formatValueAsString(Value value) {
+               // TODO enhance this method
+               try {
+                       String strValue;
+
+                       if (value.getType() == PropertyType.BINARY)
+                               strValue = "<binary>";
+                       else if (value.getType() == PropertyType.DATE)
+                               strValue = timeFormatter.format(value.getDate().getTime());
+                       else
+                               strValue = value.getString();
+                       return strValue;
+               } catch (RepositoryException e) {
+                       throw new ArgeoException("unexpected error while formatting value",
+                                       e);
+               }
+       }
+}
diff --git a/org.argeo.jcr.ui.explorer/src/org/argeo/jcr/ui/explorer/providers/SingleNodeAsTreeContentProvider.java b/org.argeo.jcr.ui.explorer/src/org/argeo/jcr/ui/explorer/providers/SingleNodeAsTreeContentProvider.java
new file mode 100644 (file)
index 0000000..8c69b6b
--- /dev/null
@@ -0,0 +1,106 @@
+/*
+ * Copyright (C) 2007-2012 Argeo GmbH
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *         http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.argeo.jcr.ui.explorer.providers;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+import javax.jcr.Node;
+import javax.jcr.NodeIterator;
+import javax.jcr.RepositoryException;
+
+import org.argeo.ArgeoException;
+import org.argeo.eclipse.ui.jcr.utils.JcrItemsComparator;
+import org.eclipse.jface.viewers.ITreeContentProvider;
+import org.eclipse.jface.viewers.Viewer;
+
+/**
+ * Implementation of the {@code ITreeContentProvider} in order to display a
+ * single JCR node and its children in a tree like structure
+ * 
+ */
+public class SingleNodeAsTreeContentProvider implements ITreeContentProvider {
+       // private Node rootNode;
+       private JcrItemsComparator itemComparator = new JcrItemsComparator();
+
+       /**
+        * Sends back the first level of the Tree. input element must be a single
+        * node object
+        */
+       public Object[] getElements(Object inputElement) {
+               try {
+                       Node rootNode = (Node) inputElement;
+                       List<Node> result = new ArrayList<Node>();
+                       NodeIterator ni = rootNode.getNodes();
+                       while (ni.hasNext()) {
+                               result.add(ni.nextNode());
+                       }
+
+                       return result.toArray();
+               } catch (RepositoryException re) {
+                       throw new ArgeoException(
+                                       "Unexpected error while getting child nodes for children editor page ",
+                                       re);
+               }
+       }
+
+       public Object[] getChildren(Object parentElement) {
+               return childrenNodes((Node) parentElement);
+       }
+
+       public Object getParent(Object element) {
+               try {
+                       Node node = (Node) element;
+                       if (!node.getPath().equals("/"))
+                               return node.getParent();
+                       else
+                               return null;
+               } catch (RepositoryException e) {
+                       return null;
+               }
+       }
+
+       public boolean hasChildren(Object element) {
+               try {
+                       return ((Node) element).hasNodes();
+               } catch (RepositoryException e) {
+                       throw new ArgeoException("Cannot check children of " + element, e);
+               }
+       }
+
+       public void dispose() {
+       }
+
+       public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
+       }
+
+       protected Object[] childrenNodes(Node parentNode) {
+               try {
+                       List<Node> children = new ArrayList<Node>();
+                       NodeIterator nit = parentNode.getNodes();
+                       while (nit.hasNext()) {
+                               Node node = nit.nextNode();
+                               children.add(node);
+                       }
+                       Node[] arr = children.toArray(new Node[children.size()]);
+                       Arrays.sort(arr, itemComparator);
+                       return arr;
+               } catch (RepositoryException e) {
+                       throw new ArgeoException("Cannot list children of " + parentNode, e);
+               }
+       }
+}
diff --git a/org.argeo.jcr.ui.explorer/src/org/argeo/jcr/ui/explorer/providers/VersionLabelProvider.java b/org.argeo.jcr.ui.explorer/src/org/argeo/jcr/ui/explorer/providers/VersionLabelProvider.java
new file mode 100644 (file)
index 0000000..69b35eb
--- /dev/null
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2007-2012 Argeo GmbH
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *         http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.argeo.jcr.ui.explorer.providers;
+
+import javax.jcr.Node;
+import javax.jcr.RepositoryException;
+import javax.jcr.version.Version;
+
+import org.argeo.ArgeoException;
+import org.eclipse.jface.viewers.ColumnLabelProvider;
+
+/**
+ * simple wrapping of the ColumnLabelProvider class to provide text display in
+ * order to build a tree for version. The Get text method does not assume that
+ * Version extends Node class to respect JCR 2.0 specification
+ * 
+ */
+public class VersionLabelProvider extends ColumnLabelProvider {
+
+       public String getText(Object element) {
+               try {
+                       if (element instanceof Version) {
+                               Version version = (Version) element;
+                               return version.getName();
+                       } else if (element instanceof Node) {
+                               return ((Node) element).getName();
+                       }
+               } catch (RepositoryException re) {
+                       throw new ArgeoException(
+                                       "Unexpected error while getting element name", re);
+               }
+               return super.getText(element);
+       }
+}
diff --git a/org.argeo.jcr.ui.explorer/src/org/argeo/jcr/ui/explorer/utils/GenericNodeDoubleClickListener.java b/org.argeo.jcr.ui.explorer/src/org/argeo/jcr/ui/explorer/utils/GenericNodeDoubleClickListener.java
new file mode 100644 (file)
index 0000000..0f93450
--- /dev/null
@@ -0,0 +1,109 @@
+/*
+ * Copyright (C) 2007-2012 Argeo GmbH
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *         http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.argeo.jcr.ui.explorer.utils;
+
+import javax.jcr.Node;
+import javax.jcr.RepositoryException;
+import javax.jcr.nodetype.NodeType;
+
+import org.argeo.ArgeoException;
+import org.argeo.eclipse.ui.jcr.utils.JcrFileProvider;
+import org.argeo.eclipse.ui.specific.FileHandler;
+import org.argeo.jcr.ui.explorer.JcrExplorerPlugin;
+import org.argeo.jcr.ui.explorer.editors.GenericNodeEditor;
+import org.argeo.jcr.ui.explorer.editors.GenericNodeEditorInput;
+import org.argeo.jcr.ui.explorer.model.RepositoryElem;
+import org.argeo.jcr.ui.explorer.model.SingleJcrNodeElem;
+import org.argeo.jcr.ui.explorer.model.WorkspaceElem;
+import org.eclipse.jface.viewers.DoubleClickEvent;
+import org.eclipse.jface.viewers.IDoubleClickListener;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.jface.viewers.TreeViewer;
+import org.eclipse.ui.PartInitException;
+
+/**
+ * Centralizes the management of double click on a NodeTreeViewer
+ */
+public class GenericNodeDoubleClickListener implements IDoubleClickListener {
+
+       // private final static Log log = LogFactory
+       // .getLog(GenericNodeDoubleClickListener.class);
+
+       private TreeViewer nodeViewer;
+       private JcrFileProvider jfp;
+       private FileHandler fileHandler;
+
+       public GenericNodeDoubleClickListener(TreeViewer nodeViewer) {
+               this.nodeViewer = nodeViewer;
+               jfp = new JcrFileProvider();
+               // Commented out. see https://www.argeo.org/bugzilla/show_bug.cgi?id=188
+               fileHandler = null;
+               // fileHandler = new FileHandler(jfp);
+       }
+
+       public void doubleClick(DoubleClickEvent event) {
+               if (event.getSelection() == null || event.getSelection().isEmpty())
+                       return;
+               Object obj = ((IStructuredSelection) event.getSelection())
+                               .getFirstElement();
+               if (obj instanceof RepositoryElem) {
+                       RepositoryElem rpNode = (RepositoryElem) obj;
+                       if (!rpNode.isConnected()) {
+                               rpNode.login();
+                               nodeViewer.refresh(obj);
+                       }
+                       // else do nothing
+               } else if (obj instanceof WorkspaceElem) {
+                       WorkspaceElem wn = (WorkspaceElem) obj;
+                       if (wn.isConnected())
+                               wn.logout();
+                       else
+                               wn.login();
+                       nodeViewer.refresh(obj);
+               } else if (obj instanceof SingleJcrNodeElem) {
+                       SingleJcrNodeElem sjn = (SingleJcrNodeElem) obj;
+                       Node node = sjn.getNode();
+                       try {
+                               if (node.isNodeType(NodeType.NT_FILE)) {
+                                       // double click on a file node triggers its opening
+                                       String name = node.getName();
+                                       String id = node.getIdentifier();
+
+                                       // For the file provider to be able to browse the
+                                       // various
+                                       // repository.
+                                       // TODO : enhanced that.
+                                       // ITreeContentProvider itcp = (ITreeContentProvider)
+                                       // nodeViewer
+                                       // .getContentProvider();
+                                       jfp.setReferenceNode(node);
+                                       if (fileHandler != null)
+                                               fileHandler.openFile(name, id);
+                               }
+                               GenericNodeEditorInput gnei = new GenericNodeEditorInput(node);
+                               JcrExplorerPlugin.getDefault().getWorkbench()
+                                               .getActiveWorkbenchWindow().getActivePage()
+                                               .openEditor(gnei, GenericNodeEditor.ID);
+                       } catch (RepositoryException re) {
+                               throw new ArgeoException(
+                                               "Repository error while getting node info", re);
+                       } catch (PartInitException pie) {
+                               throw new ArgeoException(
+                                               "Unexepected exception while opening node editor", pie);
+                       }
+               }
+       }
+}
diff --git a/org.argeo.jcr.ui.explorer/src/org/argeo/jcr/ui/explorer/utils/JcrUiUtils.java b/org.argeo.jcr.ui.explorer/src/org/argeo/jcr/ui/explorer/utils/JcrUiUtils.java
new file mode 100644 (file)
index 0000000..ca32113
--- /dev/null
@@ -0,0 +1,179 @@
+/*
+ * Copyright (C) 2007-2012 Argeo GmbH
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *         http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.argeo.jcr.ui.explorer.utils;
+
+import javax.jcr.Node;
+import javax.jcr.RepositoryException;
+
+import org.argeo.ArgeoException;
+import org.argeo.eclipse.ui.TreeParent;
+import org.argeo.jcr.ui.explorer.model.RepositoriesElem;
+import org.argeo.jcr.ui.explorer.model.RepositoryElem;
+import org.argeo.jcr.ui.explorer.model.SingleJcrNodeElem;
+import org.argeo.jcr.ui.explorer.model.WorkspaceElem;
+
+/** Centralizes some useful methods to build UIs with JCR */
+public class JcrUiUtils {
+
+       /** Insure that the UI component is not stale, refresh if needed */
+       public static void forceRefreshIfNeeded(TreeParent element) {
+               Node curNode = null;
+
+               boolean doRefresh = false;
+
+               try {
+                       if (element instanceof SingleJcrNodeElem) {
+                               curNode = ((SingleJcrNodeElem) element).getNode();
+                       } else if (element instanceof WorkspaceElem) {
+                               curNode = ((WorkspaceElem) element).getRootNode();
+                       }
+
+                       if (curNode != null
+                                       && element.getChildren().length != curNode.getNodes()
+                                                       .getSize())
+                               doRefresh = true;
+                       else if (element instanceof RepositoryElem) {
+                               RepositoryElem rn = (RepositoryElem) element;
+                               if (rn.isConnected()) {
+                                       String[] wkpNames = rn.getAccessibleWorkspaceNames();
+                                       if (element.getChildren().length != wkpNames.length)
+                                               doRefresh = true;
+                               }
+                       } else if (element instanceof RepositoriesElem) {
+                               doRefresh = true;
+                               // Always force refresh for RepositoriesElem : the condition
+                               // below does not take remote repository into account and it is
+                               // not trivial to do so.
+
+                               // RepositoriesElem rn = (RepositoriesElem) element;
+                               // if (element.getChildren().length !=
+                               // rn.getRepositoryRegister()
+                               // .getRepositories().size())
+                               // doRefresh = true;
+                       }
+                       if (doRefresh) {
+                               element.clearChildren();
+                               element.getChildren();
+                       }
+               } catch (RepositoryException re) {
+                       throw new ArgeoException(
+                                       "Unexpected error while synchronising the UI with the JCR repository",
+                                       re);
+               }
+       }
+
+       /**
+        * Insure that a model element is inline with the underlying data by
+        * cleaning the corresponding subtree and building it again.
+        */
+       public static void forceRebuild(TreeParent element) {
+               // TODO implement this method if needed.
+       }
+       /**
+        * Workaround to get the alias of the repository that contains the given
+        * element. As we cannot browse the UI tree upward we recursively browse it
+        * downward until we find the given element
+        * */
+       // public static String getRepositoryAliasFromITreeElement(
+       // NodeContentProvider ncp, Object element) {
+       // RepositoryNode repositoryNode = null;
+       // if (element instanceof RepositoryNode)
+       // return ((RepositoryNode) element).getName();
+       // else if (element instanceof RepositoryRegister)
+       // throw new ArgeoException(
+       // "Cannot get alias for a repository register");
+       //
+       // // Get root elements
+       // Object[] elements = ncp.getElements(null);
+       //
+       // try {
+       // for (int i = 0; i < elements.length; i++) {
+       // if (elements[i] instanceof Node) {
+       // Node curNode = (Node) elements[i];
+       // if (curNode.isNodeType(ArgeoTypes.ARGEO_USER_HOME)) {
+       // // Do nothing, we'll find the node in the "normal" tree
+       // // and
+       // // get corresponding alias this way round
+       // } else
+       // throw new ArgeoException(
+       // "Normal nodes should not be at the root of NodeTreeViewer");
+       // } else if (elements[i] instanceof RepositoryRegister) {
+       // RepositoryRegister repositoryRegister = (RepositoryRegister) elements[i];
+       // Map<String, Repository> repositories = repositoryRegister
+       // .getRepositories();
+       //
+       // for (String name : repositories.keySet()) {
+       // boolean found = isElementInCurrentTreePart(
+       // ncp,
+       // new RepositoryNode(name, repositories.get(name)),
+       // (Node) element);
+       // if (found)
+       // return name;
+       // }
+       // } else
+       // throw new ArgeoException(
+       // "Unexpected object class at the root of NodeTreeViewer");
+       // }
+       // } catch (RepositoryException re) {
+       // throw new ArgeoException(
+       // "Unexpected error while retrieving Alias name", re);
+       // }
+       // return null;
+       // }
+       //
+       // /** implements the recursivity */
+       // private static boolean isElementInCurrentTreePart(NodeContentProvider
+       // ncp,
+       // Object parentElement, NodParente searchedElement) {
+       // boolean found = false;
+       // if (parentElement instanceof WorkspaceNode) {
+       // WorkspaceNode wn = (WorkspaceNode) parentElement;
+       // Object[] children = wn.getChildren();
+       // int i = children.length - 1;
+       // while (!found && i >= 0) {
+       // found = isElementInCurrentTreePart(ncp, children[i],
+       // searchedElement);
+       // }
+       // return found;
+       // } else if (parentElement instanceof RepositoryNode) {
+       // RepositoryNode rn = (RepositoryNode) parentElement;
+       // Object[] children = rn.getChildren();
+       // int i = children.length - 1;
+       // while (!found && i >= 0) {
+       // found = isElementInCurrentTreePart(ncp, children[i],
+       // searchedElement);
+       // }
+       // return found;
+       // } else {
+       // Node node = (Node) parentElement;
+       // if (node.equals(searchedElement))
+       // return true;
+       // NodeIterator ni;
+       // try {
+       // ni = node.getNodes();
+       // while (!found && ni.hasNext()) {
+       // found = isElementInCurrentTreePart(ncp, ni.nextNode(),
+       // searchedElement);
+       // }
+       // } catch (RepositoryException e) {
+       // throw new ArgeoException("unexpected erreur while recursively"
+       // + " recovering RepositoryNode for selected object", e);
+       // }
+       //
+       // return found;
+       // }
+       // }
+}
diff --git a/org.argeo.jcr.ui.explorer/src/org/argeo/jcr/ui/explorer/utils/TreeObjectsComparator.java b/org.argeo.jcr.ui.explorer/src/org/argeo/jcr/ui/explorer/utils/TreeObjectsComparator.java
new file mode 100644 (file)
index 0000000..02450d6
--- /dev/null
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2007-2012 Argeo GmbH
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *         http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.argeo.jcr.ui.explorer.utils;
+
+import java.util.Comparator;
+
+import org.argeo.eclipse.ui.TreeParent;
+
+public class TreeObjectsComparator implements Comparator<TreeParent> {
+       public int compare(TreeParent o1, TreeParent o2) {
+               return o1.getName().compareTo(o2.getName());
+       }
+}
\ No newline at end of file
diff --git a/org.argeo.jcr.ui.explorer/src/org/argeo/jcr/ui/explorer/views/GenericJcrBrowser.java b/org.argeo.jcr.ui.explorer/src/org/argeo/jcr/ui/explorer/views/GenericJcrBrowser.java
new file mode 100644 (file)
index 0000000..f401ae8
--- /dev/null
@@ -0,0 +1,357 @@
+/*
+ * Copyright (C) 2007-2012 Argeo GmbH
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *         http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.argeo.jcr.ui.explorer.views;
+
+import java.util.List;
+
+import javax.jcr.Property;
+import javax.jcr.PropertyType;
+import javax.jcr.Repository;
+import javax.jcr.RepositoryException;
+import javax.jcr.RepositoryFactory;
+import javax.jcr.Session;
+import javax.jcr.Value;
+import javax.jcr.observation.Event;
+import javax.jcr.observation.EventListener;
+import javax.jcr.observation.ObservationManager;
+
+import org.argeo.ArgeoException;
+import org.argeo.eclipse.ui.TreeParent;
+import org.argeo.eclipse.ui.jcr.AsyncUiEventListener;
+import org.argeo.eclipse.ui.jcr.utils.NodeViewerComparer;
+import org.argeo.eclipse.ui.jcr.views.AbstractJcrBrowser;
+import org.argeo.jcr.RepositoryRegister;
+import org.argeo.jcr.ui.explorer.JcrExplorerPlugin;
+import org.argeo.jcr.ui.explorer.browser.NodeContentProvider;
+import org.argeo.jcr.ui.explorer.browser.NodeLabelProvider;
+import org.argeo.jcr.ui.explorer.browser.PropertiesContentProvider;
+import org.argeo.jcr.ui.explorer.model.SingleJcrNodeElem;
+import org.argeo.jcr.ui.explorer.utils.GenericNodeDoubleClickListener;
+import org.argeo.jcr.ui.explorer.utils.JcrUiUtils;
+import org.argeo.util.security.Keyring;
+import org.eclipse.jface.action.MenuManager;
+import org.eclipse.jface.viewers.ColumnLabelProvider;
+import org.eclipse.jface.viewers.ISelectionChangedListener;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.jface.viewers.ITreeContentProvider;
+import org.eclipse.jface.viewers.SelectionChangedEvent;
+import org.eclipse.jface.viewers.StructuredSelection;
+import org.eclipse.jface.viewers.TableViewer;
+import org.eclipse.jface.viewers.TableViewerColumn;
+import org.eclipse.jface.viewers.TreeViewer;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.custom.SashForm;
+import org.eclipse.swt.layout.FillLayout;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Menu;
+
+/**
+ * Basic View to display a sash form to browse a JCR compliant multirepository
+ * environment
+ */
+public class GenericJcrBrowser extends AbstractJcrBrowser {
+       public final static String ID = JcrExplorerPlugin.ID + ".browserView";
+       private boolean sortChildNodes = true;
+
+       /* DEPENDENCY INJECTION */
+       private Keyring keyring;
+       private RepositoryRegister repositoryRegister;
+       private RepositoryFactory repositoryFactory;
+       private Repository nodeRepository;
+       /**
+        * A session of the logged in user on the default workspace of the node
+        * repository.
+        */
+       private Session userSession;
+
+       // This page widgets
+       private TreeViewer nodesViewer;
+       private NodeContentProvider nodeContentProvider;
+       private TableViewer propertiesViewer;
+       private EventListener resultsObserver;
+
+       @Override
+       public void createPartControl(Composite parent) {
+               parent.setLayout(new FillLayout());
+               SashForm sashForm = new SashForm(parent, SWT.VERTICAL);
+               sashForm.setSashWidth(4);
+               sashForm.setLayout(new FillLayout());
+
+               // Create the tree on top of the view
+               Composite top = new Composite(sashForm, SWT.NONE);
+               GridLayout gl = new GridLayout(1, false);
+               top.setLayout(gl);
+
+               try {
+                       this.userSession = this.nodeRepository.login();
+               } catch (RepositoryException e) {
+                       throw new ArgeoException("Cannot open user session", e);
+               }
+
+               nodeContentProvider = new NodeContentProvider(userSession, keyring,
+                               repositoryRegister, repositoryFactory, sortChildNodes);
+
+               // nodes viewer
+               nodesViewer = createNodeViewer(top, nodeContentProvider);
+
+               // context menu : it is completely defined in the plugin.xml file.
+               MenuManager menuManager = new MenuManager();
+               Menu menu = menuManager.createContextMenu(nodesViewer.getTree());
+
+               nodesViewer.getTree().setMenu(menu);
+               getSite().registerContextMenu(menuManager, nodesViewer);
+               getSite().setSelectionProvider(nodesViewer);
+
+               nodesViewer.setInput(getViewSite());
+
+               // Create the property viewer on the bottom
+               Composite bottom = new Composite(sashForm, SWT.NONE);
+               bottom.setLayout(new GridLayout(1, false));
+               propertiesViewer = createPropertiesViewer(bottom);
+
+               sashForm.setWeights(getWeights());
+               nodesViewer.setComparer(new NodeViewerComparer());
+       }
+
+       @Override
+       public void refresh(Object obj) {
+               // Enable full refresh from a command when no element of the tree is
+               // selected
+               if (obj == null) {
+                       Object[] elements = nodeContentProvider.getElements(null);
+                       for (Object el : elements) {
+                               if (el instanceof TreeParent)
+                                       JcrUiUtils.forceRefreshIfNeeded((TreeParent) el);
+                               getNodeViewer().refresh(el);
+                       }
+               }
+               super.refresh(obj);
+       }
+
+       /**
+        * To be overridden to adapt size of form and result frames.
+        */
+       protected int[] getWeights() {
+               return new int[] { 70, 30 };
+       }
+
+       protected TreeViewer createNodeViewer(Composite parent,
+                       final ITreeContentProvider nodeContentProvider) {
+
+               final TreeViewer tmpNodeViewer = new TreeViewer(parent, SWT.MULTI);
+
+               tmpNodeViewer.getTree().setLayoutData(
+                               new GridData(SWT.FILL, SWT.FILL, true, true));
+
+               tmpNodeViewer.setContentProvider(nodeContentProvider);
+               tmpNodeViewer.setLabelProvider(new NodeLabelProvider());
+               tmpNodeViewer
+                               .addSelectionChangedListener(new ISelectionChangedListener() {
+                                       public void selectionChanged(SelectionChangedEvent event) {
+                                               if (!event.getSelection().isEmpty()) {
+                                                       IStructuredSelection sel = (IStructuredSelection) event
+                                                                       .getSelection();
+                                                       Object firstItem = sel.getFirstElement();
+                                                       if (firstItem instanceof SingleJcrNodeElem)
+                                                               propertiesViewer
+                                                                               .setInput(((SingleJcrNodeElem) firstItem)
+                                                                                               .getNode());
+                                               } else {
+                                                       propertiesViewer.setInput(getViewSite());
+                                               }
+                                       }
+                               });
+
+               resultsObserver = new TreeObserver(tmpNodeViewer.getTree().getDisplay());
+               if (keyring != null)
+                       try {
+                               ObservationManager observationManager = userSession
+                                               .getWorkspace().getObservationManager();
+                               observationManager.addEventListener(resultsObserver,
+                                               Event.PROPERTY_ADDED | Event.PROPERTY_CHANGED, "/",
+                                               true, null, null, false);
+                       } catch (RepositoryException e) {
+                               throw new ArgeoException("Cannot register listeners", e);
+                       }
+
+               tmpNodeViewer
+                               .addDoubleClickListener(new GenericNodeDoubleClickListener(
+                                               tmpNodeViewer));
+               return tmpNodeViewer;
+       }
+
+       protected TableViewer createPropertiesViewer(Composite parent) {
+               propertiesViewer = new TableViewer(parent);
+               propertiesViewer.getTable().setLayoutData(
+                               new GridData(SWT.FILL, SWT.FILL, true, true));
+               propertiesViewer.getTable().setHeaderVisible(true);
+               propertiesViewer.setContentProvider(new PropertiesContentProvider());
+               TableViewerColumn col = new TableViewerColumn(propertiesViewer,
+                               SWT.NONE);
+               col.getColumn().setText("Name");
+               col.getColumn().setWidth(200);
+               col.setLabelProvider(new ColumnLabelProvider() {
+                       public String getText(Object element) {
+                               try {
+                                       return ((Property) element).getName();
+                               } catch (RepositoryException e) {
+                                       throw new ArgeoException(
+                                                       "Unexpected exception in label provider", e);
+                               }
+                       }
+               });
+               col = new TableViewerColumn(propertiesViewer, SWT.NONE);
+               col.getColumn().setText("Value");
+               col.getColumn().setWidth(400);
+               col.setLabelProvider(new ColumnLabelProvider() {
+                       public String getText(Object element) {
+                               try {
+                                       Property property = (Property) element;
+                                       if (property.getType() == PropertyType.BINARY)
+                                               return "<binary>";
+                                       else if (property.isMultiple()) {
+                                               StringBuffer buf = new StringBuffer("[");
+                                               Value[] values = property.getValues();
+                                               for (int i = 0; i < values.length; i++) {
+                                                       if (i != 0)
+                                                               buf.append(", ");
+                                                       buf.append(values[i].getString());
+                                               }
+                                               buf.append(']');
+                                               return buf.toString();
+                                       } else
+                                               return property.getValue().getString();
+                               } catch (RepositoryException e) {
+                                       throw new ArgeoException(
+                                                       "Unexpected exception in label provider", e);
+                               }
+                       }
+               });
+               col = new TableViewerColumn(propertiesViewer, SWT.NONE);
+               col.getColumn().setText("Type");
+               col.getColumn().setWidth(200);
+               col.setLabelProvider(new ColumnLabelProvider() {
+                       public String getText(Object element) {
+                               try {
+                                       return PropertyType.nameFromValue(((Property) element)
+                                                       .getType());
+                               } catch (RepositoryException e) {
+                                       throw new ArgeoException(
+                                                       "Unexpected exception in label provider", e);
+                               }
+                       }
+               });
+               propertiesViewer.setInput(getViewSite());
+               return propertiesViewer;
+       }
+
+       @Override
+       public void dispose() {
+               super.dispose();
+       }
+
+       @Override
+       protected TreeViewer getNodeViewer() {
+               return nodesViewer;
+       }
+
+       /**
+        * Resets the tree content provider
+        * 
+        * @param sortChildNodes
+        *            if true the content provider will use a comparer to sort nodes
+        *            that might slow down the display
+        * */
+       public void setSortChildNodes(boolean sortChildNodes) {
+               this.sortChildNodes = sortChildNodes;
+               ((NodeContentProvider) nodesViewer.getContentProvider())
+                               .setSortChildren(sortChildNodes);
+               nodesViewer.setInput(getViewSite());
+       }
+
+       /** Notifies the current view that a node has been added */
+       public void nodeAdded(TreeParent parentNode) {
+               // insure that Ui objects have been correctly created:
+               JcrUiUtils.forceRefreshIfNeeded(parentNode);
+               getNodeViewer().refresh(parentNode);
+               getNodeViewer().expandToLevel(parentNode, 1);
+       }
+
+       /** Notifies the current view that a node has been removed */
+       public void nodeRemoved(TreeParent parentNode) {
+               IStructuredSelection newSel = new StructuredSelection(parentNode);
+               getNodeViewer().setSelection(newSel, true);
+               // Force refresh
+               IStructuredSelection tmpSel = (IStructuredSelection) getNodeViewer()
+                               .getSelection();
+               getNodeViewer().refresh(tmpSel.getFirstElement());
+       }
+
+       class TreeObserver extends AsyncUiEventListener {
+
+               public TreeObserver(Display display) {
+                       super(display);
+               }
+
+               @Override
+               protected Boolean willProcessInUiThread(List<Event> events)
+                               throws RepositoryException {
+                       for (Event event : events) {
+                               if (getLog().isTraceEnabled())
+                                       getLog().debug("Received event " + event);
+                               String path = event.getPath();
+                               int index = path.lastIndexOf('/');
+                               String propertyName = path.substring(index + 1);
+                               if (getLog().isTraceEnabled())
+                                       getLog().debug("Concerned property " + propertyName);
+                       }
+                       return false;
+               }
+
+               protected void onEventInUiThread(List<Event> events)
+                               throws RepositoryException {
+                       if (getLog().isTraceEnabled())
+                               getLog().trace("Refresh result list");
+                       nodesViewer.refresh();
+               }
+
+       }
+
+       public boolean getSortChildNodes() {
+               return sortChildNodes;
+       }
+
+       /* DEPENDENCY INJECTION */
+       public void setRepositoryRegister(RepositoryRegister repositoryRegister) {
+               this.repositoryRegister = repositoryRegister;
+       }
+
+       public void setKeyring(Keyring keyring) {
+               this.keyring = keyring;
+       }
+
+       public void setRepositoryFactory(RepositoryFactory repositoryFactory) {
+               this.repositoryFactory = repositoryFactory;
+       }
+
+       public void setNodeRepository(Repository nodeRepository) {
+               this.nodeRepository = nodeRepository;
+       }
+
+}
diff --git a/org.argeo.jcr.ui.explorer/src/org/argeo/jcr/ui/explorer/wizards/ChangeRightsWizard.java b/org.argeo.jcr.ui.explorer/src/org/argeo/jcr/ui/explorer/wizards/ChangeRightsWizard.java
new file mode 100644 (file)
index 0000000..4381837
--- /dev/null
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2007-2012 Argeo GmbH
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *         http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.argeo.jcr.ui.explorer.wizards;
+
+import javax.jcr.RepositoryException;
+import javax.jcr.Session;
+
+import org.argeo.ArgeoException;
+import org.argeo.jcr.JcrUtils;
+import org.eclipse.jface.wizard.Wizard;
+
+/**
+ * Small wizard to manage authorizations on the root node of the current
+ * workspace
+ */
+public class ChangeRightsWizard extends Wizard {
+
+       private Session currentSession;
+       private String path;
+
+       // This page widget
+       private ChooseRightsPage page;
+
+       public ChangeRightsWizard(Session currentSession, String path) {
+               super();
+               this.currentSession = currentSession;
+               this.path = path;
+       }
+
+       @Override
+       public void addPages() {
+               try {
+                       page = new ChooseRightsPage(path);
+                       addPage(page);
+               } catch (Exception e) {
+                       throw new ArgeoException("Cannot add page to wizard ", e);
+               }
+       }
+
+       @Override
+       public boolean performFinish() {
+               if (!canFinish())
+                       return false;
+               try {
+                       JcrUtils.addPrivilege(currentSession, path, page.getGroupName(),
+                                       page.getAuthTypeStr());
+               } catch (RepositoryException re) {
+                       throw new ArgeoException(
+                                       "Unexpected error while setting privileges", re);
+               }
+               return true;
+       }
+}
diff --git a/org.argeo.jcr.ui.explorer/src/org/argeo/jcr/ui/explorer/wizards/ChooseRightsPage.java b/org.argeo.jcr.ui.explorer/src/org/argeo/jcr/ui/explorer/wizards/ChooseRightsPage.java
new file mode 100644 (file)
index 0000000..69948ce
--- /dev/null
@@ -0,0 +1,101 @@
+/*
+ * Copyright (C) 2007-2012 Argeo GmbH
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *         http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.argeo.jcr.ui.explorer.wizards;
+
+import javax.jcr.security.Privilege;
+
+import org.eclipse.jface.wizard.WizardPage;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.ModifyEvent;
+import org.eclipse.swt.events.ModifyListener;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Combo;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Text;
+
+public class ChooseRightsPage extends WizardPage implements ModifyListener {
+
+       // This page widget
+       private Text groupNameTxt;
+       private Combo authorizationCmb;
+
+       // USABLE SHORTCUTS
+       protected final static String[] validAuthType = { Privilege.JCR_READ,
+                       Privilege.JCR_WRITE, Privilege.JCR_ALL };
+
+       public ChooseRightsPage(String path) {
+               super("Main");
+               setTitle("Add privilege to " + path);
+       }
+
+       public void createControl(Composite parent) {
+               // specify subject
+               Composite composite = new Composite(parent, SWT.NONE);
+               composite.setLayout(new GridLayout(2, false));
+               Label lbl = new Label(composite, SWT.LEAD);
+               lbl.setText("Group or user name (no blank, no special chars)");
+               lbl.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, false, false));
+               groupNameTxt = new Text(composite, SWT.LEAD | SWT.BORDER);
+               groupNameTxt.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true,
+                               false));
+               if (groupNameTxt != null)
+                       groupNameTxt.addModifyListener(this);
+
+               // Choose rigths
+               new Label(composite, SWT.NONE).setText("Choose corresponding rights");
+               authorizationCmb = new Combo(composite, SWT.BORDER | SWT.V_SCROLL);
+               authorizationCmb.setItems(validAuthType);
+               GridData gd = new GridData(GridData.FILL_HORIZONTAL);
+               authorizationCmb.setLayoutData(gd);
+
+               authorizationCmb.select(0);
+
+               // Compulsory
+               setControl(composite);
+       }
+
+       protected String getGroupName() {
+               return groupNameTxt.getText();
+       }
+
+       protected String getAuthTypeStr() {
+               return authorizationCmb.getItem(authorizationCmb.getSelectionIndex());
+       }
+
+       public void modifyText(ModifyEvent event) {
+               String message = checkComplete();
+               if (message != null)
+                       setMessage(message, WizardPage.ERROR);
+               else {
+                       setMessage("Complete", WizardPage.INFORMATION);
+                       setPageComplete(true);
+               }
+       }
+
+       /** @return error message or null if complete */
+       protected String checkComplete() {
+               String groupStr = groupNameTxt.getText();
+               if (groupStr == null || "".equals(groupStr))
+                       return "Please enter the name of the corresponding group.";
+               // Remove regexp check for the time being.
+               // else if (!match(groupStr))
+               // return
+               // "Please use only alphanumerical chars for the short technical name.";
+               return null;
+       }
+}
diff --git a/org.argeo.jcr.ui.explorer/src/org/argeo/jcr/ui/explorer/wizards/ImportFileSystemWizard.java b/org.argeo.jcr.ui.explorer/src/org/argeo/jcr/ui/explorer/wizards/ImportFileSystemWizard.java
new file mode 100644 (file)
index 0000000..127c2cd
--- /dev/null
@@ -0,0 +1,237 @@
+/*
+ * Copyright (C) 2007-2012 Argeo GmbH
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *         http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.argeo.jcr.ui.explorer.wizards;
+
+import java.io.File;
+import java.io.FileInputStream;
+
+import javax.jcr.Binary;
+import javax.jcr.Node;
+import javax.jcr.Property;
+import javax.jcr.nodetype.NodeType;
+
+import org.apache.commons.io.FileUtils;
+import org.apache.commons.io.IOUtils;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.argeo.ArgeoException;
+import org.argeo.eclipse.ui.ErrorFeedback;
+import org.argeo.eclipse.ui.specific.ImportToServerWizardPage;
+import org.argeo.eclipse.ui.specific.UploadFileWizardPage;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.jface.dialogs.MessageDialog;
+import org.eclipse.jface.operation.IRunnableWithProgress;
+import org.eclipse.jface.wizard.Wizard;
+
+public class ImportFileSystemWizard extends Wizard {
+       private final static Log log = LogFactory
+                       .getLog(ImportFileSystemWizard.class);
+
+       private UploadFileWizardPage importPage;
+       private final Node folder;
+
+       public ImportFileSystemWizard(Node folder) {
+               this.folder = folder;
+               setWindowTitle("Import from file system");
+       }
+
+       @Override
+       public void addPages() {
+               importPage = new UploadFileWizardPage();
+               addPage(importPage);
+               setNeedsProgressMonitor(importPage.getNeedsProgressMonitor());
+       }
+
+       /**
+        * Called when the user click on 'Finish' in the wizard. The real upload to
+        * the JCR repository is done here.
+        */
+       @Override
+       public boolean performFinish() {
+
+               // Initialization
+               final String objectType = importPage.getObjectType();
+               final String objectPath = importPage.getObjectPath();
+
+               // We do not display a progress bar for one file only
+               if (ImportToServerWizardPage.FILE_ITEM_TYPE.equals(objectType)) {
+                       // In Rap we must force the "real" upload of the file
+                       importPage.performFinish();
+                       try {
+                               Node fileNode = folder.addNode(importPage.getObjectName(),
+                                               NodeType.NT_FILE);
+                               Node resNode = fileNode.addNode(Property.JCR_CONTENT,
+                                               NodeType.NT_RESOURCE);
+                               Binary binary = null;
+                               try {
+                                       binary = folder.getSession().getValueFactory()
+                                                       .createBinary(importPage.getFileInputStream());
+                                       resNode.setProperty(Property.JCR_DATA, binary);
+                               } finally {
+                                       if (binary != null)
+                                               binary.dispose();
+                                       IOUtils.closeQuietly(importPage.getFileInputStream());
+                               }
+                               folder.getSession().save();
+                       } catch (Exception e) {
+                               e.printStackTrace();
+                               return false;
+                       }
+                       return true;
+               } else if (ImportToServerWizardPage.FOLDER_ITEM_TYPE.equals(objectType)) {
+                       if (objectPath == null || !new File(objectPath).exists()) {
+                               ErrorFeedback.show("Directory " + objectPath
+                                               + " does not exist");
+                               return false;
+                       }
+
+                       Boolean failed = false;
+                       final File dir = new File(objectPath).getAbsoluteFile();
+                       final Long sizeB = directorySize(dir, 0l);
+                       final Stats stats = new Stats();
+                       Long begin = System.currentTimeMillis();
+                       try {
+                               getContainer().run(true, true, new IRunnableWithProgress() {
+                                       public void run(IProgressMonitor monitor) {
+                                               try {
+                                                       Integer sizeKB = (int) (sizeB / FileUtils.ONE_KB);
+                                                       monitor.beginTask("", sizeKB);
+                                                       importDirectory(folder, dir, monitor, stats);
+                                                       monitor.done();
+                                               } catch (Exception e) {
+                                                       if (e instanceof RuntimeException)
+                                                               throw (RuntimeException) e;
+                                                       else
+                                                               throw new ArgeoException("Cannot import "
+                                                                               + objectPath, e);
+                                               }
+                                       }
+                               });
+                       } catch (Exception e) {
+                               ErrorFeedback.show("Cannot import " + objectPath, e);
+                               failed = true;
+                       }
+
+                       Long duration = System.currentTimeMillis() - begin;
+                       Long durationS = duration / 1000l;
+                       String durationStr = (durationS / 60) + " min " + (durationS % 60)
+                                       + " s";
+                       StringBuffer message = new StringBuffer("Imported\n");
+                       message.append(stats.fileCount).append(" files\n");
+                       message.append(stats.dirCount).append(" directories\n");
+                       message.append(FileUtils.byteCountToDisplaySize(stats.sizeB));
+                       if (failed)
+                               message.append(" of planned ").append(
+                                               FileUtils.byteCountToDisplaySize(sizeB));
+                       message.append("\n");
+                       message.append("in ").append(durationStr).append("\n");
+                       if (failed)
+                               MessageDialog.openError(getShell(), "Import failed",
+                                               message.toString());
+                       else
+                               MessageDialog.openInformation(getShell(), "Import successful",
+                                               message.toString());
+
+                       return true;
+               }
+               return false;
+
+       }
+
+       /** Recursively computes the size of the directory in bytes. */
+       protected Long directorySize(File dir, Long currentSize) {
+               Long size = currentSize;
+               File[] files = dir.listFiles();
+               for (File file : files) {
+                       if (file.isDirectory()) {
+                               size = directorySize(file, size);
+                       } else {
+                               size = size + file.length();
+                       }
+               }
+               return size;
+       }
+
+       /**
+        * Import recursively a directory and its content to the repository.
+        */
+       protected void importDirectory(Node folder, File dir,
+                       IProgressMonitor monitor, Stats stats) {
+               try {
+                       File[] files = dir.listFiles();
+                       for (File file : files) {
+                               if (file.isDirectory()) {
+                                       Node childFolder = folder.addNode(file.getName(),
+                                                       NodeType.NT_FOLDER);
+                                       importDirectory(childFolder, file, monitor, stats);
+                                       folder.getSession().save();
+                                       stats.dirCount++;
+                               } else {
+                                       Long fileSize = file.length();
+
+                                       // we skip tempory files that are created by apps when a
+                                       // file is being edited.
+                                       // TODO : make this configurable.
+                                       if (file.getName().lastIndexOf('~') != file.getName()
+                                                       .length() - 1) {
+
+                                               monitor.subTask(file.getName() + " ("
+                                                               + FileUtils.byteCountToDisplaySize(fileSize)
+                                                               + ") " + file.getCanonicalPath());
+                                               try {
+                                                       Node fileNode = folder.addNode(file.getName(),
+                                                                       NodeType.NT_FILE);
+                                                       Node resNode = fileNode.addNode(
+                                                                       Property.JCR_CONTENT, NodeType.NT_RESOURCE);
+                                                       Binary binary = null;
+                                                       try {
+                                                               binary = folder
+                                                                               .getSession()
+                                                                               .getValueFactory()
+                                                                               .createBinary(new FileInputStream(file));
+                                                               resNode.setProperty(Property.JCR_DATA, binary);
+                                                       } finally {
+                                                               if (binary != null)
+                                                                       binary.dispose();
+                                                       }
+                                                       folder.getSession().save();
+                                                       stats.fileCount++;
+                                                       stats.sizeB = stats.sizeB + fileSize;
+                                               } catch (Exception e) {
+                                                       log.warn("Import of "
+                                                                       + file
+                                                                       + " ("
+                                                                       + FileUtils
+                                                                                       .byteCountToDisplaySize(fileSize)
+                                                                       + ") failed: " + e);
+                                                       folder.getSession().refresh(false);
+                                               }
+                                               monitor.worked((int) (fileSize / FileUtils.ONE_KB));
+                                       }
+                               }
+                       }
+               } catch (Exception e) {
+                       throw new ArgeoException("Cannot import " + dir + " to " + folder,
+                                       e);
+               }
+       }
+
+       static class Stats {
+               public Long fileCount = 0l;
+               public Long dirCount = 0l;
+               public Long sizeB = 0l;
+       }
+}
index c5931a083cd4ad1714f5a9bdc3ea1b2fc05cd360..d2953a684d400476bf716ed6a6c3c3ae486fcd0e 100644 (file)
@@ -1,7 +1,9 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <classpath>
-       <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6"/>>>
-       <classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
-       <classpathentry kind="src" path="src/main/java"/>
-       <classpathentry kind="output" path="target/classes"/>
+       <classpathentry kind="src" path="src" />
+       <classpathentry kind="con"
+               path="org.eclipse.pde.core.requiredPlugins" />
+       <classpathentry kind="con"
+               path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6" />
+       <classpathentry kind="output" path="bin" />
 </classpath>
diff --git a/org.argeo.osgi.ui.explorer/src/main/java/org/argeo/osgi/ui/explorer/OsgiExplorerImages.java b/org.argeo.osgi.ui.explorer/src/main/java/org/argeo/osgi/ui/explorer/OsgiExplorerImages.java
deleted file mode 100644 (file)
index 77bdfe9..0000000
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * Copyright (C) 2007-2012 Argeo GmbH
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *         http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.argeo.osgi.ui.explorer;
-
-import org.eclipse.swt.graphics.Image;
-
-/** Shared icons. */
-public class OsgiExplorerImages {
-       public final static Image INSTALLED = OsgiExplorerPlugin
-                       .getImageDescriptor("icons/installed.gif").createImage();
-       public final static Image RESOLVED = OsgiExplorerPlugin.getImageDescriptor(
-                       "icons/resolved.gif").createImage();
-       public final static Image STARTING = OsgiExplorerPlugin.getImageDescriptor(
-                       "icons/starting.gif").createImage();
-       public final static Image ACTIVE = OsgiExplorerPlugin.getImageDescriptor(
-                       "icons/active.gif").createImage();
-}
diff --git a/org.argeo.osgi.ui.explorer/src/main/java/org/argeo/osgi/ui/explorer/OsgiExplorerPerspective.java b/org.argeo.osgi.ui.explorer/src/main/java/org/argeo/osgi/ui/explorer/OsgiExplorerPerspective.java
deleted file mode 100644 (file)
index 153abcd..0000000
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * Copyright (C) 2007-2012 Argeo GmbH
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *         http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.argeo.osgi.ui.explorer;
-
-import org.eclipse.ui.IPageLayout;
-import org.eclipse.ui.IPerspectiveFactory;
-
-/** OSGi explorer perspective (to be enriched declaratively) */
-public class OsgiExplorerPerspective implements IPerspectiveFactory {
-
-       public void createInitialLayout(IPageLayout layout) {
-               layout.setEditorAreaVisible(true);
-               layout.setFixed(false);
-
-       }
-
-}
diff --git a/org.argeo.osgi.ui.explorer/src/main/java/org/argeo/osgi/ui/explorer/OsgiExplorerPlugin.java b/org.argeo.osgi.ui.explorer/src/main/java/org/argeo/osgi/ui/explorer/OsgiExplorerPlugin.java
deleted file mode 100644 (file)
index 80146d1..0000000
+++ /dev/null
@@ -1,76 +0,0 @@
-/*
- * Copyright (C) 2007-2012 Argeo GmbH
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *         http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.argeo.osgi.ui.explorer;
-
-import org.eclipse.jface.resource.ImageDescriptor;
-import org.eclipse.ui.plugin.AbstractUIPlugin;
-import org.osgi.framework.BundleContext;
-
-/**
- * The activator class controls the plug-in life cycle
- */
-public class OsgiExplorerPlugin extends AbstractUIPlugin {
-
-       // The plug-in ID
-       public static final String PLUGIN_ID = "org.argeo.osgi.ui.explorer"; //$NON-NLS-1$
-
-       // The shared instance
-       private static OsgiExplorerPlugin plugin;
-
-       /**
-        * The constructor
-        */
-       public OsgiExplorerPlugin() {
-       }
-
-       /*
-        * (non-Javadoc)
-        * 
-        * @see
-        * org.eclipse.ui.plugin.AbstractUIPlugin#start(org.osgi.framework.BundleContext
-        * )
-        */
-       public void start(BundleContext context) throws Exception {
-               super.start(context);
-               plugin = this;
-       }
-
-       /*
-        * (non-Javadoc)
-        * 
-        * @see
-        * org.eclipse.ui.plugin.AbstractUIPlugin#stop(org.osgi.framework.BundleContext
-        * )
-        */
-       public void stop(BundleContext context) throws Exception {
-               plugin = null;
-               super.stop(context);
-       }
-
-       /**
-        * Returns the shared instance
-        * 
-        * @return the shared instance
-        */
-       public static OsgiExplorerPlugin getDefault() {
-               return plugin;
-       }
-
-       public static ImageDescriptor getImageDescriptor(String path) {
-               return imageDescriptorFromPlugin(PLUGIN_ID, path);
-       }
-
-}
diff --git a/org.argeo.osgi.ui.explorer/src/main/java/org/argeo/osgi/ui/explorer/views/BundlesView.java b/org.argeo.osgi.ui.explorer/src/main/java/org/argeo/osgi/ui/explorer/views/BundlesView.java
deleted file mode 100644 (file)
index 98d74a6..0000000
+++ /dev/null
@@ -1,195 +0,0 @@
-/*
- * Copyright (C) 2007-2012 Argeo GmbH
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *         http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.argeo.osgi.ui.explorer.views;
-
-import java.util.Comparator;
-
-import org.argeo.eclipse.ui.ColumnViewerComparator;
-import org.argeo.eclipse.ui.specific.EclipseUiSpecificUtils;
-import org.argeo.osgi.ui.explorer.OsgiExplorerImages;
-import org.argeo.osgi.ui.explorer.OsgiExplorerPlugin;
-import org.eclipse.jface.viewers.ColumnLabelProvider;
-import org.eclipse.jface.viewers.IStructuredContentProvider;
-import org.eclipse.jface.viewers.TableViewer;
-import org.eclipse.jface.viewers.TableViewerColumn;
-import org.eclipse.jface.viewers.Viewer;
-import org.eclipse.swt.SWT;
-import org.eclipse.swt.graphics.Image;
-import org.eclipse.swt.widgets.Composite;
-import org.eclipse.ui.part.ViewPart;
-import org.osgi.framework.Bundle;
-import org.osgi.framework.BundleContext;
-import org.osgi.framework.Constants;
-
-/**
- * Overview of the bundles as a table. Equivalent to Equinox 'ss' console
- * command.
- */
-public class BundlesView extends ViewPart {
-       private TableViewer viewer;
-
-       @Override
-       public void createPartControl(Composite parent) {
-               viewer = new TableViewer(parent);
-               viewer.setContentProvider(new BundleContentProvider());
-               viewer.getTable().setHeaderVisible(true);
-
-               EclipseUiSpecificUtils.enableToolTipSupport(viewer);
-
-               // ID
-               TableViewerColumn column = new TableViewerColumn(viewer, SWT.NONE);
-               column.getColumn().setWidth(30);
-               column.getColumn().setText("ID");
-               column.getColumn().setAlignment(SWT.RIGHT);
-               column.setLabelProvider(new ColumnLabelProvider() {
-                       public String getText(Object element) {
-                               return Long.toString(((Bundle) element).getBundleId());
-                       }
-               });
-               new ColumnViewerComparator<Bundle>(column, new Comparator<Bundle>() {
-                       public int compare(Bundle o1, Bundle o2) {
-                               return (int) (o1.getBundleId() - o2.getBundleId());
-                       }
-               });
-
-               // State
-               column = new TableViewerColumn(viewer, SWT.NONE);
-               column.getColumn().setWidth(18);
-               column.getColumn().setText("State");
-               column.setLabelProvider(new StateLabelProvider());
-               new ColumnViewerComparator<Bundle>(column, new Comparator<Bundle>() {
-                       public int compare(Bundle o1, Bundle o2) {
-                               return o1.getState() - o2.getState();
-                       }
-               });
-
-               // Symbolic name
-               column = new TableViewerColumn(viewer, SWT.NONE);
-               column.getColumn().setWidth(300);
-               column.getColumn().setText("Symbolic Name");
-               column.setLabelProvider(new ColumnLabelProvider() {
-                       public String getText(Object element) {
-                               return ((Bundle) element).getSymbolicName();
-                       }
-               });
-               new ColumnViewerComparator<Bundle>(column, new Comparator<Bundle>() {
-                       public int compare(Bundle o1, Bundle o2) {
-                               return o1.getSymbolicName().compareTo(o2.getSymbolicName());
-                       }
-               });
-
-               // Version
-               column = new TableViewerColumn(viewer, SWT.NONE);
-               column.getColumn().setWidth(150);
-               column.getColumn().setText("Version");
-               column.setLabelProvider(new ColumnLabelProvider() {
-                       public String getText(Object element) {
-                               return ((Bundle) element).getVersion().toString();
-                       }
-               });
-               new ColumnViewerComparator<Bundle>(column, new Comparator<Bundle>() {
-                       public int compare(Bundle o1, Bundle o2) {
-                               return o1.getVersion().compareTo(o2.getVersion());
-                       }
-               });
-
-               viewer.setInput(OsgiExplorerPlugin.getDefault().getBundle()
-                               .getBundleContext());
-
-       }
-
-       @Override
-       public void setFocus() {
-               if (viewer != null)
-                       viewer.getControl().setFocus();
-       }
-
-       /** Content provider managing the array of bundles */
-       private static class BundleContentProvider implements
-                       IStructuredContentProvider {
-               public Object[] getElements(Object inputElement) {
-                       if (inputElement instanceof BundleContext) {
-                               BundleContext bc = (BundleContext) inputElement;
-                               return bc.getBundles();
-                       }
-                       return null;
-               }
-
-               public void dispose() {
-               }
-
-               public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
-               }
-
-       }
-
-       /** Label provider for the state column */
-       private static class StateLabelProvider extends ColumnLabelProvider {
-               @Override
-               public Image getImage(Object element) {
-                       Integer state = ((Bundle) element).getState();
-                       switch (state) {
-                       case Bundle.UNINSTALLED:
-                               return OsgiExplorerImages.INSTALLED;
-                       case Bundle.INSTALLED:
-                               return OsgiExplorerImages.INSTALLED;
-                       case Bundle.RESOLVED:
-                               return OsgiExplorerImages.RESOLVED;
-                       case Bundle.STARTING:
-                               return OsgiExplorerImages.STARTING;
-                       case Bundle.STOPPING:
-                               return OsgiExplorerImages.STARTING;
-                       case Bundle.ACTIVE:
-                               return OsgiExplorerImages.ACTIVE;
-                       default:
-                               return null;
-                       }
-               }
-
-               @Override
-               public String getText(Object element) {
-                       return null;
-               }
-
-               @Override
-               public String getToolTipText(Object element) {
-                       Bundle bundle = (Bundle) element;
-                       Integer state = bundle.getState();
-                       switch (state) {
-                       case Bundle.UNINSTALLED:
-                               return "UNINSTALLED";
-                       case Bundle.INSTALLED:
-                               return "INSTALLED";
-                       case Bundle.RESOLVED:
-                               return "RESOLVED";
-                       case Bundle.STARTING:
-                               String activationPolicy = bundle.getHeaders()
-                                               .get(Constants.BUNDLE_ACTIVATIONPOLICY).toString();
-                               if (activationPolicy != null
-                                               && activationPolicy.equals(Constants.ACTIVATION_LAZY))
-                                       return "<<LAZY>>";
-                               return "STARTING";
-                       case Bundle.STOPPING:
-                               return "STOPPING";
-                       case Bundle.ACTIVE:
-                               return "ACTIVE";
-                       default:
-                               return null;
-                       }
-               }
-
-       }
-}
diff --git a/org.argeo.osgi.ui.explorer/src/main/java/org/argeo/osgi/ui/explorer/views/ModulesView.java b/org.argeo.osgi.ui.explorer/src/main/java/org/argeo/osgi/ui/explorer/views/ModulesView.java
deleted file mode 100644 (file)
index 5d67bd4..0000000
+++ /dev/null
@@ -1,379 +0,0 @@
-/*
- * Copyright (C) 2007-2012 Argeo GmbH
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *         http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.argeo.osgi.ui.explorer.views;
-
-import java.util.Comparator;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.Set;
-import java.util.TreeMap;
-import java.util.TreeSet;
-
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.argeo.eclipse.ui.TreeParent;
-import org.argeo.osgi.ui.explorer.OsgiExplorerPlugin;
-import org.eclipse.jface.viewers.ITableLabelProvider;
-import org.eclipse.jface.viewers.ITreeContentProvider;
-import org.eclipse.jface.viewers.LabelProvider;
-import org.eclipse.jface.viewers.TreeViewer;
-import org.eclipse.jface.viewers.Viewer;
-import org.eclipse.swt.SWT;
-import org.eclipse.swt.graphics.Image;
-import org.eclipse.swt.widgets.Composite;
-import org.eclipse.ui.part.ViewPart;
-import org.osgi.framework.Bundle;
-import org.osgi.framework.BundleContext;
-import org.osgi.framework.ServiceReference;
-import org.osgi.service.packageadmin.ExportedPackage;
-import org.osgi.service.packageadmin.PackageAdmin;
-
-/** <b>Experimental</b> The OSGi runtime from a module perspective. */
-public class ModulesView extends ViewPart {
-       private final static Log log = LogFactory.getLog(ModulesView.class);
-
-       private TreeViewer viewer;
-
-       private PackageAdmin packageAdmin;
-
-       private Comparator<ExportedPackage> exportedPackageComparator = new Comparator<ExportedPackage>() {
-
-               public int compare(ExportedPackage o1, ExportedPackage o2) {
-                       if (!o1.getName().equals(o2.getName()))
-                               return o1.getName().compareTo(o2.getName());
-                       else
-                               return o1.getVersion().compareTo(o2.getVersion());
-               }
-       };
-
-       @Override
-       public void createPartControl(Composite parent) {
-               viewer = new TreeViewer(parent, SWT.MULTI | SWT.H_SCROLL | SWT.V_SCROLL);
-               viewer.setContentProvider(new ModulesContentProvider());
-               viewer.setLabelProvider(new ModulesLabelProvider());
-               viewer.setInput(OsgiExplorerPlugin.getDefault().getBundle()
-                               .getBundleContext());
-       }
-
-       @Override
-       public void setFocus() {
-               viewer.getTree().setFocus();
-       }
-
-       private class ModulesContentProvider implements ITreeContentProvider {
-
-               public Object[] getElements(Object inputElement) {
-                       return getChildren(inputElement);
-               }
-
-               public Object[] getChildren(Object parentElement) {
-                       if (parentElement instanceof BundleContext) {
-                               BundleContext bundleContext = (BundleContext) parentElement;
-                               Bundle[] bundles = bundleContext.getBundles();
-
-                               TreeParent bundlesNode = new TreeParent("Bundles");
-                               for (Bundle bundle : bundles) {
-                                       if (bundle.getState() == Bundle.ACTIVE)
-                                               bundlesNode.addChild(new BundleNode(bundle));
-                               }
-
-                               // scan packages
-                               ServiceReference paSr = bundleContext
-                                               .getServiceReference(PackageAdmin.class.getName());
-                               // TODO: make a cleaner referencing
-                               packageAdmin = (PackageAdmin) bundleContext.getService(paSr);
-
-                               Bundle bundle1 = null;
-                               Bundle bundle2 = null;
-
-                               Map<Bundle, Set<ExportedPackage>> importedPackages = new HashMap<Bundle, Set<ExportedPackage>>();
-                               Map<String, Set<ExportedPackage>> packages = new TreeMap<String, Set<ExportedPackage>>();
-                               for (Bundle bundle : bundles) {
-                                       if (bundle.getSymbolicName()
-                                                       .equals("org.argeo.security.ui"))
-                                               bundle1 = bundle;
-                                       if (bundle.getSymbolicName().equals(
-                                                       "org.argeo.security.equinox"))
-                                               bundle2 = bundle;
-
-                                       ExportedPackage[] pkgs = packageAdmin
-                                                       .getExportedPackages(bundle);
-                                       if (pkgs != null)
-                                               for (ExportedPackage pkg : pkgs) {
-                                                       if (!packages.containsKey(pkg.getName()))
-                                                               packages.put(pkg.getName(),
-                                                                               new TreeSet<ExportedPackage>(
-                                                                                               exportedPackageComparator));
-                                                       Set<ExportedPackage> expPackages = (Set<ExportedPackage>) packages
-                                                                       .get(pkg.getName());
-                                                       expPackages.add(pkg);
-
-                                                       // imported
-                                                       for (Bundle b : pkg.getImportingBundles()) {
-                                                               if (bundle.getBundleId() != b.getBundleId()) {
-                                                                       if (!importedPackages.containsKey(b))
-                                                                               importedPackages
-                                                                                               .put(b,
-                                                                                                               new TreeSet<ExportedPackage>(
-                                                                                                                               exportedPackageComparator));
-                                                                       Set<ExportedPackage> impPackages = (Set<ExportedPackage>) importedPackages
-                                                                                       .get(b);
-                                                                       impPackages.add(pkg);
-                                                               }
-                                                       }
-                                               }
-                               }
-
-                               TreeParent mPackageNode = new TreeParent("Multiple Packages");
-                               // TreeParent aPackageNode = new TreeParent("All Packages");
-                               for (String packageName : packages.keySet()) {
-                                       Set<ExportedPackage> pkgs = packages.get(packageName);
-                                       if (pkgs.size() > 1) {
-                                               MultiplePackagesNode mpn = new MultiplePackagesNode(
-                                                               packageName, pkgs);
-                                               mPackageNode.addChild(mpn);
-                                               // aPackageNode.addChild(mpn);
-                                       } else {
-                                               // aPackageNode.addChild(new ExportedPackageNode(pkgs
-                                               // .iterator().next()));
-                                       }
-                               }
-
-                               return new Object[] { bundlesNode, mPackageNode };// ,
-                                                                                                                                       // aPackageNode
-                                                                                                                                       // };
-                       } else if (parentElement instanceof TreeParent) {
-                               return ((TreeParent) parentElement).getChildren();
-                       } else {
-                               return null;
-                       }
-               }
-
-               public Object getParent(Object element) {
-                       // TODO Auto-generated method stub
-                       return null;
-               }
-
-               public boolean hasChildren(Object element) {
-                       if (element instanceof TreeParent) {
-                               return ((TreeParent) element).hasChildren();
-                       }
-                       return false;
-               }
-
-               public void dispose() {
-                       // TODO Auto-generated method stub
-
-               }
-
-               public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
-                       // TODO Auto-generated method stub
-
-               }
-
-       }
-
-       protected Map<String, ExportedPackage> dependencySpace(Bundle bundle,
-                       Map<Bundle, Set<ExportedPackage>> importedPackages,
-                       Map<String, Set<String>> traces) {
-               log.debug("Dependency space for " + bundle.getSymbolicName());
-               Map<String, ExportedPackage> space = new TreeMap<String, ExportedPackage>();
-               fillDependencySpace(space, bundle, importedPackages,
-                               bundle.getSymbolicName(), traces);
-               return space;
-       }
-
-       /** Recursive */
-       protected void fillDependencySpace(Map<String, ExportedPackage> space,
-                       Bundle bundle, Map<Bundle, Set<ExportedPackage>> importedPackages,
-                       String currTrace, Map<String, Set<String>> traces) {
-               if (importedPackages.containsKey(bundle)) {
-                       Set<ExportedPackage> imports = importedPackages.get(bundle);
-                       // log.debug("## Fill dependency space for " + bundle + " : ");
-                       for (ExportedPackage pkg : imports) {
-                               if (!traces.containsKey(pkg.getName()))
-                                       traces.put(pkg.getName(), new TreeSet<String>());
-                               traces.get(pkg.getName()).add(currTrace);
-                               if (!space.containsKey(pkg.getName())) {
-                                       space.put(pkg.getName(), pkg);
-                                       Bundle exportingBundle = pkg.getExportingBundle();
-                                       // if (bundle.getBundleId() !=
-                                       // exportingBundle.getBundleId())
-                                       fillDependencySpace(space, exportingBundle,
-                                                       importedPackages, currTrace + " > "
-                                                                       + exportingBundle.getSymbolicName(), traces);
-                               }
-                       }
-               }
-       }
-
-       private class ModulesLabelProvider extends LabelProvider implements
-                       ITableLabelProvider {
-
-               public Image getColumnImage(Object element, int columnIndex) {
-                       // TODO Auto-generated method stub
-                       return null;
-               }
-
-               public String getColumnText(Object element, int columnIndex) {
-                       return getText(element);
-               }
-
-       }
-
-       class BundleNode extends TreeParent {
-               private final Bundle bundle;
-
-               public BundleNode(Bundle bundle) {
-                       super(bundle.getSymbolicName());
-                       this.bundle = bundle;
-
-                       // Registered services
-                       ServiceReference[] registeredServices = bundle
-                                       .getRegisteredServices();
-                       if (registeredServices != null) {
-                               TreeParent registeredServicesNode = new TreeParent(
-                                               "Registered Services");
-                               addChild(registeredServicesNode);
-                               for (ServiceReference sr : registeredServices) {
-                                       if (sr != null)
-                                               registeredServicesNode
-                                                               .addChild(new ServiceReferenceNode(sr));
-                               }
-                       }
-
-                       // Used services
-                       ServiceReference[] usedServices = bundle.getRegisteredServices();
-                       if (usedServices != null) {
-                               TreeParent usedServicesNode = new TreeParent("Used Services");
-                               addChild(usedServicesNode);
-                               for (ServiceReference sr : usedServices) {
-                                       if (sr != null)
-                                               usedServicesNode.addChild(new ServiceReferenceNode(sr));
-                               }
-                       }
-               }
-
-               public Bundle getBundle() {
-                       return bundle;
-               }
-
-       }
-
-       class ServiceReferenceNode extends TreeParent {
-               private final ServiceReference serviceReference;
-
-               public ServiceReferenceNode(ServiceReference serviceReference) {
-                       super(serviceReference.toString());
-                       this.serviceReference = serviceReference;
-
-                       Bundle[] usedBundles = serviceReference.getUsingBundles();
-                       if (usedBundles != null) {
-                               TreeParent usingBundles = new TreeParent("Using Bundles");
-                               addChild(usingBundles);
-                               for (Bundle b : usedBundles) {
-                                       if (b != null)
-                                               usingBundles.addChild(new TreeParent(b
-                                                               .getSymbolicName()));
-                               }
-                       }
-
-                       TreeParent properties = new TreeParent("Properties");
-                       addChild(properties);
-                       for (String key : serviceReference.getPropertyKeys()) {
-                               properties.addChild(new TreeParent(key + "="
-                                               + serviceReference.getProperty(key)));
-                       }
-
-               }
-
-               public ServiceReference getServiceReference() {
-                       return serviceReference;
-               }
-
-       }
-
-       class MultiplePackagesNode extends TreeParent {
-               private String packageName;
-               private Set<ExportedPackage> exportedPackages;
-
-               public MultiplePackagesNode(String packageName,
-                               Set<ExportedPackage> exportedPackages) {
-                       super(packageName);
-                       this.packageName = packageName;
-                       this.exportedPackages = exportedPackages;
-                       for (ExportedPackage pkg : exportedPackages) {
-                               addChild(new ExportedPackageNode(pkg));
-                       }
-               }
-
-       }
-
-       class ConflictingPackageNode extends TreeParent {
-               private ExportedPackage exportedPackage;
-
-               public ConflictingPackageNode(ExportedPackage exportedPackage) {
-                       super(exportedPackage.getName() + " - "
-                                       + exportedPackage.getVersion() + " ("
-                                       + exportedPackage.getExportingBundle() + ")");
-                       this.exportedPackage = exportedPackage;
-
-                       TreeParent bundlesNode = new TreeParent("Dependent Bundles");
-                       this.addChild(bundlesNode);
-                       Map<String, Bundle> bundles = new TreeMap<String, Bundle>();
-                       for (Bundle b : exportedPackage.getImportingBundles()) {
-                               bundles.put(b.getSymbolicName(), b);
-                       }
-                       for (String key : bundles.keySet()) {
-                               addDependentBundles(bundlesNode, bundles.get(key));
-                       }
-               }
-       }
-
-       protected void addDependentBundles(TreeParent parent, Bundle bundle) {
-               TreeParent bundleNode = new TreeParent(bundle.toString());
-               parent.addChild(bundleNode);
-               Map<String, Bundle> bundles = new TreeMap<String, Bundle>();
-               ExportedPackage[] pkgs = packageAdmin.getExportedPackages(bundle);
-               if (pkgs != null)
-                       for (ExportedPackage pkg : pkgs) {
-                               for (Bundle b : pkg.getImportingBundles()) {
-                                       if (!bundles.containsKey(b.getSymbolicName())
-                                                       && b.getBundleId() != bundle.getBundleId()) {
-                                               bundles.put(b.getSymbolicName(), b);
-                                       }
-                               }
-                       }
-
-               for (String key : bundles.keySet()) {
-                       addDependentBundles(bundleNode, bundles.get(key));
-               }
-       }
-
-       class ExportedPackageNode extends TreeParent {
-               private ExportedPackage exportedPackage;
-
-               public ExportedPackageNode(ExportedPackage exportedPackage) {
-                       super(exportedPackage.getName() + " - "
-                                       + exportedPackage.getVersion() + " ("
-                                       + exportedPackage.getExportingBundle() + ")");
-                       this.exportedPackage = exportedPackage;
-                       for (Bundle bundle : exportedPackage.getImportingBundles()) {
-                               addChild(new BundleNode(bundle));
-                       }
-               }
-       }
-}
diff --git a/org.argeo.osgi.ui.explorer/src/org/argeo/osgi/ui/explorer/OsgiExplorerImages.java b/org.argeo.osgi.ui.explorer/src/org/argeo/osgi/ui/explorer/OsgiExplorerImages.java
new file mode 100644 (file)
index 0000000..77bdfe9
--- /dev/null
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2007-2012 Argeo GmbH
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *         http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.argeo.osgi.ui.explorer;
+
+import org.eclipse.swt.graphics.Image;
+
+/** Shared icons. */
+public class OsgiExplorerImages {
+       public final static Image INSTALLED = OsgiExplorerPlugin
+                       .getImageDescriptor("icons/installed.gif").createImage();
+       public final static Image RESOLVED = OsgiExplorerPlugin.getImageDescriptor(
+                       "icons/resolved.gif").createImage();
+       public final static Image STARTING = OsgiExplorerPlugin.getImageDescriptor(
+                       "icons/starting.gif").createImage();
+       public final static Image ACTIVE = OsgiExplorerPlugin.getImageDescriptor(
+                       "icons/active.gif").createImage();
+}
diff --git a/org.argeo.osgi.ui.explorer/src/org/argeo/osgi/ui/explorer/OsgiExplorerPerspective.java b/org.argeo.osgi.ui.explorer/src/org/argeo/osgi/ui/explorer/OsgiExplorerPerspective.java
new file mode 100644 (file)
index 0000000..153abcd
--- /dev/null
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2007-2012 Argeo GmbH
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *         http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.argeo.osgi.ui.explorer;
+
+import org.eclipse.ui.IPageLayout;
+import org.eclipse.ui.IPerspectiveFactory;
+
+/** OSGi explorer perspective (to be enriched declaratively) */
+public class OsgiExplorerPerspective implements IPerspectiveFactory {
+
+       public void createInitialLayout(IPageLayout layout) {
+               layout.setEditorAreaVisible(true);
+               layout.setFixed(false);
+
+       }
+
+}
diff --git a/org.argeo.osgi.ui.explorer/src/org/argeo/osgi/ui/explorer/OsgiExplorerPlugin.java b/org.argeo.osgi.ui.explorer/src/org/argeo/osgi/ui/explorer/OsgiExplorerPlugin.java
new file mode 100644 (file)
index 0000000..80146d1
--- /dev/null
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) 2007-2012 Argeo GmbH
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *         http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.argeo.osgi.ui.explorer;
+
+import org.eclipse.jface.resource.ImageDescriptor;
+import org.eclipse.ui.plugin.AbstractUIPlugin;
+import org.osgi.framework.BundleContext;
+
+/**
+ * The activator class controls the plug-in life cycle
+ */
+public class OsgiExplorerPlugin extends AbstractUIPlugin {
+
+       // The plug-in ID
+       public static final String PLUGIN_ID = "org.argeo.osgi.ui.explorer"; //$NON-NLS-1$
+
+       // The shared instance
+       private static OsgiExplorerPlugin plugin;
+
+       /**
+        * The constructor
+        */
+       public OsgiExplorerPlugin() {
+       }
+
+       /*
+        * (non-Javadoc)
+        * 
+        * @see
+        * org.eclipse.ui.plugin.AbstractUIPlugin#start(org.osgi.framework.BundleContext
+        * )
+        */
+       public void start(BundleContext context) throws Exception {
+               super.start(context);
+               plugin = this;
+       }
+
+       /*
+        * (non-Javadoc)
+        * 
+        * @see
+        * org.eclipse.ui.plugin.AbstractUIPlugin#stop(org.osgi.framework.BundleContext
+        * )
+        */
+       public void stop(BundleContext context) throws Exception {
+               plugin = null;
+               super.stop(context);
+       }
+
+       /**
+        * Returns the shared instance
+        * 
+        * @return the shared instance
+        */
+       public static OsgiExplorerPlugin getDefault() {
+               return plugin;
+       }
+
+       public static ImageDescriptor getImageDescriptor(String path) {
+               return imageDescriptorFromPlugin(PLUGIN_ID, path);
+       }
+
+}
diff --git a/org.argeo.osgi.ui.explorer/src/org/argeo/osgi/ui/explorer/views/BundlesView.java b/org.argeo.osgi.ui.explorer/src/org/argeo/osgi/ui/explorer/views/BundlesView.java
new file mode 100644 (file)
index 0000000..98d74a6
--- /dev/null
@@ -0,0 +1,195 @@
+/*
+ * Copyright (C) 2007-2012 Argeo GmbH
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *         http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.argeo.osgi.ui.explorer.views;
+
+import java.util.Comparator;
+
+import org.argeo.eclipse.ui.ColumnViewerComparator;
+import org.argeo.eclipse.ui.specific.EclipseUiSpecificUtils;
+import org.argeo.osgi.ui.explorer.OsgiExplorerImages;
+import org.argeo.osgi.ui.explorer.OsgiExplorerPlugin;
+import org.eclipse.jface.viewers.ColumnLabelProvider;
+import org.eclipse.jface.viewers.IStructuredContentProvider;
+import org.eclipse.jface.viewers.TableViewer;
+import org.eclipse.jface.viewers.TableViewerColumn;
+import org.eclipse.jface.viewers.Viewer;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.ui.part.ViewPart;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.Constants;
+
+/**
+ * Overview of the bundles as a table. Equivalent to Equinox 'ss' console
+ * command.
+ */
+public class BundlesView extends ViewPart {
+       private TableViewer viewer;
+
+       @Override
+       public void createPartControl(Composite parent) {
+               viewer = new TableViewer(parent);
+               viewer.setContentProvider(new BundleContentProvider());
+               viewer.getTable().setHeaderVisible(true);
+
+               EclipseUiSpecificUtils.enableToolTipSupport(viewer);
+
+               // ID
+               TableViewerColumn column = new TableViewerColumn(viewer, SWT.NONE);
+               column.getColumn().setWidth(30);
+               column.getColumn().setText("ID");
+               column.getColumn().setAlignment(SWT.RIGHT);
+               column.setLabelProvider(new ColumnLabelProvider() {
+                       public String getText(Object element) {
+                               return Long.toString(((Bundle) element).getBundleId());
+                       }
+               });
+               new ColumnViewerComparator<Bundle>(column, new Comparator<Bundle>() {
+                       public int compare(Bundle o1, Bundle o2) {
+                               return (int) (o1.getBundleId() - o2.getBundleId());
+                       }
+               });
+
+               // State
+               column = new TableViewerColumn(viewer, SWT.NONE);
+               column.getColumn().setWidth(18);
+               column.getColumn().setText("State");
+               column.setLabelProvider(new StateLabelProvider());
+               new ColumnViewerComparator<Bundle>(column, new Comparator<Bundle>() {
+                       public int compare(Bundle o1, Bundle o2) {
+                               return o1.getState() - o2.getState();
+                       }
+               });
+
+               // Symbolic name
+               column = new TableViewerColumn(viewer, SWT.NONE);
+               column.getColumn().setWidth(300);
+               column.getColumn().setText("Symbolic Name");
+               column.setLabelProvider(new ColumnLabelProvider() {
+                       public String getText(Object element) {
+                               return ((Bundle) element).getSymbolicName();
+                       }
+               });
+               new ColumnViewerComparator<Bundle>(column, new Comparator<Bundle>() {
+                       public int compare(Bundle o1, Bundle o2) {
+                               return o1.getSymbolicName().compareTo(o2.getSymbolicName());
+                       }
+               });
+
+               // Version
+               column = new TableViewerColumn(viewer, SWT.NONE);
+               column.getColumn().setWidth(150);
+               column.getColumn().setText("Version");
+               column.setLabelProvider(new ColumnLabelProvider() {
+                       public String getText(Object element) {
+                               return ((Bundle) element).getVersion().toString();
+                       }
+               });
+               new ColumnViewerComparator<Bundle>(column, new Comparator<Bundle>() {
+                       public int compare(Bundle o1, Bundle o2) {
+                               return o1.getVersion().compareTo(o2.getVersion());
+                       }
+               });
+
+               viewer.setInput(OsgiExplorerPlugin.getDefault().getBundle()
+                               .getBundleContext());
+
+       }
+
+       @Override
+       public void setFocus() {
+               if (viewer != null)
+                       viewer.getControl().setFocus();
+       }
+
+       /** Content provider managing the array of bundles */
+       private static class BundleContentProvider implements
+                       IStructuredContentProvider {
+               public Object[] getElements(Object inputElement) {
+                       if (inputElement instanceof BundleContext) {
+                               BundleContext bc = (BundleContext) inputElement;
+                               return bc.getBundles();
+                       }
+                       return null;
+               }
+
+               public void dispose() {
+               }
+
+               public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
+               }
+
+       }
+
+       /** Label provider for the state column */
+       private static class StateLabelProvider extends ColumnLabelProvider {
+               @Override
+               public Image getImage(Object element) {
+                       Integer state = ((Bundle) element).getState();
+                       switch (state) {
+                       case Bundle.UNINSTALLED:
+                               return OsgiExplorerImages.INSTALLED;
+                       case Bundle.INSTALLED:
+                               return OsgiExplorerImages.INSTALLED;
+                       case Bundle.RESOLVED:
+                               return OsgiExplorerImages.RESOLVED;
+                       case Bundle.STARTING:
+                               return OsgiExplorerImages.STARTING;
+                       case Bundle.STOPPING:
+                               return OsgiExplorerImages.STARTING;
+                       case Bundle.ACTIVE:
+                               return OsgiExplorerImages.ACTIVE;
+                       default:
+                               return null;
+                       }
+               }
+
+               @Override
+               public String getText(Object element) {
+                       return null;
+               }
+
+               @Override
+               public String getToolTipText(Object element) {
+                       Bundle bundle = (Bundle) element;
+                       Integer state = bundle.getState();
+                       switch (state) {
+                       case Bundle.UNINSTALLED:
+                               return "UNINSTALLED";
+                       case Bundle.INSTALLED:
+                               return "INSTALLED";
+                       case Bundle.RESOLVED:
+                               return "RESOLVED";
+                       case Bundle.STARTING:
+                               String activationPolicy = bundle.getHeaders()
+                                               .get(Constants.BUNDLE_ACTIVATIONPOLICY).toString();
+                               if (activationPolicy != null
+                                               && activationPolicy.equals(Constants.ACTIVATION_LAZY))
+                                       return "<<LAZY>>";
+                               return "STARTING";
+                       case Bundle.STOPPING:
+                               return "STOPPING";
+                       case Bundle.ACTIVE:
+                               return "ACTIVE";
+                       default:
+                               return null;
+                       }
+               }
+
+       }
+}
diff --git a/org.argeo.osgi.ui.explorer/src/org/argeo/osgi/ui/explorer/views/ModulesView.java b/org.argeo.osgi.ui.explorer/src/org/argeo/osgi/ui/explorer/views/ModulesView.java
new file mode 100644 (file)
index 0000000..5d67bd4
--- /dev/null
@@ -0,0 +1,379 @@
+/*
+ * Copyright (C) 2007-2012 Argeo GmbH
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *         http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.argeo.osgi.ui.explorer.views;
+
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+import java.util.TreeMap;
+import java.util.TreeSet;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.argeo.eclipse.ui.TreeParent;
+import org.argeo.osgi.ui.explorer.OsgiExplorerPlugin;
+import org.eclipse.jface.viewers.ITableLabelProvider;
+import org.eclipse.jface.viewers.ITreeContentProvider;
+import org.eclipse.jface.viewers.LabelProvider;
+import org.eclipse.jface.viewers.TreeViewer;
+import org.eclipse.jface.viewers.Viewer;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.ui.part.ViewPart;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.ServiceReference;
+import org.osgi.service.packageadmin.ExportedPackage;
+import org.osgi.service.packageadmin.PackageAdmin;
+
+/** <b>Experimental</b> The OSGi runtime from a module perspective. */
+public class ModulesView extends ViewPart {
+       private final static Log log = LogFactory.getLog(ModulesView.class);
+
+       private TreeViewer viewer;
+
+       private PackageAdmin packageAdmin;
+
+       private Comparator<ExportedPackage> exportedPackageComparator = new Comparator<ExportedPackage>() {
+
+               public int compare(ExportedPackage o1, ExportedPackage o2) {
+                       if (!o1.getName().equals(o2.getName()))
+                               return o1.getName().compareTo(o2.getName());
+                       else
+                               return o1.getVersion().compareTo(o2.getVersion());
+               }
+       };
+
+       @Override
+       public void createPartControl(Composite parent) {
+               viewer = new TreeViewer(parent, SWT.MULTI | SWT.H_SCROLL | SWT.V_SCROLL);
+               viewer.setContentProvider(new ModulesContentProvider());
+               viewer.setLabelProvider(new ModulesLabelProvider());
+               viewer.setInput(OsgiExplorerPlugin.getDefault().getBundle()
+                               .getBundleContext());
+       }
+
+       @Override
+       public void setFocus() {
+               viewer.getTree().setFocus();
+       }
+
+       private class ModulesContentProvider implements ITreeContentProvider {
+
+               public Object[] getElements(Object inputElement) {
+                       return getChildren(inputElement);
+               }
+
+               public Object[] getChildren(Object parentElement) {
+                       if (parentElement instanceof BundleContext) {
+                               BundleContext bundleContext = (BundleContext) parentElement;
+                               Bundle[] bundles = bundleContext.getBundles();
+
+                               TreeParent bundlesNode = new TreeParent("Bundles");
+                               for (Bundle bundle : bundles) {
+                                       if (bundle.getState() == Bundle.ACTIVE)
+                                               bundlesNode.addChild(new BundleNode(bundle));
+                               }
+
+                               // scan packages
+                               ServiceReference paSr = bundleContext
+                                               .getServiceReference(PackageAdmin.class.getName());
+                               // TODO: make a cleaner referencing
+                               packageAdmin = (PackageAdmin) bundleContext.getService(paSr);
+
+                               Bundle bundle1 = null;
+                               Bundle bundle2 = null;
+
+                               Map<Bundle, Set<ExportedPackage>> importedPackages = new HashMap<Bundle, Set<ExportedPackage>>();
+                               Map<String, Set<ExportedPackage>> packages = new TreeMap<String, Set<ExportedPackage>>();
+                               for (Bundle bundle : bundles) {
+                                       if (bundle.getSymbolicName()
+                                                       .equals("org.argeo.security.ui"))
+                                               bundle1 = bundle;
+                                       if (bundle.getSymbolicName().equals(
+                                                       "org.argeo.security.equinox"))
+                                               bundle2 = bundle;
+
+                                       ExportedPackage[] pkgs = packageAdmin
+                                                       .getExportedPackages(bundle);
+                                       if (pkgs != null)
+                                               for (ExportedPackage pkg : pkgs) {
+                                                       if (!packages.containsKey(pkg.getName()))
+                                                               packages.put(pkg.getName(),
+                                                                               new TreeSet<ExportedPackage>(
+                                                                                               exportedPackageComparator));
+                                                       Set<ExportedPackage> expPackages = (Set<ExportedPackage>) packages
+                                                                       .get(pkg.getName());
+                                                       expPackages.add(pkg);
+
+                                                       // imported
+                                                       for (Bundle b : pkg.getImportingBundles()) {
+                                                               if (bundle.getBundleId() != b.getBundleId()) {
+                                                                       if (!importedPackages.containsKey(b))
+                                                                               importedPackages
+                                                                                               .put(b,
+                                                                                                               new TreeSet<ExportedPackage>(
+                                                                                                                               exportedPackageComparator));
+                                                                       Set<ExportedPackage> impPackages = (Set<ExportedPackage>) importedPackages
+                                                                                       .get(b);
+                                                                       impPackages.add(pkg);
+                                                               }
+                                                       }
+                                               }
+                               }
+
+                               TreeParent mPackageNode = new TreeParent("Multiple Packages");
+                               // TreeParent aPackageNode = new TreeParent("All Packages");
+                               for (String packageName : packages.keySet()) {
+                                       Set<ExportedPackage> pkgs = packages.get(packageName);
+                                       if (pkgs.size() > 1) {
+                                               MultiplePackagesNode mpn = new MultiplePackagesNode(
+                                                               packageName, pkgs);
+                                               mPackageNode.addChild(mpn);
+                                               // aPackageNode.addChild(mpn);
+                                       } else {
+                                               // aPackageNode.addChild(new ExportedPackageNode(pkgs
+                                               // .iterator().next()));
+                                       }
+                               }
+
+                               return new Object[] { bundlesNode, mPackageNode };// ,
+                                                                                                                                       // aPackageNode
+                                                                                                                                       // };
+                       } else if (parentElement instanceof TreeParent) {
+                               return ((TreeParent) parentElement).getChildren();
+                       } else {
+                               return null;
+                       }
+               }
+
+               public Object getParent(Object element) {
+                       // TODO Auto-generated method stub
+                       return null;
+               }
+
+               public boolean hasChildren(Object element) {
+                       if (element instanceof TreeParent) {
+                               return ((TreeParent) element).hasChildren();
+                       }
+                       return false;
+               }
+
+               public void dispose() {
+                       // TODO Auto-generated method stub
+
+               }
+
+               public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
+                       // TODO Auto-generated method stub
+
+               }
+
+       }
+
+       protected Map<String, ExportedPackage> dependencySpace(Bundle bundle,
+                       Map<Bundle, Set<ExportedPackage>> importedPackages,
+                       Map<String, Set<String>> traces) {
+               log.debug("Dependency space for " + bundle.getSymbolicName());
+               Map<String, ExportedPackage> space = new TreeMap<String, ExportedPackage>();
+               fillDependencySpace(space, bundle, importedPackages,
+                               bundle.getSymbolicName(), traces);
+               return space;
+       }
+
+       /** Recursive */
+       protected void fillDependencySpace(Map<String, ExportedPackage> space,
+                       Bundle bundle, Map<Bundle, Set<ExportedPackage>> importedPackages,
+                       String currTrace, Map<String, Set<String>> traces) {
+               if (importedPackages.containsKey(bundle)) {
+                       Set<ExportedPackage> imports = importedPackages.get(bundle);
+                       // log.debug("## Fill dependency space for " + bundle + " : ");
+                       for (ExportedPackage pkg : imports) {
+                               if (!traces.containsKey(pkg.getName()))
+                                       traces.put(pkg.getName(), new TreeSet<String>());
+                               traces.get(pkg.getName()).add(currTrace);
+                               if (!space.containsKey(pkg.getName())) {
+                                       space.put(pkg.getName(), pkg);
+                                       Bundle exportingBundle = pkg.getExportingBundle();
+                                       // if (bundle.getBundleId() !=
+                                       // exportingBundle.getBundleId())
+                                       fillDependencySpace(space, exportingBundle,
+                                                       importedPackages, currTrace + " > "
+                                                                       + exportingBundle.getSymbolicName(), traces);
+                               }
+                       }
+               }
+       }
+
+       private class ModulesLabelProvider extends LabelProvider implements
+                       ITableLabelProvider {
+
+               public Image getColumnImage(Object element, int columnIndex) {
+                       // TODO Auto-generated method stub
+                       return null;
+               }
+
+               public String getColumnText(Object element, int columnIndex) {
+                       return getText(element);
+               }
+
+       }
+
+       class BundleNode extends TreeParent {
+               private final Bundle bundle;
+
+               public BundleNode(Bundle bundle) {
+                       super(bundle.getSymbolicName());
+                       this.bundle = bundle;
+
+                       // Registered services
+                       ServiceReference[] registeredServices = bundle
+                                       .getRegisteredServices();
+                       if (registeredServices != null) {
+                               TreeParent registeredServicesNode = new TreeParent(
+                                               "Registered Services");
+                               addChild(registeredServicesNode);
+                               for (ServiceReference sr : registeredServices) {
+                                       if (sr != null)
+                                               registeredServicesNode
+                                                               .addChild(new ServiceReferenceNode(sr));
+                               }
+                       }
+
+                       // Used services
+                       ServiceReference[] usedServices = bundle.getRegisteredServices();
+                       if (usedServices != null) {
+                               TreeParent usedServicesNode = new TreeParent("Used Services");
+                               addChild(usedServicesNode);
+                               for (ServiceReference sr : usedServices) {
+                                       if (sr != null)
+                                               usedServicesNode.addChild(new ServiceReferenceNode(sr));
+                               }
+                       }
+               }
+
+               public Bundle getBundle() {
+                       return bundle;
+               }
+
+       }
+
+       class ServiceReferenceNode extends TreeParent {
+               private final ServiceReference serviceReference;
+
+               public ServiceReferenceNode(ServiceReference serviceReference) {
+                       super(serviceReference.toString());
+                       this.serviceReference = serviceReference;
+
+                       Bundle[] usedBundles = serviceReference.getUsingBundles();
+                       if (usedBundles != null) {
+                               TreeParent usingBundles = new TreeParent("Using Bundles");
+                               addChild(usingBundles);
+                               for (Bundle b : usedBundles) {
+                                       if (b != null)
+                                               usingBundles.addChild(new TreeParent(b
+                                                               .getSymbolicName()));
+                               }
+                       }
+
+                       TreeParent properties = new TreeParent("Properties");
+                       addChild(properties);
+                       for (String key : serviceReference.getPropertyKeys()) {
+                               properties.addChild(new TreeParent(key + "="
+                                               + serviceReference.getProperty(key)));
+                       }
+
+               }
+
+               public ServiceReference getServiceReference() {
+                       return serviceReference;
+               }
+
+       }
+
+       class MultiplePackagesNode extends TreeParent {
+               private String packageName;
+               private Set<ExportedPackage> exportedPackages;
+
+               public MultiplePackagesNode(String packageName,
+                               Set<ExportedPackage> exportedPackages) {
+                       super(packageName);
+                       this.packageName = packageName;
+                       this.exportedPackages = exportedPackages;
+                       for (ExportedPackage pkg : exportedPackages) {
+                               addChild(new ExportedPackageNode(pkg));
+                       }
+               }
+
+       }
+
+       class ConflictingPackageNode extends TreeParent {
+               private ExportedPackage exportedPackage;
+
+               public ConflictingPackageNode(ExportedPackage exportedPackage) {
+                       super(exportedPackage.getName() + " - "
+                                       + exportedPackage.getVersion() + " ("
+                                       + exportedPackage.getExportingBundle() + ")");
+                       this.exportedPackage = exportedPackage;
+
+                       TreeParent bundlesNode = new TreeParent("Dependent Bundles");
+                       this.addChild(bundlesNode);
+                       Map<String, Bundle> bundles = new TreeMap<String, Bundle>();
+                       for (Bundle b : exportedPackage.getImportingBundles()) {
+                               bundles.put(b.getSymbolicName(), b);
+                       }
+                       for (String key : bundles.keySet()) {
+                               addDependentBundles(bundlesNode, bundles.get(key));
+                       }
+               }
+       }
+
+       protected void addDependentBundles(TreeParent parent, Bundle bundle) {
+               TreeParent bundleNode = new TreeParent(bundle.toString());
+               parent.addChild(bundleNode);
+               Map<String, Bundle> bundles = new TreeMap<String, Bundle>();
+               ExportedPackage[] pkgs = packageAdmin.getExportedPackages(bundle);
+               if (pkgs != null)
+                       for (ExportedPackage pkg : pkgs) {
+                               for (Bundle b : pkg.getImportingBundles()) {
+                                       if (!bundles.containsKey(b.getSymbolicName())
+                                                       && b.getBundleId() != bundle.getBundleId()) {
+                                               bundles.put(b.getSymbolicName(), b);
+                                       }
+                               }
+                       }
+
+               for (String key : bundles.keySet()) {
+                       addDependentBundles(bundleNode, bundles.get(key));
+               }
+       }
+
+       class ExportedPackageNode extends TreeParent {
+               private ExportedPackage exportedPackage;
+
+               public ExportedPackageNode(ExportedPackage exportedPackage) {
+                       super(exportedPackage.getName() + " - "
+                                       + exportedPackage.getVersion() + " ("
+                                       + exportedPackage.getExportingBundle() + ")");
+                       this.exportedPackage = exportedPackage;
+                       for (Bundle bundle : exportedPackage.getImportingBundles()) {
+                               addChild(new BundleNode(bundle));
+                       }
+               }
+       }
+}
index 848725036e3c30100a159f43b86918882aa1b104..d2953a684d400476bf716ed6a6c3c3ae486fcd0e 100644 (file)
@@ -1,7 +1,9 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <classpath>
-       <classpathentry kind="src" path="src/main/java"/>
-       <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6"/>
-       <classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
-       <classpathentry kind="output" path="target/classes"/>
+       <classpathentry kind="src" path="src" />
+       <classpathentry kind="con"
+               path="org.eclipse.pde.core.requiredPlugins" />
+       <classpathentry kind="con"
+               path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6" />
+       <classpathentry kind="output" path="bin" />
 </classpath>
diff --git a/org.argeo.security.equinox/.settings/org.eclipse.pde.core.prefs b/org.argeo.security.equinox/.settings/org.eclipse.pde.core.prefs
deleted file mode 100644 (file)
index 87ab381..0000000
+++ /dev/null
@@ -1,4 +0,0 @@
-#Sun Jan 16 11:19:07 CET 2011
-eclipse.preferences.version=1
-pluginProject.extensions=false
-resolve.requirebundle=false
index 3e2615fae0c0d9a92f0b29d6c2e462bf0f376d00..ae2abc5ffab0c719e4bfbba5ae24a3e024355d0a 100644 (file)
@@ -1,4 +1 @@
-bin.includes = META-INF/,\
-               plugin.xml
-source.. = src/main/java/
-output.. = target/classes/
+source.. = src/
\ No newline at end of file
diff --git a/org.argeo.security.equinox/src/main/java/org/argeo/security/equinox/OsSpringLoginModule.java b/org.argeo.security.equinox/src/main/java/org/argeo/security/equinox/OsSpringLoginModule.java
deleted file mode 100644 (file)
index 1a7ebb4..0000000
+++ /dev/null
@@ -1,82 +0,0 @@
-/*
- * Copyright (C) 2007-2012 Argeo GmbH
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *         http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.argeo.security.equinox;
-
-import java.util.Map;
-
-import javax.security.auth.Subject;
-import javax.security.auth.callback.CallbackHandler;
-import javax.security.auth.login.LoginException;
-
-import org.argeo.security.OsAuthenticationToken;
-import org.springframework.security.Authentication;
-import org.springframework.security.AuthenticationManager;
-import org.springframework.security.context.SecurityContextHolder;
-import org.springframework.security.providers.jaas.SecurityContextLoginModule;
-
-/** Login module which caches one subject per thread. */
-public class OsSpringLoginModule extends SecurityContextLoginModule {
-       // private final static Log log =
-       // LogFactory.getLog(OsSpringLoginModule.class);
-
-       private AuthenticationManager authenticationManager;
-
-       private Subject subject;
-
-       public OsSpringLoginModule() {
-
-       }
-
-       @SuppressWarnings("rawtypes")
-       public void initialize(Subject subject, CallbackHandler callbackHandler,
-                       Map sharedState, Map options) {
-               super.initialize(subject, callbackHandler, sharedState, options);
-               this.subject = subject;
-       }
-
-       public boolean login() throws LoginException {
-               // thread already logged in
-               if (SecurityContextHolder.getContext().getAuthentication() != null)
-                       return super.login();
-
-               OsAuthenticationToken oat = new OsAuthenticationToken();
-               Authentication authentication = authenticationManager.authenticate(oat);
-               registerAuthentication(authentication);
-               return super.login();
-       }
-
-       @Override
-       public boolean logout() throws LoginException {
-               subject.getPrincipals().clear();
-               return super.logout();
-       }
-
-       /**
-        * Register an {@link Authentication} in the security context.
-        * 
-        * @param authentication
-        *            has to implement {@link Authentication}.
-        */
-       protected void registerAuthentication(Object authentication) {
-               SecurityContextHolder.getContext().setAuthentication(
-                               (Authentication) authentication);
-       }
-
-       public void setAuthenticationManager(
-                       AuthenticationManager authenticationManager) {
-               this.authenticationManager = authenticationManager;
-       }
-}
diff --git a/org.argeo.security.equinox/src/main/java/org/argeo/security/equinox/SpringLoginModule.java b/org.argeo.security.equinox/src/main/java/org/argeo/security/equinox/SpringLoginModule.java
deleted file mode 100644 (file)
index 6fd179e..0000000
+++ /dev/null
@@ -1,243 +0,0 @@
-/*
- * Copyright (C) 2007-2012 Argeo GmbH
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *         http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.argeo.security.equinox;
-
-import java.util.Locale;
-import java.util.Map;
-import java.util.UUID;
-
-import javax.security.auth.Subject;
-import javax.security.auth.callback.Callback;
-import javax.security.auth.callback.CallbackHandler;
-import javax.security.auth.callback.NameCallback;
-import javax.security.auth.callback.PasswordCallback;
-import javax.security.auth.login.LoginException;
-
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.argeo.security.NodeAuthenticationToken;
-import org.argeo.util.LocaleCallback;
-import org.argeo.util.LocaleUtils;
-import org.springframework.security.Authentication;
-import org.springframework.security.AuthenticationManager;
-import org.springframework.security.BadCredentialsException;
-import org.springframework.security.GrantedAuthority;
-import org.springframework.security.GrantedAuthorityImpl;
-import org.springframework.security.context.SecurityContextHolder;
-import org.springframework.security.providers.anonymous.AnonymousAuthenticationToken;
-import org.springframework.security.providers.jaas.SecurityContextLoginModule;
-
-/** Login module which caches one subject per thread. */
-public class SpringLoginModule extends SecurityContextLoginModule {
-       final static String NODE_REPO_URI = "argeo.node.repo.uri";
-
-       private final static Log log = LogFactory.getLog(SpringLoginModule.class);
-
-       private AuthenticationManager authenticationManager;
-
-       private CallbackHandler callbackHandler;
-
-       private Subject subject;
-
-       private Long waitBetweenFailedLoginAttempts = 5 * 1000l;
-
-       private Boolean remote = false;
-       private Boolean anonymous = false;
-       /** Comma separated list of locales */
-       private String availableLocales = "";
-
-       private String key = null;
-       private String anonymousRole = "ROLE_ANONYMOUS";
-
-       public SpringLoginModule() {
-
-       }
-
-       @SuppressWarnings("rawtypes")
-       public void initialize(Subject subject, CallbackHandler callbackHandler,
-                       Map sharedState, Map options) {
-               super.initialize(subject, callbackHandler, sharedState, options);
-               this.callbackHandler = callbackHandler;
-               this.subject = subject;
-       }
-
-       public boolean login() throws LoginException {
-               try {
-                       // thread already logged in
-                       if (SecurityContextHolder.getContext().getAuthentication() != null)
-                               return super.login();
-
-                       if (remote && anonymous)
-                               throw new LoginException(
-                                               "Cannot have a Spring login module which is remote and anonymous");
-
-                       // reset all principals and credentials
-                       if (log.isTraceEnabled())
-                               log.trace("Resetting all principals and credentials of "
-                                               + subject);
-                       if (subject.getPrincipals() != null)
-                               subject.getPrincipals().clear();
-                       if (subject.getPrivateCredentials() != null)
-                               subject.getPrivateCredentials().clear();
-                       if (subject.getPublicCredentials() != null)
-                               subject.getPublicCredentials().clear();
-
-                       Locale selectedLocale = null;
-                       // deals first with public access since it's simple
-                       if (anonymous) {
-                               // multi locale
-                               if (callbackHandler != null && availableLocales != null
-                                               && !availableLocales.trim().equals("")) {
-                                       LocaleCallback localeCallback = new LocaleCallback(
-                                                       availableLocales);
-                                       callbackHandler.handle(new Callback[] { localeCallback });
-                                       selectedLocale = localeCallback.getSelectedLocale();
-                               }
-
-                               // TODO integrate with JCR?
-                               Object principal = UUID.randomUUID().toString();
-                               GrantedAuthority[] authorities = { new GrantedAuthorityImpl(
-                                               anonymousRole) };
-                               AnonymousAuthenticationToken anonymousToken = new AnonymousAuthenticationToken(
-                                               key, principal, authorities);
-                               Authentication auth = authenticationManager
-                                               .authenticate(anonymousToken);
-                               registerAuthentication(auth);
-                       } else {
-                               if (callbackHandler == null)
-                                       throw new LoginException("No call back handler available");
-
-                               // ask for username and password
-                               NameCallback nameCallback = new NameCallback("User");
-                               PasswordCallback passwordCallback = new PasswordCallback(
-                                               "Password", false);
-                               final String defaultNodeUrl = System
-                                               .getProperty(NODE_REPO_URI,
-                                                               "http://localhost:7070/org.argeo.jcr.webapp/remoting/node");
-                               NameCallback urlCallback = new NameCallback("Site URL",
-                                               defaultNodeUrl);
-                               LocaleCallback localeCallback = new LocaleCallback(
-                                               availableLocales);
-
-                               // handle callbacks
-                               if (remote)
-                                       callbackHandler.handle(new Callback[] { nameCallback,
-                                                       passwordCallback, urlCallback, localeCallback });
-                               else
-                                       callbackHandler.handle(new Callback[] { nameCallback,
-                                                       passwordCallback, localeCallback });
-
-                               selectedLocale = localeCallback.getSelectedLocale();
-
-                               // create credentials
-                               String username = nameCallback.getName();
-                               if (username == null || username.trim().equals(""))
-                                       return false;
-
-                               String password = "";
-                               if (passwordCallback.getPassword() != null)
-                                       password = String.valueOf(passwordCallback.getPassword());
-
-                               NodeAuthenticationToken credentials;
-                               if (remote) {
-                                       String url = urlCallback.getName();
-                                       credentials = new NodeAuthenticationToken(username,
-                                                       password, url);
-                               } else {
-                                       credentials = new NodeAuthenticationToken(username,
-                                                       password);
-                               }
-
-                               Authentication authentication;
-                               try {
-                                       authentication = authenticationManager
-                                                       .authenticate(credentials);
-                               } catch (BadCredentialsException e) {
-                                       // wait between failed login attempts
-                                       Thread.sleep(waitBetweenFailedLoginAttempts);
-                                       throw e;
-                               }
-                               registerAuthentication(authentication);
-                       }
-
-                       if (selectedLocale != null)
-                               LocaleUtils.threadLocale.set(selectedLocale);
-
-                       return super.login();
-               } catch (LoginException e) {
-                       throw e;
-               } catch (ThreadDeath e) {
-                       LoginException le = new LoginException(
-                                       "Spring Security login thread died");
-                       le.initCause(e);
-                       throw le;
-               } catch (Exception e) {
-                       LoginException le = new LoginException(
-                                       "Spring Security login failed");
-                       le.initCause(e);
-                       throw le;
-               }
-       }
-
-       @Override
-       public boolean logout() throws LoginException {
-               subject.getPrincipals().clear();
-               return super.logout();
-       }
-
-       /**
-        * Register an {@link Authentication} in the security context.
-        * 
-        * @param authentication
-        *            has to implement {@link Authentication}.
-        */
-       protected void registerAuthentication(Object authentication) {
-               SecurityContextHolder.getContext().setAuthentication(
-                               (Authentication) authentication);
-       }
-
-       public void setAuthenticationManager(
-                       AuthenticationManager authenticationManager) {
-               this.authenticationManager = authenticationManager;
-       }
-
-       /** Authenticates on a remote node */
-       public void setRemote(Boolean remote) {
-               this.remote = remote;
-       }
-
-       /**
-        * Request anonymous authentication (incompatible with remote)
-        */
-       public void setAnonymous(Boolean anonymous) {
-               this.anonymous = anonymous;
-       }
-
-       /** Role identifying an anonymous user */
-       public void setAnonymousRole(String anonymousRole) {
-               this.anonymousRole = anonymousRole;
-       }
-
-       /** System key */
-       public void setKey(String key) {
-               this.key = key;
-       }
-
-       public void setAvailableLocales(String locales) {
-               this.availableLocales = locales;
-       }
-
-}
diff --git a/org.argeo.security.equinox/src/org/argeo/security/equinox/OsSpringLoginModule.java b/org.argeo.security.equinox/src/org/argeo/security/equinox/OsSpringLoginModule.java
new file mode 100644 (file)
index 0000000..1a7ebb4
--- /dev/null
@@ -0,0 +1,82 @@
+/*
+ * Copyright (C) 2007-2012 Argeo GmbH
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *         http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.argeo.security.equinox;
+
+import java.util.Map;
+
+import javax.security.auth.Subject;
+import javax.security.auth.callback.CallbackHandler;
+import javax.security.auth.login.LoginException;
+
+import org.argeo.security.OsAuthenticationToken;
+import org.springframework.security.Authentication;
+import org.springframework.security.AuthenticationManager;
+import org.springframework.security.context.SecurityContextHolder;
+import org.springframework.security.providers.jaas.SecurityContextLoginModule;
+
+/** Login module which caches one subject per thread. */
+public class OsSpringLoginModule extends SecurityContextLoginModule {
+       // private final static Log log =
+       // LogFactory.getLog(OsSpringLoginModule.class);
+
+       private AuthenticationManager authenticationManager;
+
+       private Subject subject;
+
+       public OsSpringLoginModule() {
+
+       }
+
+       @SuppressWarnings("rawtypes")
+       public void initialize(Subject subject, CallbackHandler callbackHandler,
+                       Map sharedState, Map options) {
+               super.initialize(subject, callbackHandler, sharedState, options);
+               this.subject = subject;
+       }
+
+       public boolean login() throws LoginException {
+               // thread already logged in
+               if (SecurityContextHolder.getContext().getAuthentication() != null)
+                       return super.login();
+
+               OsAuthenticationToken oat = new OsAuthenticationToken();
+               Authentication authentication = authenticationManager.authenticate(oat);
+               registerAuthentication(authentication);
+               return super.login();
+       }
+
+       @Override
+       public boolean logout() throws LoginException {
+               subject.getPrincipals().clear();
+               return super.logout();
+       }
+
+       /**
+        * Register an {@link Authentication} in the security context.
+        * 
+        * @param authentication
+        *            has to implement {@link Authentication}.
+        */
+       protected void registerAuthentication(Object authentication) {
+               SecurityContextHolder.getContext().setAuthentication(
+                               (Authentication) authentication);
+       }
+
+       public void setAuthenticationManager(
+                       AuthenticationManager authenticationManager) {
+               this.authenticationManager = authenticationManager;
+       }
+}
diff --git a/org.argeo.security.equinox/src/org/argeo/security/equinox/SpringLoginModule.java b/org.argeo.security.equinox/src/org/argeo/security/equinox/SpringLoginModule.java
new file mode 100644 (file)
index 0000000..6fd179e
--- /dev/null
@@ -0,0 +1,243 @@
+/*
+ * Copyright (C) 2007-2012 Argeo GmbH
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *         http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.argeo.security.equinox;
+
+import java.util.Locale;
+import java.util.Map;
+import java.util.UUID;
+
+import javax.security.auth.Subject;
+import javax.security.auth.callback.Callback;
+import javax.security.auth.callback.CallbackHandler;
+import javax.security.auth.callback.NameCallback;
+import javax.security.auth.callback.PasswordCallback;
+import javax.security.auth.login.LoginException;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.argeo.security.NodeAuthenticationToken;
+import org.argeo.util.LocaleCallback;
+import org.argeo.util.LocaleUtils;
+import org.springframework.security.Authentication;
+import org.springframework.security.AuthenticationManager;
+import org.springframework.security.BadCredentialsException;
+import org.springframework.security.GrantedAuthority;
+import org.springframework.security.GrantedAuthorityImpl;
+import org.springframework.security.context.SecurityContextHolder;
+import org.springframework.security.providers.anonymous.AnonymousAuthenticationToken;
+import org.springframework.security.providers.jaas.SecurityContextLoginModule;
+
+/** Login module which caches one subject per thread. */
+public class SpringLoginModule extends SecurityContextLoginModule {
+       final static String NODE_REPO_URI = "argeo.node.repo.uri";
+
+       private final static Log log = LogFactory.getLog(SpringLoginModule.class);
+
+       private AuthenticationManager authenticationManager;
+
+       private CallbackHandler callbackHandler;
+
+       private Subject subject;
+
+       private Long waitBetweenFailedLoginAttempts = 5 * 1000l;
+
+       private Boolean remote = false;
+       private Boolean anonymous = false;
+       /** Comma separated list of locales */
+       private String availableLocales = "";
+
+       private String key = null;
+       private String anonymousRole = "ROLE_ANONYMOUS";
+
+       public SpringLoginModule() {
+
+       }
+
+       @SuppressWarnings("rawtypes")
+       public void initialize(Subject subject, CallbackHandler callbackHandler,
+                       Map sharedState, Map options) {
+               super.initialize(subject, callbackHandler, sharedState, options);
+               this.callbackHandler = callbackHandler;
+               this.subject = subject;
+       }
+
+       public boolean login() throws LoginException {
+               try {
+                       // thread already logged in
+                       if (SecurityContextHolder.getContext().getAuthentication() != null)
+                               return super.login();
+
+                       if (remote && anonymous)
+                               throw new LoginException(
+                                               "Cannot have a Spring login module which is remote and anonymous");
+
+                       // reset all principals and credentials
+                       if (log.isTraceEnabled())
+                               log.trace("Resetting all principals and credentials of "
+                                               + subject);
+                       if (subject.getPrincipals() != null)
+                               subject.getPrincipals().clear();
+                       if (subject.getPrivateCredentials() != null)
+                               subject.getPrivateCredentials().clear();
+                       if (subject.getPublicCredentials() != null)
+                               subject.getPublicCredentials().clear();
+
+                       Locale selectedLocale = null;
+                       // deals first with public access since it's simple
+                       if (anonymous) {
+                               // multi locale
+                               if (callbackHandler != null && availableLocales != null
+                                               && !availableLocales.trim().equals("")) {
+                                       LocaleCallback localeCallback = new LocaleCallback(
+                                                       availableLocales);
+                                       callbackHandler.handle(new Callback[] { localeCallback });
+                                       selectedLocale = localeCallback.getSelectedLocale();
+                               }
+
+                               // TODO integrate with JCR?
+                               Object principal = UUID.randomUUID().toString();
+                               GrantedAuthority[] authorities = { new GrantedAuthorityImpl(
+                                               anonymousRole) };
+                               AnonymousAuthenticationToken anonymousToken = new AnonymousAuthenticationToken(
+                                               key, principal, authorities);
+                               Authentication auth = authenticationManager
+                                               .authenticate(anonymousToken);
+                               registerAuthentication(auth);
+                       } else {
+                               if (callbackHandler == null)
+                                       throw new LoginException("No call back handler available");
+
+                               // ask for username and password
+                               NameCallback nameCallback = new NameCallback("User");
+                               PasswordCallback passwordCallback = new PasswordCallback(
+                                               "Password", false);
+                               final String defaultNodeUrl = System
+                                               .getProperty(NODE_REPO_URI,
+                                                               "http://localhost:7070/org.argeo.jcr.webapp/remoting/node");
+                               NameCallback urlCallback = new NameCallback("Site URL",
+                                               defaultNodeUrl);
+                               LocaleCallback localeCallback = new LocaleCallback(
+                                               availableLocales);
+
+                               // handle callbacks
+                               if (remote)
+                                       callbackHandler.handle(new Callback[] { nameCallback,
+                                                       passwordCallback, urlCallback, localeCallback });
+                               else
+                                       callbackHandler.handle(new Callback[] { nameCallback,
+                                                       passwordCallback, localeCallback });
+
+                               selectedLocale = localeCallback.getSelectedLocale();
+
+                               // create credentials
+                               String username = nameCallback.getName();
+                               if (username == null || username.trim().equals(""))
+                                       return false;
+
+                               String password = "";
+                               if (passwordCallback.getPassword() != null)
+                                       password = String.valueOf(passwordCallback.getPassword());
+
+                               NodeAuthenticationToken credentials;
+                               if (remote) {
+                                       String url = urlCallback.getName();
+                                       credentials = new NodeAuthenticationToken(username,
+                                                       password, url);
+                               } else {
+                                       credentials = new NodeAuthenticationToken(username,
+                                                       password);
+                               }
+
+                               Authentication authentication;
+                               try {
+                                       authentication = authenticationManager
+                                                       .authenticate(credentials);
+                               } catch (BadCredentialsException e) {
+                                       // wait between failed login attempts
+                                       Thread.sleep(waitBetweenFailedLoginAttempts);
+                                       throw e;
+                               }
+                               registerAuthentication(authentication);
+                       }
+
+                       if (selectedLocale != null)
+                               LocaleUtils.threadLocale.set(selectedLocale);
+
+                       return super.login();
+               } catch (LoginException e) {
+                       throw e;
+               } catch (ThreadDeath e) {
+                       LoginException le = new LoginException(
+                                       "Spring Security login thread died");
+                       le.initCause(e);
+                       throw le;
+               } catch (Exception e) {
+                       LoginException le = new LoginException(
+                                       "Spring Security login failed");
+                       le.initCause(e);
+                       throw le;
+               }
+       }
+
+       @Override
+       public boolean logout() throws LoginException {
+               subject.getPrincipals().clear();
+               return super.logout();
+       }
+
+       /**
+        * Register an {@link Authentication} in the security context.
+        * 
+        * @param authentication
+        *            has to implement {@link Authentication}.
+        */
+       protected void registerAuthentication(Object authentication) {
+               SecurityContextHolder.getContext().setAuthentication(
+                               (Authentication) authentication);
+       }
+
+       public void setAuthenticationManager(
+                       AuthenticationManager authenticationManager) {
+               this.authenticationManager = authenticationManager;
+       }
+
+       /** Authenticates on a remote node */
+       public void setRemote(Boolean remote) {
+               this.remote = remote;
+       }
+
+       /**
+        * Request anonymous authentication (incompatible with remote)
+        */
+       public void setAnonymous(Boolean anonymous) {
+               this.anonymous = anonymous;
+       }
+
+       /** Role identifying an anonymous user */
+       public void setAnonymousRole(String anonymousRole) {
+               this.anonymousRole = anonymousRole;
+       }
+
+       /** System key */
+       public void setKey(String key) {
+               this.key = key;
+       }
+
+       public void setAvailableLocales(String locales) {
+               this.availableLocales = locales;
+       }
+
+}
index 848725036e3c30100a159f43b86918882aa1b104..d2953a684d400476bf716ed6a6c3c3ae486fcd0e 100644 (file)
@@ -1,7 +1,9 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <classpath>
-       <classpathentry kind="src" path="src/main/java"/>
-       <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6"/>
-       <classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
-       <classpathentry kind="output" path="target/classes"/>
+       <classpathentry kind="src" path="src" />
+       <classpathentry kind="con"
+               path="org.eclipse.pde.core.requiredPlugins" />
+       <classpathentry kind="con"
+               path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6" />
+       <classpathentry kind="output" path="bin" />
 </classpath>
index c41623e1f989b3a34f37891adb20835a26ed9a49..30f715358d984db427238bb1984c0d19b6ca4004 100644 (file)
@@ -1,5 +1 @@
-bin.includes = plugin.xml,\
-               META-INF/,\
-               security-admin.properties
-source.. = src/main/java/
-output.. = target/classes/
+source.. = src/
diff --git a/org.argeo.security.ui.admin/src/main/java/org/argeo/security/ui/admin/SecurityAdminImages.java b/org.argeo.security.ui.admin/src/main/java/org/argeo/security/ui/admin/SecurityAdminImages.java
deleted file mode 100644 (file)
index f7ffa9c..0000000
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Argeo Connect - Data management and communications
- * Copyright (C) 2012 Argeo GmbH
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>
- *
- * Additional permission under GNU GPL version 3 section 7
- *
- * If you modify this Program, or any covered work, by linking or combining it
- * with software covered by the terms of the Eclipse Public License, the
- * licensors of this Program grant you additional permission to convey the
- * resulting work. Corresponding Source for a non-source form of such a
- * combination shall include the source code for the parts of such software
- * which are used as well as that of the covered work.
- */
-package org.argeo.security.ui.admin;
-
-/** Shared icons that must be declared programmatically . */
-public class SecurityAdminImages {
-       @SuppressWarnings("unused")
-       private final static String PREFIX = "icons/";
-}
diff --git a/org.argeo.security.ui.admin/src/main/java/org/argeo/security/ui/admin/SecurityAdminPerspective.java b/org.argeo.security.ui.admin/src/main/java/org/argeo/security/ui/admin/SecurityAdminPerspective.java
deleted file mode 100644 (file)
index c743f56..0000000
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Copyright (C) 2007-2012 Argeo GmbH
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *         http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.argeo.security.ui.admin;
-
-import org.argeo.security.ui.admin.views.RolesView;
-import org.argeo.security.ui.admin.views.UsersView;
-import org.eclipse.ui.IFolderLayout;
-import org.eclipse.ui.IPageLayout;
-import org.eclipse.ui.IPerspectiveFactory;
-
-public class SecurityAdminPerspective implements IPerspectiveFactory {
-       public void createInitialLayout(IPageLayout layout) {
-               String editorArea = layout.getEditorArea();
-               layout.setEditorAreaVisible(true);
-               layout.setFixed(false);
-
-               IFolderLayout left = layout.createFolder("left", IPageLayout.LEFT,
-                               0.65f, editorArea);
-               left.addView(UsersView.ID);
-               left.addView(RolesView.ID);
-       }
-
-}
diff --git a/org.argeo.security.ui.admin/src/main/java/org/argeo/security/ui/admin/SecurityAdminPlugin.java b/org.argeo.security.ui.admin/src/main/java/org/argeo/security/ui/admin/SecurityAdminPlugin.java
deleted file mode 100644 (file)
index 06e9bd5..0000000
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * Copyright (C) 2007-2012 Argeo GmbH
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *         http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.argeo.security.ui.admin;
-
-import org.eclipse.jface.resource.ImageDescriptor;
-import org.eclipse.ui.plugin.AbstractUIPlugin;
-import org.osgi.framework.BundleContext;
-
-public class SecurityAdminPlugin extends AbstractUIPlugin {
-       public static final String PLUGIN_ID = "org.argeo.security.ui.admin"; //$NON-NLS-1$
-       private static SecurityAdminPlugin plugin;
-
-       public SecurityAdminPlugin() {
-       }
-
-       public void start(BundleContext context) throws Exception {
-               super.start(context);
-               plugin = this;
-       }
-
-       public void stop(BundleContext context) throws Exception {
-               plugin = null;
-               super.stop(context);
-       }
-
-       public static SecurityAdminPlugin getDefault() {
-               return plugin;
-       }
-
-       public static ImageDescriptor getImageDescriptor(String path) {
-               return imageDescriptorFromPlugin(PLUGIN_ID, path);
-       }
-
-}
diff --git a/org.argeo.security.ui.admin/src/main/java/org/argeo/security/ui/admin/UserTableComposite.java b/org.argeo.security.ui.admin/src/main/java/org/argeo/security/ui/admin/UserTableComposite.java
deleted file mode 100644 (file)
index 720fade..0000000
+++ /dev/null
@@ -1,367 +0,0 @@
-package org.argeo.security.ui.admin;
-
-import java.util.ArrayList;
-import java.util.List;
-
-import javax.jcr.Node;
-import javax.jcr.NodeIterator;
-import javax.jcr.Property;
-import javax.jcr.PropertyType;
-import javax.jcr.RepositoryException;
-import javax.jcr.Session;
-import javax.jcr.query.QueryManager;
-import javax.jcr.query.QueryResult;
-import javax.jcr.query.qom.Constraint;
-import javax.jcr.query.qom.Ordering;
-import javax.jcr.query.qom.QueryObjectModel;
-import javax.jcr.query.qom.QueryObjectModelFactory;
-import javax.jcr.query.qom.Selector;
-import javax.jcr.query.qom.StaticOperand;
-
-import org.argeo.ArgeoException;
-import org.argeo.eclipse.ui.EclipseUiUtils;
-import org.argeo.eclipse.ui.jcr.JcrUiUtils;
-import org.argeo.eclipse.ui.jcr.lists.ColumnDefinition;
-import org.argeo.eclipse.ui.jcr.lists.NodeViewerComparator;
-import org.argeo.eclipse.ui.jcr.lists.SimpleJcrNodeLabelProvider;
-import org.argeo.eclipse.ui.specific.EclipseUiSpecificUtils;
-import org.argeo.eclipse.ui.utils.ViewerUtils;
-import org.argeo.jcr.ArgeoNames;
-import org.argeo.jcr.ArgeoTypes;
-import org.argeo.jcr.JcrUtils;
-import org.eclipse.jface.viewers.CheckboxTableViewer;
-import org.eclipse.jface.viewers.ColumnLabelProvider;
-import org.eclipse.jface.viewers.IStructuredContentProvider;
-import org.eclipse.jface.viewers.TableViewer;
-import org.eclipse.jface.viewers.TableViewerColumn;
-import org.eclipse.jface.viewers.Viewer;
-import org.eclipse.swt.SWT;
-import org.eclipse.swt.events.ModifyEvent;
-import org.eclipse.swt.events.ModifyListener;
-import org.eclipse.swt.events.SelectionAdapter;
-import org.eclipse.swt.events.SelectionEvent;
-import org.eclipse.swt.graphics.Font;
-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.Text;
-
-public class UserTableComposite extends Composite implements ArgeoNames {
-       // private final static Log log =
-       // LogFactory.getLog(UserTableComposite.class);
-
-       private static final long serialVersionUID = -7385959046279360420L;
-
-       private TableViewer usersViewer;
-       private Text filterTxt;
-       private final static String FILTER_HELP_MSG = "Type filter criterion "
-                       + "separated by a space";
-       private Session session;
-
-       private Font italic;
-       private Font bold;
-
-       private boolean hasFilter;
-       private boolean hasSelectionColumn;
-
-       // private List<Node> selectedItems = new ArrayList<Node>();
-
-       /**
-        * Overwrite to display other columns
-        */
-       public List<ColumnDefinition> getColumnsDef() {
-               List<ColumnDefinition> columnDefs = new ArrayList<ColumnDefinition>();
-
-               // User ID
-               columnDefs.add(new ColumnDefinition(null, ARGEO_USER_ID,
-                               PropertyType.STRING, "User ID", 100));
-               // Displayed name
-               columnDefs.add(new ColumnDefinition(null, Property.JCR_TITLE,
-                               PropertyType.STRING, "Name", 150));
-
-               // E-mail
-               columnDefs.add(new ColumnDefinition(null, ARGEO_PRIMARY_EMAIL,
-                               PropertyType.STRING, "E-mail", 150));
-
-               // Description
-               columnDefs.add(new ColumnDefinition(null, Property.JCR_DESCRIPTION,
-                               PropertyType.STRING, "Description", 200));
-
-               return columnDefs;
-       }
-
-       public UserTableComposite(Composite parent, int style, Session session) {
-               super(parent, style);
-               this.session = session;
-       }
-
-       /**
-        * 
-        * @param addFilter
-        *            choose to add a field to filter results or not
-        * @param addSelection
-        *            choose to add a column to select some of the displayed results
-        *            or not
-        */
-       public void populate(boolean addFilter, boolean addSelection) {
-               // initialization
-               Composite parent = this;
-               italic = EclipseUiUtils.getItalicFont(parent);
-               bold = EclipseUiUtils.getBoldFont(parent);
-               hasFilter = addFilter;
-               hasSelectionColumn = addSelection;
-
-               // Main Layout
-               this.setLayout(new GridLayout(1, false));
-               if (hasFilter)
-                       createFilterPart(parent);
-               usersViewer = createTableViewer(parent);
-               EclipseUiSpecificUtils.enableToolTipSupport(usersViewer);
-               usersViewer.setContentProvider(new UsersContentProvider());
-               refreshFilteredList();
-       }
-
-       public List<Node> getSelectedUsers() {
-               if (hasSelectionColumn) {
-                       Object[] elements = ((CheckboxTableViewer) usersViewer)
-                                       .getCheckedElements();
-
-                       List<Node> result = new ArrayList<Node>();
-                       for (Object obj : elements) {
-                               result.add((Node) obj);
-                       }
-                       return result;
-               } else
-                       throw new ArgeoException("Unvalid request: no selection column "
-                                       + "has been created for the current table");
-       }
-
-       /** Returns the User table viewer, typically to add doubleclick listener */
-       public TableViewer getTableViewer() {
-               return usersViewer;
-       }
-       
-       /** Returns filter String or null*/
-       protected String getFilterString() {
-               return hasFilter ? filterTxt.getText() : null;
-       }
-       
-       
-
-       private TableViewer createTableViewer(final Composite parent) {
-               int style = SWT.MULTI | SWT.H_SCROLL | SWT.V_SCROLL;
-               if (hasSelectionColumn)
-                       style = style | SWT.CHECK;
-
-               Table table = new Table(parent, style);
-               table.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
-
-               TableViewer viewer;
-               if (hasSelectionColumn)
-                       viewer = new CheckboxTableViewer(table);
-               else
-                       viewer = new TableViewer(table);
-               table.setLinesVisible(true);
-               table.setHeaderVisible(true);
-
-               // pass a mapping between col index and property name to the comparator.
-               // List<String> propertiesList = new ArrayList<String>();
-
-               TableViewerColumn column;
-               int offset = 0;
-               if (hasSelectionColumn) {
-                       offset = 1;
-                       column = ViewerUtils.createTableViewerColumn(viewer, "", SWT.NONE,
-                                       25);
-                       column.setLabelProvider(new ColumnLabelProvider() {
-                               private static final long serialVersionUID = 1L;
-
-                               @Override
-                               public String getText(Object element) {
-                                       return null;
-                               }
-                       });
-                       SelectionAdapter selectionAdapter = new SelectionAdapter() {
-                               private static final long serialVersionUID = 1L;
-
-                               boolean allSelected = false;
-
-                               @Override
-                               public void widgetSelected(SelectionEvent e) {
-                                       allSelected = !allSelected;
-                                       ((CheckboxTableViewer) usersViewer)
-                                                       .setAllChecked(allSelected);
-                               }
-                       };
-                       column.getColumn().addSelectionListener(selectionAdapter);
-               }
-
-               // Create other columns
-               List<ColumnDefinition> colDefs = getColumnsDef();
-
-               NodeViewerComparator comparator = new NodeViewerComparator();
-               int i = offset;
-               for (ColumnDefinition colDef : colDefs) {
-                       column = ViewerUtils.createTableViewerColumn(viewer,
-                                       colDef.getHeaderLabel(), SWT.NONE, colDef.getColumnSize());
-                       column.setLabelProvider(new CLProvider(colDef.getPropertyName()));
-                       column.getColumn().addSelectionListener(
-                                       JcrUiUtils.getNodeSelectionAdapter(i,
-                                                       colDef.getPropertyType(), colDef.getPropertyName(),
-                                                       comparator, viewer));
-                       i++;
-               }
-
-               // IMPORTANT: initialize comparator before setting it
-               ColumnDefinition firstCol = colDefs.get(0);
-               comparator.setColumn(firstCol.getPropertyType(),
-                               firstCol.getPropertyName());
-               viewer.setComparator(comparator);
-
-               return viewer;
-       }
-
-       private class CLProvider extends SimpleJcrNodeLabelProvider {
-
-               private static final long serialVersionUID = 1L;
-
-               public CLProvider(String propertyName) {
-                       super(propertyName);
-               }
-
-               public String getToolTipText(Object element) {
-                       return getText(element);
-               }
-
-               @Override
-               public Font getFont(Object elem) {
-                       // self
-                       String username = getProperty(elem, ARGEO_USER_ID);
-                       if (username.equals(session.getUserID()))
-                               return bold;
-
-                       // disabled
-                       try {
-                               Node userProfile = (Node) elem;
-                               // Node userProfile = userHome.getNode(ARGEO_PROFILE);
-                               if (!userProfile.getProperty(ARGEO_ENABLED).getBoolean())
-                                       return italic;
-                               else
-                                       return null;
-                       } catch (RepositoryException e) {
-                               throw new ArgeoException("Cannot get font for " + username, e);
-                       }
-               }
-       }
-
-       @Override
-       public boolean setFocus() {
-               usersViewer.getTable().setFocus();
-               return true;
-       }
-
-       @Override
-       public void dispose() {
-               super.dispose();
-       }
-
-       public void refresh() {
-               refreshFilteredList();
-       }
-
-       private String getProperty(Object element, String name) {
-               try {
-                       Node userProfile = (Node) element;
-                       return userProfile.hasProperty(name) ? userProfile
-                                       .getProperty(name).getString() : "";
-               } catch (RepositoryException e) {
-                       throw new ArgeoException("Cannot get property " + name, e);
-               }
-       }
-
-       private class UsersContentProvider implements IStructuredContentProvider {
-               private static final long serialVersionUID = 1L;
-
-               public Object[] getElements(Object inputElement) {
-                       return (Object[]) inputElement;
-               }
-
-               public void dispose() {
-               }
-
-               public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
-               }
-       }
-
-       /* MANAGE FILTER */
-       private void createFilterPart(Composite parent) {
-               // Text Area for the filter
-               filterTxt = new Text(parent, SWT.BORDER | SWT.SEARCH | SWT.ICON_SEARCH
-                               | SWT.ICON_CANCEL);
-               filterTxt.setMessage(FILTER_HELP_MSG);
-               filterTxt.setLayoutData(new GridData(GridData.GRAB_HORIZONTAL
-                               | GridData.HORIZONTAL_ALIGN_FILL));
-               filterTxt.addModifyListener(new ModifyListener() {
-                       private static final long serialVersionUID = 1L;
-
-                       public void modifyText(ModifyEvent event) {
-                               refreshFilteredList();
-                       }
-               });
-       }
-
-       /**
-        * Refresh the user list: caller might overwrite in order to display a
-        * subset of all users, typically to remove current user from the list
-        */
-       protected void refreshFilteredList() {
-               List<Node> nodes;
-               try {
-                       nodes = JcrUtils.nodeIteratorToList(listFilteredElements(session,
-                                       hasFilter ? filterTxt.getText() : null));
-                       usersViewer.setInput(nodes.toArray());
-               } catch (RepositoryException e) {
-                       throw new ArgeoException("Unable to list users", e);
-               }
-       }
-
-       /**
-        * Build repository request : caller might overwrite in order to display a
-        * subset of all users
-        */
-       protected NodeIterator listFilteredElements(Session session, String filter)
-                       throws RepositoryException {
-               QueryManager queryManager = session.getWorkspace().getQueryManager();
-               QueryObjectModelFactory factory = queryManager.getQOMFactory();
-
-               Selector source = factory.selector(ArgeoTypes.ARGEO_USER_PROFILE,
-                               ArgeoTypes.ARGEO_USER_PROFILE);
-
-               // Dynamically build constraint depending on the filter String
-               Constraint defaultC = null;
-               if (filter != null && !"".equals(filter.trim())) {
-                       String[] strs = filter.trim().split(" ");
-                       for (String token : strs) {
-                               StaticOperand so = factory.literal(session.getValueFactory()
-                                               .createValue("*" + token + "*"));
-                               Constraint currC = factory.fullTextSearch(
-                                               source.getSelectorName(), null, so);
-                               if (defaultC == null)
-                                       defaultC = currC;
-                               else
-                                       defaultC = factory.and(defaultC, currC);
-                       }
-               }
-
-               Ordering order = factory.ascending(factory.propertyValue(
-                               source.getSelectorName(), ARGEO_USER_ID));
-               Ordering[] orderings = { order };
-
-               QueryObjectModel query = factory.createQuery(source, defaultC,
-                               orderings, null);
-
-               QueryResult result = query.execute();
-               return result.getNodes();
-       }
-}
\ No newline at end of file
diff --git a/org.argeo.security.ui.admin/src/main/java/org/argeo/security/ui/admin/commands/AddRole.java b/org.argeo.security.ui.admin/src/main/java/org/argeo/security/ui/admin/commands/AddRole.java
deleted file mode 100644 (file)
index a1008f6..0000000
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * Copyright (C) 2007-2012 Argeo GmbH
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *         http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.argeo.security.ui.admin.commands;
-
-import org.argeo.ArgeoException;
-import org.argeo.security.UserAdminService;
-import org.argeo.security.ui.admin.editors.ArgeoUserEditor;
-import org.argeo.security.ui.admin.views.RolesView;
-import org.eclipse.core.commands.AbstractHandler;
-import org.eclipse.core.commands.ExecutionEvent;
-import org.eclipse.core.commands.ExecutionException;
-import org.eclipse.ui.IEditorReference;
-import org.eclipse.ui.IWorkbenchPage;
-import org.eclipse.ui.handlers.HandlerUtil;
-
-/** Add a new role. */
-public class AddRole extends AbstractHandler {
-       public final static String COMMAND_ID = "org.argeo.security.ui.admin.addRole";
-       private UserAdminService userAdminService;
-       private String rolePrefix = "ROLE_";
-
-       public Object execute(ExecutionEvent event) throws ExecutionException {
-               RolesView rolesView = (RolesView) HandlerUtil
-                               .getActiveWorkbenchWindow(event).getActivePage()
-                               .findView(RolesView.ID);
-               String role = rolesView.getNewRole();
-               if (role.trim().equals(""))
-                       return null;
-               if (role.equals(rolesView.getAddNewRoleText()))
-                       return null;
-               role = role.trim().toUpperCase();
-               if (!role.startsWith(rolePrefix))
-                       role = rolePrefix + role;
-               if (userAdminService.listEditableRoles().contains(role))
-                       throw new ArgeoException("Role " + role + " already exists");
-               userAdminService.newRole(role);
-               rolesView.refresh();
-
-               // refresh editors
-               IEditorReference[] refs = HandlerUtil.getActiveWorkbenchWindow(event)
-                               .getActivePage()
-                               .findEditors(null, ArgeoUserEditor.ID, IWorkbenchPage.MATCH_ID);
-               for (IEditorReference ref : refs) {
-                       ArgeoUserEditor userEditor = (ArgeoUserEditor) ref.getEditor(false);
-                       if (userEditor != null) {
-                               userEditor.refresh();
-                       }
-               }
-               return null;
-       }
-
-       public void setUserAdminService(UserAdminService userAdminService) {
-               this.userAdminService = userAdminService;
-       }
-
-}
diff --git a/org.argeo.security.ui.admin/src/main/java/org/argeo/security/ui/admin/commands/DeleteRole.java b/org.argeo.security.ui.admin/src/main/java/org/argeo/security/ui/admin/commands/DeleteRole.java
deleted file mode 100644 (file)
index 6cba11e..0000000
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
- * Copyright (C) 2007-2012 Argeo GmbH
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *         http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.argeo.security.ui.admin.commands;
-
-import java.util.ArrayList;
-import java.util.Iterator;
-import java.util.List;
-
-import org.argeo.security.UserAdminService;
-import org.argeo.security.ui.admin.views.RolesView;
-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.jface.viewers.IStructuredSelection;
-import org.eclipse.ui.handlers.HandlerUtil;
-
-/** Deletes the selected roles */
-public class DeleteRole extends AbstractHandler {
-       private UserAdminService userAdminService;
-
-       @SuppressWarnings("unchecked")
-       public Object execute(ExecutionEvent event) throws ExecutionException {
-               ISelection selection = HandlerUtil.getCurrentSelection(event);
-               if (selection.isEmpty())
-                       return null;
-
-               List<String> toDelete = new ArrayList<String>();
-               Iterator<String> it = ((IStructuredSelection) selection).iterator();
-               while (it.hasNext()) {
-                       toDelete.add(it.next());
-               }
-
-               if (!MessageDialog
-                               .openQuestion(
-                                               HandlerUtil.getActiveShell(event),
-                                               "Delete Role",
-                                               "Are you sure that you want to delete "
-                                                               + toDelete
-                                                               + "?\n"
-                                                               + "This may lead to inconsistencies in the application."))
-                       return null;
-
-               for (String role : toDelete) {
-                       userAdminService.deleteRole(role);
-               }
-
-               RolesView view = (RolesView) HandlerUtil
-                               .getActiveWorkbenchWindow(event).getActivePage()
-                               .findView(RolesView.ID);
-               view.refresh();
-               return null;
-       }
-
-       public void setUserAdminService(UserAdminService userAdminService) {
-               this.userAdminService = userAdminService;
-       }
-}
\ No newline at end of file
diff --git a/org.argeo.security.ui.admin/src/main/java/org/argeo/security/ui/admin/commands/DeleteUser.java b/org.argeo.security.ui.admin/src/main/java/org/argeo/security/ui/admin/commands/DeleteUser.java
deleted file mode 100644 (file)
index ccf360f..0000000
+++ /dev/null
@@ -1,104 +0,0 @@
-/*
- * Copyright (C) 2007-2012 Argeo GmbH
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *         http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.argeo.security.ui.admin.commands;
-
-import java.util.Iterator;
-import java.util.Map;
-import java.util.TreeMap;
-
-import javax.jcr.Node;
-import javax.jcr.RepositoryException;
-import javax.jcr.Session;
-
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.argeo.ArgeoException;
-import org.argeo.jcr.ArgeoNames;
-import org.argeo.jcr.JcrUtils;
-import org.argeo.security.UserAdminService;
-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.jface.viewers.IStructuredSelection;
-import org.eclipse.ui.handlers.HandlerUtil;
-
-/** Deletes the selected user nodes */
-public class DeleteUser extends AbstractHandler {
-       private final static Log log = LogFactory.getLog(DeleteUser.class);
-
-       private UserAdminService userAdminService;
-
-       @SuppressWarnings("unchecked")
-       public Object execute(ExecutionEvent event) throws ExecutionException {
-               ISelection selection = HandlerUtil.getCurrentSelection(event);
-               if (selection.isEmpty())
-                       return null;
-
-               Map<String, Node> toDelete = new TreeMap<String, Node>();
-               Iterator<Node> it = ((IStructuredSelection) selection).iterator();
-               nodes: while (it.hasNext()) {
-                       Node profileNode = it.next();
-                       try {
-                               String userName = profileNode.getProperty(
-                                               ArgeoNames.ARGEO_USER_ID).getString();
-                               if (userName.equals(profileNode.getSession().getUserID())) {
-                                       log.warn("Cannot delete its own user: " + userName);
-                                       continue nodes;
-                               }
-                               toDelete.put(userName, profileNode);
-                       } catch (RepositoryException e) {
-                               log.warn("Cannot interpred user " + profileNode);
-                       }
-               }
-
-               if (!MessageDialog
-                               .openQuestion(
-                                               HandlerUtil.getActiveShell(event),
-                                               "Delete User",
-                                               "Are you sure that you want to delete users "
-                                                               + toDelete.keySet()
-                                                               + "?\n"
-                                                               + "This may lead to inconsistencies in the application."))
-                       return null;
-
-               for (String username : toDelete.keySet()) {
-                       Session session = null;
-                       try {
-                               Node profileNode = toDelete.get(username);
-                               userAdminService.deleteUser(username);
-                               profileNode.getParent().remove();
-                               session = profileNode.getSession();
-                               session.save();
-                       } catch (RepositoryException e) {
-                               JcrUtils.discardQuietly(session);
-                               throw new ArgeoException("Cannot list users", e);
-                       }
-               }
-
-               userAdminService.synchronize();
-               // UsersView view = (UsersView) HandlerUtil
-               // .getActiveWorkbenchWindow(event).getActivePage()
-               // .findView(UsersView.ID);
-               // view.refresh();
-               return null;
-       }
-
-       public void setUserAdminService(UserAdminService userAdminService) {
-               this.userAdminService = userAdminService;
-       }
-}
\ No newline at end of file
diff --git a/org.argeo.security.ui.admin/src/main/java/org/argeo/security/ui/admin/commands/NewUser.java b/org.argeo.security.ui.admin/src/main/java/org/argeo/security/ui/admin/commands/NewUser.java
deleted file mode 100644 (file)
index 660896d..0000000
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- * Copyright (C) 2007-2012 Argeo GmbH
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *         http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.argeo.security.ui.admin.commands;
-
-import javax.jcr.Repository;
-import javax.jcr.Session;
-
-import org.argeo.jcr.JcrUtils;
-import org.argeo.security.UserAdminService;
-import org.argeo.security.jcr.JcrSecurityModel;
-import org.argeo.security.ui.admin.wizards.NewUserWizard;
-import org.eclipse.core.commands.AbstractHandler;
-import org.eclipse.core.commands.ExecutionEvent;
-import org.eclipse.core.commands.ExecutionException;
-import org.eclipse.jface.wizard.WizardDialog;
-import org.eclipse.ui.handlers.HandlerUtil;
-
-/** Launch a wizard that enables creation of a new user. */
-public class NewUser extends AbstractHandler {
-       private Repository repository;
-       private UserAdminService userAdminService;
-       private JcrSecurityModel jcrSecurityModel;
-
-       public Object execute(ExecutionEvent event) throws ExecutionException {
-               Session session = null;
-               try {
-                       session = repository.login();
-                       NewUserWizard newUserWizard = new NewUserWizard(session,
-                                       userAdminService, jcrSecurityModel);
-                       WizardDialog dialog = new WizardDialog(
-                                       HandlerUtil.getActiveShell(event), newUserWizard);
-                       dialog.open();
-               } catch (Exception e) {
-                       throw new ExecutionException("Cannot open wizard", e);
-               } finally {
-                       JcrUtils.logoutQuietly(session);
-               }
-               return null;
-       }
-
-       public void setRepository(Repository repository) {
-               this.repository = repository;
-       }
-
-       public void setUserAdminService(UserAdminService userAdminService) {
-               this.userAdminService = userAdminService;
-       }
-
-       public void setJcrSecurityModel(JcrSecurityModel jcrSecurityModel) {
-               this.jcrSecurityModel = jcrSecurityModel;
-       }
-
-}
diff --git a/org.argeo.security.ui.admin/src/main/java/org/argeo/security/ui/admin/commands/OpenArgeoUserEditor.java b/org.argeo.security.ui.admin/src/main/java/org/argeo/security/ui/admin/commands/OpenArgeoUserEditor.java
deleted file mode 100644 (file)
index bae928c..0000000
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * Copyright (C) 2007-2012 Argeo GmbH
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *         http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.argeo.security.ui.admin.commands;
-
-import org.argeo.security.ui.admin.editors.ArgeoUserEditor;
-import org.argeo.security.ui.admin.editors.ArgeoUserEditorInput;
-import org.eclipse.core.commands.AbstractHandler;
-import org.eclipse.core.commands.ExecutionEvent;
-import org.eclipse.core.commands.ExecutionException;
-import org.eclipse.ui.IWorkbenchPage;
-import org.eclipse.ui.handlers.HandlerUtil;
-
-/** Command handler to set visible or open a Argeo user. */
-public class OpenArgeoUserEditor extends AbstractHandler {
-       public final static String COMMAND_ID = "org.argeo.security.ui.admin.openArgeoUserEditor";
-       public final static String PARAM_USERNAME = "org.argeo.security.ui.admin.username";
-
-       public Object execute(ExecutionEvent event) throws ExecutionException {
-               try {
-                       ArgeoUserEditorInput editorInput = new ArgeoUserEditorInput(
-                                       event.getParameter(PARAM_USERNAME));
-                       IWorkbenchPage activePage = HandlerUtil.getActiveWorkbenchWindow(
-                                       event).getActivePage();
-                       activePage.openEditor(editorInput, ArgeoUserEditor.ID);
-               } catch (Exception e) {
-                       throw new ExecutionException("Cannot open editor", e);
-               }
-               return null;
-       }
-}
diff --git a/org.argeo.security.ui.admin/src/main/java/org/argeo/security/ui/admin/commands/RefreshRoles.java b/org.argeo.security.ui.admin/src/main/java/org/argeo/security/ui/admin/commands/RefreshRoles.java
deleted file mode 100644 (file)
index 41c78f0..0000000
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Copyright (C) 2007-2012 Argeo GmbH
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *         http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.argeo.security.ui.admin.commands;
-
-import org.eclipse.core.commands.AbstractHandler;
-import org.eclipse.core.commands.ExecutionEvent;
-import org.eclipse.core.commands.ExecutionException;
-
-/**
- * Refreshes the roles view.
- */
-public class RefreshRoles extends AbstractHandler {
-       public Object execute(ExecutionEvent event) throws ExecutionException {
-
-               return null;
-       }
-
-}
\ No newline at end of file
diff --git a/org.argeo.security.ui.admin/src/main/java/org/argeo/security/ui/admin/commands/RefreshUsersList.java b/org.argeo.security.ui.admin/src/main/java/org/argeo/security/ui/admin/commands/RefreshUsersList.java
deleted file mode 100644 (file)
index e4c14ab..0000000
+++ /dev/null
@@ -1,100 +0,0 @@
-/*
- * Copyright (C) 2007-2012 Argeo GmbH
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *         http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.argeo.security.ui.admin.commands;
-
-import java.util.Set;
-
-import javax.jcr.Node;
-import javax.jcr.NodeIterator;
-import javax.jcr.Repository;
-import javax.jcr.RepositoryException;
-import javax.jcr.Session;
-import javax.jcr.query.Query;
-
-import org.argeo.ArgeoException;
-import org.argeo.jcr.ArgeoNames;
-import org.argeo.jcr.ArgeoTypes;
-import org.argeo.jcr.JcrUtils;
-import org.argeo.security.UserAdminService;
-import org.argeo.security.ui.admin.views.UsersView;
-import org.eclipse.core.commands.AbstractHandler;
-import org.eclipse.core.commands.ExecutionEvent;
-import org.eclipse.core.commands.ExecutionException;
-import org.eclipse.ui.IWorkbenchPart;
-import org.eclipse.ui.handlers.HandlerUtil;
-
-/**
- * Refreshes the main user list, removing nodes which are not referenced by user
- * admin service.
- */
-public class RefreshUsersList extends AbstractHandler {
-       private UserAdminService userAdminService;
-       private Repository repository;
-
-       public Object execute(ExecutionEvent event) throws ExecutionException {
-               Set<String> users = userAdminService.listUsers();
-               Session session = null;
-               try {
-                       session = repository.login();
-                       Query query = session
-                                       .getWorkspace()
-                                       .getQueryManager()
-                                       .createQuery(
-                                                       "select * from [" + ArgeoTypes.ARGEO_USER_HOME
-                                                                       + "]", Query.JCR_SQL2);
-                       NodeIterator nit = query.execute().getNodes();
-                       while (nit.hasNext()) {
-                               Node node = nit.nextNode();
-                               String username = node.getProperty(ArgeoNames.ARGEO_USER_ID)
-                                               .getString();
-                               if (!users.contains(username))
-                                       node.remove();
-                       }
-                       session.save();
-               } catch (RepositoryException e) {
-                       JcrUtils.discardQuietly(session);
-                       throw new ArgeoException("Cannot list users", e);
-               } finally {
-                       JcrUtils.logoutQuietly(session);
-               }
-               userAdminService.synchronize();
-
-               // FIXME try to refresh views that extend the UsersView and have another
-               // ID
-               IWorkbenchPart part = HandlerUtil.getActiveWorkbenchWindow(event)
-                               .getActivePage().getActivePart();
-               if (part instanceof UsersView)
-                       ((UsersView) part).refresh();
-
-               // Try to refresh UsersView if opened
-               UsersView view = (UsersView) HandlerUtil
-                               .getActiveWorkbenchWindow(event).getActivePage()
-                               .findView(UsersView.ID);
-               if (view != null)
-                       view.refresh();
-
-               return null;
-       }
-
-       public void setUserAdminService(UserAdminService userAdminService) {
-               this.userAdminService = userAdminService;
-       }
-
-       public void setRepository(Repository repository) {
-               this.repository = repository;
-       }
-
-}
\ No newline at end of file
diff --git a/org.argeo.security.ui.admin/src/main/java/org/argeo/security/ui/admin/commands/SaveArgeoUser.java b/org.argeo.security.ui.admin/src/main/java/org/argeo/security/ui/admin/commands/SaveArgeoUser.java
deleted file mode 100644 (file)
index bd16f8b..0000000
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * Copyright (C) 2007-2012 Argeo GmbH
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *         http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.argeo.security.ui.admin.commands;
-
-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.swt.widgets.Display;
-import org.eclipse.ui.IEditorPart;
-import org.eclipse.ui.IWorkbenchPart;
-import org.eclipse.ui.handlers.HandlerUtil;
-
-/** Save the currently edited Argeo user. */
-public class SaveArgeoUser extends AbstractHandler {
-       public final static String COMMAND_ID = "org.argeo.security.ui.admin.saveArgeoUser";
-
-       public Object execute(ExecutionEvent event) throws ExecutionException {
-               try {
-                       IWorkbenchPart iwp = HandlerUtil.getActiveWorkbenchWindow(event)
-                                       .getActivePage().getActivePart();
-
-                       if (!(iwp instanceof IEditorPart))
-                               return null;
-                       IEditorPart editor = (IEditorPart) iwp;
-                       editor.doSave(null);
-               } catch (Exception e) {
-                       MessageDialog.openError(Display.getDefault().getActiveShell(),
-                                       "Error", "Cannot save user: " + e.getMessage());
-               }
-               return null;
-       }
-
-}
diff --git a/org.argeo.security.ui.admin/src/main/java/org/argeo/security/ui/admin/commands/UserBatchUpdate.java b/org.argeo.security.ui.admin/src/main/java/org/argeo/security/ui/admin/commands/UserBatchUpdate.java
deleted file mode 100644 (file)
index 657dfc7..0000000
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- * Copyright (C) 2007-2012 Argeo GmbH
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *         http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.argeo.security.ui.admin.commands;
-
-import javax.jcr.Repository;
-import javax.jcr.Session;
-
-import org.argeo.jcr.JcrUtils;
-import org.argeo.security.UserAdminService;
-import org.argeo.security.jcr.JcrSecurityModel;
-import org.argeo.security.ui.admin.wizards.UserBatchUpdateWizard;
-import org.eclipse.core.commands.AbstractHandler;
-import org.eclipse.core.commands.ExecutionEvent;
-import org.eclipse.core.commands.ExecutionException;
-import org.eclipse.jface.wizard.WizardDialog;
-import org.eclipse.ui.handlers.HandlerUtil;
-
-/** Launch a wizard to update various properties about users in JCR. */
-public class UserBatchUpdate extends AbstractHandler {
-       private Repository repository;
-       private UserAdminService userAdminService;
-       private JcrSecurityModel jcrSecurityModel;
-
-       public Object execute(ExecutionEvent event) throws ExecutionException {
-               Session session = null;
-               try {
-                       session = repository.login();
-                       UserBatchUpdateWizard userBatchUpdateWizard = new UserBatchUpdateWizard(session,
-                                       userAdminService, jcrSecurityModel);
-                       WizardDialog dialog = new WizardDialog(
-                                       HandlerUtil.getActiveShell(event), userBatchUpdateWizard);
-                       dialog.open();
-               } catch (Exception e) {
-                       throw new ExecutionException("Cannot open wizard", e);
-               } finally {
-                       JcrUtils.logoutQuietly(session);
-               }
-               return null;
-       }
-
-       public void setRepository(Repository repository) {
-               this.repository = repository;
-       }
-
-       public void setUserAdminService(UserAdminService userAdminService) {
-               this.userAdminService = userAdminService;
-       }
-
-       public void setJcrSecurityModel(JcrSecurityModel jcrSecurityModel) {
-               this.jcrSecurityModel = jcrSecurityModel;
-       }
-
-}
diff --git a/org.argeo.security.ui.admin/src/main/java/org/argeo/security/ui/admin/editors/ArgeoUserEditor.java b/org.argeo.security.ui.admin/src/main/java/org/argeo/security/ui/admin/editors/ArgeoUserEditor.java
deleted file mode 100644 (file)
index ebc0831..0000000
+++ /dev/null
@@ -1,158 +0,0 @@
-/*
- * Copyright (C) 2007-2012 Argeo GmbH
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *         http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.argeo.security.ui.admin.editors;
-
-import javax.jcr.Node;
-import javax.jcr.Repository;
-import javax.jcr.RepositoryException;
-import javax.jcr.Session;
-
-import org.argeo.ArgeoException;
-import org.argeo.jcr.JcrUtils;
-import org.argeo.jcr.UserJcrUtils;
-import org.argeo.security.UserAdminService;
-import org.argeo.security.jcr.JcrUserDetails;
-import org.argeo.security.ui.admin.SecurityAdminPlugin;
-import org.argeo.security.ui.admin.views.UsersView;
-import org.eclipse.core.runtime.IProgressMonitor;
-import org.eclipse.ui.IEditorInput;
-import org.eclipse.ui.IEditorSite;
-import org.eclipse.ui.IWorkbench;
-import org.eclipse.ui.PartInitException;
-import org.eclipse.ui.forms.editor.FormEditor;
-import org.springframework.security.GrantedAuthority;
-
-/** Editor for an Argeo user. */
-public class ArgeoUserEditor extends FormEditor {
-       public final static String ID = SecurityAdminPlugin.PLUGIN_ID
-                       + ".adminArgeoUserEditor";
-
-       /* DEPENDENCY INJECTION */
-       private Session session;
-       private UserAdminService userAdminService;
-
-       // private Node userHome;
-       private Node userProfile;
-       private JcrUserDetails userDetails;
-
-       public void init(IEditorSite site, IEditorInput input)
-                       throws PartInitException {
-               super.init(site, input);
-               String username = ((ArgeoUserEditorInput) getEditorInput())
-                               .getUsername();
-               userProfile = UserJcrUtils.getUserProfile(session, username);
-
-               if (userAdminService.userExists(username)) {
-                       userDetails = (JcrUserDetails) userAdminService
-                                       .loadUserByUsername(username);
-               } else {
-                       GrantedAuthority[] authorities = {};
-                       try {
-                               userDetails = new JcrUserDetails(session, username, null,
-                                               authorities);
-                       } catch (RepositoryException e) {
-                               throw new ArgeoException("Cannot retrieve disabled JCR profile");
-                       }
-               }
-
-               this.setPartProperty("name", username != null ? username : "<new user>");
-               setPartName(username != null ? username : "<new user>");
-       }
-
-       protected void addPages() {
-               try {
-                       addPage(new DefaultUserMainPage(this, userProfile));
-                       addPage(new UserRolesPage(this, userDetails, userAdminService));
-               } catch (Exception e) {
-                       throw new ArgeoException("Cannot add pages", e);
-               }
-       }
-
-       @Override
-       public void doSave(IProgressMonitor monitor) {
-               // list pages
-               // TODO: make it more generic
-               DefaultUserMainPage defaultUserMainPage = (DefaultUserMainPage) findPage(DefaultUserMainPage.ID);
-               if (defaultUserMainPage.isDirty()) {
-                       defaultUserMainPage.doSave(monitor);
-                       String newPassword = defaultUserMainPage.getNewPassword();
-                       defaultUserMainPage.resetNewPassword();
-                       if (newPassword != null)
-                               userDetails = userDetails.cloneWithNewPassword(newPassword);
-               }
-
-               UserRolesPage userRolesPage = (UserRolesPage) findPage(UserRolesPage.ID);
-               if (userRolesPage.isDirty()) {
-                       userRolesPage.doSave(monitor);
-                       userDetails = userDetails.cloneWithNewRoles(userRolesPage
-                                       .getRoles());
-               }
-
-               userAdminService.updateUser(userDetails);
-
-               // if (userAdminService.userExists(user.getUsername()))
-               // userAdminService.updateUser(user);
-               // else {
-               // userAdminService.newUser(user);
-               // setPartName(user.getUsername());
-               // }
-               firePropertyChange(PROP_DIRTY);
-
-               userRolesPage.setUserDetails(userDetails);
-
-               // FIXME rather use a refresh command. Fails when called by another
-               // view.
-               // refresh users view
-               IWorkbench iw = SecurityAdminPlugin.getDefault().getWorkbench();
-               UsersView usersView = (UsersView) iw.getActiveWorkbenchWindow()
-                               .getActivePage().findView(UsersView.ID);
-               if (usersView != null)
-                       usersView.refresh();
-       }
-
-       @Override
-       public void doSaveAs() {
-       }
-
-       @Override
-       public boolean isSaveAsAllowed() {
-               return false;
-       }
-
-       public void refresh() {
-               UserRolesPage userRolesPage = (UserRolesPage) findPage(UserRolesPage.ID);
-               userRolesPage.refresh();
-       }
-
-       @Override
-       public void dispose() {
-               JcrUtils.logoutQuietly(session);
-               super.dispose();
-       }
-       
-       /* DEPENDENCY INJECTION */
-       public void setUserAdminService(UserAdminService userAdminService) {
-               this.userAdminService = userAdminService;
-       }
-       
-       public void setRepository(Repository repository) {
-               try {
-                       session = repository.login();
-               } catch (RepositoryException re) {
-                       throw new ArgeoException("Unable to initialise local session", re);
-               }
-       }
-}
diff --git a/org.argeo.security.ui.admin/src/main/java/org/argeo/security/ui/admin/editors/ArgeoUserEditorInput.java b/org.argeo.security.ui.admin/src/main/java/org/argeo/security/ui/admin/editors/ArgeoUserEditorInput.java
deleted file mode 100644 (file)
index 9d1d995..0000000
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- * Copyright (C) 2007-2012 Argeo GmbH
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *         http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.argeo.security.ui.admin.editors;
-
-import org.eclipse.jface.resource.ImageDescriptor;
-import org.eclipse.ui.IEditorInput;
-import org.eclipse.ui.IPersistableElement;
-
-/** Editor input for an Argeo user. */
-public class ArgeoUserEditorInput implements IEditorInput {
-       private final String username;
-
-       public ArgeoUserEditorInput(String username) {
-               this.username = username;
-       }
-
-       public Object getAdapter(@SuppressWarnings("rawtypes") Class adapter) {
-               return null;
-       }
-
-       public boolean exists() {
-               return username != null;
-       }
-
-       public ImageDescriptor getImageDescriptor() {
-               return null;
-       }
-
-       public String getName() {
-               return username != null ? username : "<new user>";
-       }
-
-       public IPersistableElement getPersistable() {
-               return null;
-       }
-
-       public String getToolTipText() {
-               return username != null ? username : "<new user>";
-       }
-
-       public boolean equals(Object obj) {
-               if (!(obj instanceof ArgeoUserEditorInput))
-                       return false;
-               if (((ArgeoUserEditorInput) obj).getUsername() == null)
-                       return false;
-               return ((ArgeoUserEditorInput) obj).getUsername().equals(username);
-       }
-
-       public String getUsername() {
-               return username;
-       }
-}
diff --git a/org.argeo.security.ui.admin/src/main/java/org/argeo/security/ui/admin/editors/DefaultUserMainPage.java b/org.argeo.security.ui.admin/src/main/java/org/argeo/security/ui/admin/editors/DefaultUserMainPage.java
deleted file mode 100644 (file)
index 5f99e19..0000000
+++ /dev/null
@@ -1,245 +0,0 @@
-/*
- * Copyright (C) 2007-2012 Argeo GmbH
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *         http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.argeo.security.ui.admin.editors;
-
-import java.util.Arrays;
-
-import javax.jcr.Node;
-import javax.jcr.Property;
-import javax.jcr.RepositoryException;
-
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.argeo.ArgeoException;
-import org.argeo.jcr.ArgeoNames;
-import org.eclipse.swt.SWT;
-import org.eclipse.swt.events.ModifyEvent;
-import org.eclipse.swt.events.ModifyListener;
-import org.eclipse.swt.layout.GridData;
-import org.eclipse.swt.layout.GridLayout;
-import org.eclipse.swt.widgets.Composite;
-import org.eclipse.swt.widgets.Label;
-import org.eclipse.swt.widgets.Text;
-import org.eclipse.ui.forms.AbstractFormPart;
-import org.eclipse.ui.forms.IManagedForm;
-import org.eclipse.ui.forms.SectionPart;
-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;
-import org.eclipse.ui.forms.widgets.Section;
-
-/**
- * Display/edit the properties common to all Argeo users
- */
-public class DefaultUserMainPage extends FormPage implements ArgeoNames {
-       final static String ID = "argeoUserEditor.mainPage";
-
-       private final static Log log = LogFactory.getLog(DefaultUserMainPage.class);
-       private Node userProfile;
-
-       private char[] newPassword;
-
-       public DefaultUserMainPage(FormEditor editor, Node userProfile) {
-               super(editor, ID, "Main");
-               this.userProfile = userProfile;
-       }
-
-       protected void createFormContent(final IManagedForm mf) {
-               try {
-                       ScrolledForm form = mf.getForm();
-                       refreshFormTitle(form);
-                       GridLayout mainLayout = new GridLayout(1, true);
-                       form.getBody().setLayout(mainLayout);
-
-                       createGeneralPart(form.getBody());
-                       createPassworPart(form.getBody());
-               } catch (RepositoryException e) {
-                       throw new ArgeoException("Cannot create form content", e);
-               }
-       }
-
-       /** Creates the general section */
-       protected void createGeneralPart(Composite parent)
-                       throws RepositoryException {
-               FormToolkit tk = getManagedForm().getToolkit();
-               Section section = tk.createSection(parent, Section.TITLE_BAR);
-               section.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
-               section.setText("General");
-               Composite body = tk.createComposite(section, SWT.WRAP);
-               section.setClient(body);
-               GridLayout layout = new GridLayout(2, false);
-               body.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
-               body.setLayout(layout);
-
-               final Text commonName = createLT(body, "Displayed Name",
-                               getProperty(Property.JCR_TITLE));
-               final Text firstName = createLT(body, "First name",
-                               getProperty(ARGEO_FIRST_NAME));
-               final Text lastName = createLT(body, "Last name",
-                               getProperty(ARGEO_LAST_NAME));
-               final Text email = createLT(body, "Email",
-                               getProperty(ARGEO_PRIMARY_EMAIL));
-               final Text description = createLMT(body, "Description",
-                               getProperty(Property.JCR_DESCRIPTION));
-
-               // create form part (controller)
-               AbstractFormPart part = new SectionPart(section) {
-                       public void commit(boolean onSave) {
-                               try {
-                                       userProfile.getSession().getWorkspace().getVersionManager()
-                                                       .checkout(userProfile.getPath());
-                                       userProfile.setProperty(Property.JCR_TITLE,
-                                                       commonName.getText());
-                                       userProfile.setProperty(ARGEO_FIRST_NAME,
-                                                       firstName.getText());
-                                       userProfile
-                                                       .setProperty(ARGEO_LAST_NAME, lastName.getText());
-                                       userProfile.setProperty(ARGEO_PRIMARY_EMAIL,
-                                                       email.getText());
-                                       userProfile.setProperty(Property.JCR_DESCRIPTION,
-                                                       description.getText());
-                                       userProfile.getSession().save();
-                                       userProfile.getSession().getWorkspace().getVersionManager()
-                                                       .checkin(userProfile.getPath());
-                                       super.commit(onSave);
-                                       refreshFormTitle(getManagedForm().getForm());
-                                       if (log.isTraceEnabled())
-                                               log.trace("General part committed");
-                               } catch (RepositoryException e) {
-                                       throw new ArgeoException("Cannot commit", e);
-                               }
-                       }
-               };
-               // if (username != null)
-               // username.addModifyListener(new FormPartML(part));
-               commonName.addModifyListener(new FormPartML(part));
-               firstName.addModifyListener(new FormPartML(part));
-               lastName.addModifyListener(new FormPartML(part));
-               email.addModifyListener(new FormPartML(part));
-               description.addModifyListener(new FormPartML(part));
-               getManagedForm().addPart(part);
-       }
-
-       private void refreshFormTitle(ScrolledForm form) throws RepositoryException {
-               form.setText(getProperty(Property.JCR_TITLE)
-                               + (userProfile.getProperty(ARGEO_ENABLED).getBoolean() ? ""
-                                               : " [DISABLED]"));
-       }
-
-       /** @return the property, or the empty string if not set */
-       protected String getProperty(String name) throws RepositoryException {
-               return userProfile.hasProperty(name) ? userProfile.getProperty(name)
-                               .getString() : "";
-       }
-
-       /** Creates the password section */
-       protected void createPassworPart(Composite parent) {
-               FormToolkit tk = getManagedForm().getToolkit();
-               Section section = tk.createSection(parent, Section.TITLE_BAR);
-               section.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
-               section.setText("Password");
-
-               Composite body = tk.createComposite(section, SWT.WRAP);
-               section.setClient(body);
-               GridLayout layout = new GridLayout(2, false);
-               body.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
-               body.setLayout(layout);
-
-               // add widgets (view)
-               final Text password1 = createLP(body, "New password", "");
-               final Text password2 = createLP(body, "Repeat password", "");
-               // create form part (controller)
-               AbstractFormPart part = new SectionPart(section) {
-
-                       public void commit(boolean onSave) {
-                               if (!password1.getText().equals("")
-                                               || !password2.getText().equals("")) {
-                                       if (password1.getText().equals(password2.getText())) {
-                                               newPassword = password1.getText().toCharArray();
-                                               password1.setText("");
-                                               password2.setText("");
-                                               super.commit(onSave);
-                                       } else {
-                                               password1.setText("");
-                                               password2.setText("");
-                                               throw new ArgeoException("Passwords are not equals");
-                                       }
-                               }
-                       }
-
-               };
-               password1.addModifyListener(new FormPartML(part));
-               password2.addModifyListener(new FormPartML(part));
-               getManagedForm().addPart(part);
-       }
-
-       /** Creates label and text. */
-       protected Text createLT(Composite body, String label, String value) {
-               FormToolkit toolkit = getManagedForm().getToolkit();
-               Label lbl = toolkit.createLabel(body, label);
-               lbl.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false));
-               Text text = toolkit.createText(body, value, SWT.BORDER);
-               text.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));
-               return text;
-       }
-
-       /** Creates label and multiline text. */
-       protected Text createLMT(Composite body, String label, String value) {
-               FormToolkit toolkit = getManagedForm().getToolkit();
-               Label lbl = toolkit.createLabel(body, label);
-               lbl.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false));
-               Text text = toolkit.createText(body, value, SWT.BORDER | SWT.MULTI);
-               text.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, true));
-               return text;
-       }
-
-       /** Creates label and password. */
-       protected Text createLP(Composite body, String label, String value) {
-               FormToolkit toolkit = getManagedForm().getToolkit();
-               Label lbl = toolkit.createLabel(body, label);
-               lbl.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false));
-               Text text = toolkit.createText(body, value, SWT.BORDER | SWT.PASSWORD);
-               text.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));
-               return text;
-       }
-
-       private class FormPartML implements ModifyListener {
-               private AbstractFormPart formPart;
-
-               public FormPartML(AbstractFormPart generalPart) {
-                       this.formPart = generalPart;
-               }
-
-               public void modifyText(ModifyEvent e) {
-                       formPart.markDirty();
-               }
-
-       }
-
-       public String getNewPassword() {
-               if (newPassword != null)
-                       return new String(newPassword);
-               else
-                       return null;
-       }
-
-       public void resetNewPassword() {
-               if (newPassword != null)
-                       Arrays.fill(newPassword, 'x');
-               newPassword = null;
-       }
-}
diff --git a/org.argeo.security.ui.admin/src/main/java/org/argeo/security/ui/admin/editors/UserRolesPage.java b/org.argeo.security.ui.admin/src/main/java/org/argeo/security/ui/admin/editors/UserRolesPage.java
deleted file mode 100644 (file)
index 08cd457..0000000
+++ /dev/null
@@ -1,225 +0,0 @@
-/*
- * Copyright (C) 2007-2012 Argeo GmbH
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *         http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.argeo.security.ui.admin.editors;
-
-import java.util.ArrayList;
-import java.util.List;
-
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.argeo.jcr.ArgeoNames;
-import org.argeo.security.UserAdminService;
-import org.argeo.security.ui.admin.SecurityAdminPlugin;
-import org.eclipse.jface.viewers.CellEditor;
-import org.eclipse.jface.viewers.CheckboxCellEditor;
-import org.eclipse.jface.viewers.ColumnLabelProvider;
-import org.eclipse.jface.viewers.EditingSupport;
-import org.eclipse.jface.viewers.IStructuredContentProvider;
-import org.eclipse.jface.viewers.TableViewer;
-import org.eclipse.jface.viewers.TableViewerColumn;
-import org.eclipse.jface.viewers.Viewer;
-import org.eclipse.swt.SWT;
-import org.eclipse.swt.graphics.Image;
-import org.eclipse.swt.layout.FillLayout;
-import org.eclipse.swt.widgets.Composite;
-import org.eclipse.swt.widgets.Table;
-import org.eclipse.swt.widgets.TableColumn;
-import org.eclipse.ui.forms.AbstractFormPart;
-import org.eclipse.ui.forms.IManagedForm;
-import org.eclipse.ui.forms.editor.FormEditor;
-import org.eclipse.ui.forms.editor.FormPage;
-import org.eclipse.ui.forms.widgets.ScrolledForm;
-import org.springframework.security.GrantedAuthority;
-import org.springframework.security.userdetails.UserDetails;
-
-/**
- * Display/edit the roles of a user.
- */
-public class UserRolesPage extends FormPage implements ArgeoNames {
-       final static String ID = "argeoUserEditor.rolesPage";
-
-       private final static Log log = LogFactory.getLog(UserRolesPage.class);
-       private final static Image ROLE_CHECKED = SecurityAdminPlugin
-                       .getImageDescriptor("icons/security.gif").createImage();
-
-       private TableViewer rolesViewer;
-       private UserAdminService userAdminService;
-       private List<String> roles;
-
-       public UserRolesPage(FormEditor editor, UserDetails userDetails,
-                       UserAdminService userAdminService) {
-               super(editor, ID, "Roles");
-               setUserDetails(userDetails);
-               this.userAdminService = userAdminService;
-       }
-
-       public void setUserDetails(UserDetails userDetails) {
-               this.roles = new ArrayList<String>();
-               for (GrantedAuthority ga : userDetails.getAuthorities())
-                       roles.add(ga.getAuthority());
-               if (rolesViewer != null)
-                       rolesViewer.refresh();
-       }
-
-       protected void createFormContent(final IManagedForm mf) {
-               ScrolledForm form = mf.getForm();
-               form.setText("Roles");
-               FillLayout mainLayout = new FillLayout();
-               // ColumnLayout mainLayout = new ColumnLayout();
-               // mainLayout.minNumColumns = 1;
-               // mainLayout.maxNumColumns = 4;
-               // mainLayout.topMargin = 0;
-               // mainLayout.bottomMargin = 5;
-               // mainLayout.leftMargin = mainLayout.rightMargin =
-               // mainLayout.horizontalSpacing = mainLayout.verticalSpacing = 10;
-               form.getBody().setLayout(mainLayout);
-               createRolesPart(form.getBody());
-       }
-
-       /** Creates the role section */
-       protected void createRolesPart(Composite parent) {
-               Table table = new Table(parent, SWT.MULTI | SWT.H_SCROLL | SWT.V_SCROLL);
-
-               AbstractFormPart part = new AbstractFormPart() {
-                       public void commit(boolean onSave) {
-                               // roles have already been modified in editing
-                               super.commit(onSave);
-                               if (log.isTraceEnabled())
-                                       log.trace("Role part committed");
-                       }
-               };
-               getManagedForm().addPart(part);
-
-               // GridData gridData = new GridData(SWT.FILL, SWT.FILL, true, true);
-               // gridData.verticalSpan = 20;
-               // table.setLayoutData(gridData);
-               table.setLinesVisible(true);
-               table.setHeaderVisible(false);
-               rolesViewer = new TableViewer(table);
-
-               // check column
-               TableViewerColumn column = createTableViewerColumn(rolesViewer,
-                               "checked", 20);
-               column.setLabelProvider(new ColumnLabelProvider() {
-                       public String getText(Object element) {
-                               return null;
-                       }
-
-                       public Image getImage(Object element) {
-                               String role = element.toString();
-                               if (roles.contains(role)) {
-                                       return ROLE_CHECKED;
-                               } else {
-                                       return null;
-                               }
-                       }
-               });
-               column.setEditingSupport(new RoleEditingSupport(rolesViewer, part));
-
-               // role column
-               column = createTableViewerColumn(rolesViewer, "Role", 200);
-               column.setLabelProvider(new ColumnLabelProvider() {
-                       public String getText(Object element) {
-                               return element.toString();
-                       }
-
-                       public Image getImage(Object element) {
-                               return null;
-                       }
-               });
-               rolesViewer.setContentProvider(new RolesContentProvider());
-               rolesViewer.setInput(getEditorSite());
-       }
-
-       protected TableViewerColumn createTableViewerColumn(TableViewer viewer,
-                       String title, int bound) {
-               final TableViewerColumn viewerColumn = new TableViewerColumn(viewer,
-                               SWT.NONE);
-               final TableColumn column = viewerColumn.getColumn();
-               column.setText(title);
-               column.setWidth(bound);
-               column.setResizable(true);
-               column.setMoveable(true);
-               return viewerColumn;
-
-       }
-
-       public List<String> getRoles() {
-               return roles;
-       }
-
-       public void refresh() {
-               rolesViewer.refresh();
-       }
-
-       private class RolesContentProvider implements IStructuredContentProvider {
-               public Object[] getElements(Object inputElement) {
-                       return userAdminService.listEditableRoles().toArray();
-               }
-
-               public void dispose() {
-               }
-
-               public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
-               }
-       }
-
-       /** Select the columns by editing the checkbox in the first column */
-       class RoleEditingSupport extends EditingSupport {
-
-               private final TableViewer viewer;
-               private final AbstractFormPart formPart;
-
-               public RoleEditingSupport(TableViewer viewer, AbstractFormPart formPart) {
-                       super(viewer);
-                       this.viewer = viewer;
-                       this.formPart = formPart;
-               }
-
-               @Override
-               protected CellEditor getCellEditor(Object element) {
-                       return new CheckboxCellEditor(null, SWT.CHECK | SWT.READ_ONLY);
-
-               }
-
-               @Override
-               protected boolean canEdit(Object element) {
-                       return true;
-               }
-
-               @Override
-               protected Object getValue(Object element) {
-                       String role = element.toString();
-                       return roles.contains(role);
-
-               }
-
-               @Override
-               protected void setValue(Object element, Object value) {
-                       Boolean inRole = (Boolean) value;
-                       String role = element.toString();
-                       if (inRole && !roles.contains(role)) {
-                               roles.add(role);
-                               formPart.markDirty();
-                       } else if (!inRole && roles.contains(role)) {
-                               roles.remove(role);
-                               formPart.markDirty();
-                       }
-                       viewer.refresh();
-               }
-       }
-
-}
diff --git a/org.argeo.security.ui.admin/src/main/java/org/argeo/security/ui/admin/views/RolesView.java b/org.argeo.security.ui.admin/src/main/java/org/argeo/security/ui/admin/views/RolesView.java
deleted file mode 100644 (file)
index fbe7dd5..0000000
+++ /dev/null
@@ -1,140 +0,0 @@
-/*
- * Copyright (C) 2007-2012 Argeo GmbH
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *         http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.argeo.security.ui.admin.views;
-
-import org.argeo.ArgeoException;
-import org.argeo.security.UserAdminService;
-import org.argeo.security.ui.admin.SecurityAdminPlugin;
-import org.argeo.security.ui.admin.commands.AddRole;
-import org.eclipse.jface.viewers.IStructuredContentProvider;
-import org.eclipse.jface.viewers.ITableLabelProvider;
-import org.eclipse.jface.viewers.LabelProvider;
-import org.eclipse.jface.viewers.TableViewer;
-import org.eclipse.jface.viewers.Viewer;
-import org.eclipse.swt.SWT;
-import org.eclipse.swt.graphics.Image;
-import org.eclipse.swt.layout.GridData;
-import org.eclipse.swt.layout.GridLayout;
-import org.eclipse.swt.widgets.Composite;
-import org.eclipse.swt.widgets.Event;
-import org.eclipse.swt.widgets.Listener;
-import org.eclipse.swt.widgets.Table;
-import org.eclipse.swt.widgets.Text;
-import org.eclipse.ui.IWorkbench;
-import org.eclipse.ui.handlers.IHandlerService;
-import org.eclipse.ui.part.ViewPart;
-
-/** List all roles. */
-public class RolesView extends ViewPart {
-       public final static String ID = SecurityAdminPlugin.PLUGIN_ID
-                       + ".adminRolesView";
-
-       private Text newRole;
-
-       private TableViewer viewer;
-       private UserAdminService userAdminService;
-
-       private String addNewRoleText = "<add new role here>";
-
-       @Override
-       public void createPartControl(Composite parent) {
-               parent.setLayout(new GridLayout(1, false));
-
-               // new role text field
-               newRole = new Text(parent, SWT.BORDER);
-               newRole.setText(addNewRoleText);
-               newRole.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
-               // default action is add role
-               newRole.addListener(SWT.DefaultSelection, new Listener() {
-                       public void handleEvent(Event evt) {
-                               IWorkbench iw = SecurityAdminPlugin.getDefault().getWorkbench();
-                               IHandlerService handlerService = (IHandlerService) iw
-                                               .getService(IHandlerService.class);
-                               try {
-                                       handlerService.executeCommand(AddRole.COMMAND_ID, evt);
-                               } catch (Exception e) {
-                                       throw new ArgeoException("Cannot execute add role command",
-                                                       e);
-                               }
-                       }
-               });
-               // select all on focus
-               newRole.addListener(SWT.FocusIn, new Listener() {
-                       public void handleEvent(Event e) {
-                               newRole.selectAll();
-                       }
-               });
-
-               // roles table
-               Table table = new Table(parent, SWT.V_SCROLL | SWT.BORDER);
-               table.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
-               table.setLinesVisible(false);
-               table.setHeaderVisible(false);
-               viewer = new TableViewer(table);
-               viewer.setContentProvider(new RolesContentProvider());
-               viewer.setLabelProvider(new UsersLabelProvider());
-               getViewSite().setSelectionProvider(viewer);
-               viewer.setInput(getViewSite());
-       }
-
-       @Override
-       public void setFocus() {
-               viewer.getTable().setFocus();
-       }
-
-       public void setUserAdminService(UserAdminService userAdminService) {
-               this.userAdminService = userAdminService;
-       }
-
-       public String getAddNewRoleText() {
-               return addNewRoleText;
-       }
-
-       private class RolesContentProvider implements IStructuredContentProvider {
-
-               public Object[] getElements(Object inputElement) {
-                       return userAdminService.listEditableRoles().toArray();
-               }
-
-               public void dispose() {
-               }
-
-               public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
-               }
-
-       }
-
-       private class UsersLabelProvider extends LabelProvider implements
-                       ITableLabelProvider {
-               public String getColumnText(Object element, int columnIndex) {
-                       return element.toString();
-               }
-
-               public Image getColumnImage(Object element, int columnIndex) {
-                       return null;
-               }
-
-       }
-
-       public String getNewRole() {
-               return newRole.getText();
-       }
-
-       public void refresh() {
-               viewer.refresh();
-               newRole.setText(addNewRoleText);
-       }
-}
diff --git a/org.argeo.security.ui.admin/src/main/java/org/argeo/security/ui/admin/views/UsersView.java b/org.argeo.security.ui.admin/src/main/java/org/argeo/security/ui/admin/views/UsersView.java
deleted file mode 100644 (file)
index a743715..0000000
+++ /dev/null
@@ -1,158 +0,0 @@
-/*
- * Copyright (C) 2007-2012 Argeo GmbH
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *         http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.argeo.security.ui.admin.views;
-
-import javax.jcr.Node;
-import javax.jcr.Repository;
-import javax.jcr.RepositoryException;
-import javax.jcr.Session;
-import javax.jcr.observation.Event;
-import javax.jcr.observation.EventIterator;
-import javax.jcr.observation.EventListener;
-
-import org.argeo.ArgeoException;
-import org.argeo.eclipse.ui.utils.CommandUtils;
-import org.argeo.jcr.ArgeoJcrConstants;
-import org.argeo.jcr.ArgeoNames;
-import org.argeo.jcr.ArgeoTypes;
-import org.argeo.jcr.JcrUtils;
-import org.argeo.security.ui.admin.SecurityAdminPlugin;
-import org.argeo.security.ui.admin.UserTableComposite;
-import org.argeo.security.ui.admin.commands.OpenArgeoUserEditor;
-import org.eclipse.jface.viewers.DoubleClickEvent;
-import org.eclipse.jface.viewers.IDoubleClickListener;
-import org.eclipse.jface.viewers.IStructuredSelection;
-import org.eclipse.swt.SWT;
-import org.eclipse.swt.layout.FillLayout;
-import org.eclipse.swt.widgets.Composite;
-import org.eclipse.swt.widgets.Display;
-import org.eclipse.ui.part.ViewPart;
-
-/** List all users with filter. */
-public class UsersView extends ViewPart implements ArgeoNames {
-       public final static String ID = SecurityAdminPlugin.PLUGIN_ID
-                       + ".adminUsersView";
-
-       /* DEPENDENCY INJECTION */
-       private Session session;
-
-       private UserTableComposite userTableCmp;
-       private JcrUserListener userStructureListener;
-       private JcrUserListener userPropertiesListener;
-
-       @Override
-       public void createPartControl(Composite parent) {
-               parent.setLayout(new FillLayout());
-
-               // Create the composite that displays the list and a filter
-               userTableCmp = new UserTableComposite(parent, SWT.NO_FOCUS, session);
-               userTableCmp.populate(true, false);
-
-               // Configure
-               userTableCmp.getTableViewer().addDoubleClickListener(
-                               new ViewDoubleClickListener());
-               getViewSite().setSelectionProvider(userTableCmp.getTableViewer());
-
-               // Add listener to refresh the list when something changes
-               userStructureListener = new JcrUserListener(getSite().getShell()
-                               .getDisplay());
-               JcrUtils.addListener(session, userStructureListener, Event.NODE_ADDED
-                               | Event.NODE_REMOVED, ArgeoJcrConstants.PEOPLE_BASE_PATH, null);
-               userPropertiesListener = new JcrUserListener(getSite().getShell()
-                               .getDisplay());
-               JcrUtils.addListener(session, userStructureListener,
-                               Event.PROPERTY_CHANGED | Event.PROPERTY_ADDED
-                                               | Event.PROPERTY_REMOVED,
-                               ArgeoJcrConstants.PEOPLE_BASE_PATH,
-                               ArgeoTypes.ARGEO_USER_PROFILE);
-       }
-
-       @Override
-       public void setFocus() {
-               userTableCmp.setFocus();
-       }
-
-       @Override
-       public void dispose() {
-               JcrUtils.removeListenerQuietly(session, userStructureListener);
-               JcrUtils.removeListenerQuietly(session, userPropertiesListener);
-               JcrUtils.logoutQuietly(session);
-               super.dispose();
-       }
-
-       // public void setSession(Session session) {
-       // this.session = session;
-       // }
-
-       public void refresh() {
-               this.getSite().getShell().getDisplay().asyncExec(new Runnable() {
-                       @Override
-                       public void run() {
-                               userTableCmp.refresh();
-                       }
-               });
-       }
-
-       private class JcrUserListener implements EventListener {
-               private final Display display;
-
-               public JcrUserListener(Display display) {
-                       super();
-                       this.display = display;
-               }
-
-               @Override
-               public void onEvent(EventIterator events) {
-                       display.asyncExec(new Runnable() {
-                               @Override
-                               public void run() {
-                                       userTableCmp.refresh();
-                               }
-                       });
-               }
-       }
-
-       class ViewDoubleClickListener implements IDoubleClickListener {
-               public void doubleClick(DoubleClickEvent evt) {
-                       if (evt.getSelection().isEmpty())
-                               return;
-
-                       Object obj = ((IStructuredSelection) evt.getSelection())
-                                       .getFirstElement();
-                       if (obj instanceof Node) {
-                               try {
-                                       String username = ((Node) obj).getProperty(ARGEO_USER_ID)
-                                                       .getString();
-                                       String commandId = OpenArgeoUserEditor.COMMAND_ID;
-                                       String paramName = OpenArgeoUserEditor.PARAM_USERNAME;
-                                       CommandUtils.callCommand(commandId, paramName, username);
-                               } catch (RepositoryException e) {
-                                       throw new ArgeoException("Cannot open user editor", e);
-                               }
-                       }
-               }
-       }
-
-       /* DEPENDENCY INJECTION */
-       public void setRepository(Repository repository) {
-               try {
-                       session = repository.login();
-               } catch (RepositoryException re) {
-                       throw new ArgeoException("Unable to initialise local session", re);
-               }
-       }
-
-}
\ No newline at end of file
diff --git a/org.argeo.security.ui.admin/src/main/java/org/argeo/security/ui/admin/wizards/MainUserInfoWizardPage.java b/org.argeo.security.ui.admin/src/main/java/org/argeo/security/ui/admin/wizards/MainUserInfoWizardPage.java
deleted file mode 100644 (file)
index ad3662b..0000000
+++ /dev/null
@@ -1,133 +0,0 @@
-/*
- * Copyright (C) 2007-2012 Argeo GmbH
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *         http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.argeo.security.ui.admin.wizards;
-
-import javax.jcr.Node;
-import javax.jcr.Property;
-import javax.jcr.RepositoryException;
-
-import org.argeo.ArgeoException;
-import org.argeo.eclipse.ui.EclipseUiUtils;
-import org.argeo.jcr.ArgeoNames;
-import org.argeo.security.UserAdminService;
-import org.eclipse.jface.wizard.WizardPage;
-import org.eclipse.swt.SWT;
-import org.eclipse.swt.events.ModifyEvent;
-import org.eclipse.swt.events.ModifyListener;
-import org.eclipse.swt.layout.GridLayout;
-import org.eclipse.swt.widgets.Composite;
-import org.eclipse.swt.widgets.Text;
-import org.springframework.security.userdetails.UserDetails;
-import org.springframework.security.userdetails.UsernameNotFoundException;
-
-public class MainUserInfoWizardPage extends WizardPage implements
-               ModifyListener, ArgeoNames {
-       private Text username, firstName, lastName, primaryEmail, password1,
-                       password2;
-       private UserAdminService userAdminService;
-
-       public MainUserInfoWizardPage(UserAdminService userAdminService) {
-               super("Main");
-               this.userAdminService = userAdminService;
-               setTitle("Required Information");
-       }
-
-       @Override
-       public void createControl(Composite parent) {
-               Composite composite = new Composite(parent, SWT.NONE);
-               composite.setLayout(new GridLayout(2, false));
-               username = EclipseUiUtils.createGridLT(composite, "Username", this);
-               primaryEmail = EclipseUiUtils.createGridLT(composite, "Email", this);
-               firstName = EclipseUiUtils.createGridLT(composite, "First name", this);
-               lastName = EclipseUiUtils.createGridLT(composite, "Last name", this);
-               password1 = EclipseUiUtils.createGridLP(composite, "Password", this);
-               password2 = EclipseUiUtils.createGridLP(composite, "Repeat password",
-                               this);
-               setControl(composite);
-               
-               // Initialize buttons
-               setPageComplete(false);
-               getContainer().updateButtons();
-       }
-
-       @Override
-       public void modifyText(ModifyEvent event) {
-               String message = checkComplete();
-               if (message != null) {
-                       setMessage(message, WizardPage.ERROR);
-                       setPageComplete(false);
-               } else {
-                       setMessage("Complete", WizardPage.INFORMATION);
-                       setPageComplete(true);
-               }
-               getContainer().updateButtons();
-       }
-
-       /** @return error message or null if complete */
-       protected String checkComplete() {
-               // if (!username.getText().matches(UserAdminService.USERNAME_PATTERN))
-               // return
-               // "Wrong user name format, should be lower case, between 3 and 64 characters with only '_' an '@' as acceptable special character.";
-               
-               if (username.getText().trim().equals(""))
-                       return "User name must not be empty";
-               
-               try {
-                       UserDetails userDetails = userAdminService
-                                       .loadUserByUsername(username.getText());
-                       return "User " + userDetails.getUsername() + " already exists";
-               } catch (UsernameNotFoundException e) {
-                       // silent
-               }
-               if (!primaryEmail.getText().matches(UserAdminService.EMAIL_PATTERN))
-                       return "Not a valid email address";
-               if (firstName.getText().trim().equals(""))
-                       return "Specify a first name";
-               if (lastName.getText().trim().equals(""))
-                       return "Specify a last name";
-               if (password1.getText().trim().equals(""))
-                       return "Specify a password";
-               if (password2.getText().trim().equals(""))
-                       return "Repeat the password";
-               if (!password2.getText().equals(password1.getText()))
-                       return "Passwords are different";
-               return null;
-       }
-
-       public String getUsername() {
-               return username.getText();
-       }
-
-       public String getPassword() {
-               return password1.getText();
-       }
-
-       public void mapToProfileNode(Node up) {
-               try {
-                       up.setProperty(ARGEO_PRIMARY_EMAIL, primaryEmail.getText());
-                       up.setProperty(ARGEO_FIRST_NAME, firstName.getText());
-                       up.setProperty(ARGEO_LAST_NAME, lastName.getText());
-
-                       // derived values
-                       // TODO add wizard pages to do it
-                       up.setProperty(Property.JCR_TITLE, firstName.getText() + " "
-                                       + lastName.getText());
-                       up.setProperty(Property.JCR_DESCRIPTION, "");
-               } catch (RepositoryException e) {
-                       throw new ArgeoException("Cannot map to " + up, e);
-               }
-       }
-}
diff --git a/org.argeo.security.ui.admin/src/main/java/org/argeo/security/ui/admin/wizards/NewUserWizard.java b/org.argeo.security.ui.admin/src/main/java/org/argeo/security/ui/admin/wizards/NewUserWizard.java
deleted file mode 100644 (file)
index c2d041f..0000000
+++ /dev/null
@@ -1,100 +0,0 @@
-/*
- * Copyright (C) 2007-2012 Argeo GmbH
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *         http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.argeo.security.ui.admin.wizards;
-
-import javax.jcr.Node;
-import javax.jcr.RepositoryException;
-import javax.jcr.Session;
-
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.argeo.eclipse.ui.ErrorFeedback;
-import org.argeo.jcr.JcrUtils;
-import org.argeo.jcr.UserJcrUtils;
-import org.argeo.security.UserAdminService;
-import org.argeo.security.jcr.JcrSecurityModel;
-import org.argeo.security.jcr.JcrUserDetails;
-import org.eclipse.jface.wizard.Wizard;
-import org.springframework.security.GrantedAuthority;
-
-/** Wizard to create a new user */
-public class NewUserWizard extends Wizard {
-       private final static Log log = LogFactory.getLog(NewUserWizard.class);
-       private Session session;
-       private UserAdminService userAdminService;
-       private JcrSecurityModel jcrSecurityModel;
-
-       // pages
-       private MainUserInfoWizardPage mainUserInfo;
-
-       public NewUserWizard(Session session, UserAdminService userAdminService,
-                       JcrSecurityModel jcrSecurityModel) {
-               this.session = session;
-               this.userAdminService = userAdminService;
-               this.jcrSecurityModel = jcrSecurityModel;
-       }
-
-       @Override
-       public void addPages() {
-               mainUserInfo = new MainUserInfoWizardPage(userAdminService);
-               addPage(mainUserInfo);
-       }
-
-       @Override
-       public boolean performFinish() {
-               if (!canFinish())
-                       return false;
-
-               String username = mainUserInfo.getUsername();
-               try {
-                       // Node userProfile = SecurityJcrUtils.createUserProfile(session,
-                       // username);
-                       Node userProfile = jcrSecurityModel.sync(session, username, null);
-                       session.getWorkspace().getVersionManager()
-                                       .checkout(userProfile.getPath());
-                       mainUserInfo.mapToProfileNode(userProfile);
-                       String password = mainUserInfo.getPassword();
-                       // TODO add roles
-                       JcrUserDetails jcrUserDetails = new JcrUserDetails(userProfile,
-                                       password, new GrantedAuthority[0]);
-                       session.save();
-                       session.getWorkspace().getVersionManager()
-                                       .checkin(userProfile.getPath());
-                       userAdminService.createUser(jcrUserDetails);
-                       return true;
-               } catch (Exception e) {
-                       JcrUtils.discardQuietly(session);
-                       Node userHome = UserJcrUtils.getUserHome(session, username);
-                       if (userHome != null) {
-                               try {
-                                       userHome.remove();
-                                       session.save();
-                               } catch (RepositoryException e1) {
-                                       JcrUtils.discardQuietly(session);
-                                       log.warn("Error when trying to clean up failed new user "
-                                                       + username, e1);
-                               }
-                       }
-                       ErrorFeedback.show("Cannot create new user " + username, e);
-                       return false;
-               }
-       }
-
-       public void setSession(Session session) {
-               this.session = session;
-       }
-
-}
diff --git a/org.argeo.security.ui.admin/src/main/java/org/argeo/security/ui/admin/wizards/UserBatchUpdateWizard.java b/org.argeo.security.ui.admin/src/main/java/org/argeo/security/ui/admin/wizards/UserBatchUpdateWizard.java
deleted file mode 100644 (file)
index 71e4a1b..0000000
+++ /dev/null
@@ -1,607 +0,0 @@
-/*
- * Copyright (C) 2007-2012 Argeo GmbH
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *         http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.argeo.security.ui.admin.wizards;
-
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-import javax.jcr.Node;
-import javax.jcr.NodeIterator;
-import javax.jcr.RepositoryException;
-import javax.jcr.Session;
-import javax.jcr.version.VersionManager;
-
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.argeo.ArgeoException;
-import org.argeo.ArgeoMonitor;
-import org.argeo.eclipse.ui.EclipseArgeoMonitor;
-import org.argeo.jcr.ArgeoNames;
-import org.argeo.jcr.JcrUtils;
-import org.argeo.security.UserAdminService;
-import org.argeo.security.jcr.JcrSecurityModel;
-import org.argeo.security.jcr.JcrUserDetails;
-import org.argeo.security.ui.PrivilegedJob;
-import org.argeo.security.ui.admin.SecurityAdminPlugin;
-import org.argeo.security.ui.admin.UserTableComposite;
-import org.eclipse.core.runtime.IProgressMonitor;
-import org.eclipse.core.runtime.IStatus;
-import org.eclipse.core.runtime.Status;
-import org.eclipse.jface.dialogs.IPageChangeProvider;
-import org.eclipse.jface.dialogs.IPageChangedListener;
-import org.eclipse.jface.dialogs.PageChangedEvent;
-import org.eclipse.jface.wizard.IWizardContainer;
-import org.eclipse.jface.wizard.Wizard;
-import org.eclipse.jface.wizard.WizardPage;
-import org.eclipse.swt.SWT;
-import org.eclipse.swt.events.SelectionEvent;
-import org.eclipse.swt.events.SelectionListener;
-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.Combo;
-import org.eclipse.swt.widgets.Composite;
-import org.eclipse.swt.widgets.Control;
-import org.eclipse.swt.widgets.Label;
-import org.eclipse.swt.widgets.Text;
-
-/** Wizard to update users */
-public class UserBatchUpdateWizard extends Wizard {
-       private final static Log log = LogFactory
-                       .getLog(UserBatchUpdateWizard.class);
-       private Session session;
-       private UserAdminService userAdminService;
-
-       // pages
-       private ChooseCommandWizardPage chooseCommandPage;
-       private ChooseUsersWizardPage userListPage;
-       private ValidateAndLaunchWizardPage validatePage;
-
-       // /////////////////////////////////////////////////
-       // / Definition of the various implemented commands
-       private final static String CMD_UPDATE_PASSWORD = "resetPassword";
-       private final static String CMD_GROUP_MEMBERSHIP = "groupMembership";
-
-       private final Map<String, String> commands = new HashMap<String, String>() {
-               private static final long serialVersionUID = 1L;
-               {
-                       put("Enable user(s)", ArgeoNames.ARGEO_ENABLED);
-                       put("Expire credentials", ArgeoNames.ARGEO_CREDENTIALS_NON_EXPIRED);
-                       put("Expire account(s)", ArgeoNames.ARGEO_ACCOUNT_NON_EXPIRED);
-                       put("Lock account(s)", ArgeoNames.ARGEO_ACCOUNT_NON_LOCKED);
-                       put("Reset password(s)", CMD_UPDATE_PASSWORD);
-                       // TODO implement role / group management
-                       // put("Add/Remove from group", CMD_GROUP_MEMBERSHIP);
-               }
-       };
-
-       public UserBatchUpdateWizard(Session session,
-                       UserAdminService userAdminService, JcrSecurityModel jcrSecurityModel) {
-               this.session = session;
-               this.userAdminService = userAdminService;
-               // this.jcrSecurityModel = jcrSecurityModel;
-       }
-
-       @Override
-       public void addPages() {
-               chooseCommandPage = new ChooseCommandWizardPage();
-               addPage(chooseCommandPage);
-               userListPage = new ChooseUsersWizardPage(session);
-               addPage(userListPage);
-               validatePage = new ValidateAndLaunchWizardPage(session);
-               addPage(validatePage);
-       }
-
-       @Override
-       public boolean performFinish() {
-               if (!canFinish())
-                       return false;
-
-               UpdateJob job = null;
-               if (ArgeoNames.ARGEO_ENABLED.equals(chooseCommandPage.getCommand())) {
-                       job = new UpdateBoolean(session, userListPage.getSelectedUsers(),
-                                       ArgeoNames.ARGEO_ENABLED,
-                                       chooseCommandPage.getBoleanValue());
-               } else if (ArgeoNames.ARGEO_CREDENTIALS_NON_EXPIRED
-                               .equals(chooseCommandPage.getCommand())) {
-                       job = new UpdateBoolean(session, userListPage.getSelectedUsers(),
-                                       ArgeoNames.ARGEO_CREDENTIALS_NON_EXPIRED,
-                                       chooseCommandPage.getBoleanValue());
-               } else if (ArgeoNames.ARGEO_ACCOUNT_NON_EXPIRED
-                               .equals(chooseCommandPage.getCommand())) {
-                       job = new UpdateBoolean(session, userListPage.getSelectedUsers(),
-                                       ArgeoNames.ARGEO_ACCOUNT_NON_EXPIRED,
-                                       chooseCommandPage.getBoleanValue());
-               } else if (ArgeoNames.ARGEO_ACCOUNT_NON_LOCKED.equals(chooseCommandPage
-                               .getCommand())) {
-                       job = new UpdateBoolean(session, userListPage.getSelectedUsers(),
-                                       ArgeoNames.ARGEO_ACCOUNT_NON_LOCKED,
-                                       chooseCommandPage.getBoleanValue());
-               } else if (CMD_UPDATE_PASSWORD.equals(chooseCommandPage.getCommand())) {
-                       String newValue = chooseCommandPage.getPwdValue();
-                       if (newValue == null)
-                               throw new ArgeoException(
-                                               "Password cannot be null or an empty string");
-                       job = new ResetPassword(session, userAdminService,
-                                       userListPage.getSelectedUsers(), newValue);
-               }
-
-               if (job != null)
-                       job.schedule();
-               return true;
-       }
-
-       public void setSession(Session session) {
-               this.session = session;
-       }
-
-       public boolean canFinish() {
-               if (this.getContainer().getCurrentPage() == validatePage)
-                       return true;
-               return false;
-       }
-
-       // /////////////////////////
-       // REEL UPDATE JOB
-       private class UpdateBoolean extends UpdateJob {
-               private String propertyName;
-               private boolean value;
-
-               public UpdateBoolean(Session session, List<Node> nodesToUpdate,
-                               String propertyName, boolean value) {
-                       super(session, nodesToUpdate);
-                       this.propertyName = propertyName;
-                       this.value = value;
-               }
-
-               protected void doUpdate(Node node) {
-                       try {
-                               node.setProperty(propertyName, value);
-                       } catch (RepositoryException re) {
-                               throw new ArgeoException(
-                                               "Unable to update boolean value for node " + node, re);
-                       }
-               }
-       }
-
-       private class ResetPassword extends UpdateJob {
-               private String newValue;
-               private UserAdminService userAdminService;
-
-               public ResetPassword(Session session,
-                               UserAdminService userAdminService, List<Node> nodesToUpdate,
-                               String newValue) {
-                       super(session, nodesToUpdate);
-                       this.newValue = newValue;
-                       this.userAdminService = userAdminService;
-               }
-
-               protected void doUpdate(Node node) {
-                       try {
-                               String userId = node.getProperty(ArgeoNames.ARGEO_USER_ID)
-                                               .getString();
-                               if (userAdminService.userExists(userId)) {
-                                       JcrUserDetails userDetails = (JcrUserDetails) userAdminService
-                                                       .loadUserByUsername(userId);
-                                       userAdminService.updateUser(userDetails
-                                                       .cloneWithNewPassword(newValue));
-                               }
-                       } catch (RepositoryException re) {
-                               throw new ArgeoException(
-                                               "Unable to update boolean value for node " + node, re);
-                       }
-               }
-       }
-
-       @SuppressWarnings("unused")
-       private class AddToGroup extends UpdateJob {
-               private String groupID;
-               private Session session;
-
-               public AddToGroup(Session session, List<Node> nodesToUpdate,
-                               String groupID) {
-                       super(session, nodesToUpdate);
-                       this.session = session;
-                       this.groupID = groupID;
-               }
-
-               protected void doUpdate(Node node) {
-                       log.info("Add/Remove to group actions are not yet implemented");
-                       // TODO implement this
-                       // try {
-                       // throw new ArgeoException("Not yet implemented");
-                       // } catch (RepositoryException re) {
-                       // throw new ArgeoException(
-                       // "Unable to update boolean value for node " + node, re);
-                       // }
-               }
-       }
-
-       /**
-        * Base privileged job that will be run asynchronously to perform the batch
-        * update
-        */
-       private abstract class UpdateJob extends PrivilegedJob {
-
-               private final Session currSession;
-               private final List<Node> nodesToUpdate;
-
-               protected abstract void doUpdate(Node node);
-
-               public UpdateJob(Session session, List<Node> nodesToUpdate) {
-                       super("Perform update");
-                       try {
-                               this.currSession = session.getRepository().login();
-                               // "move" nodes to update in the new session
-                               // the "old" session will be closed by the calling command
-                               // before the job has effectively ran
-                               // TODO there must be a cleaner way to do.
-                               List<Node> nodes = new ArrayList<Node>();
-                               for (Node node : nodesToUpdate) {
-                                       nodes.add(currSession.getNode(node.getPath()));
-                               }
-                               this.nodesToUpdate = nodes;
-                       } catch (RepositoryException e) {
-                               throw new ArgeoException("Error while dupplicating "
-                                               + "session for job", e);
-                       }
-               }
-
-               @Override
-               protected IStatus doRun(IProgressMonitor progressMonitor) {
-                       try {
-                               ArgeoMonitor monitor = new EclipseArgeoMonitor(progressMonitor);
-                               VersionManager vm = currSession.getWorkspace()
-                                               .getVersionManager();
-                               int total = nodesToUpdate.size();
-                               monitor.beginTask("Performing change", total);
-                               for (Node node : nodesToUpdate) {
-                                       String path = node.getPath();
-                                       vm.checkout(path);
-                                       doUpdate(node);
-                                       currSession.save();
-                                       vm.checkin(path);
-                                       monitor.worked(1);
-                               }
-                       } catch (Exception e) {
-                               log.error("Cannot perform batch update on users", e);
-                               // e.printStackTrace();
-
-                               // Dig exception to find the root cause that will enable the
-                               // user to understand the problem
-                               Throwable cause = e;
-                               Throwable originalCause = e;
-                               while (cause != null) {
-                                       if (log.isTraceEnabled())
-                                               log.trace("Parent Cause message : "
-                                                               + cause.getMessage());
-                                       originalCause = cause;
-                                       cause = cause.getCause();
-                               }
-                               return new Status(IStatus.ERROR, SecurityAdminPlugin.PLUGIN_ID,
-                                               "Cannot perform updates.", originalCause);
-                       } finally {
-                               JcrUtils.logoutQuietly(currSession);
-                       }
-                       return Status.OK_STATUS;
-               }
-       }
-
-       // //////////////////////
-       // Pages definition
-       /** Displays a combo box that enables user to choose which action to perform */
-       private class ChooseCommandWizardPage extends WizardPage {
-               private static final long serialVersionUID = 1L;
-
-               private Combo chooseCommandCmb;
-               private Button trueChk;
-               private Text valueTxt;
-               private Text pwdTxt;
-               private Text pwd2Txt;
-
-               public ChooseCommandWizardPage() {
-                       super("Choose a command to run.");
-                       setTitle("Choose a command to run.");
-               }
-
-               @Override
-               public void createControl(Composite parent) {
-                       GridLayout gl = new GridLayout();
-                       Composite container = new Composite(parent, SWT.NO_FOCUS);
-                       container.setLayout(gl);
-
-                       chooseCommandCmb = new Combo(container, SWT.NO_FOCUS);
-                       String[] values = commands.keySet().toArray(
-                                       new String[commands.size()]);
-                       chooseCommandCmb.setItems(values);
-                       chooseCommandCmb.setLayoutData(new GridData(SWT.FILL, SWT.TOP,
-                                       true, false));
-
-                       final Composite bottomPart = new Composite(container, SWT.NO_FOCUS);
-                       gl = new GridLayout();
-                       gl.horizontalSpacing = gl.marginWidth = gl.verticalSpacing = 0;
-                       bottomPart.setLayout(gl);
-                       bottomPart.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true,
-                                       true));
-
-                       chooseCommandCmb.addSelectionListener(new SelectionListener() {
-                               private static final long serialVersionUID = 1L;
-
-                               @Override
-                               public void widgetSelected(SelectionEvent e) {
-                                       if (getCommand().equals(CMD_UPDATE_PASSWORD))
-                                               populatePasswordCmp(bottomPart);
-                                       else if (getCommand().equals(CMD_GROUP_MEMBERSHIP))
-                                               populateGroupCmp(bottomPart);
-                                       else
-                                               populateBooleanFlagCmp(bottomPart);
-                                       bottomPart.pack(true);
-                                       bottomPart.layout();
-                               }
-
-                               @Override
-                               public void widgetDefaultSelected(SelectionEvent e) {
-                               }
-                       });
-
-                       setControl(container);
-               }
-
-               private void cleanParent(Composite parent) {
-                       if (parent.getChildren().length > 0) {
-                               for (Control control : parent.getChildren())
-                                       control.dispose();
-                       }
-               }
-
-               private void populateBooleanFlagCmp(Composite parent) {
-                       cleanParent(parent);
-                       trueChk = new Button(parent, SWT.CHECK);
-                       trueChk.setText("Do it. (It will to the contrary if unchecked)");
-                       trueChk.setSelection(true);
-                       trueChk.setLayoutData(new GridData(SWT.LEFT, SWT.TOP, false, false));
-               }
-
-               private void populatePasswordCmp(Composite parent) {
-                       cleanParent(parent);
-                       Composite body = new Composite(parent, SWT.NO_FOCUS);
-                       body.setLayout(new GridLayout(2, false));
-                       body.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
-                       pwdTxt = createLP(body, "New password", "");
-                       pwd2Txt = createLP(body, "Repeat password", "");
-               }
-
-               /** Creates label and password. */
-               protected Text createLP(Composite body, String label, String value) {
-                       Label lbl = new Label(body, SWT.NONE);
-                       lbl.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false));
-                       lbl.setText(label);
-                       Text text = new Text(body, SWT.BORDER | SWT.PASSWORD);
-                       text.setText(value);
-                       text.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));
-                       return text;
-               }
-
-               private void populateGroupCmp(Composite parent) {
-                       if (parent.getChildren().length > 0) {
-                               for (Control control : parent.getChildren())
-                                       control.dispose();
-                       }
-                       trueChk = new Button(parent, SWT.CHECK);
-                       trueChk.setText("Add to group. (It will remove user(s) from the "
-                                       + "corresponding group if unchecked)");
-                       trueChk.setSelection(true);
-                       trueChk.setLayoutData(new GridData(SWT.LEFT, SWT.TOP, false, false));
-               }
-
-               protected String getCommand() {
-                       return commands.get(chooseCommandCmb.getItem(chooseCommandCmb
-                                       .getSelectionIndex()));
-               }
-
-               protected String getCommandLbl() {
-                       return chooseCommandCmb.getItem(chooseCommandCmb
-                                       .getSelectionIndex());
-               }
-
-               protected boolean getBoleanValue() {
-                       // FIXME this is not consistent and will lead to errors.
-                       if (ArgeoNames.ARGEO_ENABLED.equals(getCommand()))
-                               return trueChk.getSelection();
-                       else
-                               return !trueChk.getSelection();
-               }
-
-               @SuppressWarnings("unused")
-               protected String getStringValue() {
-                       String value = null;
-                       if (valueTxt != null) {
-                               value = valueTxt.getText();
-                               if ("".equals(value.trim()))
-                                       value = null;
-                       }
-                       return value;
-               }
-
-               protected String getPwdValue() {
-                       String newPwd = null;
-                       if (pwdTxt == null || pwd2Txt == null)
-                               return null;
-                       if (!pwdTxt.getText().equals("") || !pwd2Txt.getText().equals("")) {
-                               if (pwdTxt.getText().equals(pwd2Txt.getText())) {
-                                       newPwd = pwdTxt.getText();
-                                       pwdTxt.setText("");
-                                       pwd2Txt.setText("");
-                               } else {
-                                       pwdTxt.setText("");
-                                       pwd2Txt.setText("");
-                                       throw new ArgeoException("Passwords are not equals");
-                               }
-                       }
-                       return newPwd;
-               }
-       }
-
-       /**
-        * Displays a list of users with a check box to be able to choose some of
-        * them
-        */
-       private class ChooseUsersWizardPage extends WizardPage implements
-                       IPageChangedListener {
-               private static final long serialVersionUID = 1L;
-               private UserTableComposite userTableCmp;
-               private Composite container;
-               private Session session;
-
-               public ChooseUsersWizardPage(Session session) {
-                       super("Choose Users");
-                       this.session = session;
-                       setTitle("Select users who will be impacted");
-               }
-
-               @Override
-               public void createControl(Composite parent) {
-                       container = new Composite(parent, SWT.NONE);
-                       container.setLayout(new FillLayout());
-                       userTableCmp = new MyUserTableCmp(container, SWT.NO_FOCUS, session);
-                       userTableCmp.populate(true, true);
-                       setControl(container);
-
-                       // Add listener to update message when shown
-                       final IWizardContainer container = this.getContainer();
-                       if (container instanceof IPageChangeProvider) {
-                               ((IPageChangeProvider) container).addPageChangedListener(this);
-                       }
-
-               }
-
-               @Override
-               public void pageChanged(PageChangedEvent event) {
-                       if (event.getSelectedPage() == this) {
-                               String msg = "Chosen batch action: "
-                                               + chooseCommandPage.getCommandLbl();
-                               ((WizardPage) event.getSelectedPage()).setMessage(msg);
-                       }
-               }
-
-               protected List<Node> getSelectedUsers() {
-                       return userTableCmp.getSelectedUsers();
-               }
-
-               private class MyUserTableCmp extends UserTableComposite {
-
-                       private static final long serialVersionUID = 1L;
-
-                       public MyUserTableCmp(Composite parent, int style, Session session) {
-                               super(parent, style, session);
-                       }
-
-                       @Override
-                       protected void refreshFilteredList() {
-                               List<Node> nodes = new ArrayList<Node>();
-                               try {
-                                       NodeIterator ni = listFilteredElements(session,
-                                                       getFilterString());
-
-                                       users: while (ni.hasNext()) {
-                                               Node currNode = ni.nextNode();
-                                               String username = currNode.hasProperty(ARGEO_USER_ID) ? currNode
-                                                               .getProperty(ARGEO_USER_ID).getString() : "";
-                                               if (username.equals(session.getUserID()))
-                                                       continue users;
-                                               else
-                                                       nodes.add(currNode);
-                                       }
-                                       getTableViewer().setInput(nodes.toArray());
-                               } catch (RepositoryException e) {
-                                       throw new ArgeoException("Unable to list users", e);
-                               }
-                       }
-               }
-       }
-
-       /**
-        * Recapitulation of input data before running real update
-        */
-       private class ValidateAndLaunchWizardPage extends WizardPage implements
-                       IPageChangedListener {
-               private static final long serialVersionUID = 1L;
-               private UserTableComposite userTableCmp;
-               private Session session;
-
-               public ValidateAndLaunchWizardPage(Session session) {
-                       super("Validate and launch");
-                       this.session = session;
-                       setTitle("Validate and launch");
-               }
-
-               @Override
-               public void createControl(Composite parent) {
-                       Composite mainCmp = new Composite(parent, SWT.NO_FOCUS);
-                       mainCmp.setLayout(new FillLayout());
-
-                       // Add listener to update user list when shown
-                       final IWizardContainer container = this.getContainer();
-                       if (container instanceof IPageChangeProvider) {
-                               ((IPageChangeProvider) container).addPageChangedListener(this);
-                       }
-
-                       userTableCmp = new UserTableComposite(mainCmp, SWT.NO_FOCUS,
-                                       session);
-                       userTableCmp.populate(false, false);
-                       setControl(mainCmp);
-               }
-
-               @Override
-               public void pageChanged(PageChangedEvent event) {
-                       if (event.getSelectedPage() == this) {
-                               @SuppressWarnings({ "unchecked", "rawtypes" })
-                               Object[] values = ((ArrayList) userListPage.getSelectedUsers())
-                                               .toArray(new Object[userListPage.getSelectedUsers()
-                                                               .size()]);
-                               userTableCmp.getTableViewer().setInput(values);
-                               String msg = "Following batch action: ["
-                                               + chooseCommandPage.getCommandLbl()
-                                               + "] will be perfomed on the users listed below.\n"
-                                               + "Are you sure you want to proceed?";
-                               ((WizardPage) event.getSelectedPage()).setMessage(msg);
-                       }
-               }
-
-               // private class MyUserTableCmp extends UserTableComposite {
-               // public MyUserTableCmp(Composite parent, int style, Session session) {
-               // super(parent, style, session);
-               // }
-               //
-               // @Override
-               // protected void refreshFilteredList() {
-               // @SuppressWarnings({ "unchecked", "rawtypes" })
-               //
-               // setFilteredList(values);
-               // }
-               //
-               // @Override
-               // public void setVisible(boolean visible) {
-               // super.setVisible(visible);
-               // if (visible)
-               // refreshFilteredList();
-               // }
-               // }
-       }
-}
\ No newline at end of file
diff --git a/org.argeo.security.ui.admin/src/org/argeo/security/ui/admin/SecurityAdminImages.java b/org.argeo.security.ui.admin/src/org/argeo/security/ui/admin/SecurityAdminImages.java
new file mode 100644 (file)
index 0000000..f7ffa9c
--- /dev/null
@@ -0,0 +1,33 @@
+/*
+ * Argeo Connect - Data management and communications
+ * Copyright (C) 2012 Argeo GmbH
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>
+ *
+ * Additional permission under GNU GPL version 3 section 7
+ *
+ * If you modify this Program, or any covered work, by linking or combining it
+ * with software covered by the terms of the Eclipse Public License, the
+ * licensors of this Program grant you additional permission to convey the
+ * resulting work. Corresponding Source for a non-source form of such a
+ * combination shall include the source code for the parts of such software
+ * which are used as well as that of the covered work.
+ */
+package org.argeo.security.ui.admin;
+
+/** Shared icons that must be declared programmatically . */
+public class SecurityAdminImages {
+       @SuppressWarnings("unused")
+       private final static String PREFIX = "icons/";
+}
diff --git a/org.argeo.security.ui.admin/src/org/argeo/security/ui/admin/SecurityAdminPerspective.java b/org.argeo.security.ui.admin/src/org/argeo/security/ui/admin/SecurityAdminPerspective.java
new file mode 100644 (file)
index 0000000..c743f56
--- /dev/null
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2007-2012 Argeo GmbH
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *         http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.argeo.security.ui.admin;
+
+import org.argeo.security.ui.admin.views.RolesView;
+import org.argeo.security.ui.admin.views.UsersView;
+import org.eclipse.ui.IFolderLayout;
+import org.eclipse.ui.IPageLayout;
+import org.eclipse.ui.IPerspectiveFactory;
+
+public class SecurityAdminPerspective implements IPerspectiveFactory {
+       public void createInitialLayout(IPageLayout layout) {
+               String editorArea = layout.getEditorArea();
+               layout.setEditorAreaVisible(true);
+               layout.setFixed(false);
+
+               IFolderLayout left = layout.createFolder("left", IPageLayout.LEFT,
+                               0.65f, editorArea);
+               left.addView(UsersView.ID);
+               left.addView(RolesView.ID);
+       }
+
+}
diff --git a/org.argeo.security.ui.admin/src/org/argeo/security/ui/admin/SecurityAdminPlugin.java b/org.argeo.security.ui.admin/src/org/argeo/security/ui/admin/SecurityAdminPlugin.java
new file mode 100644 (file)
index 0000000..06e9bd5
--- /dev/null
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2007-2012 Argeo GmbH
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *         http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.argeo.security.ui.admin;
+
+import org.eclipse.jface.resource.ImageDescriptor;
+import org.eclipse.ui.plugin.AbstractUIPlugin;
+import org.osgi.framework.BundleContext;
+
+public class SecurityAdminPlugin extends AbstractUIPlugin {
+       public static final String PLUGIN_ID = "org.argeo.security.ui.admin"; //$NON-NLS-1$
+       private static SecurityAdminPlugin plugin;
+
+       public SecurityAdminPlugin() {
+       }
+
+       public void start(BundleContext context) throws Exception {
+               super.start(context);
+               plugin = this;
+       }
+
+       public void stop(BundleContext context) throws Exception {
+               plugin = null;
+               super.stop(context);
+       }
+
+       public static SecurityAdminPlugin getDefault() {
+               return plugin;
+       }
+
+       public static ImageDescriptor getImageDescriptor(String path) {
+               return imageDescriptorFromPlugin(PLUGIN_ID, path);
+       }
+
+}
diff --git a/org.argeo.security.ui.admin/src/org/argeo/security/ui/admin/UserTableComposite.java b/org.argeo.security.ui.admin/src/org/argeo/security/ui/admin/UserTableComposite.java
new file mode 100644 (file)
index 0000000..720fade
--- /dev/null
@@ -0,0 +1,367 @@
+package org.argeo.security.ui.admin;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.jcr.Node;
+import javax.jcr.NodeIterator;
+import javax.jcr.Property;
+import javax.jcr.PropertyType;
+import javax.jcr.RepositoryException;
+import javax.jcr.Session;
+import javax.jcr.query.QueryManager;
+import javax.jcr.query.QueryResult;
+import javax.jcr.query.qom.Constraint;
+import javax.jcr.query.qom.Ordering;
+import javax.jcr.query.qom.QueryObjectModel;
+import javax.jcr.query.qom.QueryObjectModelFactory;
+import javax.jcr.query.qom.Selector;
+import javax.jcr.query.qom.StaticOperand;
+
+import org.argeo.ArgeoException;
+import org.argeo.eclipse.ui.EclipseUiUtils;
+import org.argeo.eclipse.ui.jcr.JcrUiUtils;
+import org.argeo.eclipse.ui.jcr.lists.ColumnDefinition;
+import org.argeo.eclipse.ui.jcr.lists.NodeViewerComparator;
+import org.argeo.eclipse.ui.jcr.lists.SimpleJcrNodeLabelProvider;
+import org.argeo.eclipse.ui.specific.EclipseUiSpecificUtils;
+import org.argeo.eclipse.ui.utils.ViewerUtils;
+import org.argeo.jcr.ArgeoNames;
+import org.argeo.jcr.ArgeoTypes;
+import org.argeo.jcr.JcrUtils;
+import org.eclipse.jface.viewers.CheckboxTableViewer;
+import org.eclipse.jface.viewers.ColumnLabelProvider;
+import org.eclipse.jface.viewers.IStructuredContentProvider;
+import org.eclipse.jface.viewers.TableViewer;
+import org.eclipse.jface.viewers.TableViewerColumn;
+import org.eclipse.jface.viewers.Viewer;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.ModifyEvent;
+import org.eclipse.swt.events.ModifyListener;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.graphics.Font;
+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.Text;
+
+public class UserTableComposite extends Composite implements ArgeoNames {
+       // private final static Log log =
+       // LogFactory.getLog(UserTableComposite.class);
+
+       private static final long serialVersionUID = -7385959046279360420L;
+
+       private TableViewer usersViewer;
+       private Text filterTxt;
+       private final static String FILTER_HELP_MSG = "Type filter criterion "
+                       + "separated by a space";
+       private Session session;
+
+       private Font italic;
+       private Font bold;
+
+       private boolean hasFilter;
+       private boolean hasSelectionColumn;
+
+       // private List<Node> selectedItems = new ArrayList<Node>();
+
+       /**
+        * Overwrite to display other columns
+        */
+       public List<ColumnDefinition> getColumnsDef() {
+               List<ColumnDefinition> columnDefs = new ArrayList<ColumnDefinition>();
+
+               // User ID
+               columnDefs.add(new ColumnDefinition(null, ARGEO_USER_ID,
+                               PropertyType.STRING, "User ID", 100));
+               // Displayed name
+               columnDefs.add(new ColumnDefinition(null, Property.JCR_TITLE,
+                               PropertyType.STRING, "Name", 150));
+
+               // E-mail
+               columnDefs.add(new ColumnDefinition(null, ARGEO_PRIMARY_EMAIL,
+                               PropertyType.STRING, "E-mail", 150));
+
+               // Description
+               columnDefs.add(new ColumnDefinition(null, Property.JCR_DESCRIPTION,
+                               PropertyType.STRING, "Description", 200));
+
+               return columnDefs;
+       }
+
+       public UserTableComposite(Composite parent, int style, Session session) {
+               super(parent, style);
+               this.session = session;
+       }
+
+       /**
+        * 
+        * @param addFilter
+        *            choose to add a field to filter results or not
+        * @param addSelection
+        *            choose to add a column to select some of the displayed results
+        *            or not
+        */
+       public void populate(boolean addFilter, boolean addSelection) {
+               // initialization
+               Composite parent = this;
+               italic = EclipseUiUtils.getItalicFont(parent);
+               bold = EclipseUiUtils.getBoldFont(parent);
+               hasFilter = addFilter;
+               hasSelectionColumn = addSelection;
+
+               // Main Layout
+               this.setLayout(new GridLayout(1, false));
+               if (hasFilter)
+                       createFilterPart(parent);
+               usersViewer = createTableViewer(parent);
+               EclipseUiSpecificUtils.enableToolTipSupport(usersViewer);
+               usersViewer.setContentProvider(new UsersContentProvider());
+               refreshFilteredList();
+       }
+
+       public List<Node> getSelectedUsers() {
+               if (hasSelectionColumn) {
+                       Object[] elements = ((CheckboxTableViewer) usersViewer)
+                                       .getCheckedElements();
+
+                       List<Node> result = new ArrayList<Node>();
+                       for (Object obj : elements) {
+                               result.add((Node) obj);
+                       }
+                       return result;
+               } else
+                       throw new ArgeoException("Unvalid request: no selection column "
+                                       + "has been created for the current table");
+       }
+
+       /** Returns the User table viewer, typically to add doubleclick listener */
+       public TableViewer getTableViewer() {
+               return usersViewer;
+       }
+       
+       /** Returns filter String or null*/
+       protected String getFilterString() {
+               return hasFilter ? filterTxt.getText() : null;
+       }
+       
+       
+
+       private TableViewer createTableViewer(final Composite parent) {
+               int style = SWT.MULTI | SWT.H_SCROLL | SWT.V_SCROLL;
+               if (hasSelectionColumn)
+                       style = style | SWT.CHECK;
+
+               Table table = new Table(parent, style);
+               table.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
+
+               TableViewer viewer;
+               if (hasSelectionColumn)
+                       viewer = new CheckboxTableViewer(table);
+               else
+                       viewer = new TableViewer(table);
+               table.setLinesVisible(true);
+               table.setHeaderVisible(true);
+
+               // pass a mapping between col index and property name to the comparator.
+               // List<String> propertiesList = new ArrayList<String>();
+
+               TableViewerColumn column;
+               int offset = 0;
+               if (hasSelectionColumn) {
+                       offset = 1;
+                       column = ViewerUtils.createTableViewerColumn(viewer, "", SWT.NONE,
+                                       25);
+                       column.setLabelProvider(new ColumnLabelProvider() {
+                               private static final long serialVersionUID = 1L;
+
+                               @Override
+                               public String getText(Object element) {
+                                       return null;
+                               }
+                       });
+                       SelectionAdapter selectionAdapter = new SelectionAdapter() {
+                               private static final long serialVersionUID = 1L;
+
+                               boolean allSelected = false;
+
+                               @Override
+                               public void widgetSelected(SelectionEvent e) {
+                                       allSelected = !allSelected;
+                                       ((CheckboxTableViewer) usersViewer)
+                                                       .setAllChecked(allSelected);
+                               }
+                       };
+                       column.getColumn().addSelectionListener(selectionAdapter);
+               }
+
+               // Create other columns
+               List<ColumnDefinition> colDefs = getColumnsDef();
+
+               NodeViewerComparator comparator = new NodeViewerComparator();
+               int i = offset;
+               for (ColumnDefinition colDef : colDefs) {
+                       column = ViewerUtils.createTableViewerColumn(viewer,
+                                       colDef.getHeaderLabel(), SWT.NONE, colDef.getColumnSize());
+                       column.setLabelProvider(new CLProvider(colDef.getPropertyName()));
+                       column.getColumn().addSelectionListener(
+                                       JcrUiUtils.getNodeSelectionAdapter(i,
+                                                       colDef.getPropertyType(), colDef.getPropertyName(),
+                                                       comparator, viewer));
+                       i++;
+               }
+
+               // IMPORTANT: initialize comparator before setting it
+               ColumnDefinition firstCol = colDefs.get(0);
+               comparator.setColumn(firstCol.getPropertyType(),
+                               firstCol.getPropertyName());
+               viewer.setComparator(comparator);
+
+               return viewer;
+       }
+
+       private class CLProvider extends SimpleJcrNodeLabelProvider {
+
+               private static final long serialVersionUID = 1L;
+
+               public CLProvider(String propertyName) {
+                       super(propertyName);
+               }
+
+               public String getToolTipText(Object element) {
+                       return getText(element);
+               }
+
+               @Override
+               public Font getFont(Object elem) {
+                       // self
+                       String username = getProperty(elem, ARGEO_USER_ID);
+                       if (username.equals(session.getUserID()))
+                               return bold;
+
+                       // disabled
+                       try {
+                               Node userProfile = (Node) elem;
+                               // Node userProfile = userHome.getNode(ARGEO_PROFILE);
+                               if (!userProfile.getProperty(ARGEO_ENABLED).getBoolean())
+                                       return italic;
+                               else
+                                       return null;
+                       } catch (RepositoryException e) {
+                               throw new ArgeoException("Cannot get font for " + username, e);
+                       }
+               }
+       }
+
+       @Override
+       public boolean setFocus() {
+               usersViewer.getTable().setFocus();
+               return true;
+       }
+
+       @Override
+       public void dispose() {
+               super.dispose();
+       }
+
+       public void refresh() {
+               refreshFilteredList();
+       }
+
+       private String getProperty(Object element, String name) {
+               try {
+                       Node userProfile = (Node) element;
+                       return userProfile.hasProperty(name) ? userProfile
+                                       .getProperty(name).getString() : "";
+               } catch (RepositoryException e) {
+                       throw new ArgeoException("Cannot get property " + name, e);
+               }
+       }
+
+       private class UsersContentProvider implements IStructuredContentProvider {
+               private static final long serialVersionUID = 1L;
+
+               public Object[] getElements(Object inputElement) {
+                       return (Object[]) inputElement;
+               }
+
+               public void dispose() {
+               }
+
+               public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
+               }
+       }
+
+       /* MANAGE FILTER */
+       private void createFilterPart(Composite parent) {
+               // Text Area for the filter
+               filterTxt = new Text(parent, SWT.BORDER | SWT.SEARCH | SWT.ICON_SEARCH
+                               | SWT.ICON_CANCEL);
+               filterTxt.setMessage(FILTER_HELP_MSG);
+               filterTxt.setLayoutData(new GridData(GridData.GRAB_HORIZONTAL
+                               | GridData.HORIZONTAL_ALIGN_FILL));
+               filterTxt.addModifyListener(new ModifyListener() {
+                       private static final long serialVersionUID = 1L;
+
+                       public void modifyText(ModifyEvent event) {
+                               refreshFilteredList();
+                       }
+               });
+       }
+
+       /**
+        * Refresh the user list: caller might overwrite in order to display a
+        * subset of all users, typically to remove current user from the list
+        */
+       protected void refreshFilteredList() {
+               List<Node> nodes;
+               try {
+                       nodes = JcrUtils.nodeIteratorToList(listFilteredElements(session,
+                                       hasFilter ? filterTxt.getText() : null));
+                       usersViewer.setInput(nodes.toArray());
+               } catch (RepositoryException e) {
+                       throw new ArgeoException("Unable to list users", e);
+               }
+       }
+
+       /**
+        * Build repository request : caller might overwrite in order to display a
+        * subset of all users
+        */
+       protected NodeIterator listFilteredElements(Session session, String filter)
+                       throws RepositoryException {
+               QueryManager queryManager = session.getWorkspace().getQueryManager();
+               QueryObjectModelFactory factory = queryManager.getQOMFactory();
+
+               Selector source = factory.selector(ArgeoTypes.ARGEO_USER_PROFILE,
+                               ArgeoTypes.ARGEO_USER_PROFILE);
+
+               // Dynamically build constraint depending on the filter String
+               Constraint defaultC = null;
+               if (filter != null && !"".equals(filter.trim())) {
+                       String[] strs = filter.trim().split(" ");
+                       for (String token : strs) {
+                               StaticOperand so = factory.literal(session.getValueFactory()
+                                               .createValue("*" + token + "*"));
+                               Constraint currC = factory.fullTextSearch(
+                                               source.getSelectorName(), null, so);
+                               if (defaultC == null)
+                                       defaultC = currC;
+                               else
+                                       defaultC = factory.and(defaultC, currC);
+                       }
+               }
+
+               Ordering order = factory.ascending(factory.propertyValue(
+                               source.getSelectorName(), ARGEO_USER_ID));
+               Ordering[] orderings = { order };
+
+               QueryObjectModel query = factory.createQuery(source, defaultC,
+                               orderings, null);
+
+               QueryResult result = query.execute();
+               return result.getNodes();
+       }
+}
\ No newline at end of file
diff --git a/org.argeo.security.ui.admin/src/org/argeo/security/ui/admin/commands/AddRole.java b/org.argeo.security.ui.admin/src/org/argeo/security/ui/admin/commands/AddRole.java
new file mode 100644 (file)
index 0000000..a1008f6
--- /dev/null
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2007-2012 Argeo GmbH
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *         http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.argeo.security.ui.admin.commands;
+
+import org.argeo.ArgeoException;
+import org.argeo.security.UserAdminService;
+import org.argeo.security.ui.admin.editors.ArgeoUserEditor;
+import org.argeo.security.ui.admin.views.RolesView;
+import org.eclipse.core.commands.AbstractHandler;
+import org.eclipse.core.commands.ExecutionEvent;
+import org.eclipse.core.commands.ExecutionException;
+import org.eclipse.ui.IEditorReference;
+import org.eclipse.ui.IWorkbenchPage;
+import org.eclipse.ui.handlers.HandlerUtil;
+
+/** Add a new role. */
+public class AddRole extends AbstractHandler {
+       public final static String COMMAND_ID = "org.argeo.security.ui.admin.addRole";
+       private UserAdminService userAdminService;
+       private String rolePrefix = "ROLE_";
+
+       public Object execute(ExecutionEvent event) throws ExecutionException {
+               RolesView rolesView = (RolesView) HandlerUtil
+                               .getActiveWorkbenchWindow(event).getActivePage()
+                               .findView(RolesView.ID);
+               String role = rolesView.getNewRole();
+               if (role.trim().equals(""))
+                       return null;
+               if (role.equals(rolesView.getAddNewRoleText()))
+                       return null;
+               role = role.trim().toUpperCase();
+               if (!role.startsWith(rolePrefix))
+                       role = rolePrefix + role;
+               if (userAdminService.listEditableRoles().contains(role))
+                       throw new ArgeoException("Role " + role + " already exists");
+               userAdminService.newRole(role);
+               rolesView.refresh();
+
+               // refresh editors
+               IEditorReference[] refs = HandlerUtil.getActiveWorkbenchWindow(event)
+                               .getActivePage()
+                               .findEditors(null, ArgeoUserEditor.ID, IWorkbenchPage.MATCH_ID);
+               for (IEditorReference ref : refs) {
+                       ArgeoUserEditor userEditor = (ArgeoUserEditor) ref.getEditor(false);
+                       if (userEditor != null) {
+                               userEditor.refresh();
+                       }
+               }
+               return null;
+       }
+
+       public void setUserAdminService(UserAdminService userAdminService) {
+               this.userAdminService = userAdminService;
+       }
+
+}
diff --git a/org.argeo.security.ui.admin/src/org/argeo/security/ui/admin/commands/DeleteRole.java b/org.argeo.security.ui.admin/src/org/argeo/security/ui/admin/commands/DeleteRole.java
new file mode 100644 (file)
index 0000000..6cba11e
--- /dev/null
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2007-2012 Argeo GmbH
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *         http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.argeo.security.ui.admin.commands;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import org.argeo.security.UserAdminService;
+import org.argeo.security.ui.admin.views.RolesView;
+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.jface.viewers.IStructuredSelection;
+import org.eclipse.ui.handlers.HandlerUtil;
+
+/** Deletes the selected roles */
+public class DeleteRole extends AbstractHandler {
+       private UserAdminService userAdminService;
+
+       @SuppressWarnings("unchecked")
+       public Object execute(ExecutionEvent event) throws ExecutionException {
+               ISelection selection = HandlerUtil.getCurrentSelection(event);
+               if (selection.isEmpty())
+                       return null;
+
+               List<String> toDelete = new ArrayList<String>();
+               Iterator<String> it = ((IStructuredSelection) selection).iterator();
+               while (it.hasNext()) {
+                       toDelete.add(it.next());
+               }
+
+               if (!MessageDialog
+                               .openQuestion(
+                                               HandlerUtil.getActiveShell(event),
+                                               "Delete Role",
+                                               "Are you sure that you want to delete "
+                                                               + toDelete
+                                                               + "?\n"
+                                                               + "This may lead to inconsistencies in the application."))
+                       return null;
+
+               for (String role : toDelete) {
+                       userAdminService.deleteRole(role);
+               }
+
+               RolesView view = (RolesView) HandlerUtil
+                               .getActiveWorkbenchWindow(event).getActivePage()
+                               .findView(RolesView.ID);
+               view.refresh();
+               return null;
+       }
+
+       public void setUserAdminService(UserAdminService userAdminService) {
+               this.userAdminService = userAdminService;
+       }
+}
\ No newline at end of file
diff --git a/org.argeo.security.ui.admin/src/org/argeo/security/ui/admin/commands/DeleteUser.java b/org.argeo.security.ui.admin/src/org/argeo/security/ui/admin/commands/DeleteUser.java
new file mode 100644 (file)
index 0000000..ccf360f
--- /dev/null
@@ -0,0 +1,104 @@
+/*
+ * Copyright (C) 2007-2012 Argeo GmbH
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *         http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.argeo.security.ui.admin.commands;
+
+import java.util.Iterator;
+import java.util.Map;
+import java.util.TreeMap;
+
+import javax.jcr.Node;
+import javax.jcr.RepositoryException;
+import javax.jcr.Session;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.argeo.ArgeoException;
+import org.argeo.jcr.ArgeoNames;
+import org.argeo.jcr.JcrUtils;
+import org.argeo.security.UserAdminService;
+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.jface.viewers.IStructuredSelection;
+import org.eclipse.ui.handlers.HandlerUtil;
+
+/** Deletes the selected user nodes */
+public class DeleteUser extends AbstractHandler {
+       private final static Log log = LogFactory.getLog(DeleteUser.class);
+
+       private UserAdminService userAdminService;
+
+       @SuppressWarnings("unchecked")
+       public Object execute(ExecutionEvent event) throws ExecutionException {
+               ISelection selection = HandlerUtil.getCurrentSelection(event);
+               if (selection.isEmpty())
+                       return null;
+
+               Map<String, Node> toDelete = new TreeMap<String, Node>();
+               Iterator<Node> it = ((IStructuredSelection) selection).iterator();
+               nodes: while (it.hasNext()) {
+                       Node profileNode = it.next();
+                       try {
+                               String userName = profileNode.getProperty(
+                                               ArgeoNames.ARGEO_USER_ID).getString();
+                               if (userName.equals(profileNode.getSession().getUserID())) {
+                                       log.warn("Cannot delete its own user: " + userName);
+                                       continue nodes;
+                               }
+                               toDelete.put(userName, profileNode);
+                       } catch (RepositoryException e) {
+                               log.warn("Cannot interpred user " + profileNode);
+                       }
+               }
+
+               if (!MessageDialog
+                               .openQuestion(
+                                               HandlerUtil.getActiveShell(event),
+                                               "Delete User",
+                                               "Are you sure that you want to delete users "
+                                                               + toDelete.keySet()
+                                                               + "?\n"
+                                                               + "This may lead to inconsistencies in the application."))
+                       return null;
+
+               for (String username : toDelete.keySet()) {
+                       Session session = null;
+                       try {
+                               Node profileNode = toDelete.get(username);
+                               userAdminService.deleteUser(username);
+                               profileNode.getParent().remove();
+                               session = profileNode.getSession();
+                               session.save();
+                       } catch (RepositoryException e) {
+                               JcrUtils.discardQuietly(session);
+                               throw new ArgeoException("Cannot list users", e);
+                       }
+               }
+
+               userAdminService.synchronize();
+               // UsersView view = (UsersView) HandlerUtil
+               // .getActiveWorkbenchWindow(event).getActivePage()
+               // .findView(UsersView.ID);
+               // view.refresh();
+               return null;
+       }
+
+       public void setUserAdminService(UserAdminService userAdminService) {
+               this.userAdminService = userAdminService;
+       }
+}
\ No newline at end of file
diff --git a/org.argeo.security.ui.admin/src/org/argeo/security/ui/admin/commands/NewUser.java b/org.argeo.security.ui.admin/src/org/argeo/security/ui/admin/commands/NewUser.java
new file mode 100644 (file)
index 0000000..660896d
--- /dev/null
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2007-2012 Argeo GmbH
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *         http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.argeo.security.ui.admin.commands;
+
+import javax.jcr.Repository;
+import javax.jcr.Session;
+
+import org.argeo.jcr.JcrUtils;
+import org.argeo.security.UserAdminService;
+import org.argeo.security.jcr.JcrSecurityModel;
+import org.argeo.security.ui.admin.wizards.NewUserWizard;
+import org.eclipse.core.commands.AbstractHandler;
+import org.eclipse.core.commands.ExecutionEvent;
+import org.eclipse.core.commands.ExecutionException;
+import org.eclipse.jface.wizard.WizardDialog;
+import org.eclipse.ui.handlers.HandlerUtil;
+
+/** Launch a wizard that enables creation of a new user. */
+public class NewUser extends AbstractHandler {
+       private Repository repository;
+       private UserAdminService userAdminService;
+       private JcrSecurityModel jcrSecurityModel;
+
+       public Object execute(ExecutionEvent event) throws ExecutionException {
+               Session session = null;
+               try {
+                       session = repository.login();
+                       NewUserWizard newUserWizard = new NewUserWizard(session,
+                                       userAdminService, jcrSecurityModel);
+                       WizardDialog dialog = new WizardDialog(
+                                       HandlerUtil.getActiveShell(event), newUserWizard);
+                       dialog.open();
+               } catch (Exception e) {
+                       throw new ExecutionException("Cannot open wizard", e);
+               } finally {
+                       JcrUtils.logoutQuietly(session);
+               }
+               return null;
+       }
+
+       public void setRepository(Repository repository) {
+               this.repository = repository;
+       }
+
+       public void setUserAdminService(UserAdminService userAdminService) {
+               this.userAdminService = userAdminService;
+       }
+
+       public void setJcrSecurityModel(JcrSecurityModel jcrSecurityModel) {
+               this.jcrSecurityModel = jcrSecurityModel;
+       }
+
+}
diff --git a/org.argeo.security.ui.admin/src/org/argeo/security/ui/admin/commands/OpenArgeoUserEditor.java b/org.argeo.security.ui.admin/src/org/argeo/security/ui/admin/commands/OpenArgeoUserEditor.java
new file mode 100644 (file)
index 0000000..bae928c
--- /dev/null
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2007-2012 Argeo GmbH
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *         http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.argeo.security.ui.admin.commands;
+
+import org.argeo.security.ui.admin.editors.ArgeoUserEditor;
+import org.argeo.security.ui.admin.editors.ArgeoUserEditorInput;
+import org.eclipse.core.commands.AbstractHandler;
+import org.eclipse.core.commands.ExecutionEvent;
+import org.eclipse.core.commands.ExecutionException;
+import org.eclipse.ui.IWorkbenchPage;
+import org.eclipse.ui.handlers.HandlerUtil;
+
+/** Command handler to set visible or open a Argeo user. */
+public class OpenArgeoUserEditor extends AbstractHandler {
+       public final static String COMMAND_ID = "org.argeo.security.ui.admin.openArgeoUserEditor";
+       public final static String PARAM_USERNAME = "org.argeo.security.ui.admin.username";
+
+       public Object execute(ExecutionEvent event) throws ExecutionException {
+               try {
+                       ArgeoUserEditorInput editorInput = new ArgeoUserEditorInput(
+                                       event.getParameter(PARAM_USERNAME));
+                       IWorkbenchPage activePage = HandlerUtil.getActiveWorkbenchWindow(
+                                       event).getActivePage();
+                       activePage.openEditor(editorInput, ArgeoUserEditor.ID);
+               } catch (Exception e) {
+                       throw new ExecutionException("Cannot open editor", e);
+               }
+               return null;
+       }
+}
diff --git a/org.argeo.security.ui.admin/src/org/argeo/security/ui/admin/commands/RefreshRoles.java b/org.argeo.security.ui.admin/src/org/argeo/security/ui/admin/commands/RefreshRoles.java
new file mode 100644 (file)
index 0000000..41c78f0
--- /dev/null
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2007-2012 Argeo GmbH
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *         http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.argeo.security.ui.admin.commands;
+
+import org.eclipse.core.commands.AbstractHandler;
+import org.eclipse.core.commands.ExecutionEvent;
+import org.eclipse.core.commands.ExecutionException;
+
+/**
+ * Refreshes the roles view.
+ */
+public class RefreshRoles extends AbstractHandler {
+       public Object execute(ExecutionEvent event) throws ExecutionException {
+
+               return null;
+       }
+
+}
\ No newline at end of file
diff --git a/org.argeo.security.ui.admin/src/org/argeo/security/ui/admin/commands/RefreshUsersList.java b/org.argeo.security.ui.admin/src/org/argeo/security/ui/admin/commands/RefreshUsersList.java
new file mode 100644 (file)
index 0000000..e4c14ab
--- /dev/null
@@ -0,0 +1,100 @@
+/*
+ * Copyright (C) 2007-2012 Argeo GmbH
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *         http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.argeo.security.ui.admin.commands;
+
+import java.util.Set;
+
+import javax.jcr.Node;
+import javax.jcr.NodeIterator;
+import javax.jcr.Repository;
+import javax.jcr.RepositoryException;
+import javax.jcr.Session;
+import javax.jcr.query.Query;
+
+import org.argeo.ArgeoException;
+import org.argeo.jcr.ArgeoNames;
+import org.argeo.jcr.ArgeoTypes;
+import org.argeo.jcr.JcrUtils;
+import org.argeo.security.UserAdminService;
+import org.argeo.security.ui.admin.views.UsersView;
+import org.eclipse.core.commands.AbstractHandler;
+import org.eclipse.core.commands.ExecutionEvent;
+import org.eclipse.core.commands.ExecutionException;
+import org.eclipse.ui.IWorkbenchPart;
+import org.eclipse.ui.handlers.HandlerUtil;
+
+/**
+ * Refreshes the main user list, removing nodes which are not referenced by user
+ * admin service.
+ */
+public class RefreshUsersList extends AbstractHandler {
+       private UserAdminService userAdminService;
+       private Repository repository;
+
+       public Object execute(ExecutionEvent event) throws ExecutionException {
+               Set<String> users = userAdminService.listUsers();
+               Session session = null;
+               try {
+                       session = repository.login();
+                       Query query = session
+                                       .getWorkspace()
+                                       .getQueryManager()
+                                       .createQuery(
+                                                       "select * from [" + ArgeoTypes.ARGEO_USER_HOME
+                                                                       + "]", Query.JCR_SQL2);
+                       NodeIterator nit = query.execute().getNodes();
+                       while (nit.hasNext()) {
+                               Node node = nit.nextNode();
+                               String username = node.getProperty(ArgeoNames.ARGEO_USER_ID)
+                                               .getString();
+                               if (!users.contains(username))
+                                       node.remove();
+                       }
+                       session.save();
+               } catch (RepositoryException e) {
+                       JcrUtils.discardQuietly(session);
+                       throw new ArgeoException("Cannot list users", e);
+               } finally {
+                       JcrUtils.logoutQuietly(session);
+               }
+               userAdminService.synchronize();
+
+               // FIXME try to refresh views that extend the UsersView and have another
+               // ID
+               IWorkbenchPart part = HandlerUtil.getActiveWorkbenchWindow(event)
+                               .getActivePage().getActivePart();
+               if (part instanceof UsersView)
+                       ((UsersView) part).refresh();
+
+               // Try to refresh UsersView if opened
+               UsersView view = (UsersView) HandlerUtil
+                               .getActiveWorkbenchWindow(event).getActivePage()
+                               .findView(UsersView.ID);
+               if (view != null)
+                       view.refresh();
+
+               return null;
+       }
+
+       public void setUserAdminService(UserAdminService userAdminService) {
+               this.userAdminService = userAdminService;
+       }
+
+       public void setRepository(Repository repository) {
+               this.repository = repository;
+       }
+
+}
\ No newline at end of file
diff --git a/org.argeo.security.ui.admin/src/org/argeo/security/ui/admin/commands/SaveArgeoUser.java b/org.argeo.security.ui.admin/src/org/argeo/security/ui/admin/commands/SaveArgeoUser.java
new file mode 100644 (file)
index 0000000..bd16f8b
--- /dev/null
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2007-2012 Argeo GmbH
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *         http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.argeo.security.ui.admin.commands;
+
+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.swt.widgets.Display;
+import org.eclipse.ui.IEditorPart;
+import org.eclipse.ui.IWorkbenchPart;
+import org.eclipse.ui.handlers.HandlerUtil;
+
+/** Save the currently edited Argeo user. */
+public class SaveArgeoUser extends AbstractHandler {
+       public final static String COMMAND_ID = "org.argeo.security.ui.admin.saveArgeoUser";
+
+       public Object execute(ExecutionEvent event) throws ExecutionException {
+               try {
+                       IWorkbenchPart iwp = HandlerUtil.getActiveWorkbenchWindow(event)
+                                       .getActivePage().getActivePart();
+
+                       if (!(iwp instanceof IEditorPart))
+                               return null;
+                       IEditorPart editor = (IEditorPart) iwp;
+                       editor.doSave(null);
+               } catch (Exception e) {
+                       MessageDialog.openError(Display.getDefault().getActiveShell(),
+                                       "Error", "Cannot save user: " + e.getMessage());
+               }
+               return null;
+       }
+
+}
diff --git a/org.argeo.security.ui.admin/src/org/argeo/security/ui/admin/commands/UserBatchUpdate.java b/org.argeo.security.ui.admin/src/org/argeo/security/ui/admin/commands/UserBatchUpdate.java
new file mode 100644 (file)
index 0000000..657dfc7
--- /dev/null
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2007-2012 Argeo GmbH
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *         http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.argeo.security.ui.admin.commands;
+
+import javax.jcr.Repository;
+import javax.jcr.Session;
+
+import org.argeo.jcr.JcrUtils;
+import org.argeo.security.UserAdminService;
+import org.argeo.security.jcr.JcrSecurityModel;
+import org.argeo.security.ui.admin.wizards.UserBatchUpdateWizard;
+import org.eclipse.core.commands.AbstractHandler;
+import org.eclipse.core.commands.ExecutionEvent;
+import org.eclipse.core.commands.ExecutionException;
+import org.eclipse.jface.wizard.WizardDialog;
+import org.eclipse.ui.handlers.HandlerUtil;
+
+/** Launch a wizard to update various properties about users in JCR. */
+public class UserBatchUpdate extends AbstractHandler {
+       private Repository repository;
+       private UserAdminService userAdminService;
+       private JcrSecurityModel jcrSecurityModel;
+
+       public Object execute(ExecutionEvent event) throws ExecutionException {
+               Session session = null;
+               try {
+                       session = repository.login();
+                       UserBatchUpdateWizard userBatchUpdateWizard = new UserBatchUpdateWizard(session,
+                                       userAdminService, jcrSecurityModel);
+                       WizardDialog dialog = new WizardDialog(
+                                       HandlerUtil.getActiveShell(event), userBatchUpdateWizard);
+                       dialog.open();
+               } catch (Exception e) {
+                       throw new ExecutionException("Cannot open wizard", e);
+               } finally {
+                       JcrUtils.logoutQuietly(session);
+               }
+               return null;
+       }
+
+       public void setRepository(Repository repository) {
+               this.repository = repository;
+       }
+
+       public void setUserAdminService(UserAdminService userAdminService) {
+               this.userAdminService = userAdminService;
+       }
+
+       public void setJcrSecurityModel(JcrSecurityModel jcrSecurityModel) {
+               this.jcrSecurityModel = jcrSecurityModel;
+       }
+
+}
diff --git a/org.argeo.security.ui.admin/src/org/argeo/security/ui/admin/editors/ArgeoUserEditor.java b/org.argeo.security.ui.admin/src/org/argeo/security/ui/admin/editors/ArgeoUserEditor.java
new file mode 100644 (file)
index 0000000..ebc0831
--- /dev/null
@@ -0,0 +1,158 @@
+/*
+ * Copyright (C) 2007-2012 Argeo GmbH
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *         http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.argeo.security.ui.admin.editors;
+
+import javax.jcr.Node;
+import javax.jcr.Repository;
+import javax.jcr.RepositoryException;
+import javax.jcr.Session;
+
+import org.argeo.ArgeoException;
+import org.argeo.jcr.JcrUtils;
+import org.argeo.jcr.UserJcrUtils;
+import org.argeo.security.UserAdminService;
+import org.argeo.security.jcr.JcrUserDetails;
+import org.argeo.security.ui.admin.SecurityAdminPlugin;
+import org.argeo.security.ui.admin.views.UsersView;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.ui.IEditorInput;
+import org.eclipse.ui.IEditorSite;
+import org.eclipse.ui.IWorkbench;
+import org.eclipse.ui.PartInitException;
+import org.eclipse.ui.forms.editor.FormEditor;
+import org.springframework.security.GrantedAuthority;
+
+/** Editor for an Argeo user. */
+public class ArgeoUserEditor extends FormEditor {
+       public final static String ID = SecurityAdminPlugin.PLUGIN_ID
+                       + ".adminArgeoUserEditor";
+
+       /* DEPENDENCY INJECTION */
+       private Session session;
+       private UserAdminService userAdminService;
+
+       // private Node userHome;
+       private Node userProfile;
+       private JcrUserDetails userDetails;
+
+       public void init(IEditorSite site, IEditorInput input)
+                       throws PartInitException {
+               super.init(site, input);
+               String username = ((ArgeoUserEditorInput) getEditorInput())
+                               .getUsername();
+               userProfile = UserJcrUtils.getUserProfile(session, username);
+
+               if (userAdminService.userExists(username)) {
+                       userDetails = (JcrUserDetails) userAdminService
+                                       .loadUserByUsername(username);
+               } else {
+                       GrantedAuthority[] authorities = {};
+                       try {
+                               userDetails = new JcrUserDetails(session, username, null,
+                                               authorities);
+                       } catch (RepositoryException e) {
+                               throw new ArgeoException("Cannot retrieve disabled JCR profile");
+                       }
+               }
+
+               this.setPartProperty("name", username != null ? username : "<new user>");
+               setPartName(username != null ? username : "<new user>");
+       }
+
+       protected void addPages() {
+               try {
+                       addPage(new DefaultUserMainPage(this, userProfile));
+                       addPage(new UserRolesPage(this, userDetails, userAdminService));
+               } catch (Exception e) {
+                       throw new ArgeoException("Cannot add pages", e);
+               }
+       }
+
+       @Override
+       public void doSave(IProgressMonitor monitor) {
+               // list pages
+               // TODO: make it more generic
+               DefaultUserMainPage defaultUserMainPage = (DefaultUserMainPage) findPage(DefaultUserMainPage.ID);
+               if (defaultUserMainPage.isDirty()) {
+                       defaultUserMainPage.doSave(monitor);
+                       String newPassword = defaultUserMainPage.getNewPassword();
+                       defaultUserMainPage.resetNewPassword();
+                       if (newPassword != null)
+                               userDetails = userDetails.cloneWithNewPassword(newPassword);
+               }
+
+               UserRolesPage userRolesPage = (UserRolesPage) findPage(UserRolesPage.ID);
+               if (userRolesPage.isDirty()) {
+                       userRolesPage.doSave(monitor);
+                       userDetails = userDetails.cloneWithNewRoles(userRolesPage
+                                       .getRoles());
+               }
+
+               userAdminService.updateUser(userDetails);
+
+               // if (userAdminService.userExists(user.getUsername()))
+               // userAdminService.updateUser(user);
+               // else {
+               // userAdminService.newUser(user);
+               // setPartName(user.getUsername());
+               // }
+               firePropertyChange(PROP_DIRTY);
+
+               userRolesPage.setUserDetails(userDetails);
+
+               // FIXME rather use a refresh command. Fails when called by another
+               // view.
+               // refresh users view
+               IWorkbench iw = SecurityAdminPlugin.getDefault().getWorkbench();
+               UsersView usersView = (UsersView) iw.getActiveWorkbenchWindow()
+                               .getActivePage().findView(UsersView.ID);
+               if (usersView != null)
+                       usersView.refresh();
+       }
+
+       @Override
+       public void doSaveAs() {
+       }
+
+       @Override
+       public boolean isSaveAsAllowed() {
+               return false;
+       }
+
+       public void refresh() {
+               UserRolesPage userRolesPage = (UserRolesPage) findPage(UserRolesPage.ID);
+               userRolesPage.refresh();
+       }
+
+       @Override
+       public void dispose() {
+               JcrUtils.logoutQuietly(session);
+               super.dispose();
+       }
+       
+       /* DEPENDENCY INJECTION */
+       public void setUserAdminService(UserAdminService userAdminService) {
+               this.userAdminService = userAdminService;
+       }
+       
+       public void setRepository(Repository repository) {
+               try {
+                       session = repository.login();
+               } catch (RepositoryException re) {
+                       throw new ArgeoException("Unable to initialise local session", re);
+               }
+       }
+}
diff --git a/org.argeo.security.ui.admin/src/org/argeo/security/ui/admin/editors/ArgeoUserEditorInput.java b/org.argeo.security.ui.admin/src/org/argeo/security/ui/admin/editors/ArgeoUserEditorInput.java
new file mode 100644 (file)
index 0000000..9d1d995
--- /dev/null
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2007-2012 Argeo GmbH
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *         http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.argeo.security.ui.admin.editors;
+
+import org.eclipse.jface.resource.ImageDescriptor;
+import org.eclipse.ui.IEditorInput;
+import org.eclipse.ui.IPersistableElement;
+
+/** Editor input for an Argeo user. */
+public class ArgeoUserEditorInput implements IEditorInput {
+       private final String username;
+
+       public ArgeoUserEditorInput(String username) {
+               this.username = username;
+       }
+
+       public Object getAdapter(@SuppressWarnings("rawtypes") Class adapter) {
+               return null;
+       }
+
+       public boolean exists() {
+               return username != null;
+       }
+
+       public ImageDescriptor getImageDescriptor() {
+               return null;
+       }
+
+       public String getName() {
+               return username != null ? username : "<new user>";
+       }
+
+       public IPersistableElement getPersistable() {
+               return null;
+       }
+
+       public String getToolTipText() {
+               return username != null ? username : "<new user>";
+       }
+
+       public boolean equals(Object obj) {
+               if (!(obj instanceof ArgeoUserEditorInput))
+                       return false;
+               if (((ArgeoUserEditorInput) obj).getUsername() == null)
+                       return false;
+               return ((ArgeoUserEditorInput) obj).getUsername().equals(username);
+       }
+
+       public String getUsername() {
+               return username;
+       }
+}
diff --git a/org.argeo.security.ui.admin/src/org/argeo/security/ui/admin/editors/DefaultUserMainPage.java b/org.argeo.security.ui.admin/src/org/argeo/security/ui/admin/editors/DefaultUserMainPage.java
new file mode 100644 (file)
index 0000000..5f99e19
--- /dev/null
@@ -0,0 +1,245 @@
+/*
+ * Copyright (C) 2007-2012 Argeo GmbH
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *         http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.argeo.security.ui.admin.editors;
+
+import java.util.Arrays;
+
+import javax.jcr.Node;
+import javax.jcr.Property;
+import javax.jcr.RepositoryException;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.argeo.ArgeoException;
+import org.argeo.jcr.ArgeoNames;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.ModifyEvent;
+import org.eclipse.swt.events.ModifyListener;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Text;
+import org.eclipse.ui.forms.AbstractFormPart;
+import org.eclipse.ui.forms.IManagedForm;
+import org.eclipse.ui.forms.SectionPart;
+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;
+import org.eclipse.ui.forms.widgets.Section;
+
+/**
+ * Display/edit the properties common to all Argeo users
+ */
+public class DefaultUserMainPage extends FormPage implements ArgeoNames {
+       final static String ID = "argeoUserEditor.mainPage";
+
+       private final static Log log = LogFactory.getLog(DefaultUserMainPage.class);
+       private Node userProfile;
+
+       private char[] newPassword;
+
+       public DefaultUserMainPage(FormEditor editor, Node userProfile) {
+               super(editor, ID, "Main");
+               this.userProfile = userProfile;
+       }
+
+       protected void createFormContent(final IManagedForm mf) {
+               try {
+                       ScrolledForm form = mf.getForm();
+                       refreshFormTitle(form);
+                       GridLayout mainLayout = new GridLayout(1, true);
+                       form.getBody().setLayout(mainLayout);
+
+                       createGeneralPart(form.getBody());
+                       createPassworPart(form.getBody());
+               } catch (RepositoryException e) {
+                       throw new ArgeoException("Cannot create form content", e);
+               }
+       }
+
+       /** Creates the general section */
+       protected void createGeneralPart(Composite parent)
+                       throws RepositoryException {
+               FormToolkit tk = getManagedForm().getToolkit();
+               Section section = tk.createSection(parent, Section.TITLE_BAR);
+               section.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
+               section.setText("General");
+               Composite body = tk.createComposite(section, SWT.WRAP);
+               section.setClient(body);
+               GridLayout layout = new GridLayout(2, false);
+               body.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
+               body.setLayout(layout);
+
+               final Text commonName = createLT(body, "Displayed Name",
+                               getProperty(Property.JCR_TITLE));
+               final Text firstName = createLT(body, "First name",
+                               getProperty(ARGEO_FIRST_NAME));
+               final Text lastName = createLT(body, "Last name",
+                               getProperty(ARGEO_LAST_NAME));
+               final Text email = createLT(body, "Email",
+                               getProperty(ARGEO_PRIMARY_EMAIL));
+               final Text description = createLMT(body, "Description",
+                               getProperty(Property.JCR_DESCRIPTION));
+
+               // create form part (controller)
+               AbstractFormPart part = new SectionPart(section) {
+                       public void commit(boolean onSave) {
+                               try {
+                                       userProfile.getSession().getWorkspace().getVersionManager()
+                                                       .checkout(userProfile.getPath());
+                                       userProfile.setProperty(Property.JCR_TITLE,
+                                                       commonName.getText());
+                                       userProfile.setProperty(ARGEO_FIRST_NAME,
+                                                       firstName.getText());
+                                       userProfile
+                                                       .setProperty(ARGEO_LAST_NAME, lastName.getText());
+                                       userProfile.setProperty(ARGEO_PRIMARY_EMAIL,
+                                                       email.getText());
+                                       userProfile.setProperty(Property.JCR_DESCRIPTION,
+                                                       description.getText());
+                                       userProfile.getSession().save();
+                                       userProfile.getSession().getWorkspace().getVersionManager()
+                                                       .checkin(userProfile.getPath());
+                                       super.commit(onSave);
+                                       refreshFormTitle(getManagedForm().getForm());
+                                       if (log.isTraceEnabled())
+                                               log.trace("General part committed");
+                               } catch (RepositoryException e) {
+                                       throw new ArgeoException("Cannot commit", e);
+                               }
+                       }
+               };
+               // if (username != null)
+               // username.addModifyListener(new FormPartML(part));
+               commonName.addModifyListener(new FormPartML(part));
+               firstName.addModifyListener(new FormPartML(part));
+               lastName.addModifyListener(new FormPartML(part));
+               email.addModifyListener(new FormPartML(part));
+               description.addModifyListener(new FormPartML(part));
+               getManagedForm().addPart(part);
+       }
+
+       private void refreshFormTitle(ScrolledForm form) throws RepositoryException {
+               form.setText(getProperty(Property.JCR_TITLE)
+                               + (userProfile.getProperty(ARGEO_ENABLED).getBoolean() ? ""
+                                               : " [DISABLED]"));
+       }
+
+       /** @return the property, or the empty string if not set */
+       protected String getProperty(String name) throws RepositoryException {
+               return userProfile.hasProperty(name) ? userProfile.getProperty(name)
+                               .getString() : "";
+       }
+
+       /** Creates the password section */
+       protected void createPassworPart(Composite parent) {
+               FormToolkit tk = getManagedForm().getToolkit();
+               Section section = tk.createSection(parent, Section.TITLE_BAR);
+               section.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
+               section.setText("Password");
+
+               Composite body = tk.createComposite(section, SWT.WRAP);
+               section.setClient(body);
+               GridLayout layout = new GridLayout(2, false);
+               body.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
+               body.setLayout(layout);
+
+               // add widgets (view)
+               final Text password1 = createLP(body, "New password", "");
+               final Text password2 = createLP(body, "Repeat password", "");
+               // create form part (controller)
+               AbstractFormPart part = new SectionPart(section) {
+
+                       public void commit(boolean onSave) {
+                               if (!password1.getText().equals("")
+                                               || !password2.getText().equals("")) {
+                                       if (password1.getText().equals(password2.getText())) {
+                                               newPassword = password1.getText().toCharArray();
+                                               password1.setText("");
+                                               password2.setText("");
+                                               super.commit(onSave);
+                                       } else {
+                                               password1.setText("");
+                                               password2.setText("");
+                                               throw new ArgeoException("Passwords are not equals");
+                                       }
+                               }
+                       }
+
+               };
+               password1.addModifyListener(new FormPartML(part));
+               password2.addModifyListener(new FormPartML(part));
+               getManagedForm().addPart(part);
+       }
+
+       /** Creates label and text. */
+       protected Text createLT(Composite body, String label, String value) {
+               FormToolkit toolkit = getManagedForm().getToolkit();
+               Label lbl = toolkit.createLabel(body, label);
+               lbl.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false));
+               Text text = toolkit.createText(body, value, SWT.BORDER);
+               text.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));
+               return text;
+       }
+
+       /** Creates label and multiline text. */
+       protected Text createLMT(Composite body, String label, String value) {
+               FormToolkit toolkit = getManagedForm().getToolkit();
+               Label lbl = toolkit.createLabel(body, label);
+               lbl.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false));
+               Text text = toolkit.createText(body, value, SWT.BORDER | SWT.MULTI);
+               text.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, true));
+               return text;
+       }
+
+       /** Creates label and password. */
+       protected Text createLP(Composite body, String label, String value) {
+               FormToolkit toolkit = getManagedForm().getToolkit();
+               Label lbl = toolkit.createLabel(body, label);
+               lbl.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false));
+               Text text = toolkit.createText(body, value, SWT.BORDER | SWT.PASSWORD);
+               text.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));
+               return text;
+       }
+
+       private class FormPartML implements ModifyListener {
+               private AbstractFormPart formPart;
+
+               public FormPartML(AbstractFormPart generalPart) {
+                       this.formPart = generalPart;
+               }
+
+               public void modifyText(ModifyEvent e) {
+                       formPart.markDirty();
+               }
+
+       }
+
+       public String getNewPassword() {
+               if (newPassword != null)
+                       return new String(newPassword);
+               else
+                       return null;
+       }
+
+       public void resetNewPassword() {
+               if (newPassword != null)
+                       Arrays.fill(newPassword, 'x');
+               newPassword = null;
+       }
+}
diff --git a/org.argeo.security.ui.admin/src/org/argeo/security/ui/admin/editors/UserRolesPage.java b/org.argeo.security.ui.admin/src/org/argeo/security/ui/admin/editors/UserRolesPage.java
new file mode 100644 (file)
index 0000000..08cd457
--- /dev/null
@@ -0,0 +1,225 @@
+/*
+ * Copyright (C) 2007-2012 Argeo GmbH
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *         http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.argeo.security.ui.admin.editors;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.argeo.jcr.ArgeoNames;
+import org.argeo.security.UserAdminService;
+import org.argeo.security.ui.admin.SecurityAdminPlugin;
+import org.eclipse.jface.viewers.CellEditor;
+import org.eclipse.jface.viewers.CheckboxCellEditor;
+import org.eclipse.jface.viewers.ColumnLabelProvider;
+import org.eclipse.jface.viewers.EditingSupport;
+import org.eclipse.jface.viewers.IStructuredContentProvider;
+import org.eclipse.jface.viewers.TableViewer;
+import org.eclipse.jface.viewers.TableViewerColumn;
+import org.eclipse.jface.viewers.Viewer;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.layout.FillLayout;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Table;
+import org.eclipse.swt.widgets.TableColumn;
+import org.eclipse.ui.forms.AbstractFormPart;
+import org.eclipse.ui.forms.IManagedForm;
+import org.eclipse.ui.forms.editor.FormEditor;
+import org.eclipse.ui.forms.editor.FormPage;
+import org.eclipse.ui.forms.widgets.ScrolledForm;
+import org.springframework.security.GrantedAuthority;
+import org.springframework.security.userdetails.UserDetails;
+
+/**
+ * Display/edit the roles of a user.
+ */
+public class UserRolesPage extends FormPage implements ArgeoNames {
+       final static String ID = "argeoUserEditor.rolesPage";
+
+       private final static Log log = LogFactory.getLog(UserRolesPage.class);
+       private final static Image ROLE_CHECKED = SecurityAdminPlugin
+                       .getImageDescriptor("icons/security.gif").createImage();
+
+       private TableViewer rolesViewer;
+       private UserAdminService userAdminService;
+       private List<String> roles;
+
+       public UserRolesPage(FormEditor editor, UserDetails userDetails,
+                       UserAdminService userAdminService) {
+               super(editor, ID, "Roles");
+               setUserDetails(userDetails);
+               this.userAdminService = userAdminService;
+       }
+
+       public void setUserDetails(UserDetails userDetails) {
+               this.roles = new ArrayList<String>();
+               for (GrantedAuthority ga : userDetails.getAuthorities())
+                       roles.add(ga.getAuthority());
+               if (rolesViewer != null)
+                       rolesViewer.refresh();
+       }
+
+       protected void createFormContent(final IManagedForm mf) {
+               ScrolledForm form = mf.getForm();
+               form.setText("Roles");
+               FillLayout mainLayout = new FillLayout();
+               // ColumnLayout mainLayout = new ColumnLayout();
+               // mainLayout.minNumColumns = 1;
+               // mainLayout.maxNumColumns = 4;
+               // mainLayout.topMargin = 0;
+               // mainLayout.bottomMargin = 5;
+               // mainLayout.leftMargin = mainLayout.rightMargin =
+               // mainLayout.horizontalSpacing = mainLayout.verticalSpacing = 10;
+               form.getBody().setLayout(mainLayout);
+               createRolesPart(form.getBody());
+       }
+
+       /** Creates the role section */
+       protected void createRolesPart(Composite parent) {
+               Table table = new Table(parent, SWT.MULTI | SWT.H_SCROLL | SWT.V_SCROLL);
+
+               AbstractFormPart part = new AbstractFormPart() {
+                       public void commit(boolean onSave) {
+                               // roles have already been modified in editing
+                               super.commit(onSave);
+                               if (log.isTraceEnabled())
+                                       log.trace("Role part committed");
+                       }
+               };
+               getManagedForm().addPart(part);
+
+               // GridData gridData = new GridData(SWT.FILL, SWT.FILL, true, true);
+               // gridData.verticalSpan = 20;
+               // table.setLayoutData(gridData);
+               table.setLinesVisible(true);
+               table.setHeaderVisible(false);
+               rolesViewer = new TableViewer(table);
+
+               // check column
+               TableViewerColumn column = createTableViewerColumn(rolesViewer,
+                               "checked", 20);
+               column.setLabelProvider(new ColumnLabelProvider() {
+                       public String getText(Object element) {
+                               return null;
+                       }
+
+                       public Image getImage(Object element) {
+                               String role = element.toString();
+                               if (roles.contains(role)) {
+                                       return ROLE_CHECKED;
+                               } else {
+                                       return null;
+                               }
+                       }
+               });
+               column.setEditingSupport(new RoleEditingSupport(rolesViewer, part));
+
+               // role column
+               column = createTableViewerColumn(rolesViewer, "Role", 200);
+               column.setLabelProvider(new ColumnLabelProvider() {
+                       public String getText(Object element) {
+                               return element.toString();
+                       }
+
+                       public Image getImage(Object element) {
+                               return null;
+                       }
+               });
+               rolesViewer.setContentProvider(new RolesContentProvider());
+               rolesViewer.setInput(getEditorSite());
+       }
+
+       protected TableViewerColumn createTableViewerColumn(TableViewer viewer,
+                       String title, int bound) {
+               final TableViewerColumn viewerColumn = new TableViewerColumn(viewer,
+                               SWT.NONE);
+               final TableColumn column = viewerColumn.getColumn();
+               column.setText(title);
+               column.setWidth(bound);
+               column.setResizable(true);
+               column.setMoveable(true);
+               return viewerColumn;
+
+       }
+
+       public List<String> getRoles() {
+               return roles;
+       }
+
+       public void refresh() {
+               rolesViewer.refresh();
+       }
+
+       private class RolesContentProvider implements IStructuredContentProvider {
+               public Object[] getElements(Object inputElement) {
+                       return userAdminService.listEditableRoles().toArray();
+               }
+
+               public void dispose() {
+               }
+
+               public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
+               }
+       }
+
+       /** Select the columns by editing the checkbox in the first column */
+       class RoleEditingSupport extends EditingSupport {
+
+               private final TableViewer viewer;
+               private final AbstractFormPart formPart;
+
+               public RoleEditingSupport(TableViewer viewer, AbstractFormPart formPart) {
+                       super(viewer);
+                       this.viewer = viewer;
+                       this.formPart = formPart;
+               }
+
+               @Override
+               protected CellEditor getCellEditor(Object element) {
+                       return new CheckboxCellEditor(null, SWT.CHECK | SWT.READ_ONLY);
+
+               }
+
+               @Override
+               protected boolean canEdit(Object element) {
+                       return true;
+               }
+
+               @Override
+               protected Object getValue(Object element) {
+                       String role = element.toString();
+                       return roles.contains(role);
+
+               }
+
+               @Override
+               protected void setValue(Object element, Object value) {
+                       Boolean inRole = (Boolean) value;
+                       String role = element.toString();
+                       if (inRole && !roles.contains(role)) {
+                               roles.add(role);
+                               formPart.markDirty();
+                       } else if (!inRole && roles.contains(role)) {
+                               roles.remove(role);
+                               formPart.markDirty();
+                       }
+                       viewer.refresh();
+               }
+       }
+
+}
diff --git a/org.argeo.security.ui.admin/src/org/argeo/security/ui/admin/views/RolesView.java b/org.argeo.security.ui.admin/src/org/argeo/security/ui/admin/views/RolesView.java
new file mode 100644 (file)
index 0000000..fbe7dd5
--- /dev/null
@@ -0,0 +1,140 @@
+/*
+ * Copyright (C) 2007-2012 Argeo GmbH
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *         http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.argeo.security.ui.admin.views;
+
+import org.argeo.ArgeoException;
+import org.argeo.security.UserAdminService;
+import org.argeo.security.ui.admin.SecurityAdminPlugin;
+import org.argeo.security.ui.admin.commands.AddRole;
+import org.eclipse.jface.viewers.IStructuredContentProvider;
+import org.eclipse.jface.viewers.ITableLabelProvider;
+import org.eclipse.jface.viewers.LabelProvider;
+import org.eclipse.jface.viewers.TableViewer;
+import org.eclipse.jface.viewers.Viewer;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Event;
+import org.eclipse.swt.widgets.Listener;
+import org.eclipse.swt.widgets.Table;
+import org.eclipse.swt.widgets.Text;
+import org.eclipse.ui.IWorkbench;
+import org.eclipse.ui.handlers.IHandlerService;
+import org.eclipse.ui.part.ViewPart;
+
+/** List all roles. */
+public class RolesView extends ViewPart {
+       public final static String ID = SecurityAdminPlugin.PLUGIN_ID
+                       + ".adminRolesView";
+
+       private Text newRole;
+
+       private TableViewer viewer;
+       private UserAdminService userAdminService;
+
+       private String addNewRoleText = "<add new role here>";
+
+       @Override
+       public void createPartControl(Composite parent) {
+               parent.setLayout(new GridLayout(1, false));
+
+               // new role text field
+               newRole = new Text(parent, SWT.BORDER);
+               newRole.setText(addNewRoleText);
+               newRole.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
+               // default action is add role
+               newRole.addListener(SWT.DefaultSelection, new Listener() {
+                       public void handleEvent(Event evt) {
+                               IWorkbench iw = SecurityAdminPlugin.getDefault().getWorkbench();
+                               IHandlerService handlerService = (IHandlerService) iw
+                                               .getService(IHandlerService.class);
+                               try {
+                                       handlerService.executeCommand(AddRole.COMMAND_ID, evt);
+                               } catch (Exception e) {
+                                       throw new ArgeoException("Cannot execute add role command",
+                                                       e);
+                               }
+                       }
+               });
+               // select all on focus
+               newRole.addListener(SWT.FocusIn, new Listener() {
+                       public void handleEvent(Event e) {
+                               newRole.selectAll();
+                       }
+               });
+
+               // roles table
+               Table table = new Table(parent, SWT.V_SCROLL | SWT.BORDER);
+               table.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
+               table.setLinesVisible(false);
+               table.setHeaderVisible(false);
+               viewer = new TableViewer(table);
+               viewer.setContentProvider(new RolesContentProvider());
+               viewer.setLabelProvider(new UsersLabelProvider());
+               getViewSite().setSelectionProvider(viewer);
+               viewer.setInput(getViewSite());
+       }
+
+       @Override
+       public void setFocus() {
+               viewer.getTable().setFocus();
+       }
+
+       public void setUserAdminService(UserAdminService userAdminService) {
+               this.userAdminService = userAdminService;
+       }
+
+       public String getAddNewRoleText() {
+               return addNewRoleText;
+       }
+
+       private class RolesContentProvider implements IStructuredContentProvider {
+
+               public Object[] getElements(Object inputElement) {
+                       return userAdminService.listEditableRoles().toArray();
+               }
+
+               public void dispose() {
+               }
+
+               public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
+               }
+
+       }
+
+       private class UsersLabelProvider extends LabelProvider implements
+                       ITableLabelProvider {
+               public String getColumnText(Object element, int columnIndex) {
+                       return element.toString();
+               }
+
+               public Image getColumnImage(Object element, int columnIndex) {
+                       return null;
+               }
+
+       }
+
+       public String getNewRole() {
+               return newRole.getText();
+       }
+
+       public void refresh() {
+               viewer.refresh();
+               newRole.setText(addNewRoleText);
+       }
+}
diff --git a/org.argeo.security.ui.admin/src/org/argeo/security/ui/admin/views/UsersView.java b/org.argeo.security.ui.admin/src/org/argeo/security/ui/admin/views/UsersView.java
new file mode 100644 (file)
index 0000000..a743715
--- /dev/null
@@ -0,0 +1,158 @@
+/*
+ * Copyright (C) 2007-2012 Argeo GmbH
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *         http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.argeo.security.ui.admin.views;
+
+import javax.jcr.Node;
+import javax.jcr.Repository;
+import javax.jcr.RepositoryException;
+import javax.jcr.Session;
+import javax.jcr.observation.Event;
+import javax.jcr.observation.EventIterator;
+import javax.jcr.observation.EventListener;
+
+import org.argeo.ArgeoException;
+import org.argeo.eclipse.ui.utils.CommandUtils;
+import org.argeo.jcr.ArgeoJcrConstants;
+import org.argeo.jcr.ArgeoNames;
+import org.argeo.jcr.ArgeoTypes;
+import org.argeo.jcr.JcrUtils;
+import org.argeo.security.ui.admin.SecurityAdminPlugin;
+import org.argeo.security.ui.admin.UserTableComposite;
+import org.argeo.security.ui.admin.commands.OpenArgeoUserEditor;
+import org.eclipse.jface.viewers.DoubleClickEvent;
+import org.eclipse.jface.viewers.IDoubleClickListener;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.layout.FillLayout;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.ui.part.ViewPart;
+
+/** List all users with filter. */
+public class UsersView extends ViewPart implements ArgeoNames {
+       public final static String ID = SecurityAdminPlugin.PLUGIN_ID
+                       + ".adminUsersView";
+
+       /* DEPENDENCY INJECTION */
+       private Session session;
+
+       private UserTableComposite userTableCmp;
+       private JcrUserListener userStructureListener;
+       private JcrUserListener userPropertiesListener;
+
+       @Override
+       public void createPartControl(Composite parent) {
+               parent.setLayout(new FillLayout());
+
+               // Create the composite that displays the list and a filter
+               userTableCmp = new UserTableComposite(parent, SWT.NO_FOCUS, session);
+               userTableCmp.populate(true, false);
+
+               // Configure
+               userTableCmp.getTableViewer().addDoubleClickListener(
+                               new ViewDoubleClickListener());
+               getViewSite().setSelectionProvider(userTableCmp.getTableViewer());
+
+               // Add listener to refresh the list when something changes
+               userStructureListener = new JcrUserListener(getSite().getShell()
+                               .getDisplay());
+               JcrUtils.addListener(session, userStructureListener, Event.NODE_ADDED
+                               | Event.NODE_REMOVED, ArgeoJcrConstants.PEOPLE_BASE_PATH, null);
+               userPropertiesListener = new JcrUserListener(getSite().getShell()
+                               .getDisplay());
+               JcrUtils.addListener(session, userStructureListener,
+                               Event.PROPERTY_CHANGED | Event.PROPERTY_ADDED
+                                               | Event.PROPERTY_REMOVED,
+                               ArgeoJcrConstants.PEOPLE_BASE_PATH,
+                               ArgeoTypes.ARGEO_USER_PROFILE);
+       }
+
+       @Override
+       public void setFocus() {
+               userTableCmp.setFocus();
+       }
+
+       @Override
+       public void dispose() {
+               JcrUtils.removeListenerQuietly(session, userStructureListener);
+               JcrUtils.removeListenerQuietly(session, userPropertiesListener);
+               JcrUtils.logoutQuietly(session);
+               super.dispose();
+       }
+
+       // public void setSession(Session session) {
+       // this.session = session;
+       // }
+
+       public void refresh() {
+               this.getSite().getShell().getDisplay().asyncExec(new Runnable() {
+                       @Override
+                       public void run() {
+                               userTableCmp.refresh();
+                       }
+               });
+       }
+
+       private class JcrUserListener implements EventListener {
+               private final Display display;
+
+               public JcrUserListener(Display display) {
+                       super();
+                       this.display = display;
+               }
+
+               @Override
+               public void onEvent(EventIterator events) {
+                       display.asyncExec(new Runnable() {
+                               @Override
+                               public void run() {
+                                       userTableCmp.refresh();
+                               }
+                       });
+               }
+       }
+
+       class ViewDoubleClickListener implements IDoubleClickListener {
+               public void doubleClick(DoubleClickEvent evt) {
+                       if (evt.getSelection().isEmpty())
+                               return;
+
+                       Object obj = ((IStructuredSelection) evt.getSelection())
+                                       .getFirstElement();
+                       if (obj instanceof Node) {
+                               try {
+                                       String username = ((Node) obj).getProperty(ARGEO_USER_ID)
+                                                       .getString();
+                                       String commandId = OpenArgeoUserEditor.COMMAND_ID;
+                                       String paramName = OpenArgeoUserEditor.PARAM_USERNAME;
+                                       CommandUtils.callCommand(commandId, paramName, username);
+                               } catch (RepositoryException e) {
+                                       throw new ArgeoException("Cannot open user editor", e);
+                               }
+                       }
+               }
+       }
+
+       /* DEPENDENCY INJECTION */
+       public void setRepository(Repository repository) {
+               try {
+                       session = repository.login();
+               } catch (RepositoryException re) {
+                       throw new ArgeoException("Unable to initialise local session", re);
+               }
+       }
+
+}
\ No newline at end of file
diff --git a/org.argeo.security.ui.admin/src/org/argeo/security/ui/admin/wizards/MainUserInfoWizardPage.java b/org.argeo.security.ui.admin/src/org/argeo/security/ui/admin/wizards/MainUserInfoWizardPage.java
new file mode 100644 (file)
index 0000000..ad3662b
--- /dev/null
@@ -0,0 +1,133 @@
+/*
+ * Copyright (C) 2007-2012 Argeo GmbH
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *         http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.argeo.security.ui.admin.wizards;
+
+import javax.jcr.Node;
+import javax.jcr.Property;
+import javax.jcr.RepositoryException;
+
+import org.argeo.ArgeoException;
+import org.argeo.eclipse.ui.EclipseUiUtils;
+import org.argeo.jcr.ArgeoNames;
+import org.argeo.security.UserAdminService;
+import org.eclipse.jface.wizard.WizardPage;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.ModifyEvent;
+import org.eclipse.swt.events.ModifyListener;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Text;
+import org.springframework.security.userdetails.UserDetails;
+import org.springframework.security.userdetails.UsernameNotFoundException;
+
+public class MainUserInfoWizardPage extends WizardPage implements
+               ModifyListener, ArgeoNames {
+       private Text username, firstName, lastName, primaryEmail, password1,
+                       password2;
+       private UserAdminService userAdminService;
+
+       public MainUserInfoWizardPage(UserAdminService userAdminService) {
+               super("Main");
+               this.userAdminService = userAdminService;
+               setTitle("Required Information");
+       }
+
+       @Override
+       public void createControl(Composite parent) {
+               Composite composite = new Composite(parent, SWT.NONE);
+               composite.setLayout(new GridLayout(2, false));
+               username = EclipseUiUtils.createGridLT(composite, "Username", this);
+               primaryEmail = EclipseUiUtils.createGridLT(composite, "Email", this);
+               firstName = EclipseUiUtils.createGridLT(composite, "First name", this);
+               lastName = EclipseUiUtils.createGridLT(composite, "Last name", this);
+               password1 = EclipseUiUtils.createGridLP(composite, "Password", this);
+               password2 = EclipseUiUtils.createGridLP(composite, "Repeat password",
+                               this);
+               setControl(composite);
+               
+               // Initialize buttons
+               setPageComplete(false);
+               getContainer().updateButtons();
+       }
+
+       @Override
+       public void modifyText(ModifyEvent event) {
+               String message = checkComplete();
+               if (message != null) {
+                       setMessage(message, WizardPage.ERROR);
+                       setPageComplete(false);
+               } else {
+                       setMessage("Complete", WizardPage.INFORMATION);
+                       setPageComplete(true);
+               }
+               getContainer().updateButtons();
+       }
+
+       /** @return error message or null if complete */
+       protected String checkComplete() {
+               // if (!username.getText().matches(UserAdminService.USERNAME_PATTERN))
+               // return
+               // "Wrong user name format, should be lower case, between 3 and 64 characters with only '_' an '@' as acceptable special character.";
+               
+               if (username.getText().trim().equals(""))
+                       return "User name must not be empty";
+               
+               try {
+                       UserDetails userDetails = userAdminService
+                                       .loadUserByUsername(username.getText());
+                       return "User " + userDetails.getUsername() + " already exists";
+               } catch (UsernameNotFoundException e) {
+                       // silent
+               }
+               if (!primaryEmail.getText().matches(UserAdminService.EMAIL_PATTERN))
+                       return "Not a valid email address";
+               if (firstName.getText().trim().equals(""))
+                       return "Specify a first name";
+               if (lastName.getText().trim().equals(""))
+                       return "Specify a last name";
+               if (password1.getText().trim().equals(""))
+                       return "Specify a password";
+               if (password2.getText().trim().equals(""))
+                       return "Repeat the password";
+               if (!password2.getText().equals(password1.getText()))
+                       return "Passwords are different";
+               return null;
+       }
+
+       public String getUsername() {
+               return username.getText();
+       }
+
+       public String getPassword() {
+               return password1.getText();
+       }
+
+       public void mapToProfileNode(Node up) {
+               try {
+                       up.setProperty(ARGEO_PRIMARY_EMAIL, primaryEmail.getText());
+                       up.setProperty(ARGEO_FIRST_NAME, firstName.getText());
+                       up.setProperty(ARGEO_LAST_NAME, lastName.getText());
+
+                       // derived values
+                       // TODO add wizard pages to do it
+                       up.setProperty(Property.JCR_TITLE, firstName.getText() + " "
+                                       + lastName.getText());
+                       up.setProperty(Property.JCR_DESCRIPTION, "");
+               } catch (RepositoryException e) {
+                       throw new ArgeoException("Cannot map to " + up, e);
+               }
+       }
+}
diff --git a/org.argeo.security.ui.admin/src/org/argeo/security/ui/admin/wizards/NewUserWizard.java b/org.argeo.security.ui.admin/src/org/argeo/security/ui/admin/wizards/NewUserWizard.java
new file mode 100644 (file)
index 0000000..c2d041f
--- /dev/null
@@ -0,0 +1,100 @@
+/*
+ * Copyright (C) 2007-2012 Argeo GmbH
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *         http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.argeo.security.ui.admin.wizards;
+
+import javax.jcr.Node;
+import javax.jcr.RepositoryException;
+import javax.jcr.Session;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.argeo.eclipse.ui.ErrorFeedback;
+import org.argeo.jcr.JcrUtils;
+import org.argeo.jcr.UserJcrUtils;
+import org.argeo.security.UserAdminService;
+import org.argeo.security.jcr.JcrSecurityModel;
+import org.argeo.security.jcr.JcrUserDetails;
+import org.eclipse.jface.wizard.Wizard;
+import org.springframework.security.GrantedAuthority;
+
+/** Wizard to create a new user */
+public class NewUserWizard extends Wizard {
+       private final static Log log = LogFactory.getLog(NewUserWizard.class);
+       private Session session;
+       private UserAdminService userAdminService;
+       private JcrSecurityModel jcrSecurityModel;
+
+       // pages
+       private MainUserInfoWizardPage mainUserInfo;
+
+       public NewUserWizard(Session session, UserAdminService userAdminService,
+                       JcrSecurityModel jcrSecurityModel) {
+               this.session = session;
+               this.userAdminService = userAdminService;
+               this.jcrSecurityModel = jcrSecurityModel;
+       }
+
+       @Override
+       public void addPages() {
+               mainUserInfo = new MainUserInfoWizardPage(userAdminService);
+               addPage(mainUserInfo);
+       }
+
+       @Override
+       public boolean performFinish() {
+               if (!canFinish())
+                       return false;
+
+               String username = mainUserInfo.getUsername();
+               try {
+                       // Node userProfile = SecurityJcrUtils.createUserProfile(session,
+                       // username);
+                       Node userProfile = jcrSecurityModel.sync(session, username, null);
+                       session.getWorkspace().getVersionManager()
+                                       .checkout(userProfile.getPath());
+                       mainUserInfo.mapToProfileNode(userProfile);
+                       String password = mainUserInfo.getPassword();
+                       // TODO add roles
+                       JcrUserDetails jcrUserDetails = new JcrUserDetails(userProfile,
+                                       password, new GrantedAuthority[0]);
+                       session.save();
+                       session.getWorkspace().getVersionManager()
+                                       .checkin(userProfile.getPath());
+                       userAdminService.createUser(jcrUserDetails);
+                       return true;
+               } catch (Exception e) {
+                       JcrUtils.discardQuietly(session);
+                       Node userHome = UserJcrUtils.getUserHome(session, username);
+                       if (userHome != null) {
+                               try {
+                                       userHome.remove();
+                                       session.save();
+                               } catch (RepositoryException e1) {
+                                       JcrUtils.discardQuietly(session);
+                                       log.warn("Error when trying to clean up failed new user "
+                                                       + username, e1);
+                               }
+                       }
+                       ErrorFeedback.show("Cannot create new user " + username, e);
+                       return false;
+               }
+       }
+
+       public void setSession(Session session) {
+               this.session = session;
+       }
+
+}
diff --git a/org.argeo.security.ui.admin/src/org/argeo/security/ui/admin/wizards/UserBatchUpdateWizard.java b/org.argeo.security.ui.admin/src/org/argeo/security/ui/admin/wizards/UserBatchUpdateWizard.java
new file mode 100644 (file)
index 0000000..71e4a1b
--- /dev/null
@@ -0,0 +1,607 @@
+/*
+ * Copyright (C) 2007-2012 Argeo GmbH
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *         http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.argeo.security.ui.admin.wizards;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import javax.jcr.Node;
+import javax.jcr.NodeIterator;
+import javax.jcr.RepositoryException;
+import javax.jcr.Session;
+import javax.jcr.version.VersionManager;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.argeo.ArgeoException;
+import org.argeo.ArgeoMonitor;
+import org.argeo.eclipse.ui.EclipseArgeoMonitor;
+import org.argeo.jcr.ArgeoNames;
+import org.argeo.jcr.JcrUtils;
+import org.argeo.security.UserAdminService;
+import org.argeo.security.jcr.JcrSecurityModel;
+import org.argeo.security.jcr.JcrUserDetails;
+import org.argeo.security.ui.PrivilegedJob;
+import org.argeo.security.ui.admin.SecurityAdminPlugin;
+import org.argeo.security.ui.admin.UserTableComposite;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.jface.dialogs.IPageChangeProvider;
+import org.eclipse.jface.dialogs.IPageChangedListener;
+import org.eclipse.jface.dialogs.PageChangedEvent;
+import org.eclipse.jface.wizard.IWizardContainer;
+import org.eclipse.jface.wizard.Wizard;
+import org.eclipse.jface.wizard.WizardPage;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.events.SelectionListener;
+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.Combo;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Text;
+
+/** Wizard to update users */
+public class UserBatchUpdateWizard extends Wizard {
+       private final static Log log = LogFactory
+                       .getLog(UserBatchUpdateWizard.class);
+       private Session session;
+       private UserAdminService userAdminService;
+
+       // pages
+       private ChooseCommandWizardPage chooseCommandPage;
+       private ChooseUsersWizardPage userListPage;
+       private ValidateAndLaunchWizardPage validatePage;
+
+       // /////////////////////////////////////////////////
+       // / Definition of the various implemented commands
+       private final static String CMD_UPDATE_PASSWORD = "resetPassword";
+       private final static String CMD_GROUP_MEMBERSHIP = "groupMembership";
+
+       private final Map<String, String> commands = new HashMap<String, String>() {
+               private static final long serialVersionUID = 1L;
+               {
+                       put("Enable user(s)", ArgeoNames.ARGEO_ENABLED);
+                       put("Expire credentials", ArgeoNames.ARGEO_CREDENTIALS_NON_EXPIRED);
+                       put("Expire account(s)", ArgeoNames.ARGEO_ACCOUNT_NON_EXPIRED);
+                       put("Lock account(s)", ArgeoNames.ARGEO_ACCOUNT_NON_LOCKED);
+                       put("Reset password(s)", CMD_UPDATE_PASSWORD);
+                       // TODO implement role / group management
+                       // put("Add/Remove from group", CMD_GROUP_MEMBERSHIP);
+               }
+       };
+
+       public UserBatchUpdateWizard(Session session,
+                       UserAdminService userAdminService, JcrSecurityModel jcrSecurityModel) {
+               this.session = session;
+               this.userAdminService = userAdminService;
+               // this.jcrSecurityModel = jcrSecurityModel;
+       }
+
+       @Override
+       public void addPages() {
+               chooseCommandPage = new ChooseCommandWizardPage();
+               addPage(chooseCommandPage);
+               userListPage = new ChooseUsersWizardPage(session);
+               addPage(userListPage);
+               validatePage = new ValidateAndLaunchWizardPage(session);
+               addPage(validatePage);
+       }
+
+       @Override
+       public boolean performFinish() {
+               if (!canFinish())
+                       return false;
+
+               UpdateJob job = null;
+               if (ArgeoNames.ARGEO_ENABLED.equals(chooseCommandPage.getCommand())) {
+                       job = new UpdateBoolean(session, userListPage.getSelectedUsers(),
+                                       ArgeoNames.ARGEO_ENABLED,
+                                       chooseCommandPage.getBoleanValue());
+               } else if (ArgeoNames.ARGEO_CREDENTIALS_NON_EXPIRED
+                               .equals(chooseCommandPage.getCommand())) {
+                       job = new UpdateBoolean(session, userListPage.getSelectedUsers(),
+                                       ArgeoNames.ARGEO_CREDENTIALS_NON_EXPIRED,
+                                       chooseCommandPage.getBoleanValue());
+               } else if (ArgeoNames.ARGEO_ACCOUNT_NON_EXPIRED
+                               .equals(chooseCommandPage.getCommand())) {
+                       job = new UpdateBoolean(session, userListPage.getSelectedUsers(),
+                                       ArgeoNames.ARGEO_ACCOUNT_NON_EXPIRED,
+                                       chooseCommandPage.getBoleanValue());
+               } else if (ArgeoNames.ARGEO_ACCOUNT_NON_LOCKED.equals(chooseCommandPage
+                               .getCommand())) {
+                       job = new UpdateBoolean(session, userListPage.getSelectedUsers(),
+                                       ArgeoNames.ARGEO_ACCOUNT_NON_LOCKED,
+                                       chooseCommandPage.getBoleanValue());
+               } else if (CMD_UPDATE_PASSWORD.equals(chooseCommandPage.getCommand())) {
+                       String newValue = chooseCommandPage.getPwdValue();
+                       if (newValue == null)
+                               throw new ArgeoException(
+                                               "Password cannot be null or an empty string");
+                       job = new ResetPassword(session, userAdminService,
+                                       userListPage.getSelectedUsers(), newValue);
+               }
+
+               if (job != null)
+                       job.schedule();
+               return true;
+       }
+
+       public void setSession(Session session) {
+               this.session = session;
+       }
+
+       public boolean canFinish() {
+               if (this.getContainer().getCurrentPage() == validatePage)
+                       return true;
+               return false;
+       }
+
+       // /////////////////////////
+       // REEL UPDATE JOB
+       private class UpdateBoolean extends UpdateJob {
+               private String propertyName;
+               private boolean value;
+
+               public UpdateBoolean(Session session, List<Node> nodesToUpdate,
+                               String propertyName, boolean value) {
+                       super(session, nodesToUpdate);
+                       this.propertyName = propertyName;
+                       this.value = value;
+               }
+
+               protected void doUpdate(Node node) {
+                       try {
+                               node.setProperty(propertyName, value);
+                       } catch (RepositoryException re) {
+                               throw new ArgeoException(
+                                               "Unable to update boolean value for node " + node, re);
+                       }
+               }
+       }
+
+       private class ResetPassword extends UpdateJob {
+               private String newValue;
+               private UserAdminService userAdminService;
+
+               public ResetPassword(Session session,
+                               UserAdminService userAdminService, List<Node> nodesToUpdate,
+                               String newValue) {
+                       super(session, nodesToUpdate);
+                       this.newValue = newValue;
+                       this.userAdminService = userAdminService;
+               }
+
+               protected void doUpdate(Node node) {
+                       try {
+                               String userId = node.getProperty(ArgeoNames.ARGEO_USER_ID)
+                                               .getString();
+                               if (userAdminService.userExists(userId)) {
+                                       JcrUserDetails userDetails = (JcrUserDetails) userAdminService
+                                                       .loadUserByUsername(userId);
+                                       userAdminService.updateUser(userDetails
+                                                       .cloneWithNewPassword(newValue));
+                               }
+                       } catch (RepositoryException re) {
+                               throw new ArgeoException(
+                                               "Unable to update boolean value for node " + node, re);
+                       }
+               }
+       }
+
+       @SuppressWarnings("unused")
+       private class AddToGroup extends UpdateJob {
+               private String groupID;
+               private Session session;
+
+               public AddToGroup(Session session, List<Node> nodesToUpdate,
+                               String groupID) {
+                       super(session, nodesToUpdate);
+                       this.session = session;
+                       this.groupID = groupID;
+               }
+
+               protected void doUpdate(Node node) {
+                       log.info("Add/Remove to group actions are not yet implemented");
+                       // TODO implement this
+                       // try {
+                       // throw new ArgeoException("Not yet implemented");
+                       // } catch (RepositoryException re) {
+                       // throw new ArgeoException(
+                       // "Unable to update boolean value for node " + node, re);
+                       // }
+               }
+       }
+
+       /**
+        * Base privileged job that will be run asynchronously to perform the batch
+        * update
+        */
+       private abstract class UpdateJob extends PrivilegedJob {
+
+               private final Session currSession;
+               private final List<Node> nodesToUpdate;
+
+               protected abstract void doUpdate(Node node);
+
+               public UpdateJob(Session session, List<Node> nodesToUpdate) {
+                       super("Perform update");
+                       try {
+                               this.currSession = session.getRepository().login();
+                               // "move" nodes to update in the new session
+                               // the "old" session will be closed by the calling command
+                               // before the job has effectively ran
+                               // TODO there must be a cleaner way to do.
+                               List<Node> nodes = new ArrayList<Node>();
+                               for (Node node : nodesToUpdate) {
+                                       nodes.add(currSession.getNode(node.getPath()));
+                               }
+                               this.nodesToUpdate = nodes;
+                       } catch (RepositoryException e) {
+                               throw new ArgeoException("Error while dupplicating "
+                                               + "session for job", e);
+                       }
+               }
+
+               @Override
+               protected IStatus doRun(IProgressMonitor progressMonitor) {
+                       try {
+                               ArgeoMonitor monitor = new EclipseArgeoMonitor(progressMonitor);
+                               VersionManager vm = currSession.getWorkspace()
+                                               .getVersionManager();
+                               int total = nodesToUpdate.size();
+                               monitor.beginTask("Performing change", total);
+                               for (Node node : nodesToUpdate) {
+                                       String path = node.getPath();
+                                       vm.checkout(path);
+                                       doUpdate(node);
+                                       currSession.save();
+                                       vm.checkin(path);
+                                       monitor.worked(1);
+                               }
+                       } catch (Exception e) {
+                               log.error("Cannot perform batch update on users", e);
+                               // e.printStackTrace();
+
+                               // Dig exception to find the root cause that will enable the
+                               // user to understand the problem
+                               Throwable cause = e;
+                               Throwable originalCause = e;
+                               while (cause != null) {
+                                       if (log.isTraceEnabled())
+                                               log.trace("Parent Cause message : "
+                                                               + cause.getMessage());
+                                       originalCause = cause;
+                                       cause = cause.getCause();
+                               }
+                               return new Status(IStatus.ERROR, SecurityAdminPlugin.PLUGIN_ID,
+                                               "Cannot perform updates.", originalCause);
+                       } finally {
+                               JcrUtils.logoutQuietly(currSession);
+                       }
+                       return Status.OK_STATUS;
+               }
+       }
+
+       // //////////////////////
+       // Pages definition
+       /** Displays a combo box that enables user to choose which action to perform */
+       private class ChooseCommandWizardPage extends WizardPage {
+               private static final long serialVersionUID = 1L;
+
+               private Combo chooseCommandCmb;
+               private Button trueChk;
+               private Text valueTxt;
+               private Text pwdTxt;
+               private Text pwd2Txt;
+
+               public ChooseCommandWizardPage() {
+                       super("Choose a command to run.");
+                       setTitle("Choose a command to run.");
+               }
+
+               @Override
+               public void createControl(Composite parent) {
+                       GridLayout gl = new GridLayout();
+                       Composite container = new Composite(parent, SWT.NO_FOCUS);
+                       container.setLayout(gl);
+
+                       chooseCommandCmb = new Combo(container, SWT.NO_FOCUS);
+                       String[] values = commands.keySet().toArray(
+                                       new String[commands.size()]);
+                       chooseCommandCmb.setItems(values);
+                       chooseCommandCmb.setLayoutData(new GridData(SWT.FILL, SWT.TOP,
+                                       true, false));
+
+                       final Composite bottomPart = new Composite(container, SWT.NO_FOCUS);
+                       gl = new GridLayout();
+                       gl.horizontalSpacing = gl.marginWidth = gl.verticalSpacing = 0;
+                       bottomPart.setLayout(gl);
+                       bottomPart.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true,
+                                       true));
+
+                       chooseCommandCmb.addSelectionListener(new SelectionListener() {
+                               private static final long serialVersionUID = 1L;
+
+                               @Override
+                               public void widgetSelected(SelectionEvent e) {
+                                       if (getCommand().equals(CMD_UPDATE_PASSWORD))
+                                               populatePasswordCmp(bottomPart);
+                                       else if (getCommand().equals(CMD_GROUP_MEMBERSHIP))
+                                               populateGroupCmp(bottomPart);
+                                       else
+                                               populateBooleanFlagCmp(bottomPart);
+                                       bottomPart.pack(true);
+                                       bottomPart.layout();
+                               }
+
+                               @Override
+                               public void widgetDefaultSelected(SelectionEvent e) {
+                               }
+                       });
+
+                       setControl(container);
+               }
+
+               private void cleanParent(Composite parent) {
+                       if (parent.getChildren().length > 0) {
+                               for (Control control : parent.getChildren())
+                                       control.dispose();
+                       }
+               }
+
+               private void populateBooleanFlagCmp(Composite parent) {
+                       cleanParent(parent);
+                       trueChk = new Button(parent, SWT.CHECK);
+                       trueChk.setText("Do it. (It will to the contrary if unchecked)");
+                       trueChk.setSelection(true);
+                       trueChk.setLayoutData(new GridData(SWT.LEFT, SWT.TOP, false, false));
+               }
+
+               private void populatePasswordCmp(Composite parent) {
+                       cleanParent(parent);
+                       Composite body = new Composite(parent, SWT.NO_FOCUS);
+                       body.setLayout(new GridLayout(2, false));
+                       body.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
+                       pwdTxt = createLP(body, "New password", "");
+                       pwd2Txt = createLP(body, "Repeat password", "");
+               }
+
+               /** Creates label and password. */
+               protected Text createLP(Composite body, String label, String value) {
+                       Label lbl = new Label(body, SWT.NONE);
+                       lbl.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false));
+                       lbl.setText(label);
+                       Text text = new Text(body, SWT.BORDER | SWT.PASSWORD);
+                       text.setText(value);
+                       text.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));
+                       return text;
+               }
+
+               private void populateGroupCmp(Composite parent) {
+                       if (parent.getChildren().length > 0) {
+                               for (Control control : parent.getChildren())
+                                       control.dispose();
+                       }
+                       trueChk = new Button(parent, SWT.CHECK);
+                       trueChk.setText("Add to group. (It will remove user(s) from the "
+                                       + "corresponding group if unchecked)");
+                       trueChk.setSelection(true);
+                       trueChk.setLayoutData(new GridData(SWT.LEFT, SWT.TOP, false, false));
+               }
+
+               protected String getCommand() {
+                       return commands.get(chooseCommandCmb.getItem(chooseCommandCmb
+                                       .getSelectionIndex()));
+               }
+
+               protected String getCommandLbl() {
+                       return chooseCommandCmb.getItem(chooseCommandCmb
+                                       .getSelectionIndex());
+               }
+
+               protected boolean getBoleanValue() {
+                       // FIXME this is not consistent and will lead to errors.
+                       if (ArgeoNames.ARGEO_ENABLED.equals(getCommand()))
+                               return trueChk.getSelection();
+                       else
+                               return !trueChk.getSelection();
+               }
+
+               @SuppressWarnings("unused")
+               protected String getStringValue() {
+                       String value = null;
+                       if (valueTxt != null) {
+                               value = valueTxt.getText();
+                               if ("".equals(value.trim()))
+                                       value = null;
+                       }
+                       return value;
+               }
+
+               protected String getPwdValue() {
+                       String newPwd = null;
+                       if (pwdTxt == null || pwd2Txt == null)
+                               return null;
+                       if (!pwdTxt.getText().equals("") || !pwd2Txt.getText().equals("")) {
+                               if (pwdTxt.getText().equals(pwd2Txt.getText())) {
+                                       newPwd = pwdTxt.getText();
+                                       pwdTxt.setText("");
+                                       pwd2Txt.setText("");
+                               } else {
+                                       pwdTxt.setText("");
+                                       pwd2Txt.setText("");
+                                       throw new ArgeoException("Passwords are not equals");
+                               }
+                       }
+                       return newPwd;
+               }
+       }
+
+       /**
+        * Displays a list of users with a check box to be able to choose some of
+        * them
+        */
+       private class ChooseUsersWizardPage extends WizardPage implements
+                       IPageChangedListener {
+               private static final long serialVersionUID = 1L;
+               private UserTableComposite userTableCmp;
+               private Composite container;
+               private Session session;
+
+               public ChooseUsersWizardPage(Session session) {
+                       super("Choose Users");
+                       this.session = session;
+                       setTitle("Select users who will be impacted");
+               }
+
+               @Override
+               public void createControl(Composite parent) {
+                       container = new Composite(parent, SWT.NONE);
+                       container.setLayout(new FillLayout());
+                       userTableCmp = new MyUserTableCmp(container, SWT.NO_FOCUS, session);
+                       userTableCmp.populate(true, true);
+                       setControl(container);
+
+                       // Add listener to update message when shown
+                       final IWizardContainer container = this.getContainer();
+                       if (container instanceof IPageChangeProvider) {
+                               ((IPageChangeProvider) container).addPageChangedListener(this);
+                       }
+
+               }
+
+               @Override
+               public void pageChanged(PageChangedEvent event) {
+                       if (event.getSelectedPage() == this) {
+                               String msg = "Chosen batch action: "
+                                               + chooseCommandPage.getCommandLbl();
+                               ((WizardPage) event.getSelectedPage()).setMessage(msg);
+                       }
+               }
+
+               protected List<Node> getSelectedUsers() {
+                       return userTableCmp.getSelectedUsers();
+               }
+
+               private class MyUserTableCmp extends UserTableComposite {
+
+                       private static final long serialVersionUID = 1L;
+
+                       public MyUserTableCmp(Composite parent, int style, Session session) {
+                               super(parent, style, session);
+                       }
+
+                       @Override
+                       protected void refreshFilteredList() {
+                               List<Node> nodes = new ArrayList<Node>();
+                               try {
+                                       NodeIterator ni = listFilteredElements(session,
+                                                       getFilterString());
+
+                                       users: while (ni.hasNext()) {
+                                               Node currNode = ni.nextNode();
+                                               String username = currNode.hasProperty(ARGEO_USER_ID) ? currNode
+                                                               .getProperty(ARGEO_USER_ID).getString() : "";
+                                               if (username.equals(session.getUserID()))
+                                                       continue users;
+                                               else
+                                                       nodes.add(currNode);
+                                       }
+                                       getTableViewer().setInput(nodes.toArray());
+                               } catch (RepositoryException e) {
+                                       throw new ArgeoException("Unable to list users", e);
+                               }
+                       }
+               }
+       }
+
+       /**
+        * Recapitulation of input data before running real update
+        */
+       private class ValidateAndLaunchWizardPage extends WizardPage implements
+                       IPageChangedListener {
+               private static final long serialVersionUID = 1L;
+               private UserTableComposite userTableCmp;
+               private Session session;
+
+               public ValidateAndLaunchWizardPage(Session session) {
+                       super("Validate and launch");
+                       this.session = session;
+                       setTitle("Validate and launch");
+               }
+
+               @Override
+               public void createControl(Composite parent) {
+                       Composite mainCmp = new Composite(parent, SWT.NO_FOCUS);
+                       mainCmp.setLayout(new FillLayout());
+
+                       // Add listener to update user list when shown
+                       final IWizardContainer container = this.getContainer();
+                       if (container instanceof IPageChangeProvider) {
+                               ((IPageChangeProvider) container).addPageChangedListener(this);
+                       }
+
+                       userTableCmp = new UserTableComposite(mainCmp, SWT.NO_FOCUS,
+                                       session);
+                       userTableCmp.populate(false, false);
+                       setControl(mainCmp);
+               }
+
+               @Override
+               public void pageChanged(PageChangedEvent event) {
+                       if (event.getSelectedPage() == this) {
+                               @SuppressWarnings({ "unchecked", "rawtypes" })
+                               Object[] values = ((ArrayList) userListPage.getSelectedUsers())
+                                               .toArray(new Object[userListPage.getSelectedUsers()
+                                                               .size()]);
+                               userTableCmp.getTableViewer().setInput(values);
+                               String msg = "Following batch action: ["
+                                               + chooseCommandPage.getCommandLbl()
+                                               + "] will be perfomed on the users listed below.\n"
+                                               + "Are you sure you want to proceed?";
+                               ((WizardPage) event.getSelectedPage()).setMessage(msg);
+                       }
+               }
+
+               // private class MyUserTableCmp extends UserTableComposite {
+               // public MyUserTableCmp(Composite parent, int style, Session session) {
+               // super(parent, style, session);
+               // }
+               //
+               // @Override
+               // protected void refreshFilteredList() {
+               // @SuppressWarnings({ "unchecked", "rawtypes" })
+               //
+               // setFilteredList(values);
+               // }
+               //
+               // @Override
+               // public void setVisible(boolean visible) {
+               // super.setVisible(visible);
+               // if (visible)
+               // refreshFilteredList();
+               // }
+               // }
+       }
+}
\ No newline at end of file
index 5641c7ca39f6826ec4ff5af926bfd34f528f3684..d2953a684d400476bf716ed6a6c3c3ae486fcd0e 100644 (file)
@@ -1,7 +1,9 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <classpath>
-       <classpathentry kind="src" path="src/main/java"/>
-       <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6"/>>>
-       <classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
-       <classpathentry kind="output" path="target/classes"/>
+       <classpathentry kind="src" path="src" />
+       <classpathentry kind="con"
+               path="org.eclipse.pde.core.requiredPlugins" />
+       <classpathentry kind="con"
+               path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6" />
+       <classpathentry kind="output" path="bin" />
 </classpath>
index 5618fae36d54dc2947d5f94aad2c5030a989ade1..30f715358d984db427238bb1984c0d19b6ca4004 100644 (file)
@@ -1,6 +1 @@
-bin.includes = plugin.xml,\
-               META-INF/,\
-               branding/,\
-               icons/
-source.. = src/main/java/
-output.. = target/classes/
+source.. = src/
diff --git a/org.argeo.security.ui.rap/src/main/java/org/argeo/security/ui/rap/AnonymousEntryPoint.java b/org.argeo.security.ui.rap/src/main/java/org/argeo/security/ui/rap/AnonymousEntryPoint.java
deleted file mode 100644 (file)
index 16d2489..0000000
+++ /dev/null
@@ -1,118 +0,0 @@
-/*
- * Copyright (C) 2007-2012 Argeo GmbH
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *         http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.argeo.security.ui.rap;
-
-import java.security.PrivilegedAction;
-
-import javax.security.auth.Subject;
-import javax.security.auth.login.LoginException;
-
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.argeo.ArgeoException;
-import org.eclipse.equinox.security.auth.ILoginContext;
-import org.eclipse.rap.rwt.RWT;
-import org.eclipse.rap.rwt.application.IEntryPoint;
-import org.eclipse.swt.widgets.Display;
-import org.eclipse.ui.PlatformUI;
-
-/**
- * RAP entry point which authenticates the subject as anonymous, for public
- * unauthenticated access.
- */
-public class AnonymousEntryPoint implements IEntryPoint {
-       private final static Log log = LogFactory.getLog(AnonymousEntryPoint.class);
-
-       /**
-        * How many seconds to wait before invalidating the session if the user has
-        * not yet logged in.
-        */
-       private Integer loginTimeout = 1 * 60;
-       private Integer sessionTimeout = 15 * 60;
-
-       @Override
-       public int createUI() {
-               // Short login timeout so that the modal dialog login doesn't hang
-               // around too long
-               RWT.getRequest().getSession().setMaxInactiveInterval(loginTimeout);
-
-               if (log.isDebugEnabled())
-                       log.debug("Anonymous THREAD=" + Thread.currentThread().getId()
-                                       + ", sessionStore=" + RWT.getSessionStore().getId());
-
-               // create display
-               final Display display = PlatformUI.createDisplay();
-
-               // log in
-               final ILoginContext loginContext = SecureRapActivator
-                               .createLoginContext(SecureRapActivator.CONTEXT_SPRING_ANONYMOUS);
-               Subject subject = null;
-               try {
-                       loginContext.login();
-                       subject = loginContext.getSubject();
-               } catch (LoginException e) {
-                       throw new ArgeoException(
-                                       "Unexpected exception during authentication", e);
-               }
-
-               // identify after successful login
-               if (log.isDebugEnabled())
-                       log.debug("Authenticated " + subject);
-               final String username = subject.getPrincipals().iterator().next()
-                               .getName();
-
-               // Once the user is logged in, she can have a longer session timeout
-               RWT.getRequest().getSession().setMaxInactiveInterval(sessionTimeout);
-
-               // Logout callback when the display is disposed
-               display.disposeExec(new Runnable() {
-                       public void run() {
-                               log.debug("Display disposed");
-                               logout(loginContext, username);
-                       }
-               });
-
-               //
-               // RUN THE WORKBENCH
-               //
-               Integer returnCode = null;
-               try {
-                       returnCode = Subject.doAs(subject, new PrivilegedAction<Integer>() {
-                               public Integer run() {
-                                       RapWorkbenchAdvisor workbenchAdvisor = new RapWorkbenchAdvisor(
-                                                       null);
-                                       int result = PlatformUI.createAndRunWorkbench(display,
-                                                       workbenchAdvisor);
-                                       return new Integer(result);
-                               }
-                       });
-                       logout(loginContext, username);
-               } finally {
-                       display.dispose();
-               }
-               return returnCode;
-       }
-
-       private void logout(ILoginContext secureContext, String username) {
-               try {
-                       secureContext.logout();
-                       log.info("Logged out " + (username != null ? username : "")
-                                       + " (THREAD=" + Thread.currentThread().getId() + ")");
-               } catch (LoginException e) {
-                       log.error("Erorr when logging out", e);
-               }
-       }
-}
diff --git a/org.argeo.security.ui.rap/src/main/java/org/argeo/security/ui/rap/LogoutEntryPoint.java b/org.argeo.security.ui.rap/src/main/java/org/argeo/security/ui/rap/LogoutEntryPoint.java
deleted file mode 100644 (file)
index 7337549..0000000
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * Copyright (C) 2007-2012 Argeo GmbH
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *         http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.argeo.security.ui.rap;
-
-import javax.security.auth.login.LoginException;
-
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.eclipse.equinox.security.auth.ILoginContext;
-import org.eclipse.rap.rwt.RWT;
-import org.eclipse.rap.rwt.application.IEntryPoint;
-import org.eclipse.ui.PlatformUI;
-import org.springframework.security.context.SecurityContextHolder;
-
-/**
- * RAP entry point which logs out the currently authenticated user
- */
-public class LogoutEntryPoint implements IEntryPoint {
-       private final static Log log = LogFactory.getLog(LogoutEntryPoint.class);
-
-       /**
-        * From org.springframework.security.context.
-        * HttpSessionContextIntegrationFilter
-        */
-       protected static final String SPRING_SECURITY_CONTEXT_KEY = "SPRING_SECURITY_CONTEXT";
-
-       @Override
-       public int createUI() {
-               // create display
-               PlatformUI.createDisplay();
-
-               final ILoginContext loginContext = SecureRapActivator
-                               .createLoginContext(SecureRapActivator.CONTEXT_SPRING);
-               try {
-                       loginContext.logout();
-               } catch (LoginException e) {
-                       e.printStackTrace();
-               }
-
-               RWT.getRequest().getSession()
-                               .removeAttribute(SPRING_SECURITY_CONTEXT_KEY);
-               SecurityContextHolder.clearContext();
-               RWT.getRequest().getSession().setMaxInactiveInterval(1);
-
-               if (log.isDebugEnabled())
-                       log.debug("Logged out session " + RWT.getSessionStore().getId());
-               return 0;
-       }
-}
diff --git a/org.argeo.security.ui.rap/src/main/java/org/argeo/security/ui/rap/NullEntryPoint.java b/org.argeo.security.ui.rap/src/main/java/org/argeo/security/ui/rap/NullEntryPoint.java
deleted file mode 100644 (file)
index 811cc28..0000000
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Copyright (C) 2007-2012 Argeo GmbH
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *         http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.argeo.security.ui.rap;
-
-import org.eclipse.rap.rwt.application.IEntryPoint;
-import org.eclipse.ui.PlatformUI;
-
-/**
- * RAP entry point which does doesing except creating the display
- */
-public class NullEntryPoint implements IEntryPoint {
-       @Override
-       public int createUI() {
-               // create display
-               PlatformUI.createDisplay();
-               return 0;
-       }
-}
diff --git a/org.argeo.security.ui.rap/src/main/java/org/argeo/security/ui/rap/RapActionBarAdvisor.java b/org.argeo.security.ui.rap/src/main/java/org/argeo/security/ui/rap/RapActionBarAdvisor.java
deleted file mode 100644 (file)
index 074b798..0000000
+++ /dev/null
@@ -1,227 +0,0 @@
-/*
- * Copyright (C) 2007-2012 Argeo GmbH
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *         http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.argeo.security.ui.rap;
-
-import org.argeo.security.ui.commands.OpenHomePerspective;
-import org.eclipse.core.commands.Category;
-import org.eclipse.core.commands.Command;
-import org.eclipse.jface.action.ICoolBarManager;
-import org.eclipse.jface.action.IMenuManager;
-import org.eclipse.jface.action.IToolBarManager;
-import org.eclipse.jface.action.ToolBarManager;
-import org.eclipse.swt.SWT;
-import org.eclipse.ui.IWorkbenchWindow;
-import org.eclipse.ui.actions.ActionFactory;
-import org.eclipse.ui.actions.ActionFactory.IWorkbenchAction;
-import org.eclipse.ui.application.ActionBarAdvisor;
-import org.eclipse.ui.application.IActionBarConfigurer;
-import org.eclipse.ui.commands.ICommandService;
-
-/** Eclipse rap specific action bar advisor */
-public class RapActionBarAdvisor extends ActionBarAdvisor {
-       private final static String ID_BASE = "org.argeo.security.ui.rap";
-       // private final static Log log = LogFactory
-       // .getLog(SecureActionBarAdvisor.class);
-
-       /** Null means anonymous */
-       private String username = null;
-
-       // private IAction logoutAction;
-       // private IWorkbenchAction openPerspectiveDialogAction;
-       // private IWorkbenchAction showViewMenuAction;
-       // private IWorkbenchAction preferences;
-       private IWorkbenchAction saveAction;
-       private IWorkbenchAction saveAllAction;
-
-       // private IWorkbenchAction closeAllAction;
-
-       public RapActionBarAdvisor(IActionBarConfigurer configurer, String username) {
-               super(configurer);
-               this.username = username;
-       }
-
-       protected void makeActions(IWorkbenchWindow window) {
-               // preferences = ActionFactory.PREFERENCES.create(window);
-               // register(preferences);
-               // openPerspectiveDialogAction = ActionFactory.OPEN_PERSPECTIVE_DIALOG
-               // .create(window);
-               // register(openPerspectiveDialogAction);
-               // showViewMenuAction = ActionFactory.SHOW_VIEW_MENU.create(window);
-               // register(showViewMenuAction);
-               //
-               // // logout
-               // logoutAction = ActionFactory.QUIT.create(window);
-               // // logoutAction = createLogoutAction();
-               // register(logoutAction);
-               //
-               // Save semantics
-               saveAction = ActionFactory.SAVE.create(window);
-               register(saveAction);
-               saveAllAction = ActionFactory.SAVE_ALL.create(window);
-               register(saveAllAction);
-               // closeAllAction = ActionFactory.CLOSE_ALL.create(window);
-               // register(closeAllAction);
-
-       }
-
-       protected void fillMenuBar(IMenuManager menuBar) {
-               // MenuManager fileMenu = new MenuManager("&File",
-               // IWorkbenchActionConstants.M_FILE);
-               // MenuManager editMenu = new MenuManager("&Edit",
-               // IWorkbenchActionConstants.M_EDIT);
-               // MenuManager windowMenu = new MenuManager("&Window",
-               // IWorkbenchActionConstants.M_WINDOW);
-               //
-               // menuBar.add(fileMenu);
-               // menuBar.add(editMenu);
-               // menuBar.add(windowMenu);
-               // // Add a group marker indicating where action set menus will appear.
-               // menuBar.add(new GroupMarker(IWorkbenchActionConstants.MB_ADDITIONS));
-               //
-               // // File
-               // fileMenu.add(saveAction);
-               // fileMenu.add(saveAllAction);
-               // fileMenu.add(closeAllAction);
-               // fileMenu.add(new
-               // GroupMarker(IWorkbenchActionConstants.MB_ADDITIONS));
-               // fileMenu.add(new Separator());
-               // fileMenu.add(logoutAction);
-               //
-               // // Edit
-               // editMenu.add(preferences);
-               //
-               // // Window
-               // windowMenu.add(openPerspectiveDialogAction);
-               // windowMenu.add(showViewMenuAction);
-       }
-
-       @Override
-       protected void fillCoolBar(ICoolBarManager coolBar) {
-               if (username != null) {
-                       ICommandService cmdService = (ICommandService) getActionBarConfigurer()
-                                       .getWindowConfigurer().getWorkbenchConfigurer()
-                                       .getWorkbench().getService(ICommandService.class);
-                       Category userMenus = cmdService.getCategory(ID_BASE + ".userMenus");
-                       if (!userMenus.isDefined())
-                               userMenus.define("User Menus", "User related menus");
-
-                       Command userMenu = cmdService.getCommand(ID_BASE
-                                       + ".userMenuCommand");
-                       if (userMenu.isDefined())
-                               userMenu.undefine();
-                       userMenu.define(username, "User menu actions", userMenus);
-                       userMenu.setHandler(new OpenHomePerspective());
-
-                       // userToolbar.add(new UserMenuAction());
-                       // coolBar.add(userToolbar);
-               } else {// anonymous
-                       IToolBarManager userToolbar = new ToolBarManager(SWT.FLAT
-                                       | SWT.RIGHT);
-                       // userToolbar.add(logoutAction);
-                       coolBar.add(userToolbar);
-               }
-               // IToolBarManager saveToolbar = new ToolBarManager(SWT.FLAT |
-               // SWT.RIGHT);
-               // saveToolbar.add(saveAction);
-               // saveToolbar.add(saveAllAction);
-               // coolBar.add(saveToolbar);
-       }
-
-       // class UserMenuAction extends Action implements IWorkbenchAction {
-       //
-       // public UserMenuAction() {
-       // super(username, IAction.AS_DROP_DOWN_MENU);
-       // // setMenuCreator(new UserMenu());
-       // }
-       //
-       // @Override
-       // public String getId() {
-       // return "org.argeo.security.ui.rap.userMenu";
-       // }
-       //
-       // @Override
-       // public void dispose() {
-       // }
-       //
-       // }
-
-       // class UserMenu implements IMenuCreator {
-       // private Menu menu;
-       //
-       // public Menu getMenu(Control parent) {
-       // Menu menu = new Menu(parent);
-       // addActionToMenu(menu, logoutAction);
-       // return menu;
-       // }
-       //
-       // private void addActionToMenu(Menu menu, IAction action) {
-       // ActionContributionItem item = new ActionContributionItem(action);
-       // item.fill(menu, -1);
-       // }
-       //
-       // public void dispose() {
-       // if (menu != null) {
-       // menu.dispose();
-       // }
-       // }
-       //
-       // public Menu getMenu(Menu parent) {
-       // // Not use
-       // return null;
-       // }
-       //
-       // }
-
-       // protected IAction createLogoutAction() {
-       // Subject subject = Subject.getSubject(AccessController.getContext());
-       // final String username = subject.getPrincipals().iterator().next()
-       // .getName();
-       //
-       // IAction logoutAction = new Action() {
-       // public String getId() {
-       // return SecureRapActivator.ID + ".logoutAction";
-       // }
-       //
-       // public String getText() {
-       // return "Logout " + username;
-       // }
-       //
-       // public void run() {
-       // // try {
-       // // Subject subject = SecureRapActivator.getLoginContext()
-       // // .getSubject();
-       // // String subjectStr = subject.toString();
-       // // subject.getPrincipals().clear();
-       // // SecureRapActivator.getLoginContext().logout();
-       // // log.info(subjectStr + " logged out");
-       // // } catch (LoginException e) {
-       // // log.error("Error when logging out", e);
-       // // }
-       // // SecureEntryPoint.logout(username);
-       // // PlatformUI.getWorkbench().close();
-       // // try {
-       // // RWT.getRequest().getSession().setMaxInactiveInterval(1);
-       // // } catch (Exception e) {
-       // // if (log.isTraceEnabled())
-       // // log.trace("Error when invalidating session", e);
-       // // }
-       // }
-       //
-       // };
-       // return logoutAction;
-       // }
-
-}
diff --git a/org.argeo.security.ui.rap/src/main/java/org/argeo/security/ui/rap/RapWindowAdvisor.java b/org.argeo.security.ui.rap/src/main/java/org/argeo/security/ui/rap/RapWindowAdvisor.java
deleted file mode 100644 (file)
index 4808152..0000000
+++ /dev/null
@@ -1,98 +0,0 @@
-/*
- * Copyright (C) 2007-2012 Argeo GmbH
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *         http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.argeo.security.ui.rap;
-
-import org.eclipse.swt.SWT;
-import org.eclipse.swt.graphics.Point;
-import org.eclipse.swt.graphics.Rectangle;
-import org.eclipse.swt.widgets.Display;
-import org.eclipse.swt.widgets.Event;
-import org.eclipse.swt.widgets.Listener;
-import org.eclipse.swt.widgets.Shell;
-import org.eclipse.ui.IWorkbenchWindow;
-import org.eclipse.ui.actions.ActionFactory;
-import org.eclipse.ui.actions.ActionFactory.IWorkbenchAction;
-import org.eclipse.ui.application.ActionBarAdvisor;
-import org.eclipse.ui.application.IActionBarConfigurer;
-import org.eclipse.ui.application.IWorkbenchWindowConfigurer;
-import org.eclipse.ui.application.WorkbenchWindowAdvisor;
-import org.eclipse.ui.internal.UIPlugin;
-
-/** Eclipse RAP specific window advisor */
-public class RapWindowAdvisor extends WorkbenchWindowAdvisor {
-
-       private String username;
-
-       public RapWindowAdvisor(IWorkbenchWindowConfigurer configurer,
-                       String username) {
-               super(configurer);
-               this.username = username;
-       }
-
-       @Override
-       public ActionBarAdvisor createActionBarAdvisor(
-                       IActionBarConfigurer configurer) {
-               return new RapActionBarAdvisor(configurer, username);
-       }
-
-       public void preWindowOpen() {
-               IWorkbenchWindowConfigurer configurer = getWindowConfigurer();
-               configurer.setShowCoolBar(true);
-               configurer.setShowMenuBar(false);
-               configurer.setShowStatusLine(false);
-               configurer.setShowPerspectiveBar(true);
-               configurer.setTitle("Argeo Web UI"); //$NON-NLS-1$
-               // Full screen, see
-               // http://wiki.eclipse.org/RAP/FAQ#How_to_create_a_fullscreen_application
-               configurer.setShellStyle(SWT.NO_TRIM);
-               Rectangle bounds = Display.getCurrent().getBounds();
-               configurer.setInitialSize(new Point(bounds.width, bounds.height));
-               
-               // Handle window resize in Rap 2.1+ see https://bugs.eclipse.org/bugs/show_bug.cgi?id=417254
-               Display.getCurrent().addListener(SWT.Resize, new Listener() {
-                       @Override
-                       public void handleEvent(Event event) {
-                               Rectangle bounds = event.display.getBounds();
-                               IWorkbenchWindow iww = UIPlugin.getDefault().getWorkbench()
-                                               .getActiveWorkbenchWindow();
-                               iww.getShell().setBounds(bounds);
-                       }
-               });
-       }
-
-       @Override
-       public void postWindowCreate() {
-               Shell shell = getWindowConfigurer().getWindow().getShell();
-               shell.setMaximized(true);
-       }
-
-       @Override
-       public void postWindowOpen() {
-               String defaultPerspective = getWindowConfigurer()
-                               .getWorkbenchConfigurer().getWorkbench()
-                               .getPerspectiveRegistry().getDefaultPerspective();
-               if (defaultPerspective == null) {
-                       IWorkbenchWindow window = getWindowConfigurer().getWindow();
-                       if (window == null)
-                               return;
-
-                       IWorkbenchAction openPerspectiveDialogAction = ActionFactory.OPEN_PERSPECTIVE_DIALOG
-                                       .create(window);
-                       openPerspectiveDialogAction.run();
-               }
-       }
-
-}
diff --git a/org.argeo.security.ui.rap/src/main/java/org/argeo/security/ui/rap/RapWorkbenchAdvisor.java b/org.argeo.security.ui.rap/src/main/java/org/argeo/security/ui/rap/RapWorkbenchAdvisor.java
deleted file mode 100644 (file)
index edde41f..0000000
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * Copyright (C) 2007-2012 Argeo GmbH
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *         http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.argeo.security.ui.rap;
-
-import org.eclipse.ui.IPerspectiveDescriptor;
-import org.eclipse.ui.application.IWorkbenchConfigurer;
-import org.eclipse.ui.application.IWorkbenchWindowConfigurer;
-import org.eclipse.ui.application.WorkbenchAdvisor;
-import org.eclipse.ui.application.WorkbenchWindowAdvisor;
-
-/** Eclipse RAP specific workbench advisor */
-public class RapWorkbenchAdvisor extends WorkbenchAdvisor {
-       public final static String INITIAL_PERSPECTIVE_PROPERTY = "org.argeo.security.ui.initialPerspective";
-       public final static String SAVE_AND_RESTORE_PROPERTY = "org.argeo.security.ui.saveAndRestore";
-
-       private String initialPerspective = System.getProperty(
-                       INITIAL_PERSPECTIVE_PROPERTY, null);
-
-       private String username;
-
-       public RapWorkbenchAdvisor(String username) {
-               this.username = username;
-       }
-
-       @Override
-       public void initialize(IWorkbenchConfigurer configurer) {
-               super.initialize(configurer);
-               Boolean saveAndRestore = Boolean.parseBoolean(System.getProperty(
-                               SAVE_AND_RESTORE_PROPERTY, "false"));
-               configurer.setSaveAndRestore(saveAndRestore);
-       }
-
-       public WorkbenchWindowAdvisor createWorkbenchWindowAdvisor(
-                       IWorkbenchWindowConfigurer configurer) {
-               return new RapWindowAdvisor(configurer, username);
-       }
-
-       public String getInitialWindowPerspectiveId() {
-               if (initialPerspective != null) {
-                       // check whether this user can see the declared perspective
-                       // (typically the perspective won't be listed if this user doesn't
-                       // have the right to see it)
-                       IPerspectiveDescriptor pd = getWorkbenchConfigurer().getWorkbench()
-                                       .getPerspectiveRegistry()
-                                       .findPerspectiveWithId(initialPerspective);
-                       if (pd == null)
-                               return null;
-               }
-               return initialPerspective;
-       }
-}
diff --git a/org.argeo.security.ui.rap/src/main/java/org/argeo/security/ui/rap/SecureEntryPoint.java b/org.argeo.security.ui.rap/src/main/java/org/argeo/security/ui/rap/SecureEntryPoint.java
deleted file mode 100644 (file)
index 288ca62..0000000
+++ /dev/null
@@ -1,215 +0,0 @@
-/*
- * Copyright (C) 2007-2012 Argeo GmbH
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *         http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.argeo.security.ui.rap;
-
-import java.security.PrivilegedAction;
-
-import javax.security.auth.Subject;
-import javax.security.auth.login.LoginException;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpSession;
-
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.argeo.ArgeoException;
-import org.argeo.eclipse.ui.ErrorFeedback;
-import org.argeo.util.LocaleUtils;
-import org.eclipse.equinox.security.auth.ILoginContext;
-import org.eclipse.jface.dialogs.MessageDialog;
-import org.eclipse.rap.rwt.RWT;
-import org.eclipse.rap.rwt.application.IEntryPoint;
-import org.eclipse.swt.widgets.Display;
-import org.eclipse.ui.PlatformUI;
-import org.springframework.security.BadCredentialsException;
-import org.springframework.security.context.SecurityContext;
-import org.springframework.security.context.SecurityContextHolder;
-
-/**
- * RAP entry point with login capabilities. Once the user has been
- * authenticated, the workbench is run as a privileged action by the related
- * subject.
- */
-public class SecureEntryPoint implements IEntryPoint {
-       private final static Log log = LogFactory.getLog(SecureEntryPoint.class);
-
-       /**
-        * From org.springframework.security.context.
-        * HttpSessionContextIntegrationFilter
-        */
-       protected static final String SPRING_SECURITY_CONTEXT_KEY = "SPRING_SECURITY_CONTEXT";
-
-       /**
-        * How many seconds to wait before invalidating the session if the user has
-        * not yet logged in.
-        */
-       private Integer loginTimeout = 1 * 60;
-       // TODO make it configurable
-       /** Default session timeout is 8 hours (European working day length) */
-       private Integer sessionTimeout = 8 * 60 * 60;
-
-       /** Override to provide an application specific workbench advisor */
-       protected RapWorkbenchAdvisor createRapWorkbenchAdvisor(String username) {
-               return new RapWorkbenchAdvisor(username);
-       }
-
-       @Override
-       public final int createUI() {
-               // Short login timeout so that the modal dialog login doesn't hang
-               // around too long
-               RWT.getRequest().getSession().setMaxInactiveInterval(loginTimeout);
-
-               // Try to load security context thanks to the session processing filter
-               HttpServletRequest httpRequest = RWT.getRequest();
-               HttpSession httpSession = httpRequest.getSession();
-               Object contextFromSessionObject = httpSession
-                               .getAttribute(SPRING_SECURITY_CONTEXT_KEY);
-               if (contextFromSessionObject != null)
-                       SecurityContextHolder
-                                       .setContext((SecurityContext) contextFromSessionObject);
-
-//             if (log.isDebugEnabled())
-//                     log.debug("THREAD=" + Thread.currentThread().getId()
-//                                     + ", sessionStore=" + RWT.getSessionStore().getId()
-//                                     + ", remote user=" + httpRequest.getRemoteUser());
-
-               // create display
-               final Display display = PlatformUI.createDisplay();
-
-               // log in
-               final ILoginContext loginContext = SecureRapActivator
-                               .createLoginContext(SecureRapActivator.CONTEXT_SPRING);
-               Subject subject = null;
-               tryLogin: while (subject == null && !display.isDisposed()) {
-                       try {
-                               loginContext.login();
-                               subject = loginContext.getSubject();
-
-                               // add security context to session
-                               if (httpSession.getAttribute(SPRING_SECURITY_CONTEXT_KEY) == null)
-                                       httpSession.setAttribute(SPRING_SECURITY_CONTEXT_KEY,
-                                                       SecurityContextHolder.getContext());
-                               // add thread locale to RWT session
-                               log.info("Locale "+LocaleUtils.threadLocale.get());
-                               RWT.setLocale(LocaleUtils.threadLocale.get());
-
-                               // Once the user is logged in, she can have a longer session
-                               // timeout
-                               RWT.getRequest().getSession()
-                                               .setMaxInactiveInterval(sessionTimeout);
-                               if (log.isDebugEnabled())
-                                       log.debug("Authenticated " + subject);
-                       } catch (LoginException e) {
-                               BadCredentialsException bce = wasCausedByBadCredentials(e);
-                               if (bce != null) {
-                                       MessageDialog.openInformation(display.getActiveShell(),
-                                                       "Bad Credentials", bce.getMessage());
-                                       // retry login
-                                       continue tryLogin;
-                               }
-                               return processLoginDeath(display, e);
-                       }
-               }
-
-               final String username = subject.getPrincipals().iterator().next()
-                               .getName();
-               // Logout callback when the display is disposed
-               display.disposeExec(new Runnable() {
-                       public void run() {
-                               log.debug("Display disposed");
-                               logout(loginContext, username);
-                       }
-               });
-
-               //
-               // RUN THE WORKBENCH
-               //
-               Integer returnCode = null;
-               try {
-                       returnCode = Subject.doAs(subject, new PrivilegedAction<Integer>() {
-                               public Integer run() {
-                                       RapWorkbenchAdvisor workbenchAdvisor = createRapWorkbenchAdvisor(username);
-                                       int result = PlatformUI.createAndRunWorkbench(display,
-                                                       workbenchAdvisor);
-                                       return new Integer(result);
-                               }
-                       });
-                       // logout(loginContext, username);
-               } finally {
-                       display.dispose();
-               }
-               return returnCode;
-       }
-
-       private Integer processLoginDeath(Display display, LoginException e) {
-               // check thread death
-               ThreadDeath td = wasCausedByThreadDeath(e);
-               if (td != null) {
-                       display.dispose();
-                       throw td;
-               }
-               if (!display.isDisposed()) {
-                       ErrorFeedback.show("Unexpected exception during authentication", e);
-                       // this was not just bad credentials or death thread
-                       RWT.getRequest().getSession().setMaxInactiveInterval(1);
-                       display.dispose();
-                       return -1;
-               } else {
-                       throw new ArgeoException(
-                                       "Unexpected exception during authentication", e);
-               }
-
-       }
-
-       /** Recursively look for {@link BadCredentialsException} in the root causes. */
-       private BadCredentialsException wasCausedByBadCredentials(Throwable t) {
-               if (t instanceof BadCredentialsException)
-                       return (BadCredentialsException) t;
-
-               if (t.getCause() != null)
-                       return wasCausedByBadCredentials(t.getCause());
-               else
-                       return null;
-       }
-
-       /**
-        * If there is a {@link ThreadDeath} in the root causes, rethrow it
-        * (important for RAP cleaning mechanism)
-        */
-       protected ThreadDeath wasCausedByThreadDeath(Throwable t) {
-               if (t instanceof ThreadDeath)
-                       return (ThreadDeath) t;
-
-               if (t.getCause() != null)
-                       return wasCausedByThreadDeath(t.getCause());
-               else
-                       return null;
-       }
-
-       protected void logout(ILoginContext secureContext, String username) {
-               try {
-                       HttpServletRequest httpRequest = RWT.getRequest();
-                       HttpSession httpSession = httpRequest.getSession();
-                       httpSession.setAttribute(SPRING_SECURITY_CONTEXT_KEY, null);
-                       RWT.getRequest().getSession().setMaxInactiveInterval(1);
-                       SecurityContextHolder.clearContext();
-                       secureContext.logout();
-                       log.info("Logged out " + (username != null ? username : "")
-                                       + " (THREAD=" + Thread.currentThread().getId() + ")");
-               } catch (LoginException e) {
-                       log.error("Erorr when logging out", e);
-               }
-       }
-}
diff --git a/org.argeo.security.ui.rap/src/main/java/org/argeo/security/ui/rap/SecureRapActivator.java b/org.argeo.security.ui.rap/src/main/java/org/argeo/security/ui/rap/SecureRapActivator.java
deleted file mode 100644 (file)
index 4cbb441..0000000
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * Copyright (C) 2007-2012 Argeo GmbH
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *         http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.argeo.security.ui.rap;
-
-import java.net.URL;
-
-import org.eclipse.equinox.security.auth.ILoginContext;
-import org.eclipse.equinox.security.auth.LoginContextFactory;
-import org.osgi.framework.BundleActivator;
-import org.osgi.framework.BundleContext;
-
-/** Configure Equinox login context from the bundle context. */
-public class SecureRapActivator implements BundleActivator {
-
-       public final static String ID = "org.argeo.security.ui.rap";
-       public final static String CONTEXT_SPRING = "SPRING";
-       public final static String CONTEXT_SPRING_ANONYMOUS = "SPRING_ANONYMOUS";
-       private static final String JAAS_CONFIG_FILE = "/META-INF/jaas_default.txt";
-
-       private BundleContext bundleContext;
-       private static SecureRapActivator activator = null;
-
-       public void start(BundleContext bundleContext) throws Exception {
-               activator = this;
-               this.bundleContext = bundleContext;
-       }
-
-       public void stop(BundleContext context) throws Exception {
-               bundleContext = null;
-               activator = null;
-       }
-
-       public BundleContext getBundleContext() {
-               return bundleContext;
-       }
-
-       public static SecureRapActivator getActivator() {
-               return activator;
-       }
-
-       static ILoginContext createLoginContext(String contextName) {
-               URL configUrl = getActivator().getBundleContext().getBundle()
-                               .getEntry(JAAS_CONFIG_FILE);
-               return LoginContextFactory.createContext(contextName, configUrl);
-       }
-}
diff --git a/org.argeo.security.ui.rap/src/main/java/org/argeo/security/ui/rap/commands/UserMenu.java b/org.argeo.security.ui.rap/src/main/java/org/argeo/security/ui/rap/commands/UserMenu.java
deleted file mode 100644 (file)
index 9867430..0000000
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * Copyright (C) 2007-2012 Argeo GmbH
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *         http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.argeo.security.ui.rap.commands;
-
-import org.eclipse.core.commands.AbstractHandler;
-import org.eclipse.core.commands.ExecutionEvent;
-import org.eclipse.core.commands.ExecutionException;
-
-/** Default action of the user menu */
-public class UserMenu extends AbstractHandler {
-
-       @Override
-       public Object execute(ExecutionEvent event) throws ExecutionException {
-               return null;
-       }
-
-}
diff --git a/org.argeo.security.ui.rap/src/org/argeo/security/ui/rap/AnonymousEntryPoint.java b/org.argeo.security.ui.rap/src/org/argeo/security/ui/rap/AnonymousEntryPoint.java
new file mode 100644 (file)
index 0000000..16d2489
--- /dev/null
@@ -0,0 +1,118 @@
+/*
+ * Copyright (C) 2007-2012 Argeo GmbH
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *         http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.argeo.security.ui.rap;
+
+import java.security.PrivilegedAction;
+
+import javax.security.auth.Subject;
+import javax.security.auth.login.LoginException;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.argeo.ArgeoException;
+import org.eclipse.equinox.security.auth.ILoginContext;
+import org.eclipse.rap.rwt.RWT;
+import org.eclipse.rap.rwt.application.IEntryPoint;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.ui.PlatformUI;
+
+/**
+ * RAP entry point which authenticates the subject as anonymous, for public
+ * unauthenticated access.
+ */
+public class AnonymousEntryPoint implements IEntryPoint {
+       private final static Log log = LogFactory.getLog(AnonymousEntryPoint.class);
+
+       /**
+        * How many seconds to wait before invalidating the session if the user has
+        * not yet logged in.
+        */
+       private Integer loginTimeout = 1 * 60;
+       private Integer sessionTimeout = 15 * 60;
+
+       @Override
+       public int createUI() {
+               // Short login timeout so that the modal dialog login doesn't hang
+               // around too long
+               RWT.getRequest().getSession().setMaxInactiveInterval(loginTimeout);
+
+               if (log.isDebugEnabled())
+                       log.debug("Anonymous THREAD=" + Thread.currentThread().getId()
+                                       + ", sessionStore=" + RWT.getSessionStore().getId());
+
+               // create display
+               final Display display = PlatformUI.createDisplay();
+
+               // log in
+               final ILoginContext loginContext = SecureRapActivator
+                               .createLoginContext(SecureRapActivator.CONTEXT_SPRING_ANONYMOUS);
+               Subject subject = null;
+               try {
+                       loginContext.login();
+                       subject = loginContext.getSubject();
+               } catch (LoginException e) {
+                       throw new ArgeoException(
+                                       "Unexpected exception during authentication", e);
+               }
+
+               // identify after successful login
+               if (log.isDebugEnabled())
+                       log.debug("Authenticated " + subject);
+               final String username = subject.getPrincipals().iterator().next()
+                               .getName();
+
+               // Once the user is logged in, she can have a longer session timeout
+               RWT.getRequest().getSession().setMaxInactiveInterval(sessionTimeout);
+
+               // Logout callback when the display is disposed
+               display.disposeExec(new Runnable() {
+                       public void run() {
+                               log.debug("Display disposed");
+                               logout(loginContext, username);
+                       }
+               });
+
+               //
+               // RUN THE WORKBENCH
+               //
+               Integer returnCode = null;
+               try {
+                       returnCode = Subject.doAs(subject, new PrivilegedAction<Integer>() {
+                               public Integer run() {
+                                       RapWorkbenchAdvisor workbenchAdvisor = new RapWorkbenchAdvisor(
+                                                       null);
+                                       int result = PlatformUI.createAndRunWorkbench(display,
+                                                       workbenchAdvisor);
+                                       return new Integer(result);
+                               }
+                       });
+                       logout(loginContext, username);
+               } finally {
+                       display.dispose();
+               }
+               return returnCode;
+       }
+
+       private void logout(ILoginContext secureContext, String username) {
+               try {
+                       secureContext.logout();
+                       log.info("Logged out " + (username != null ? username : "")
+                                       + " (THREAD=" + Thread.currentThread().getId() + ")");
+               } catch (LoginException e) {
+                       log.error("Erorr when logging out", e);
+               }
+       }
+}
diff --git a/org.argeo.security.ui.rap/src/org/argeo/security/ui/rap/LogoutEntryPoint.java b/org.argeo.security.ui.rap/src/org/argeo/security/ui/rap/LogoutEntryPoint.java
new file mode 100644 (file)
index 0000000..7337549
--- /dev/null
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2007-2012 Argeo GmbH
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *         http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.argeo.security.ui.rap;
+
+import javax.security.auth.login.LoginException;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.eclipse.equinox.security.auth.ILoginContext;
+import org.eclipse.rap.rwt.RWT;
+import org.eclipse.rap.rwt.application.IEntryPoint;
+import org.eclipse.ui.PlatformUI;
+import org.springframework.security.context.SecurityContextHolder;
+
+/**
+ * RAP entry point which logs out the currently authenticated user
+ */
+public class LogoutEntryPoint implements IEntryPoint {
+       private final static Log log = LogFactory.getLog(LogoutEntryPoint.class);
+
+       /**
+        * From org.springframework.security.context.
+        * HttpSessionContextIntegrationFilter
+        */
+       protected static final String SPRING_SECURITY_CONTEXT_KEY = "SPRING_SECURITY_CONTEXT";
+
+       @Override
+       public int createUI() {
+               // create display
+               PlatformUI.createDisplay();
+
+               final ILoginContext loginContext = SecureRapActivator
+                               .createLoginContext(SecureRapActivator.CONTEXT_SPRING);
+               try {
+                       loginContext.logout();
+               } catch (LoginException e) {
+                       e.printStackTrace();
+               }
+
+               RWT.getRequest().getSession()
+                               .removeAttribute(SPRING_SECURITY_CONTEXT_KEY);
+               SecurityContextHolder.clearContext();
+               RWT.getRequest().getSession().setMaxInactiveInterval(1);
+
+               if (log.isDebugEnabled())
+                       log.debug("Logged out session " + RWT.getSessionStore().getId());
+               return 0;
+       }
+}
diff --git a/org.argeo.security.ui.rap/src/org/argeo/security/ui/rap/NullEntryPoint.java b/org.argeo.security.ui.rap/src/org/argeo/security/ui/rap/NullEntryPoint.java
new file mode 100644 (file)
index 0000000..811cc28
--- /dev/null
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2007-2012 Argeo GmbH
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *         http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.argeo.security.ui.rap;
+
+import org.eclipse.rap.rwt.application.IEntryPoint;
+import org.eclipse.ui.PlatformUI;
+
+/**
+ * RAP entry point which does doesing except creating the display
+ */
+public class NullEntryPoint implements IEntryPoint {
+       @Override
+       public int createUI() {
+               // create display
+               PlatformUI.createDisplay();
+               return 0;
+       }
+}
diff --git a/org.argeo.security.ui.rap/src/org/argeo/security/ui/rap/RapActionBarAdvisor.java b/org.argeo.security.ui.rap/src/org/argeo/security/ui/rap/RapActionBarAdvisor.java
new file mode 100644 (file)
index 0000000..074b798
--- /dev/null
@@ -0,0 +1,227 @@
+/*
+ * Copyright (C) 2007-2012 Argeo GmbH
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *         http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.argeo.security.ui.rap;
+
+import org.argeo.security.ui.commands.OpenHomePerspective;
+import org.eclipse.core.commands.Category;
+import org.eclipse.core.commands.Command;
+import org.eclipse.jface.action.ICoolBarManager;
+import org.eclipse.jface.action.IMenuManager;
+import org.eclipse.jface.action.IToolBarManager;
+import org.eclipse.jface.action.ToolBarManager;
+import org.eclipse.swt.SWT;
+import org.eclipse.ui.IWorkbenchWindow;
+import org.eclipse.ui.actions.ActionFactory;
+import org.eclipse.ui.actions.ActionFactory.IWorkbenchAction;
+import org.eclipse.ui.application.ActionBarAdvisor;
+import org.eclipse.ui.application.IActionBarConfigurer;
+import org.eclipse.ui.commands.ICommandService;
+
+/** Eclipse rap specific action bar advisor */
+public class RapActionBarAdvisor extends ActionBarAdvisor {
+       private final static String ID_BASE = "org.argeo.security.ui.rap";
+       // private final static Log log = LogFactory
+       // .getLog(SecureActionBarAdvisor.class);
+
+       /** Null means anonymous */
+       private String username = null;
+
+       // private IAction logoutAction;
+       // private IWorkbenchAction openPerspectiveDialogAction;
+       // private IWorkbenchAction showViewMenuAction;
+       // private IWorkbenchAction preferences;
+       private IWorkbenchAction saveAction;
+       private IWorkbenchAction saveAllAction;
+
+       // private IWorkbenchAction closeAllAction;
+
+       public RapActionBarAdvisor(IActionBarConfigurer configurer, String username) {
+               super(configurer);
+               this.username = username;
+       }
+
+       protected void makeActions(IWorkbenchWindow window) {
+               // preferences = ActionFactory.PREFERENCES.create(window);
+               // register(preferences);
+               // openPerspectiveDialogAction = ActionFactory.OPEN_PERSPECTIVE_DIALOG
+               // .create(window);
+               // register(openPerspectiveDialogAction);
+               // showViewMenuAction = ActionFactory.SHOW_VIEW_MENU.create(window);
+               // register(showViewMenuAction);
+               //
+               // // logout
+               // logoutAction = ActionFactory.QUIT.create(window);
+               // // logoutAction = createLogoutAction();
+               // register(logoutAction);
+               //
+               // Save semantics
+               saveAction = ActionFactory.SAVE.create(window);
+               register(saveAction);
+               saveAllAction = ActionFactory.SAVE_ALL.create(window);
+               register(saveAllAction);
+               // closeAllAction = ActionFactory.CLOSE_ALL.create(window);
+               // register(closeAllAction);
+
+       }
+
+       protected void fillMenuBar(IMenuManager menuBar) {
+               // MenuManager fileMenu = new MenuManager("&File",
+               // IWorkbenchActionConstants.M_FILE);
+               // MenuManager editMenu = new MenuManager("&Edit",
+               // IWorkbenchActionConstants.M_EDIT);
+               // MenuManager windowMenu = new MenuManager("&Window",
+               // IWorkbenchActionConstants.M_WINDOW);
+               //
+               // menuBar.add(fileMenu);
+               // menuBar.add(editMenu);
+               // menuBar.add(windowMenu);
+               // // Add a group marker indicating where action set menus will appear.
+               // menuBar.add(new GroupMarker(IWorkbenchActionConstants.MB_ADDITIONS));
+               //
+               // // File
+               // fileMenu.add(saveAction);
+               // fileMenu.add(saveAllAction);
+               // fileMenu.add(closeAllAction);
+               // fileMenu.add(new
+               // GroupMarker(IWorkbenchActionConstants.MB_ADDITIONS));
+               // fileMenu.add(new Separator());
+               // fileMenu.add(logoutAction);
+               //
+               // // Edit
+               // editMenu.add(preferences);
+               //
+               // // Window
+               // windowMenu.add(openPerspectiveDialogAction);
+               // windowMenu.add(showViewMenuAction);
+       }
+
+       @Override
+       protected void fillCoolBar(ICoolBarManager coolBar) {
+               if (username != null) {
+                       ICommandService cmdService = (ICommandService) getActionBarConfigurer()
+                                       .getWindowConfigurer().getWorkbenchConfigurer()
+                                       .getWorkbench().getService(ICommandService.class);
+                       Category userMenus = cmdService.getCategory(ID_BASE + ".userMenus");
+                       if (!userMenus.isDefined())
+                               userMenus.define("User Menus", "User related menus");
+
+                       Command userMenu = cmdService.getCommand(ID_BASE
+                                       + ".userMenuCommand");
+                       if (userMenu.isDefined())
+                               userMenu.undefine();
+                       userMenu.define(username, "User menu actions", userMenus);
+                       userMenu.setHandler(new OpenHomePerspective());
+
+                       // userToolbar.add(new UserMenuAction());
+                       // coolBar.add(userToolbar);
+               } else {// anonymous
+                       IToolBarManager userToolbar = new ToolBarManager(SWT.FLAT
+                                       | SWT.RIGHT);
+                       // userToolbar.add(logoutAction);
+                       coolBar.add(userToolbar);
+               }
+               // IToolBarManager saveToolbar = new ToolBarManager(SWT.FLAT |
+               // SWT.RIGHT);
+               // saveToolbar.add(saveAction);
+               // saveToolbar.add(saveAllAction);
+               // coolBar.add(saveToolbar);
+       }
+
+       // class UserMenuAction extends Action implements IWorkbenchAction {
+       //
+       // public UserMenuAction() {
+       // super(username, IAction.AS_DROP_DOWN_MENU);
+       // // setMenuCreator(new UserMenu());
+       // }
+       //
+       // @Override
+       // public String getId() {
+       // return "org.argeo.security.ui.rap.userMenu";
+       // }
+       //
+       // @Override
+       // public void dispose() {
+       // }
+       //
+       // }
+
+       // class UserMenu implements IMenuCreator {
+       // private Menu menu;
+       //
+       // public Menu getMenu(Control parent) {
+       // Menu menu = new Menu(parent);
+       // addActionToMenu(menu, logoutAction);
+       // return menu;
+       // }
+       //
+       // private void addActionToMenu(Menu menu, IAction action) {
+       // ActionContributionItem item = new ActionContributionItem(action);
+       // item.fill(menu, -1);
+       // }
+       //
+       // public void dispose() {
+       // if (menu != null) {
+       // menu.dispose();
+       // }
+       // }
+       //
+       // public Menu getMenu(Menu parent) {
+       // // Not use
+       // return null;
+       // }
+       //
+       // }
+
+       // protected IAction createLogoutAction() {
+       // Subject subject = Subject.getSubject(AccessController.getContext());
+       // final String username = subject.getPrincipals().iterator().next()
+       // .getName();
+       //
+       // IAction logoutAction = new Action() {
+       // public String getId() {
+       // return SecureRapActivator.ID + ".logoutAction";
+       // }
+       //
+       // public String getText() {
+       // return "Logout " + username;
+       // }
+       //
+       // public void run() {
+       // // try {
+       // // Subject subject = SecureRapActivator.getLoginContext()
+       // // .getSubject();
+       // // String subjectStr = subject.toString();
+       // // subject.getPrincipals().clear();
+       // // SecureRapActivator.getLoginContext().logout();
+       // // log.info(subjectStr + " logged out");
+       // // } catch (LoginException e) {
+       // // log.error("Error when logging out", e);
+       // // }
+       // // SecureEntryPoint.logout(username);
+       // // PlatformUI.getWorkbench().close();
+       // // try {
+       // // RWT.getRequest().getSession().setMaxInactiveInterval(1);
+       // // } catch (Exception e) {
+       // // if (log.isTraceEnabled())
+       // // log.trace("Error when invalidating session", e);
+       // // }
+       // }
+       //
+       // };
+       // return logoutAction;
+       // }
+
+}
diff --git a/org.argeo.security.ui.rap/src/org/argeo/security/ui/rap/RapWindowAdvisor.java b/org.argeo.security.ui.rap/src/org/argeo/security/ui/rap/RapWindowAdvisor.java
new file mode 100644 (file)
index 0000000..4808152
--- /dev/null
@@ -0,0 +1,98 @@
+/*
+ * Copyright (C) 2007-2012 Argeo GmbH
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *         http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.argeo.security.ui.rap;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.graphics.Rectangle;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Event;
+import org.eclipse.swt.widgets.Listener;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.ui.IWorkbenchWindow;
+import org.eclipse.ui.actions.ActionFactory;
+import org.eclipse.ui.actions.ActionFactory.IWorkbenchAction;
+import org.eclipse.ui.application.ActionBarAdvisor;
+import org.eclipse.ui.application.IActionBarConfigurer;
+import org.eclipse.ui.application.IWorkbenchWindowConfigurer;
+import org.eclipse.ui.application.WorkbenchWindowAdvisor;
+import org.eclipse.ui.internal.UIPlugin;
+
+/** Eclipse RAP specific window advisor */
+public class RapWindowAdvisor extends WorkbenchWindowAdvisor {
+
+       private String username;
+
+       public RapWindowAdvisor(IWorkbenchWindowConfigurer configurer,
+                       String username) {
+               super(configurer);
+               this.username = username;
+       }
+
+       @Override
+       public ActionBarAdvisor createActionBarAdvisor(
+                       IActionBarConfigurer configurer) {
+               return new RapActionBarAdvisor(configurer, username);
+       }
+
+       public void preWindowOpen() {
+               IWorkbenchWindowConfigurer configurer = getWindowConfigurer();
+               configurer.setShowCoolBar(true);
+               configurer.setShowMenuBar(false);
+               configurer.setShowStatusLine(false);
+               configurer.setShowPerspectiveBar(true);
+               configurer.setTitle("Argeo Web UI"); //$NON-NLS-1$
+               // Full screen, see
+               // http://wiki.eclipse.org/RAP/FAQ#How_to_create_a_fullscreen_application
+               configurer.setShellStyle(SWT.NO_TRIM);
+               Rectangle bounds = Display.getCurrent().getBounds();
+               configurer.setInitialSize(new Point(bounds.width, bounds.height));
+               
+               // Handle window resize in Rap 2.1+ see https://bugs.eclipse.org/bugs/show_bug.cgi?id=417254
+               Display.getCurrent().addListener(SWT.Resize, new Listener() {
+                       @Override
+                       public void handleEvent(Event event) {
+                               Rectangle bounds = event.display.getBounds();
+                               IWorkbenchWindow iww = UIPlugin.getDefault().getWorkbench()
+                                               .getActiveWorkbenchWindow();
+                               iww.getShell().setBounds(bounds);
+                       }
+               });
+       }
+
+       @Override
+       public void postWindowCreate() {
+               Shell shell = getWindowConfigurer().getWindow().getShell();
+               shell.setMaximized(true);
+       }
+
+       @Override
+       public void postWindowOpen() {
+               String defaultPerspective = getWindowConfigurer()
+                               .getWorkbenchConfigurer().getWorkbench()
+                               .getPerspectiveRegistry().getDefaultPerspective();
+               if (defaultPerspective == null) {
+                       IWorkbenchWindow window = getWindowConfigurer().getWindow();
+                       if (window == null)
+                               return;
+
+                       IWorkbenchAction openPerspectiveDialogAction = ActionFactory.OPEN_PERSPECTIVE_DIALOG
+                                       .create(window);
+                       openPerspectiveDialogAction.run();
+               }
+       }
+
+}
diff --git a/org.argeo.security.ui.rap/src/org/argeo/security/ui/rap/RapWorkbenchAdvisor.java b/org.argeo.security.ui.rap/src/org/argeo/security/ui/rap/RapWorkbenchAdvisor.java
new file mode 100644 (file)
index 0000000..edde41f
--- /dev/null
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2007-2012 Argeo GmbH
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *         http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.argeo.security.ui.rap;
+
+import org.eclipse.ui.IPerspectiveDescriptor;
+import org.eclipse.ui.application.IWorkbenchConfigurer;
+import org.eclipse.ui.application.IWorkbenchWindowConfigurer;
+import org.eclipse.ui.application.WorkbenchAdvisor;
+import org.eclipse.ui.application.WorkbenchWindowAdvisor;
+
+/** Eclipse RAP specific workbench advisor */
+public class RapWorkbenchAdvisor extends WorkbenchAdvisor {
+       public final static String INITIAL_PERSPECTIVE_PROPERTY = "org.argeo.security.ui.initialPerspective";
+       public final static String SAVE_AND_RESTORE_PROPERTY = "org.argeo.security.ui.saveAndRestore";
+
+       private String initialPerspective = System.getProperty(
+                       INITIAL_PERSPECTIVE_PROPERTY, null);
+
+       private String username;
+
+       public RapWorkbenchAdvisor(String username) {
+               this.username = username;
+       }
+
+       @Override
+       public void initialize(IWorkbenchConfigurer configurer) {
+               super.initialize(configurer);
+               Boolean saveAndRestore = Boolean.parseBoolean(System.getProperty(
+                               SAVE_AND_RESTORE_PROPERTY, "false"));
+               configurer.setSaveAndRestore(saveAndRestore);
+       }
+
+       public WorkbenchWindowAdvisor createWorkbenchWindowAdvisor(
+                       IWorkbenchWindowConfigurer configurer) {
+               return new RapWindowAdvisor(configurer, username);
+       }
+
+       public String getInitialWindowPerspectiveId() {
+               if (initialPerspective != null) {
+                       // check whether this user can see the declared perspective
+                       // (typically the perspective won't be listed if this user doesn't
+                       // have the right to see it)
+                       IPerspectiveDescriptor pd = getWorkbenchConfigurer().getWorkbench()
+                                       .getPerspectiveRegistry()
+                                       .findPerspectiveWithId(initialPerspective);
+                       if (pd == null)
+                               return null;
+               }
+               return initialPerspective;
+       }
+}
diff --git a/org.argeo.security.ui.rap/src/org/argeo/security/ui/rap/SecureEntryPoint.java b/org.argeo.security.ui.rap/src/org/argeo/security/ui/rap/SecureEntryPoint.java
new file mode 100644 (file)
index 0000000..288ca62
--- /dev/null
@@ -0,0 +1,215 @@
+/*
+ * Copyright (C) 2007-2012 Argeo GmbH
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *         http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.argeo.security.ui.rap;
+
+import java.security.PrivilegedAction;
+
+import javax.security.auth.Subject;
+import javax.security.auth.login.LoginException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpSession;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.argeo.ArgeoException;
+import org.argeo.eclipse.ui.ErrorFeedback;
+import org.argeo.util.LocaleUtils;
+import org.eclipse.equinox.security.auth.ILoginContext;
+import org.eclipse.jface.dialogs.MessageDialog;
+import org.eclipse.rap.rwt.RWT;
+import org.eclipse.rap.rwt.application.IEntryPoint;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.ui.PlatformUI;
+import org.springframework.security.BadCredentialsException;
+import org.springframework.security.context.SecurityContext;
+import org.springframework.security.context.SecurityContextHolder;
+
+/**
+ * RAP entry point with login capabilities. Once the user has been
+ * authenticated, the workbench is run as a privileged action by the related
+ * subject.
+ */
+public class SecureEntryPoint implements IEntryPoint {
+       private final static Log log = LogFactory.getLog(SecureEntryPoint.class);
+
+       /**
+        * From org.springframework.security.context.
+        * HttpSessionContextIntegrationFilter
+        */
+       protected static final String SPRING_SECURITY_CONTEXT_KEY = "SPRING_SECURITY_CONTEXT";
+
+       /**
+        * How many seconds to wait before invalidating the session if the user has
+        * not yet logged in.
+        */
+       private Integer loginTimeout = 1 * 60;
+       // TODO make it configurable
+       /** Default session timeout is 8 hours (European working day length) */
+       private Integer sessionTimeout = 8 * 60 * 60;
+
+       /** Override to provide an application specific workbench advisor */
+       protected RapWorkbenchAdvisor createRapWorkbenchAdvisor(String username) {
+               return new RapWorkbenchAdvisor(username);
+       }
+
+       @Override
+       public final int createUI() {
+               // Short login timeout so that the modal dialog login doesn't hang
+               // around too long
+               RWT.getRequest().getSession().setMaxInactiveInterval(loginTimeout);
+
+               // Try to load security context thanks to the session processing filter
+               HttpServletRequest httpRequest = RWT.getRequest();
+               HttpSession httpSession = httpRequest.getSession();
+               Object contextFromSessionObject = httpSession
+                               .getAttribute(SPRING_SECURITY_CONTEXT_KEY);
+               if (contextFromSessionObject != null)
+                       SecurityContextHolder
+                                       .setContext((SecurityContext) contextFromSessionObject);
+
+//             if (log.isDebugEnabled())
+//                     log.debug("THREAD=" + Thread.currentThread().getId()
+//                                     + ", sessionStore=" + RWT.getSessionStore().getId()
+//                                     + ", remote user=" + httpRequest.getRemoteUser());
+
+               // create display
+               final Display display = PlatformUI.createDisplay();
+
+               // log in
+               final ILoginContext loginContext = SecureRapActivator
+                               .createLoginContext(SecureRapActivator.CONTEXT_SPRING);
+               Subject subject = null;
+               tryLogin: while (subject == null && !display.isDisposed()) {
+                       try {
+                               loginContext.login();
+                               subject = loginContext.getSubject();
+
+                               // add security context to session
+                               if (httpSession.getAttribute(SPRING_SECURITY_CONTEXT_KEY) == null)
+                                       httpSession.setAttribute(SPRING_SECURITY_CONTEXT_KEY,
+                                                       SecurityContextHolder.getContext());
+                               // add thread locale to RWT session
+                               log.info("Locale "+LocaleUtils.threadLocale.get());
+                               RWT.setLocale(LocaleUtils.threadLocale.get());
+
+                               // Once the user is logged in, she can have a longer session
+                               // timeout
+                               RWT.getRequest().getSession()
+                                               .setMaxInactiveInterval(sessionTimeout);
+                               if (log.isDebugEnabled())
+                                       log.debug("Authenticated " + subject);
+                       } catch (LoginException e) {
+                               BadCredentialsException bce = wasCausedByBadCredentials(e);
+                               if (bce != null) {
+                                       MessageDialog.openInformation(display.getActiveShell(),
+                                                       "Bad Credentials", bce.getMessage());
+                                       // retry login
+                                       continue tryLogin;
+                               }
+                               return processLoginDeath(display, e);
+                       }
+               }
+
+               final String username = subject.getPrincipals().iterator().next()
+                               .getName();
+               // Logout callback when the display is disposed
+               display.disposeExec(new Runnable() {
+                       public void run() {
+                               log.debug("Display disposed");
+                               logout(loginContext, username);
+                       }
+               });
+
+               //
+               // RUN THE WORKBENCH
+               //
+               Integer returnCode = null;
+               try {
+                       returnCode = Subject.doAs(subject, new PrivilegedAction<Integer>() {
+                               public Integer run() {
+                                       RapWorkbenchAdvisor workbenchAdvisor = createRapWorkbenchAdvisor(username);
+                                       int result = PlatformUI.createAndRunWorkbench(display,
+                                                       workbenchAdvisor);
+                                       return new Integer(result);
+                               }
+                       });
+                       // logout(loginContext, username);
+               } finally {
+                       display.dispose();
+               }
+               return returnCode;
+       }
+
+       private Integer processLoginDeath(Display display, LoginException e) {
+               // check thread death
+               ThreadDeath td = wasCausedByThreadDeath(e);
+               if (td != null) {
+                       display.dispose();
+                       throw td;
+               }
+               if (!display.isDisposed()) {
+                       ErrorFeedback.show("Unexpected exception during authentication", e);
+                       // this was not just bad credentials or death thread
+                       RWT.getRequest().getSession().setMaxInactiveInterval(1);
+                       display.dispose();
+                       return -1;
+               } else {
+                       throw new ArgeoException(
+                                       "Unexpected exception during authentication", e);
+               }
+
+       }
+
+       /** Recursively look for {@link BadCredentialsException} in the root causes. */
+       private BadCredentialsException wasCausedByBadCredentials(Throwable t) {
+               if (t instanceof BadCredentialsException)
+                       return (BadCredentialsException) t;
+
+               if (t.getCause() != null)
+                       return wasCausedByBadCredentials(t.getCause());
+               else
+                       return null;
+       }
+
+       /**
+        * If there is a {@link ThreadDeath} in the root causes, rethrow it
+        * (important for RAP cleaning mechanism)
+        */
+       protected ThreadDeath wasCausedByThreadDeath(Throwable t) {
+               if (t instanceof ThreadDeath)
+                       return (ThreadDeath) t;
+
+               if (t.getCause() != null)
+                       return wasCausedByThreadDeath(t.getCause());
+               else
+                       return null;
+       }
+
+       protected void logout(ILoginContext secureContext, String username) {
+               try {
+                       HttpServletRequest httpRequest = RWT.getRequest();
+                       HttpSession httpSession = httpRequest.getSession();
+                       httpSession.setAttribute(SPRING_SECURITY_CONTEXT_KEY, null);
+                       RWT.getRequest().getSession().setMaxInactiveInterval(1);
+                       SecurityContextHolder.clearContext();
+                       secureContext.logout();
+                       log.info("Logged out " + (username != null ? username : "")
+                                       + " (THREAD=" + Thread.currentThread().getId() + ")");
+               } catch (LoginException e) {
+                       log.error("Erorr when logging out", e);
+               }
+       }
+}
diff --git a/org.argeo.security.ui.rap/src/org/argeo/security/ui/rap/SecureRapActivator.java b/org.argeo.security.ui.rap/src/org/argeo/security/ui/rap/SecureRapActivator.java
new file mode 100644 (file)
index 0000000..4cbb441
--- /dev/null
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2007-2012 Argeo GmbH
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *         http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.argeo.security.ui.rap;
+
+import java.net.URL;
+
+import org.eclipse.equinox.security.auth.ILoginContext;
+import org.eclipse.equinox.security.auth.LoginContextFactory;
+import org.osgi.framework.BundleActivator;
+import org.osgi.framework.BundleContext;
+
+/** Configure Equinox login context from the bundle context. */
+public class SecureRapActivator implements BundleActivator {
+
+       public final static String ID = "org.argeo.security.ui.rap";
+       public final static String CONTEXT_SPRING = "SPRING";
+       public final static String CONTEXT_SPRING_ANONYMOUS = "SPRING_ANONYMOUS";
+       private static final String JAAS_CONFIG_FILE = "/META-INF/jaas_default.txt";
+
+       private BundleContext bundleContext;
+       private static SecureRapActivator activator = null;
+
+       public void start(BundleContext bundleContext) throws Exception {
+               activator = this;
+               this.bundleContext = bundleContext;
+       }
+
+       public void stop(BundleContext context) throws Exception {
+               bundleContext = null;
+               activator = null;
+       }
+
+       public BundleContext getBundleContext() {
+               return bundleContext;
+       }
+
+       public static SecureRapActivator getActivator() {
+               return activator;
+       }
+
+       static ILoginContext createLoginContext(String contextName) {
+               URL configUrl = getActivator().getBundleContext().getBundle()
+                               .getEntry(JAAS_CONFIG_FILE);
+               return LoginContextFactory.createContext(contextName, configUrl);
+       }
+}
diff --git a/org.argeo.security.ui.rap/src/org/argeo/security/ui/rap/commands/UserMenu.java b/org.argeo.security.ui.rap/src/org/argeo/security/ui/rap/commands/UserMenu.java
new file mode 100644 (file)
index 0000000..9867430
--- /dev/null
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2007-2012 Argeo GmbH
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *         http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.argeo.security.ui.rap.commands;
+
+import org.eclipse.core.commands.AbstractHandler;
+import org.eclipse.core.commands.ExecutionEvent;
+import org.eclipse.core.commands.ExecutionException;
+
+/** Default action of the user menu */
+public class UserMenu extends AbstractHandler {
+
+       @Override
+       public Object execute(ExecutionEvent event) throws ExecutionException {
+               return null;
+       }
+
+}
index 8cf7f48a042a0cc96dfada5bf36efafd90b7b9e4..d2953a684d400476bf716ed6a6c3c3ae486fcd0e 100644 (file)
@@ -1,7 +1,9 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <classpath>
-       <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6"/>
-       <classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
-       <classpathentry kind="src" path="src/main/java"/>
-       <classpathentry kind="output" path="target/classes"/>
+       <classpathentry kind="src" path="src" />
+       <classpathentry kind="con"
+               path="org.eclipse.pde.core.requiredPlugins" />
+       <classpathentry kind="con"
+               path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6" />
+       <classpathentry kind="output" path="bin" />
 </classpath>
diff --git a/org.argeo.security.ui.rcp/src/main/java/org/argeo/security/ui/rcp/AbstractSecureApplication.java b/org.argeo.security.ui.rcp/src/main/java/org/argeo/security/ui/rcp/AbstractSecureApplication.java
deleted file mode 100644 (file)
index 75184cb..0000000
+++ /dev/null
@@ -1,166 +0,0 @@
-/*
- * Copyright (C) 2007-2012 Argeo GmbH
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *         http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.argeo.security.ui.rcp;
-
-import java.security.PrivilegedAction;
-
-import javax.security.auth.Subject;
-import javax.security.auth.login.LoginException;
-
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.argeo.OperatingSystem;
-import org.eclipse.equinox.app.IApplication;
-import org.eclipse.equinox.app.IApplicationContext;
-import org.eclipse.equinox.security.auth.ILoginContext;
-import org.eclipse.swt.widgets.Display;
-import org.eclipse.ui.IWorkbench;
-import org.eclipse.ui.PlatformUI;
-import org.eclipse.ui.application.WorkbenchAdvisor;
-
-/**
- * RCP workbench initialization
- */
-public abstract class AbstractSecureApplication implements IApplication {
-       final static String NODE_REPO_URI = "argeo.node.repo.uri";
-
-       private static final Log log = LogFactory
-                       .getLog(AbstractSecureApplication.class);
-
-       protected WorkbenchAdvisor createWorkbenchAdvisor(String username) {
-               return new SecureWorkbenchAdvisor(username);
-       }
-
-       public Object start(IApplicationContext context) throws Exception {
-               // wait for the system to be initialized
-               // try {
-               // Thread.sleep(3000);
-               // } catch (Exception e2) {
-               // // silent
-               // }
-
-               boolean remote = System.getProperty(NODE_REPO_URI) != null;
-
-               // choose login context
-               final ILoginContext loginContext;
-               if (remote) {
-                       loginContext = SecureApplicationActivator
-                                       .createLoginContext(SecureApplicationActivator.CONTEXT_REMOTE);
-               } else {
-                       if (OperatingSystem.os == OperatingSystem.WINDOWS)
-                               loginContext = SecureApplicationActivator
-                                               .createLoginContext(SecureApplicationActivator.CONTEXT_WINDOWS);
-                       else
-                               loginContext = SecureApplicationActivator
-                                               .createLoginContext(SecureApplicationActivator.CONTEXT_NIX);
-               }
-
-               final Display display = PlatformUI.createDisplay();
-
-               // login
-               Subject subject = null;
-               try {
-                       loginContext.login();
-                       subject = loginContext.getSubject();
-               } catch (LoginException e) {
-                       log.error("Error when logging in.", e);
-                       display.dispose();
-                       try {
-                               Thread.sleep(2000);
-                       } catch (InterruptedException e1) {
-                               // silent
-                       }
-                       return null;
-               }
-
-               // identify after successful login
-               if (log.isDebugEnabled())
-                       log.debug("subject=" + subject);
-               final String username = subject.getPrincipals().iterator().next()
-                               .getName();
-               if (log.isDebugEnabled())
-                       log.debug(username + " logged in");
-//             display.disposeExec(new Runnable() {
-//                     public void run() {
-//                             log.debug("Display disposed");
-//                             logout(loginContext, username);
-//                     }
-//             });
-
-               try {
-                       PrivilegedAction<?> privilegedAction = new PrivilegedAction<Object>() {
-                               public Object run() {
-                                       int result = PlatformUI.createAndRunWorkbench(display,
-                                                       createWorkbenchAdvisor(username));
-                                       return new Integer(result);
-                               }
-                       };
-
-                       Integer returnCode = (Integer) Subject.doAs(subject,
-                                       privilegedAction);
-                       logout(loginContext, username);
-                       return processReturnCode(returnCode);
-               } catch (Exception e) {
-                       if (subject != null)
-                               logout(loginContext, username);
-                       log.error("Unexpected error", e);
-               } finally {
-                       display.dispose();
-               }
-               return null;
-       }
-
-       protected Integer processReturnCode(Integer returnCode) {
-               if (returnCode == PlatformUI.RETURN_RESTART)
-                       return IApplication.EXIT_RESTART;
-               else
-                       return IApplication.EXIT_OK;
-       }
-
-       static void logout(ILoginContext secureContext, String username) {
-               try {
-                       secureContext.logout();
-                       log.info("Logged out " + (username != null ? username : "")
-                                       + " (THREAD=" + Thread.currentThread().getId() + ")");
-               } catch (LoginException e) {
-                       log.error("Erorr when logging out", e);
-               }
-       }
-
-       public void stop() {
-               final IWorkbench workbench;
-               try {
-                       workbench = PlatformUI.getWorkbench();
-               } catch (Exception e) {
-                       return;
-               }
-               if (workbench == null)
-                       return;
-               final Display display = workbench.getDisplay();
-               if (display != null && !display.isDisposed())
-                       display.syncExec(new Runnable() {
-
-                               public void run() {
-                                       if (!display.isDisposed())
-                                               workbench.close();
-                               }
-                       });
-
-               if (log.isDebugEnabled())
-                       log.debug("workbench stopped");
-       }
-
-}
diff --git a/org.argeo.security.ui.rcp/src/main/java/org/argeo/security/ui/rcp/SecureActionBarAdvisor.java b/org.argeo.security.ui.rcp/src/main/java/org/argeo/security/ui/rcp/SecureActionBarAdvisor.java
deleted file mode 100644 (file)
index 481865b..0000000
+++ /dev/null
@@ -1,113 +0,0 @@
-/*
- * Copyright (C) 2007-2012 Argeo GmbH
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *         http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.argeo.security.ui.rcp;
-
-import org.eclipse.jface.action.GroupMarker;
-import org.eclipse.jface.action.ICoolBarManager;
-import org.eclipse.jface.action.IMenuManager;
-import org.eclipse.jface.action.IToolBarManager;
-import org.eclipse.jface.action.MenuManager;
-import org.eclipse.jface.action.Separator;
-import org.eclipse.jface.action.ToolBarManager;
-import org.eclipse.swt.SWT;
-import org.eclipse.ui.IWorkbenchActionConstants;
-import org.eclipse.ui.IWorkbenchWindow;
-import org.eclipse.ui.actions.ActionFactory;
-import org.eclipse.ui.actions.ActionFactory.IWorkbenchAction;
-import org.eclipse.ui.application.ActionBarAdvisor;
-import org.eclipse.ui.application.IActionBarConfigurer;
-
-public class SecureActionBarAdvisor extends ActionBarAdvisor {
-       private IWorkbenchAction exitAction;
-       private IWorkbenchAction openPerspectiveDialogAction;
-       private IWorkbenchAction showViewMenuAction;
-       private IWorkbenchAction preferences;
-       private IWorkbenchAction saveAction;
-       private IWorkbenchAction saveAsAction;
-       private IWorkbenchAction saveAllAction;
-       private IWorkbenchAction closeAllAction;
-
-       // private final Boolean isRcp;
-
-       public SecureActionBarAdvisor(IActionBarConfigurer configurer, Boolean isRcp) {
-               super(configurer);
-               // this.isRcp = isRcp;
-       }
-
-       protected void makeActions(IWorkbenchWindow window) {
-               preferences = ActionFactory.PREFERENCES.create(window);
-               register(preferences);
-               openPerspectiveDialogAction = ActionFactory.OPEN_PERSPECTIVE_DIALOG
-                               .create(window);
-               register(openPerspectiveDialogAction);
-               showViewMenuAction = ActionFactory.SHOW_VIEW_MENU.create(window);
-               register(showViewMenuAction);
-
-               exitAction = ActionFactory.QUIT.create(window);
-               register(exitAction);
-
-               // Save semantiocs
-               saveAction = ActionFactory.SAVE.create(window);
-               register(saveAction);
-               saveAsAction = ActionFactory.SAVE_AS.create(window);
-               register(saveAsAction);
-               saveAllAction = ActionFactory.SAVE_ALL.create(window);
-               register(saveAllAction);
-               closeAllAction = ActionFactory.CLOSE_ALL.create(window);
-               register(closeAllAction);
-
-       }
-
-       protected void fillMenuBar(IMenuManager menuBar) {
-               MenuManager fileMenu = new MenuManager("&File",
-                               IWorkbenchActionConstants.M_FILE);
-               MenuManager editMenu = new MenuManager("&Edit",
-                               IWorkbenchActionConstants.M_EDIT);
-               MenuManager windowMenu = new MenuManager("&Window",
-                               IWorkbenchActionConstants.M_WINDOW);
-
-               menuBar.add(fileMenu);
-               menuBar.add(editMenu);
-               menuBar.add(windowMenu);
-               // Add a group marker indicating where action set menus will appear.
-               menuBar.add(new GroupMarker(IWorkbenchActionConstants.MB_ADDITIONS));
-
-               // File
-               fileMenu.add(saveAction);
-               fileMenu.add(saveAsAction);
-               fileMenu.add(saveAllAction);
-               fileMenu.add(closeAllAction);
-               fileMenu.add(new GroupMarker(IWorkbenchActionConstants.MB_ADDITIONS));
-               fileMenu.add(new Separator());
-               fileMenu.add(exitAction);
-
-               // Edit
-               editMenu.add(preferences);
-
-               // Window
-               windowMenu.add(openPerspectiveDialogAction);
-               windowMenu.add(showViewMenuAction);
-       }
-
-       @Override
-       protected void fillCoolBar(ICoolBarManager coolBar) {
-               IToolBarManager saveToolbar = new ToolBarManager(SWT.FLAT | SWT.RIGHT);
-               saveToolbar.add(saveAction);
-               saveToolbar.add(saveAllAction);
-               coolBar.add(saveToolbar);
-       }
-
-}
diff --git a/org.argeo.security.ui.rcp/src/main/java/org/argeo/security/ui/rcp/SecureApplicationActivator.java b/org.argeo.security.ui.rcp/src/main/java/org/argeo/security/ui/rcp/SecureApplicationActivator.java
deleted file mode 100644 (file)
index 9c0425c..0000000
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * Copyright (C) 2007-2012 Argeo GmbH
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *         http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.argeo.security.ui.rcp;
-
-import java.net.URL;
-
-import org.eclipse.equinox.security.auth.ILoginContext;
-import org.eclipse.equinox.security.auth.LoginContextFactory;
-import org.osgi.framework.BundleActivator;
-import org.osgi.framework.BundleContext;
-
-/** Activator able to create {@link ILoginContext} */
-public class SecureApplicationActivator implements BundleActivator {
-
-       public final static String CONTEXT_REMOTE = "REMOTE";
-       public final static String CONTEXT_NIX = "NIX";
-       public final static String CONTEXT_WINDOWS = "WINDOWS";
-       private static final String JAAS_CONFIG_FILE = "/META-INF/jaas_default.txt";
-
-       private static BundleContext bundleContext;
-
-       public void start(BundleContext bundleContext) throws Exception {
-               SecureApplicationActivator.bundleContext = bundleContext;
-       }
-
-       public void stop(BundleContext context) throws Exception {
-       }
-
-       static ILoginContext createLoginContext(String context) {
-               URL configUrl = bundleContext.getBundle().getEntry(JAAS_CONFIG_FILE);
-               return LoginContextFactory.createContext(context, configUrl);
-       }
-}
diff --git a/org.argeo.security.ui.rcp/src/main/java/org/argeo/security/ui/rcp/SecureRcp.java b/org.argeo.security.ui.rcp/src/main/java/org/argeo/security/ui/rcp/SecureRcp.java
deleted file mode 100644 (file)
index d8125cf..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
- * Copyright (C) 2007-2012 Argeo GmbH
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *         http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.argeo.security.ui.rcp;
-
-
-public class SecureRcp extends AbstractSecureApplication {
-}
diff --git a/org.argeo.security.ui.rcp/src/main/java/org/argeo/security/ui/rcp/SecureWorkbenchAdvisor.java b/org.argeo.security.ui.rcp/src/main/java/org/argeo/security/ui/rcp/SecureWorkbenchAdvisor.java
deleted file mode 100644 (file)
index 33b781e..0000000
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
- * Copyright (C) 2007-2012 Argeo GmbH
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *         http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.argeo.security.ui.rcp;
-
-import org.eclipse.ui.IPerspectiveDescriptor;
-import org.eclipse.ui.application.IWorkbenchConfigurer;
-import org.eclipse.ui.application.IWorkbenchWindowConfigurer;
-import org.eclipse.ui.application.WorkbenchAdvisor;
-import org.eclipse.ui.application.WorkbenchWindowAdvisor;
-
-/**
- * Workbench configuration which is aware of the logged in user and can remember
- * workbench state.
- */
-public class SecureWorkbenchAdvisor extends WorkbenchAdvisor {
-       public final static String INITIAL_PERSPECTIVE_PROPERTY = "org.argeo.security.ui.initialPerspective";
-       public final static String SAVE_AND_RESTORE_PROPERTY = "org.argeo.security.ui.saveAndRestore";
-
-       private String initialPerspective = System.getProperty(
-                       INITIAL_PERSPECTIVE_PROPERTY, null);
-
-       private final String username;
-
-       public SecureWorkbenchAdvisor(String username) {
-               this.username = username;
-       }
-
-       @Override
-       public void initialize(final IWorkbenchConfigurer configurer) {
-               super.initialize(configurer);
-               Boolean saveAndRestore = Boolean.parseBoolean(System.getProperty(
-                               SAVE_AND_RESTORE_PROPERTY, "true"));
-               configurer.setSaveAndRestore(saveAndRestore);
-       }
-
-       public WorkbenchWindowAdvisor createWorkbenchWindowAdvisor(
-                       IWorkbenchWindowConfigurer configurer) {
-               return new SecureWorkbenchWindowAdvisor(configurer, username);
-       }
-
-       public String getInitialWindowPerspectiveId() {
-               if (initialPerspective != null) {
-                       // check whether this user can see the declared perspective
-                       // (typically the perspective won't be listed if this user doesn't
-                       // have the right to see it)
-                       IPerspectiveDescriptor pd = getWorkbenchConfigurer().getWorkbench()
-                                       .getPerspectiveRegistry()
-                                       .findPerspectiveWithId(initialPerspective);
-                       if (pd == null)
-                               return null;
-               }
-               return initialPerspective;
-       }
-
-       protected String getUsername() {
-               return username;
-       }
-}
diff --git a/org.argeo.security.ui.rcp/src/main/java/org/argeo/security/ui/rcp/SecureWorkbenchWindowAdvisor.java b/org.argeo.security.ui.rcp/src/main/java/org/argeo/security/ui/rcp/SecureWorkbenchWindowAdvisor.java
deleted file mode 100644 (file)
index d8aaec4..0000000
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * Copyright (C) 2007-2012 Argeo GmbH
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *         http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.argeo.security.ui.rcp;
-
-import org.eclipse.swt.graphics.Point;
-import org.eclipse.ui.application.ActionBarAdvisor;
-import org.eclipse.ui.application.IActionBarConfigurer;
-import org.eclipse.ui.application.IWorkbenchWindowConfigurer;
-import org.eclipse.ui.application.WorkbenchWindowAdvisor;
-
-public class SecureWorkbenchWindowAdvisor extends WorkbenchWindowAdvisor {
-       private final String username;
-
-       public SecureWorkbenchWindowAdvisor(IWorkbenchWindowConfigurer configurer,
-                       String username) {
-               super(configurer);
-               this.username = username;
-       }
-
-       public ActionBarAdvisor createActionBarAdvisor(
-                       IActionBarConfigurer configurer) {
-               return new SecureActionBarAdvisor(configurer, true);
-       }
-
-       public void preWindowOpen() {
-               IWorkbenchWindowConfigurer configurer = getWindowConfigurer();
-               configurer.setInitialSize(new Point(1200, 900));
-               configurer.setShowCoolBar(true);
-               configurer.setShowMenuBar(true);
-               configurer.setShowStatusLine(true);
-               configurer.setShowProgressIndicator(true);
-
-               configurer.setShowPerspectiveBar(true);
-               String remoteUri = System
-                               .getProperty(AbstractSecureApplication.NODE_REPO_URI);
-               if (remoteUri != null)
-                       configurer
-                                       .setTitle("Argeo UI - " + username + " (" + remoteUri + ")"); //$NON-NLS-1$
-               else
-                       configurer.setTitle("Argeo UI - " + username); //$NON-NLS-1$
-
-       }
-}
diff --git a/org.argeo.security.ui.rcp/src/org/argeo/security/ui/rcp/AbstractSecureApplication.java b/org.argeo.security.ui.rcp/src/org/argeo/security/ui/rcp/AbstractSecureApplication.java
new file mode 100644 (file)
index 0000000..75184cb
--- /dev/null
@@ -0,0 +1,166 @@
+/*
+ * Copyright (C) 2007-2012 Argeo GmbH
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *         http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.argeo.security.ui.rcp;
+
+import java.security.PrivilegedAction;
+
+import javax.security.auth.Subject;
+import javax.security.auth.login.LoginException;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.argeo.OperatingSystem;
+import org.eclipse.equinox.app.IApplication;
+import org.eclipse.equinox.app.IApplicationContext;
+import org.eclipse.equinox.security.auth.ILoginContext;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.ui.IWorkbench;
+import org.eclipse.ui.PlatformUI;
+import org.eclipse.ui.application.WorkbenchAdvisor;
+
+/**
+ * RCP workbench initialization
+ */
+public abstract class AbstractSecureApplication implements IApplication {
+       final static String NODE_REPO_URI = "argeo.node.repo.uri";
+
+       private static final Log log = LogFactory
+                       .getLog(AbstractSecureApplication.class);
+
+       protected WorkbenchAdvisor createWorkbenchAdvisor(String username) {
+               return new SecureWorkbenchAdvisor(username);
+       }
+
+       public Object start(IApplicationContext context) throws Exception {
+               // wait for the system to be initialized
+               // try {
+               // Thread.sleep(3000);
+               // } catch (Exception e2) {
+               // // silent
+               // }
+
+               boolean remote = System.getProperty(NODE_REPO_URI) != null;
+
+               // choose login context
+               final ILoginContext loginContext;
+               if (remote) {
+                       loginContext = SecureApplicationActivator
+                                       .createLoginContext(SecureApplicationActivator.CONTEXT_REMOTE);
+               } else {
+                       if (OperatingSystem.os == OperatingSystem.WINDOWS)
+                               loginContext = SecureApplicationActivator
+                                               .createLoginContext(SecureApplicationActivator.CONTEXT_WINDOWS);
+                       else
+                               loginContext = SecureApplicationActivator
+                                               .createLoginContext(SecureApplicationActivator.CONTEXT_NIX);
+               }
+
+               final Display display = PlatformUI.createDisplay();
+
+               // login
+               Subject subject = null;
+               try {
+                       loginContext.login();
+                       subject = loginContext.getSubject();
+               } catch (LoginException e) {
+                       log.error("Error when logging in.", e);
+                       display.dispose();
+                       try {
+                               Thread.sleep(2000);
+                       } catch (InterruptedException e1) {
+                               // silent
+                       }
+                       return null;
+               }
+
+               // identify after successful login
+               if (log.isDebugEnabled())
+                       log.debug("subject=" + subject);
+               final String username = subject.getPrincipals().iterator().next()
+                               .getName();
+               if (log.isDebugEnabled())
+                       log.debug(username + " logged in");
+//             display.disposeExec(new Runnable() {
+//                     public void run() {
+//                             log.debug("Display disposed");
+//                             logout(loginContext, username);
+//                     }
+//             });
+
+               try {
+                       PrivilegedAction<?> privilegedAction = new PrivilegedAction<Object>() {
+                               public Object run() {
+                                       int result = PlatformUI.createAndRunWorkbench(display,
+                                                       createWorkbenchAdvisor(username));
+                                       return new Integer(result);
+                               }
+                       };
+
+                       Integer returnCode = (Integer) Subject.doAs(subject,
+                                       privilegedAction);
+                       logout(loginContext, username);
+                       return processReturnCode(returnCode);
+               } catch (Exception e) {
+                       if (subject != null)
+                               logout(loginContext, username);
+                       log.error("Unexpected error", e);
+               } finally {
+                       display.dispose();
+               }
+               return null;
+       }
+
+       protected Integer processReturnCode(Integer returnCode) {
+               if (returnCode == PlatformUI.RETURN_RESTART)
+                       return IApplication.EXIT_RESTART;
+               else
+                       return IApplication.EXIT_OK;
+       }
+
+       static void logout(ILoginContext secureContext, String username) {
+               try {
+                       secureContext.logout();
+                       log.info("Logged out " + (username != null ? username : "")
+                                       + " (THREAD=" + Thread.currentThread().getId() + ")");
+               } catch (LoginException e) {
+                       log.error("Erorr when logging out", e);
+               }
+       }
+
+       public void stop() {
+               final IWorkbench workbench;
+               try {
+                       workbench = PlatformUI.getWorkbench();
+               } catch (Exception e) {
+                       return;
+               }
+               if (workbench == null)
+                       return;
+               final Display display = workbench.getDisplay();
+               if (display != null && !display.isDisposed())
+                       display.syncExec(new Runnable() {
+
+                               public void run() {
+                                       if (!display.isDisposed())
+                                               workbench.close();
+                               }
+                       });
+
+               if (log.isDebugEnabled())
+                       log.debug("workbench stopped");
+       }
+
+}
diff --git a/org.argeo.security.ui.rcp/src/org/argeo/security/ui/rcp/SecureActionBarAdvisor.java b/org.argeo.security.ui.rcp/src/org/argeo/security/ui/rcp/SecureActionBarAdvisor.java
new file mode 100644 (file)
index 0000000..481865b
--- /dev/null
@@ -0,0 +1,113 @@
+/*
+ * Copyright (C) 2007-2012 Argeo GmbH
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *         http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.argeo.security.ui.rcp;
+
+import org.eclipse.jface.action.GroupMarker;
+import org.eclipse.jface.action.ICoolBarManager;
+import org.eclipse.jface.action.IMenuManager;
+import org.eclipse.jface.action.IToolBarManager;
+import org.eclipse.jface.action.MenuManager;
+import org.eclipse.jface.action.Separator;
+import org.eclipse.jface.action.ToolBarManager;
+import org.eclipse.swt.SWT;
+import org.eclipse.ui.IWorkbenchActionConstants;
+import org.eclipse.ui.IWorkbenchWindow;
+import org.eclipse.ui.actions.ActionFactory;
+import org.eclipse.ui.actions.ActionFactory.IWorkbenchAction;
+import org.eclipse.ui.application.ActionBarAdvisor;
+import org.eclipse.ui.application.IActionBarConfigurer;
+
+public class SecureActionBarAdvisor extends ActionBarAdvisor {
+       private IWorkbenchAction exitAction;
+       private IWorkbenchAction openPerspectiveDialogAction;
+       private IWorkbenchAction showViewMenuAction;
+       private IWorkbenchAction preferences;
+       private IWorkbenchAction saveAction;
+       private IWorkbenchAction saveAsAction;
+       private IWorkbenchAction saveAllAction;
+       private IWorkbenchAction closeAllAction;
+
+       // private final Boolean isRcp;
+
+       public SecureActionBarAdvisor(IActionBarConfigurer configurer, Boolean isRcp) {
+               super(configurer);
+               // this.isRcp = isRcp;
+       }
+
+       protected void makeActions(IWorkbenchWindow window) {
+               preferences = ActionFactory.PREFERENCES.create(window);
+               register(preferences);
+               openPerspectiveDialogAction = ActionFactory.OPEN_PERSPECTIVE_DIALOG
+                               .create(window);
+               register(openPerspectiveDialogAction);
+               showViewMenuAction = ActionFactory.SHOW_VIEW_MENU.create(window);
+               register(showViewMenuAction);
+
+               exitAction = ActionFactory.QUIT.create(window);
+               register(exitAction);
+
+               // Save semantiocs
+               saveAction = ActionFactory.SAVE.create(window);
+               register(saveAction);
+               saveAsAction = ActionFactory.SAVE_AS.create(window);
+               register(saveAsAction);
+               saveAllAction = ActionFactory.SAVE_ALL.create(window);
+               register(saveAllAction);
+               closeAllAction = ActionFactory.CLOSE_ALL.create(window);
+               register(closeAllAction);
+
+       }
+
+       protected void fillMenuBar(IMenuManager menuBar) {
+               MenuManager fileMenu = new MenuManager("&File",
+                               IWorkbenchActionConstants.M_FILE);
+               MenuManager editMenu = new MenuManager("&Edit",
+                               IWorkbenchActionConstants.M_EDIT);
+               MenuManager windowMenu = new MenuManager("&Window",
+                               IWorkbenchActionConstants.M_WINDOW);
+
+               menuBar.add(fileMenu);
+               menuBar.add(editMenu);
+               menuBar.add(windowMenu);
+               // Add a group marker indicating where action set menus will appear.
+               menuBar.add(new GroupMarker(IWorkbenchActionConstants.MB_ADDITIONS));
+
+               // File
+               fileMenu.add(saveAction);
+               fileMenu.add(saveAsAction);
+               fileMenu.add(saveAllAction);
+               fileMenu.add(closeAllAction);
+               fileMenu.add(new GroupMarker(IWorkbenchActionConstants.MB_ADDITIONS));
+               fileMenu.add(new Separator());
+               fileMenu.add(exitAction);
+
+               // Edit
+               editMenu.add(preferences);
+
+               // Window
+               windowMenu.add(openPerspectiveDialogAction);
+               windowMenu.add(showViewMenuAction);
+       }
+
+       @Override
+       protected void fillCoolBar(ICoolBarManager coolBar) {
+               IToolBarManager saveToolbar = new ToolBarManager(SWT.FLAT | SWT.RIGHT);
+               saveToolbar.add(saveAction);
+               saveToolbar.add(saveAllAction);
+               coolBar.add(saveToolbar);
+       }
+
+}
diff --git a/org.argeo.security.ui.rcp/src/org/argeo/security/ui/rcp/SecureApplicationActivator.java b/org.argeo.security.ui.rcp/src/org/argeo/security/ui/rcp/SecureApplicationActivator.java
new file mode 100644 (file)
index 0000000..9c0425c
--- /dev/null
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2007-2012 Argeo GmbH
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *         http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.argeo.security.ui.rcp;
+
+import java.net.URL;
+
+import org.eclipse.equinox.security.auth.ILoginContext;
+import org.eclipse.equinox.security.auth.LoginContextFactory;
+import org.osgi.framework.BundleActivator;
+import org.osgi.framework.BundleContext;
+
+/** Activator able to create {@link ILoginContext} */
+public class SecureApplicationActivator implements BundleActivator {
+
+       public final static String CONTEXT_REMOTE = "REMOTE";
+       public final static String CONTEXT_NIX = "NIX";
+       public final static String CONTEXT_WINDOWS = "WINDOWS";
+       private static final String JAAS_CONFIG_FILE = "/META-INF/jaas_default.txt";
+
+       private static BundleContext bundleContext;
+
+       public void start(BundleContext bundleContext) throws Exception {
+               SecureApplicationActivator.bundleContext = bundleContext;
+       }
+
+       public void stop(BundleContext context) throws Exception {
+       }
+
+       static ILoginContext createLoginContext(String context) {
+               URL configUrl = bundleContext.getBundle().getEntry(JAAS_CONFIG_FILE);
+               return LoginContextFactory.createContext(context, configUrl);
+       }
+}
diff --git a/org.argeo.security.ui.rcp/src/org/argeo/security/ui/rcp/SecureRcp.java b/org.argeo.security.ui.rcp/src/org/argeo/security/ui/rcp/SecureRcp.java
new file mode 100644 (file)
index 0000000..d8125cf
--- /dev/null
@@ -0,0 +1,20 @@
+/*
+ * Copyright (C) 2007-2012 Argeo GmbH
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *         http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.argeo.security.ui.rcp;
+
+
+public class SecureRcp extends AbstractSecureApplication {
+}
diff --git a/org.argeo.security.ui.rcp/src/org/argeo/security/ui/rcp/SecureWorkbenchAdvisor.java b/org.argeo.security.ui.rcp/src/org/argeo/security/ui/rcp/SecureWorkbenchAdvisor.java
new file mode 100644 (file)
index 0000000..33b781e
--- /dev/null
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2007-2012 Argeo GmbH
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *         http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.argeo.security.ui.rcp;
+
+import org.eclipse.ui.IPerspectiveDescriptor;
+import org.eclipse.ui.application.IWorkbenchConfigurer;
+import org.eclipse.ui.application.IWorkbenchWindowConfigurer;
+import org.eclipse.ui.application.WorkbenchAdvisor;
+import org.eclipse.ui.application.WorkbenchWindowAdvisor;
+
+/**
+ * Workbench configuration which is aware of the logged in user and can remember
+ * workbench state.
+ */
+public class SecureWorkbenchAdvisor extends WorkbenchAdvisor {
+       public final static String INITIAL_PERSPECTIVE_PROPERTY = "org.argeo.security.ui.initialPerspective";
+       public final static String SAVE_AND_RESTORE_PROPERTY = "org.argeo.security.ui.saveAndRestore";
+
+       private String initialPerspective = System.getProperty(
+                       INITIAL_PERSPECTIVE_PROPERTY, null);
+
+       private final String username;
+
+       public SecureWorkbenchAdvisor(String username) {
+               this.username = username;
+       }
+
+       @Override
+       public void initialize(final IWorkbenchConfigurer configurer) {
+               super.initialize(configurer);
+               Boolean saveAndRestore = Boolean.parseBoolean(System.getProperty(
+                               SAVE_AND_RESTORE_PROPERTY, "true"));
+               configurer.setSaveAndRestore(saveAndRestore);
+       }
+
+       public WorkbenchWindowAdvisor createWorkbenchWindowAdvisor(
+                       IWorkbenchWindowConfigurer configurer) {
+               return new SecureWorkbenchWindowAdvisor(configurer, username);
+       }
+
+       public String getInitialWindowPerspectiveId() {
+               if (initialPerspective != null) {
+                       // check whether this user can see the declared perspective
+                       // (typically the perspective won't be listed if this user doesn't
+                       // have the right to see it)
+                       IPerspectiveDescriptor pd = getWorkbenchConfigurer().getWorkbench()
+                                       .getPerspectiveRegistry()
+                                       .findPerspectiveWithId(initialPerspective);
+                       if (pd == null)
+                               return null;
+               }
+               return initialPerspective;
+       }
+
+       protected String getUsername() {
+               return username;
+       }
+}
diff --git a/org.argeo.security.ui.rcp/src/org/argeo/security/ui/rcp/SecureWorkbenchWindowAdvisor.java b/org.argeo.security.ui.rcp/src/org/argeo/security/ui/rcp/SecureWorkbenchWindowAdvisor.java
new file mode 100644 (file)
index 0000000..d8aaec4
--- /dev/null
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2007-2012 Argeo GmbH
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *         http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.argeo.security.ui.rcp;
+
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.ui.application.ActionBarAdvisor;
+import org.eclipse.ui.application.IActionBarConfigurer;
+import org.eclipse.ui.application.IWorkbenchWindowConfigurer;
+import org.eclipse.ui.application.WorkbenchWindowAdvisor;
+
+public class SecureWorkbenchWindowAdvisor extends WorkbenchWindowAdvisor {
+       private final String username;
+
+       public SecureWorkbenchWindowAdvisor(IWorkbenchWindowConfigurer configurer,
+                       String username) {
+               super(configurer);
+               this.username = username;
+       }
+
+       public ActionBarAdvisor createActionBarAdvisor(
+                       IActionBarConfigurer configurer) {
+               return new SecureActionBarAdvisor(configurer, true);
+       }
+
+       public void preWindowOpen() {
+               IWorkbenchWindowConfigurer configurer = getWindowConfigurer();
+               configurer.setInitialSize(new Point(1200, 900));
+               configurer.setShowCoolBar(true);
+               configurer.setShowMenuBar(true);
+               configurer.setShowStatusLine(true);
+               configurer.setShowProgressIndicator(true);
+
+               configurer.setShowPerspectiveBar(true);
+               String remoteUri = System
+                               .getProperty(AbstractSecureApplication.NODE_REPO_URI);
+               if (remoteUri != null)
+                       configurer
+                                       .setTitle("Argeo UI - " + username + " (" + remoteUri + ")"); //$NON-NLS-1$
+               else
+                       configurer.setTitle("Argeo UI - " + username); //$NON-NLS-1$
+
+       }
+}
index 5641c7ca39f6826ec4ff5af926bfd34f528f3684..d2953a684d400476bf716ed6a6c3c3ae486fcd0e 100644 (file)
@@ -1,7 +1,9 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <classpath>
-       <classpathentry kind="src" path="src/main/java"/>
-       <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6"/>>>
-       <classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
-       <classpathentry kind="output" path="target/classes"/>
+       <classpathentry kind="src" path="src" />
+       <classpathentry kind="con"
+               path="org.eclipse.pde.core.requiredPlugins" />
+       <classpathentry kind="con"
+               path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6" />
+       <classpathentry kind="output" path="bin" />
 </classpath>
index 3868784bf842eed7f55ac6da0a547f19794556f1..30f715358d984db427238bb1984c0d19b6ca4004 100644 (file)
@@ -1,6 +1 @@
-source.. = src/main/java/
-output.. = target/classes/
-bin.includes = META-INF/,\
-               .,\
-               plugin.xml,\
-               icons/
+source.. = src/
diff --git a/org.argeo.security.ui/src/main/java/org/argeo/security/ui/MaintenancePerspective.java b/org.argeo.security.ui/src/main/java/org/argeo/security/ui/MaintenancePerspective.java
deleted file mode 100644 (file)
index 86307ab..0000000
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * Copyright (C) 2007-2012 Argeo GmbH
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *         http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.argeo.security.ui;
-
-import org.argeo.security.ui.views.AdminLogView;
-import org.argeo.security.ui.views.UserProfile;
-import org.eclipse.ui.IFolderLayout;
-import org.eclipse.ui.IPageLayout;
-import org.eclipse.ui.IPerspectiveFactory;
-
-/** Home perspective for the current user */
-public class MaintenancePerspective implements IPerspectiveFactory {
-       public final static String ID = SecurityUiPlugin.PLUGIN_ID
-                       + ".adminMaintenancePerspective";
-
-       public void createInitialLayout(IPageLayout layout) {
-               String editorArea = layout.getEditorArea();
-               layout.setEditorAreaVisible(true);
-               layout.setFixed(false);
-
-               IFolderLayout bottom = layout.createFolder("bottom",
-                               IPageLayout.BOTTOM, 0.50f, editorArea);
-               bottom.addView(AdminLogView.ID);
-
-               IFolderLayout left = layout.createFolder("left", IPageLayout.LEFT,
-                               0.30f, editorArea);
-               left.addView(UserProfile.ID);
-               // left.addView(RolesView.ID);
-
-       }
-
-}
diff --git a/org.argeo.security.ui/src/main/java/org/argeo/security/ui/PrivilegedJob.java b/org.argeo.security.ui/src/main/java/org/argeo/security/ui/PrivilegedJob.java
deleted file mode 100644 (file)
index 1ded50f..0000000
+++ /dev/null
@@ -1,46 +0,0 @@
-package org.argeo.security.ui;
-
-import java.security.AccessController;
-import java.security.PrivilegedAction;
-
-import javax.security.auth.Subject;
-
-import org.eclipse.core.runtime.IProgressMonitor;
-import org.eclipse.core.runtime.IStatus;
-import org.eclipse.core.runtime.jobs.Job;
-import org.springframework.security.Authentication;
-import org.springframework.security.context.SecurityContextHolder;
-
-/**
- * Propagate authentication to an eclipse job. Typically to execute a privileged
- * action outside the UI thread
- */
-public abstract class PrivilegedJob extends Job {
-
-       private final Authentication authentication;
-       private Subject subject;
-
-       public PrivilegedJob(String jobName) {
-               super(jobName);
-               authentication = SecurityContextHolder.getContext().getAuthentication();
-               subject = Subject.getSubject(AccessController.getContext());
-       }
-
-       @Override
-       protected IStatus run(final IProgressMonitor progressMonitor) {
-               PrivilegedAction<IStatus> privilegedAction = new PrivilegedAction<IStatus>() {
-                       public IStatus run() {
-                               SecurityContextHolder.getContext().setAuthentication(
-                                               authentication);
-                               return doRun(progressMonitor);
-                       }
-               };
-               return Subject.doAs(subject, privilegedAction);
-       }
-
-       /**
-        * Implement here what should be executed with default context
-        * authentication
-        */
-       protected abstract IStatus doRun(IProgressMonitor progressMonitor);
-}
\ No newline at end of file
diff --git a/org.argeo.security.ui/src/main/java/org/argeo/security/ui/RolesSourceProvider.java b/org.argeo.security.ui/src/main/java/org/argeo/security/ui/RolesSourceProvider.java
deleted file mode 100644 (file)
index a81dc20..0000000
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * Copyright (C) 2007-2012 Argeo GmbH
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *         http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.argeo.security.ui;
-
-import java.util.HashMap;
-import java.util.Map;
-import java.util.Set;
-
-import org.argeo.security.ui.internal.CurrentUser;
-import org.eclipse.ui.AbstractSourceProvider;
-
-/**
- * Provides the roles of the current user as a variable to be used for activity
- * binding
- */
-public class RolesSourceProvider extends AbstractSourceProvider {
-       public final static String ROLES_VARIABLE = "roles";
-       private final static String[] PROVIDED_SOURCE_NAMES = new String[] { ROLES_VARIABLE };
-
-       public Map<String, Set<String>> getCurrentState() {
-               Map<String, Set<String>> stateMap = new HashMap<String, Set<String>>();
-               stateMap.put(ROLES_VARIABLE, CurrentUser.roles());
-               return stateMap;
-       }
-
-       public String[] getProvidedSourceNames() {
-               return PROVIDED_SOURCE_NAMES;
-       }
-
-       public void updateRoles() {
-               fireSourceChanged(0, getCurrentState());
-       }
-
-       public void dispose() {
-       }
-}
\ No newline at end of file
diff --git a/org.argeo.security.ui/src/main/java/org/argeo/security/ui/SecurityUiPlugin.java b/org.argeo.security.ui/src/main/java/org/argeo/security/ui/SecurityUiPlugin.java
deleted file mode 100644 (file)
index 0358418..0000000
+++ /dev/null
@@ -1,109 +0,0 @@
-/*
- * Copyright (C) 2007-2012 Argeo GmbH
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *         http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.argeo.security.ui;
-
-import java.io.IOException;
-
-import javax.security.auth.callback.Callback;
-import javax.security.auth.callback.CallbackHandler;
-import javax.security.auth.callback.UnsupportedCallbackException;
-
-import org.argeo.ArgeoException;
-import org.argeo.security.ui.dialogs.DefaultLoginDialog;
-import org.eclipse.jface.resource.ImageDescriptor;
-import org.eclipse.swt.widgets.Display;
-import org.eclipse.ui.plugin.AbstractUIPlugin;
-import org.osgi.framework.BundleContext;
-import org.osgi.framework.ServiceRegistration;
-
-/**
- * The activator class controls the plug-in life cycle
- */
-public class SecurityUiPlugin extends AbstractUIPlugin {
-
-       // The plug-in ID
-       public static final String PLUGIN_ID = "org.argeo.security.ui"; //$NON-NLS-1$
-
-       public final static String CONTEXT_KEYRING = "KEYRING";
-
-       private CallbackHandler defaultCallbackHandler;
-       private ServiceRegistration defaultCallbackHandlerReg;
-
-       private static SecurityUiPlugin plugin;
-
-       public static InheritableThreadLocal<Display> display = new InheritableThreadLocal<Display>() {
-
-               @Override
-               protected Display initialValue() {
-                       return Display.getCurrent();
-               }
-       };
-
-       public void start(BundleContext context) throws Exception {
-               super.start(context);
-               plugin = this;
-
-               defaultCallbackHandler = new DefaultCallbackHandler();
-               defaultCallbackHandlerReg = context.registerService(
-                               CallbackHandler.class.getName(), defaultCallbackHandler, null);
-       }
-
-       public void stop(BundleContext context) throws Exception {
-               plugin = null;
-               defaultCallbackHandlerReg.unregister();
-               super.stop(context);
-       }
-
-       /**
-        * Returns the shared instance
-        * 
-        * @return the shared instance
-        */
-       public static SecurityUiPlugin getDefault() {
-               return plugin;
-       }
-
-       public static ImageDescriptor getImageDescriptor(String path) {
-               return imageDescriptorFromPlugin(PLUGIN_ID, path);
-       }
-
-       protected class DefaultCallbackHandler implements CallbackHandler {
-               public void handle(final Callback[] callbacks) throws IOException,
-                               UnsupportedCallbackException {
-
-                       // if (display != null) // RCP
-                       Display displayToUse = display.get();
-                       if (displayToUse == null)// RCP
-                               displayToUse = Display.getDefault();
-                       displayToUse.syncExec(new Runnable() {
-                               public void run() {
-                                       DefaultLoginDialog dialog = new DefaultLoginDialog(display
-                                                       .get().getActiveShell());
-                                       try {
-                                               dialog.handle(callbacks);
-                                       } catch (IOException e) {
-                                               throw new ArgeoException("Cannot open dialog", e);
-                                       }
-                               }
-                       });
-                       // else {// RAP
-                       // DefaultLoginDialog dialog = new DefaultLoginDialog();
-                       // dialog.handle(callbacks);
-                       // }
-               }
-
-       }
-}
diff --git a/org.argeo.security.ui/src/main/java/org/argeo/security/ui/UserHomePerspective.java b/org.argeo.security.ui/src/main/java/org/argeo/security/ui/UserHomePerspective.java
deleted file mode 100644 (file)
index 119549f..0000000
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * Copyright (C) 2007-2012 Argeo GmbH
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *         http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.argeo.security.ui;
-
-import org.argeo.security.ui.views.LogView;
-import org.argeo.security.ui.views.UserProfile;
-import org.eclipse.ui.IFolderLayout;
-import org.eclipse.ui.IPageLayout;
-import org.eclipse.ui.IPerspectiveFactory;
-
-/** Home perspective for the current user */
-public class UserHomePerspective implements IPerspectiveFactory {
-       public final static String ID = SecurityUiPlugin.PLUGIN_ID
-                       + ".userHomePerspective";
-
-       public void createInitialLayout(IPageLayout layout) {
-               String editorArea = layout.getEditorArea();
-               layout.setEditorAreaVisible(true);
-               layout.setFixed(false);
-
-               IFolderLayout left = layout.createFolder("left", IPageLayout.LEFT,
-                               0.30f, editorArea);
-               left.addView(UserProfile.ID);
-               left.addView(LogView.ID);
-       }
-
-}
diff --git a/org.argeo.security.ui/src/main/java/org/argeo/security/ui/commands/OpenChangePasswordDialog.java b/org.argeo.security.ui/src/main/java/org/argeo/security/ui/commands/OpenChangePasswordDialog.java
deleted file mode 100644 (file)
index 3044e2c..0000000
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * Copyright (C) 2007-2012 Argeo GmbH
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *         http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.argeo.security.ui.commands;
-
-import org.argeo.security.ui.dialogs.ChangePasswordDialog;
-import org.eclipse.core.commands.AbstractHandler;
-import org.eclipse.core.commands.ExecutionEvent;
-import org.eclipse.core.commands.ExecutionException;
-import org.eclipse.jface.dialogs.Dialog;
-import org.eclipse.jface.dialogs.MessageDialog;
-import org.eclipse.ui.handlers.HandlerUtil;
-import org.springframework.security.userdetails.UserDetailsManager;
-
-/** Opens the change password dialog. */
-public class OpenChangePasswordDialog extends AbstractHandler {
-       private UserDetailsManager userDetailsManager;
-
-       public Object execute(ExecutionEvent event) throws ExecutionException {
-               ChangePasswordDialog dialog = new ChangePasswordDialog(
-                               HandlerUtil.getActiveShell(event), userDetailsManager);
-               if (dialog.open() == Dialog.OK) {
-                       MessageDialog.openInformation(HandlerUtil.getActiveShell(event),
-                                       "Password changed", "Password changed.");
-               }
-               return null;
-       }
-
-       public void setUserDetailsManager(UserDetailsManager userDetailsManager) {
-               this.userDetailsManager = userDetailsManager;
-       }
-
-}
diff --git a/org.argeo.security.ui/src/main/java/org/argeo/security/ui/commands/OpenHomePerspective.java b/org.argeo.security.ui/src/main/java/org/argeo/security/ui/commands/OpenHomePerspective.java
deleted file mode 100644 (file)
index d56498a..0000000
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * Copyright (C) 2007-2012 Argeo GmbH
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *         http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.argeo.security.ui.commands;
-
-import org.argeo.eclipse.ui.ErrorFeedback;
-import org.argeo.security.ui.UserHomePerspective;
-import org.eclipse.core.commands.AbstractHandler;
-import org.eclipse.core.commands.ExecutionEvent;
-import org.eclipse.core.commands.ExecutionException;
-import org.eclipse.ui.WorkbenchException;
-import org.eclipse.ui.handlers.HandlerUtil;
-
-/** Default action of the user menu */
-public class OpenHomePerspective extends AbstractHandler {
-
-       public Object execute(ExecutionEvent event) throws ExecutionException {
-               try {
-                       HandlerUtil.getActiveSite(event).getWorkbenchWindow()
-                                       .openPage(UserHomePerspective.ID, null);
-               } catch (WorkbenchException e) {
-                       ErrorFeedback.show("Cannot open home perspective", e);
-               }
-               return null;
-       }
-
-}
diff --git a/org.argeo.security.ui/src/main/java/org/argeo/security/ui/dialogs/AbstractLoginDialog.java b/org.argeo.security.ui/src/main/java/org/argeo/security/ui/dialogs/AbstractLoginDialog.java
deleted file mode 100644 (file)
index 7c7e0c6..0000000
+++ /dev/null
@@ -1,191 +0,0 @@
-/*
- * Copyright (C) 2007-2012 Argeo GmbH
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *         http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.argeo.security.ui.dialogs;
-
-import java.io.IOException;
-
-import javax.security.auth.callback.Callback;
-import javax.security.auth.callback.CallbackHandler;
-import javax.security.auth.callback.NameCallback;
-import javax.security.auth.callback.PasswordCallback;
-
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.argeo.security.ui.SecurityUiPlugin;
-import org.eclipse.core.runtime.IProgressMonitor;
-import org.eclipse.core.runtime.NullProgressMonitor;
-import org.eclipse.jface.dialogs.IDialogConstants;
-import org.eclipse.jface.dialogs.TrayDialog;
-import org.eclipse.jface.operation.IRunnableWithProgress;
-import org.eclipse.jface.operation.ModalContext;
-import org.eclipse.swt.events.SelectionEvent;
-import org.eclipse.swt.events.SelectionListener;
-import org.eclipse.swt.widgets.Button;
-import org.eclipse.swt.widgets.Display;
-import org.eclipse.swt.widgets.Shell;
-
-/** Base for login dialogs */
-public abstract class AbstractLoginDialog extends TrayDialog implements
-               CallbackHandler {
-
-       private final static Log log = LogFactory.getLog(AbstractLoginDialog.class);
-
-       private Thread modalContextThread = null;
-       boolean processCallbacks = false;
-       boolean isCancelled = false;
-       Callback[] callbackArray;
-
-       protected final Callback[] getCallbacks() {
-               return this.callbackArray;
-       }
-
-       public abstract void internalHandle();
-
-       public boolean isCancelled() {
-               return isCancelled;
-       }
-
-       protected AbstractLoginDialog(Shell parentShell) {
-               super(parentShell);
-       }
-
-       /*
-        * (non-Javadoc)
-        * 
-        * @see
-        * javax.security.auth.callback.CallbackHandler#handle(javax.security.auth
-        * .callback.Callback[])
-        */
-       public void handle(final Callback[] callbacks) throws IOException {
-               // clean previous usage
-               if (processCallbacks) {
-                       // this handler was already used
-                       processCallbacks = false;
-               }
-
-               if (modalContextThread != null) {
-                       try {
-                               modalContextThread.join(1000);
-                       } catch (InterruptedException e) {
-                               // silent
-                       }
-                       modalContextThread = null;
-               }
-
-               // initialize
-               this.callbackArray = callbacks;
-               final Display display = Display.getDefault();
-               display.syncExec(new Runnable() {
-
-                       public void run() {
-                               isCancelled = false;
-                               setBlockOnOpen(false);
-                               open();
-
-                               final Button okButton = getButton(IDialogConstants.OK_ID);
-                               okButton.setText("Login");
-                               okButton.addSelectionListener(new SelectionListener() {
-
-                                       public void widgetSelected(final SelectionEvent event) {
-                                               processCallbacks = true;
-                                       }
-
-                                       public void widgetDefaultSelected(final SelectionEvent event) {
-                                               // nothing to do
-                                       }
-                               });
-                               final Button cancel = getButton(IDialogConstants.CANCEL_ID);
-                               cancel.addSelectionListener(new SelectionListener() {
-
-                                       public void widgetSelected(final SelectionEvent event) {
-                                               isCancelled = true;
-                                               processCallbacks = true;
-                                       }
-
-                                       public void widgetDefaultSelected(final SelectionEvent event) {
-                                               // nothing to do
-                                       }
-                               });
-                       }
-               });
-               try {
-                       ModalContext.setAllowReadAndDispatch(true); // Works for now.
-                       ModalContext.run(new IRunnableWithProgress() {
-
-                               public void run(final IProgressMonitor monitor) {
-                                       modalContextThread = Thread.currentThread();
-                                       // Wait here until OK or cancel is pressed, then let it rip.
-                                       // The event
-                                       // listener
-                                       // is responsible for closing the dialog (in the
-                                       // loginSucceeded
-                                       // event).
-                                       while (!processCallbacks && (modalContextThread != null)
-                                                       && (modalContextThread == Thread.currentThread())
-                                                       && SecurityUiPlugin.getDefault() != null) {
-                                               // Note: SecurityUiPlugin.getDefault() != null is false
-                                               // when the OSGi runtime is shut down
-                                               try {
-                                                       Thread.sleep(100);
-                                                       // if (display.isDisposed()) {
-                                                       // log.warn("Display is disposed, killing login dialog thread");
-                                                       // throw new ThreadDeath();
-                                                       // }
-                                               } catch (final Exception e) {
-                                                       // do nothing
-                                               }
-                                       }
-                                       processCallbacks = false;
-                                       // Call the adapter to handle the callbacks
-                                       if (!isCancelled())
-                                               internalHandle();
-                                       else
-                                               // clear callbacks are when cancelling
-                                               for (Callback callback : callbacks)
-                                                       if (callback instanceof PasswordCallback)
-                                                               ((PasswordCallback) callback).setPassword(null);
-                                                       else if (callback instanceof NameCallback)
-                                                               ((NameCallback) callback).setName(null);
-                               }
-                       }, true, new NullProgressMonitor(), Display.getDefault());
-               } catch (ThreadDeath e) {
-                       isCancelled = true;
-                       log.debug("Thread " + Thread.currentThread().getId() + " died");
-                       throw e;
-               } catch (Exception e) {
-                       isCancelled = true;
-                       IOException ioe = new IOException(
-                                       "Unexpected issue in login dialog, see root cause for more details");
-                       ioe.initCause(e);
-                       throw ioe;
-               } finally {
-                       // so that the modal thread dies
-                       processCallbacks = true;
-                       // try {
-                       // // wait for the modal context thread to gracefully exit
-                       // modalContextThread.join();
-                       // } catch (InterruptedException ie) {
-                       // // silent
-                       // }
-                       modalContextThread = null;
-               }
-       }
-
-       protected void configureShell(Shell shell) {
-               super.configureShell(shell);
-               shell.setText("Authentication");
-       }
-}
diff --git a/org.argeo.security.ui/src/main/java/org/argeo/security/ui/dialogs/ChangePasswordDialog.java b/org.argeo.security.ui/src/main/java/org/argeo/security/ui/dialogs/ChangePasswordDialog.java
deleted file mode 100644 (file)
index fe9b6ae..0000000
+++ /dev/null
@@ -1,90 +0,0 @@
-/*
- * Copyright (C) 2007-2012 Argeo GmbH
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *         http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.argeo.security.ui.dialogs;
-
-import org.argeo.ArgeoException;
-import org.argeo.eclipse.ui.ErrorFeedback;
-import org.eclipse.jface.dialogs.IMessageProvider;
-import org.eclipse.jface.dialogs.TitleAreaDialog;
-import org.eclipse.swt.SWT;
-import org.eclipse.swt.graphics.Point;
-import org.eclipse.swt.layout.GridData;
-import org.eclipse.swt.layout.GridLayout;
-import org.eclipse.swt.widgets.Composite;
-import org.eclipse.swt.widgets.Control;
-import org.eclipse.swt.widgets.Label;
-import org.eclipse.swt.widgets.Shell;
-import org.eclipse.swt.widgets.Text;
-import org.springframework.security.userdetails.UserDetailsManager;
-
-/** Dialog to change the current user password */
-public class ChangePasswordDialog extends TitleAreaDialog {
-       private Text currentPassword, newPassword1, newPassword2;
-       private UserDetailsManager userDetailsManager;
-
-       public ChangePasswordDialog(Shell parentShell,
-                       UserDetailsManager securityService) {
-               super(parentShell);
-               this.userDetailsManager = securityService;
-       }
-
-       protected Point getInitialSize() {
-               return new Point(300, 250);
-       }
-
-       protected Control createDialogArea(Composite parent) {
-               Composite dialogarea = (Composite) super.createDialogArea(parent);
-               dialogarea.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
-               Composite composite = new Composite(dialogarea, SWT.NONE);
-               composite.setLayout(new GridLayout(2, false));
-               composite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
-               currentPassword = createLP(composite, "Current password");
-               newPassword1 = createLP(composite, "New password");
-               newPassword2 = createLP(composite, "Repeat new password");
-
-               setMessage("Change password", IMessageProvider.INFORMATION);
-               parent.pack();
-               return composite;
-       }
-
-       @Override
-       protected void okPressed() {
-               if (!newPassword1.getText().equals(newPassword2.getText()))
-                       throw new ArgeoException("Passwords are different");
-               try {
-                       userDetailsManager.changePassword(currentPassword.getText(),
-                                       newPassword1.getText());
-                       close();
-               } catch (Exception e) {
-                       ErrorFeedback.show("Cannot change password", e);
-               }
-       }
-
-       /** Creates label and password. */
-       protected Text createLP(Composite parent, String label) {
-               new Label(parent, SWT.NONE).setText(label);
-               Text text = new Text(parent, SWT.SINGLE | SWT.LEAD | SWT.PASSWORD
-                               | SWT.BORDER);
-               text.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
-               return text;
-       }
-
-       protected void configureShell(Shell shell) {
-               super.configureShell(shell);
-               shell.setText("Change password");
-       }
-
-}
diff --git a/org.argeo.security.ui/src/main/java/org/argeo/security/ui/dialogs/DefaultLoginDialog.java b/org.argeo.security.ui/src/main/java/org/argeo/security/ui/dialogs/DefaultLoginDialog.java
deleted file mode 100644 (file)
index 57ba01b..0000000
+++ /dev/null
@@ -1,189 +0,0 @@
-/*
- * Copyright (C) 2007-2012 Argeo GmbH
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *         http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.argeo.security.ui.dialogs;
-
-import javax.security.auth.callback.Callback;
-import javax.security.auth.callback.CallbackHandler;
-import javax.security.auth.callback.NameCallback;
-import javax.security.auth.callback.PasswordCallback;
-import javax.security.auth.callback.TextOutputCallback;
-
-import org.argeo.security.ui.SecurityUiPlugin;
-import org.argeo.util.LocaleCallback;
-import org.eclipse.swt.SWT;
-import org.eclipse.swt.events.ModifyEvent;
-import org.eclipse.swt.events.ModifyListener;
-import org.eclipse.swt.events.SelectionEvent;
-import org.eclipse.swt.events.SelectionListener;
-import org.eclipse.swt.graphics.Point;
-import org.eclipse.swt.graphics.Rectangle;
-import org.eclipse.swt.layout.GridData;
-import org.eclipse.swt.layout.GridLayout;
-import org.eclipse.swt.widgets.Combo;
-import org.eclipse.swt.widgets.Composite;
-import org.eclipse.swt.widgets.Control;
-import org.eclipse.swt.widgets.Display;
-import org.eclipse.swt.widgets.Label;
-import org.eclipse.swt.widgets.Shell;
-import org.eclipse.swt.widgets.Text;
-
-/** Default authentication dialog, to be used as {@link CallbackHandler}. */
-public class DefaultLoginDialog extends AbstractLoginDialog {
-       public DefaultLoginDialog() {
-               this(SecurityUiPlugin.display.get().getActiveShell());
-       }
-
-       public DefaultLoginDialog(Shell parentShell) {
-               super(parentShell);
-       }
-
-       protected Point getInitialSize() {
-               return new Point(350, 180);
-       }
-
-       @Override
-       protected Control createContents(Composite parent) {
-               Control control = super.createContents(parent);
-               parent.pack();
-
-               // Move the dialog to the center of the top level shell.
-               Rectangle shellBounds;
-               if (Display.getCurrent().getActiveShell() != null) // RCP
-                       shellBounds = Display.getCurrent().getActiveShell().getBounds();
-               else
-                       shellBounds = Display.getCurrent().getBounds();// RAP
-               Point dialogSize = parent.getSize();
-               int x = shellBounds.x + (shellBounds.width - dialogSize.x) / 2;
-               int y = shellBounds.y + (shellBounds.height - dialogSize.y) / 2;
-               parent.setLocation(x, y);
-               return control;
-       }
-
-       protected Control createDialogArea(Composite parent) {
-               Composite dialogarea = (Composite) super.createDialogArea(parent);
-               Composite composite = new Composite(dialogarea, SWT.NONE);
-               composite.setLayout(new GridLayout(2, false));
-               composite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
-               createCallbackHandlers(composite);
-               // parent.pack();
-               return composite;
-       }
-
-       private void createCallbackHandlers(Composite composite) {
-               Callback[] callbacks = getCallbacks();
-               for (int i = 0; i < callbacks.length; i++) {
-                       Callback callback = callbacks[i];
-                       if (callback instanceof TextOutputCallback) {
-                               createLabelTextoutputHandler(composite,
-                                               (TextOutputCallback) callback);
-                       } else if (callback instanceof NameCallback) {
-                               createNameHandler(composite, (NameCallback) callback);
-                       } else if (callback instanceof PasswordCallback) {
-                               createPasswordHandler(composite, (PasswordCallback) callback);
-                       } else if (callback instanceof LocaleCallback) {
-                               createLocaleHandler(composite, (LocaleCallback) callback);
-                       }
-               }
-       }
-
-       private void createPasswordHandler(Composite composite,
-                       final PasswordCallback callback) {
-               Label label = new Label(composite, SWT.NONE);
-               label.setText(callback.getPrompt());
-               final Text passwordText = new Text(composite, SWT.SINGLE | SWT.LEAD
-                               | SWT.PASSWORD | SWT.BORDER);
-               passwordText
-                               .setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
-               passwordText.addModifyListener(new ModifyListener() {
-
-                       public void modifyText(ModifyEvent event) {
-                               // FIXME use getTextChars() in Eclipse 3.7
-                               callback.setPassword(passwordText.getText().toCharArray());
-                       }
-               });
-       }
-
-       private void createLocaleHandler(Composite composite,
-                       final LocaleCallback callback) {
-               String[] labels = callback.getSupportedLocalesLabels();
-               if (labels.length == 0)
-                       return;
-               Label label = new Label(composite, SWT.NONE);
-               label.setText(callback.getPrompt());
-
-               final Combo combo = new Combo(composite, SWT.READ_ONLY);
-               combo.setItems(labels);
-               combo.select(callback.getDefaultIndex());
-               combo.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
-               combo.addSelectionListener(new SelectionListener() {
-                       @Override
-                       public void widgetSelected(SelectionEvent e) {
-                               callback.setSelectedIndex(combo.getSelectionIndex());
-                       }
-
-                       @Override
-                       public void widgetDefaultSelected(SelectionEvent e) {
-                       }
-               });
-       }
-
-       private void createNameHandler(Composite composite,
-                       final NameCallback callback) {
-               Label label = new Label(composite, SWT.NONE);
-               label.setText(callback.getPrompt());
-               final Text text = new Text(composite, SWT.SINGLE | SWT.LEAD
-                               | SWT.BORDER);
-               if (callback.getDefaultName() != null) {
-                       // set default value, if provided
-                       text.setText(callback.getDefaultName());
-                       callback.setName(callback.getDefaultName());
-               }
-               text.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
-               text.addModifyListener(new ModifyListener() {
-
-                       public void modifyText(ModifyEvent event) {
-                               callback.setName(text.getText());
-                       }
-               });
-       }
-
-       private void createLabelTextoutputHandler(Composite composite,
-                       final TextOutputCallback callback) {
-               Label label = new Label(composite, SWT.NONE);
-               label.setText(callback.getMessage());
-               GridData data = new GridData(SWT.FILL, SWT.FILL, true, true);
-               data.horizontalSpan = 2;
-               label.setLayoutData(data);
-               // TODO: find a way to pass this information
-               // int messageType = callback.getMessageType();
-               // int dialogMessageType = IMessageProvider.NONE;
-               // switch (messageType) {
-               // case TextOutputCallback.INFORMATION:
-               // dialogMessageType = IMessageProvider.INFORMATION;
-               // break;
-               // case TextOutputCallback.WARNING:
-               // dialogMessageType = IMessageProvider.WARNING;
-               // break;
-               // case TextOutputCallback.ERROR:
-               // dialogMessageType = IMessageProvider.ERROR;
-               // break;
-               // }
-               // setMessage(callback.getMessage(), dialogMessageType);
-       }
-
-       public void internalHandle() {
-       }
-}
diff --git a/org.argeo.security.ui/src/main/java/org/argeo/security/ui/internal/CurrentUser.java b/org.argeo.security.ui/src/main/java/org/argeo/security/ui/internal/CurrentUser.java
deleted file mode 100644 (file)
index 43ca588..0000000
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * Copyright (C) 2007-2012 Argeo GmbH
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *         http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.argeo.security.ui.internal;
-
-import java.security.AccessController;
-import java.security.Principal;
-import java.util.Collections;
-import java.util.HashSet;
-import java.util.Set;
-
-import javax.security.auth.Subject;
-
-import org.argeo.ArgeoException;
-import org.springframework.security.Authentication;
-import org.springframework.security.GrantedAuthority;
-
-/**
- * Retrieves information about the current user. Not an API, can change without
- * notice.
- */
-public class CurrentUser {
-       public final static String getUsername() {
-               Subject subject = getSubject();
-               if (subject == null)
-                       return null;
-               Principal principal = subject.getPrincipals().iterator().next();
-               return principal.getName();
-
-       }
-
-       public final static Set<String> roles() {
-               Set<String> roles = Collections.synchronizedSet(new HashSet<String>());
-               Authentication authentication = getAuthentication();
-               for (GrantedAuthority ga : authentication.getAuthorities()) {
-                       roles.add(ga.getAuthority());
-               }
-               return Collections.unmodifiableSet(roles);
-       }
-
-       public final static Authentication getAuthentication() {
-               Set<Authentication> authens = getSubject().getPrincipals(
-                               Authentication.class);
-               if (authens != null && !authens.isEmpty()) {
-                       Principal principal = authens.iterator().next();
-                       Authentication authentication = (Authentication) principal;
-                       return authentication;
-               }
-               throw new ArgeoException("No authentication found");
-       }
-
-       public final static Subject getSubject() {
-               Subject subject = Subject.getSubject(AccessController.getContext());
-               if (subject == null)
-                       throw new ArgeoException("Not authenticated.");
-               return subject;
-       }
-}
diff --git a/org.argeo.security.ui/src/main/java/org/argeo/security/ui/views/AdminLogView.java b/org.argeo.security.ui/src/main/java/org/argeo/security/ui/views/AdminLogView.java
deleted file mode 100644 (file)
index d59edf8..0000000
+++ /dev/null
@@ -1,88 +0,0 @@
-/*
- * Copyright (C) 2007-2012 Argeo GmbH
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *         http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.argeo.security.ui.views;
-
-import java.util.ArrayList;
-
-import org.argeo.ArgeoLogger;
-import org.argeo.security.ui.SecurityUiPlugin;
-import org.eclipse.jface.resource.JFaceResources;
-import org.eclipse.jface.viewers.LabelProvider;
-import org.eclipse.jface.viewers.TableViewer;
-import org.eclipse.swt.SWT;
-import org.eclipse.swt.graphics.Font;
-import org.eclipse.swt.widgets.Composite;
-import org.eclipse.swt.widgets.Table;
-import org.eclipse.ui.part.ViewPart;
-
-/**
- * Display log lines for all users with a virtual table.
- */
-public class AdminLogView extends ViewPart {
-       public static String ID = SecurityUiPlugin.PLUGIN_ID + ".adminLogView";
-
-       private TableViewer viewer;
-
-       private LogContentProvider logContentProvider;
-       private ArgeoLogger argeoLogger;
-
-       @Override
-       public void createPartControl(Composite parent) {
-               // FIXME doesn't return a monospace font in RAP
-               Font font = JFaceResources.getTextFont();
-               Table table = new Table(parent, SWT.VIRTUAL | SWT.MULTI | SWT.H_SCROLL
-                               | SWT.V_SCROLL | SWT.FULL_SELECTION | SWT.BORDER);
-               table.setFont(font);
-
-               viewer = new TableViewer(table);
-               viewer.setLabelProvider(new LabelProvider());
-               logContentProvider = new LogContentProvider(viewer) {
-
-                       @Override
-                       protected StringBuffer prefix(String username, Long timestamp,
-                                       String level, String category, String thread) {
-                               return super
-                                               .prefix(username, timestamp, level, category, thread)
-                                               .append(norm(level, 5))
-                                               .append(' ')
-                                               .append(norm(username != null ? username
-                                                               : "<anonymous>", 16)).append(' ');
-                       }
-               };
-               viewer.setContentProvider(logContentProvider);
-               // viewer.setUseHashlookup(true);
-               viewer.setInput(new ArrayList<String>());
-
-               if (argeoLogger != null)
-                       argeoLogger.registerForAll(logContentProvider, 1000, true);
-       }
-
-       @Override
-       public void setFocus() {
-               viewer.getTable().setFocus();
-       }
-
-       @Override
-       public void dispose() {
-               if (argeoLogger != null)
-                       argeoLogger.unregisterForAll(logContentProvider);
-       }
-
-       public void setArgeoLogger(ArgeoLogger argeoLogger) {
-               this.argeoLogger = argeoLogger;
-       }
-
-}
diff --git a/org.argeo.security.ui/src/main/java/org/argeo/security/ui/views/LogContentProvider.java b/org.argeo.security.ui/src/main/java/org/argeo/security/ui/views/LogContentProvider.java
deleted file mode 100644 (file)
index 72f2059..0000000
+++ /dev/null
@@ -1,187 +0,0 @@
-/*
- * Copyright (C) 2007-2012 Argeo GmbH
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *         http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.argeo.security.ui.views;
-
-import java.text.DateFormat;
-import java.text.SimpleDateFormat;
-import java.util.Arrays;
-import java.util.Date;
-import java.util.LinkedList;
-import java.util.List;
-
-import org.argeo.ArgeoLogListener;
-import org.eclipse.jface.viewers.ILazyContentProvider;
-import org.eclipse.jface.viewers.TableViewer;
-import org.eclipse.jface.viewers.Viewer;
-import org.eclipse.swt.widgets.Table;
-import org.eclipse.swt.widgets.TableItem;
-
-/** A content provider maintaining an array of lines */
-class LogContentProvider implements ILazyContentProvider, ArgeoLogListener {
-       private DateFormat dateFormat = new SimpleDateFormat("HH:mm:ss");
-
-       private final Long start;
-       /** current - start = line number. first line is number '1' */
-       private Long current;
-
-       // TODO make it configurable
-       private final Integer maxLineBufferSize = 10 * 1000;
-
-       private final TableViewer viewer;
-       private LinkedList<LogLine> lines;
-
-       public LogContentProvider(TableViewer viewer) {
-               this.viewer = viewer;
-               start = System.currentTimeMillis();
-               lines = new LinkedList<LogLine>();
-               current = start;
-       }
-
-       public synchronized void dispose() {
-               lines.clear();
-               lines = null;
-       }
-
-       @SuppressWarnings("unchecked")
-       public synchronized void inputChanged(Viewer viewer, Object oldInput,
-                       Object newInput) {
-               List<String> lin = (List<String>) newInput;
-               if (lin == null)
-                       return;
-               for (String line : lin) {
-                       addLine(line);
-               }
-               this.viewer.setItemCount(lines.size());
-       }
-
-       public void updateElement(int index) {
-               viewer.replace(lines.get(index), index);
-       }
-
-       public synchronized void appendLog(String username, Long timestamp,
-                       String level, String category, String thread, Object msg,
-                       String[] exception) {
-               // check if valid
-               if (lines == null)
-                       return;
-
-               String message = msg.toString();
-               int count = 0;
-               String prefix = prefix(username, timestamp, level, category, thread)
-                               .toString();
-               // String suffix = suffix(username, timestamp, level, category, thread);
-               for (String line : message.split("\n")) {
-                       addLine(count == 0 ? prefix + line : line);
-                       count++;
-               }
-
-               if (exception != null) {
-                       for (String ste : exception) {
-                               addLine(ste);
-                       }
-               }
-
-               viewer.getTable().getDisplay().asyncExec(new Runnable() {
-                       public void run() {
-                               if (lines == null)
-                                       return;
-                               viewer.setItemCount(lines.size());
-                               // doesn't work with syncExec
-                               scrollToLastLine();
-                       }
-               });
-       }
-
-       protected StringBuffer prefix(String username, Long timestamp,
-                       String level, String category, String thread) {
-               StringBuffer buf = new StringBuffer("");
-               buf.append(dateFormat.format(new Date(timestamp))).append(" ");
-               // buf.append(level).append(" ");
-               return buf;
-       }
-
-       /** Normalize string to the given size */
-       protected String norm(String str, Integer size) {
-               int length = str.length();
-               if (length == size)
-                       return str;
-               else if (length > size)
-                       return str.substring(0, size);
-               else {
-                       char[] arr = new char[size - length];
-                       Arrays.fill(arr, ' ');
-                       return str + new String(arr);
-               }
-       }
-
-       // protected String suffix(String username, Long timestamp, String level,
-       // String category, String thread) {
-       // return "";
-       // }
-
-       /** Scroll to the last line */
-       protected synchronized void scrollToLastLine() {
-               // we try to show last line with two methods
-               // viewer.reveal(lines.peekLast());
-
-               Table table = viewer.getTable();
-               TableItem ti = table.getItem(table.getItemCount() - 1);
-               table.showItem(ti);
-       }
-
-       protected synchronized LogLine addLine(String line) {
-               // check for maximal size and purge if necessary
-               while (lines.size() >= maxLineBufferSize) {
-                       for (int i = 0; i < maxLineBufferSize / 10; i++) {
-                               lines.poll();
-                       }
-               }
-
-               current++;
-               LogLine logLine = new LogLine(current, line);
-               lines.add(logLine);
-               return logLine;
-       }
-
-       private class LogLine {
-               private Long linenumber;
-               private String message;
-
-               public LogLine(Long linenumber, String message) {
-                       this.linenumber = linenumber;
-                       this.message = message;
-               }
-
-               @Override
-               public int hashCode() {
-                       return linenumber.intValue();
-               }
-
-               @Override
-               public boolean equals(Object obj) {
-                       if (obj instanceof LogLine)
-                               return ((LogLine) obj).linenumber.equals(linenumber);
-                       else
-                               return false;
-               }
-
-               @Override
-               public String toString() {
-                       return message;
-               }
-
-       }
-}
\ No newline at end of file
diff --git a/org.argeo.security.ui/src/main/java/org/argeo/security/ui/views/LogView.java b/org.argeo.security.ui/src/main/java/org/argeo/security/ui/views/LogView.java
deleted file mode 100644 (file)
index c7c47b3..0000000
+++ /dev/null
@@ -1,77 +0,0 @@
-/*
- * Copyright (C) 2007-2012 Argeo GmbH
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *         http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.argeo.security.ui.views;
-
-import java.util.ArrayList;
-
-import org.argeo.ArgeoLogListener;
-import org.argeo.ArgeoLogger;
-import org.argeo.security.ui.SecurityUiPlugin;
-import org.eclipse.jface.resource.JFaceResources;
-import org.eclipse.jface.viewers.LabelProvider;
-import org.eclipse.jface.viewers.TableViewer;
-import org.eclipse.swt.SWT;
-import org.eclipse.swt.graphics.Font;
-import org.eclipse.swt.widgets.Composite;
-import org.eclipse.swt.widgets.Table;
-import org.eclipse.ui.part.ViewPart;
-
-/**
- * Display log lines with a virtual table. Register and unregisters a
- * {@link ArgeoLogListener} via OSGi services.
- */
-public class LogView extends ViewPart {
-       public static String ID = SecurityUiPlugin.PLUGIN_ID + ".logView";
-
-       private TableViewer viewer;
-
-       private LogContentProvider logContentProvider;
-       private ArgeoLogger argeoLogger;
-
-       @Override
-       public void createPartControl(Composite parent) {
-               Font font = JFaceResources.getTextFont();
-               Table table = new Table(parent, SWT.VIRTUAL | SWT.MULTI | SWT.H_SCROLL
-                               | SWT.V_SCROLL | SWT.FULL_SELECTION | SWT.BORDER);
-               table.setFont(font);
-
-               viewer = new TableViewer(table);
-               viewer.setLabelProvider(new LabelProvider());
-               logContentProvider = new LogContentProvider(viewer);
-               viewer.setContentProvider(logContentProvider);
-               // viewer.setUseHashlookup(true);
-               viewer.setInput(new ArrayList<String>());
-
-               if (argeoLogger != null)
-                       argeoLogger.register(logContentProvider, 1000);
-       }
-
-       @Override
-       public void setFocus() {
-               viewer.getTable().setFocus();
-       }
-
-       @Override
-       public void dispose() {
-               if (argeoLogger != null)
-                       argeoLogger.unregister(logContentProvider);
-       }
-
-       public void setArgeoLogger(ArgeoLogger argeoLogger) {
-               this.argeoLogger = argeoLogger;
-       }
-
-}
diff --git a/org.argeo.security.ui/src/main/java/org/argeo/security/ui/views/UserProfile.java b/org.argeo.security.ui/src/main/java/org/argeo/security/ui/views/UserProfile.java
deleted file mode 100644 (file)
index 3f1f000..0000000
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
- * Copyright (C) 2007-2012 Argeo GmbH
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *         http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.argeo.security.ui.views;
-
-import java.util.TreeSet;
-
-import org.argeo.eclipse.ui.EclipseUiUtils;
-import org.argeo.security.ui.SecurityUiPlugin;
-import org.argeo.security.ui.internal.CurrentUser;
-import org.eclipse.jface.viewers.IStructuredContentProvider;
-import org.eclipse.jface.viewers.LabelProvider;
-import org.eclipse.jface.viewers.TableViewer;
-import org.eclipse.jface.viewers.Viewer;
-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.Table;
-import org.eclipse.ui.part.ViewPart;
-import org.springframework.security.Authentication;
-
-/** Information about the currently logged in user */
-public class UserProfile extends ViewPart {
-       public static String ID = SecurityUiPlugin.PLUGIN_ID + ".userProfile";
-
-       private TableViewer viewer;
-
-       @Override
-       public void createPartControl(Composite parent) {
-               parent.setLayout(new GridLayout(2, false));
-
-               Authentication authentication = CurrentUser.getAuthentication();
-               EclipseUiUtils.createGridLL(parent, "Name", authentication
-                               .getPrincipal().toString());
-               EclipseUiUtils.createGridLL(parent, "User ID",
-                               CurrentUser.getUsername());
-
-               // roles table
-               Table table = new Table(parent, SWT.V_SCROLL | SWT.BORDER);
-               table.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 2, 1));
-               table.setLinesVisible(false);
-               table.setHeaderVisible(false);
-               viewer = new TableViewer(table);
-               viewer.setContentProvider(new RolesContentProvider());
-               viewer.setLabelProvider(new LabelProvider());
-               getViewSite().setSelectionProvider(viewer);
-               viewer.setInput(getViewSite());
-       }
-
-       @Override
-       public void setFocus() {
-               viewer.getTable();
-       }
-
-       private class RolesContentProvider implements IStructuredContentProvider {
-               public Object[] getElements(Object inputElement) {
-                       return new TreeSet<String>(CurrentUser.roles()).toArray();
-               }
-
-               public void dispose() {
-               }
-
-               public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
-               }
-
-       }
-
-}
diff --git a/org.argeo.security.ui/src/org/argeo/security/ui/MaintenancePerspective.java b/org.argeo.security.ui/src/org/argeo/security/ui/MaintenancePerspective.java
new file mode 100644 (file)
index 0000000..86307ab
--- /dev/null
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2007-2012 Argeo GmbH
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *         http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.argeo.security.ui;
+
+import org.argeo.security.ui.views.AdminLogView;
+import org.argeo.security.ui.views.UserProfile;
+import org.eclipse.ui.IFolderLayout;
+import org.eclipse.ui.IPageLayout;
+import org.eclipse.ui.IPerspectiveFactory;
+
+/** Home perspective for the current user */
+public class MaintenancePerspective implements IPerspectiveFactory {
+       public final static String ID = SecurityUiPlugin.PLUGIN_ID
+                       + ".adminMaintenancePerspective";
+
+       public void createInitialLayout(IPageLayout layout) {
+               String editorArea = layout.getEditorArea();
+               layout.setEditorAreaVisible(true);
+               layout.setFixed(false);
+
+               IFolderLayout bottom = layout.createFolder("bottom",
+                               IPageLayout.BOTTOM, 0.50f, editorArea);
+               bottom.addView(AdminLogView.ID);
+
+               IFolderLayout left = layout.createFolder("left", IPageLayout.LEFT,
+                               0.30f, editorArea);
+               left.addView(UserProfile.ID);
+               // left.addView(RolesView.ID);
+
+       }
+
+}
diff --git a/org.argeo.security.ui/src/org/argeo/security/ui/PrivilegedJob.java b/org.argeo.security.ui/src/org/argeo/security/ui/PrivilegedJob.java
new file mode 100644 (file)
index 0000000..1ded50f
--- /dev/null
@@ -0,0 +1,46 @@
+package org.argeo.security.ui;
+
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+
+import javax.security.auth.Subject;
+
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.jobs.Job;
+import org.springframework.security.Authentication;
+import org.springframework.security.context.SecurityContextHolder;
+
+/**
+ * Propagate authentication to an eclipse job. Typically to execute a privileged
+ * action outside the UI thread
+ */
+public abstract class PrivilegedJob extends Job {
+
+       private final Authentication authentication;
+       private Subject subject;
+
+       public PrivilegedJob(String jobName) {
+               super(jobName);
+               authentication = SecurityContextHolder.getContext().getAuthentication();
+               subject = Subject.getSubject(AccessController.getContext());
+       }
+
+       @Override
+       protected IStatus run(final IProgressMonitor progressMonitor) {
+               PrivilegedAction<IStatus> privilegedAction = new PrivilegedAction<IStatus>() {
+                       public IStatus run() {
+                               SecurityContextHolder.getContext().setAuthentication(
+                                               authentication);
+                               return doRun(progressMonitor);
+                       }
+               };
+               return Subject.doAs(subject, privilegedAction);
+       }
+
+       /**
+        * Implement here what should be executed with default context
+        * authentication
+        */
+       protected abstract IStatus doRun(IProgressMonitor progressMonitor);
+}
\ No newline at end of file
diff --git a/org.argeo.security.ui/src/org/argeo/security/ui/RolesSourceProvider.java b/org.argeo.security.ui/src/org/argeo/security/ui/RolesSourceProvider.java
new file mode 100644 (file)
index 0000000..a81dc20
--- /dev/null
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2007-2012 Argeo GmbH
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *         http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.argeo.security.ui;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+
+import org.argeo.security.ui.internal.CurrentUser;
+import org.eclipse.ui.AbstractSourceProvider;
+
+/**
+ * Provides the roles of the current user as a variable to be used for activity
+ * binding
+ */
+public class RolesSourceProvider extends AbstractSourceProvider {
+       public final static String ROLES_VARIABLE = "roles";
+       private final static String[] PROVIDED_SOURCE_NAMES = new String[] { ROLES_VARIABLE };
+
+       public Map<String, Set<String>> getCurrentState() {
+               Map<String, Set<String>> stateMap = new HashMap<String, Set<String>>();
+               stateMap.put(ROLES_VARIABLE, CurrentUser.roles());
+               return stateMap;
+       }
+
+       public String[] getProvidedSourceNames() {
+               return PROVIDED_SOURCE_NAMES;
+       }
+
+       public void updateRoles() {
+               fireSourceChanged(0, getCurrentState());
+       }
+
+       public void dispose() {
+       }
+}
\ No newline at end of file
diff --git a/org.argeo.security.ui/src/org/argeo/security/ui/SecurityUiPlugin.java b/org.argeo.security.ui/src/org/argeo/security/ui/SecurityUiPlugin.java
new file mode 100644 (file)
index 0000000..0358418
--- /dev/null
@@ -0,0 +1,109 @@
+/*
+ * Copyright (C) 2007-2012 Argeo GmbH
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *         http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.argeo.security.ui;
+
+import java.io.IOException;
+
+import javax.security.auth.callback.Callback;
+import javax.security.auth.callback.CallbackHandler;
+import javax.security.auth.callback.UnsupportedCallbackException;
+
+import org.argeo.ArgeoException;
+import org.argeo.security.ui.dialogs.DefaultLoginDialog;
+import org.eclipse.jface.resource.ImageDescriptor;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.ui.plugin.AbstractUIPlugin;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.ServiceRegistration;
+
+/**
+ * The activator class controls the plug-in life cycle
+ */
+public class SecurityUiPlugin extends AbstractUIPlugin {
+
+       // The plug-in ID
+       public static final String PLUGIN_ID = "org.argeo.security.ui"; //$NON-NLS-1$
+
+       public final static String CONTEXT_KEYRING = "KEYRING";
+
+       private CallbackHandler defaultCallbackHandler;
+       private ServiceRegistration defaultCallbackHandlerReg;
+
+       private static SecurityUiPlugin plugin;
+
+       public static InheritableThreadLocal<Display> display = new InheritableThreadLocal<Display>() {
+
+               @Override
+               protected Display initialValue() {
+                       return Display.getCurrent();
+               }
+       };
+
+       public void start(BundleContext context) throws Exception {
+               super.start(context);
+               plugin = this;
+
+               defaultCallbackHandler = new DefaultCallbackHandler();
+               defaultCallbackHandlerReg = context.registerService(
+                               CallbackHandler.class.getName(), defaultCallbackHandler, null);
+       }
+
+       public void stop(BundleContext context) throws Exception {
+               plugin = null;
+               defaultCallbackHandlerReg.unregister();
+               super.stop(context);
+       }
+
+       /**
+        * Returns the shared instance
+        * 
+        * @return the shared instance
+        */
+       public static SecurityUiPlugin getDefault() {
+               return plugin;
+       }
+
+       public static ImageDescriptor getImageDescriptor(String path) {
+               return imageDescriptorFromPlugin(PLUGIN_ID, path);
+       }
+
+       protected class DefaultCallbackHandler implements CallbackHandler {
+               public void handle(final Callback[] callbacks) throws IOException,
+                               UnsupportedCallbackException {
+
+                       // if (display != null) // RCP
+                       Display displayToUse = display.get();
+                       if (displayToUse == null)// RCP
+                               displayToUse = Display.getDefault();
+                       displayToUse.syncExec(new Runnable() {
+                               public void run() {
+                                       DefaultLoginDialog dialog = new DefaultLoginDialog(display
+                                                       .get().getActiveShell());
+                                       try {
+                                               dialog.handle(callbacks);
+                                       } catch (IOException e) {
+                                               throw new ArgeoException("Cannot open dialog", e);
+                                       }
+                               }
+                       });
+                       // else {// RAP
+                       // DefaultLoginDialog dialog = new DefaultLoginDialog();
+                       // dialog.handle(callbacks);
+                       // }
+               }
+
+       }
+}
diff --git a/org.argeo.security.ui/src/org/argeo/security/ui/UserHomePerspective.java b/org.argeo.security.ui/src/org/argeo/security/ui/UserHomePerspective.java
new file mode 100644 (file)
index 0000000..119549f
--- /dev/null
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2007-2012 Argeo GmbH
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *         http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.argeo.security.ui;
+
+import org.argeo.security.ui.views.LogView;
+import org.argeo.security.ui.views.UserProfile;
+import org.eclipse.ui.IFolderLayout;
+import org.eclipse.ui.IPageLayout;
+import org.eclipse.ui.IPerspectiveFactory;
+
+/** Home perspective for the current user */
+public class UserHomePerspective implements IPerspectiveFactory {
+       public final static String ID = SecurityUiPlugin.PLUGIN_ID
+                       + ".userHomePerspective";
+
+       public void createInitialLayout(IPageLayout layout) {
+               String editorArea = layout.getEditorArea();
+               layout.setEditorAreaVisible(true);
+               layout.setFixed(false);
+
+               IFolderLayout left = layout.createFolder("left", IPageLayout.LEFT,
+                               0.30f, editorArea);
+               left.addView(UserProfile.ID);
+               left.addView(LogView.ID);
+       }
+
+}
diff --git a/org.argeo.security.ui/src/org/argeo/security/ui/commands/OpenChangePasswordDialog.java b/org.argeo.security.ui/src/org/argeo/security/ui/commands/OpenChangePasswordDialog.java
new file mode 100644 (file)
index 0000000..3044e2c
--- /dev/null
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2007-2012 Argeo GmbH
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *         http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.argeo.security.ui.commands;
+
+import org.argeo.security.ui.dialogs.ChangePasswordDialog;
+import org.eclipse.core.commands.AbstractHandler;
+import org.eclipse.core.commands.ExecutionEvent;
+import org.eclipse.core.commands.ExecutionException;
+import org.eclipse.jface.dialogs.Dialog;
+import org.eclipse.jface.dialogs.MessageDialog;
+import org.eclipse.ui.handlers.HandlerUtil;
+import org.springframework.security.userdetails.UserDetailsManager;
+
+/** Opens the change password dialog. */
+public class OpenChangePasswordDialog extends AbstractHandler {
+       private UserDetailsManager userDetailsManager;
+
+       public Object execute(ExecutionEvent event) throws ExecutionException {
+               ChangePasswordDialog dialog = new ChangePasswordDialog(
+                               HandlerUtil.getActiveShell(event), userDetailsManager);
+               if (dialog.open() == Dialog.OK) {
+                       MessageDialog.openInformation(HandlerUtil.getActiveShell(event),
+                                       "Password changed", "Password changed.");
+               }
+               return null;
+       }
+
+       public void setUserDetailsManager(UserDetailsManager userDetailsManager) {
+               this.userDetailsManager = userDetailsManager;
+       }
+
+}
diff --git a/org.argeo.security.ui/src/org/argeo/security/ui/commands/OpenHomePerspective.java b/org.argeo.security.ui/src/org/argeo/security/ui/commands/OpenHomePerspective.java
new file mode 100644 (file)
index 0000000..d56498a
--- /dev/null
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2007-2012 Argeo GmbH
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *         http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.argeo.security.ui.commands;
+
+import org.argeo.eclipse.ui.ErrorFeedback;
+import org.argeo.security.ui.UserHomePerspective;
+import org.eclipse.core.commands.AbstractHandler;
+import org.eclipse.core.commands.ExecutionEvent;
+import org.eclipse.core.commands.ExecutionException;
+import org.eclipse.ui.WorkbenchException;
+import org.eclipse.ui.handlers.HandlerUtil;
+
+/** Default action of the user menu */
+public class OpenHomePerspective extends AbstractHandler {
+
+       public Object execute(ExecutionEvent event) throws ExecutionException {
+               try {
+                       HandlerUtil.getActiveSite(event).getWorkbenchWindow()
+                                       .openPage(UserHomePerspective.ID, null);
+               } catch (WorkbenchException e) {
+                       ErrorFeedback.show("Cannot open home perspective", e);
+               }
+               return null;
+       }
+
+}
diff --git a/org.argeo.security.ui/src/org/argeo/security/ui/dialogs/AbstractLoginDialog.java b/org.argeo.security.ui/src/org/argeo/security/ui/dialogs/AbstractLoginDialog.java
new file mode 100644 (file)
index 0000000..7c7e0c6
--- /dev/null
@@ -0,0 +1,191 @@
+/*
+ * Copyright (C) 2007-2012 Argeo GmbH
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *         http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.argeo.security.ui.dialogs;
+
+import java.io.IOException;
+
+import javax.security.auth.callback.Callback;
+import javax.security.auth.callback.CallbackHandler;
+import javax.security.auth.callback.NameCallback;
+import javax.security.auth.callback.PasswordCallback;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.argeo.security.ui.SecurityUiPlugin;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.NullProgressMonitor;
+import org.eclipse.jface.dialogs.IDialogConstants;
+import org.eclipse.jface.dialogs.TrayDialog;
+import org.eclipse.jface.operation.IRunnableWithProgress;
+import org.eclipse.jface.operation.ModalContext;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.events.SelectionListener;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Shell;
+
+/** Base for login dialogs */
+public abstract class AbstractLoginDialog extends TrayDialog implements
+               CallbackHandler {
+
+       private final static Log log = LogFactory.getLog(AbstractLoginDialog.class);
+
+       private Thread modalContextThread = null;
+       boolean processCallbacks = false;
+       boolean isCancelled = false;
+       Callback[] callbackArray;
+
+       protected final Callback[] getCallbacks() {
+               return this.callbackArray;
+       }
+
+       public abstract void internalHandle();
+
+       public boolean isCancelled() {
+               return isCancelled;
+       }
+
+       protected AbstractLoginDialog(Shell parentShell) {
+               super(parentShell);
+       }
+
+       /*
+        * (non-Javadoc)
+        * 
+        * @see
+        * javax.security.auth.callback.CallbackHandler#handle(javax.security.auth
+        * .callback.Callback[])
+        */
+       public void handle(final Callback[] callbacks) throws IOException {
+               // clean previous usage
+               if (processCallbacks) {
+                       // this handler was already used
+                       processCallbacks = false;
+               }
+
+               if (modalContextThread != null) {
+                       try {
+                               modalContextThread.join(1000);
+                       } catch (InterruptedException e) {
+                               // silent
+                       }
+                       modalContextThread = null;
+               }
+
+               // initialize
+               this.callbackArray = callbacks;
+               final Display display = Display.getDefault();
+               display.syncExec(new Runnable() {
+
+                       public void run() {
+                               isCancelled = false;
+                               setBlockOnOpen(false);
+                               open();
+
+                               final Button okButton = getButton(IDialogConstants.OK_ID);
+                               okButton.setText("Login");
+                               okButton.addSelectionListener(new SelectionListener() {
+
+                                       public void widgetSelected(final SelectionEvent event) {
+                                               processCallbacks = true;
+                                       }
+
+                                       public void widgetDefaultSelected(final SelectionEvent event) {
+                                               // nothing to do
+                                       }
+                               });
+                               final Button cancel = getButton(IDialogConstants.CANCEL_ID);
+                               cancel.addSelectionListener(new SelectionListener() {
+
+                                       public void widgetSelected(final SelectionEvent event) {
+                                               isCancelled = true;
+                                               processCallbacks = true;
+                                       }
+
+                                       public void widgetDefaultSelected(final SelectionEvent event) {
+                                               // nothing to do
+                                       }
+                               });
+                       }
+               });
+               try {
+                       ModalContext.setAllowReadAndDispatch(true); // Works for now.
+                       ModalContext.run(new IRunnableWithProgress() {
+
+                               public void run(final IProgressMonitor monitor) {
+                                       modalContextThread = Thread.currentThread();
+                                       // Wait here until OK or cancel is pressed, then let it rip.
+                                       // The event
+                                       // listener
+                                       // is responsible for closing the dialog (in the
+                                       // loginSucceeded
+                                       // event).
+                                       while (!processCallbacks && (modalContextThread != null)
+                                                       && (modalContextThread == Thread.currentThread())
+                                                       && SecurityUiPlugin.getDefault() != null) {
+                                               // Note: SecurityUiPlugin.getDefault() != null is false
+                                               // when the OSGi runtime is shut down
+                                               try {
+                                                       Thread.sleep(100);
+                                                       // if (display.isDisposed()) {
+                                                       // log.warn("Display is disposed, killing login dialog thread");
+                                                       // throw new ThreadDeath();
+                                                       // }
+                                               } catch (final Exception e) {
+                                                       // do nothing
+                                               }
+                                       }
+                                       processCallbacks = false;
+                                       // Call the adapter to handle the callbacks
+                                       if (!isCancelled())
+                                               internalHandle();
+                                       else
+                                               // clear callbacks are when cancelling
+                                               for (Callback callback : callbacks)
+                                                       if (callback instanceof PasswordCallback)
+                                                               ((PasswordCallback) callback).setPassword(null);
+                                                       else if (callback instanceof NameCallback)
+                                                               ((NameCallback) callback).setName(null);
+                               }
+                       }, true, new NullProgressMonitor(), Display.getDefault());
+               } catch (ThreadDeath e) {
+                       isCancelled = true;
+                       log.debug("Thread " + Thread.currentThread().getId() + " died");
+                       throw e;
+               } catch (Exception e) {
+                       isCancelled = true;
+                       IOException ioe = new IOException(
+                                       "Unexpected issue in login dialog, see root cause for more details");
+                       ioe.initCause(e);
+                       throw ioe;
+               } finally {
+                       // so that the modal thread dies
+                       processCallbacks = true;
+                       // try {
+                       // // wait for the modal context thread to gracefully exit
+                       // modalContextThread.join();
+                       // } catch (InterruptedException ie) {
+                       // // silent
+                       // }
+                       modalContextThread = null;
+               }
+       }
+
+       protected void configureShell(Shell shell) {
+               super.configureShell(shell);
+               shell.setText("Authentication");
+       }
+}
diff --git a/org.argeo.security.ui/src/org/argeo/security/ui/dialogs/ChangePasswordDialog.java b/org.argeo.security.ui/src/org/argeo/security/ui/dialogs/ChangePasswordDialog.java
new file mode 100644 (file)
index 0000000..fe9b6ae
--- /dev/null
@@ -0,0 +1,90 @@
+/*
+ * Copyright (C) 2007-2012 Argeo GmbH
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *         http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.argeo.security.ui.dialogs;
+
+import org.argeo.ArgeoException;
+import org.argeo.eclipse.ui.ErrorFeedback;
+import org.eclipse.jface.dialogs.IMessageProvider;
+import org.eclipse.jface.dialogs.TitleAreaDialog;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.swt.widgets.Text;
+import org.springframework.security.userdetails.UserDetailsManager;
+
+/** Dialog to change the current user password */
+public class ChangePasswordDialog extends TitleAreaDialog {
+       private Text currentPassword, newPassword1, newPassword2;
+       private UserDetailsManager userDetailsManager;
+
+       public ChangePasswordDialog(Shell parentShell,
+                       UserDetailsManager securityService) {
+               super(parentShell);
+               this.userDetailsManager = securityService;
+       }
+
+       protected Point getInitialSize() {
+               return new Point(300, 250);
+       }
+
+       protected Control createDialogArea(Composite parent) {
+               Composite dialogarea = (Composite) super.createDialogArea(parent);
+               dialogarea.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
+               Composite composite = new Composite(dialogarea, SWT.NONE);
+               composite.setLayout(new GridLayout(2, false));
+               composite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
+               currentPassword = createLP(composite, "Current password");
+               newPassword1 = createLP(composite, "New password");
+               newPassword2 = createLP(composite, "Repeat new password");
+
+               setMessage("Change password", IMessageProvider.INFORMATION);
+               parent.pack();
+               return composite;
+       }
+
+       @Override
+       protected void okPressed() {
+               if (!newPassword1.getText().equals(newPassword2.getText()))
+                       throw new ArgeoException("Passwords are different");
+               try {
+                       userDetailsManager.changePassword(currentPassword.getText(),
+                                       newPassword1.getText());
+                       close();
+               } catch (Exception e) {
+                       ErrorFeedback.show("Cannot change password", e);
+               }
+       }
+
+       /** Creates label and password. */
+       protected Text createLP(Composite parent, String label) {
+               new Label(parent, SWT.NONE).setText(label);
+               Text text = new Text(parent, SWT.SINGLE | SWT.LEAD | SWT.PASSWORD
+                               | SWT.BORDER);
+               text.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
+               return text;
+       }
+
+       protected void configureShell(Shell shell) {
+               super.configureShell(shell);
+               shell.setText("Change password");
+       }
+
+}
diff --git a/org.argeo.security.ui/src/org/argeo/security/ui/dialogs/DefaultLoginDialog.java b/org.argeo.security.ui/src/org/argeo/security/ui/dialogs/DefaultLoginDialog.java
new file mode 100644 (file)
index 0000000..57ba01b
--- /dev/null
@@ -0,0 +1,189 @@
+/*
+ * Copyright (C) 2007-2012 Argeo GmbH
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *         http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.argeo.security.ui.dialogs;
+
+import javax.security.auth.callback.Callback;
+import javax.security.auth.callback.CallbackHandler;
+import javax.security.auth.callback.NameCallback;
+import javax.security.auth.callback.PasswordCallback;
+import javax.security.auth.callback.TextOutputCallback;
+
+import org.argeo.security.ui.SecurityUiPlugin;
+import org.argeo.util.LocaleCallback;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.ModifyEvent;
+import org.eclipse.swt.events.ModifyListener;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.events.SelectionListener;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.graphics.Rectangle;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Combo;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.swt.widgets.Text;
+
+/** Default authentication dialog, to be used as {@link CallbackHandler}. */
+public class DefaultLoginDialog extends AbstractLoginDialog {
+       public DefaultLoginDialog() {
+               this(SecurityUiPlugin.display.get().getActiveShell());
+       }
+
+       public DefaultLoginDialog(Shell parentShell) {
+               super(parentShell);
+       }
+
+       protected Point getInitialSize() {
+               return new Point(350, 180);
+       }
+
+       @Override
+       protected Control createContents(Composite parent) {
+               Control control = super.createContents(parent);
+               parent.pack();
+
+               // Move the dialog to the center of the top level shell.
+               Rectangle shellBounds;
+               if (Display.getCurrent().getActiveShell() != null) // RCP
+                       shellBounds = Display.getCurrent().getActiveShell().getBounds();
+               else
+                       shellBounds = Display.getCurrent().getBounds();// RAP
+               Point dialogSize = parent.getSize();
+               int x = shellBounds.x + (shellBounds.width - dialogSize.x) / 2;
+               int y = shellBounds.y + (shellBounds.height - dialogSize.y) / 2;
+               parent.setLocation(x, y);
+               return control;
+       }
+
+       protected Control createDialogArea(Composite parent) {
+               Composite dialogarea = (Composite) super.createDialogArea(parent);
+               Composite composite = new Composite(dialogarea, SWT.NONE);
+               composite.setLayout(new GridLayout(2, false));
+               composite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
+               createCallbackHandlers(composite);
+               // parent.pack();
+               return composite;
+       }
+
+       private void createCallbackHandlers(Composite composite) {
+               Callback[] callbacks = getCallbacks();
+               for (int i = 0; i < callbacks.length; i++) {
+                       Callback callback = callbacks[i];
+                       if (callback instanceof TextOutputCallback) {
+                               createLabelTextoutputHandler(composite,
+                                               (TextOutputCallback) callback);
+                       } else if (callback instanceof NameCallback) {
+                               createNameHandler(composite, (NameCallback) callback);
+                       } else if (callback instanceof PasswordCallback) {
+                               createPasswordHandler(composite, (PasswordCallback) callback);
+                       } else if (callback instanceof LocaleCallback) {
+                               createLocaleHandler(composite, (LocaleCallback) callback);
+                       }
+               }
+       }
+
+       private void createPasswordHandler(Composite composite,
+                       final PasswordCallback callback) {
+               Label label = new Label(composite, SWT.NONE);
+               label.setText(callback.getPrompt());
+               final Text passwordText = new Text(composite, SWT.SINGLE | SWT.LEAD
+                               | SWT.PASSWORD | SWT.BORDER);
+               passwordText
+                               .setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
+               passwordText.addModifyListener(new ModifyListener() {
+
+                       public void modifyText(ModifyEvent event) {
+                               // FIXME use getTextChars() in Eclipse 3.7
+                               callback.setPassword(passwordText.getText().toCharArray());
+                       }
+               });
+       }
+
+       private void createLocaleHandler(Composite composite,
+                       final LocaleCallback callback) {
+               String[] labels = callback.getSupportedLocalesLabels();
+               if (labels.length == 0)
+                       return;
+               Label label = new Label(composite, SWT.NONE);
+               label.setText(callback.getPrompt());
+
+               final Combo combo = new Combo(composite, SWT.READ_ONLY);
+               combo.setItems(labels);
+               combo.select(callback.getDefaultIndex());
+               combo.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
+               combo.addSelectionListener(new SelectionListener() {
+                       @Override
+                       public void widgetSelected(SelectionEvent e) {
+                               callback.setSelectedIndex(combo.getSelectionIndex());
+                       }
+
+                       @Override
+                       public void widgetDefaultSelected(SelectionEvent e) {
+                       }
+               });
+       }
+
+       private void createNameHandler(Composite composite,
+                       final NameCallback callback) {
+               Label label = new Label(composite, SWT.NONE);
+               label.setText(callback.getPrompt());
+               final Text text = new Text(composite, SWT.SINGLE | SWT.LEAD
+                               | SWT.BORDER);
+               if (callback.getDefaultName() != null) {
+                       // set default value, if provided
+                       text.setText(callback.getDefaultName());
+                       callback.setName(callback.getDefaultName());
+               }
+               text.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
+               text.addModifyListener(new ModifyListener() {
+
+                       public void modifyText(ModifyEvent event) {
+                               callback.setName(text.getText());
+                       }
+               });
+       }
+
+       private void createLabelTextoutputHandler(Composite composite,
+                       final TextOutputCallback callback) {
+               Label label = new Label(composite, SWT.NONE);
+               label.setText(callback.getMessage());
+               GridData data = new GridData(SWT.FILL, SWT.FILL, true, true);
+               data.horizontalSpan = 2;
+               label.setLayoutData(data);
+               // TODO: find a way to pass this information
+               // int messageType = callback.getMessageType();
+               // int dialogMessageType = IMessageProvider.NONE;
+               // switch (messageType) {
+               // case TextOutputCallback.INFORMATION:
+               // dialogMessageType = IMessageProvider.INFORMATION;
+               // break;
+               // case TextOutputCallback.WARNING:
+               // dialogMessageType = IMessageProvider.WARNING;
+               // break;
+               // case TextOutputCallback.ERROR:
+               // dialogMessageType = IMessageProvider.ERROR;
+               // break;
+               // }
+               // setMessage(callback.getMessage(), dialogMessageType);
+       }
+
+       public void internalHandle() {
+       }
+}
diff --git a/org.argeo.security.ui/src/org/argeo/security/ui/internal/CurrentUser.java b/org.argeo.security.ui/src/org/argeo/security/ui/internal/CurrentUser.java
new file mode 100644 (file)
index 0000000..43ca588
--- /dev/null
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2007-2012 Argeo GmbH
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *         http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.argeo.security.ui.internal;
+
+import java.security.AccessController;
+import java.security.Principal;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Set;
+
+import javax.security.auth.Subject;
+
+import org.argeo.ArgeoException;
+import org.springframework.security.Authentication;
+import org.springframework.security.GrantedAuthority;
+
+/**
+ * Retrieves information about the current user. Not an API, can change without
+ * notice.
+ */
+public class CurrentUser {
+       public final static String getUsername() {
+               Subject subject = getSubject();
+               if (subject == null)
+                       return null;
+               Principal principal = subject.getPrincipals().iterator().next();
+               return principal.getName();
+
+       }
+
+       public final static Set<String> roles() {
+               Set<String> roles = Collections.synchronizedSet(new HashSet<String>());
+               Authentication authentication = getAuthentication();
+               for (GrantedAuthority ga : authentication.getAuthorities()) {
+                       roles.add(ga.getAuthority());
+               }
+               return Collections.unmodifiableSet(roles);
+       }
+
+       public final static Authentication getAuthentication() {
+               Set<Authentication> authens = getSubject().getPrincipals(
+                               Authentication.class);
+               if (authens != null && !authens.isEmpty()) {
+                       Principal principal = authens.iterator().next();
+                       Authentication authentication = (Authentication) principal;
+                       return authentication;
+               }
+               throw new ArgeoException("No authentication found");
+       }
+
+       public final static Subject getSubject() {
+               Subject subject = Subject.getSubject(AccessController.getContext());
+               if (subject == null)
+                       throw new ArgeoException("Not authenticated.");
+               return subject;
+       }
+}
diff --git a/org.argeo.security.ui/src/org/argeo/security/ui/views/AdminLogView.java b/org.argeo.security.ui/src/org/argeo/security/ui/views/AdminLogView.java
new file mode 100644 (file)
index 0000000..d59edf8
--- /dev/null
@@ -0,0 +1,88 @@
+/*
+ * Copyright (C) 2007-2012 Argeo GmbH
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *         http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.argeo.security.ui.views;
+
+import java.util.ArrayList;
+
+import org.argeo.ArgeoLogger;
+import org.argeo.security.ui.SecurityUiPlugin;
+import org.eclipse.jface.resource.JFaceResources;
+import org.eclipse.jface.viewers.LabelProvider;
+import org.eclipse.jface.viewers.TableViewer;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.graphics.Font;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Table;
+import org.eclipse.ui.part.ViewPart;
+
+/**
+ * Display log lines for all users with a virtual table.
+ */
+public class AdminLogView extends ViewPart {
+       public static String ID = SecurityUiPlugin.PLUGIN_ID + ".adminLogView";
+
+       private TableViewer viewer;
+
+       private LogContentProvider logContentProvider;
+       private ArgeoLogger argeoLogger;
+
+       @Override
+       public void createPartControl(Composite parent) {
+               // FIXME doesn't return a monospace font in RAP
+               Font font = JFaceResources.getTextFont();
+               Table table = new Table(parent, SWT.VIRTUAL | SWT.MULTI | SWT.H_SCROLL
+                               | SWT.V_SCROLL | SWT.FULL_SELECTION | SWT.BORDER);
+               table.setFont(font);
+
+               viewer = new TableViewer(table);
+               viewer.setLabelProvider(new LabelProvider());
+               logContentProvider = new LogContentProvider(viewer) {
+
+                       @Override
+                       protected StringBuffer prefix(String username, Long timestamp,
+                                       String level, String category, String thread) {
+                               return super
+                                               .prefix(username, timestamp, level, category, thread)
+                                               .append(norm(level, 5))
+                                               .append(' ')
+                                               .append(norm(username != null ? username
+                                                               : "<anonymous>", 16)).append(' ');
+                       }
+               };
+               viewer.setContentProvider(logContentProvider);
+               // viewer.setUseHashlookup(true);
+               viewer.setInput(new ArrayList<String>());
+
+               if (argeoLogger != null)
+                       argeoLogger.registerForAll(logContentProvider, 1000, true);
+       }
+
+       @Override
+       public void setFocus() {
+               viewer.getTable().setFocus();
+       }
+
+       @Override
+       public void dispose() {
+               if (argeoLogger != null)
+                       argeoLogger.unregisterForAll(logContentProvider);
+       }
+
+       public void setArgeoLogger(ArgeoLogger argeoLogger) {
+               this.argeoLogger = argeoLogger;
+       }
+
+}
diff --git a/org.argeo.security.ui/src/org/argeo/security/ui/views/LogContentProvider.java b/org.argeo.security.ui/src/org/argeo/security/ui/views/LogContentProvider.java
new file mode 100644 (file)
index 0000000..72f2059
--- /dev/null
@@ -0,0 +1,187 @@
+/*
+ * Copyright (C) 2007-2012 Argeo GmbH
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *         http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.argeo.security.ui.views;
+
+import java.text.DateFormat;
+import java.text.SimpleDateFormat;
+import java.util.Arrays;
+import java.util.Date;
+import java.util.LinkedList;
+import java.util.List;
+
+import org.argeo.ArgeoLogListener;
+import org.eclipse.jface.viewers.ILazyContentProvider;
+import org.eclipse.jface.viewers.TableViewer;
+import org.eclipse.jface.viewers.Viewer;
+import org.eclipse.swt.widgets.Table;
+import org.eclipse.swt.widgets.TableItem;
+
+/** A content provider maintaining an array of lines */
+class LogContentProvider implements ILazyContentProvider, ArgeoLogListener {
+       private DateFormat dateFormat = new SimpleDateFormat("HH:mm:ss");
+
+       private final Long start;
+       /** current - start = line number. first line is number '1' */
+       private Long current;
+
+       // TODO make it configurable
+       private final Integer maxLineBufferSize = 10 * 1000;
+
+       private final TableViewer viewer;
+       private LinkedList<LogLine> lines;
+
+       public LogContentProvider(TableViewer viewer) {
+               this.viewer = viewer;
+               start = System.currentTimeMillis();
+               lines = new LinkedList<LogLine>();
+               current = start;
+       }
+
+       public synchronized void dispose() {
+               lines.clear();
+               lines = null;
+       }
+
+       @SuppressWarnings("unchecked")
+       public synchronized void inputChanged(Viewer viewer, Object oldInput,
+                       Object newInput) {
+               List<String> lin = (List<String>) newInput;
+               if (lin == null)
+                       return;
+               for (String line : lin) {
+                       addLine(line);
+               }
+               this.viewer.setItemCount(lines.size());
+       }
+
+       public void updateElement(int index) {
+               viewer.replace(lines.get(index), index);
+       }
+
+       public synchronized void appendLog(String username, Long timestamp,
+                       String level, String category, String thread, Object msg,
+                       String[] exception) {
+               // check if valid
+               if (lines == null)
+                       return;
+
+               String message = msg.toString();
+               int count = 0;
+               String prefix = prefix(username, timestamp, level, category, thread)
+                               .toString();
+               // String suffix = suffix(username, timestamp, level, category, thread);
+               for (String line : message.split("\n")) {
+                       addLine(count == 0 ? prefix + line : line);
+                       count++;
+               }
+
+               if (exception != null) {
+                       for (String ste : exception) {
+                               addLine(ste);
+                       }
+               }
+
+               viewer.getTable().getDisplay().asyncExec(new Runnable() {
+                       public void run() {
+                               if (lines == null)
+                                       return;
+                               viewer.setItemCount(lines.size());
+                               // doesn't work with syncExec
+                               scrollToLastLine();
+                       }
+               });
+       }
+
+       protected StringBuffer prefix(String username, Long timestamp,
+                       String level, String category, String thread) {
+               StringBuffer buf = new StringBuffer("");
+               buf.append(dateFormat.format(new Date(timestamp))).append(" ");
+               // buf.append(level).append(" ");
+               return buf;
+       }
+
+       /** Normalize string to the given size */
+       protected String norm(String str, Integer size) {
+               int length = str.length();
+               if (length == size)
+                       return str;
+               else if (length > size)
+                       return str.substring(0, size);
+               else {
+                       char[] arr = new char[size - length];
+                       Arrays.fill(arr, ' ');
+                       return str + new String(arr);
+               }
+       }
+
+       // protected String suffix(String username, Long timestamp, String level,
+       // String category, String thread) {
+       // return "";
+       // }
+
+       /** Scroll to the last line */
+       protected synchronized void scrollToLastLine() {
+               // we try to show last line with two methods
+               // viewer.reveal(lines.peekLast());
+
+               Table table = viewer.getTable();
+               TableItem ti = table.getItem(table.getItemCount() - 1);
+               table.showItem(ti);
+       }
+
+       protected synchronized LogLine addLine(String line) {
+               // check for maximal size and purge if necessary
+               while (lines.size() >= maxLineBufferSize) {
+                       for (int i = 0; i < maxLineBufferSize / 10; i++) {
+                               lines.poll();
+                       }
+               }
+
+               current++;
+               LogLine logLine = new LogLine(current, line);
+               lines.add(logLine);
+               return logLine;
+       }
+
+       private class LogLine {
+               private Long linenumber;
+               private String message;
+
+               public LogLine(Long linenumber, String message) {
+                       this.linenumber = linenumber;
+                       this.message = message;
+               }
+
+               @Override
+               public int hashCode() {
+                       return linenumber.intValue();
+               }
+
+               @Override
+               public boolean equals(Object obj) {
+                       if (obj instanceof LogLine)
+                               return ((LogLine) obj).linenumber.equals(linenumber);
+                       else
+                               return false;
+               }
+
+               @Override
+               public String toString() {
+                       return message;
+               }
+
+       }
+}
\ No newline at end of file
diff --git a/org.argeo.security.ui/src/org/argeo/security/ui/views/LogView.java b/org.argeo.security.ui/src/org/argeo/security/ui/views/LogView.java
new file mode 100644 (file)
index 0000000..c7c47b3
--- /dev/null
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2007-2012 Argeo GmbH
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *         http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.argeo.security.ui.views;
+
+import java.util.ArrayList;
+
+import org.argeo.ArgeoLogListener;
+import org.argeo.ArgeoLogger;
+import org.argeo.security.ui.SecurityUiPlugin;
+import org.eclipse.jface.resource.JFaceResources;
+import org.eclipse.jface.viewers.LabelProvider;
+import org.eclipse.jface.viewers.TableViewer;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.graphics.Font;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Table;
+import org.eclipse.ui.part.ViewPart;
+
+/**
+ * Display log lines with a virtual table. Register and unregisters a
+ * {@link ArgeoLogListener} via OSGi services.
+ */
+public class LogView extends ViewPart {
+       public static String ID = SecurityUiPlugin.PLUGIN_ID + ".logView";
+
+       private TableViewer viewer;
+
+       private LogContentProvider logContentProvider;
+       private ArgeoLogger argeoLogger;
+
+       @Override
+       public void createPartControl(Composite parent) {
+               Font font = JFaceResources.getTextFont();
+               Table table = new Table(parent, SWT.VIRTUAL | SWT.MULTI | SWT.H_SCROLL
+                               | SWT.V_SCROLL | SWT.FULL_SELECTION | SWT.BORDER);
+               table.setFont(font);
+
+               viewer = new TableViewer(table);
+               viewer.setLabelProvider(new LabelProvider());
+               logContentProvider = new LogContentProvider(viewer);
+               viewer.setContentProvider(logContentProvider);
+               // viewer.setUseHashlookup(true);
+               viewer.setInput(new ArrayList<String>());
+
+               if (argeoLogger != null)
+                       argeoLogger.register(logContentProvider, 1000);
+       }
+
+       @Override
+       public void setFocus() {
+               viewer.getTable().setFocus();
+       }
+
+       @Override
+       public void dispose() {
+               if (argeoLogger != null)
+                       argeoLogger.unregister(logContentProvider);
+       }
+
+       public void setArgeoLogger(ArgeoLogger argeoLogger) {
+               this.argeoLogger = argeoLogger;
+       }
+
+}
diff --git a/org.argeo.security.ui/src/org/argeo/security/ui/views/UserProfile.java b/org.argeo.security.ui/src/org/argeo/security/ui/views/UserProfile.java
new file mode 100644 (file)
index 0000000..3f1f000
--- /dev/null
@@ -0,0 +1,81 @@
+/*
+ * Copyright (C) 2007-2012 Argeo GmbH
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *         http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.argeo.security.ui.views;
+
+import java.util.TreeSet;
+
+import org.argeo.eclipse.ui.EclipseUiUtils;
+import org.argeo.security.ui.SecurityUiPlugin;
+import org.argeo.security.ui.internal.CurrentUser;
+import org.eclipse.jface.viewers.IStructuredContentProvider;
+import org.eclipse.jface.viewers.LabelProvider;
+import org.eclipse.jface.viewers.TableViewer;
+import org.eclipse.jface.viewers.Viewer;
+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.Table;
+import org.eclipse.ui.part.ViewPart;
+import org.springframework.security.Authentication;
+
+/** Information about the currently logged in user */
+public class UserProfile extends ViewPart {
+       public static String ID = SecurityUiPlugin.PLUGIN_ID + ".userProfile";
+
+       private TableViewer viewer;
+
+       @Override
+       public void createPartControl(Composite parent) {
+               parent.setLayout(new GridLayout(2, false));
+
+               Authentication authentication = CurrentUser.getAuthentication();
+               EclipseUiUtils.createGridLL(parent, "Name", authentication
+                               .getPrincipal().toString());
+               EclipseUiUtils.createGridLL(parent, "User ID",
+                               CurrentUser.getUsername());
+
+               // roles table
+               Table table = new Table(parent, SWT.V_SCROLL | SWT.BORDER);
+               table.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 2, 1));
+               table.setLinesVisible(false);
+               table.setHeaderVisible(false);
+               viewer = new TableViewer(table);
+               viewer.setContentProvider(new RolesContentProvider());
+               viewer.setLabelProvider(new LabelProvider());
+               getViewSite().setSelectionProvider(viewer);
+               viewer.setInput(getViewSite());
+       }
+
+       @Override
+       public void setFocus() {
+               viewer.getTable();
+       }
+
+       private class RolesContentProvider implements IStructuredContentProvider {
+               public Object[] getElements(Object inputElement) {
+                       return new TreeSet<String>(CurrentUser.roles()).toArray();
+               }
+
+               public void dispose() {
+               }
+
+               public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
+               }
+
+       }
+
+}
diff --git a/org.argeo.server.ads.server/bnd.bnd b/org.argeo.server.ads.server/bnd.bnd
new file mode 100644 (file)
index 0000000..71b51a3
--- /dev/null
@@ -0,0 +1,23 @@
+Spring-Context: META-INF/spring/*.xml;create-asynchronously:=false
+Import-Package: javax.naming.directory,\
+jdbm,\
+org.apache.directory.server.configuration,\
+org.apache.directory.server.core.authn,\
+org.apache.directory.server.core.authz,\
+org.apache.directory.server.core.collective,\
+org.apache.directory.server.core.configuration,\
+org.apache.directory.server.core.event,\
+org.apache.directory.server.core.exception,\
+org.apache.directory.server.core.normalization,\
+org.apache.directory.server.core.operational,\
+org.apache.directory.server.core.partition.impl.btree,\
+org.apache.directory.server.core.referral,\
+org.apache.directory.server.core.schema,\
+org.apache.directory.server.core.schema.bootstrap,\
+org.apache.directory.server.core.subtree,\
+org.apache.directory.server.jndi,\
+org.apache.directory.server.ldap.support.extended,\
+org.apache.directory.shared.asn1.codec,\
+org.argeo.server.ads,\
+org.springframework.beans.factory.config,\
+*
\ No newline at end of file
index 4e6c53721964d502ea3a34d8e9f117a31b4a9d47..3f491595a64248d7283df5240e86c6c8d87e4f21 100644 (file)
@@ -8,43 +8,4 @@
        </parent>
        <artifactId>org.argeo.server.ads.server</artifactId>
        <name>Commons Server Default ADS LDAP Server</name>
-       <build>
-               <plugins>
-                       <plugin>
-                               <groupId>org.apache.felix</groupId>
-                               <artifactId>maven-bundle-plugin</artifactId>
-                               <configuration>
-                                       <instructions>
-                                               <!-- Import-Package needs to be specified explicitly since BND doesn't 
-                                                       deal with custom Spring-Context instructions -->
-                                               <Spring-Context>META-INF/spring/*.xml;create-asynchronously:=false</Spring-Context>
-                                               <Import-Package>
-                                                       *,
-                                                       javax.naming.directory,
-                                                       jdbm,
-                                                       org.apache.directory.server.configuration,
-                                                       org.apache.directory.server.core.authn,
-                                                       org.apache.directory.server.core.authz,
-                                                       org.apache.directory.server.core.collective,
-                                                       org.apache.directory.server.core.configuration,
-                                                       org.apache.directory.server.core.event,
-                                                       org.apache.directory.server.core.exception,
-                                                       org.apache.directory.server.core.normalization,
-                                                       org.apache.directory.server.core.operational,
-                                                       org.apache.directory.server.core.partition.impl.btree,
-                                                       org.apache.directory.server.core.referral,
-                                                       org.apache.directory.server.core.schema,
-                                                       org.apache.directory.server.core.schema.bootstrap,
-                                                       org.apache.directory.server.core.subtree,
-                                                       org.apache.directory.server.jndi,
-                                                       org.apache.directory.server.ldap.support.extended,
-                                                       org.apache.directory.shared.asn1.codec,
-                                                       org.argeo.server.ads,
-                                                       org.springframework.beans.factory.config
-                                               </Import-Package>
-                                       </instructions>
-                               </configuration>
-                       </plugin>
-               </plugins>
-       </build>
 </project>
\ No newline at end of file
index ff41fbb4dd356738ea37e8d854b1d4a17585bd63..d2953a684d400476bf716ed6a6c3c3ae486fcd0e 100644 (file)
@@ -1,7 +1,9 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <classpath>
-       <classpathentry kind="src" output="target/classes" path="src/main/java"/>
-       <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6"/>
-       <classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
-       <classpathentry kind="output" path="bin"/>
+       <classpathentry kind="src" path="src" />
+       <classpathentry kind="con"
+               path="org.eclipse.pde.core.requiredPlugins" />
+       <classpathentry kind="con"
+               path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6" />
+       <classpathentry kind="output" path="bin" />
 </classpath>
diff --git a/org.argeo.server.ads/.settings/org.eclipse.jdt.core.prefs b/org.argeo.server.ads/.settings/org.eclipse.jdt.core.prefs
deleted file mode 100644 (file)
index 34d3d60..0000000
+++ /dev/null
@@ -1,67 +0,0 @@
-#Sun Feb 21 11:17:20 CET 2010
-eclipse.preferences.version=1
-org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.5
-org.eclipse.jdt.core.compiler.compliance=1.5
-org.eclipse.jdt.core.compiler.problem.annotationSuperInterface=warning
-org.eclipse.jdt.core.compiler.problem.autoboxing=ignore
-org.eclipse.jdt.core.compiler.problem.comparingIdentical=warning
-org.eclipse.jdt.core.compiler.problem.deadCode=warning
-org.eclipse.jdt.core.compiler.problem.deprecation=warning
-org.eclipse.jdt.core.compiler.problem.deprecationInDeprecatedCode=disabled
-org.eclipse.jdt.core.compiler.problem.deprecationWhenOverridingDeprecatedMethod=disabled
-org.eclipse.jdt.core.compiler.problem.discouragedReference=warning
-org.eclipse.jdt.core.compiler.problem.emptyStatement=ignore
-org.eclipse.jdt.core.compiler.problem.fallthroughCase=ignore
-org.eclipse.jdt.core.compiler.problem.fatalOptionalError=enabled
-org.eclipse.jdt.core.compiler.problem.fieldHiding=ignore
-org.eclipse.jdt.core.compiler.problem.finalParameterBound=warning
-org.eclipse.jdt.core.compiler.problem.finallyBlockNotCompletingNormally=warning
-org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
-org.eclipse.jdt.core.compiler.problem.hiddenCatchBlock=warning
-org.eclipse.jdt.core.compiler.problem.incompatibleNonInheritedInterfaceMethod=warning
-org.eclipse.jdt.core.compiler.problem.incompleteEnumSwitch=ignore
-org.eclipse.jdt.core.compiler.problem.indirectStaticAccess=ignore
-org.eclipse.jdt.core.compiler.problem.localVariableHiding=ignore
-org.eclipse.jdt.core.compiler.problem.methodWithConstructorName=warning
-org.eclipse.jdt.core.compiler.problem.missingDeprecatedAnnotation=ignore
-org.eclipse.jdt.core.compiler.problem.missingHashCodeMethod=ignore
-org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotation=ignore
-org.eclipse.jdt.core.compiler.problem.missingSerialVersion=warning
-org.eclipse.jdt.core.compiler.problem.missingSynchronizedOnInheritedMethod=ignore
-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.nullReference=warning
-org.eclipse.jdt.core.compiler.problem.overridingPackageDefaultMethod=warning
-org.eclipse.jdt.core.compiler.problem.parameterAssignment=ignore
-org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment=ignore
-org.eclipse.jdt.core.compiler.problem.potentialNullReference=ignore
-org.eclipse.jdt.core.compiler.problem.rawTypeReference=warning
-org.eclipse.jdt.core.compiler.problem.redundantNullCheck=ignore
-org.eclipse.jdt.core.compiler.problem.redundantSuperinterface=ignore
-org.eclipse.jdt.core.compiler.problem.specialParameterHidingField=disabled
-org.eclipse.jdt.core.compiler.problem.staticAccessReceiver=warning
-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.uncheckedTypeOperation=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.unqualifiedFieldAccess=ignore
-org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownException=ignore
-org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionExemptExceptionAndThrowable=enabled
-org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionIncludeDocCommentReference=enabled
-org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionWhenOverriding=disabled
-org.eclipse.jdt.core.compiler.problem.unusedImport=warning
-org.eclipse.jdt.core.compiler.problem.unusedLabel=warning
-org.eclipse.jdt.core.compiler.problem.unusedLocal=warning
-org.eclipse.jdt.core.compiler.problem.unusedParameter=ignore
-org.eclipse.jdt.core.compiler.problem.unusedParameterIncludeDocCommentReference=enabled
-org.eclipse.jdt.core.compiler.problem.unusedParameterWhenImplementingAbstract=disabled
-org.eclipse.jdt.core.compiler.problem.unusedParameterWhenOverridingConcrete=disabled
-org.eclipse.jdt.core.compiler.problem.unusedPrivateMember=warning
-org.eclipse.jdt.core.compiler.problem.unusedWarningToken=warning
-org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=warning
-org.eclipse.jdt.core.compiler.source=1.5
diff --git a/org.argeo.server.ads/.settings/org.maven.ide.eclipse.prefs b/org.argeo.server.ads/.settings/org.maven.ide.eclipse.prefs
deleted file mode 100644 (file)
index 8a80a77..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-#Mon Nov 23 13:34:22 CET 2009
-activeProfiles=
-eclipse.preferences.version=1
-fullBuildGoals=process-test-resources
-includeModules=false
-resolveWorkspaceProjects=true
-resourceFilterGoals=process-resources resources\:testResources
-skipCompilerPlugin=true
-version=1
index f883dc49f0c2e2e0c021f9dfa2ca3632ce4cad83..6e3ef5450f3399fd84ee0325e2e1b96a2ee271d9 100644 (file)
@@ -1,2 +1,2 @@
 additional.bundles = org.apache.directory.server.core
-source.. = src/main/java/
+source.. = src/
index 51e2a3d8342c3938ab2abdb7ccaf6e3ec6648120..d2a3e7391c66338ac5d63a362ed0d311aac3617c 100644 (file)
@@ -8,34 +8,6 @@
        </parent>
        <artifactId>org.argeo.server.ads</artifactId>
        <name>Commons Server Apache Directory Server</name>
-       <build>
-               <plugins>
-                       <plugin>
-                               <groupId>org.apache.maven.plugins</groupId>
-                               <artifactId>maven-compiler-plugin</artifactId>
-                       </plugin>
-                       <plugin>
-                               <groupId>org.apache.maven.plugins</groupId>
-                               <artifactId>maven-source-plugin</artifactId>
-                       </plugin>
-                       <plugin>
-                               <groupId>org.apache.maven.plugins</groupId>
-                               <artifactId>maven-jar-plugin</artifactId>
-                       </plugin>
-                       <plugin>
-                               <groupId>org.apache.felix</groupId>
-                               <artifactId>maven-bundle-plugin</artifactId>
-
-                               <configuration>
-                                       <instructions>
-                                               <Export-Package>
-                                                       org.argeo.server.ads.*
-                                               </Export-Package>
-                                       </instructions>
-                               </configuration>
-                       </plugin>
-               </plugins>
-       </build>
        <dependencies>
                <dependency>
                        <groupId>org.argeo.commons</groupId>
diff --git a/org.argeo.server.ads/src/main/java/org/argeo/server/ads/AdsContainer.java b/org.argeo.server.ads/src/main/java/org/argeo/server/ads/AdsContainer.java
deleted file mode 100644 (file)
index e95cd8f..0000000
+++ /dev/null
@@ -1,243 +0,0 @@
-/*
- * Copyright (C) 2007-2012 Argeo GmbH
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *         http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.argeo.server.ads;
-
-import java.io.BufferedReader;
-import java.io.File;
-import java.io.FileWriter;
-import java.io.IOException;
-import java.io.InputStreamReader;
-import java.io.Writer;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Properties;
-
-import javax.naming.Context;
-import javax.naming.InitialContext;
-import javax.naming.NamingException;
-import javax.naming.directory.InitialDirContext;
-
-import org.apache.commons.io.FileUtils;
-import org.apache.commons.io.IOUtils;
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.apache.directory.server.configuration.MutableServerStartupConfiguration;
-import org.apache.directory.server.core.configuration.ShutdownConfiguration;
-import org.apache.directory.server.jndi.ServerContextFactory;
-import org.argeo.ArgeoException;
-import org.springframework.beans.factory.DisposableBean;
-import org.springframework.beans.factory.InitializingBean;
-import org.springframework.core.io.Resource;
-import org.springframework.util.Assert;
-
-/** Wraps an Apache Directory Server instance. */
-@SuppressWarnings("restriction")
-public class AdsContainer implements InitializingBean, DisposableBean {
-       private final static Log log = LogFactory.getLog(AdsContainer.class);
-
-       private MutableServerStartupConfiguration configuration;
-       private Properties environment = null;
-       private File workingDirectory = new File(
-                       System.getProperty("java.io.tmpdir") + File.separator
-                                       + "argeo-apacheDirectoryServer");
-       private Boolean deleteWorkingDirOnExit = false;
-
-       // LDIF
-       private List<Resource> ldifs = new ArrayList<Resource>();
-       private List<String> ignoredLdifAttributes = new ArrayList<String>();
-       /** default is 'demo' */
-       private String ldifPassword = "e1NIQX1pZVNWNTVRYytlUU9hWURSU2hhL0Fqek5USkU9";
-       private String ldifPasswordAttribute = "userPassword";
-       private File ldifDirectory;
-
-       @SuppressWarnings("unchecked")
-       public void afterPropertiesSet() throws Exception {
-
-               log.info("Starting directory server with id '"
-                               + configuration.getInstanceId() + "' in directory "
-                               + workingDirectory.getAbsolutePath());
-
-               if (deleteWorkingDirOnExit && workingDirectory.exists()) {
-                       log.warn("Found existing directory " + workingDirectory
-                                       + " deleting it...");
-                       FileUtils.deleteDirectory(workingDirectory);
-               }
-               configuration.setWorkingDirectory(workingDirectory);
-               workingDirectory.mkdirs();
-
-               if (ldifDirectory != null)
-                       configuration.setLdifDirectory(ldifDirectory);
-               else
-                       configuration.setLdifDirectory(new File(workingDirectory
-                                       .getAbsolutePath() + File.separator + "ldif"));
-
-               if (ignoredLdifAttributes.size() == 0) {
-                       ignoredLdifAttributes.add("entryUUID");
-                       ignoredLdifAttributes.add("structuralObjectClass");
-                       ignoredLdifAttributes.add("creatorsName");
-                       ignoredLdifAttributes.add("createTimestamp");
-                       ignoredLdifAttributes.add("entryCSN");
-                       ignoredLdifAttributes.add("modifiersName");
-                       ignoredLdifAttributes.add("modifyTimestamp");
-               }
-
-               // Process provided LDIF files
-               if (ldifs.size() > 0)
-                       configuration.getLdifDirectory().mkdirs();
-               for (Resource ldif : ldifs) {
-                       File targetFile = new File(configuration.getLdifDirectory()
-                                       .getAbsolutePath()
-                                       + File.separator
-                                       + ldif.getFilename().replace(':', '_'));
-                       processLdif(ldif, targetFile);
-               }
-
-               Properties env = new Properties();
-               env.setProperty(Context.INITIAL_CONTEXT_FACTORY,
-                               ServerContextFactory.class.getName());
-               Assert.notNull(environment);
-               env.putAll(environment);
-               env.putAll(configuration.toJndiEnvironment());
-
-               try {
-                       new InitialDirContext(env);
-               } catch (NamingException e) {
-                       throw new ArgeoException("Failed to start Apache Directory server",
-                                       e);
-               }
-       }
-
-       /**
-        * Processes an LDIF resource, filtering out attributes that cannot be
-        * imported in ADS and forcing a password.
-        */
-       protected void processLdif(Resource ldif, File targetFile) {
-               BufferedReader reader = null;
-               Writer writer = null;
-               try {
-                       reader = new BufferedReader(new InputStreamReader(
-                                       ldif.getInputStream()));
-                       writer = new FileWriter(targetFile);
-                       String line = null;
-                       lines: while ((line = reader.readLine()) != null) {
-                               // comment and empty lines
-                               if (line.trim().equals("") || line.startsWith("#")) {
-                                       writer.write(line);
-                                       writer.write('\n');
-                                       continue lines;
-                               }
-
-                               String[] tokens = line.split(":");
-                               String attribute = null;
-                               if (tokens != null && tokens.length > 1) {
-                                       attribute = tokens[0].trim();
-                                       if (ignoredLdifAttributes.contains(attribute))
-                                               continue lines;// ignore
-
-                                       if (attribute.equals("bdb_db_open")) {
-                                               log.warn("Ignored OpenLDAP output\n" + line);
-                                               continue lines;
-                                       }
-
-                                       if (ldifPassword != null
-                                                       && attribute.equals(ldifPasswordAttribute)) {
-                                               line = ldifPasswordAttribute + ":: " + ldifPassword;
-                                       }
-
-                                       writer.write(line);
-                                       writer.write('\n');
-                               } else {
-                                       log.warn("Ignored LDIF line\n" + line);
-                               }
-                       }
-                       if (log.isDebugEnabled())
-                               log.debug("Processed " + ldif + " to LDIF directory "
-                                               + configuration.getLdifDirectory());
-               } catch (IOException e) {
-                       throw new ArgeoException("Cannot process LDIF " + ldif, e);
-               } finally {
-                       IOUtils.closeQuietly(reader);
-                       IOUtils.closeQuietly(writer);
-               }
-       }
-
-       @SuppressWarnings("unchecked")
-       public void destroy() throws Exception {
-               ShutdownConfiguration shutdown = new ShutdownConfiguration(
-                               configuration.getInstanceId());
-
-               Properties env = new Properties();
-               env.setProperty(Context.INITIAL_CONTEXT_FACTORY,
-                               ServerContextFactory.class.getName());
-               Assert.notNull(environment);
-               env.putAll(environment);
-               env.putAll(shutdown.toJndiEnvironment());
-
-               log.info("Shutting down directory server with id '"
-                               + configuration.getInstanceId() + "'");
-
-               try {
-                       new InitialContext(env);
-               } catch (NamingException e) {
-                       throw new ArgeoException("Failed to stop Apache Directory server",
-                                       e);
-               }
-
-               if (workingDirectory.exists() && deleteWorkingDirOnExit) {
-                       if (log.isDebugEnabled())
-                               log.debug("Delete Apache DS working dir " + workingDirectory);
-                       FileUtils.deleteDirectory(workingDirectory);
-               }
-
-       }
-
-       public void setConfiguration(MutableServerStartupConfiguration configuration) {
-               this.configuration = configuration;
-       }
-
-       public void setWorkingDirectory(File workingDirectory) {
-               this.workingDirectory = workingDirectory;
-       }
-
-       public void setEnvironment(Properties environment) {
-               this.environment = environment;
-       }
-
-       public void setLdifs(List<Resource> ldifs) {
-               this.ldifs = ldifs;
-       }
-
-       public void setLdifDirectory(File ldifDirectory) {
-               this.ldifDirectory = ldifDirectory;
-       }
-
-       public void setDeleteWorkingDirOnExit(Boolean deleteWorkingDirOnExit) {
-               this.deleteWorkingDirOnExit = deleteWorkingDirOnExit;
-       }
-
-       public void setIgnoredLdifAttributes(List<String> ignoredLdifAttributes) {
-               this.ignoredLdifAttributes = ignoredLdifAttributes;
-       }
-
-       public void setLdifPassword(String ldifPassword) {
-               this.ldifPassword = ldifPassword;
-       }
-
-       public void setLdifPasswordAttribute(String ldifPasswordAttribute) {
-               this.ldifPasswordAttribute = ldifPasswordAttribute;
-       }
-
-}
diff --git a/org.argeo.server.ads/src/org/argeo/server/ads/AdsContainer.java b/org.argeo.server.ads/src/org/argeo/server/ads/AdsContainer.java
new file mode 100644 (file)
index 0000000..e95cd8f
--- /dev/null
@@ -0,0 +1,243 @@
+/*
+ * Copyright (C) 2007-2012 Argeo GmbH
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *         http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.argeo.server.ads;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.io.Writer;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Properties;
+
+import javax.naming.Context;
+import javax.naming.InitialContext;
+import javax.naming.NamingException;
+import javax.naming.directory.InitialDirContext;
+
+import org.apache.commons.io.FileUtils;
+import org.apache.commons.io.IOUtils;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.directory.server.configuration.MutableServerStartupConfiguration;
+import org.apache.directory.server.core.configuration.ShutdownConfiguration;
+import org.apache.directory.server.jndi.ServerContextFactory;
+import org.argeo.ArgeoException;
+import org.springframework.beans.factory.DisposableBean;
+import org.springframework.beans.factory.InitializingBean;
+import org.springframework.core.io.Resource;
+import org.springframework.util.Assert;
+
+/** Wraps an Apache Directory Server instance. */
+@SuppressWarnings("restriction")
+public class AdsContainer implements InitializingBean, DisposableBean {
+       private final static Log log = LogFactory.getLog(AdsContainer.class);
+
+       private MutableServerStartupConfiguration configuration;
+       private Properties environment = null;
+       private File workingDirectory = new File(
+                       System.getProperty("java.io.tmpdir") + File.separator
+                                       + "argeo-apacheDirectoryServer");
+       private Boolean deleteWorkingDirOnExit = false;
+
+       // LDIF
+       private List<Resource> ldifs = new ArrayList<Resource>();
+       private List<String> ignoredLdifAttributes = new ArrayList<String>();
+       /** default is 'demo' */
+       private String ldifPassword = "e1NIQX1pZVNWNTVRYytlUU9hWURSU2hhL0Fqek5USkU9";
+       private String ldifPasswordAttribute = "userPassword";
+       private File ldifDirectory;
+
+       @SuppressWarnings("unchecked")
+       public void afterPropertiesSet() throws Exception {
+
+               log.info("Starting directory server with id '"
+                               + configuration.getInstanceId() + "' in directory "
+                               + workingDirectory.getAbsolutePath());
+
+               if (deleteWorkingDirOnExit && workingDirectory.exists()) {
+                       log.warn("Found existing directory " + workingDirectory
+                                       + " deleting it...");
+                       FileUtils.deleteDirectory(workingDirectory);
+               }
+               configuration.setWorkingDirectory(workingDirectory);
+               workingDirectory.mkdirs();
+
+               if (ldifDirectory != null)
+                       configuration.setLdifDirectory(ldifDirectory);
+               else
+                       configuration.setLdifDirectory(new File(workingDirectory
+                                       .getAbsolutePath() + File.separator + "ldif"));
+
+               if (ignoredLdifAttributes.size() == 0) {
+                       ignoredLdifAttributes.add("entryUUID");
+                       ignoredLdifAttributes.add("structuralObjectClass");
+                       ignoredLdifAttributes.add("creatorsName");
+                       ignoredLdifAttributes.add("createTimestamp");
+                       ignoredLdifAttributes.add("entryCSN");
+                       ignoredLdifAttributes.add("modifiersName");
+                       ignoredLdifAttributes.add("modifyTimestamp");
+               }
+
+               // Process provided LDIF files
+               if (ldifs.size() > 0)
+                       configuration.getLdifDirectory().mkdirs();
+               for (Resource ldif : ldifs) {
+                       File targetFile = new File(configuration.getLdifDirectory()
+                                       .getAbsolutePath()
+                                       + File.separator
+                                       + ldif.getFilename().replace(':', '_'));
+                       processLdif(ldif, targetFile);
+               }
+
+               Properties env = new Properties();
+               env.setProperty(Context.INITIAL_CONTEXT_FACTORY,
+                               ServerContextFactory.class.getName());
+               Assert.notNull(environment);
+               env.putAll(environment);
+               env.putAll(configuration.toJndiEnvironment());
+
+               try {
+                       new InitialDirContext(env);
+               } catch (NamingException e) {
+                       throw new ArgeoException("Failed to start Apache Directory server",
+                                       e);
+               }
+       }
+
+       /**
+        * Processes an LDIF resource, filtering out attributes that cannot be
+        * imported in ADS and forcing a password.
+        */
+       protected void processLdif(Resource ldif, File targetFile) {
+               BufferedReader reader = null;
+               Writer writer = null;
+               try {
+                       reader = new BufferedReader(new InputStreamReader(
+                                       ldif.getInputStream()));
+                       writer = new FileWriter(targetFile);
+                       String line = null;
+                       lines: while ((line = reader.readLine()) != null) {
+                               // comment and empty lines
+                               if (line.trim().equals("") || line.startsWith("#")) {
+                                       writer.write(line);
+                                       writer.write('\n');
+                                       continue lines;
+                               }
+
+                               String[] tokens = line.split(":");
+                               String attribute = null;
+                               if (tokens != null && tokens.length > 1) {
+                                       attribute = tokens[0].trim();
+                                       if (ignoredLdifAttributes.contains(attribute))
+                                               continue lines;// ignore
+
+                                       if (attribute.equals("bdb_db_open")) {
+                                               log.warn("Ignored OpenLDAP output\n" + line);
+                                               continue lines;
+                                       }
+
+                                       if (ldifPassword != null
+                                                       && attribute.equals(ldifPasswordAttribute)) {
+                                               line = ldifPasswordAttribute + ":: " + ldifPassword;
+                                       }
+
+                                       writer.write(line);
+                                       writer.write('\n');
+                               } else {
+                                       log.warn("Ignored LDIF line\n" + line);
+                               }
+                       }
+                       if (log.isDebugEnabled())
+                               log.debug("Processed " + ldif + " to LDIF directory "
+                                               + configuration.getLdifDirectory());
+               } catch (IOException e) {
+                       throw new ArgeoException("Cannot process LDIF " + ldif, e);
+               } finally {
+                       IOUtils.closeQuietly(reader);
+                       IOUtils.closeQuietly(writer);
+               }
+       }
+
+       @SuppressWarnings("unchecked")
+       public void destroy() throws Exception {
+               ShutdownConfiguration shutdown = new ShutdownConfiguration(
+                               configuration.getInstanceId());
+
+               Properties env = new Properties();
+               env.setProperty(Context.INITIAL_CONTEXT_FACTORY,
+                               ServerContextFactory.class.getName());
+               Assert.notNull(environment);
+               env.putAll(environment);
+               env.putAll(shutdown.toJndiEnvironment());
+
+               log.info("Shutting down directory server with id '"
+                               + configuration.getInstanceId() + "'");
+
+               try {
+                       new InitialContext(env);
+               } catch (NamingException e) {
+                       throw new ArgeoException("Failed to stop Apache Directory server",
+                                       e);
+               }
+
+               if (workingDirectory.exists() && deleteWorkingDirOnExit) {
+                       if (log.isDebugEnabled())
+                               log.debug("Delete Apache DS working dir " + workingDirectory);
+                       FileUtils.deleteDirectory(workingDirectory);
+               }
+
+       }
+
+       public void setConfiguration(MutableServerStartupConfiguration configuration) {
+               this.configuration = configuration;
+       }
+
+       public void setWorkingDirectory(File workingDirectory) {
+               this.workingDirectory = workingDirectory;
+       }
+
+       public void setEnvironment(Properties environment) {
+               this.environment = environment;
+       }
+
+       public void setLdifs(List<Resource> ldifs) {
+               this.ldifs = ldifs;
+       }
+
+       public void setLdifDirectory(File ldifDirectory) {
+               this.ldifDirectory = ldifDirectory;
+       }
+
+       public void setDeleteWorkingDirOnExit(Boolean deleteWorkingDirOnExit) {
+               this.deleteWorkingDirOnExit = deleteWorkingDirOnExit;
+       }
+
+       public void setIgnoredLdifAttributes(List<String> ignoredLdifAttributes) {
+               this.ignoredLdifAttributes = ignoredLdifAttributes;
+       }
+
+       public void setLdifPassword(String ldifPassword) {
+               this.ldifPassword = ldifPassword;
+       }
+
+       public void setLdifPasswordAttribute(String ldifPasswordAttribute) {
+               this.ldifPasswordAttribute = ldifPasswordAttribute;
+       }
+
+}
index e9c521af644948148fc8c8c94be83b38531935b9..d2953a684d400476bf716ed6a6c3c3ae486fcd0e 100644 (file)
@@ -1,8 +1,9 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <classpath>
-       <classpathentry kind="src" output="target/classes" path="src/main/java"/>
-       <classpathentry kind="src" output="target/classes" path="src/main/resources"/>
-       <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6"/>>>
-       <classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
-       <classpathentry kind="output" path="bin"/>
+       <classpathentry kind="src" path="src" />
+       <classpathentry kind="con"
+               path="org.eclipse.pde.core.requiredPlugins" />
+       <classpathentry kind="con"
+               path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6" />
+       <classpathentry kind="output" path="bin" />
 </classpath>
diff --git a/org.argeo.server.jackrabbit/bnd.bnd b/org.argeo.server.jackrabbit/bnd.bnd
new file mode 100644 (file)
index 0000000..df9b79b
--- /dev/null
@@ -0,0 +1,8 @@
+Import-Package: javax.servlet,\
+org.apache.jackrabbit.webdav.server,\
+org.springframework.web.context,\
+org.osgi.framework;version="0.0.0",\
+org.xml.sax;version="0.0.0",\
+org.apache.jackrabbit.webdav.jcr,\
+org.springframework.beans,\
+*
index 722c27c7337ffceaeef0b1a9347593b7f0577eb4..d32561da6451daa9812fc78bb6513a93a26dd36c 100644 (file)
@@ -6,5 +6,4 @@ additional.bundles = slf4j.api,\
                      org.h2,\
                      org.apache.lucene,\
                      org.springframework.context
-source.. = src/main/java/,\
-           src/main/resources/
+source.. = src/
index 3de65ea2fdc85458f94fd048f093ba1dc6d3b1b2..e2edf43b92e40ffeff80ec26e679f0a1ff84c537 100644 (file)
        </parent>
        <artifactId>org.argeo.server.jackrabbit</artifactId>
        <name>Commons Server Jackrabbit</name>
-       <build>
-               <plugins>
-                       <plugin>
-                               <groupId>org.apache.maven.plugins</groupId>
-                               <artifactId>maven-compiler-plugin</artifactId>
-                       </plugin>
-                       <plugin>
-                               <groupId>org.apache.maven.plugins</groupId>
-                               <artifactId>maven-source-plugin</artifactId>
-                       </plugin>
-                       <plugin>
-                               <groupId>org.apache.maven.plugins</groupId>
-                               <artifactId>maven-jar-plugin</artifactId>
-                       </plugin>
-                       <plugin>
-                               <groupId>org.apache.felix</groupId>
-                               <artifactId>maven-bundle-plugin</artifactId>
-                               <configuration>
-                                       <instructions>
-                                               <Export-Package>
-                                                       org.argeo.jackrabbit.*,
-                                               </Export-Package>
-                                               <Import-Package>
-                                                       javax.servlet,
-                                                       org.apache.jackrabbit.webdav.server,
-                                                       org.springframework.web.context,
-                                                       org.osgi.framework;version="0.0.0",
-                                                       org.xml.sax;version="0.0.0",
-                                                       org.apache.jackrabbit.webdav.jcr,
-                                                       org.springframework.beans,
-                                                       *
-                                               </Import-Package>
-                                       </instructions>
-                               </configuration>
-                       </plugin>
-               </plugins>
-       </build>
        <dependencies>
                <dependency>
                        <groupId>org.argeo.commons</groupId>
diff --git a/org.argeo.server.jackrabbit/src/main/java/org/argeo/jackrabbit/JackrabbitAuthorizations.java b/org.argeo.server.jackrabbit/src/main/java/org/argeo/jackrabbit/JackrabbitAuthorizations.java
deleted file mode 100644 (file)
index e880b67..0000000
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- * Copyright (C) 2007-2012 Argeo GmbH
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *         http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.argeo.jackrabbit;
-
-import java.security.Principal;
-import java.util.Arrays;
-import java.util.List;
-
-import javax.jcr.RepositoryException;
-import javax.jcr.Session;
-
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.apache.jackrabbit.api.JackrabbitSession;
-import org.apache.jackrabbit.api.security.user.Authorizable;
-import org.apache.jackrabbit.api.security.user.UserManager;
-import org.argeo.ArgeoException;
-import org.argeo.jcr.security.JcrAuthorizations;
-
-/** Apply authorizations to a Jackrabbit repository. */
-public class JackrabbitAuthorizations extends JcrAuthorizations {
-       private final static Log log = LogFactory
-                       .getLog(JackrabbitAuthorizations.class);
-
-       private List<String> groupPrefixes = Arrays
-                       .asList(new String[] { "ROLE_" });// new ArrayList<String>();
-
-       @Override
-       protected Principal getOrCreatePrincipal(Session session,
-                       String principalName) throws RepositoryException {
-               UserManager um = ((JackrabbitSession) session).getUserManager();
-               synchronized (um) {
-                       Authorizable authorizable = um.getAuthorizable(principalName);
-                       if (authorizable == null) {
-                               groupPrefixes: for (String groupPrefix : groupPrefixes) {
-                                       if (principalName.startsWith(groupPrefix)) {
-                                               authorizable = um.createGroup(principalName);
-                                               log.info("Created group " + principalName);
-                                               break groupPrefixes;
-                                       }
-                               }
-                               if (authorizable == null)
-                                       throw new ArgeoException("Authorizable " + principalName
-                                                       + " not found");
-                       }
-                       return authorizable.getPrincipal();
-               }
-       }
-
-       public void setGroupPrefixes(List<String> groupsToCreate) {
-               this.groupPrefixes = groupsToCreate;
-       }
-}
diff --git a/org.argeo.server.jackrabbit/src/main/java/org/argeo/jackrabbit/JackrabbitContainer.java b/org.argeo.server.jackrabbit/src/main/java/org/argeo/jackrabbit/JackrabbitContainer.java
deleted file mode 100644 (file)
index 9060b58..0000000
+++ /dev/null
@@ -1,352 +0,0 @@
-/*
- * Copyright (C) 2007-2012 Argeo GmbH
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *         http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.argeo.jackrabbit;
-
-import java.io.File;
-import java.io.IOException;
-import java.io.InputStream;
-import java.util.HashSet;
-import java.util.Map;
-import java.util.Properties;
-import java.util.Set;
-import java.util.TreeSet;
-import java.util.UUID;
-
-import javax.jcr.Node;
-import javax.jcr.Repository;
-import javax.jcr.RepositoryException;
-import javax.jcr.Session;
-
-import org.apache.commons.io.FileUtils;
-import org.apache.commons.io.IOUtils;
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.apache.jackrabbit.api.JackrabbitRepository;
-import org.apache.jackrabbit.core.RepositoryImpl;
-import org.apache.jackrabbit.core.config.RepositoryConfig;
-import org.apache.jackrabbit.core.config.RepositoryConfigurationParser;
-import org.argeo.ArgeoException;
-import org.argeo.jcr.ArgeoNames;
-import org.argeo.jcr.JcrUtils;
-import org.argeo.jcr.MaintainedRepository;
-import org.springframework.core.io.Resource;
-import org.springframework.util.SystemPropertyUtils;
-import org.xml.sax.InputSource;
-
-/**
- * Wrapper around a Jackrabbit repository which allows to configure it in Spring
- * and expose it as a {@link Repository}.
- */
-public class JackrabbitContainer extends JackrabbitWrapper implements
-               MaintainedRepository {
-       private final static Log log = LogFactory.getLog(JackrabbitContainer.class);
-
-       // local
-       private Resource configuration;
-       private Resource variables;
-       private RepositoryConfig repositoryConfig;
-       private File homeDirectory;
-       private Boolean inMemory = false;
-
-       /** Migrations to execute (if not already done) */
-       private Set<JackrabbitDataModelMigration> dataModelMigrations = new HashSet<JackrabbitDataModelMigration>();
-
-       /**
-        * Empty constructor, {@link #init()} should be called after properties have
-        * been set
-        */
-       public JackrabbitContainer() {
-       }
-
-       public void init() {
-               long begin = System.currentTimeMillis();
-
-               if (getRepository() != null)
-                       throw new ArgeoException(
-                                       "Cannot be used to wrap another repository");
-               Repository repository = createJackrabbitRepository();
-               super.setRepository(repository);
-
-               // migrate if needed
-               migrate();
-
-               // apply new CND files after migration
-               prepareDataModel();
-
-               double duration = ((double) (System.currentTimeMillis() - begin)) / 1000;
-               if (log.isDebugEnabled())
-                       log.debug("Initialized JCR repository wrapper in " + duration
-                                       + " s");
-       }
-
-       /** Actually creates the new repository. */
-       protected Repository createJackrabbitRepository() {
-               long begin = System.currentTimeMillis();
-               InputStream configurationIn = null;
-               Repository repository;
-               try {
-                       // temporary
-                       if (inMemory && getHomeDirectory().exists()) {
-                               FileUtils.deleteDirectory(getHomeDirectory());
-                               log.warn("Deleted Jackrabbit home directory "
-                                               + getHomeDirectory());
-                       }
-
-                       // process configuration file
-                       Properties vars = getConfigurationProperties();
-                       configurationIn = readConfiguration();
-                       vars.put(RepositoryConfigurationParser.REPOSITORY_HOME_VARIABLE,
-                                       getHomeDirectory().getCanonicalPath());
-                       repositoryConfig = RepositoryConfig.create(new InputSource(
-                                       configurationIn), vars);
-
-                       //
-                       // Actual repository creation
-                       //
-                       repository = RepositoryImpl.create(repositoryConfig);
-
-                       double duration = ((double) (System.currentTimeMillis() - begin)) / 1000;
-                       if (log.isTraceEnabled())
-                               log.trace("Created Jackrabbit repository in " + duration
-                                               + " s, home: " + getHomeDirectory());
-
-                       return repository;
-               } catch (Exception e) {
-                       throw new ArgeoException("Cannot create Jackrabbit repository "
-                                       + getHomeDirectory(), e);
-               } finally {
-                       IOUtils.closeQuietly(configurationIn);
-               }
-       }
-
-       /** Lazy init. */
-       protected File getHomeDirectory() {
-               try {
-                       if (homeDirectory == null) {
-                               if (inMemory) {
-                                       homeDirectory = new File(
-                                                       System.getProperty("java.io.tmpdir")
-                                                                       + File.separator
-                                                                       + System.getProperty("user.name")
-                                                                       + File.separator + "jackrabbit-"
-                                                                       + UUID.randomUUID());
-                                       homeDirectory.mkdirs();
-                                       // will it work if directory is not empty??
-                                       homeDirectory.deleteOnExit();
-                               }
-                       }
-
-                       return homeDirectory.getCanonicalFile();
-               } catch (IOException e) {
-                       throw new ArgeoException("Cannot get canonical file for "
-                                       + homeDirectory, e);
-               }
-       }
-
-       /** Executes migrations, if needed. */
-       protected void migrate() {
-               // No migration to perform
-               if (dataModelMigrations.size() == 0)
-                       return;
-
-               Boolean restartAndClearCaches = false;
-
-               // migrate data
-               Session session = null;
-               try {
-                       session = login();
-                       for (JackrabbitDataModelMigration dataModelMigration : new TreeSet<JackrabbitDataModelMigration>(
-                                       dataModelMigrations)) {
-                               if (dataModelMigration.migrate(session)) {
-                                       restartAndClearCaches = true;
-                               }
-                       }
-               } catch (ArgeoException e) {
-                       throw e;
-               } catch (Exception e) {
-                       throw new ArgeoException("Cannot migrate", e);
-               } finally {
-                       JcrUtils.logoutQuietly(session);
-               }
-
-               // restart repository
-               if (restartAndClearCaches) {
-                       Repository repository = getRepository();
-                       if (repository instanceof RepositoryImpl) {
-                               JackrabbitDataModelMigration
-                                               .clearRepositoryCaches(((RepositoryImpl) repository)
-                                                               .getConfig());
-                       }
-                       ((JackrabbitRepository) repository).shutdown();
-                       createJackrabbitRepository();
-               }
-
-               // set data model version
-               try {
-                       session = login();
-               } catch (RepositoryException e) {
-                       throw new ArgeoException("Cannot login to migrated repository", e);
-               }
-
-               for (JackrabbitDataModelMigration dataModelMigration : new TreeSet<JackrabbitDataModelMigration>(
-                               dataModelMigrations)) {
-                       try {
-                               if (session.itemExists(dataModelMigration
-                                               .getDataModelNodePath())) {
-                                       Node dataModelNode = session.getNode(dataModelMigration
-                                                       .getDataModelNodePath());
-                                       dataModelNode.setProperty(
-                                                       ArgeoNames.ARGEO_DATA_MODEL_VERSION,
-                                                       dataModelMigration.getTargetVersion());
-                                       session.save();
-                               }
-                       } catch (Exception e) {
-                               log.error("Cannot set model version", e);
-                       }
-               }
-               JcrUtils.logoutQuietly(session);
-
-       }
-
-       /** Shutdown the repository */
-       public void destroy() throws Exception {
-               Repository repository = getRepository();
-               if (repository != null && repository instanceof RepositoryImpl) {
-                       long begin = System.currentTimeMillis();
-                       ((RepositoryImpl) repository).shutdown();
-                       if (inMemory)
-                               if (getHomeDirectory().exists()) {
-                                       FileUtils.deleteDirectory(getHomeDirectory());
-                                       if (log.isDebugEnabled())
-                                               log.debug("Deleted Jackrabbit home directory "
-                                                               + getHomeDirectory());
-                               }
-                       double duration = ((double) (System.currentTimeMillis() - begin)) / 1000;
-                       log.info("Destroyed Jackrabbit repository in " + duration
-                                       + " s, home: " + getHomeDirectory());
-               }
-               repository = null;
-       }
-
-       public void dispose() {
-               throw new IllegalArgumentException(
-                               "Call destroy() method instead of dispose()");
-       }
-
-       /*
-        * UTILITIES
-        */
-       /**
-        * Reads the configuration which will initialize a {@link RepositoryConfig}.
-        */
-       protected InputStream readConfiguration() {
-               try {
-                       return configuration != null ? configuration.getInputStream()
-                                       : null;
-               } catch (IOException e) {
-                       throw new ArgeoException("Cannot read Jackrabbit configuration "
-                                       + configuration, e);
-               }
-       }
-
-       /**
-        * Reads the variables which will initialize a {@link Properties}. Returns
-        * null by default, to be overridden.
-        * 
-        * @return a new stream or null if no variables available
-        */
-       protected InputStream readVariables() {
-               try {
-                       return variables != null ? variables.getInputStream() : null;
-               } catch (IOException e) {
-                       throw new ArgeoException("Cannot read Jackrabbit variables "
-                                       + variables, e);
-               }
-       }
-
-       /**
-        * Resolves ${} placeholders in the provided string. Based on system
-        * properties if no map is provided.
-        */
-       protected String resolvePlaceholders(String string,
-                       Map<String, String> variables) {
-               return SystemPropertyUtils.resolvePlaceholders(string);
-       }
-
-       /** Generates the properties to use in the configuration. */
-       protected Properties getConfigurationProperties() {
-               InputStream propsIn = null;
-               Properties vars;
-               try {
-                       vars = new Properties();
-                       propsIn = readVariables();
-                       if (propsIn != null) {
-                               vars.load(propsIn);
-                       }
-                       // resolve system properties
-                       for (Object key : vars.keySet()) {
-                               // TODO: implement a smarter mechanism to resolve nested ${}
-                               String newValue = resolvePlaceholders(
-                                               vars.getProperty(key.toString()), null);
-                               vars.put(key, newValue);
-                       }
-                       // override with system properties
-                       vars.putAll(System.getProperties());
-
-                       if (log.isTraceEnabled()) {
-                               log.trace("Jackrabbit config variables:");
-                               for (Object key : new TreeSet<Object>(vars.keySet()))
-                                       log.trace(key + "=" + vars.getProperty(key.toString()));
-                       }
-
-               } catch (IOException e) {
-                       throw new ArgeoException("Cannot read configuration properties", e);
-               } finally {
-                       IOUtils.closeQuietly(propsIn);
-               }
-               return vars;
-       }
-
-       /*
-        * FIELDS ACCESS
-        */
-
-       public void setHomeDirectory(File homeDirectory) {
-               this.homeDirectory = homeDirectory;
-       }
-
-       public void setInMemory(Boolean inMemory) {
-               this.inMemory = inMemory;
-       }
-
-       public void setRepository(Repository repository) {
-               throw new ArgeoException("Cannot be used to wrap another repository");
-       }
-
-       public void setDataModelMigrations(
-                       Set<JackrabbitDataModelMigration> dataModelMigrations) {
-               this.dataModelMigrations = dataModelMigrations;
-       }
-
-       public void setVariables(Resource variables) {
-               this.variables = variables;
-       }
-
-       public void setConfiguration(Resource configuration) {
-               this.configuration = configuration;
-       }
-
-}
diff --git a/org.argeo.server.jackrabbit/src/main/java/org/argeo/jackrabbit/JackrabbitDataModelMigration.java b/org.argeo.server.jackrabbit/src/main/java/org/argeo/jackrabbit/JackrabbitDataModelMigration.java
deleted file mode 100644 (file)
index 401b34d..0000000
+++ /dev/null
@@ -1,182 +0,0 @@
-/*
- * Copyright (C) 2007-2012 Argeo GmbH
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *         http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.argeo.jackrabbit;
-
-import java.io.InputStreamReader;
-import java.io.Reader;
-
-import javax.jcr.Node;
-import javax.jcr.Session;
-
-import org.apache.commons.io.IOUtils;
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.apache.jackrabbit.commons.cnd.CndImporter;
-import org.apache.jackrabbit.core.config.RepositoryConfig;
-import org.argeo.ArgeoException;
-import org.argeo.jcr.ArgeoNames;
-import org.argeo.jcr.JcrCallback;
-import org.argeo.jcr.JcrUtils;
-import org.springframework.core.io.Resource;
-
-/** Migrate the data in a Jackrabbit repository. */
-public class JackrabbitDataModelMigration implements
-               Comparable<JackrabbitDataModelMigration> {
-       private final static Log log = LogFactory
-                       .getLog(JackrabbitDataModelMigration.class);
-
-       private String dataModelNodePath;
-       private String targetVersion;
-       private Resource migrationCnd;
-       private JcrCallback dataModification;
-
-       /**
-        * Expects an already started repository with the old data model to migrate.
-        * Expects to be run with admin rights (Repository.login() will be used).
-        * 
-        * @return true if a migration was performed and the repository needs to be
-        *         restarted and its caches cleared.
-        */
-       public Boolean migrate(Session session) {
-               long begin = System.currentTimeMillis();
-               Reader reader = null;
-               try {
-                       // check if already migrated
-                       if (!session.itemExists(dataModelNodePath)) {
-                               log.warn("Node " + dataModelNodePath
-                                               + " does not exist: nothing to migrate.");
-                               return false;
-                       }
-                       Node dataModelNode = session.getNode(dataModelNodePath);
-                       if (dataModelNode.hasProperty(ArgeoNames.ARGEO_DATA_MODEL_VERSION)) {
-                               String currentVersion = dataModelNode.getProperty(
-                                               ArgeoNames.ARGEO_DATA_MODEL_VERSION).getString();
-                               if (compareVersions(currentVersion, targetVersion) >= 0) {
-                                       log.info("Data model at version " + currentVersion
-                                                       + ", no need to migrate.");
-                                       return false;
-                               }
-                       }
-
-                       // apply transitional CND
-                       if (migrationCnd != null) {
-                               reader = new InputStreamReader(migrationCnd.getInputStream());
-                               CndImporter.registerNodeTypes(reader, session, true);
-                               session.save();
-                               log.info("Registered migration node types from " + migrationCnd);
-                       }
-
-                       // modify data
-                       dataModification.execute(session);
-
-                       // apply changes
-                       session.save();
-
-                       long duration = System.currentTimeMillis() - begin;
-                       log.info("Migration of data model " + dataModelNodePath + " to "
-                                       + targetVersion + " performed in " + duration + "ms");
-                       return true;
-               } catch (Exception e) {
-                       JcrUtils.discardQuietly(session);
-                       throw new ArgeoException("Migration of data model "
-                                       + dataModelNodePath + " to " + targetVersion + " failed.",
-                                       e);
-               } finally {
-                       JcrUtils.logoutQuietly(session);
-                       IOUtils.closeQuietly(reader);
-               }
-       }
-
-       protected static int compareVersions(String version1, String version2) {
-               // TODO do a proper version analysis and comparison
-               return version1.compareTo(version2);
-       }
-
-       /** To be called on a stopped repository. */
-       public static void clearRepositoryCaches(RepositoryConfig repositoryConfig) {
-               try {
-                       String customeNodeTypesPath = "/nodetypes/custom_nodetypes.xml";
-                       repositoryConfig.getFileSystem().deleteFile(customeNodeTypesPath);
-                       if (log.isDebugEnabled())
-                               log.debug("Cleared " + customeNodeTypesPath);
-               } catch (Exception e) {
-                       throw new ArgeoException("Cannot clear caches", e);
-               }
-
-               // File customNodeTypes = new File(home.getPath()
-               // + "/repository/nodetypes/custom_nodetypes.xml");
-               // if (customNodeTypes.exists()) {
-               // customNodeTypes.delete();
-               // if (log.isDebugEnabled())
-               // log.debug("Cleared " + customNodeTypes);
-               // } else {
-               // log.warn("File " + customNodeTypes + " not found.");
-               // }
-       }
-
-       /*
-        * FOR USE IN (SORTED) SETS
-        */
-
-       public int compareTo(JackrabbitDataModelMigration dataModelMigration) {
-               // TODO make ordering smarter
-               if (dataModelNodePath.equals(dataModelMigration.dataModelNodePath))
-                       return compareVersions(targetVersion,
-                                       dataModelMigration.targetVersion);
-               else
-                       return dataModelNodePath
-                                       .compareTo(dataModelMigration.dataModelNodePath);
-       }
-
-       @Override
-       public boolean equals(Object obj) {
-               if (!(obj instanceof JackrabbitDataModelMigration))
-                       return false;
-               JackrabbitDataModelMigration dataModelMigration = (JackrabbitDataModelMigration) obj;
-               return dataModelNodePath.equals(dataModelMigration.dataModelNodePath)
-                               && targetVersion.equals(dataModelMigration.targetVersion);
-       }
-
-       @Override
-       public int hashCode() {
-               return targetVersion.hashCode();
-       }
-
-       public void setDataModelNodePath(String dataModelNodePath) {
-               this.dataModelNodePath = dataModelNodePath;
-       }
-
-       public void setTargetVersion(String targetVersion) {
-               this.targetVersion = targetVersion;
-       }
-
-       public void setMigrationCnd(Resource migrationCnd) {
-               this.migrationCnd = migrationCnd;
-       }
-
-       public void setDataModification(JcrCallback dataModification) {
-               this.dataModification = dataModification;
-       }
-
-       public String getDataModelNodePath() {
-               return dataModelNodePath;
-       }
-
-       public String getTargetVersion() {
-               return targetVersion;
-       }
-
-}
diff --git a/org.argeo.server.jackrabbit/src/main/java/org/argeo/jackrabbit/JackrabbitRepositoryFactory.java b/org.argeo.server.jackrabbit/src/main/java/org/argeo/jackrabbit/JackrabbitRepositoryFactory.java
deleted file mode 100644 (file)
index d64bb5e..0000000
+++ /dev/null
@@ -1,169 +0,0 @@
-/*
- * Copyright (C) 2007-2012 Argeo GmbH
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *         http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.argeo.jackrabbit;
-
-import java.io.File;
-import java.io.InputStream;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.Properties;
-
-import javax.jcr.Repository;
-import javax.jcr.RepositoryException;
-import javax.jcr.RepositoryFactory;
-import javax.jcr.Session;
-
-import org.apache.commons.io.IOUtils;
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.apache.jackrabbit.commons.JcrUtils;
-import org.apache.jackrabbit.core.RepositoryImpl;
-import org.apache.jackrabbit.core.config.RepositoryConfig;
-import org.apache.jackrabbit.core.config.RepositoryConfigurationParser;
-import org.apache.jackrabbit.jcr2dav.Jcr2davRepositoryFactory;
-import org.argeo.ArgeoException;
-import org.argeo.jcr.ArgeoJcrConstants;
-import org.argeo.jcr.DefaultRepositoryFactory;
-import org.springframework.core.io.ClassPathResource;
-import org.springframework.core.io.Resource;
-import org.xml.sax.InputSource;
-
-/**
- * Repository factory which can create new repositories and access remote
- * Jackrabbit repositories
- */
-public class JackrabbitRepositoryFactory extends DefaultRepositoryFactory
-               implements RepositoryFactory, ArgeoJcrConstants {
-
-       private final static Log log = LogFactory
-                       .getLog(JackrabbitRepositoryFactory.class);
-
-       private Resource fileRepositoryConfiguration = new ClassPathResource(
-                       "/org/argeo/jackrabbit/repository-h2.xml");
-
-       @SuppressWarnings({ "rawtypes", "unchecked" })
-       public Repository getRepository(Map parameters) throws RepositoryException {
-               // check if can be found by alias
-               Repository repository = super.getRepository(parameters);
-               if (repository != null)
-                       return repository;
-
-               // check if remote
-               String uri = null;
-               if (parameters.containsKey(JCR_REPOSITORY_URI))
-                       uri = parameters.get(JCR_REPOSITORY_URI).toString();
-               else if (parameters.containsKey(JcrUtils.REPOSITORY_URI))
-                       uri = parameters.get(JcrUtils.REPOSITORY_URI).toString();
-
-               if (uri != null) {
-                       if (uri.startsWith("http"))// http, https
-                               repository = createRemoteRepository(uri);
-                       else if (uri.startsWith("file"))// http, https
-                               repository = createFileRepository(uri, parameters);
-                       else if (uri.startsWith("vm")) {
-                               log.warn("URI "
-                                               + uri
-                                               + " should have been managed by generic JCR repository factory");
-                               repository = getRepositoryByAlias(getAliasFromURI(uri));
-                       }
-               }
-
-               // publish under alias
-               if (parameters.containsKey(JCR_REPOSITORY_ALIAS)) {
-                       Properties properties = new Properties();
-                       properties.putAll(parameters);
-                       String alias = parameters.get(JCR_REPOSITORY_ALIAS).toString();
-                       publish(alias, repository, properties);
-                       log.info("Registered JCR repository under alias '" + alias
-                                       + "' with properties " + properties);
-               }
-
-               return repository;
-       }
-
-       protected Repository createRemoteRepository(String uri)
-                       throws RepositoryException {
-               Map<String, String> params = new HashMap<String, String>();
-               params.put(JcrUtils.REPOSITORY_URI, uri);
-               Repository repository = new Jcr2davRepositoryFactory()
-                               .getRepository(params);
-               if (repository == null)
-                       throw new ArgeoException("Remote Davex repository " + uri
-                                       + " not found");
-               log.info("Initialized remote Jackrabbit repository from uri " + uri);
-               return repository;
-       }
-
-       @SuppressWarnings({ "rawtypes", "unchecked" })
-       protected Repository createFileRepository(final String uri, Map parameters)
-                       throws RepositoryException {
-               InputStream configurationIn = null;
-               try {
-                       Properties vars = new Properties();
-                       vars.putAll(parameters);
-                       String dirPath = uri.substring("file:".length());
-                       File homeDir = new File(dirPath);
-                       if (homeDir.exists() && !homeDir.isDirectory())
-                               throw new ArgeoException("Repository home " + dirPath
-                                               + " is not a directory");
-                       if (!homeDir.exists())
-                               homeDir.mkdirs();
-                       configurationIn = fileRepositoryConfiguration.getInputStream();
-                       vars.put(RepositoryConfigurationParser.REPOSITORY_HOME_VARIABLE,
-                                       homeDir.getCanonicalPath());
-                       RepositoryConfig repositoryConfig = RepositoryConfig.create(
-                                       new InputSource(configurationIn), vars);
-
-                       // TransientRepository repository = new
-                       // TransientRepository(repositoryConfig);
-                       final RepositoryImpl repository = RepositoryImpl
-                                       .create(repositoryConfig);
-                       Session session = repository.login();
-                       // FIXME make it generic
-                       org.argeo.jcr.JcrUtils.addPrivilege(session, "/", "ROLE_ADMIN",
-                                       "jcr:all");
-                       org.argeo.jcr.JcrUtils.logoutQuietly(session);
-                       Runtime.getRuntime().addShutdownHook(
-                                       new Thread("Clean JCR repository " + uri) {
-                                               public void run() {
-                                                       repository.shutdown();
-                                                       log.info("Destroyed repository " + uri);
-                                               }
-                                       });
-                       log.info("Initialized file Jackrabbit repository from uri " + uri);
-                       return repository;
-               } catch (Exception e) {
-                       throw new ArgeoException("Cannot create repository " + uri, e);
-               } finally {
-                       IOUtils.closeQuietly(configurationIn);
-               }
-       }
-
-       /**
-        * Called after the repository has been initialised. Does nothing by
-        * default.
-        */
-       @SuppressWarnings("rawtypes")
-       protected void postInitialization(Repository repository, Map parameters) {
-
-       }
-
-       public void setFileRepositoryConfiguration(
-                       Resource fileRepositoryConfiguration) {
-               this.fileRepositoryConfiguration = fileRepositoryConfiguration;
-       }
-
-}
diff --git a/org.argeo.server.jackrabbit/src/main/java/org/argeo/jackrabbit/JackrabbitWrapper.java b/org.argeo.server.jackrabbit/src/main/java/org/argeo/jackrabbit/JackrabbitWrapper.java
deleted file mode 100644 (file)
index f9f04c4..0000000
+++ /dev/null
@@ -1,375 +0,0 @@
-/*
- * Copyright (C) 2007-2012 Argeo GmbH
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *         http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.argeo.jackrabbit;
-
-import java.io.ByteArrayInputStream;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.io.Reader;
-import java.net.URL;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-import javax.jcr.Credentials;
-import javax.jcr.Node;
-import javax.jcr.NodeIterator;
-import javax.jcr.Repository;
-import javax.jcr.Session;
-import javax.jcr.nodetype.NodeType;
-
-import org.apache.commons.io.FilenameUtils;
-import org.apache.commons.io.IOUtils;
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.apache.jackrabbit.commons.NamespaceHelper;
-import org.apache.jackrabbit.commons.cnd.CndImporter;
-import org.argeo.ArgeoException;
-import org.argeo.jcr.ArgeoJcrConstants;
-import org.argeo.jcr.ArgeoNames;
-import org.argeo.jcr.ArgeoTypes;
-import org.argeo.jcr.JcrRepositoryWrapper;
-import org.argeo.jcr.JcrUtils;
-import org.argeo.util.security.DigestUtils;
-import org.osgi.framework.Bundle;
-import org.osgi.framework.BundleContext;
-import org.osgi.framework.ServiceReference;
-import org.osgi.service.packageadmin.ExportedPackage;
-import org.osgi.service.packageadmin.PackageAdmin;
-import org.springframework.context.ResourceLoaderAware;
-import org.springframework.core.io.Resource;
-import org.springframework.core.io.ResourceLoader;
-
-/**
- * Wrapper around a Jackrabbit repository which allows to simplify configuration
- * and intercept some actions. It exposes itself as a {@link Repository}.
- */
-public class JackrabbitWrapper extends JcrRepositoryWrapper implements
-               ResourceLoaderAware {
-       private final static Log log = LogFactory.getLog(JackrabbitWrapper.class);
-       private final static String DIGEST_ALGORITHM = "MD5";
-
-       // local
-       private ResourceLoader resourceLoader;
-
-       // data model
-       /** Node type definitions in CND format */
-       private List<String> cndFiles = new ArrayList<String>();
-       /**
-        * Always import CNDs. Useful during development of new data models. In
-        * production, explicit migration processes should be used.
-        */
-       private Boolean forceCndImport = true;
-
-       /** Namespaces to register: key is prefix, value namespace */
-       private Map<String, String> namespaces = new HashMap<String, String>();
-
-       private BundleContext bundleContext;
-
-       /**
-        * Explicitly set admin credentials used in initialization. Useful for
-        * testing, in real applications authentication is rather dealt with
-        * externally
-        */
-       private Credentials adminCredentials = null;
-
-       /**
-        * Empty constructor, {@link #init()} should be called after properties have
-        * been set
-        */
-       public JackrabbitWrapper() {
-       }
-
-       @Override
-       public void init() {
-               prepareDataModel();
-       }
-
-       /*
-        * DATA MODEL
-        */
-
-       /**
-        * Import declared node type definitions and register namespaces. Tries to
-        * update the node definitions if they have changed. In case of failures an
-        * error will be logged but no exception will be thrown.
-        */
-       protected void prepareDataModel() {
-               if ((cndFiles == null || cndFiles.size() == 0)
-                               && (namespaces == null || namespaces.size() == 0))
-                       return;
-
-               Session session = null;
-               try {
-                       session = login(adminCredentials);
-                       // register namespaces
-                       if (namespaces.size() > 0) {
-                               NamespaceHelper namespaceHelper = new NamespaceHelper(session);
-                               namespaceHelper.registerNamespaces(namespaces);
-                       }
-
-                       // load CND files from classpath or as URL
-                       for (String resUrl : cndFiles) {
-                               processCndFile(session, resUrl);
-                       }
-               } catch (Exception e) {
-                       JcrUtils.discardQuietly(session);
-                       throw new ArgeoException("Cannot import node type definitions "
-                                       + cndFiles, e);
-               } finally {
-                       JcrUtils.logoutQuietly(session);
-               }
-
-       }
-
-       protected void processCndFile(Session session, String resUrl) {
-               Reader reader = null;
-               try {
-                       // check existing data model nodes
-                       new NamespaceHelper(session).registerNamespace(ArgeoNames.ARGEO,
-                                       ArgeoNames.ARGEO_NAMESPACE);
-                       if (!session.itemExists(ArgeoJcrConstants.DATA_MODELS_BASE_PATH))
-                               JcrUtils.mkdirs(session,
-                                               ArgeoJcrConstants.DATA_MODELS_BASE_PATH);
-                       Node dataModels = session
-                                       .getNode(ArgeoJcrConstants.DATA_MODELS_BASE_PATH);
-                       NodeIterator it = dataModels.getNodes();
-                       Node dataModel = null;
-                       while (it.hasNext()) {
-                               Node node = it.nextNode();
-                               if (node.getProperty(ArgeoNames.ARGEO_URI).getString()
-                                               .equals(resUrl)) {
-                                       dataModel = node;
-                                       break;
-                               }
-                       }
-
-                       byte[] cndContent = readCndContent(resUrl);
-                       String newDigest = DigestUtils.digest(DIGEST_ALGORITHM, cndContent);
-                       Bundle bundle = findDataModelBundle(resUrl);
-
-                       String currentVersion = null;
-                       if (dataModel != null) {
-                               currentVersion = dataModel.getProperty(
-                                               ArgeoNames.ARGEO_DATA_MODEL_VERSION).getString();
-                               if (dataModel.hasNode(Node.JCR_CONTENT)) {
-                                       String oldDigest = JcrUtils.checksumFile(dataModel,
-                                                       DIGEST_ALGORITHM);
-                                       if (oldDigest.equals(newDigest)) {
-                                               if (log.isDebugEnabled())
-                                                       log.debug("Data model " + resUrl
-                                                                       + " hasn't changed, keeping version "
-                                                                       + currentVersion);
-                                               return;
-                                       }
-                               }
-                       }
-
-                       if (dataModel != null && !forceCndImport) {
-                               log.info("Data model "
-                                               + resUrl
-                                               + " has changed since version "
-                                               + currentVersion
-                                               + (bundle != null ? ": version " + bundle.getVersion()
-                                                               + ", bundle " + bundle.getSymbolicName() : ""));
-                               return;
-                       }
-
-                       reader = new InputStreamReader(new ByteArrayInputStream(cndContent));
-                       // actually imports the CND
-                       try {
-                               CndImporter.registerNodeTypes(reader, session, true);
-                       } catch (Exception e) {
-                               log.error("Cannot import data model " + resUrl, e);
-                               return;
-                       }
-
-                       if (dataModel != null && !dataModel.isNodeType(NodeType.NT_FILE)) {
-                               dataModel.remove();
-                               dataModel = null;
-                       }
-
-                       // FIXME: what if argeo.cnd would not be the first called on
-                       // a new repo? argeo:dataModel would not be found
-                       String fileName = FilenameUtils.getName(resUrl);
-                       if (dataModel == null) {
-                               dataModel = dataModels.addNode(fileName, NodeType.NT_FILE);
-                               dataModel.addNode(Node.JCR_CONTENT, NodeType.NT_RESOURCE);
-                               dataModel.addMixin(ArgeoTypes.ARGEO_DATA_MODEL);
-                               dataModel.setProperty(ArgeoNames.ARGEO_URI, resUrl);
-                       } else {
-                               session.getWorkspace().getVersionManager()
-                                               .checkout(dataModel.getPath());
-                       }
-                       if (bundle != null)
-                               dataModel.setProperty(ArgeoNames.ARGEO_DATA_MODEL_VERSION,
-                                               bundle.getVersion().toString());
-                       else
-                               dataModel.setProperty(ArgeoNames.ARGEO_DATA_MODEL_VERSION,
-                                               "0.0.0");
-                       JcrUtils.copyBytesAsFile(dataModel.getParent(), fileName,
-                                       cndContent);
-                       JcrUtils.updateLastModified(dataModel);
-                       session.save();
-                       session.getWorkspace().getVersionManager()
-                                       .checkin(dataModel.getPath());
-
-                       if (currentVersion == null)
-                               log.info("Data model "
-                                               + resUrl
-                                               + (bundle != null ? ", version " + bundle.getVersion()
-                                                               + ", bundle " + bundle.getSymbolicName() : ""));
-                       else
-                               log.info("Data model "
-                                               + resUrl
-                                               + " updated from version "
-                                               + currentVersion
-                                               + (bundle != null ? ", version " + bundle.getVersion()
-                                                               + ", bundle " + bundle.getSymbolicName() : ""));
-               } catch (Exception e) {
-                       throw new ArgeoException("Cannot process data model " + resUrl, e);
-               } finally {
-                       IOUtils.closeQuietly(reader);
-               }
-       }
-
-       protected byte[] readCndContent(String resUrl) {
-               InputStream in = null;
-               try {
-                       boolean classpath;
-                       // normalize URL
-                       if (bundleContext != null && resUrl.startsWith("classpath:")) {
-                               resUrl = resUrl.substring("classpath:".length());
-                               classpath = true;
-                       } else if (resUrl.indexOf(':') < 0) {
-                               if (!resUrl.startsWith("/")) {
-                                       resUrl = "/" + resUrl;
-                                       log.warn("Classpath should start with '/'");
-                               }
-                               classpath = true;
-                       } else {
-                               classpath = false;
-                       }
-
-                       URL url = null;
-                       if (classpath) {
-                               if (bundleContext != null) {
-                                       Bundle currentBundle = bundleContext.getBundle();
-                                       url = currentBundle.getResource(resUrl);
-                               } else {
-                                       resUrl = "classpath:" + resUrl;
-                                       url = null;
-                               }
-                       } else if (!resUrl.startsWith("classpath:")) {
-                               url = new URL(resUrl);
-                       }
-
-                       if (url != null) {
-                               in = url.openStream();
-                       } else if (resourceLoader != null) {
-                               Resource res = resourceLoader.getResource(resUrl);
-                               in = res.getInputStream();
-                               url = res.getURL();
-                       } else {
-                               throw new ArgeoException("No " + resUrl + " in the classpath,"
-                                               + " make sure the containing" + " package is visible.");
-                       }
-
-                       return IOUtils.toByteArray(in);
-               } catch (Exception e) {
-                       throw new ArgeoException("Cannot read CND from " + resUrl, e);
-               } finally {
-                       IOUtils.closeQuietly(in);
-               }
-       }
-
-       /*
-        * REPOSITORY INTERCEPTOR
-        */
-
-       /*
-        * UTILITIES
-        */
-       /** Find which OSGi bundle provided the data model resource */
-       protected Bundle findDataModelBundle(String resUrl) {
-               if (bundleContext == null)
-                       return null;
-
-               if (resUrl.startsWith("/"))
-                       resUrl = resUrl.substring(1);
-               String pkg = resUrl.substring(0, resUrl.lastIndexOf('/')).replace('/',
-                               '.');
-               ServiceReference paSr = bundleContext
-                               .getServiceReference(PackageAdmin.class.getName());
-               PackageAdmin packageAdmin = (PackageAdmin) bundleContext
-                               .getService(paSr);
-
-               // find exported package
-               ExportedPackage exportedPackage = null;
-               ExportedPackage[] exportedPackages = packageAdmin
-                               .getExportedPackages(pkg);
-               if (exportedPackages == null)
-                       throw new ArgeoException("No exported package found for " + pkg);
-               for (ExportedPackage ep : exportedPackages) {
-                       for (Bundle b : ep.getImportingBundles()) {
-                               if (b.getBundleId() == bundleContext.getBundle().getBundleId()) {
-                                       exportedPackage = ep;
-                                       break;
-                               }
-                       }
-               }
-
-               Bundle exportingBundle = null;
-               if (exportedPackage != null) {
-                       exportingBundle = exportedPackage.getExportingBundle();
-               } else {
-                       // assume this is in the same bundle
-                       exportingBundle = bundleContext.getBundle();
-//                     throw new ArgeoException("No OSGi exporting package found for "
-//                                     + resUrl);
-               }
-               return exportingBundle;
-       }
-
-       /*
-        * FIELDS ACCESS
-        */
-       public void setNamespaces(Map<String, String> namespaces) {
-               this.namespaces = namespaces;
-       }
-
-       public void setCndFiles(List<String> cndFiles) {
-               this.cndFiles = cndFiles;
-       }
-
-       public void setBundleContext(BundleContext bundleContext) {
-               this.bundleContext = bundleContext;
-       }
-
-       public void setForceCndImport(Boolean forceCndUpdate) {
-               this.forceCndImport = forceCndUpdate;
-       }
-
-       public void setResourceLoader(ResourceLoader resourceLoader) {
-               this.resourceLoader = resourceLoader;
-       }
-
-       public void setAdminCredentials(Credentials adminCredentials) {
-               this.adminCredentials = adminCredentials;
-       }
-
-}
diff --git a/org.argeo.server.jackrabbit/src/main/java/org/argeo/jackrabbit/OsgiJackrabbitRepositoryFactory.java b/org.argeo.server.jackrabbit/src/main/java/org/argeo/jackrabbit/OsgiJackrabbitRepositoryFactory.java
deleted file mode 100644 (file)
index b28699e..0000000
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * Copyright (C) 2007-2012 Argeo GmbH
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *         http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.argeo.jackrabbit;
-
-import java.util.Hashtable;
-import java.util.Properties;
-
-import javax.jcr.Repository;
-
-import org.osgi.framework.BundleContext;
-
-/**
- * OSGi-aware Jackrabbit repository factory which can retrieve/publish
- * {@link Repository} as OSGi services.
- */
-public class OsgiJackrabbitRepositoryFactory extends
-               JackrabbitRepositoryFactory {
-       private BundleContext bundleContext;
-
-       protected void publish(String alias, Repository repository,
-                       Properties properties) {
-               if (bundleContext != null) {
-                       // do not modify reference
-                       Hashtable<String, String> props = new Hashtable<String, String>();
-                       props.putAll(props);
-                       props.put(JCR_REPOSITORY_ALIAS, alias);
-                       bundleContext.registerService(Repository.class.getName(),
-                                       repository, props);
-               }
-       }
-
-       public void setBundleContext(BundleContext bundleContext) {
-               this.bundleContext = bundleContext;
-       }
-
-}
diff --git a/org.argeo.server.jackrabbit/src/main/java/org/argeo/jackrabbit/remote/AbstractJackrabbitHandlerMapping.java b/org.argeo.server.jackrabbit/src/main/java/org/argeo/jackrabbit/remote/AbstractJackrabbitHandlerMapping.java
deleted file mode 100644 (file)
index 99bfab4..0000000
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * Copyright (C) 2007-2012 Argeo GmbH
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *         http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.argeo.jackrabbit.remote;
-
-import org.apache.jackrabbit.server.SessionProvider;
-import org.argeo.jcr.mvc.MultipleRepositoryHandlerMapping;
-
-/** Base class for Jackrabbit handler mappings. */
-public abstract class AbstractJackrabbitHandlerMapping extends
-               MultipleRepositoryHandlerMapping {
-       private SessionProvider sessionProvider;
-
-       protected SessionProvider getSessionProvider() {
-               return sessionProvider;
-       }
-
-       public void setSessionProvider(SessionProvider sessionProvider) {
-               this.sessionProvider = sessionProvider;
-       }
-
-}
diff --git a/org.argeo.server.jackrabbit/src/main/java/org/argeo/jackrabbit/remote/ExtendedDispatcherServlet.java b/org.argeo.server.jackrabbit/src/main/java/org/argeo/jackrabbit/remote/ExtendedDispatcherServlet.java
deleted file mode 100644 (file)
index 14b6e99..0000000
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * Copyright (C) 2007-2012 Argeo GmbH
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *         http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.argeo.jackrabbit.remote;
-
-import javax.servlet.ServletException;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.argeo.ArgeoException;
-import org.springframework.web.servlet.DispatcherServlet;
-
-/**
- * Overrides Spring {@link DispatcherServlet}, see
- * http://forum.springsource.org/showthread.php?t=53472.
- */
-public class ExtendedDispatcherServlet extends DispatcherServlet {
-       private static final long serialVersionUID = -5584673209855752009L;
-
-       private final static Log log = LogFactory
-                       .getLog(ExtendedDispatcherServlet.class);
-
-       protected void service(HttpServletRequest request,
-                       HttpServletResponse response) throws ServletException,
-                       java.io.IOException {
-               try {
-                       if (log.isTraceEnabled()) {
-                               log.trace("SessionID    = " + request.getSession().getId());
-                               log.trace(" ContextPath = " + request.getContextPath());
-                               log.trace(" ServletPath = " + request.getServletPath());
-                               log.trace(" PathInfo    = " + request.getPathInfo());
-                               log.trace(" Method      = " + request.getMethod());
-                               log.trace(" User-Agent  = " + request.getHeader("User-Agent"));
-                       }
-                       doService(request, response);
-               } catch (Exception e) {
-                       throw new ArgeoException("Cannot process request", e);
-               }
-       }
-
-}
diff --git a/org.argeo.server.jackrabbit/src/main/java/org/argeo/jackrabbit/remote/IOHandlerWrapper.java b/org.argeo.server.jackrabbit/src/main/java/org/argeo/jackrabbit/remote/IOHandlerWrapper.java
deleted file mode 100644 (file)
index daf2ecb..0000000
+++ /dev/null
@@ -1,114 +0,0 @@
-/*
- * Copyright (C) 2007-2012 Argeo GmbH
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *         http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.argeo.jackrabbit.remote;
-
-import java.io.IOException;
-
-import org.apache.jackrabbit.server.io.ExportContext;
-import org.apache.jackrabbit.server.io.IOHandler;
-import org.apache.jackrabbit.server.io.IOManager;
-import org.apache.jackrabbit.server.io.ImportContext;
-import org.apache.jackrabbit.webdav.DavResource;
-import org.argeo.ArgeoException;
-
-/** Wraps an IOHandler so that it can be injected a posteriori */
-public class IOHandlerWrapper implements IOHandler {
-       private IOManager ioManager = null;
-       private IOHandler ioHandler = null;
-
-       public void setIOHandler(IOHandler ioHandler) {
-               if ((this.ioHandler != null) && (ioHandler != null))
-                       throw new ArgeoException(
-                                       "There is already an IO Handler registered");
-               this.ioHandler = ioHandler;
-               if (ioManager != null && this.ioHandler != null)
-                       ioHandler.setIOManager(ioManager);
-       }
-
-       public IOHandler getIOHandler() {
-               return ioHandler;
-       }
-
-       public IOManager getIOManager() {
-               return ioManager;
-       }
-
-       public void setIOManager(IOManager ioManager) {
-               this.ioManager = ioManager;
-               if (ioHandler != null)
-                       ioHandler.setIOManager(ioManager);
-       }
-
-       public String getName() {
-               if (ioHandler != null)
-                       return ioHandler.getName();
-               else
-                       return "Empty IOHandler Wrapper";
-       }
-
-       public boolean canImport(ImportContext context, boolean isCollection) {
-               if (ioHandler != null)
-                       return ioHandler.canImport(context, isCollection);
-               return false;
-       }
-
-       public boolean canImport(ImportContext context, DavResource resource) {
-               if (ioHandler != null)
-                       return ioHandler.canImport(context, resource);
-               return false;
-       }
-
-       public boolean importContent(ImportContext context, boolean isCollection)
-                       throws IOException {
-               if (ioHandler != null)
-                       ioHandler.importContent(context, isCollection);
-               return false;
-       }
-
-       public boolean importContent(ImportContext context, DavResource resource)
-                       throws IOException {
-               if (ioHandler != null)
-                       ioHandler.importContent(context, resource);
-               return false;
-       }
-
-       public boolean canExport(ExportContext context, boolean isCollection) {
-               if (ioHandler != null)
-                       ioHandler.canExport(context, isCollection);
-               return false;
-       }
-
-       public boolean canExport(ExportContext context, DavResource resource) {
-               if (ioHandler != null)
-                       ioHandler.canExport(context, resource);
-               return false;
-       }
-
-       public boolean exportContent(ExportContext context, boolean isCollection)
-                       throws IOException {
-               if (ioHandler != null)
-                       ioHandler.exportContent(context, isCollection);
-               return false;
-       }
-
-       public boolean exportContent(ExportContext context, DavResource resource)
-                       throws IOException {
-               if (ioHandler != null)
-                       ioHandler.exportContent(context, resource);
-               return false;
-       }
-
-}
diff --git a/org.argeo.server.jackrabbit/src/main/java/org/argeo/jackrabbit/remote/IOManagerBean.java b/org.argeo.server.jackrabbit/src/main/java/org/argeo/jackrabbit/remote/IOManagerBean.java
deleted file mode 100644 (file)
index 82a7673..0000000
+++ /dev/null
@@ -1,82 +0,0 @@
-/*
- * Copyright (C) 2007-2012 Argeo GmbH
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *         http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.argeo.jackrabbit.remote;
-
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.List;
-
-import org.apache.jackrabbit.server.io.ExportContext;
-import org.apache.jackrabbit.server.io.IOHandler;
-import org.apache.jackrabbit.server.io.IOManager;
-import org.apache.jackrabbit.server.io.ImportContext;
-import org.apache.jackrabbit.webdav.DavResource;
-import org.apache.tika.detect.Detector;
-
-/** {@link IOManager} that can easily be configured as a bean. */
-public class IOManagerBean implements IOManager {
-       private Detector detector = null;
-       private List<IOHandler> ioHandlers = new ArrayList<IOHandler>();
-
-       public boolean importContent(ImportContext context, boolean isCollection)
-                       throws IOException {
-               // TODO Auto-generated method stub
-               return false;
-       }
-
-       public boolean importContent(ImportContext context, DavResource resource)
-                       throws IOException {
-               // TODO Auto-generated method stub
-               return false;
-       }
-
-       public boolean exportContent(ExportContext context, boolean isCollection)
-                       throws IOException {
-               // TODO Auto-generated method stub
-               return false;
-       }
-
-       public boolean exportContent(ExportContext context, DavResource resource)
-                       throws IOException {
-               // TODO Auto-generated method stub
-               return false;
-       }
-
-       public synchronized void addIOHandler(IOHandler ioHandler) {
-               ioHandlers.add(ioHandler);
-       }
-
-       public synchronized IOHandler[] getIOHandlers() {
-               return ioHandlers.toArray(new IOHandler[ioHandlers.size()]);
-       }
-
-       public Detector getDetector() {
-               return detector;
-       }
-
-       public void setDetector(Detector detector) {
-               this.detector = detector;
-       }
-
-       public synchronized List<IOHandler> getIoHandlers() {
-               return ioHandlers;
-       }
-
-       public synchronized void setIoHandlers(List<IOHandler> ioHandlers) {
-               this.ioHandlers = ioHandlers;
-       }
-
-}
diff --git a/org.argeo.server.jackrabbit/src/main/java/org/argeo/jackrabbit/remote/JcrRemotingHandlerMapping.java b/org.argeo.server.jackrabbit/src/main/java/org/argeo/jackrabbit/remote/JcrRemotingHandlerMapping.java
deleted file mode 100644 (file)
index caea5fc..0000000
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Copyright (C) 2007-2012 Argeo GmbH
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *         http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.argeo.jackrabbit.remote;
-
-import java.util.Properties;
-
-import javax.jcr.Repository;
-import javax.servlet.ServletException;
-import javax.servlet.http.HttpServlet;
-
-public class JcrRemotingHandlerMapping extends AbstractJackrabbitHandlerMapping {
-
-       protected HttpServlet createServlet(Repository repository, String pathPrefix)
-                       throws ServletException {
-               JcrRemotingServlet servlet = new JcrRemotingServlet(repository,
-                               getSessionProvider());
-               Properties initParameters = new Properties();
-               initParameters.setProperty(
-                               JcrRemotingServlet.INIT_PARAM_RESOURCE_PATH_PREFIX, pathPrefix);
-               servlet.init(new DelegatingServletConfig(pathPrefix.replace('/', '_'),
-                               initParameters));
-               return servlet;
-       }
-}
diff --git a/org.argeo.server.jackrabbit/src/main/java/org/argeo/jackrabbit/remote/JcrRemotingServlet.java b/org.argeo.server.jackrabbit/src/main/java/org/argeo/jackrabbit/remote/JcrRemotingServlet.java
deleted file mode 100644 (file)
index b3f0797..0000000
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * Copyright (C) 2007-2012 Argeo GmbH
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *         http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.argeo.jackrabbit.remote;
-
-import javax.jcr.Repository;
-
-import org.apache.jackrabbit.server.SessionProvider;
-
-public class JcrRemotingServlet extends
-               org.apache.jackrabbit.server.remoting.davex.JcrRemotingServlet {
-
-       private static final long serialVersionUID = 3131835511468341309L;
-
-       private final Repository repository;
-       private final SessionProvider sessionProvider;
-
-       public JcrRemotingServlet(Repository repository,
-                       SessionProvider sessionProvider) {
-               this.repository = repository;
-               this.sessionProvider = sessionProvider;
-       }
-
-       @Override
-       protected Repository getRepository() {
-               return repository;
-       }
-
-       @Override
-       protected SessionProvider getSessionProvider() {
-               return sessionProvider;
-       }
-
-}
diff --git a/org.argeo.server.jackrabbit/src/main/java/org/argeo/jackrabbit/remote/OpenInViewSessionProvider.java b/org.argeo.server.jackrabbit/src/main/java/org/argeo/jackrabbit/remote/OpenInViewSessionProvider.java
deleted file mode 100644 (file)
index b4d1d60..0000000
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * Copyright (C) 2007-2012 Argeo GmbH
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *         http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.argeo.jackrabbit.remote;
-
-import java.io.Serializable;
-
-import javax.jcr.LoginException;
-import javax.jcr.Repository;
-import javax.jcr.RepositoryException;
-import javax.jcr.Session;
-import javax.servlet.ServletException;
-import javax.servlet.http.HttpServletRequest;
-
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.apache.jackrabbit.server.SessionProvider;
-import org.argeo.jcr.JcrUtils;
-
-/**
- * Implements an open session in view patter: a new JCR session is created for
- * each request
- */
-public class OpenInViewSessionProvider implements SessionProvider, Serializable {
-       private static final long serialVersionUID = 2270957712453841368L;
-
-       private final static Log log = LogFactory
-                       .getLog(OpenInViewSessionProvider.class);
-
-       public Session getSession(HttpServletRequest request, Repository rep,
-                       String workspace) throws LoginException, ServletException,
-                       RepositoryException {
-               return login(request, rep, workspace);
-       }
-
-       protected Session login(HttpServletRequest request, Repository repository,
-                       String workspace) throws RepositoryException {
-               if (log.isTraceEnabled())
-                       log.trace("Login to workspace "
-                                       + (workspace == null ? "<default>" : workspace)
-                                       + " in web session " + request.getSession().getId());
-               return repository.login(workspace);
-       }
-
-       public void releaseSession(Session session) {
-               JcrUtils.logoutQuietly(session);
-               if (log.isTraceEnabled())
-                       log.trace("Logged out remote JCR session " + session);
-       }
-
-       public void init() {
-       }
-
-       public void destroy() {
-       }
-
-}
diff --git a/org.argeo.server.jackrabbit/src/main/java/org/argeo/jackrabbit/remote/ScopedSessionProvider.java b/org.argeo.server.jackrabbit/src/main/java/org/argeo/jackrabbit/remote/ScopedSessionProvider.java
deleted file mode 100644 (file)
index ffe6df9..0000000
+++ /dev/null
@@ -1,171 +0,0 @@
-/*
- * Copyright (C) 2007-2012 Argeo GmbH
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *         http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.argeo.jackrabbit.remote;
-
-import java.io.Serializable;
-
-import javax.jcr.LoginException;
-import javax.jcr.Repository;
-import javax.jcr.RepositoryException;
-import javax.jcr.Session;
-import javax.servlet.ServletException;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpSession;
-
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.apache.jackrabbit.server.SessionProvider;
-import org.argeo.ArgeoException;
-import org.argeo.jcr.ArgeoJcrConstants;
-import org.argeo.jcr.JcrUtils;
-import org.springframework.security.Authentication;
-import org.springframework.security.context.SecurityContextHolder;
-
-/**
- * Session provider assuming a single workspace and a short life cycle,
- * typically a Spring bean of scope (web) 'session'.
- */
-public class ScopedSessionProvider implements SessionProvider, Serializable {
-       private static final long serialVersionUID = 6589775984177317058L;
-       private static final Log log = LogFactory
-                       .getLog(ScopedSessionProvider.class);
-       private transient HttpSession httpSession = null;
-       private transient Session jcrSession = null;
-
-       private transient String currentRepositoryName = null;
-       private transient String currentWorkspaceName = null;
-       private transient String currentJcrUser = null;
-
-       // private transient String anonymousUserId = "anonymous";
-
-       public Session getSession(HttpServletRequest request, Repository rep,
-                       String workspace) throws LoginException, ServletException,
-                       RepositoryException {
-
-               Authentication authentication = SecurityContextHolder.getContext()
-                               .getAuthentication();
-               if (authentication == null)
-                       throw new ArgeoException(
-                                       "Request not authenticated by Spring Security");
-               String springUser = authentication.getName();
-
-               // HTTP
-               String requestJcrRepository = (String) request
-                               .getAttribute(ArgeoJcrConstants.JCR_REPOSITORY_ALIAS);
-
-               // HTTP session
-               if (httpSession != null
-                               && !httpSession.getId().equals(request.getSession().getId()))
-                       throw new ArgeoException(
-                                       "Only session scope is supported in this mode");
-               if (httpSession == null)
-                       httpSession = request.getSession();
-
-               // Initializes current values
-               if (currentRepositoryName == null)
-                       currentRepositoryName = requestJcrRepository;
-               if (currentWorkspaceName == null)
-                       currentWorkspaceName = workspace;
-               if (currentJcrUser == null)
-                       currentJcrUser = springUser;
-
-               // logout if there was a change in session coordinates
-               if (jcrSession != null)
-                       if (!currentRepositoryName.equals(requestJcrRepository)) {
-                               if (log.isDebugEnabled())
-                                       log.debug(getHttpSessionId() + " Changed from repository '"
-                                                       + currentRepositoryName + "' to '"
-                                                       + requestJcrRepository
-                                                       + "', logging out cached JCR session.");
-                               logout();
-                       } else if (!currentWorkspaceName.equals(workspace)) {
-                               if (log.isDebugEnabled())
-                                       log.debug(getHttpSessionId() + " Changed from workspace '"
-                                                       + currentWorkspaceName + "' to '" + workspace
-                                                       + "', logging out cached JCR session.");
-                               logout();
-                       } else if (!currentJcrUser.equals(springUser)) {
-                               if (log.isDebugEnabled())
-                                       log.debug(getHttpSessionId() + " Changed from user '"
-                                                       + currentJcrUser + "' to '" + springUser
-                                                       + "', logging out cached JCR session.");
-                               logout();
-                       }
-
-               // login if needed
-               if (jcrSession == null)
-                       try {
-                               Session session = login(rep, workspace);
-                               if (!session.getUserID().equals(springUser)) {
-                                       JcrUtils.logoutQuietly(session);
-                                       throw new ArgeoException("Spring Security user '"
-                                                       + springUser + "' not in line with JCR user '"
-                                                       + session.getUserID() + "'");
-                               }
-                               currentRepositoryName = requestJcrRepository;
-                               // do not use workspace variable which may be null
-                               currentWorkspaceName = session.getWorkspace().getName();
-                               currentJcrUser = session.getUserID();
-
-                               jcrSession = session;
-                               return jcrSession;
-                       } catch (RepositoryException e) {
-                               throw new ArgeoException("Cannot open session to workspace "
-                                               + workspace, e);
-                       }
-
-               // returns cached session
-               return jcrSession;
-       }
-
-       protected Session login(Repository repository, String workspace)
-                       throws RepositoryException {
-               Session session = repository.login(workspace);
-               if (log.isDebugEnabled())
-                       log.debug(getHttpSessionId() + " User '" + session.getUserID()
-                                       + "' logged in workspace '"
-                                       + session.getWorkspace().getName() + "' of repository '"
-                                       + currentRepositoryName + "'");
-               return session;
-       }
-
-       public void releaseSession(Session session) {
-               if (log.isTraceEnabled())
-                       log.trace(getHttpSessionId() + " Releasing JCR session " + session);
-       }
-
-       protected void logout() {
-               JcrUtils.logoutQuietly(jcrSession);
-               jcrSession = null;
-       }
-
-       protected final String getHttpSessionId() {
-               return httpSession != null ? httpSession.getId() : "<null>";
-       }
-
-       public void init() {
-       }
-
-       public void destroy() {
-               logout();
-               if (getHttpSessionId() != null)
-                       if (log.isDebugEnabled())
-                               log.debug(getHttpSessionId()
-                                               + " Cleaned up provider for web session ");
-               httpSession = null;
-       }
-
-}
diff --git a/org.argeo.server.jackrabbit/src/main/java/org/argeo/jackrabbit/remote/SimpleSessionProvider.java b/org.argeo.server.jackrabbit/src/main/java/org/argeo/jackrabbit/remote/SimpleSessionProvider.java
deleted file mode 100644 (file)
index 1d438d5..0000000
+++ /dev/null
@@ -1,216 +0,0 @@
-/*
- * Copyright (C) 2007-2012 Argeo GmbH
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *         http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.argeo.jackrabbit.remote;
-
-import java.io.Serializable;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-
-import javax.jcr.LoginException;
-import javax.jcr.Node;
-import javax.jcr.Repository;
-import javax.jcr.RepositoryException;
-import javax.jcr.Session;
-import javax.jcr.Value;
-import javax.servlet.ServletException;
-import javax.servlet.http.HttpServletRequest;
-
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.apache.jackrabbit.api.JackrabbitSession;
-import org.apache.jackrabbit.api.security.user.Group;
-import org.apache.jackrabbit.api.security.user.User;
-import org.apache.jackrabbit.api.security.user.UserManager;
-import org.apache.jackrabbit.server.SessionProvider;
-import org.argeo.ArgeoException;
-import org.argeo.jcr.ArgeoNames;
-import org.argeo.jcr.JcrUtils;
-import org.argeo.jcr.UserJcrUtils;
-
-/**
- * Implements an open session in view patter: a new JCR session is created for
- * each request
- * 
- * @deprecated use {@link ScopedSessionProvider} or
- *             {@link OpenInViewSessionProvider}
- */
-@Deprecated
-public class SimpleSessionProvider implements SessionProvider, Serializable {
-       private static final long serialVersionUID = 2270957712453841368L;
-
-       private final static Log log = LogFactory
-                       .getLog(SimpleSessionProvider.class);
-
-       private transient Map<String, Session> sessions;
-
-       private Boolean openSessionInView = true;
-
-       private String defaultWorkspace = "default";
-
-       private String webSessionId = null;
-
-       public Session getSession(HttpServletRequest request, Repository rep,
-                       String workspace) throws LoginException, ServletException,
-                       RepositoryException {
-
-               if (openSessionInView) {
-                       JackrabbitSession session = (JackrabbitSession) login(request, rep,
-                                       workspace);
-                       if (session.getWorkspace().getName().equals(defaultWorkspace))
-                               writeRemoteRoles(session);
-                       return session;
-               } else {
-                       if (webSessionId != null
-                                       && !webSessionId.equals(request.getSession().getId()))
-                               throw new ArgeoException(
-                                               "Only session scope is supported in this mode");
-                       webSessionId = request.getSession().getId();
-
-                       // since sessions is transient it can't be restored from the session
-                       if (sessions == null)
-                               sessions = Collections
-                                               .synchronizedMap(new HashMap<String, Session>());
-
-                       if (!sessions.containsKey(workspace)) {
-                               try {
-                                       // JackrabbitSession session = (JackrabbitSession)
-                                       // rep.login(
-                                       // null, workspace);
-                                       JackrabbitSession session = (JackrabbitSession) login(
-                                                       request, rep, workspace);
-                                       if (session.getWorkspace().getName()
-                                                       .equals(defaultWorkspace))
-                                               writeRemoteRoles(session);
-                                       if (log.isTraceEnabled())
-                                               log.trace("User " + session.getUserID()
-                                                               + " logged into " + request.getServletPath());
-                                       sessions.put(workspace, session);
-                                       return session;
-                               } catch (Exception e) {
-                                       throw new ArgeoException("Cannot open session", e);
-                               }
-                       } else {
-                               Session session = sessions.get(workspace);
-                               if (!session.isLive()) {
-                                       sessions.remove(workspace);
-                                       session = login(request, rep, workspace);
-                                       sessions.put(workspace, session);
-                               }
-                               return session;
-                       }
-               }
-       }
-
-       protected Session login(HttpServletRequest request, Repository repository,
-                       String workspace) throws RepositoryException {
-               if (log.isDebugEnabled())
-                       log.debug("Login to workspace "
-                                       + (workspace == null ? "<default>" : workspace)
-                                       + " in web session " + request.getSession().getId());
-               return repository.login(workspace);
-       }
-
-       protected void writeRemoteRoles(JackrabbitSession session)
-                       throws RepositoryException {
-               // FIXME better deal w/ non node repo
-
-               // retrieve roles
-               String userId = session.getUserID();
-               UserManager userManager = session.getUserManager();
-               User user = (User) userManager.getAuthorizable(userId);
-               if (user == null) {
-                       // anonymous
-                       return;
-               }
-               List<String> userGroupIds = new ArrayList<String>();
-               if (user != null)
-                       for (Iterator<Group> it = user.memberOf(); it.hasNext();)
-                               userGroupIds.add(it.next().getID());
-
-               // write roles if needed
-               Node userHome = UserJcrUtils.getUserHome(session);
-               boolean writeRoles = false;
-               if (userHome.hasProperty(ArgeoNames.ARGEO_REMOTE_ROLES)) {
-                       Value[] roles = userHome.getProperty(ArgeoNames.ARGEO_REMOTE_ROLES)
-                                       .getValues();
-                       if (roles.length != userGroupIds.size())
-                               writeRoles = true;
-                       else
-                               for (int i = 0; i < roles.length; i++)
-                                       if (!roles[i].getString().equals(userGroupIds.get(i)))
-                                               writeRoles = true;
-               } else
-                       writeRoles = true;
-
-               if (writeRoles) {
-                       session.getWorkspace().getVersionManager()
-                                       .checkout(userHome.getPath());
-                       String[] roleIds = userGroupIds.toArray(new String[userGroupIds
-                                       .size()]);
-                       userHome.setProperty(ArgeoNames.ARGEO_REMOTE_ROLES, roleIds);
-                       JcrUtils.updateLastModified(userHome);
-                       session.save();
-                       session.getWorkspace().getVersionManager()
-                                       .checkin(userHome.getPath());
-               }
-
-       }
-
-       public void releaseSession(Session session) {
-               if (log.isTraceEnabled())
-                       log.trace("Releasing JCR session " + session);
-               if (openSessionInView) {
-                       JcrUtils.logoutQuietly(session);
-                       if (log.isDebugEnabled())
-                               log.debug("Logged out remote JCR session " + session);
-               }
-       }
-
-       public void init() {
-               if (log.isDebugEnabled())
-                       log.debug("Init session provider for web session " + webSessionId);
-       }
-
-       public void destroy() {
-               if (log.isDebugEnabled())
-                       log.debug("Destroy session provider for web session "
-                                       + webSessionId);
-
-               if (sessions != null)
-                       for (String workspace : sessions.keySet()) {
-                               Session session = sessions.get(workspace);
-                               JcrUtils.logoutQuietly(session);
-                       }
-       }
-
-       /**
-        * If set to true a new session will be created each time (the default),
-        * otherwise a single session is cached by workspace and the object should
-        * be of scope session (not supported)
-        */
-       public void setOpenSessionInView(Boolean openSessionInView) {
-               this.openSessionInView = openSessionInView;
-       }
-
-       public void setSecurityWorkspace(String securityWorkspace) {
-               this.defaultWorkspace = securityWorkspace;
-       }
-
-}
diff --git a/org.argeo.server.jackrabbit/src/main/java/org/argeo/jackrabbit/remote/SimpleWebdavHandlerMapping.java b/org.argeo.server.jackrabbit/src/main/java/org/argeo/jackrabbit/remote/SimpleWebdavHandlerMapping.java
deleted file mode 100644 (file)
index bd8d804..0000000
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * Copyright (C) 2007-2012 Argeo GmbH
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *         http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.argeo.jackrabbit.remote;
-
-import java.util.Properties;
-
-import javax.jcr.Repository;
-import javax.servlet.ServletException;
-import javax.servlet.http.HttpServlet;
-
-/** Handler mapping for WebDav */
-public class SimpleWebdavHandlerMapping extends
-               AbstractJackrabbitHandlerMapping {
-       private String configuration;
-
-       protected HttpServlet createServlet(Repository repository, String pathPrefix)
-                       throws ServletException {
-
-               SimpleWebdavServlet servlet = new SimpleWebdavServlet(repository,
-                               getSessionProvider());
-               Properties initParameters = new Properties();
-               initParameters.setProperty(
-                               SimpleWebdavServlet.INIT_PARAM_RESOURCE_CONFIG, configuration);
-               initParameters
-                               .setProperty(
-                                               SimpleWebdavServlet.INIT_PARAM_RESOURCE_PATH_PREFIX,
-                                               pathPrefix);
-               servlet.init(new DelegatingServletConfig(pathPrefix.replace('/', '_'),
-                               initParameters));
-               return servlet;
-       }
-
-       public void setConfiguration(String configuration) {
-               this.configuration = configuration;
-       }
-}
diff --git a/org.argeo.server.jackrabbit/src/main/java/org/argeo/jackrabbit/remote/SimpleWebdavServlet.java b/org.argeo.server.jackrabbit/src/main/java/org/argeo/jackrabbit/remote/SimpleWebdavServlet.java
deleted file mode 100644 (file)
index f1ca0a9..0000000
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- * Copyright (C) 2007-2012 Argeo GmbH
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *         http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.argeo.jackrabbit.remote;
-
-import java.io.IOException;
-
-import javax.jcr.Repository;
-import javax.servlet.ServletException;
-
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.apache.jackrabbit.server.SessionProvider;
-import org.apache.jackrabbit.webdav.DavException;
-import org.apache.jackrabbit.webdav.DavResource;
-import org.apache.jackrabbit.webdav.WebdavRequest;
-import org.apache.jackrabbit.webdav.WebdavResponse;
-
-/** WebDav servlet whose repository is injected */
-public class SimpleWebdavServlet extends
-               org.apache.jackrabbit.webdav.simple.SimpleWebdavServlet {
-       private static final long serialVersionUID = -369787931175177080L;
-
-       private final static Log log = LogFactory.getLog(SimpleWebdavServlet.class);
-
-       private final Repository repository;
-
-       public SimpleWebdavServlet(Repository repository,
-                       SessionProvider sessionProvider) {
-               this.repository = repository;
-               setSessionProvider(sessionProvider);
-       }
-
-       public Repository getRepository() {
-               return repository;
-       }
-
-       @Override
-       protected boolean execute(WebdavRequest request, WebdavResponse response,
-                       int method, DavResource resource) throws ServletException,
-                       IOException, DavException {
-               if (log.isTraceEnabled())
-                       log.trace(request.getMethod() + "\t" + request.getPathInfo());
-               boolean res = super.execute(request, response, method, resource);
-               return res;
-       }
-
-}
diff --git a/org.argeo.server.jackrabbit/src/main/resources/org/argeo/jackrabbit/repository-fs.xml b/org.argeo.server.jackrabbit/src/main/resources/org/argeo/jackrabbit/repository-fs.xml
deleted file mode 100644 (file)
index 609fc8b..0000000
+++ /dev/null
@@ -1,53 +0,0 @@
-<?xml version="1.0"?>
-<!DOCTYPE Repository PUBLIC "-//The Apache Software Foundation//DTD Jackrabbit 1.6//EN"
-                            "http://jackrabbit.apache.org/dtd/repository-2.0.dtd">
-<Repository>
-       <!-- File system and datastore -->
-       <FileSystem class="org.apache.jackrabbit.core.fs.local.LocalFileSystem">
-               <param name="path" value="${rep.home}/fs" />
-       </FileSystem>
-       <DataStore class="org.apache.jackrabbit.core.data.FileDataStore">
-               <param name="path" value="${rep.home}/datastore" />
-       </DataStore>
-
-       <!-- Workspace templates -->
-       <Workspaces rootPath="${rep.home}/workspaces"
-               defaultWorkspace="${argeo.node.repo.defaultWorkspace}" />
-       <Workspace name="${wsp.name}">
-               <FileSystem class="org.apache.jackrabbit.core.fs.local.LocalFileSystem">
-                       <param name="path" value="${wsp.home}" />
-               </FileSystem>
-               <PersistenceManager
-                       class="org.apache.jackrabbit.core.persistence.bundle.BundleFsPersistenceManager" />
-               <SearchIndex class="org.apache.jackrabbit.core.query.lucene.SearchIndex">
-                       <param name="path" value="${wsp.home}/index" />
-               </SearchIndex>
-       </Workspace>
-
-       <!-- Versioning -->
-       <Versioning rootPath="${rep.home}/version">
-               <FileSystem class="org.apache.jackrabbit.core.fs.local.LocalFileSystem">
-                       <param name="path" value="${rep.home}/version" />
-               </FileSystem>
-               <PersistenceManager
-                       class="org.apache.jackrabbit.core.persistence.bundle.BundleFsPersistenceManager" />
-       </Versioning>
-
-       <!-- Indexing -->
-       <SearchIndex class="org.apache.jackrabbit.core.query.lucene.SearchIndex">
-               <param name="path" value="${rep.home}/index" />
-               <param name="extractorPoolSize" value="2" />
-               <param name="supportHighlighting" value="true" />
-       </SearchIndex>
-
-       <!-- Security -->
-       <Security appName="Jackrabbit">
-               <SecurityManager class="org.argeo.security.jackrabbit.ArgeoSecurityManager"
-                       workspaceName="security">
-               </SecurityManager>
-               <AccessManager class="org.argeo.security.jackrabbit.ArgeoAccessManager">
-               </AccessManager>
-               <LoginModule class="org.argeo.security.jackrabbit.ArgeoLoginModule">
-               </LoginModule>
-       </Security>
-</Repository>
\ No newline at end of file
diff --git a/org.argeo.server.jackrabbit/src/main/resources/org/argeo/jackrabbit/repository-h2.xml b/org.argeo.server.jackrabbit/src/main/resources/org/argeo/jackrabbit/repository-h2.xml
deleted file mode 100644 (file)
index b6a9252..0000000
+++ /dev/null
@@ -1,77 +0,0 @@
-<?xml version="1.0"?>
-<!DOCTYPE Repository PUBLIC "-//The Apache Software Foundation//DTD Jackrabbit 1.6//EN"
-                            "http://jackrabbit.apache.org/dtd/repository-2.0.dtd">
-<Repository>
-       <!-- Shared datasource -->
-       <DataSources>
-               <DataSource name="dataSource">
-                       <param name="driver" value="org.h2.Driver" />
-                       <param name="url" value="jdbc:h2:${rep.home}/h2/repository" />
-                       <param name="user" value="sa" />
-                       <param name="password" value="" />
-                       <param name="databaseType" value="h2" />
-                       <param name="maxPoolSize" value="10" />
-               </DataSource>
-       </DataSources>
-
-       <!-- File system and datastore -->
-       <FileSystem class="org.apache.jackrabbit.core.fs.db.DbFileSystem">
-               <param name="dataSourceName" value="dataSource" />
-               <param name="schema" value="default" />
-               <param name="schemaObjectPrefix" value="fs_" />
-       </FileSystem>
-       <DataStore class="org.apache.jackrabbit.core.data.FileDataStore">
-               <param name="path" value="${rep.home}/datastore" />
-       </DataStore>
-
-       <!-- Workspace templates -->
-       <Workspaces rootPath="${rep.home}/workspaces"
-               defaultWorkspace="main" />
-       <Workspace name="${wsp.name}">
-               <FileSystem class="org.apache.jackrabbit.core.fs.db.DbFileSystem">
-                       <param name="dataSourceName" value="dataSource" />
-                       <param name="schema" value="default" />
-                       <param name="schemaObjectPrefix" value="${wsp.name}_fs_" />
-               </FileSystem>
-               <PersistenceManager
-                       class="org.apache.jackrabbit.core.persistence.pool.H2PersistenceManager">
-                       <param name="dataSourceName" value="dataSource" />
-                       <param name="schemaObjectPrefix" value="${wsp.name}_pm_" />
-               </PersistenceManager>
-               <SearchIndex class="org.apache.jackrabbit.core.query.lucene.SearchIndex">
-                       <param name="path" value="${wsp.home}/index" />
-               </SearchIndex>
-       </Workspace>
-
-       <!-- Versioning -->
-       <Versioning rootPath="${rep.home}/version">
-               <FileSystem class="org.apache.jackrabbit.core.fs.db.DbFileSystem">
-                       <param name="dataSourceName" value="dataSource" />
-                       <param name="schema" value="default" />
-                       <param name="schemaObjectPrefix" value="fs_ver_" />
-               </FileSystem>
-               <PersistenceManager
-                       class="org.apache.jackrabbit.core.persistence.pool.H2PersistenceManager">
-                       <param name="dataSourceName" value="dataSource" />
-                       <param name="schemaObjectPrefix" value="pm_ver_" />
-               </PersistenceManager>
-       </Versioning>
-
-       <!-- Indexing -->
-       <SearchIndex class="org.apache.jackrabbit.core.query.lucene.SearchIndex">
-               <param name="path" value="${rep.home}/index" />
-               <param name="extractorPoolSize" value="2" />
-               <param name="supportHighlighting" value="true" />
-       </SearchIndex>
-
-       <!-- Security -->
-       <Security appName="Jackrabbit">
-               <SecurityManager class="org.argeo.security.jackrabbit.ArgeoSecurityManager"
-                       workspaceName="security">
-               </SecurityManager>
-               <AccessManager class="org.argeo.security.jackrabbit.ArgeoAccessManager">
-               </AccessManager>
-               <LoginModule class="org.argeo.security.jackrabbit.ArgeoLoginModule">
-               </LoginModule>
-       </Security>
-</Repository>
\ No newline at end of file
diff --git a/org.argeo.server.jackrabbit/src/main/resources/org/argeo/jackrabbit/repository-memory.xml b/org.argeo.server.jackrabbit/src/main/resources/org/argeo/jackrabbit/repository-memory.xml
deleted file mode 100644 (file)
index e552c33..0000000
+++ /dev/null
@@ -1,69 +0,0 @@
-<?xml version="1.0"?>
-<!--
-
-    Copyright (C) 2007-2012 Argeo GmbH
-
-    Licensed under the Apache License, Version 2.0 (the "License");
-    you may not use this file except in compliance with the License.
-    You may obtain a copy of the License at
-
-            http://www.apache.org/licenses/LICENSE-2.0
-
-    Unless required by applicable law or agreed to in writing, software
-    distributed under the License is distributed on an "AS IS" BASIS,
-    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-    See the License for the specific language governing permissions and
-    limitations under the License.
-
--->
-<!DOCTYPE Repository PUBLIC "-//The Apache Software Foundation//DTD Jackrabbit 1.6//EN"
-                            "http://jackrabbit.apache.org/dtd/repository-2.0.dtd">
-<Repository>
-       <!-- File system and datastore -->
-       <FileSystem class="org.apache.jackrabbit.core.fs.mem.MemoryFileSystem" />
-
-       <!-- Workspace templates -->
-       <Workspaces rootPath="${rep.home}/workspaces"
-               defaultWorkspace="main" configRootPath="/workspaces" />
-       <Workspace name="${wsp.name}">
-               <FileSystem class="org.apache.jackrabbit.core.fs.mem.MemoryFileSystem" />
-               <PersistenceManager
-                       class="org.apache.jackrabbit.core.persistence.bundle.BundleFsPersistenceManager">
-                       <param name="blobFSBlockSize" value="1" />
-               </PersistenceManager>
-               <SearchIndex class="org.apache.jackrabbit.core.query.lucene.SearchIndex">
-                       <param name="path" value="${rep.home}/repository/index" />
-                       <param name="directoryManagerClass"
-                               value="org.apache.jackrabbit.core.query.lucene.directory.RAMDirectoryManager" />
-                       <FileSystem class="org.apache.jackrabbit.core.fs.mem.MemoryFileSystem" />
-               </SearchIndex>
-       </Workspace>
-
-       <!-- Versioning -->
-       <Versioning rootPath="${rep.home}/version">
-               <FileSystem class="org.apache.jackrabbit.core.fs.mem.MemoryFileSystem" />
-               <PersistenceManager
-                       class="org.apache.jackrabbit.core.persistence.bundle.BundleFsPersistenceManager">
-                       <param name="blobFSBlockSize" value="1" />
-               </PersistenceManager>
-       </Versioning>
-
-       <!-- Indexing -->
-       <SearchIndex class="org.apache.jackrabbit.core.query.lucene.SearchIndex">
-               <param name="path" value="${rep.home}/repository/index" />
-               <param name="directoryManagerClass"
-                       value="org.apache.jackrabbit.core.query.lucene.directory.RAMDirectoryManager" />
-               <FileSystem class="org.apache.jackrabbit.core.fs.mem.MemoryFileSystem" />
-       </SearchIndex>
-
-       <!-- Security -->
-       <Security appName="Jackrabbit">
-               <SecurityManager class="org.argeo.security.jackrabbit.ArgeoSecurityManager"
-                       workspaceName="security">
-               </SecurityManager>
-               <AccessManager class="org.argeo.security.jackrabbit.ArgeoAccessManager">
-               </AccessManager>
-               <LoginModule class="org.argeo.security.jackrabbit.ArgeoLoginModule">
-               </LoginModule>
-       </Security>
-</Repository>
\ No newline at end of file
diff --git a/org.argeo.server.jackrabbit/src/main/wikitext/design.mediawiki b/org.argeo.server.jackrabbit/src/main/wikitext/design.mediawiki
deleted file mode 100644 (file)
index 1a27383..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-= Titre =\r
-\r
- == Sous Titre ==\r
-\r
-* point1\r
-* point2\r
-\r
- Code (il suffit de mettre un espace en début de ligne\r
\ No newline at end of file
diff --git a/org.argeo.server.jackrabbit/src/org/argeo/jackrabbit/JackrabbitAuthorizations.java b/org.argeo.server.jackrabbit/src/org/argeo/jackrabbit/JackrabbitAuthorizations.java
new file mode 100644 (file)
index 0000000..e880b67
--- /dev/null
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2007-2012 Argeo GmbH
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *         http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.argeo.jackrabbit;
+
+import java.security.Principal;
+import java.util.Arrays;
+import java.util.List;
+
+import javax.jcr.RepositoryException;
+import javax.jcr.Session;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.jackrabbit.api.JackrabbitSession;
+import org.apache.jackrabbit.api.security.user.Authorizable;
+import org.apache.jackrabbit.api.security.user.UserManager;
+import org.argeo.ArgeoException;
+import org.argeo.jcr.security.JcrAuthorizations;
+
+/** Apply authorizations to a Jackrabbit repository. */
+public class JackrabbitAuthorizations extends JcrAuthorizations {
+       private final static Log log = LogFactory
+                       .getLog(JackrabbitAuthorizations.class);
+
+       private List<String> groupPrefixes = Arrays
+                       .asList(new String[] { "ROLE_" });// new ArrayList<String>();
+
+       @Override
+       protected Principal getOrCreatePrincipal(Session session,
+                       String principalName) throws RepositoryException {
+               UserManager um = ((JackrabbitSession) session).getUserManager();
+               synchronized (um) {
+                       Authorizable authorizable = um.getAuthorizable(principalName);
+                       if (authorizable == null) {
+                               groupPrefixes: for (String groupPrefix : groupPrefixes) {
+                                       if (principalName.startsWith(groupPrefix)) {
+                                               authorizable = um.createGroup(principalName);
+                                               log.info("Created group " + principalName);
+                                               break groupPrefixes;
+                                       }
+                               }
+                               if (authorizable == null)
+                                       throw new ArgeoException("Authorizable " + principalName
+                                                       + " not found");
+                       }
+                       return authorizable.getPrincipal();
+               }
+       }
+
+       public void setGroupPrefixes(List<String> groupsToCreate) {
+               this.groupPrefixes = groupsToCreate;
+       }
+}
diff --git a/org.argeo.server.jackrabbit/src/org/argeo/jackrabbit/JackrabbitContainer.java b/org.argeo.server.jackrabbit/src/org/argeo/jackrabbit/JackrabbitContainer.java
new file mode 100644 (file)
index 0000000..9060b58
--- /dev/null
@@ -0,0 +1,352 @@
+/*
+ * Copyright (C) 2007-2012 Argeo GmbH
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *         http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.argeo.jackrabbit;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Properties;
+import java.util.Set;
+import java.util.TreeSet;
+import java.util.UUID;
+
+import javax.jcr.Node;
+import javax.jcr.Repository;
+import javax.jcr.RepositoryException;
+import javax.jcr.Session;
+
+import org.apache.commons.io.FileUtils;
+import org.apache.commons.io.IOUtils;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.jackrabbit.api.JackrabbitRepository;
+import org.apache.jackrabbit.core.RepositoryImpl;
+import org.apache.jackrabbit.core.config.RepositoryConfig;
+import org.apache.jackrabbit.core.config.RepositoryConfigurationParser;
+import org.argeo.ArgeoException;
+import org.argeo.jcr.ArgeoNames;
+import org.argeo.jcr.JcrUtils;
+import org.argeo.jcr.MaintainedRepository;
+import org.springframework.core.io.Resource;
+import org.springframework.util.SystemPropertyUtils;
+import org.xml.sax.InputSource;
+
+/**
+ * Wrapper around a Jackrabbit repository which allows to configure it in Spring
+ * and expose it as a {@link Repository}.
+ */
+public class JackrabbitContainer extends JackrabbitWrapper implements
+               MaintainedRepository {
+       private final static Log log = LogFactory.getLog(JackrabbitContainer.class);
+
+       // local
+       private Resource configuration;
+       private Resource variables;
+       private RepositoryConfig repositoryConfig;
+       private File homeDirectory;
+       private Boolean inMemory = false;
+
+       /** Migrations to execute (if not already done) */
+       private Set<JackrabbitDataModelMigration> dataModelMigrations = new HashSet<JackrabbitDataModelMigration>();
+
+       /**
+        * Empty constructor, {@link #init()} should be called after properties have
+        * been set
+        */
+       public JackrabbitContainer() {
+       }
+
+       public void init() {
+               long begin = System.currentTimeMillis();
+
+               if (getRepository() != null)
+                       throw new ArgeoException(
+                                       "Cannot be used to wrap another repository");
+               Repository repository = createJackrabbitRepository();
+               super.setRepository(repository);
+
+               // migrate if needed
+               migrate();
+
+               // apply new CND files after migration
+               prepareDataModel();
+
+               double duration = ((double) (System.currentTimeMillis() - begin)) / 1000;
+               if (log.isDebugEnabled())
+                       log.debug("Initialized JCR repository wrapper in " + duration
+                                       + " s");
+       }
+
+       /** Actually creates the new repository. */
+       protected Repository createJackrabbitRepository() {
+               long begin = System.currentTimeMillis();
+               InputStream configurationIn = null;
+               Repository repository;
+               try {
+                       // temporary
+                       if (inMemory && getHomeDirectory().exists()) {
+                               FileUtils.deleteDirectory(getHomeDirectory());
+                               log.warn("Deleted Jackrabbit home directory "
+                                               + getHomeDirectory());
+                       }
+
+                       // process configuration file
+                       Properties vars = getConfigurationProperties();
+                       configurationIn = readConfiguration();
+                       vars.put(RepositoryConfigurationParser.REPOSITORY_HOME_VARIABLE,
+                                       getHomeDirectory().getCanonicalPath());
+                       repositoryConfig = RepositoryConfig.create(new InputSource(
+                                       configurationIn), vars);
+
+                       //
+                       // Actual repository creation
+                       //
+                       repository = RepositoryImpl.create(repositoryConfig);
+
+                       double duration = ((double) (System.currentTimeMillis() - begin)) / 1000;
+                       if (log.isTraceEnabled())
+                               log.trace("Created Jackrabbit repository in " + duration
+                                               + " s, home: " + getHomeDirectory());
+
+                       return repository;
+               } catch (Exception e) {
+                       throw new ArgeoException("Cannot create Jackrabbit repository "
+                                       + getHomeDirectory(), e);
+               } finally {
+                       IOUtils.closeQuietly(configurationIn);
+               }
+       }
+
+       /** Lazy init. */
+       protected File getHomeDirectory() {
+               try {
+                       if (homeDirectory == null) {
+                               if (inMemory) {
+                                       homeDirectory = new File(
+                                                       System.getProperty("java.io.tmpdir")
+                                                                       + File.separator
+                                                                       + System.getProperty("user.name")
+                                                                       + File.separator + "jackrabbit-"
+                                                                       + UUID.randomUUID());
+                                       homeDirectory.mkdirs();
+                                       // will it work if directory is not empty??
+                                       homeDirectory.deleteOnExit();
+                               }
+                       }
+
+                       return homeDirectory.getCanonicalFile();
+               } catch (IOException e) {
+                       throw new ArgeoException("Cannot get canonical file for "
+                                       + homeDirectory, e);
+               }
+       }
+
+       /** Executes migrations, if needed. */
+       protected void migrate() {
+               // No migration to perform
+               if (dataModelMigrations.size() == 0)
+                       return;
+
+               Boolean restartAndClearCaches = false;
+
+               // migrate data
+               Session session = null;
+               try {
+                       session = login();
+                       for (JackrabbitDataModelMigration dataModelMigration : new TreeSet<JackrabbitDataModelMigration>(
+                                       dataModelMigrations)) {
+                               if (dataModelMigration.migrate(session)) {
+                                       restartAndClearCaches = true;
+                               }
+                       }
+               } catch (ArgeoException e) {
+                       throw e;
+               } catch (Exception e) {
+                       throw new ArgeoException("Cannot migrate", e);
+               } finally {
+                       JcrUtils.logoutQuietly(session);
+               }
+
+               // restart repository
+               if (restartAndClearCaches) {
+                       Repository repository = getRepository();
+                       if (repository instanceof RepositoryImpl) {
+                               JackrabbitDataModelMigration
+                                               .clearRepositoryCaches(((RepositoryImpl) repository)
+                                                               .getConfig());
+                       }
+                       ((JackrabbitRepository) repository).shutdown();
+                       createJackrabbitRepository();
+               }
+
+               // set data model version
+               try {
+                       session = login();
+               } catch (RepositoryException e) {
+                       throw new ArgeoException("Cannot login to migrated repository", e);
+               }
+
+               for (JackrabbitDataModelMigration dataModelMigration : new TreeSet<JackrabbitDataModelMigration>(
+                               dataModelMigrations)) {
+                       try {
+                               if (session.itemExists(dataModelMigration
+                                               .getDataModelNodePath())) {
+                                       Node dataModelNode = session.getNode(dataModelMigration
+                                                       .getDataModelNodePath());
+                                       dataModelNode.setProperty(
+                                                       ArgeoNames.ARGEO_DATA_MODEL_VERSION,
+                                                       dataModelMigration.getTargetVersion());
+                                       session.save();
+                               }
+                       } catch (Exception e) {
+                               log.error("Cannot set model version", e);
+                       }
+               }
+               JcrUtils.logoutQuietly(session);
+
+       }
+
+       /** Shutdown the repository */
+       public void destroy() throws Exception {
+               Repository repository = getRepository();
+               if (repository != null && repository instanceof RepositoryImpl) {
+                       long begin = System.currentTimeMillis();
+                       ((RepositoryImpl) repository).shutdown();
+                       if (inMemory)
+                               if (getHomeDirectory().exists()) {
+                                       FileUtils.deleteDirectory(getHomeDirectory());
+                                       if (log.isDebugEnabled())
+                                               log.debug("Deleted Jackrabbit home directory "
+                                                               + getHomeDirectory());
+                               }
+                       double duration = ((double) (System.currentTimeMillis() - begin)) / 1000;
+                       log.info("Destroyed Jackrabbit repository in " + duration
+                                       + " s, home: " + getHomeDirectory());
+               }
+               repository = null;
+       }
+
+       public void dispose() {
+               throw new IllegalArgumentException(
+                               "Call destroy() method instead of dispose()");
+       }
+
+       /*
+        * UTILITIES
+        */
+       /**
+        * Reads the configuration which will initialize a {@link RepositoryConfig}.
+        */
+       protected InputStream readConfiguration() {
+               try {
+                       return configuration != null ? configuration.getInputStream()
+                                       : null;
+               } catch (IOException e) {
+                       throw new ArgeoException("Cannot read Jackrabbit configuration "
+                                       + configuration, e);
+               }
+       }
+
+       /**
+        * Reads the variables which will initialize a {@link Properties}. Returns
+        * null by default, to be overridden.
+        * 
+        * @return a new stream or null if no variables available
+        */
+       protected InputStream readVariables() {
+               try {
+                       return variables != null ? variables.getInputStream() : null;
+               } catch (IOException e) {
+                       throw new ArgeoException("Cannot read Jackrabbit variables "
+                                       + variables, e);
+               }
+       }
+
+       /**
+        * Resolves ${} placeholders in the provided string. Based on system
+        * properties if no map is provided.
+        */
+       protected String resolvePlaceholders(String string,
+                       Map<String, String> variables) {
+               return SystemPropertyUtils.resolvePlaceholders(string);
+       }
+
+       /** Generates the properties to use in the configuration. */
+       protected Properties getConfigurationProperties() {
+               InputStream propsIn = null;
+               Properties vars;
+               try {
+                       vars = new Properties();
+                       propsIn = readVariables();
+                       if (propsIn != null) {
+                               vars.load(propsIn);
+                       }
+                       // resolve system properties
+                       for (Object key : vars.keySet()) {
+                               // TODO: implement a smarter mechanism to resolve nested ${}
+                               String newValue = resolvePlaceholders(
+                                               vars.getProperty(key.toString()), null);
+                               vars.put(key, newValue);
+                       }
+                       // override with system properties
+                       vars.putAll(System.getProperties());
+
+                       if (log.isTraceEnabled()) {
+                               log.trace("Jackrabbit config variables:");
+                               for (Object key : new TreeSet<Object>(vars.keySet()))
+                                       log.trace(key + "=" + vars.getProperty(key.toString()));
+                       }
+
+               } catch (IOException e) {
+                       throw new ArgeoException("Cannot read configuration properties", e);
+               } finally {
+                       IOUtils.closeQuietly(propsIn);
+               }
+               return vars;
+       }
+
+       /*
+        * FIELDS ACCESS
+        */
+
+       public void setHomeDirectory(File homeDirectory) {
+               this.homeDirectory = homeDirectory;
+       }
+
+       public void setInMemory(Boolean inMemory) {
+               this.inMemory = inMemory;
+       }
+
+       public void setRepository(Repository repository) {
+               throw new ArgeoException("Cannot be used to wrap another repository");
+       }
+
+       public void setDataModelMigrations(
+                       Set<JackrabbitDataModelMigration> dataModelMigrations) {
+               this.dataModelMigrations = dataModelMigrations;
+       }
+
+       public void setVariables(Resource variables) {
+               this.variables = variables;
+       }
+
+       public void setConfiguration(Resource configuration) {
+               this.configuration = configuration;
+       }
+
+}
diff --git a/org.argeo.server.jackrabbit/src/org/argeo/jackrabbit/JackrabbitDataModelMigration.java b/org.argeo.server.jackrabbit/src/org/argeo/jackrabbit/JackrabbitDataModelMigration.java
new file mode 100644 (file)
index 0000000..401b34d
--- /dev/null
@@ -0,0 +1,182 @@
+/*
+ * Copyright (C) 2007-2012 Argeo GmbH
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *         http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.argeo.jackrabbit;
+
+import java.io.InputStreamReader;
+import java.io.Reader;
+
+import javax.jcr.Node;
+import javax.jcr.Session;
+
+import org.apache.commons.io.IOUtils;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.jackrabbit.commons.cnd.CndImporter;
+import org.apache.jackrabbit.core.config.RepositoryConfig;
+import org.argeo.ArgeoException;
+import org.argeo.jcr.ArgeoNames;
+import org.argeo.jcr.JcrCallback;
+import org.argeo.jcr.JcrUtils;
+import org.springframework.core.io.Resource;
+
+/** Migrate the data in a Jackrabbit repository. */
+public class JackrabbitDataModelMigration implements
+               Comparable<JackrabbitDataModelMigration> {
+       private final static Log log = LogFactory
+                       .getLog(JackrabbitDataModelMigration.class);
+
+       private String dataModelNodePath;
+       private String targetVersion;
+       private Resource migrationCnd;
+       private JcrCallback dataModification;
+
+       /**
+        * Expects an already started repository with the old data model to migrate.
+        * Expects to be run with admin rights (Repository.login() will be used).
+        * 
+        * @return true if a migration was performed and the repository needs to be
+        *         restarted and its caches cleared.
+        */
+       public Boolean migrate(Session session) {
+               long begin = System.currentTimeMillis();
+               Reader reader = null;
+               try {
+                       // check if already migrated
+                       if (!session.itemExists(dataModelNodePath)) {
+                               log.warn("Node " + dataModelNodePath
+                                               + " does not exist: nothing to migrate.");
+                               return false;
+                       }
+                       Node dataModelNode = session.getNode(dataModelNodePath);
+                       if (dataModelNode.hasProperty(ArgeoNames.ARGEO_DATA_MODEL_VERSION)) {
+                               String currentVersion = dataModelNode.getProperty(
+                                               ArgeoNames.ARGEO_DATA_MODEL_VERSION).getString();
+                               if (compareVersions(currentVersion, targetVersion) >= 0) {
+                                       log.info("Data model at version " + currentVersion
+                                                       + ", no need to migrate.");
+                                       return false;
+                               }
+                       }
+
+                       // apply transitional CND
+                       if (migrationCnd != null) {
+                               reader = new InputStreamReader(migrationCnd.getInputStream());
+                               CndImporter.registerNodeTypes(reader, session, true);
+                               session.save();
+                               log.info("Registered migration node types from " + migrationCnd);
+                       }
+
+                       // modify data
+                       dataModification.execute(session);
+
+                       // apply changes
+                       session.save();
+
+                       long duration = System.currentTimeMillis() - begin;
+                       log.info("Migration of data model " + dataModelNodePath + " to "
+                                       + targetVersion + " performed in " + duration + "ms");
+                       return true;
+               } catch (Exception e) {
+                       JcrUtils.discardQuietly(session);
+                       throw new ArgeoException("Migration of data model "
+                                       + dataModelNodePath + " to " + targetVersion + " failed.",
+                                       e);
+               } finally {
+                       JcrUtils.logoutQuietly(session);
+                       IOUtils.closeQuietly(reader);
+               }
+       }
+
+       protected static int compareVersions(String version1, String version2) {
+               // TODO do a proper version analysis and comparison
+               return version1.compareTo(version2);
+       }
+
+       /** To be called on a stopped repository. */
+       public static void clearRepositoryCaches(RepositoryConfig repositoryConfig) {
+               try {
+                       String customeNodeTypesPath = "/nodetypes/custom_nodetypes.xml";
+                       repositoryConfig.getFileSystem().deleteFile(customeNodeTypesPath);
+                       if (log.isDebugEnabled())
+                               log.debug("Cleared " + customeNodeTypesPath);
+               } catch (Exception e) {
+                       throw new ArgeoException("Cannot clear caches", e);
+               }
+
+               // File customNodeTypes = new File(home.getPath()
+               // + "/repository/nodetypes/custom_nodetypes.xml");
+               // if (customNodeTypes.exists()) {
+               // customNodeTypes.delete();
+               // if (log.isDebugEnabled())
+               // log.debug("Cleared " + customNodeTypes);
+               // } else {
+               // log.warn("File " + customNodeTypes + " not found.");
+               // }
+       }
+
+       /*
+        * FOR USE IN (SORTED) SETS
+        */
+
+       public int compareTo(JackrabbitDataModelMigration dataModelMigration) {
+               // TODO make ordering smarter
+               if (dataModelNodePath.equals(dataModelMigration.dataModelNodePath))
+                       return compareVersions(targetVersion,
+                                       dataModelMigration.targetVersion);
+               else
+                       return dataModelNodePath
+                                       .compareTo(dataModelMigration.dataModelNodePath);
+       }
+
+       @Override
+       public boolean equals(Object obj) {
+               if (!(obj instanceof JackrabbitDataModelMigration))
+                       return false;
+               JackrabbitDataModelMigration dataModelMigration = (JackrabbitDataModelMigration) obj;
+               return dataModelNodePath.equals(dataModelMigration.dataModelNodePath)
+                               && targetVersion.equals(dataModelMigration.targetVersion);
+       }
+
+       @Override
+       public int hashCode() {
+               return targetVersion.hashCode();
+       }
+
+       public void setDataModelNodePath(String dataModelNodePath) {
+               this.dataModelNodePath = dataModelNodePath;
+       }
+
+       public void setTargetVersion(String targetVersion) {
+               this.targetVersion = targetVersion;
+       }
+
+       public void setMigrationCnd(Resource migrationCnd) {
+               this.migrationCnd = migrationCnd;
+       }
+
+       public void setDataModification(JcrCallback dataModification) {
+               this.dataModification = dataModification;
+       }
+
+       public String getDataModelNodePath() {
+               return dataModelNodePath;
+       }
+
+       public String getTargetVersion() {
+               return targetVersion;
+       }
+
+}
diff --git a/org.argeo.server.jackrabbit/src/org/argeo/jackrabbit/JackrabbitRepositoryFactory.java b/org.argeo.server.jackrabbit/src/org/argeo/jackrabbit/JackrabbitRepositoryFactory.java
new file mode 100644 (file)
index 0000000..d64bb5e
--- /dev/null
@@ -0,0 +1,169 @@
+/*
+ * Copyright (C) 2007-2012 Argeo GmbH
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *         http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.argeo.jackrabbit;
+
+import java.io.File;
+import java.io.InputStream;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Properties;
+
+import javax.jcr.Repository;
+import javax.jcr.RepositoryException;
+import javax.jcr.RepositoryFactory;
+import javax.jcr.Session;
+
+import org.apache.commons.io.IOUtils;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.jackrabbit.commons.JcrUtils;
+import org.apache.jackrabbit.core.RepositoryImpl;
+import org.apache.jackrabbit.core.config.RepositoryConfig;
+import org.apache.jackrabbit.core.config.RepositoryConfigurationParser;
+import org.apache.jackrabbit.jcr2dav.Jcr2davRepositoryFactory;
+import org.argeo.ArgeoException;
+import org.argeo.jcr.ArgeoJcrConstants;
+import org.argeo.jcr.DefaultRepositoryFactory;
+import org.springframework.core.io.ClassPathResource;
+import org.springframework.core.io.Resource;
+import org.xml.sax.InputSource;
+
+/**
+ * Repository factory which can create new repositories and access remote
+ * Jackrabbit repositories
+ */
+public class JackrabbitRepositoryFactory extends DefaultRepositoryFactory
+               implements RepositoryFactory, ArgeoJcrConstants {
+
+       private final static Log log = LogFactory
+                       .getLog(JackrabbitRepositoryFactory.class);
+
+       private Resource fileRepositoryConfiguration = new ClassPathResource(
+                       "/org/argeo/jackrabbit/repository-h2.xml");
+
+       @SuppressWarnings({ "rawtypes", "unchecked" })
+       public Repository getRepository(Map parameters) throws RepositoryException {
+               // check if can be found by alias
+               Repository repository = super.getRepository(parameters);
+               if (repository != null)
+                       return repository;
+
+               // check if remote
+               String uri = null;
+               if (parameters.containsKey(JCR_REPOSITORY_URI))
+                       uri = parameters.get(JCR_REPOSITORY_URI).toString();
+               else if (parameters.containsKey(JcrUtils.REPOSITORY_URI))
+                       uri = parameters.get(JcrUtils.REPOSITORY_URI).toString();
+
+               if (uri != null) {
+                       if (uri.startsWith("http"))// http, https
+                               repository = createRemoteRepository(uri);
+                       else if (uri.startsWith("file"))// http, https
+                               repository = createFileRepository(uri, parameters);
+                       else if (uri.startsWith("vm")) {
+                               log.warn("URI "
+                                               + uri
+                                               + " should have been managed by generic JCR repository factory");
+                               repository = getRepositoryByAlias(getAliasFromURI(uri));
+                       }
+               }
+
+               // publish under alias
+               if (parameters.containsKey(JCR_REPOSITORY_ALIAS)) {
+                       Properties properties = new Properties();
+                       properties.putAll(parameters);
+                       String alias = parameters.get(JCR_REPOSITORY_ALIAS).toString();
+                       publish(alias, repository, properties);
+                       log.info("Registered JCR repository under alias '" + alias
+                                       + "' with properties " + properties);
+               }
+
+               return repository;
+       }
+
+       protected Repository createRemoteRepository(String uri)
+                       throws RepositoryException {
+               Map<String, String> params = new HashMap<String, String>();
+               params.put(JcrUtils.REPOSITORY_URI, uri);
+               Repository repository = new Jcr2davRepositoryFactory()
+                               .getRepository(params);
+               if (repository == null)
+                       throw new ArgeoException("Remote Davex repository " + uri
+                                       + " not found");
+               log.info("Initialized remote Jackrabbit repository from uri " + uri);
+               return repository;
+       }
+
+       @SuppressWarnings({ "rawtypes", "unchecked" })
+       protected Repository createFileRepository(final String uri, Map parameters)
+                       throws RepositoryException {
+               InputStream configurationIn = null;
+               try {
+                       Properties vars = new Properties();
+                       vars.putAll(parameters);
+                       String dirPath = uri.substring("file:".length());
+                       File homeDir = new File(dirPath);
+                       if (homeDir.exists() && !homeDir.isDirectory())
+                               throw new ArgeoException("Repository home " + dirPath
+                                               + " is not a directory");
+                       if (!homeDir.exists())
+                               homeDir.mkdirs();
+                       configurationIn = fileRepositoryConfiguration.getInputStream();
+                       vars.put(RepositoryConfigurationParser.REPOSITORY_HOME_VARIABLE,
+                                       homeDir.getCanonicalPath());
+                       RepositoryConfig repositoryConfig = RepositoryConfig.create(
+                                       new InputSource(configurationIn), vars);
+
+                       // TransientRepository repository = new
+                       // TransientRepository(repositoryConfig);
+                       final RepositoryImpl repository = RepositoryImpl
+                                       .create(repositoryConfig);
+                       Session session = repository.login();
+                       // FIXME make it generic
+                       org.argeo.jcr.JcrUtils.addPrivilege(session, "/", "ROLE_ADMIN",
+                                       "jcr:all");
+                       org.argeo.jcr.JcrUtils.logoutQuietly(session);
+                       Runtime.getRuntime().addShutdownHook(
+                                       new Thread("Clean JCR repository " + uri) {
+                                               public void run() {
+                                                       repository.shutdown();
+                                                       log.info("Destroyed repository " + uri);
+                                               }
+                                       });
+                       log.info("Initialized file Jackrabbit repository from uri " + uri);
+                       return repository;
+               } catch (Exception e) {
+                       throw new ArgeoException("Cannot create repository " + uri, e);
+               } finally {
+                       IOUtils.closeQuietly(configurationIn);
+               }
+       }
+
+       /**
+        * Called after the repository has been initialised. Does nothing by
+        * default.
+        */
+       @SuppressWarnings("rawtypes")
+       protected void postInitialization(Repository repository, Map parameters) {
+
+       }
+
+       public void setFileRepositoryConfiguration(
+                       Resource fileRepositoryConfiguration) {
+               this.fileRepositoryConfiguration = fileRepositoryConfiguration;
+       }
+
+}
diff --git a/org.argeo.server.jackrabbit/src/org/argeo/jackrabbit/JackrabbitWrapper.java b/org.argeo.server.jackrabbit/src/org/argeo/jackrabbit/JackrabbitWrapper.java
new file mode 100644 (file)
index 0000000..f9f04c4
--- /dev/null
@@ -0,0 +1,375 @@
+/*
+ * Copyright (C) 2007-2012 Argeo GmbH
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *         http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.argeo.jackrabbit;
+
+import java.io.ByteArrayInputStream;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.Reader;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import javax.jcr.Credentials;
+import javax.jcr.Node;
+import javax.jcr.NodeIterator;
+import javax.jcr.Repository;
+import javax.jcr.Session;
+import javax.jcr.nodetype.NodeType;
+
+import org.apache.commons.io.FilenameUtils;
+import org.apache.commons.io.IOUtils;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.jackrabbit.commons.NamespaceHelper;
+import org.apache.jackrabbit.commons.cnd.CndImporter;
+import org.argeo.ArgeoException;
+import org.argeo.jcr.ArgeoJcrConstants;
+import org.argeo.jcr.ArgeoNames;
+import org.argeo.jcr.ArgeoTypes;
+import org.argeo.jcr.JcrRepositoryWrapper;
+import org.argeo.jcr.JcrUtils;
+import org.argeo.util.security.DigestUtils;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.ServiceReference;
+import org.osgi.service.packageadmin.ExportedPackage;
+import org.osgi.service.packageadmin.PackageAdmin;
+import org.springframework.context.ResourceLoaderAware;
+import org.springframework.core.io.Resource;
+import org.springframework.core.io.ResourceLoader;
+
+/**
+ * Wrapper around a Jackrabbit repository which allows to simplify configuration
+ * and intercept some actions. It exposes itself as a {@link Repository}.
+ */
+public class JackrabbitWrapper extends JcrRepositoryWrapper implements
+               ResourceLoaderAware {
+       private final static Log log = LogFactory.getLog(JackrabbitWrapper.class);
+       private final static String DIGEST_ALGORITHM = "MD5";
+
+       // local
+       private ResourceLoader resourceLoader;
+
+       // data model
+       /** Node type definitions in CND format */
+       private List<String> cndFiles = new ArrayList<String>();
+       /**
+        * Always import CNDs. Useful during development of new data models. In
+        * production, explicit migration processes should be used.
+        */
+       private Boolean forceCndImport = true;
+
+       /** Namespaces to register: key is prefix, value namespace */
+       private Map<String, String> namespaces = new HashMap<String, String>();
+
+       private BundleContext bundleContext;
+
+       /**
+        * Explicitly set admin credentials used in initialization. Useful for
+        * testing, in real applications authentication is rather dealt with
+        * externally
+        */
+       private Credentials adminCredentials = null;
+
+       /**
+        * Empty constructor, {@link #init()} should be called after properties have
+        * been set
+        */
+       public JackrabbitWrapper() {
+       }
+
+       @Override
+       public void init() {
+               prepareDataModel();
+       }
+
+       /*
+        * DATA MODEL
+        */
+
+       /**
+        * Import declared node type definitions and register namespaces. Tries to
+        * update the node definitions if they have changed. In case of failures an
+        * error will be logged but no exception will be thrown.
+        */
+       protected void prepareDataModel() {
+               if ((cndFiles == null || cndFiles.size() == 0)
+                               && (namespaces == null || namespaces.size() == 0))
+                       return;
+
+               Session session = null;
+               try {
+                       session = login(adminCredentials);
+                       // register namespaces
+                       if (namespaces.size() > 0) {
+                               NamespaceHelper namespaceHelper = new NamespaceHelper(session);
+                               namespaceHelper.registerNamespaces(namespaces);
+                       }
+
+                       // load CND files from classpath or as URL
+                       for (String resUrl : cndFiles) {
+                               processCndFile(session, resUrl);
+                       }
+               } catch (Exception e) {
+                       JcrUtils.discardQuietly(session);
+                       throw new ArgeoException("Cannot import node type definitions "
+                                       + cndFiles, e);
+               } finally {
+                       JcrUtils.logoutQuietly(session);
+               }
+
+       }
+
+       protected void processCndFile(Session session, String resUrl) {
+               Reader reader = null;
+               try {
+                       // check existing data model nodes
+                       new NamespaceHelper(session).registerNamespace(ArgeoNames.ARGEO,
+                                       ArgeoNames.ARGEO_NAMESPACE);
+                       if (!session.itemExists(ArgeoJcrConstants.DATA_MODELS_BASE_PATH))
+                               JcrUtils.mkdirs(session,
+                                               ArgeoJcrConstants.DATA_MODELS_BASE_PATH);
+                       Node dataModels = session
+                                       .getNode(ArgeoJcrConstants.DATA_MODELS_BASE_PATH);
+                       NodeIterator it = dataModels.getNodes();
+                       Node dataModel = null;
+                       while (it.hasNext()) {
+                               Node node = it.nextNode();
+                               if (node.getProperty(ArgeoNames.ARGEO_URI).getString()
+                                               .equals(resUrl)) {
+                                       dataModel = node;
+                                       break;
+                               }
+                       }
+
+                       byte[] cndContent = readCndContent(resUrl);
+                       String newDigest = DigestUtils.digest(DIGEST_ALGORITHM, cndContent);
+                       Bundle bundle = findDataModelBundle(resUrl);
+
+                       String currentVersion = null;
+                       if (dataModel != null) {
+                               currentVersion = dataModel.getProperty(
+                                               ArgeoNames.ARGEO_DATA_MODEL_VERSION).getString();
+                               if (dataModel.hasNode(Node.JCR_CONTENT)) {
+                                       String oldDigest = JcrUtils.checksumFile(dataModel,
+                                                       DIGEST_ALGORITHM);
+                                       if (oldDigest.equals(newDigest)) {
+                                               if (log.isDebugEnabled())
+                                                       log.debug("Data model " + resUrl
+                                                                       + " hasn't changed, keeping version "
+                                                                       + currentVersion);
+                                               return;
+                                       }
+                               }
+                       }
+
+                       if (dataModel != null && !forceCndImport) {
+                               log.info("Data model "
+                                               + resUrl
+                                               + " has changed since version "
+                                               + currentVersion
+                                               + (bundle != null ? ": version " + bundle.getVersion()
+                                                               + ", bundle " + bundle.getSymbolicName() : ""));
+                               return;
+                       }
+
+                       reader = new InputStreamReader(new ByteArrayInputStream(cndContent));
+                       // actually imports the CND
+                       try {
+                               CndImporter.registerNodeTypes(reader, session, true);
+                       } catch (Exception e) {
+                               log.error("Cannot import data model " + resUrl, e);
+                               return;
+                       }
+
+                       if (dataModel != null && !dataModel.isNodeType(NodeType.NT_FILE)) {
+                               dataModel.remove();
+                               dataModel = null;
+                       }
+
+                       // FIXME: what if argeo.cnd would not be the first called on
+                       // a new repo? argeo:dataModel would not be found
+                       String fileName = FilenameUtils.getName(resUrl);
+                       if (dataModel == null) {
+                               dataModel = dataModels.addNode(fileName, NodeType.NT_FILE);
+                               dataModel.addNode(Node.JCR_CONTENT, NodeType.NT_RESOURCE);
+                               dataModel.addMixin(ArgeoTypes.ARGEO_DATA_MODEL);
+                               dataModel.setProperty(ArgeoNames.ARGEO_URI, resUrl);
+                       } else {
+                               session.getWorkspace().getVersionManager()
+                                               .checkout(dataModel.getPath());
+                       }
+                       if (bundle != null)
+                               dataModel.setProperty(ArgeoNames.ARGEO_DATA_MODEL_VERSION,
+                                               bundle.getVersion().toString());
+                       else
+                               dataModel.setProperty(ArgeoNames.ARGEO_DATA_MODEL_VERSION,
+                                               "0.0.0");
+                       JcrUtils.copyBytesAsFile(dataModel.getParent(), fileName,
+                                       cndContent);
+                       JcrUtils.updateLastModified(dataModel);
+                       session.save();
+                       session.getWorkspace().getVersionManager()
+                                       .checkin(dataModel.getPath());
+
+                       if (currentVersion == null)
+                               log.info("Data model "
+                                               + resUrl
+                                               + (bundle != null ? ", version " + bundle.getVersion()
+                                                               + ", bundle " + bundle.getSymbolicName() : ""));
+                       else
+                               log.info("Data model "
+                                               + resUrl
+                                               + " updated from version "
+                                               + currentVersion
+                                               + (bundle != null ? ", version " + bundle.getVersion()
+                                                               + ", bundle " + bundle.getSymbolicName() : ""));
+               } catch (Exception e) {
+                       throw new ArgeoException("Cannot process data model " + resUrl, e);
+               } finally {
+                       IOUtils.closeQuietly(reader);
+               }
+       }
+
+       protected byte[] readCndContent(String resUrl) {
+               InputStream in = null;
+               try {
+                       boolean classpath;
+                       // normalize URL
+                       if (bundleContext != null && resUrl.startsWith("classpath:")) {
+                               resUrl = resUrl.substring("classpath:".length());
+                               classpath = true;
+                       } else if (resUrl.indexOf(':') < 0) {
+                               if (!resUrl.startsWith("/")) {
+                                       resUrl = "/" + resUrl;
+                                       log.warn("Classpath should start with '/'");
+                               }
+                               classpath = true;
+                       } else {
+                               classpath = false;
+                       }
+
+                       URL url = null;
+                       if (classpath) {
+                               if (bundleContext != null) {
+                                       Bundle currentBundle = bundleContext.getBundle();
+                                       url = currentBundle.getResource(resUrl);
+                               } else {
+                                       resUrl = "classpath:" + resUrl;
+                                       url = null;
+                               }
+                       } else if (!resUrl.startsWith("classpath:")) {
+                               url = new URL(resUrl);
+                       }
+
+                       if (url != null) {
+                               in = url.openStream();
+                       } else if (resourceLoader != null) {
+                               Resource res = resourceLoader.getResource(resUrl);
+                               in = res.getInputStream();
+                               url = res.getURL();
+                       } else {
+                               throw new ArgeoException("No " + resUrl + " in the classpath,"
+                                               + " make sure the containing" + " package is visible.");
+                       }
+
+                       return IOUtils.toByteArray(in);
+               } catch (Exception e) {
+                       throw new ArgeoException("Cannot read CND from " + resUrl, e);
+               } finally {
+                       IOUtils.closeQuietly(in);
+               }
+       }
+
+       /*
+        * REPOSITORY INTERCEPTOR
+        */
+
+       /*
+        * UTILITIES
+        */
+       /** Find which OSGi bundle provided the data model resource */
+       protected Bundle findDataModelBundle(String resUrl) {
+               if (bundleContext == null)
+                       return null;
+
+               if (resUrl.startsWith("/"))
+                       resUrl = resUrl.substring(1);
+               String pkg = resUrl.substring(0, resUrl.lastIndexOf('/')).replace('/',
+                               '.');
+               ServiceReference paSr = bundleContext
+                               .getServiceReference(PackageAdmin.class.getName());
+               PackageAdmin packageAdmin = (PackageAdmin) bundleContext
+                               .getService(paSr);
+
+               // find exported package
+               ExportedPackage exportedPackage = null;
+               ExportedPackage[] exportedPackages = packageAdmin
+                               .getExportedPackages(pkg);
+               if (exportedPackages == null)
+                       throw new ArgeoException("No exported package found for " + pkg);
+               for (ExportedPackage ep : exportedPackages) {
+                       for (Bundle b : ep.getImportingBundles()) {
+                               if (b.getBundleId() == bundleContext.getBundle().getBundleId()) {
+                                       exportedPackage = ep;
+                                       break;
+                               }
+                       }
+               }
+
+               Bundle exportingBundle = null;
+               if (exportedPackage != null) {
+                       exportingBundle = exportedPackage.getExportingBundle();
+               } else {
+                       // assume this is in the same bundle
+                       exportingBundle = bundleContext.getBundle();
+//                     throw new ArgeoException("No OSGi exporting package found for "
+//                                     + resUrl);
+               }
+               return exportingBundle;
+       }
+
+       /*
+        * FIELDS ACCESS
+        */
+       public void setNamespaces(Map<String, String> namespaces) {
+               this.namespaces = namespaces;
+       }
+
+       public void setCndFiles(List<String> cndFiles) {
+               this.cndFiles = cndFiles;
+       }
+
+       public void setBundleContext(BundleContext bundleContext) {
+               this.bundleContext = bundleContext;
+       }
+
+       public void setForceCndImport(Boolean forceCndUpdate) {
+               this.forceCndImport = forceCndUpdate;
+       }
+
+       public void setResourceLoader(ResourceLoader resourceLoader) {
+               this.resourceLoader = resourceLoader;
+       }
+
+       public void setAdminCredentials(Credentials adminCredentials) {
+               this.adminCredentials = adminCredentials;
+       }
+
+}
diff --git a/org.argeo.server.jackrabbit/src/org/argeo/jackrabbit/OsgiJackrabbitRepositoryFactory.java b/org.argeo.server.jackrabbit/src/org/argeo/jackrabbit/OsgiJackrabbitRepositoryFactory.java
new file mode 100644 (file)
index 0000000..b28699e
--- /dev/null
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2007-2012 Argeo GmbH
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *         http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.argeo.jackrabbit;
+
+import java.util.Hashtable;
+import java.util.Properties;
+
+import javax.jcr.Repository;
+
+import org.osgi.framework.BundleContext;
+
+/**
+ * OSGi-aware Jackrabbit repository factory which can retrieve/publish
+ * {@link Repository} as OSGi services.
+ */
+public class OsgiJackrabbitRepositoryFactory extends
+               JackrabbitRepositoryFactory {
+       private BundleContext bundleContext;
+
+       protected void publish(String alias, Repository repository,
+                       Properties properties) {
+               if (bundleContext != null) {
+                       // do not modify reference
+                       Hashtable<String, String> props = new Hashtable<String, String>();
+                       props.putAll(props);
+                       props.put(JCR_REPOSITORY_ALIAS, alias);
+                       bundleContext.registerService(Repository.class.getName(),
+                                       repository, props);
+               }
+       }
+
+       public void setBundleContext(BundleContext bundleContext) {
+               this.bundleContext = bundleContext;
+       }
+
+}
diff --git a/org.argeo.server.jackrabbit/src/org/argeo/jackrabbit/remote/AbstractJackrabbitHandlerMapping.java b/org.argeo.server.jackrabbit/src/org/argeo/jackrabbit/remote/AbstractJackrabbitHandlerMapping.java
new file mode 100644 (file)
index 0000000..99bfab4
--- /dev/null
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2007-2012 Argeo GmbH
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *         http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.argeo.jackrabbit.remote;
+
+import org.apache.jackrabbit.server.SessionProvider;
+import org.argeo.jcr.mvc.MultipleRepositoryHandlerMapping;
+
+/** Base class for Jackrabbit handler mappings. */
+public abstract class AbstractJackrabbitHandlerMapping extends
+               MultipleRepositoryHandlerMapping {
+       private SessionProvider sessionProvider;
+
+       protected SessionProvider getSessionProvider() {
+               return sessionProvider;
+       }
+
+       public void setSessionProvider(SessionProvider sessionProvider) {
+               this.sessionProvider = sessionProvider;
+       }
+
+}
diff --git a/org.argeo.server.jackrabbit/src/org/argeo/jackrabbit/remote/ExtendedDispatcherServlet.java b/org.argeo.server.jackrabbit/src/org/argeo/jackrabbit/remote/ExtendedDispatcherServlet.java
new file mode 100644 (file)
index 0000000..14b6e99
--- /dev/null
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2007-2012 Argeo GmbH
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *         http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.argeo.jackrabbit.remote;
+
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.argeo.ArgeoException;
+import org.springframework.web.servlet.DispatcherServlet;
+
+/**
+ * Overrides Spring {@link DispatcherServlet}, see
+ * http://forum.springsource.org/showthread.php?t=53472.
+ */
+public class ExtendedDispatcherServlet extends DispatcherServlet {
+       private static final long serialVersionUID = -5584673209855752009L;
+
+       private final static Log log = LogFactory
+                       .getLog(ExtendedDispatcherServlet.class);
+
+       protected void service(HttpServletRequest request,
+                       HttpServletResponse response) throws ServletException,
+                       java.io.IOException {
+               try {
+                       if (log.isTraceEnabled()) {
+                               log.trace("SessionID    = " + request.getSession().getId());
+                               log.trace(" ContextPath = " + request.getContextPath());
+                               log.trace(" ServletPath = " + request.getServletPath());
+                               log.trace(" PathInfo    = " + request.getPathInfo());
+                               log.trace(" Method      = " + request.getMethod());
+                               log.trace(" User-Agent  = " + request.getHeader("User-Agent"));
+                       }
+                       doService(request, response);
+               } catch (Exception e) {
+                       throw new ArgeoException("Cannot process request", e);
+               }
+       }
+
+}
diff --git a/org.argeo.server.jackrabbit/src/org/argeo/jackrabbit/remote/IOHandlerWrapper.java b/org.argeo.server.jackrabbit/src/org/argeo/jackrabbit/remote/IOHandlerWrapper.java
new file mode 100644 (file)
index 0000000..daf2ecb
--- /dev/null
@@ -0,0 +1,114 @@
+/*
+ * Copyright (C) 2007-2012 Argeo GmbH
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *         http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.argeo.jackrabbit.remote;
+
+import java.io.IOException;
+
+import org.apache.jackrabbit.server.io.ExportContext;
+import org.apache.jackrabbit.server.io.IOHandler;
+import org.apache.jackrabbit.server.io.IOManager;
+import org.apache.jackrabbit.server.io.ImportContext;
+import org.apache.jackrabbit.webdav.DavResource;
+import org.argeo.ArgeoException;
+
+/** Wraps an IOHandler so that it can be injected a posteriori */
+public class IOHandlerWrapper implements IOHandler {
+       private IOManager ioManager = null;
+       private IOHandler ioHandler = null;
+
+       public void setIOHandler(IOHandler ioHandler) {
+               if ((this.ioHandler != null) && (ioHandler != null))
+                       throw new ArgeoException(
+                                       "There is already an IO Handler registered");
+               this.ioHandler = ioHandler;
+               if (ioManager != null && this.ioHandler != null)
+                       ioHandler.setIOManager(ioManager);
+       }
+
+       public IOHandler getIOHandler() {
+               return ioHandler;
+       }
+
+       public IOManager getIOManager() {
+               return ioManager;
+       }
+
+       public void setIOManager(IOManager ioManager) {
+               this.ioManager = ioManager;
+               if (ioHandler != null)
+                       ioHandler.setIOManager(ioManager);
+       }
+
+       public String getName() {
+               if (ioHandler != null)
+                       return ioHandler.getName();
+               else
+                       return "Empty IOHandler Wrapper";
+       }
+
+       public boolean canImport(ImportContext context, boolean isCollection) {
+               if (ioHandler != null)
+                       return ioHandler.canImport(context, isCollection);
+               return false;
+       }
+
+       public boolean canImport(ImportContext context, DavResource resource) {
+               if (ioHandler != null)
+                       return ioHandler.canImport(context, resource);
+               return false;
+       }
+
+       public boolean importContent(ImportContext context, boolean isCollection)
+                       throws IOException {
+               if (ioHandler != null)
+                       ioHandler.importContent(context, isCollection);
+               return false;
+       }
+
+       public boolean importContent(ImportContext context, DavResource resource)
+                       throws IOException {
+               if (ioHandler != null)
+                       ioHandler.importContent(context, resource);
+               return false;
+       }
+
+       public boolean canExport(ExportContext context, boolean isCollection) {
+               if (ioHandler != null)
+                       ioHandler.canExport(context, isCollection);
+               return false;
+       }
+
+       public boolean canExport(ExportContext context, DavResource resource) {
+               if (ioHandler != null)
+                       ioHandler.canExport(context, resource);
+               return false;
+       }
+
+       public boolean exportContent(ExportContext context, boolean isCollection)
+                       throws IOException {
+               if (ioHandler != null)
+                       ioHandler.exportContent(context, isCollection);
+               return false;
+       }
+
+       public boolean exportContent(ExportContext context, DavResource resource)
+                       throws IOException {
+               if (ioHandler != null)
+                       ioHandler.exportContent(context, resource);
+               return false;
+       }
+
+}
diff --git a/org.argeo.server.jackrabbit/src/org/argeo/jackrabbit/remote/IOManagerBean.java b/org.argeo.server.jackrabbit/src/org/argeo/jackrabbit/remote/IOManagerBean.java
new file mode 100644 (file)
index 0000000..82a7673
--- /dev/null
@@ -0,0 +1,82 @@
+/*
+ * Copyright (C) 2007-2012 Argeo GmbH
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *         http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.argeo.jackrabbit.remote;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.jackrabbit.server.io.ExportContext;
+import org.apache.jackrabbit.server.io.IOHandler;
+import org.apache.jackrabbit.server.io.IOManager;
+import org.apache.jackrabbit.server.io.ImportContext;
+import org.apache.jackrabbit.webdav.DavResource;
+import org.apache.tika.detect.Detector;
+
+/** {@link IOManager} that can easily be configured as a bean. */
+public class IOManagerBean implements IOManager {
+       private Detector detector = null;
+       private List<IOHandler> ioHandlers = new ArrayList<IOHandler>();
+
+       public boolean importContent(ImportContext context, boolean isCollection)
+                       throws IOException {
+               // TODO Auto-generated method stub
+               return false;
+       }
+
+       public boolean importContent(ImportContext context, DavResource resource)
+                       throws IOException {
+               // TODO Auto-generated method stub
+               return false;
+       }
+
+       public boolean exportContent(ExportContext context, boolean isCollection)
+                       throws IOException {
+               // TODO Auto-generated method stub
+               return false;
+       }
+
+       public boolean exportContent(ExportContext context, DavResource resource)
+                       throws IOException {
+               // TODO Auto-generated method stub
+               return false;
+       }
+
+       public synchronized void addIOHandler(IOHandler ioHandler) {
+               ioHandlers.add(ioHandler);
+       }
+
+       public synchronized IOHandler[] getIOHandlers() {
+               return ioHandlers.toArray(new IOHandler[ioHandlers.size()]);
+       }
+
+       public Detector getDetector() {
+               return detector;
+       }
+
+       public void setDetector(Detector detector) {
+               this.detector = detector;
+       }
+
+       public synchronized List<IOHandler> getIoHandlers() {
+               return ioHandlers;
+       }
+
+       public synchronized void setIoHandlers(List<IOHandler> ioHandlers) {
+               this.ioHandlers = ioHandlers;
+       }
+
+}
diff --git a/org.argeo.server.jackrabbit/src/org/argeo/jackrabbit/remote/JcrRemotingHandlerMapping.java b/org.argeo.server.jackrabbit/src/org/argeo/jackrabbit/remote/JcrRemotingHandlerMapping.java
new file mode 100644 (file)
index 0000000..caea5fc
--- /dev/null
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2007-2012 Argeo GmbH
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *         http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.argeo.jackrabbit.remote;
+
+import java.util.Properties;
+
+import javax.jcr.Repository;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServlet;
+
+public class JcrRemotingHandlerMapping extends AbstractJackrabbitHandlerMapping {
+
+       protected HttpServlet createServlet(Repository repository, String pathPrefix)
+                       throws ServletException {
+               JcrRemotingServlet servlet = new JcrRemotingServlet(repository,
+                               getSessionProvider());
+               Properties initParameters = new Properties();
+               initParameters.setProperty(
+                               JcrRemotingServlet.INIT_PARAM_RESOURCE_PATH_PREFIX, pathPrefix);
+               servlet.init(new DelegatingServletConfig(pathPrefix.replace('/', '_'),
+                               initParameters));
+               return servlet;
+       }
+}
diff --git a/org.argeo.server.jackrabbit/src/org/argeo/jackrabbit/remote/JcrRemotingServlet.java b/org.argeo.server.jackrabbit/src/org/argeo/jackrabbit/remote/JcrRemotingServlet.java
new file mode 100644 (file)
index 0000000..b3f0797
--- /dev/null
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2007-2012 Argeo GmbH
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *         http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.argeo.jackrabbit.remote;
+
+import javax.jcr.Repository;
+
+import org.apache.jackrabbit.server.SessionProvider;
+
+public class JcrRemotingServlet extends
+               org.apache.jackrabbit.server.remoting.davex.JcrRemotingServlet {
+
+       private static final long serialVersionUID = 3131835511468341309L;
+
+       private final Repository repository;
+       private final SessionProvider sessionProvider;
+
+       public JcrRemotingServlet(Repository repository,
+                       SessionProvider sessionProvider) {
+               this.repository = repository;
+               this.sessionProvider = sessionProvider;
+       }
+
+       @Override
+       protected Repository getRepository() {
+               return repository;
+       }
+
+       @Override
+       protected SessionProvider getSessionProvider() {
+               return sessionProvider;
+       }
+
+}
diff --git a/org.argeo.server.jackrabbit/src/org/argeo/jackrabbit/remote/OpenInViewSessionProvider.java b/org.argeo.server.jackrabbit/src/org/argeo/jackrabbit/remote/OpenInViewSessionProvider.java
new file mode 100644 (file)
index 0000000..b4d1d60
--- /dev/null
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2007-2012 Argeo GmbH
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *         http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.argeo.jackrabbit.remote;
+
+import java.io.Serializable;
+
+import javax.jcr.LoginException;
+import javax.jcr.Repository;
+import javax.jcr.RepositoryException;
+import javax.jcr.Session;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.jackrabbit.server.SessionProvider;
+import org.argeo.jcr.JcrUtils;
+
+/**
+ * Implements an open session in view patter: a new JCR session is created for
+ * each request
+ */
+public class OpenInViewSessionProvider implements SessionProvider, Serializable {
+       private static final long serialVersionUID = 2270957712453841368L;
+
+       private final static Log log = LogFactory
+                       .getLog(OpenInViewSessionProvider.class);
+
+       public Session getSession(HttpServletRequest request, Repository rep,
+                       String workspace) throws LoginException, ServletException,
+                       RepositoryException {
+               return login(request, rep, workspace);
+       }
+
+       protected Session login(HttpServletRequest request, Repository repository,
+                       String workspace) throws RepositoryException {
+               if (log.isTraceEnabled())
+                       log.trace("Login to workspace "
+                                       + (workspace == null ? "<default>" : workspace)
+                                       + " in web session " + request.getSession().getId());
+               return repository.login(workspace);
+       }
+
+       public void releaseSession(Session session) {
+               JcrUtils.logoutQuietly(session);
+               if (log.isTraceEnabled())
+                       log.trace("Logged out remote JCR session " + session);
+       }
+
+       public void init() {
+       }
+
+       public void destroy() {
+       }
+
+}
diff --git a/org.argeo.server.jackrabbit/src/org/argeo/jackrabbit/remote/ScopedSessionProvider.java b/org.argeo.server.jackrabbit/src/org/argeo/jackrabbit/remote/ScopedSessionProvider.java
new file mode 100644 (file)
index 0000000..ffe6df9
--- /dev/null
@@ -0,0 +1,171 @@
+/*
+ * Copyright (C) 2007-2012 Argeo GmbH
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *         http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.argeo.jackrabbit.remote;
+
+import java.io.Serializable;
+
+import javax.jcr.LoginException;
+import javax.jcr.Repository;
+import javax.jcr.RepositoryException;
+import javax.jcr.Session;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpSession;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.jackrabbit.server.SessionProvider;
+import org.argeo.ArgeoException;
+import org.argeo.jcr.ArgeoJcrConstants;
+import org.argeo.jcr.JcrUtils;
+import org.springframework.security.Authentication;
+import org.springframework.security.context.SecurityContextHolder;
+
+/**
+ * Session provider assuming a single workspace and a short life cycle,
+ * typically a Spring bean of scope (web) 'session'.
+ */
+public class ScopedSessionProvider implements SessionProvider, Serializable {
+       private static final long serialVersionUID = 6589775984177317058L;
+       private static final Log log = LogFactory
+                       .getLog(ScopedSessionProvider.class);
+       private transient HttpSession httpSession = null;
+       private transient Session jcrSession = null;
+
+       private transient String currentRepositoryName = null;
+       private transient String currentWorkspaceName = null;
+       private transient String currentJcrUser = null;
+
+       // private transient String anonymousUserId = "anonymous";
+
+       public Session getSession(HttpServletRequest request, Repository rep,
+                       String workspace) throws LoginException, ServletException,
+                       RepositoryException {
+
+               Authentication authentication = SecurityContextHolder.getContext()
+                               .getAuthentication();
+               if (authentication == null)
+                       throw new ArgeoException(
+                                       "Request not authenticated by Spring Security");
+               String springUser = authentication.getName();
+
+               // HTTP
+               String requestJcrRepository = (String) request
+                               .getAttribute(ArgeoJcrConstants.JCR_REPOSITORY_ALIAS);
+
+               // HTTP session
+               if (httpSession != null
+                               && !httpSession.getId().equals(request.getSession().getId()))
+                       throw new ArgeoException(
+                                       "Only session scope is supported in this mode");
+               if (httpSession == null)
+                       httpSession = request.getSession();
+
+               // Initializes current values
+               if (currentRepositoryName == null)
+                       currentRepositoryName = requestJcrRepository;
+               if (currentWorkspaceName == null)
+                       currentWorkspaceName = workspace;
+               if (currentJcrUser == null)
+                       currentJcrUser = springUser;
+
+               // logout if there was a change in session coordinates
+               if (jcrSession != null)
+                       if (!currentRepositoryName.equals(requestJcrRepository)) {
+                               if (log.isDebugEnabled())
+                                       log.debug(getHttpSessionId() + " Changed from repository '"
+                                                       + currentRepositoryName + "' to '"
+                                                       + requestJcrRepository
+                                                       + "', logging out cached JCR session.");
+                               logout();
+                       } else if (!currentWorkspaceName.equals(workspace)) {
+                               if (log.isDebugEnabled())
+                                       log.debug(getHttpSessionId() + " Changed from workspace '"
+                                                       + currentWorkspaceName + "' to '" + workspace
+                                                       + "', logging out cached JCR session.");
+                               logout();
+                       } else if (!currentJcrUser.equals(springUser)) {
+                               if (log.isDebugEnabled())
+                                       log.debug(getHttpSessionId() + " Changed from user '"
+                                                       + currentJcrUser + "' to '" + springUser
+                                                       + "', logging out cached JCR session.");
+                               logout();
+                       }
+
+               // login if needed
+               if (jcrSession == null)
+                       try {
+                               Session session = login(rep, workspace);
+                               if (!session.getUserID().equals(springUser)) {
+                                       JcrUtils.logoutQuietly(session);
+                                       throw new ArgeoException("Spring Security user '"
+                                                       + springUser + "' not in line with JCR user '"
+                                                       + session.getUserID() + "'");
+                               }
+                               currentRepositoryName = requestJcrRepository;
+                               // do not use workspace variable which may be null
+                               currentWorkspaceName = session.getWorkspace().getName();
+                               currentJcrUser = session.getUserID();
+
+                               jcrSession = session;
+                               return jcrSession;
+                       } catch (RepositoryException e) {
+                               throw new ArgeoException("Cannot open session to workspace "
+                                               + workspace, e);
+                       }
+
+               // returns cached session
+               return jcrSession;
+       }
+
+       protected Session login(Repository repository, String workspace)
+                       throws RepositoryException {
+               Session session = repository.login(workspace);
+               if (log.isDebugEnabled())
+                       log.debug(getHttpSessionId() + " User '" + session.getUserID()
+                                       + "' logged in workspace '"
+                                       + session.getWorkspace().getName() + "' of repository '"
+                                       + currentRepositoryName + "'");
+               return session;
+       }
+
+       public void releaseSession(Session session) {
+               if (log.isTraceEnabled())
+                       log.trace(getHttpSessionId() + " Releasing JCR session " + session);
+       }
+
+       protected void logout() {
+               JcrUtils.logoutQuietly(jcrSession);
+               jcrSession = null;
+       }
+
+       protected final String getHttpSessionId() {
+               return httpSession != null ? httpSession.getId() : "<null>";
+       }
+
+       public void init() {
+       }
+
+       public void destroy() {
+               logout();
+               if (getHttpSessionId() != null)
+                       if (log.isDebugEnabled())
+                               log.debug(getHttpSessionId()
+                                               + " Cleaned up provider for web session ");
+               httpSession = null;
+       }
+
+}
diff --git a/org.argeo.server.jackrabbit/src/org/argeo/jackrabbit/remote/SimpleSessionProvider.java b/org.argeo.server.jackrabbit/src/org/argeo/jackrabbit/remote/SimpleSessionProvider.java
new file mode 100644 (file)
index 0000000..1d438d5
--- /dev/null
@@ -0,0 +1,216 @@
+/*
+ * Copyright (C) 2007-2012 Argeo GmbH
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *         http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.argeo.jackrabbit.remote;
+
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+import javax.jcr.LoginException;
+import javax.jcr.Node;
+import javax.jcr.Repository;
+import javax.jcr.RepositoryException;
+import javax.jcr.Session;
+import javax.jcr.Value;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.jackrabbit.api.JackrabbitSession;
+import org.apache.jackrabbit.api.security.user.Group;
+import org.apache.jackrabbit.api.security.user.User;
+import org.apache.jackrabbit.api.security.user.UserManager;
+import org.apache.jackrabbit.server.SessionProvider;
+import org.argeo.ArgeoException;
+import org.argeo.jcr.ArgeoNames;
+import org.argeo.jcr.JcrUtils;
+import org.argeo.jcr.UserJcrUtils;
+
+/**
+ * Implements an open session in view patter: a new JCR session is created for
+ * each request
+ * 
+ * @deprecated use {@link ScopedSessionProvider} or
+ *             {@link OpenInViewSessionProvider}
+ */
+@Deprecated
+public class SimpleSessionProvider implements SessionProvider, Serializable {
+       private static final long serialVersionUID = 2270957712453841368L;
+
+       private final static Log log = LogFactory
+                       .getLog(SimpleSessionProvider.class);
+
+       private transient Map<String, Session> sessions;
+
+       private Boolean openSessionInView = true;
+
+       private String defaultWorkspace = "default";
+
+       private String webSessionId = null;
+
+       public Session getSession(HttpServletRequest request, Repository rep,
+                       String workspace) throws LoginException, ServletException,
+                       RepositoryException {
+
+               if (openSessionInView) {
+                       JackrabbitSession session = (JackrabbitSession) login(request, rep,
+                                       workspace);
+                       if (session.getWorkspace().getName().equals(defaultWorkspace))
+                               writeRemoteRoles(session);
+                       return session;
+               } else {
+                       if (webSessionId != null
+                                       && !webSessionId.equals(request.getSession().getId()))
+                               throw new ArgeoException(
+                                               "Only session scope is supported in this mode");
+                       webSessionId = request.getSession().getId();
+
+                       // since sessions is transient it can't be restored from the session
+                       if (sessions == null)
+                               sessions = Collections
+                                               .synchronizedMap(new HashMap<String, Session>());
+
+                       if (!sessions.containsKey(workspace)) {
+                               try {
+                                       // JackrabbitSession session = (JackrabbitSession)
+                                       // rep.login(
+                                       // null, workspace);
+                                       JackrabbitSession session = (JackrabbitSession) login(
+                                                       request, rep, workspace);
+                                       if (session.getWorkspace().getName()
+                                                       .equals(defaultWorkspace))
+                                               writeRemoteRoles(session);
+                                       if (log.isTraceEnabled())
+                                               log.trace("User " + session.getUserID()
+                                                               + " logged into " + request.getServletPath());
+                                       sessions.put(workspace, session);
+                                       return session;
+                               } catch (Exception e) {
+                                       throw new ArgeoException("Cannot open session", e);
+                               }
+                       } else {
+                               Session session = sessions.get(workspace);
+                               if (!session.isLive()) {
+                                       sessions.remove(workspace);
+                                       session = login(request, rep, workspace);
+                                       sessions.put(workspace, session);
+                               }
+                               return session;
+                       }
+               }
+       }
+
+       protected Session login(HttpServletRequest request, Repository repository,
+                       String workspace) throws RepositoryException {
+               if (log.isDebugEnabled())
+                       log.debug("Login to workspace "
+                                       + (workspace == null ? "<default>" : workspace)
+                                       + " in web session " + request.getSession().getId());
+               return repository.login(workspace);
+       }
+
+       protected void writeRemoteRoles(JackrabbitSession session)
+                       throws RepositoryException {
+               // FIXME better deal w/ non node repo
+
+               // retrieve roles
+               String userId = session.getUserID();
+               UserManager userManager = session.getUserManager();
+               User user = (User) userManager.getAuthorizable(userId);
+               if (user == null) {
+                       // anonymous
+                       return;
+               }
+               List<String> userGroupIds = new ArrayList<String>();
+               if (user != null)
+                       for (Iterator<Group> it = user.memberOf(); it.hasNext();)
+                               userGroupIds.add(it.next().getID());
+
+               // write roles if needed
+               Node userHome = UserJcrUtils.getUserHome(session);
+               boolean writeRoles = false;
+               if (userHome.hasProperty(ArgeoNames.ARGEO_REMOTE_ROLES)) {
+                       Value[] roles = userHome.getProperty(ArgeoNames.ARGEO_REMOTE_ROLES)
+                                       .getValues();
+                       if (roles.length != userGroupIds.size())
+                               writeRoles = true;
+                       else
+                               for (int i = 0; i < roles.length; i++)
+                                       if (!roles[i].getString().equals(userGroupIds.get(i)))
+                                               writeRoles = true;
+               } else
+                       writeRoles = true;
+
+               if (writeRoles) {
+                       session.getWorkspace().getVersionManager()
+                                       .checkout(userHome.getPath());
+                       String[] roleIds = userGroupIds.toArray(new String[userGroupIds
+                                       .size()]);
+                       userHome.setProperty(ArgeoNames.ARGEO_REMOTE_ROLES, roleIds);
+                       JcrUtils.updateLastModified(userHome);
+                       session.save();
+                       session.getWorkspace().getVersionManager()
+                                       .checkin(userHome.getPath());
+               }
+
+       }
+
+       public void releaseSession(Session session) {
+               if (log.isTraceEnabled())
+                       log.trace("Releasing JCR session " + session);
+               if (openSessionInView) {
+                       JcrUtils.logoutQuietly(session);
+                       if (log.isDebugEnabled())
+                               log.debug("Logged out remote JCR session " + session);
+               }
+       }
+
+       public void init() {
+               if (log.isDebugEnabled())
+                       log.debug("Init session provider for web session " + webSessionId);
+       }
+
+       public void destroy() {
+               if (log.isDebugEnabled())
+                       log.debug("Destroy session provider for web session "
+                                       + webSessionId);
+
+               if (sessions != null)
+                       for (String workspace : sessions.keySet()) {
+                               Session session = sessions.get(workspace);
+                               JcrUtils.logoutQuietly(session);
+                       }
+       }
+
+       /**
+        * If set to true a new session will be created each time (the default),
+        * otherwise a single session is cached by workspace and the object should
+        * be of scope session (not supported)
+        */
+       public void setOpenSessionInView(Boolean openSessionInView) {
+               this.openSessionInView = openSessionInView;
+       }
+
+       public void setSecurityWorkspace(String securityWorkspace) {
+               this.defaultWorkspace = securityWorkspace;
+       }
+
+}
diff --git a/org.argeo.server.jackrabbit/src/org/argeo/jackrabbit/remote/SimpleWebdavHandlerMapping.java b/org.argeo.server.jackrabbit/src/org/argeo/jackrabbit/remote/SimpleWebdavHandlerMapping.java
new file mode 100644 (file)
index 0000000..bd8d804
--- /dev/null
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2007-2012 Argeo GmbH
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *         http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.argeo.jackrabbit.remote;
+
+import java.util.Properties;
+
+import javax.jcr.Repository;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServlet;
+
+/** Handler mapping for WebDav */
+public class SimpleWebdavHandlerMapping extends
+               AbstractJackrabbitHandlerMapping {
+       private String configuration;
+
+       protected HttpServlet createServlet(Repository repository, String pathPrefix)
+                       throws ServletException {
+
+               SimpleWebdavServlet servlet = new SimpleWebdavServlet(repository,
+                               getSessionProvider());
+               Properties initParameters = new Properties();
+               initParameters.setProperty(
+                               SimpleWebdavServlet.INIT_PARAM_RESOURCE_CONFIG, configuration);
+               initParameters
+                               .setProperty(
+                                               SimpleWebdavServlet.INIT_PARAM_RESOURCE_PATH_PREFIX,
+                                               pathPrefix);
+               servlet.init(new DelegatingServletConfig(pathPrefix.replace('/', '_'),
+                               initParameters));
+               return servlet;
+       }
+
+       public void setConfiguration(String configuration) {
+               this.configuration = configuration;
+       }
+}
diff --git a/org.argeo.server.jackrabbit/src/org/argeo/jackrabbit/remote/SimpleWebdavServlet.java b/org.argeo.server.jackrabbit/src/org/argeo/jackrabbit/remote/SimpleWebdavServlet.java
new file mode 100644 (file)
index 0000000..f1ca0a9
--- /dev/null
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2007-2012 Argeo GmbH
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *         http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.argeo.jackrabbit.remote;
+
+import java.io.IOException;
+
+import javax.jcr.Repository;
+import javax.servlet.ServletException;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.jackrabbit.server.SessionProvider;
+import org.apache.jackrabbit.webdav.DavException;
+import org.apache.jackrabbit.webdav.DavResource;
+import org.apache.jackrabbit.webdav.WebdavRequest;
+import org.apache.jackrabbit.webdav.WebdavResponse;
+
+/** WebDav servlet whose repository is injected */
+public class SimpleWebdavServlet extends
+               org.apache.jackrabbit.webdav.simple.SimpleWebdavServlet {
+       private static final long serialVersionUID = -369787931175177080L;
+
+       private final static Log log = LogFactory.getLog(SimpleWebdavServlet.class);
+
+       private final Repository repository;
+
+       public SimpleWebdavServlet(Repository repository,
+                       SessionProvider sessionProvider) {
+               this.repository = repository;
+               setSessionProvider(sessionProvider);
+       }
+
+       public Repository getRepository() {
+               return repository;
+       }
+
+       @Override
+       protected boolean execute(WebdavRequest request, WebdavResponse response,
+                       int method, DavResource resource) throws ServletException,
+                       IOException, DavException {
+               if (log.isTraceEnabled())
+                       log.trace(request.getMethod() + "\t" + request.getPathInfo());
+               boolean res = super.execute(request, response, method, resource);
+               return res;
+       }
+
+}
diff --git a/org.argeo.server.jackrabbit/src/org/argeo/jackrabbit/repository-fs.xml b/org.argeo.server.jackrabbit/src/org/argeo/jackrabbit/repository-fs.xml
new file mode 100644 (file)
index 0000000..609fc8b
--- /dev/null
@@ -0,0 +1,53 @@
+<?xml version="1.0"?>
+<!DOCTYPE Repository PUBLIC "-//The Apache Software Foundation//DTD Jackrabbit 1.6//EN"
+                            "http://jackrabbit.apache.org/dtd/repository-2.0.dtd">
+<Repository>
+       <!-- File system and datastore -->
+       <FileSystem class="org.apache.jackrabbit.core.fs.local.LocalFileSystem">
+               <param name="path" value="${rep.home}/fs" />
+       </FileSystem>
+       <DataStore class="org.apache.jackrabbit.core.data.FileDataStore">
+               <param name="path" value="${rep.home}/datastore" />
+       </DataStore>
+
+       <!-- Workspace templates -->
+       <Workspaces rootPath="${rep.home}/workspaces"
+               defaultWorkspace="${argeo.node.repo.defaultWorkspace}" />
+       <Workspace name="${wsp.name}">
+               <FileSystem class="org.apache.jackrabbit.core.fs.local.LocalFileSystem">
+                       <param name="path" value="${wsp.home}" />
+               </FileSystem>
+               <PersistenceManager
+                       class="org.apache.jackrabbit.core.persistence.bundle.BundleFsPersistenceManager" />
+               <SearchIndex class="org.apache.jackrabbit.core.query.lucene.SearchIndex">
+                       <param name="path" value="${wsp.home}/index" />
+               </SearchIndex>
+       </Workspace>
+
+       <!-- Versioning -->
+       <Versioning rootPath="${rep.home}/version">
+               <FileSystem class="org.apache.jackrabbit.core.fs.local.LocalFileSystem">
+                       <param name="path" value="${rep.home}/version" />
+               </FileSystem>
+               <PersistenceManager
+                       class="org.apache.jackrabbit.core.persistence.bundle.BundleFsPersistenceManager" />
+       </Versioning>
+
+       <!-- Indexing -->
+       <SearchIndex class="org.apache.jackrabbit.core.query.lucene.SearchIndex">
+               <param name="path" value="${rep.home}/index" />
+               <param name="extractorPoolSize" value="2" />
+               <param name="supportHighlighting" value="true" />
+       </SearchIndex>
+
+       <!-- Security -->
+       <Security appName="Jackrabbit">
+               <SecurityManager class="org.argeo.security.jackrabbit.ArgeoSecurityManager"
+                       workspaceName="security">
+               </SecurityManager>
+               <AccessManager class="org.argeo.security.jackrabbit.ArgeoAccessManager">
+               </AccessManager>
+               <LoginModule class="org.argeo.security.jackrabbit.ArgeoLoginModule">
+               </LoginModule>
+       </Security>
+</Repository>
\ No newline at end of file
diff --git a/org.argeo.server.jackrabbit/src/org/argeo/jackrabbit/repository-h2.xml b/org.argeo.server.jackrabbit/src/org/argeo/jackrabbit/repository-h2.xml
new file mode 100644 (file)
index 0000000..b6a9252
--- /dev/null
@@ -0,0 +1,77 @@
+<?xml version="1.0"?>
+<!DOCTYPE Repository PUBLIC "-//The Apache Software Foundation//DTD Jackrabbit 1.6//EN"
+                            "http://jackrabbit.apache.org/dtd/repository-2.0.dtd">
+<Repository>
+       <!-- Shared datasource -->
+       <DataSources>
+               <DataSource name="dataSource">
+                       <param name="driver" value="org.h2.Driver" />
+                       <param name="url" value="jdbc:h2:${rep.home}/h2/repository" />
+                       <param name="user" value="sa" />
+                       <param name="password" value="" />
+                       <param name="databaseType" value="h2" />
+                       <param name="maxPoolSize" value="10" />
+               </DataSource>
+       </DataSources>
+
+       <!-- File system and datastore -->
+       <FileSystem class="org.apache.jackrabbit.core.fs.db.DbFileSystem">
+               <param name="dataSourceName" value="dataSource" />
+               <param name="schema" value="default" />
+               <param name="schemaObjectPrefix" value="fs_" />
+       </FileSystem>
+       <DataStore class="org.apache.jackrabbit.core.data.FileDataStore">
+               <param name="path" value="${rep.home}/datastore" />
+       </DataStore>
+
+       <!-- Workspace templates -->
+       <Workspaces rootPath="${rep.home}/workspaces"
+               defaultWorkspace="main" />
+       <Workspace name="${wsp.name}">
+               <FileSystem class="org.apache.jackrabbit.core.fs.db.DbFileSystem">
+                       <param name="dataSourceName" value="dataSource" />
+                       <param name="schema" value="default" />
+                       <param name="schemaObjectPrefix" value="${wsp.name}_fs_" />
+               </FileSystem>
+               <PersistenceManager
+                       class="org.apache.jackrabbit.core.persistence.pool.H2PersistenceManager">
+                       <param name="dataSourceName" value="dataSource" />
+                       <param name="schemaObjectPrefix" value="${wsp.name}_pm_" />
+               </PersistenceManager>
+               <SearchIndex class="org.apache.jackrabbit.core.query.lucene.SearchIndex">
+                       <param name="path" value="${wsp.home}/index" />
+               </SearchIndex>
+       </Workspace>
+
+       <!-- Versioning -->
+       <Versioning rootPath="${rep.home}/version">
+               <FileSystem class="org.apache.jackrabbit.core.fs.db.DbFileSystem">
+                       <param name="dataSourceName" value="dataSource" />
+                       <param name="schema" value="default" />
+                       <param name="schemaObjectPrefix" value="fs_ver_" />
+               </FileSystem>
+               <PersistenceManager
+                       class="org.apache.jackrabbit.core.persistence.pool.H2PersistenceManager">
+                       <param name="dataSourceName" value="dataSource" />
+                       <param name="schemaObjectPrefix" value="pm_ver_" />
+               </PersistenceManager>
+       </Versioning>
+
+       <!-- Indexing -->
+       <SearchIndex class="org.apache.jackrabbit.core.query.lucene.SearchIndex">
+               <param name="path" value="${rep.home}/index" />
+               <param name="extractorPoolSize" value="2" />
+               <param name="supportHighlighting" value="true" />
+       </SearchIndex>
+
+       <!-- Security -->
+       <Security appName="Jackrabbit">
+               <SecurityManager class="org.argeo.security.jackrabbit.ArgeoSecurityManager"
+                       workspaceName="security">
+               </SecurityManager>
+               <AccessManager class="org.argeo.security.jackrabbit.ArgeoAccessManager">
+               </AccessManager>
+               <LoginModule class="org.argeo.security.jackrabbit.ArgeoLoginModule">
+               </LoginModule>
+       </Security>
+</Repository>
\ No newline at end of file
diff --git a/org.argeo.server.jackrabbit/src/org/argeo/jackrabbit/repository-memory.xml b/org.argeo.server.jackrabbit/src/org/argeo/jackrabbit/repository-memory.xml
new file mode 100644 (file)
index 0000000..e552c33
--- /dev/null
@@ -0,0 +1,69 @@
+<?xml version="1.0"?>
+<!--
+
+    Copyright (C) 2007-2012 Argeo GmbH
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+            http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+
+-->
+<!DOCTYPE Repository PUBLIC "-//The Apache Software Foundation//DTD Jackrabbit 1.6//EN"
+                            "http://jackrabbit.apache.org/dtd/repository-2.0.dtd">
+<Repository>
+       <!-- File system and datastore -->
+       <FileSystem class="org.apache.jackrabbit.core.fs.mem.MemoryFileSystem" />
+
+       <!-- Workspace templates -->
+       <Workspaces rootPath="${rep.home}/workspaces"
+               defaultWorkspace="main" configRootPath="/workspaces" />
+       <Workspace name="${wsp.name}">
+               <FileSystem class="org.apache.jackrabbit.core.fs.mem.MemoryFileSystem" />
+               <PersistenceManager
+                       class="org.apache.jackrabbit.core.persistence.bundle.BundleFsPersistenceManager">
+                       <param name="blobFSBlockSize" value="1" />
+               </PersistenceManager>
+               <SearchIndex class="org.apache.jackrabbit.core.query.lucene.SearchIndex">
+                       <param name="path" value="${rep.home}/repository/index" />
+                       <param name="directoryManagerClass"
+                               value="org.apache.jackrabbit.core.query.lucene.directory.RAMDirectoryManager" />
+                       <FileSystem class="org.apache.jackrabbit.core.fs.mem.MemoryFileSystem" />
+               </SearchIndex>
+       </Workspace>
+
+       <!-- Versioning -->
+       <Versioning rootPath="${rep.home}/version">
+               <FileSystem class="org.apache.jackrabbit.core.fs.mem.MemoryFileSystem" />
+               <PersistenceManager
+                       class="org.apache.jackrabbit.core.persistence.bundle.BundleFsPersistenceManager">
+                       <param name="blobFSBlockSize" value="1" />
+               </PersistenceManager>
+       </Versioning>
+
+       <!-- Indexing -->
+       <SearchIndex class="org.apache.jackrabbit.core.query.lucene.SearchIndex">
+               <param name="path" value="${rep.home}/repository/index" />
+               <param name="directoryManagerClass"
+                       value="org.apache.jackrabbit.core.query.lucene.directory.RAMDirectoryManager" />
+               <FileSystem class="org.apache.jackrabbit.core.fs.mem.MemoryFileSystem" />
+       </SearchIndex>
+
+       <!-- Security -->
+       <Security appName="Jackrabbit">
+               <SecurityManager class="org.argeo.security.jackrabbit.ArgeoSecurityManager"
+                       workspaceName="security">
+               </SecurityManager>
+               <AccessManager class="org.argeo.security.jackrabbit.ArgeoAccessManager">
+               </AccessManager>
+               <LoginModule class="org.argeo.security.jackrabbit.ArgeoLoginModule">
+               </LoginModule>
+       </Security>
+</Repository>
\ No newline at end of file
diff --git a/org.argeo.server.rap.webapp/bnd.bnd b/org.argeo.server.rap.webapp/bnd.bnd
new file mode 100644 (file)
index 0000000..954f2d3
--- /dev/null
@@ -0,0 +1,24 @@
+Web-ContextPath: ui
+Import-Package: org.springframework.beans.factory.config,\             
+org.eclipse.equinox.http.servlet,\
+org.springframework.osgi.web.context.support,\
+org.springframework.security,\
+org.springframework.security.context,\
+org.springframework.security.intercept.web,\
+org.springframework.security.providers.anonymous,\
+org.springframework.security.ui,\
+org.springframework.security.ui.basicauth,\
+org.springframework.security.ui.logout,\
+org.springframework.security.ui.rememberme,\
+org.springframework.security.ui.webapp,\
+org.springframework.security.ui.preauth.x509,\
+org.springframework.security.userdetails,\
+org.springframework.security.util,\
+org.springframework.security.vote,\
+org.springframework.security.wrapper,\
+org.springframework.web.context,\
+org.springframework.web.filter,\
+org.springframework.web.servlet,\
+org.springframework.web.servlet.handler,\
+org.springframework.web.servlet.mvc,\
+*
\ No newline at end of file
index abf636f5ee388b678dc95d1acc97431c2a995ca5..8c61d3f0be8bce533a2335a6b4cc4b23984b10df 100644 (file)
@@ -9,46 +9,4 @@
        <artifactId>org.argeo.server.rap.webapp</artifactId>
        <name>Commons Server RAP Webapp</name>
        <description>Integrates into OSGi HTTP registry</description>
-       <build>
-               <plugins>
-                       <plugin>
-                               <groupId>org.apache.felix</groupId>
-                               <artifactId>maven-bundle-plugin</artifactId>
-                               <configuration>
-                                       <instructions>
-                                               <Web-ContextPath>ui</Web-ContextPath>
-                                               <Import-Package>
-                                                       *,
-
-                                                       org.springframework.beans.factory.config,
-                                                       
-                                                       org.eclipse.equinox.http.servlet,
-                                                       org.springframework.osgi.web.context.support,
-                                                       org.springframework.security,
-                                                       org.springframework.security.context,
-                                                       org.springframework.security.intercept.web,
-                                                       org.springframework.security.providers.anonymous,
-                                                       org.springframework.security.ui,
-                                                       org.springframework.security.ui.basicauth,
-                                                       org.springframework.security.ui.logout,
-                                                       org.springframework.security.ui.rememberme,
-                                                       org.springframework.security.ui.webapp,
-                                                       org.springframework.security.ui.preauth.x509,
-                                                       org.springframework.security.userdetails,
-                                                       org.springframework.security.util,
-                                                       org.springframework.security.vote,
-                                                       org.springframework.security.wrapper,
-                                                       org.springframework.web.context,
-                                                       org.springframework.web.filter,
-                                                       org.springframework.web.servlet,
-                                                       org.springframework.web.servlet.handler,
-                                                       org.springframework.web.servlet.mvc,
-                                                       
-                                                       
-                                               </Import-Package>
-                                       </instructions>
-                               </configuration>
-                       </plugin>
-               </plugins>
-       </build>
 </project>
\ No newline at end of file