Improve RAP security
authorMathieu Baudier <mbaudier@argeo.org>
Mon, 21 Mar 2011 22:29:36 +0000 (22:29 +0000)
committerMathieu Baudier <mbaudier@argeo.org>
Mon, 21 Mar 2011 22:29:36 +0000 (22:29 +0000)
git-svn-id: https://svn.argeo.org/commons/trunk@4334 4cfe0d0a-d680-48aa-b62c-e0a02a3f76cc

28 files changed:
demo/log4j.properties
security/modules/org.argeo.security.dao.ldap/META-INF/spring/ldap-jcr.xml
security/modules/org.argeo.security.dao.ldap/META-INF/spring/ldap-osgi.xml
security/plugins/org.argeo.security.equinox/src/main/java/org/argeo/security/equinox/SpringLoginModule.java
security/plugins/org.argeo.security.ui.admin/META-INF/spring/editors.xml
security/plugins/org.argeo.security.ui.admin/META-INF/spring/osgi.xml
security/plugins/org.argeo.security.ui.admin/META-INF/spring/views.xml
security/plugins/org.argeo.security.ui.admin/plugin.xml
security/plugins/org.argeo.security.ui.admin/src/main/java/org/argeo/security/ui/admin/commands/AddRole.java
security/plugins/org.argeo.security.ui.admin/src/main/java/org/argeo/security/ui/admin/editors/ArgeoUserEditor.java
security/plugins/org.argeo.security.ui.admin/src/main/java/org/argeo/security/ui/admin/editors/ArgeoUserEditorInput.java
security/plugins/org.argeo.security.ui.admin/src/main/java/org/argeo/security/ui/admin/editors/DefaultUserMainPage.java
security/plugins/org.argeo.security.ui.admin/src/main/java/org/argeo/security/ui/admin/editors/UserRolesPage.java [new file with mode: 0644]
security/plugins/org.argeo.security.ui.admin/src/main/java/org/argeo/security/ui/admin/views/UsersView.java
security/plugins/org.argeo.security.ui.rap/src/main/java/org/argeo/security/ui/rap/SecureEntryPoint.java
security/plugins/org.argeo.security.ui/plugin.xml
security/plugins/org.argeo.security.ui/src/main/java/org/argeo/security/ui/internal/CurrentUser.java
security/runtime/org.argeo.security.core/src/main/java/org/argeo/security/UserAdminService.java
security/runtime/org.argeo.security.core/src/main/java/org/argeo/security/core/ArgeoUserDetails.java
security/runtime/org.argeo.security.core/src/main/java/org/argeo/security/core/DefaultUserAdminService.java
security/runtime/org.argeo.security.core/src/main/java/org/argeo/security/core/KeyBasedSystemExecutionService.java
security/runtime/org.argeo.security.core/src/main/java/org/argeo/security/jcr/JcrUserDetails.java
security/runtime/org.argeo.security.jackrabbit/src/main/java/org/argeo/security/jackrabbit/ArgeoLoginModule.java
security/runtime/org.argeo.security.jackrabbit/src/main/java/org/argeo/security/jackrabbit/ArgeoSecurityManager.java
security/runtime/org.argeo.security.ldap/src/main/java/org/argeo/security/ldap/jcr/JcrUserDetailsContextMapper.java
server/runtime/org.argeo.server.jackrabbit/src/main/java/org/argeo/jackrabbit/JackrabbitContainer.java
server/runtime/org.argeo.server.jcr/src/main/java/org/argeo/jcr/ArgeoNames.java
server/runtime/org.argeo.server.jcr/src/main/java/org/argeo/jcr/ThreadBoundJcrSessionFactory.java

index 1e5895edf0c2ba1eaf06d09dd836a03853ddacea..cd83759a461f50919b7c4959faf40e32635e9882 100644 (file)
@@ -4,7 +4,7 @@ log4j.rootLogger=WARN, console
 log4j.logger.org.argeo=DEBUG
 log4j.logger.org.argeo.jackrabbit.remote.ExtendedDispatcherServlet=WARN
 
-log4j.logger.org.springframework.security=WARN
+log4j.logger.org.springframework.security=DEBUG
 
 log4j.logger.org.apache.catalina=INFO
 log4j.logger.org.apache.coyote=INFO
index 794ac0195b6246da04eca5de9dfb0d3dcfb6b21b..b1dc9a9e16e390831436a6d48c5ce5e35dbad545 100644 (file)
                        </list>
                </property>
                <property name="systemExecutor" ref="systemExecutionService" />
+               <property name="passwordEncoder" ref="passwordEncoder" />
+               <property name="session" ref="nodeSession" />
                <property name="propertyToAttributes">
                        <map>
                                <entry value="cn">
                                        <key>
-                                               <util:constant static-field="org.argeo.jcr.ArgeoNames.ARGEO_DISPLAY_NAME" />
+                                               <util:constant static-field="javax.jcr.Property.JCR_TITLE" />
+                                       </key>
+                               </entry>
+                               <entry value="description">
+                                       <key>
+                                               <util:constant static-field="javax.jcr.Property.JCR_DESCRIPTION" />
                                        </key>
                                </entry>
                                <entry value="givenName">
index 67ad8981705ae694a12392ef173ae224b5aa2438..8deaeacdea6af41542c282890364d6d7109b1934 100644 (file)
@@ -7,13 +7,15 @@
        http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">\r
 \r
        <!-- REFERENCES -->\r
-       <list id="userNatureMappers" interface="org.argeo.security.ldap.UserNatureMapper"\r
-               cardinality="0..N" />\r
-       <reference id="repositoryFactory" interface="javax.jcr.RepositoryFactory"\r
-               cardinality="0..1">\r
-               <listener ref="jcrUserDetailsContextMapper" bind-method="register"\r
-                       unbind-method="unregister" />\r
-       </reference>\r
+<!--   <list id="userNatureMappers" interface="org.argeo.security.ldap.UserNatureMapper" -->\r
+<!--           cardinality="0..N" /> -->\r
+<!--   <reference id="repositoryFactory" interface="javax.jcr.RepositoryFactory" -->\r
+<!--           cardinality="0..1"> -->\r
+<!--           <listener ref="jcrUserDetailsContextMapper" bind-method="register" -->\r
+<!--                   unbind-method="unregister" /> -->\r
+<!--   </reference> -->\r
+       <reference id="nodeSession" interface="javax.jcr.Session"\r
+               filter="(argeo.jcr.repository.alias=node)" />\r
        <reference id="systemExecutionService" interface="org.argeo.security.SystemExecutionService" />\r
 \r
        <!-- SERVICES -->\r
@@ -28,4 +30,7 @@
        <service ref="userDetailsManager"\r
                interface="org.springframework.security.userdetails.UserDetailsService"\r
                context-class-loader="service-provider" />\r
+       <service ref="userDetailsManager"\r
+               interface="org.springframework.security.userdetails.UserDetailsManager"\r
+               context-class-loader="service-provider" />\r
 </beans:beans>
\ No newline at end of file
index c357a9ea7f1ae44e0e756bacfd2f15125486748e..90e8b3decedae4932ed7b6d0ba9d20d05c3c313c 100644 (file)
@@ -1,6 +1,7 @@
 package org.argeo.security.equinox;
 
 import java.util.Map;
+import java.util.concurrent.Executor;
 
 import javax.security.auth.Subject;
 import javax.security.auth.callback.Callback;
@@ -20,6 +21,7 @@ import org.springframework.security.providers.jaas.SecurityContextLoginModule;
 /** Login module which caches one subject per thread. */
 public class SpringLoginModule extends SecurityContextLoginModule {
        private AuthenticationManager authenticationManager;
+       private Executor systemExecutor;
 
        private CallbackHandler callbackHandler;
 
@@ -88,6 +90,7 @@ public class SpringLoginModule extends SecurityContextLoginModule {
                                username, password, url, workspace);
 
                try {
+                       
                        Authentication authentication = authenticationManager
                                        .authenticate(credentials);
                        registerAuthentication(authentication);
@@ -127,6 +130,10 @@ public class SpringLoginModule extends SecurityContextLoginModule {
                this.authenticationManager = authenticationManager;
        }
 
+       public void setSystemExecutor(Executor systemExecutor) {
+               this.systemExecutor = systemExecutor;
+       }
+
        // protected Subject getSubject() {
        // return subject.get();
        // }
index 84399c26ec845744a4126a5cd64445634dc79e0d..c1eb9ea61383cdbe242aedd78aa374283b3ad842 100644 (file)
@@ -8,5 +8,6 @@
        <bean id="adminArgeoUserEditor" class="org.argeo.security.ui.admin.editors.ArgeoUserEditor"
                scope="prototype">
                <property name="userAdminService" ref="userAdminService" />
+               <property name="userDetailsManager" ref="userDetailsManager" />
        </bean>
 </beans>
index f77b5a029a7d68cdf0ed77771b1cad82ccc12a53..690dd16a971b2f467f5d9750945aadf296664da6 100644 (file)
@@ -8,5 +8,10 @@
        http://www.springframework.org/schema/beans/spring-beans-2.5.xsd"\r
        osgi:default-timeout="30000">\r
 \r
+       <reference id="jcrSession" interface="javax.jcr.Session"\r
+               filter="(argeo.jcr.repository.alias=node)" />\r
        <reference id="userAdminService" interface="org.argeo.security.UserAdminService" />\r
+       <reference id="currentUserService" interface="org.argeo.security.CurrentUserService" />\r
+       <reference id="userDetailsManager"\r
+               interface="org.springframework.security.userdetails.UserDetailsManager" />\r
 </beans:beans>
\ No newline at end of file
index 8cf9fd68c80358d115ba7cc1cc175243286523bf..cc5fbb57d061fad48219ada8db2930f5cd439447 100644 (file)
@@ -6,7 +6,8 @@
 
        <bean id="adminUsersView" class="org.argeo.security.ui.admin.views.UsersView"
                scope="prototype">
-               <property name="userAdminService" ref="userAdminService" />
+<!--           <property name="userAdminService" ref="userAdminService" /> -->
+               <property name="session" ref="jcrSession" />
        </bean>
        <bean id="adminRolesView" class="org.argeo.security.ui.admin.views.RolesView"
                scope="prototype">
index d5bc7d18d814282bda0e7671f3c8f19b8fc039c8..f6c16439138ea97ecf5855699077a50753fcc18e 100644 (file)
@@ -7,7 +7,7 @@
             class="org.argeo.security.ui.admin.SecurityAdminPerspective"
             icon="icons/security.gif"
             id="org.argeo.security.ui.admin.adminSecurityPerspective"
-            name="Security">
+            name="Security Administration">
       </perspective>
    </extension>
    <extension
@@ -67,7 +67,7 @@
      <extension
          point="org.eclipse.ui.menus">
        <menuContribution
-            locationURI="toolbar:org.argeo.security.ui.admin.rolesView">
+            locationURI="toolbar:org.argeo.security.ui.admin.adminRolesView">
             <command
                   commandId="org.argeo.security.ui.admin.addRole"
                   icon="icons/add.gif"
@@ -76,7 +76,7 @@
             </command>
         </menuContribution>
        <menuContribution
-            locationURI="toolbar:org.argeo.security.ui.admin.usersView">
+            locationURI="toolbar:org.argeo.security.ui.admin.adminUsersView">
             <command
                   commandId="org.argeo.security.ui.admin.newArgeoUserEditor"
                   icon="icons/add.gif"
                    </with>
                  </enabledWhen>
         </activity>
+        <!-- TODO: find a way to exclude evrything -->
         <activityPatternBinding
               activityId="org.argeo.security.ui.admin.adminActivity"
               isEqualityPattern="true"
-              pattern="org.argeo.security.ui.admin/.*">
+              pattern="org.argeo.security.ui.admin/org.argeo.security.ui.admin.adminSecurityPerspective">
         </activityPatternBinding>
      </extension>
  </plugin>
index 047c167e07f34590e8f67c499de989276e712eea..a036d12a34ded0c7dce300ca3102a1a5fad3851f 100644 (file)
@@ -2,11 +2,15 @@ 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;
+import org.eclipse.ui.internal.EditorReference;
 
 /** Add a new role. */
 public class AddRole extends AbstractHandler {
@@ -30,6 +34,17 @@ public class AddRole extends AbstractHandler {
                        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;
        }
 
index 9b82e8783985325f4dfd3979e52125d035308a47..a0e4dfc82332faf44b9dfbc04e909e44b02fae4b 100644 (file)
@@ -1,44 +1,62 @@
 package org.argeo.security.ui.admin.editors;
 
+import javax.jcr.Node;
+
 import org.argeo.ArgeoException;
+import org.argeo.jcr.ArgeoNames;
 import org.argeo.security.ArgeoUser;
 import org.argeo.security.SimpleArgeoUser;
 import org.argeo.security.UserAdminService;
+import org.argeo.security.jcr.JcrUserDetails;
 import org.argeo.security.nature.SimpleUserNature;
+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.userdetails.UserDetailsManager;
 
 /** Editor for an Argeo user. */
 public class ArgeoUserEditor extends FormEditor {
        public final static String ID = "org.argeo.security.ui.admin.adminArgeoUserEditor";
 
        private ArgeoUser user;
+       private JcrUserDetails userDetails;
+       private Node userHome;
        private UserAdminService userAdminService;
+       private UserDetailsManager userDetailsManager;
 
        public void init(IEditorSite site, IEditorInput input)
                        throws PartInitException {
                super.init(site, input);
+               userHome = ((ArgeoUserEditorInput) getEditorInput()).getUserHome();
                String username = ((ArgeoUserEditorInput) getEditorInput())
                                .getUsername();
+
+               userDetails = (JcrUserDetails) userDetailsManager
+                               .loadUserByUsername(username);
+
                if (username == null) {// new
                        user = new SimpleArgeoUser();
                        user.getUserNatures().put(SimpleUserNature.TYPE,
                                        new SimpleUserNature());
                } else
                        user = userAdminService.getUser(username);
+
                this.setPartProperty("name", username != null ? username : "<new user>");
                setPartName(username != null ? username : "<new user>");
        }
 
        protected void addPages() {
                try {
-                       addPage(new DefaultUserMainPage(this, userAdminService, user));
-
-               } catch (PartInitException e) {
-                       throw new ArgeoException("Not able to add page ", e);
+                       addPage(new DefaultUserMainPage(this,
+                                       userHome.getNode(ArgeoNames.ARGEO_USER_PROFILE)));
+                       addPage(new UserRolesPage(this, userDetails, userAdminService));
+               } catch (Exception e) {
+                       throw new ArgeoException("Cannot add pages", e);
                }
        }
 
@@ -46,15 +64,39 @@ public class ArgeoUserEditor extends FormEditor {
        public void doSave(IProgressMonitor monitor) {
                // list pages
                // TODO: make it more generic
-               findPage(DefaultUserMainPage.ID).doSave(monitor);
+               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);
+               }
 
-               if (userAdminService.userExists(user.getUsername()))
-                       userAdminService.updateUser(user);
-               else {
-                       userAdminService.newUser(user);
-                       setPartName(user.getUsername());
+               UserRolesPage userRolesPage = (UserRolesPage) findPage(UserRolesPage.ID);
+               if (userRolesPage.isDirty()) {
+                       userRolesPage.doSave(monitor);
+                       userDetails = userDetails.cloneWithNewRoles(userRolesPage
+                                       .getRoles());
                }
+
+               userDetailsManager.updateUser(userDetails);
+
+               // if (userAdminService.userExists(user.getUsername()))
+               // userAdminService.updateUser(user);
+               // else {
+               // userAdminService.newUser(user);
+               // setPartName(user.getUsername());
+               // }
                firePropertyChange(PROP_DIRTY);
+
+               userRolesPage.setUserDetails(userDetails);
+
+               // refresh users view
+               IWorkbench iw = SecurityAdminPlugin.getDefault().getWorkbench();
+               UsersView usersView = (UsersView) iw.getActiveWorkbenchWindow()
+                               .getActivePage().findView(UsersView.ID);
+               usersView.refresh();
        }
 
        @Override
@@ -66,7 +108,17 @@ public class ArgeoUserEditor extends FormEditor {
                return false;
        }
 
+       public void refresh() {
+               UserRolesPage userRolesPage = (UserRolesPage) findPage(UserRolesPage.ID);
+               userRolesPage.refresh();
+       }
+
        public void setUserAdminService(UserAdminService userAdminService) {
                this.userAdminService = userAdminService;
        }
+
+       public void setUserDetailsManager(UserDetailsManager userDetailsManager) {
+               this.userDetailsManager = userDetailsManager;
+       }
+
 }
index 8812ee36abf126928faac562b7cb8f9e8d1c3586..51aeeef80f314f1937b0d0717b46012ad43f6a5d 100644 (file)
@@ -1,5 +1,12 @@
 package org.argeo.security.ui.admin.editors;
 
+import javax.jcr.Node;
+import javax.jcr.PathNotFoundException;
+import javax.jcr.RepositoryException;
+import javax.jcr.ValueFormatException;
+
+import org.argeo.ArgeoException;
+import org.argeo.jcr.ArgeoNames;
 import org.eclipse.jface.resource.ImageDescriptor;
 import org.eclipse.ui.IEditorInput;
 import org.eclipse.ui.IPersistableElement;
@@ -7,9 +14,23 @@ import org.eclipse.ui.IPersistableElement;
 /** Editor input for an Argeo user. */
 public class ArgeoUserEditorInput implements IEditorInput {
        private final String username;
+       private final Node userHome;
 
+       @Deprecated
        public ArgeoUserEditorInput(String username) {
                this.username = username;
+               this.userHome = null;
+       }
+
+       public ArgeoUserEditorInput(Node userHome) {
+               try {
+                       this.username = userHome.getProperty(ArgeoNames.ARGEO_USER_ID)
+                                       .getString();
+                       this.userHome = userHome;
+               } catch (RepositoryException e) {
+                       throw new ArgeoException("Cannot initialize editor input for "
+                                       + userHome, e);
+               }
        }
 
        public Object getAdapter(@SuppressWarnings("rawtypes") Class adapter) {
@@ -48,4 +69,8 @@ public class ArgeoUserEditorInput implements IEditorInput {
                return username;
        }
 
+       public Node getUserHome() {
+               return userHome;
+       }
+
 }
index ee36b573125f1d7246de9780d48b19e594b0438c..cfaf6e4fb6aa47c0d7b571f4ffa53f4cb2b46883 100644 (file)
 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.security.ArgeoUser;
-import org.argeo.security.SimpleArgeoUser;
-import org.argeo.security.UserAdminService;
-import org.argeo.security.nature.SimpleUserNature;
-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.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.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.Table;
-import org.eclipse.swt.widgets.TableColumn;
+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.ColumnLayout;
 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 {@link ArgeoUser} (username and
- * roles) as well as the properties of the {@link SimpleUserNature}.
+ * Display/edit the properties common to all Argeo users
  */
-public class DefaultUserMainPage extends FormPage {
+public class DefaultUserMainPage extends FormPage implements ArgeoNames {
        final static String ID = "argeoUserEditor.mainPage";
 
        private final static Log log = LogFactory.getLog(DefaultUserMainPage.class);
-       private final static Image ROLE_CHECKED = SecurityAdminPlugin
-                       .getImageDescriptor("icons/security.gif").createImage();
+       private Node userProfile;
 
-       private ArgeoUser user;
-       private SimpleUserNature simpleNature;
-       private String simpleNatureType;
-       private UserAdminService securityService;
+       private char[] newPassword;
 
-       public DefaultUserMainPage(FormEditor editor,
-                       UserAdminService securityService, ArgeoUser user) {
+       public DefaultUserMainPage(FormEditor editor, Node userProfile) {
                super(editor, ID, "Main");
-               this.securityService = securityService;
-               this.user = user;
-               this.simpleNature = SimpleUserNature.findSimpleUserNature(user,
-                               simpleNatureType);
+               this.userProfile = userProfile;
        }
 
        protected void createFormContent(final IManagedForm mf) {
-               ScrolledForm form = mf.getForm();
-               form.setText(simpleNature.getFirstName() + " "
-                               + simpleNature.getLastName());
-               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);
-
-               createGeneralPart(form.getBody());
-               createRolesPart(form.getBody());
-               createPassworPart(form.getBody());
+               try {
+                       ScrolledForm form = mf.getForm();
+                       form.setText(userProfile.getProperty(ARGEO_FIRST_NAME).getString()
+                                       + " "
+                                       + userProfile.getProperty(ARGEO_LAST_NAME).getString());
+                       GridLayout mainLayout = new GridLayout(1, true);
+                       // 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);
+
+                       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) {
+       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();
-               layout.marginWidth = layout.marginHeight = 0;
-               layout.numColumns = 2;
+               GridLayout layout = new GridLayout(2, false);
+               body.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
                body.setLayout(layout);
 
                // add widgets (view)
-               final Text username;
-               if (user.getUsername() != null) {
-                       tk.createLabel(body, "Username");
-                       tk.createLabel(body, user.getUsername());
-                       username = null;
-               } else {
-                       username = createLT(body, "Username", "");
-               }
+               // final Text username;
+               // if (user.getUsername() != null) {
+               // tk.createLabel(body, "Username");
+               // tk.createLabel(body, user.getUsername());
+               // username = null;
+               // } else {
+               // username = createLT(body, "Username", "");
+               // }
                final Text firstName = createLT(body, "First name",
-                               simpleNature.getFirstName());
+                               userProfile.getProperty(ARGEO_FIRST_NAME));
                final Text lastName = createLT(body, "Last name",
-                               simpleNature.getLastName());
-               final Text email = createLT(body, "Email", simpleNature.getEmail());
+                               userProfile.getProperty(ARGEO_LAST_NAME));
+               final Text email = createLT(body, "Email",
+                               userProfile.getProperty(ARGEO_PRIMARY_EMAIL));
                final Text description = createLT(body, "Description",
-                               simpleNature.getDescription());
+                               userProfile.getProperty(Property.JCR_DESCRIPTION));
 
                // create form part (controller)
                AbstractFormPart part = new SectionPart(section) {
                        public void commit(boolean onSave) {
-                               if (username != null) {
-                                       ((SimpleArgeoUser) user).setUsername(username.getText());
-                                       username.setEditable(false);
-                                       username.setEnabled(false);
+                               // if (username != null) {
+                               // ((SimpleArgeoUser) user).setUsername(username.getText());
+                               // username.setEditable(false);
+                               // username.setEnabled(false);
+                               // }
+                               // simpleNature.setFirstName(firstName.getText());
+                               // simpleNature.setLastName(lastName.getText());
+                               // simpleNature.setEmail(email.getText());
+                               // simpleNature.setDescription(description.getText());
+                               try {
+                                       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());
+                                       super.commit(onSave);
+                                       if (log.isTraceEnabled())
+                                               log.trace("General part committed");
+                               } catch (RepositoryException e) {
+                                       throw new ArgeoException("Cannot commit", e);
                                }
-                               simpleNature.setFirstName(firstName.getText());
-                               simpleNature.setLastName(lastName.getText());
-                               simpleNature.setEmail(email.getText());
-                               simpleNature.setDescription(description.getText());
-                               super.commit(onSave);
-                               if (log.isTraceEnabled())
-                                       log.trace("General part committed");
                        }
                };
-               if (username != null)
-                       username.addModifyListener(new FormPartML(part));
+               // if (username != null)
+               // username.addModifyListener(new FormPartML(part));
                firstName.addModifyListener(new FormPartML(part));
                lastName.addModifyListener(new FormPartML(part));
                email.addModifyListener(new FormPartML(part));
@@ -137,13 +139,13 @@ public class DefaultUserMainPage extends FormPage {
        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();
-               layout.marginWidth = layout.marginHeight = 0;
-               layout.numColumns = 2;
+               GridLayout layout = new GridLayout(2, false);
+               body.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
                body.setLayout(layout);
 
                // add widgets (view)
@@ -151,119 +153,54 @@ public class DefaultUserMainPage extends FormPage {
                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("")
-                                               && password1.getText().equals(password2.getText())) {
-                                       ((SimpleArgeoUser) user).setPassword(password1.getText());
+                                               || !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");
+                                       }
                                }
-                               super.commit(onSave);
-                               if (log.isTraceEnabled())
-                                       log.trace("Password part committed");
                        }
+
                };
                password1.addModifyListener(new FormPartML(part));
                password2.addModifyListener(new FormPartML(part));
                getManagedForm().addPart(part);
        }
 
-       /** Creates the role section */
-       protected void createRolesPart(Composite parent) {
-               FormToolkit tk = getManagedForm().getToolkit();
-               Section section = tk.createSection(parent, Section.DESCRIPTION
-                               | Section.TITLE_BAR);
-               section.setText("Roles");
-               section.setDescription("Roles define "
-                               + "the authorizations for this user.");
-               Table table = new Table(section, SWT.MULTI | SWT.H_SCROLL
-                               | SWT.V_SCROLL);
-               section.setClient(table);
-
-               AbstractFormPart part = new SectionPart(section) {
-                       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);
-               TableViewer 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) {
-                               String role = element.toString();
-                               if (user.getRoles().contains(role)) {
-                                       return ROLE_CHECKED;
-                               } else {
-                                       return null;
-                               }
-                       }
-               });
-               column.setEditingSupport(new RoleEditingSupport(viewer, part));
-
-               // role column
-               column = createTableViewerColumn(viewer, "Role", 200);
-               column.setLabelProvider(new ColumnLabelProvider() {
-                       public String getText(Object element) {
-                               return element.toString();
-                       }
-
-                       public Image getImage(Object element) {
-                               return null;
-                       }
-               });
-               viewer.setContentProvider(new RolesContentProvider());
-               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;
-
-       }
-
        /** Creates label and text. */
        protected Text createLT(Composite body, String label, String value) {
                FormToolkit toolkit = getManagedForm().getToolkit();
-               toolkit.createLabel(body, label);
+               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.FILL, true, true));
+               text.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));
                return text;
        }
 
+       protected Text createLT(Composite body, String label, Property value)
+                       throws RepositoryException {
+               return createLT(body, label, value.getString());
+       }
+
        /** Creates label and password. */
        protected Text createLP(Composite body, String label, String value) {
                FormToolkit toolkit = getManagedForm().getToolkit();
-               toolkit.createLabel(body, label);
+               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.FILL, true, true));
+               text.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));
                return text;
        }
 
-       public void setSimpleNatureType(String simpleNatureType) {
-               this.simpleNatureType = simpleNatureType;
-       }
-
        private class FormPartML implements ModifyListener {
                private AbstractFormPart formPart;
 
@@ -277,61 +214,16 @@ public class DefaultUserMainPage extends FormPage {
 
        }
 
-       private class RolesContentProvider implements IStructuredContentProvider {
-               public Object[] getElements(Object inputElement) {
-                       return securityService.listEditableRoles().toArray();
-               }
-
-               public void dispose() {
-               }
-
-               public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
-               }
+       public String getNewPassword() {
+               if (newPassword != null)
+                       return new String(newPassword);
+               else
+                       return null;
        }
 
-       /** 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 user.getRoles().contains(role);
-
-               }
-
-               @Override
-               protected void setValue(Object element, Object value) {
-                       Boolean inRole = (Boolean) value;
-                       String role = element.toString();
-                       if (inRole && !user.getRoles().contains(role)) {
-                               user.getRoles().add(role);
-                               formPart.markDirty();
-                       } else if (!inRole && user.getRoles().contains(role)) {
-                               user.getRoles().remove(role);
-                               formPart.markDirty();
-                       }
-                       viewer.refresh();
-               }
+       public void resetNewPassword() {
+               if (newPassword != null)
+                       Arrays.fill(newPassword, 'x');
+               newPassword = null;
        }
-
 }
diff --git a/security/plugins/org.argeo.security.ui.admin/src/main/java/org/argeo/security/ui/admin/editors/UserRolesPage.java b/security/plugins/org.argeo.security.ui.admin/src/main/java/org/argeo/security/ui/admin/editors/UserRolesPage.java
new file mode 100644 (file)
index 0000000..c593106
--- /dev/null
@@ -0,0 +1,210 @@
+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();
+               }
+       }
+
+}
index df909b6c761b3b020e047d39b04cf2aa983929c9..af3a886efb950c58f91b31958cc15da068e2e96b 100644 (file)
@@ -1,13 +1,25 @@
 package org.argeo.security.ui.admin.views;
 
 import java.util.ArrayList;
+import java.util.List;
+
+import javax.jcr.Node;
+import javax.jcr.NodeIterator;
+import javax.jcr.RepositoryException;
+import javax.jcr.Session;
+import javax.jcr.observation.EventIterator;
+import javax.jcr.observation.EventListener;
+import javax.jcr.query.Query;
 
 import org.argeo.ArgeoException;
+import org.argeo.eclipse.ui.dialogs.Error;
+import org.argeo.jcr.ArgeoNames;
+import org.argeo.jcr.ArgeoTypes;
 import org.argeo.security.ArgeoUser;
-import org.argeo.security.UserAdminService;
-import org.argeo.security.nature.SimpleUserNature;
 import org.argeo.security.ui.admin.SecurityAdminPlugin;
 import org.argeo.security.ui.admin.commands.OpenArgeoUserEditor;
+import org.argeo.security.ui.admin.editors.ArgeoUserEditor;
+import org.argeo.security.ui.admin.editors.ArgeoUserEditorInput;
 import org.eclipse.core.commands.Command;
 import org.eclipse.core.commands.IParameter;
 import org.eclipse.core.commands.Parameterization;
@@ -27,18 +39,18 @@ import org.eclipse.swt.widgets.Table;
 import org.eclipse.swt.widgets.TableColumn;
 import org.eclipse.ui.IWorkbench;
 import org.eclipse.ui.IWorkbenchWindow;
+import org.eclipse.ui.PartInitException;
 import org.eclipse.ui.commands.ICommandService;
 import org.eclipse.ui.handlers.IHandlerService;
 import org.eclipse.ui.part.ViewPart;
 
 /** List all users. */
-public class UsersView extends ViewPart {
+public class UsersView extends ViewPart implements ArgeoNames, ArgeoTypes,
+               EventListener {
        public final static String ID = "org.argeo.security.ui.admin.adminUsersView";
 
        private TableViewer viewer;
-       private UserAdminService userAdminService;
-
-       private String simpleNatureType = null;
+       private Session session;
 
        @Override
        public void createPartControl(Composite parent) {
@@ -73,22 +85,39 @@ public class UsersView extends ViewPart {
                viewer.getTable().setFocus();
        }
 
-       public void setUserAdminService(UserAdminService userAdminService) {
-               this.userAdminService = userAdminService;
+       public void setSession(Session session) {
+               this.session = session;
        }
 
-       public void setSimpleNatureType(String simpleNatureType) {
-               this.simpleNatureType = simpleNatureType;
+       public void refresh() {
+               viewer.refresh();
        }
 
-       public void refresh() {
+       @Override
+       public void onEvent(EventIterator events) {
                viewer.refresh();
        }
 
        private class UsersContentProvider implements IStructuredContentProvider {
 
                public Object[] getElements(Object inputElement) {
-                       return userAdminService.listUsers().toArray();
+                       try {
+                               Query query = session
+                                               .getWorkspace()
+                                               .getQueryManager()
+                                               .createQuery(
+                                                               "select [" + ARGEO_USER_PROFILE + "] from ["
+                                                                               + ARGEO_USER_HOME + "]", Query.JCR_SQL2);
+                               NodeIterator nit = query.execute().getNodes();
+                               List<Node> userProfiles = new ArrayList<Node>();
+                               while (nit.hasNext()) {
+                                       userProfiles.add(nit.nextNode());
+                               }
+                               return userProfiles.toArray();
+                       } catch (RepositoryException e) {
+                               throw new ArgeoException("Cannot list users", e);
+                       }
+                       // return userAdminService.listUsers().toArray();
                }
 
                public void dispose() {
@@ -102,26 +131,52 @@ public class UsersView extends ViewPart {
        private class UsersLabelProvider extends LabelProvider implements
                        ITableLabelProvider {
                public String getColumnText(Object element, int columnIndex) {
-                       // String currentUsername = CurrentUser.getUsername();
-                       String currentUsername = "";
-                       ArgeoUser user = (ArgeoUser) element;
-                       SimpleUserNature simpleNature = SimpleUserNature
-                                       .findSimpleUserNature(user, simpleNatureType);
-                       switch (columnIndex) {
-                       case 0:
-                               String userName = user.getUsername();
-                               if (userName.equals(currentUsername))
-                                       userName = userName + "*";
-                               return userName;
-                       case 1:
-                               return simpleNature.getFirstName();
-                       case 2:
-                               return simpleNature.getLastName();
-                       case 3:
-                               return simpleNature.getEmail();
-                       default:
-                               throw new ArgeoException("Unmanaged column " + columnIndex);
+                       try {
+                               Node userHome = (Node) element;
+                               switch (columnIndex) {
+                               case 0:
+                                       String userName = userHome.getProperty(ARGEO_USER_ID)
+                                                       .getString();
+                                       if (userName.equals(session.getUserID()))
+                                               return "[" + userName + "]";
+                                       else
+                                               return userName;
+                               case 1:
+                                       return userHome.getNode(ARGEO_USER_PROFILE)
+                                                       .getProperty(ARGEO_FIRST_NAME).getString();
+                               case 2:
+                                       return userHome.getNode(ARGEO_USER_PROFILE)
+                                                       .getProperty(ARGEO_LAST_NAME).getString();
+                               case 3:
+                                       return userHome.getNode(ARGEO_USER_PROFILE)
+                                                       .getProperty(ARGEO_PRIMARY_EMAIL).getString();
+                               default:
+                                       throw new ArgeoException("Unmanaged column " + columnIndex);
+                               }
+                       } catch (RepositoryException e) {
+                               throw new ArgeoException("Cannot get text", e);
                        }
+
+                       // String currentUsername = CurrentUser.getUsername();
+                       // String currentUsername = "";
+                       // ArgeoUser user = (ArgeoUser) element;
+                       // SimpleUserNature simpleNature = SimpleUserNature
+                       // .findSimpleUserNature(user, simpleNatureType);
+                       // switch (columnIndex) {
+                       // case 0:
+                       // String userName = user.getUsername();
+                       // if (userName.equals(currentUsername))
+                       // userName = userName + "*";
+                       // return userName;
+                       // case 1:
+                       // return simpleNature.getFirstName();
+                       // case 2:
+                       // return simpleNature.getLastName();
+                       // case 3:
+                       // return simpleNature.getEmail();
+                       // default:
+                       // throw new ArgeoException("Unmanaged column " + columnIndex);
+                       // }
                }
 
                public Image getColumnImage(Object element, int columnIndex) {
@@ -133,10 +188,23 @@ public class UsersView extends ViewPart {
 
        class ViewDoubleClickListener implements IDoubleClickListener {
                public void doubleClick(DoubleClickEvent evt) {
+                       if (evt.getSelection().isEmpty())
+                               return;
+
                        Object obj = ((IStructuredSelection) evt.getSelection())
                                        .getFirstElement();
-
-                       if (obj instanceof ArgeoUser) {
+                       if (obj instanceof Node) {
+                               try {
+                                       IWorkbench iw = SecurityAdminPlugin.getDefault()
+                                                       .getWorkbench();
+                                       iw.getActiveWorkbenchWindow()
+                                                       .getActivePage()
+                                                       .openEditor(new ArgeoUserEditorInput((Node) obj),
+                                                                       ArgeoUserEditor.ID);
+                               } catch (PartInitException e) {
+                                       Error.show("Cannot open user editor for " + obj, e);
+                               }
+                       } else if (obj instanceof ArgeoUser) {
                                ArgeoUser argeoUser = (ArgeoUser) obj;
 
                                IWorkbench iw = SecurityAdminPlugin.getDefault().getWorkbench();
index d7dc18ca9c5dacdde74b134c465482763fd776b7..50f74e9c72fe6a06f7227f04b524577e14288b59 100644 (file)
@@ -1,25 +1,45 @@
 package org.argeo.security.ui.rap;
 
 import java.security.PrivilegedAction;
+import java.util.Set;
 
 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.eclipse.ui.dialogs.Error;
 import org.eclipse.core.runtime.IStatus;
 import org.eclipse.core.runtime.Status;
 import org.eclipse.jface.dialogs.ErrorDialog;
+import org.eclipse.rwt.RWT;
 import org.eclipse.rwt.lifecycle.IEntryPoint;
+import org.eclipse.rwt.service.SessionStoreEvent;
+import org.eclipse.rwt.service.SessionStoreListener;
 import org.eclipse.swt.widgets.Display;
 import org.eclipse.ui.PlatformUI;
 import org.eclipse.ui.application.IWorkbenchWindowConfigurer;
 import org.eclipse.ui.application.WorkbenchAdvisor;
 import org.eclipse.ui.application.WorkbenchWindowAdvisor;
+import org.springframework.security.Authentication;
+import org.springframework.security.context.SecurityContextHolder;
 
-public class SecureEntryPoint implements IEntryPoint {
+public class SecureEntryPoint implements IEntryPoint, SessionStoreListener {
+       private Log log = LogFactory.getLog(SecureEntryPoint.class);
+
+       private final static String SECURITY_CONTEXT_ATTRIBUTE = "securityContextAttribute";
 
        @Override
        public int createUI() {
+//             log.debug("THREAD=" + Thread.currentThread().getId()
+//                             + ", RWT.getSessionStore().getId()="
+//                             + RWT.getSessionStore().getId());
+
+               Authentication authen = (Authentication) RWT.getSessionStore()
+                               .getAttribute(SECURITY_CONTEXT_ATTRIBUTE);
+               if (authen != null)
+                       SecurityContextHolder.getContext().setAuthentication(authen);
+
                Integer returnCode = null;
                Display display = PlatformUI.createDisplay();
                try {
@@ -27,9 +47,18 @@ public class SecureEntryPoint implements IEntryPoint {
                        Boolean retry = true;
                        while (retry) {
                                try {
-                                       SecureRapActivator.getLoginContext().login();
-                                       subject = SecureRapActivator.getLoginContext()
-                                                       .getSubject();
+                                       // if (authen == null)
+                                       // SecureRapActivator.getLoginContext().login();
+                                       subject = SecureRapActivator.getLoginContext().getSubject();
+                                       Set<Authentication> auths = subject
+                                                       .getPrincipals(Authentication.class);
+                                       if (auths.size() > 0)
+                                               SecurityContextHolder.getContext().setAuthentication(
+                                                               auths.iterator().next());
+                                       // authen = SecurityContextHolder.getContext()
+                                       // .getAuthentication();
+                                       // RWT.getSessionStore().setAttribute(
+                                       // SECURITY_CONTEXT_ATTRIBUTE, authen);
                                        retry = false;
                                } catch (LoginException e) {
                                        Error.show("Cannot login", e);
@@ -99,4 +128,13 @@ public class SecureEntryPoint implements IEntryPoint {
                };
        }
 
+       @Override
+       public void beforeDestroy(SessionStoreEvent event) {
+               if (log.isDebugEnabled())
+                       log.debug("RWT session " + event.getSessionStore().getId()
+                                       + " about to be destroyed. THREAD="
+                                       + Thread.currentThread().getId());
+
+       }
+
 }
index e189e5efe1c2b91039c321e83f797d7b659c7e17..a9ad7d848b8a1a5d08936d6fad4687bcbb21040c 100644 (file)
@@ -52,7 +52,7 @@
                 </command>
           </menuContribution>
   </extension>
-  <extension
+   <extension
            point="org.eclipse.ui.services">
         <sourceProvider
               provider="org.argeo.security.ui.RolesSourceProvider">
index 1abdc15646dc6453045762147f3ad503458f36fe..638eb03a59e14c3b209f8f4a7ce257f6f7c5c761 100644 (file)
@@ -23,7 +23,8 @@ public class CurrentUser {
        }
 
        public final static Set<String> roles() {
-               Principal principal = getSubject().getPrincipals().iterator().next();
+               Principal principal = getSubject().getPrincipals(Authentication.class)
+                               .iterator().next();
                Authentication authentication = (Authentication) principal;
                Set<String> roles = Collections.synchronizedSet(new HashSet<String>());
                for (GrantedAuthority ga : authentication.getAuthorities()) {
index cd49d656668cfa15037bfe470f30c4620f5232b7..e813e72a4fd99dc468917b4dcd38331e74f85f59 100644 (file)
@@ -1,5 +1,6 @@
 package org.argeo.security;
 
+import java.util.List;
 import java.util.Set;
 
 public interface UserAdminService {
@@ -21,6 +22,8 @@ public interface UserAdminService {
        /** List users having this role (except the super user). */
        public Set<ArgeoUser> listUsersInRole(String role);
 
+       public List<String> listUserRoles(String username);
+
        public void deleteUser(String username);
 
        /*
index edd7e2bf391359724b6b39ee6a2bb18a35932872..eac1d3706a13d2472bc4010562eb7e12713b89f5 100644 (file)
@@ -33,6 +33,7 @@ import org.springframework.security.context.SecurityContextHolder;
 import org.springframework.security.userdetails.User;
 import org.springframework.security.userdetails.UserDetails;
 
+@Deprecated
 public class ArgeoUserDetails extends User implements ArgeoUser {
        private static final long serialVersionUID = 1L;
        private final static Log log = LogFactory.getLog(ArgeoUserDetails.class);
index 94cdfa94f4fc59272c8be5377952d949aadd6469..e744dd0e73f0a70cb6b134b93c325e37ce104787 100644 (file)
@@ -18,6 +18,7 @@ package org.argeo.security.core;
 
 import java.util.HashSet;
 import java.util.Iterator;
+import java.util.List;
 import java.util.Set;
 
 import org.argeo.security.ArgeoUser;
@@ -95,6 +96,10 @@ public class DefaultUserAdminService implements UserAdminService {
                return userAdminDao.listUsers();
        }
 
+       public List<String> listUserRoles(String username) {
+               return getUser(username).getRoles();
+       }
+
        public Set<String> listEditableRoles() {
                return userAdminDao.listEditableRoles();
        }
index 08ef6428ad925f9cc19db8ffece144002df41218..a02221e323ce7dba34de0b03e46f5e5b8137948c 100644 (file)
@@ -1,5 +1,6 @@
 package org.argeo.security.core;
 
+import org.argeo.ArgeoException;
 import org.argeo.security.SystemExecutionService;
 import org.springframework.core.task.SimpleAsyncTaskExecutor;
 import org.springframework.core.task.TaskExecutor;
@@ -36,6 +37,14 @@ public class KeyBasedSystemExecutionService implements SystemExecutionService,
                        public void run() {
                                SecurityContext securityContext = SecurityContextHolder
                                                .getContext();
+                               Authentication currentAuth = securityContext
+                                               .getAuthentication();
+                               if (currentAuth != null) {
+                                       throw new ArgeoException(
+                                                       "System execution on an already authenticated thread: "
+                                                                       + currentAuth + ", THREAD="
+                                                                       + Thread.currentThread().getId());
+                               }
                                Authentication auth = authenticationManager
                                                .authenticate(new InternalAuthentication(
                                                                systemAuthenticationKey));
index ea66b5ff74e529f03d2bb97b766253b51e227f7d..3815b843b18c447650f2de9be7e45a322528b389 100644 (file)
@@ -66,4 +66,21 @@ public class JcrUserDetails extends User {
                                jcrUserDetails.isEnabled());
 
        }
+
+       public JcrUserDetails cloneWithNewRoles(List<String> roles) {
+               List<GrantedAuthority> authorities = new ArrayList<GrantedAuthority>();
+               for (String role : roles) {
+                       authorities.add(new GrantedAuthorityImpl(role));
+               }
+               return new JcrUserDetails(homePath, getUsername(), getPassword(),
+                               isEnabled(), isAccountNonExpired(), isAccountNonExpired(),
+                               isAccountNonLocked(),
+                               authorities.toArray(new GrantedAuthority[authorities.size()]));
+       }
+
+       public JcrUserDetails cloneWithNewPassword(String password) {
+               return new JcrUserDetails(homePath, getUsername(), password,
+                               isEnabled(), isAccountNonExpired(), isAccountNonExpired(),
+                               isAccountNonLocked(), getAuthorities());
+       }
 }
index d05cdf9ce7b88a6f2c96df50132b69c3a23adee5..1ab93edbb18f5678bfadd79f88c2b11ba8e7657c 100644 (file)
@@ -31,7 +31,9 @@ public class ArgeoLoginModule extends AbstractLoginModule {
         */
        @Override
        protected Principal getPrincipal(Credentials credentials) {
-               return SecurityContextHolder.getContext().getAuthentication();
+               org.springframework.security.Authentication authen = SecurityContextHolder
+                               .getContext().getAuthentication();
+               return authen;
        }
 
        protected Set<Principal> getPrincipals() {
index 5612b638868cd462cc310f8b25dd7812ea196427..72479128c4daab4b4ebef81c397e611653f4df57 100644 (file)
@@ -16,8 +16,6 @@ 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.core.DefaultSecurityManager;
-import org.apache.jackrabbit.core.RepositoryImpl;
-import org.apache.jackrabbit.core.security.AnonymousPrincipal;
 import org.apache.jackrabbit.core.security.SecurityConstants;
 import org.apache.jackrabbit.core.security.SystemPrincipal;
 import org.apache.jackrabbit.core.security.authorization.WorkspaceAccessManager;
@@ -94,7 +92,7 @@ public class ArgeoSecurityManager extends DefaultSecurityManager {
        private class ArgeoWorkspaceAccessManagerImpl implements SecurityConstants,
                        WorkspaceAccessManager {
                private final WorkspaceAccessManager wam;
-               private String defaultWorkspace;
+               //private String defaultWorkspace;
 
                public ArgeoWorkspaceAccessManagerImpl(WorkspaceAccessManager wam) {
                        super();
@@ -103,8 +101,8 @@ public class ArgeoSecurityManager extends DefaultSecurityManager {
 
                public void init(Session systemSession) throws RepositoryException {
                        wam.init(systemSession);
-                       defaultWorkspace = ((RepositoryImpl) getRepository()).getConfig()
-                                       .getDefaultWorkspaceName();
+//                     defaultWorkspace = ((RepositoryImpl) getRepository()).getConfig()
+//                                     .getDefaultWorkspaceName();
                }
 
                public void close() throws RepositoryException {
index 2d9fb1c1adf05cecf42a85c3137602d2b70d4163..0e8dbab32abff9c117bf466460c9f88126f7579d 100644 (file)
@@ -1,8 +1,11 @@
 package org.argeo.security.ldap.jcr;
 
+import java.security.NoSuchAlgorithmException;
+import java.security.SecureRandom;
 import java.util.Arrays;
 import java.util.HashMap;
 import java.util.Map;
+import java.util.Random;
 import java.util.concurrent.Executor;
 
 import javax.jcr.Node;
@@ -10,6 +13,7 @@ import javax.jcr.Repository;
 import javax.jcr.RepositoryException;
 import javax.jcr.RepositoryFactory;
 import javax.jcr.Session;
+import javax.jcr.nodetype.NodeType;
 
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
@@ -22,6 +26,8 @@ import org.argeo.security.jcr.JcrUserDetails;
 import org.springframework.ldap.core.DirContextAdapter;
 import org.springframework.ldap.core.DirContextOperations;
 import org.springframework.security.GrantedAuthority;
+import org.springframework.security.context.SecurityContextHolder;
+import org.springframework.security.providers.encoding.PasswordEncoder;
 import org.springframework.security.userdetails.UserDetails;
 import org.springframework.security.userdetails.ldap.UserDetailsContextMapper;
 
@@ -42,19 +48,38 @@ public class JcrUserDetailsContextMapper implements UserDetailsContextMapper,
 
        private Map<String, String> propertyToAttributes = new HashMap<String, String>();
        private Executor systemExecutor;
-       private RepositoryFactory repositoryFactory;
+       private Session session;
+
+       private PasswordEncoder passwordEncoder;
+       private final Random random;
+
+       public JcrUserDetailsContextMapper() {
+               random = createRandom();
+       }
+
+       private static Random createRandom() {
+               try {
+                       return SecureRandom.getInstance("SHA1PRNG");
+               } catch (NoSuchAlgorithmException e) {
+                       return new Random(System.currentTimeMillis());
+               }
+       }
 
        public UserDetails mapUserFromContext(final DirContextOperations ctx,
                        final String username, GrantedAuthority[] authorities) {
-               if (repositoryFactory == null)
-                       throw new ArgeoException("No JCR repository factory registered");
+               // if (repository == null)
+               // throw new ArgeoException("No JCR repository registered");
                final StringBuffer userHomePathT = new StringBuffer("");
-               systemExecutor.execute(new Runnable() {
+               Runnable action = new Runnable() {
                        public void run() {
                                String userHomepath = mapLdapToJcr(username, ctx);
                                userHomePathT.append(userHomepath);
                        }
-               });
+               };
+               if (SecurityContextHolder.getContext().getAuthentication() == null)// authentication
+                       systemExecutor.execute(action);
+               else
+                       action.run();
 
                // password
                byte[] arr = (byte[]) ctx
@@ -69,18 +94,24 @@ public class JcrUserDetailsContextMapper implements UserDetailsContextMapper,
 
        /** @return path to the user home node */
        protected String mapLdapToJcr(String username, DirContextOperations ctx) {
-               Session session = null;
+               // Session session = null;
                try {
-                       Repository nodeRepo = JcrUtils.getRepositoryByAlias(
-                                       repositoryFactory, ArgeoJcrConstants.ALIAS_NODE);
-                       session = nodeRepo.login();
+                       // Repository nodeRepo = JcrUtils.getRepositoryByAlias(
+                       // repositoryFactory, ArgeoJcrConstants.ALIAS_NODE);
+                       // session = nodeRepo.login();
                        Node userHome = JcrUtils.getUserHome(session, username);
                        if (userHome == null)
                                userHome = createUserHome(session, username);
                        String userHomePath = userHome.getPath();
-                       Node userProfile = userHome.hasNode(ARGEO_USER_PROFILE) ? userHome
-                                       .getNode(ARGEO_USER_PROFILE) : userHome
-                                       .addNode(ARGEO_USER_PROFILE);
+                       Node userProfile;
+                       if (userHome.hasNode(ARGEO_USER_PROFILE)) {
+                               userProfile = userHome.getNode(ARGEO_USER_PROFILE);
+                       } else {
+                               userProfile = userHome.addNode(ARGEO_USER_PROFILE);
+                               userProfile.addMixin(NodeType.MIX_TITLE);
+                               userProfile.addMixin(NodeType.MIX_CREATED);
+                               userProfile.addMixin(NodeType.MIX_LAST_MODIFIED);
+                       }
                        for (String jcrProperty : propertyToAttributes.keySet())
                                ldapToJcr(userProfile, jcrProperty, ctx);
                        session.save();
@@ -91,7 +122,7 @@ public class JcrUserDetailsContextMapper implements UserDetailsContextMapper,
                        JcrUtils.discardQuietly(session);
                        throw new ArgeoException("Cannot synchronize JCR and LDAP", e);
                } finally {
-                       session.logout();
+                       // JcrUtils.logoutQuietly(session);
                }
        }
 
@@ -120,31 +151,40 @@ public class JcrUserDetailsContextMapper implements UserDetailsContextMapper,
 
                ctx.setAttributeValues("objectClass", userClasses);
                ctx.setAttributeValue(usernameAttribute, user.getUsername());
-               ctx.setAttributeValue(passwordAttribute, user.getPassword());
+               ctx.setAttributeValue(passwordAttribute,
+                               encodePassword(user.getPassword()));
 
                final JcrUserDetails jcrUserDetails = (JcrUserDetails) user;
-               systemExecutor.execute(new Runnable() {
-                       public void run() {
-                               Session session = null;
-                               try {
-                                       Repository nodeRepo = JcrUtils.getRepositoryByAlias(
-                                                       repositoryFactory, ArgeoJcrConstants.ALIAS_NODE);
-                                       session = nodeRepo.login();
-                                       Node userProfile = session.getNode(jcrUserDetails
-                                                       .getHomePath() + '/' + ARGEO_USER_PROFILE);
-                                       for (String jcrProperty : propertyToAttributes.keySet())
-                                               jcrToLdap(userProfile, jcrProperty, ctx);
-                                       if (log.isDebugEnabled())
-                                               log.debug("Mapped " + userProfile + " to "
-                                                               + ctx.getDn());
-                               } catch (RepositoryException e) {
-                                       throw new ArgeoException("Cannot synchronize JCR and LDAP",
-                                                       e);
-                               } finally {
-                                       session.logout();
-                               }
-                       }
-               });
+               // systemExecutor.execute(new Runnable() {
+               // public void run() {
+//             Session session = null;
+               try {
+                       // Repository nodeRepo = JcrUtils.getRepositoryByAlias(
+                       // repositoryFactory, ArgeoJcrConstants.ALIAS_NODE);
+                       // session = nodeRepo.login();
+                       Node userProfile = session.getNode(jcrUserDetails.getHomePath()
+                                       + '/' + ARGEO_USER_PROFILE);
+                       for (String jcrProperty : propertyToAttributes.keySet())
+                               jcrToLdap(userProfile, jcrProperty, ctx);
+                       if (log.isDebugEnabled())
+                               log.debug("Mapped " + userProfile + " to " + ctx.getDn());
+               } catch (RepositoryException e) {
+                       throw new ArgeoException("Cannot synchronize JCR and LDAP", e);
+               } finally {
+                       // session.logout();
+               }
+               // }
+               // });
+       }
+
+       protected String encodePassword(String password) {
+               if (!password.startsWith("{")) {
+                       byte[] salt = new byte[16];
+                       random.nextBytes(salt);
+                       return passwordEncoder.encodePassword(password, salt);
+               } else {
+                       return password;
+               }
        }
 
        protected void ldapToJcr(Node userProfile, String jcrProperty,
@@ -201,15 +241,15 @@ public class JcrUserDetailsContextMapper implements UserDetailsContextMapper,
                this.homeBasePath = homeBasePath;
        }
 
-       public void register(RepositoryFactory repositoryFactory,
-                       Map<String, String> parameters) {
-               this.repositoryFactory = repositoryFactory;
-       }
-
-       public void unregister(RepositoryFactory repositoryFactory,
-                       Map<String, String> parameters) {
-               this.repositoryFactory = null;
-       }
+       // public void register(RepositoryFactory repositoryFactory,
+       // Map<String, String> parameters) {
+       // this.repositoryFactory = repositoryFactory;
+       // }
+       //
+       // public void unregister(RepositoryFactory repositoryFactory,
+       // Map<String, String> parameters) {
+       // this.repositoryFactory = null;
+       // }
 
        public void setUsernameAttribute(String usernameAttribute) {
                this.usernameAttribute = usernameAttribute;
@@ -223,4 +263,12 @@ public class JcrUserDetailsContextMapper implements UserDetailsContextMapper,
                this.userClasses = userClasses;
        }
 
+       public void setPasswordEncoder(PasswordEncoder passwordEncoder) {
+               this.passwordEncoder = passwordEncoder;
+       }
+
+       public void setSession(Session session) {
+               this.session = session;
+       }
+
 }
index 895c31c591ecf19fa45f7b39a633e81868123ce8..48845a0d805308d605dceee175792f1570b3ff62 100644 (file)
@@ -98,7 +98,7 @@ public class JackrabbitContainer implements InitializingBean, DisposableBean,
                                throw new ArgeoException("Remote Davex repository " + uri
                                                + " not found");
                        log.info("Initialized Jackrabbit repository " + repository
-                                       + " from uri " + uri);
+                                       + " from URI " + uri);
                        // do not perform further initialization since we assume that the
                        // remote repository has been properly configured
                        return;
@@ -275,6 +275,7 @@ public class JackrabbitContainer implements InitializingBean, DisposableBean,
                try {
                        NamespaceHelper namespaceHelper = new NamespaceHelper(session);
                        namespaceHelper.registerNamespaces(namespaces);
+
                } catch (Exception e) {
                        throw new ArgeoException("Cannot process new session", e);
                }
index 4b5ffb8db78b24203d613149422da13c727abac2..4026e87ecbcd4aef414434a951d502334fbeb48c 100644 (file)
@@ -7,8 +7,8 @@ public interface ArgeoNames {
        public final static String ARGEO_URI = "argeo:uri";
        public final static String ARGEO_USER_ID = "argeo:userID";
        
+       // user profile
        public final static String ARGEO_USER_PROFILE = "argeo:userProfile";
-       public final static String ARGEO_DISPLAY_NAME = "argeo:displayName";
        public final static String ARGEO_FIRST_NAME = "argeo:firstName";
        public final static String ARGEO_LAST_NAME = "argeo:lastName";
        public final static String ARGEO_PRIMARY_EMAIL = "argeo:primaryEmail";
index aaafdc26a704f2781c11164c07aec708a3a00769..9428c69593a5237f4f6237979f69e9b8e650bd60 100644 (file)
@@ -167,4 +167,13 @@ public class ThreadBoundJcrSessionFactory implements FactoryBean,
                        return ret;
                }
        }
+       
+       protected class MonitoringThread extends Thread{
+
+               @Override
+               public void run() {
+                       Thread thread=null;
+               }
+               
+       }
 }