<launcherArgs>
<programArgs>-console -clean</programArgs>
- <vmArgs>-Dlog4j.configuration="file:${system_property:user.home}/dev/src/commons/demo/log4j.properties"</vmArgs>
+ <vmArgs>-Dlog4j.configuration="file:${system_property:user.home}/dev/src/commons/demo/log4j.properties" -Dorg.argeo.security.ui.initialPerspective=org.argeo.jcr.ui.explorer.perspective</vmArgs>
<vmArgsMac>-XstartOnFirstThread -Dorg.eclipse.swt.internal.carbon.smallFonts</vmArgsMac>
</launcherArgs>
<plugin id="org.argeo.eclipse.ui"/>
<plugin id="org.argeo.eclipse.ui.jcr"/>
<plugin id="org.argeo.eclipse.ui.rcp"/>
- <plugin id="org.argeo.infra.core" fragment=""/>
+ <plugin id="org.argeo.infra.core"/>
<plugin id="org.argeo.infra.security.services" fragment="true"/>
<plugin id="org.argeo.jcr.ui.explorer"/>
<plugin id="org.argeo.node.repo.jackrabbit"/>
<plugin id="org.argeo.security.core"/>
+ <plugin id="org.argeo.security.dao.jackrabbit"/>
<plugin id="org.argeo.security.equinox"/>
<plugin id="org.argeo.security.jackrabbit" fragment="true"/>
<plugin id="org.argeo.security.ldap"/>
- <plugin id="org.argeo.security.manager.ldap"/>
+ <plugin id="org.argeo.security.manager.ldap" fragment=""/>
<plugin id="org.argeo.security.services"/>
<plugin id="org.argeo.security.ui"/>
<plugin id="org.argeo.security.ui.rcp"/>
<configurations>
<plugin id="org.argeo.node.repo.jackrabbit" autoStart="true" startLevel="0" />
- <plugin id="org.argeo.security.manager.ldap" autoStart="true" startLevel="0" />
+ <plugin id="org.argeo.security.dao.jackrabbit" autoStart="true" startLevel="0" />
<plugin id="org.argeo.security.services" autoStart="true" startLevel="0" />
- <plugin id="org.argeo.server.ads.server" autoStart="false" startLevel="0" />
<plugin id="org.springframework.osgi.extender" autoStart="true" startLevel="0" />
</configurations>
## Levels
log4j.logger.org.argeo=DEBUG
-log4j.logger.org.springframework.security=DEBUG
+log4j.logger.org.argeo.jackrabbit.remote.ExtendedDispatcherServlet=WARN
+
+log4j.logger.org.springframework.security=WARN
log4j.logger.org.apache.catalina=INFO
log4j.logger.org.apache.coyote=INFO
+++ /dev/null
-package org.argeo.eclipse.ui.jcr.commands;
-
-import javax.jcr.Node;
-import javax.jcr.Session;
-
-import org.argeo.eclipse.ui.dialogs.Error;
-import org.argeo.jcr.ArgeoNames;
-import org.argeo.jcr.ArgeoTypes;
-import org.eclipse.core.commands.AbstractHandler;
-import org.eclipse.core.commands.ExecutionEvent;
-import org.eclipse.core.commands.ExecutionException;
-
-/** Init the user home directory within the node */
-public class InitUserHome extends AbstractHandler {
- private Session session;
-
- private String defaultHome = "home";
-
- public Object execute(ExecutionEvent event) throws ExecutionException {
- String userID = "<not yet logged in>";
- try {
- userID = session.getUserID();
- Node rootNode = session.getRootNode();
- Node homeNode;
- if (!rootNode.hasNode(defaultHome)) {
- homeNode = rootNode.addNode(defaultHome, ArgeoTypes.ARGEO_HOME);
- } else {
- homeNode = rootNode.getNode(defaultHome);
- }
-
- if (!homeNode.hasNode(userID)) {
- Node userHome = homeNode.addNode(userID);
- userHome.addMixin(ArgeoTypes.ARGEO_USER_HOME);
- userHome.setProperty(ArgeoNames.ARGEO_USER_ID, userID);
- }
- session.save();
- } catch (Exception e) {
- Error.show("Cannot initialize home for user '" + userID + "'", e);
- }
- return null;
- }
-
- public void setSession(Session session) {
- this.session = session;
- }
-
-}
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
+import java.util.concurrent.Executor;
import javax.jcr.Node;
import javax.jcr.Property;
private DataStore dataStore;
private Session session;
- private SystemExecutionService systemExecutionService;
+ private Executor systemExecutionService;
/** The key is the workspace */
private Map<String, FeatureStore<SimpleFeatureType, SimpleFeature>> geoJcrIndexes = Collections
private FilterFactory2 ff = new FilterFactoryImpl();
public void init() {
- systemExecutionService.executeAsSystem(new Runnable() {
+ systemExecutionService.execute(new Runnable() {
public void run() {
initGeoJcrIndex();
}
final Set<FeatureId> toRemove = new HashSet<FeatureId>();
// execute with system authentication so that JCR can be read
- systemExecutionService.executeAsSystem(new Runnable() {
+ systemExecutionService.execute(new Runnable() {
public void run() {
while (events.hasNext()) {
Event event = events.nextEvent();
}
public void setSystemExecutionService(
- SystemExecutionService systemExecutionService) {
+ Executor systemExecutionService) {
this.systemExecutionService = systemExecutionService;
}
-Bundle-SymbolicName: org.argeo.security.dao.ldap
+Bundle-SymbolicName: org.argeo.security.dao.jackrabbit
Bundle-Version: 0.2.3.SNAPSHOT
Import-Package: javax.jcr;version="[2.0.0,3.0.0)",
+ org.argeo.security,
+ org.argeo.security.jackrabbit.providers,
+ org.argeo.security.jcr,
+ org.springframework.security.providers;specification-version="2.0.6.RELEASE"
Bundle-Name: Security DAO Jackrabbit
http://www.springframework.org/schema/util/spring-util-2.5.xsd">\r
\r
<!-- REFERENCE -->\r
- <reference id="repositoryFactoryRef" interface="javax.jcr.RepositoryFactory"\r
+ <reference id="repositoryFactory" interface="javax.jcr.RepositoryFactory"\r
cardinality="0..1">\r
<listener ref="jcrAuthenticationProvider" bind-method="register"\r
unbind-method="unregister" />\r
</reference>\r
- <reference id="systemExecutionService" interface="org.argeo.security.SystemExecutionService" />\r
\r
<!-- SERVICES -->\r
<service ref="jcrAuthenticationProvider"\r
interface="org.springframework.security.providers.AuthenticationProvider" />\r
+ <service ref="jcrCurrentUserDao" interface="org.argeo.security.CurrentUserDao" />\r
\r
</beans:beans>
\ No newline at end of file
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
-
<bean id="jcrAuthenticationProvider"
class="org.argeo.security.jackrabbit.providers.JackrabbitAuthenticationProvider" />
- <bean id="repositoryFactory" class="org.argeo.jackrabbit.JackrabbitRepositoryFactory">
- </bean>
-
+ <bean id="jcrCurrentUserDao" class="org.argeo.security.jcr.CurrentUserDaoJcr" />
</beans>
\ No newline at end of file
org.springframework.security.providers.ldap.authenticator,
org.springframework.security.userdetails,
org.springframework.security.userdetails.ldap
-Bundle-Name: Security Manager LDAP
+Bundle-Name: Security DAO LDAP
+++ /dev/null
-<beans xmlns="http://www.springframework.org/schema/beans"
- xmlns:security="http://www.springframework.org/schema/security"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:util="http://www.springframework.org/schema/util"
- xsi:schemaLocation="http://www.springframework.org/schema/beans
- http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
- http://www.springframework.org/schema/security
- http://www.springframework.org/schema/security/spring-security-2.0.4.xsd
- http://www.springframework.org/schema/util
- http://www.springframework.org/schema/util/spring-util-2.5.xsd">
-
-
- <bean id="jcrUserDetailsContextMapper" class="org.argeo.security.ldap.jcr.JcrUserDetailsContextMapper">
- <property name="systemExecutionService" ref="systemExecutionService" />
- <property name="propertyToAttributes">
- <map>
- <entry value="cn">
- <key>
- <util:constant static-field="org.argeo.jcr.ArgeoNames.ARGEO_DISPLAY_NAME" />
- </key>
- </entry>
- <entry value="givenName">
- <key>
- <util:constant static-field="org.argeo.jcr.ArgeoNames.ARGEO_FIRST_NAME" />
- </key>
- </entry>
- <entry value="sn">
- <key>
- <util:constant static-field="org.argeo.jcr.ArgeoNames.ARGEO_LAST_NAME" />
- </key>
- </entry>
- <entry value="mail">
- <key>
- <util:constant static-field="org.argeo.jcr.ArgeoNames.ARGEO_PRIMARY_EMAIL" />
- </key>
- </entry>
- <entry value="o">
- <key>
- <util:constant
- static-field="org.argeo.jcr.ArgeoNames.ARGEO_PRIMARY_ORGANIZATION" />
- </key>
- </entry>
- </map>
- </property>
-
- </bean>
-</beans>
--- /dev/null
+<beans xmlns="http://www.springframework.org/schema/beans"
+ xmlns:security="http://www.springframework.org/schema/security"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:util="http://www.springframework.org/schema/util"
+ xsi:schemaLocation="http://www.springframework.org/schema/beans
+ http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
+ http://www.springframework.org/schema/security
+ http://www.springframework.org/schema/security/spring-security-2.0.4.xsd
+ http://www.springframework.org/schema/util
+ http://www.springframework.org/schema/util/spring-util-2.5.xsd">
+
+ <bean id="jcrUserDetailsContextMapper" class="org.argeo.security.ldap.jcr.JcrUserDetailsContextMapper">
+ <property name="homeBasePath" value="/home" />
+ <property name="usernameAttribute" value="${argeo.ldap.usernameAttribute}" />
+ <property name="passwordAttribute" value="${argeo.ldap.passwordAttribute}" />
+ <property name="userClasses">
+ <list>
+ <value>${argeo.ldap.userClass}</value>
+ </list>
+ </property>
+ <property name="systemExecutor" ref="systemExecutionService" />
+ <property name="propertyToAttributes">
+ <map>
+ <entry value="cn">
+ <key>
+ <util:constant static-field="org.argeo.jcr.ArgeoNames.ARGEO_DISPLAY_NAME" />
+ </key>
+ </entry>
+ <entry value="givenName">
+ <key>
+ <util:constant static-field="org.argeo.jcr.ArgeoNames.ARGEO_FIRST_NAME" />
+ </key>
+ </entry>
+ <entry value="sn">
+ <key>
+ <util:constant static-field="org.argeo.jcr.ArgeoNames.ARGEO_LAST_NAME" />
+ </key>
+ </entry>
+ <entry value="mail">
+ <key>
+ <util:constant static-field="org.argeo.jcr.ArgeoNames.ARGEO_PRIMARY_EMAIL" />
+ </key>
+ </entry>
+ <entry value="o">
+ <key>
+ <util:constant
+ static-field="org.argeo.jcr.ArgeoNames.ARGEO_PRIMARY_ORGANIZATION" />
+ </key>
+ </entry>
+ </map>
+ </property>
+
+ </bean>
+</beans>
<reference id="systemExecutionService" interface="org.argeo.security.SystemExecutionService" />\r
\r
<!-- SERVICES -->\r
- <service ref="authenticationProvider"\r
+ <service ref="ldapAuthenticationProvider"\r
interface="org.springframework.security.providers.AuthenticationProvider"\r
context-class-loader="service-provider" />\r
+ \r
<service ref="securityDao" interface="org.argeo.security.CurrentUserDao"\r
context-class-loader="service-provider" />\r
<service ref="securityDao" interface="org.argeo.security.UserAdminDao"\r
</bean>
<!-- AUTHENTICATION -->
- <bean id="authenticationProvider"
+ <bean id="ldapAuthenticationProvider"
class="org.springframework.security.providers.ldap.LdapAuthenticationProvider">
<constructor-arg ref="passwordComparisonAuthenticator" />
<constructor-arg ref="authoritiesPopulator" />
<value><![CDATA[${argeo.ldap.usernameAttribute}={0},${argeo.ldap.userBase}]]></value>
</list>
</property>
+ <property name="passwordAttributeName" value="${argeo.ldap.passwordAttribute}" />
<property name="passwordEncoder" ref="passwordEncoder" />
</bean>
<!-- USER DETAILS -->
<bean id="securityDao" class="org.argeo.security.ldap.ArgeoSecurityDaoLdap">
<constructor-arg ref="contextSource" />
-
<property name="userBase" value="${argeo.ldap.userBase}" />
<property name="usernameAttribute" value="${argeo.ldap.usernameAttribute}" />
<property name="groupClasses">
<property name="groupMemberAttribute" value="${argeo.ldap.groupMemberAttribute}" />
<property name="defaultRole" value="${argeo.security.defaultRole}" />
<property name="rolePrefix" value="${argeo.security.rolePrefix}" />
-
<property name="passwordEncoder" ref="passwordEncoder" />
<property name="usernameMapper" ref="usernameMapper" />
<property name="userDetailsManager" ref="userDetailsManager" />
argeo.ldap.rootdn=dc=demo,dc=argeo,dc=org
argeo.ldap.protocol=ldap
argeo.ldap.host=localhost
+# default are for Apache Directory Server
argeo.ldap.port=10389
argeo.ldap.manager.userdn=uid=admin,ou=system
argeo.ldap.manager.password=secret
+# USER
+argeo.ldap.userClass=inetOrgPerson
argeo.ldap.userBase=ou=People
argeo.ldap.usernameAttribute=uid
+argeo.ldap.passwordAttribute=userPassword
+# ROLES
argeo.ldap.groupClass=groupOfNames
argeo.ldap.groupBase=ou=Roles
argeo.ldap.groupRoleAttribute=cn
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">\r
\r
<!-- REFERENCES -->\r
+ <!-- Cardinality is 0, in order to let a bundle providing the DAO while \r
+ depending on the system execution service. The dependency will then have \r
+ been satisfied when the first user tries to log-in. -->\r
<reference id="currentUserDao" interface="org.argeo.security.CurrentUserDao"\r
cardinality="0..1" />\r
\r
public interface CurrentUserDao {
public void updateCurrentUserPassword(String oldPassword, String newPassword);
+ @Deprecated
public String getDefaultRole();
}
package org.argeo.security;
+import java.util.concurrent.Executor;
+
import org.springframework.core.task.TaskExecutor;
/**
* Allows to execute code authenticated as a system user (that is not a real
- * person)
+ * person). The {@link Executor} interface interface is not used directly in
+ * order to allow future extension of this interface and to simplify its
+ * publication (e.g. as an OSGi service) and interception. Support for Spring's
+ * {@link TaskExecutor} will be dropped when upgrading to Spring 3, since it is
+ * only to ensure compatibility with versions of Java before 1.5.
*/
-public interface SystemExecutionService {
+public interface SystemExecutionService extends Executor, TaskExecutor {
/**
* Executes this Runnable within a system authenticated context.
* Implementations should make sure that this method is properly secured via
* Java permissions since it could access to everything without credentials.
*/
- public void executeAsSystem(Runnable runnable);
-
- public TaskExecutor createSystemAuthenticatedTaskExecutor();
+ public void execute(Runnable runnable);
}
import org.springframework.security.context.SecurityContext;
import org.springframework.security.context.SecurityContextHolder;
-public class KeyBasedSystemExecutionService implements SystemExecutionService {
+public class KeyBasedSystemExecutionService implements SystemExecutionService,
+ TaskExecutor {
private AuthenticationManager authenticationManager;
private String systemAuthenticationKey;
- public void executeAsSystem(Runnable runnable) {
+ public void execute(Runnable runnable) {
wrapWithSystemAuthentication(runnable).run();
}
--- /dev/null
+package org.argeo.security.jcr;
+
+import org.argeo.security.CurrentUserDao;
+
+public class CurrentUserDaoJcr implements CurrentUserDao {
+ private String defaultRole= "ROLE_USER";
+
+ public void updateCurrentUserPassword(String oldPassword, String newPassword) {
+ throw new UnsupportedOperationException(
+ "Updating passwords is not supported");
+ }
+
+ public String getDefaultRole() {
+ return defaultRole;
+ }
+
+ public void setDefaultRole(String defaultRole) {
+ this.defaultRole = defaultRole;
+ }
+
+}
import org.argeo.ArgeoException;
import org.argeo.jcr.ArgeoJcrConstants;
-import org.argeo.jcr.ArgeoNames;
-import org.argeo.jcr.ArgeoTypes;
+import org.argeo.jcr.JcrUtils;
import org.argeo.security.SiteAuthenticationToken;
import org.springframework.security.Authentication;
import org.springframework.security.AuthenticationException;
import org.springframework.security.GrantedAuthority;
import org.springframework.security.GrantedAuthorityImpl;
import org.springframework.security.providers.AuthenticationProvider;
+import org.springframework.security.userdetails.UserDetails;
/** Connects to a JCR repository and delegate authentication to it. */
public class JcrAuthenticationProvider implements AuthenticationProvider {
- private RepositoryFactory repositoryFactory;
- private final String defaultHome;
- private final String userRole;
-
- public JcrAuthenticationProvider() {
- this("ROLE_USER", "home");
- }
+ public final static String ROLE_REMOTE_JCR_AUTHENTICATED = "ROLE_REMOTE_JCR_AUTHENTICATED";
- public JcrAuthenticationProvider(String userRole) {
- this(userRole, "home");
- }
-
- public JcrAuthenticationProvider(String defaultHome, String userRole) {
- super();
- this.defaultHome = defaultHome;
- this.userRole = userRole;
- }
+ private RepositoryFactory repositoryFactory;
public Authentication authenticate(Authentication authentication)
throws AuthenticationException {
session = repository.login(sp);
else
session = repository.login(sp, workspace);
- Node userHome = getUserHome(session);
+ Node userHome = JcrUtils.getUserHome(session);
+ if (userHome == null)
+ throw new ArgeoException("No home found for user "
+ + session.getUserID());
GrantedAuthority[] authorities = {};
- return new JcrAuthenticationToken(siteAuth.getPrincipal(),
- siteAuth.getCredentials(), authorities, url, userHome);
+ JcrAuthenticationToken authen = new JcrAuthenticationToken(
+ siteAuth.getPrincipal(), siteAuth.getCredentials(),
+ authorities, url, userHome);
+ authen.setDetails(getUserDetails(userHome, authen));
+ return authen;
} catch (RepositoryException e) {
throw new ArgeoException(
"Unexpected exception when authenticating to " + url, e);
}
}
+ /**
+ * By default, assigns only the role {@value #ROLE_REMOTE_JCR_AUTHENTICATED}
+ * . Should typically be overridden in order to assign more relevant roles.
+ */
protected GrantedAuthority[] getGrantedAuthorities(Session session) {
- return new GrantedAuthority[] { new GrantedAuthorityImpl(userRole) };
- }
-
- @SuppressWarnings("rawtypes")
- public boolean supports(Class authentication) {
- return SiteAuthenticationToken.class.isAssignableFrom(authentication);
+ return new GrantedAuthority[] { new GrantedAuthorityImpl(
+ ROLE_REMOTE_JCR_AUTHENTICATED) };
}
- protected Node getUserHome(Session session) {
- String userID = "<not yet logged in>";
+ /** Builds user details based on the authentication and the user home. */
+ protected UserDetails getUserDetails(Node userHome,
+ JcrAuthenticationToken authen) {
try {
- userID = session.getUserID();
- Node rootNode = session.getRootNode();
- Node homeNode;
- if (!rootNode.hasNode(defaultHome)) {
- homeNode = rootNode.addNode(defaultHome, ArgeoTypes.ARGEO_HOME);
- } else {
- homeNode = rootNode.getNode(defaultHome);
- }
-
- Node userHome;
- if (!homeNode.hasNode(userID)) {
- userHome = homeNode.addNode(userID);
- userHome.addMixin(ArgeoTypes.ARGEO_USER_HOME);
- userHome.setProperty(ArgeoNames.ARGEO_USER_ID, userID);
- } else {
- userHome = homeNode.getNode(userID);
- }
- session.save();
- return userHome;
+ // TODO: loads enabled, locked, etc. from the home node.
+ return new JcrUserDetails(userHome.getPath(), authen.getPrincipal()
+ .toString(), authen.getCredentials().toString(), true,
+ true, true, true, authen.getAuthorities());
} catch (Exception e) {
- throw new ArgeoException("Cannot initialize home for user '"
- + userID + "'", e);
+ throw new ArgeoException("Cannot get user details for " + userHome,
+ e);
}
}
+ @SuppressWarnings("rawtypes")
+ public boolean supports(Class authentication) {
+ return SiteAuthenticationToken.class.isAssignableFrom(authentication);
+ }
+
public void register(RepositoryFactory repositoryFactory,
Map<String, String> parameters) {
this.repositoryFactory = repositoryFactory;
Map<String, String> parameters) {
this.repositoryFactory = null;
}
-
- public String getDefaultHome() {
- return defaultHome;
- }
-
- public String getUserRole() {
- return userRole;
- }
-
}
import javax.jcr.Node;
import javax.jcr.RepositoryException;
+import javax.jcr.Session;
import org.argeo.ArgeoException;
import org.argeo.security.SiteAuthenticationToken;
import org.springframework.security.GrantedAuthority;
+/** An authenticated authentication based on a JCR session. */
public class JcrAuthenticationToken extends SiteAuthenticationToken {
private static final long serialVersionUID = -2736830165315486169L;
- private final transient Node userHome;
+
+ private final transient Session session;
+ private final String userHomePath;
public JcrAuthenticationToken(Object principal, Object credentials,
GrantedAuthority[] authorities, String url, Node userHome) {
super(principal, credentials, authorities, url,
extractWorkspace(userHome));
- this.userHome = userHome;
+ try {
+ this.session = userHome.getSession();
+ this.userHomePath = userHome.getPath();
+ } catch (RepositoryException e) {
+ throw new ArgeoException("Cannot extract path from " + userHome, e);
+ }
}
private static String extractWorkspace(Node userHome) {
try {
return userHome.getSession().getWorkspace().getName();
} catch (RepositoryException e) {
- throw new ArgeoException("Cannot extract workspace of " + userHome,
- e);
+ throw new ArgeoException("Cannot extract workspace from "
+ + userHome, e);
}
}
- public Node getUserHome() {
- return userHome;
+ /** The path to the authenticated user home node. */
+ public String getUserHomePath() {
+ return userHomePath;
+ }
+
+ /** The session used to create this authentication. */
+ public Session getSession() {
+ return session;
+ }
+
+ @Override
+ public boolean isAuthenticated() {
+ if (session == null || !session.isLive())
+ setAuthenticated(false);
+ return super.isAuthenticated();
+ }
+
+ @Override
+ public void setAuthenticated(boolean isAuthenticated)
+ throws IllegalArgumentException {
+ super.setAuthenticated(isAuthenticated);
+ if (!isAuthenticated && session != null)
+ session.logout();
}
}
<instructions>
<Fragment-Host>org.argeo.dep.osgi.jackrabbit</Fragment-Host>
<Export-Package>org.argeo.security.jackrabbit.*</Export-Package>
+ <Import-Package>*,org.springframework.core</Import-Package>
</instructions>
</configuration>
</plugin>
package org.argeo.security.jackrabbit;
+import javax.jcr.RepositoryException;
+
import org.apache.jackrabbit.core.security.DefaultAccessManager;
/** Intermediary class in order to have a consistent naming in config files. */
public class ArgeoAccessManager extends DefaultAccessManager {
+ @Override
+ public boolean canAccess(String workspaceName) throws RepositoryException {
+ // TODO Auto-generated method stub
+ return super.canAccess(workspaceName);
+ }
+
}
package org.argeo.security.jackrabbit;
+import java.security.Principal;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import javax.jcr.RepositoryException;
+import javax.jcr.Session;
import javax.security.auth.Subject;
import org.apache.commons.logging.Log;
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;
import org.argeo.ArgeoException;
import org.springframework.security.Authentication;
import org.springframework.security.GrantedAuthority;
group.removeMember(user);
}
- if (log.isDebugEnabled())
- log.debug("Spring and Jackrabbit Security synchronized for user "
+ if (log.isTraceEnabled())
+ log.trace("Spring and Jackrabbit Security synchronized for user "
+ userId + " in " + (System.currentTimeMillis() - begin)
+ " ms");
return userId;
}
+
+ @Override
+ protected WorkspaceAccessManager createDefaultWorkspaceAccessManager() {
+ WorkspaceAccessManager wam = super
+ .createDefaultWorkspaceAccessManager();
+ return new ArgeoWorkspaceAccessManagerImpl(wam);
+ }
+
+ private class ArgeoWorkspaceAccessManagerImpl implements SecurityConstants,
+ WorkspaceAccessManager {
+ private final WorkspaceAccessManager wam;
+ private String defaultWorkspace;
+
+ public ArgeoWorkspaceAccessManagerImpl(WorkspaceAccessManager wam) {
+ super();
+ this.wam = wam;
+ }
+
+ public void init(Session systemSession) throws RepositoryException {
+ wam.init(systemSession);
+ defaultWorkspace = ((RepositoryImpl) getRepository()).getConfig()
+ .getDefaultWorkspaceName();
+ }
+
+ public void close() throws RepositoryException {
+ }
+
+ public boolean grants(Set<Principal> principals, String workspaceName)
+ throws RepositoryException {
+ // anonymous has access to the default workspace (required for
+ // remoting which does a default login when initializing the
+ // repository)
+ Boolean anonymous = false;
+ for (Principal principal : principals)
+ if (principal instanceof AnonymousPrincipal)
+ anonymous = true;
+
+ if (anonymous && workspaceName.equals(defaultWorkspace))
+ return true;
+ else
+ return wam.grants(principals, workspaceName);
+ }
+ }
+
}
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
+import java.util.concurrent.Executor;
import javax.jcr.Node;
import javax.jcr.Repository;
import org.argeo.ArgeoException;
import org.argeo.jcr.ArgeoJcrConstants;
import org.argeo.jcr.ArgeoNames;
+import org.argeo.jcr.ArgeoTypes;
import org.argeo.jcr.JcrUtils;
-import org.argeo.security.SystemExecutionService;
import org.argeo.security.jcr.JcrUserDetails;
import org.springframework.ldap.core.DirContextAdapter;
import org.springframework.ldap.core.DirContextOperations;
* checks of which values should be mandatory should be performed at a higher
* level.
*/
-public class JcrUserDetailsContextMapper implements UserDetailsContextMapper {
+public class JcrUserDetailsContextMapper implements UserDetailsContextMapper,
+ ArgeoNames {
private final static Log log = LogFactory
.getLog(JcrUserDetailsContextMapper.class);
+ private String usernameAttribute;
+ private String passwordAttribute;
+ private String homeBasePath;
+ private String[] userClasses;
+
private Map<String, String> propertyToAttributes = new HashMap<String, String>();
- private SystemExecutionService systemExecutionService;
- private String homeBasePath = "/home";
+ private Executor systemExecutor;
private RepositoryFactory repositoryFactory;
public UserDetails mapUserFromContext(final DirContextOperations ctx,
final String username, GrantedAuthority[] authorities) {
if (repositoryFactory == null)
throw new ArgeoException("No JCR repository factory registered");
- final String userHomePath = usernameToHomePath(username);
- systemExecutionService.executeAsSystem(new Runnable() {
+ final StringBuffer userHomePathT = new StringBuffer("");
+ systemExecutor.execute(new Runnable() {
public void run() {
- Session session = null;
- try {
- Repository nodeRepo = JcrUtils.getRepositoryByAlias(
- repositoryFactory, ArgeoJcrConstants.ALIAS_NODE);
- session = nodeRepo.login();
- Node userProfile = JcrUtils.mkdirs(session, userHomePath
- + '/' + ArgeoNames.ARGEO_USER_PROFILE);
- for (String jcrProperty : propertyToAttributes.keySet())
- ldapToJcr(userProfile, jcrProperty, ctx);
- session.save();
- if (log.isDebugEnabled())
- log.debug("Mapped " + ctx.getDn() + " to "
- + userProfile);
- } catch (RepositoryException e) {
- throw new ArgeoException("Cannot synchronize JCR and LDAP",
- e);
- } finally {
- session.logout();
- }
+ String userHomepath = mapLdapToJcr(username, ctx);
+ userHomePathT.append(userHomepath);
}
});
// password
- byte[] arr = (byte[]) ctx.getAttributeSortedStringSet("userPassword")
- .first();
- JcrUserDetails userDetails = new JcrUserDetails(userHomePath, username,
- new String(arr), true, true, true, true, authorities);
+ byte[] arr = (byte[]) ctx
+ .getAttributeSortedStringSet(passwordAttribute).first();
+ JcrUserDetails userDetails = new JcrUserDetails(
+ userHomePathT.toString(), username, new String(arr), true,
+ true, true, true, authorities);
+ // erase password
Arrays.fill(arr, (byte) 0);
return userDetails;
}
+ /** @return path to the user home node */
+ protected String mapLdapToJcr(String username, DirContextOperations ctx) {
+ Session session = null;
+ try {
+ 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);
+ for (String jcrProperty : propertyToAttributes.keySet())
+ ldapToJcr(userProfile, jcrProperty, ctx);
+ session.save();
+ if (log.isDebugEnabled())
+ log.debug("Mapped " + ctx.getDn() + " to " + userProfile);
+ return userHomePath;
+ } catch (RepositoryException e) {
+ JcrUtils.discardQuietly(session);
+ throw new ArgeoException("Cannot synchronize JCR and LDAP", e);
+ } finally {
+ session.logout();
+ }
+ }
+
+ protected Node createUserHome(Session session, String username) {
+ try {
+ Node userHome = JcrUtils.mkdirs(session,
+ usernameToHomePath(username));
+ userHome.addMixin(ArgeoTypes.ARGEO_USER_HOME);
+ userHome.setProperty(ARGEO_USER_ID, username);
+ return userHome;
+ } catch (RepositoryException e) {
+ throw new ArgeoException("Cannot create home node for user "
+ + username, e);
+ }
+ }
+
+ protected String usernameToHomePath(String username) {
+ return homeBasePath + '/' + JcrUtils.firstCharsToPath(username, 2)
+ + '/' + username;
+ }
+
public void mapUserToContext(UserDetails user, final DirContextAdapter ctx) {
if (!(user instanceof JcrUserDetails))
throw new ArgeoException("Unsupported user details: "
+ user.getClass());
- ctx.setAttributeValues("objectClass", new String[] { "inetOrgPerson" });
- ctx.setAttributeValue("uid", user.getUsername());
- ctx.setAttributeValue("userPassword", user.getPassword());
+ ctx.setAttributeValues("objectClass", userClasses);
+ ctx.setAttributeValue(usernameAttribute, user.getUsername());
+ ctx.setAttributeValue(passwordAttribute, user.getPassword());
final JcrUserDetails jcrUserDetails = (JcrUserDetails) user;
- systemExecutionService.executeAsSystem(new Runnable() {
+ systemExecutor.execute(new Runnable() {
public void run() {
Session session = null;
try {
repositoryFactory, ArgeoJcrConstants.ALIAS_NODE);
session = nodeRepo.login();
Node userProfile = session.getNode(jcrUserDetails
- .getHomePath()
- + '/'
- + ArgeoNames.ARGEO_USER_PROFILE);
+ .getHomePath() + '/' + ARGEO_USER_PROFILE);
for (String jcrProperty : propertyToAttributes.keySet())
jcrToLdap(userProfile, jcrProperty, ctx);
if (log.isDebugEnabled())
});
}
- protected String usernameToHomePath(String username) {
- return homeBasePath + '/' + JcrUtils.firstCharsToPath(username, 2)
- + '/' + username;
- }
-
protected void ldapToJcr(Node userProfile, String jcrProperty,
DirContextOperations ctx) {
try {
this.propertyToAttributes = propertyToAttributes;
}
- public void setSystemExecutionService(
- SystemExecutionService systemExecutionService) {
- this.systemExecutionService = systemExecutionService;
+ public void setSystemExecutor(Executor systemExecutor) {
+ this.systemExecutor = systemExecutor;
}
public void setHomeBasePath(String homeBasePath) {
Map<String, String> parameters) {
this.repositoryFactory = null;
}
+
+ public void setUsernameAttribute(String usernameAttribute) {
+ this.usernameAttribute = usernameAttribute;
+ }
+
+ public void setPasswordAttribute(String passwordAttribute) {
+ this.passwordAttribute = passwordAttribute;
+ }
+
+ public void setUserClasses(String[] userClasses) {
+ this.userClasses = userClasses;
+ }
+
}
<bean id="sessionProvider" scope="session" init-method="init"
destroy-method="dispose" class="org.argeo.jackrabbit.remote.SimpleSessionProvider">
<aop:scoped-proxy proxy-target-class="false" />
+<!-- <property name="credentials"> -->
+<!-- <bean class="javax.jcr.SimpleCredentials"> -->
+<!-- <constructor-arg value="root" /> -->
+<!-- <constructor-arg value="demo" /> -->
+<!-- </bean> -->
+<!-- </property> -->
</bean>
<bean id="osivInterceptor" class="org.argeo.jcr.mvc.OpenSessionInViewJcrInterceptor">
<security:intercept-url pattern="/**"
access="ROLE_USER,ROLE_ADMIN,ROLE_ANONYMOUS" />
<security:http-basic />
- <security:anonymous />
+ <security:anonymous username="anonymous" />
</security:http>
<!-- LDAP -->
org.apache.xalan.processor,
org.argeo.jackrabbit,
org.argeo.jcr,
- org.argeo.security.jackrabbit.providers,
- org.argeo.security.jcr,
+ org.argeo.security,
org.h2;version="[1.0.0,2.0.0)";resolution:=optional,
org.postgresql;version="[8.0.0,9.0.0)";resolution:=optional,
- org.springframework.beans.factory.config,
- org.springframework.security.providers;version="2.0.6.RELEASE"
+ org.springframework.beans.factory.config
http://www.springframework.org/schema/util/spring-util-2.5.xsd">\r
\r
<!-- REFERENCE -->\r
- <reference id="repositoryFactoryRef" interface="javax.jcr.RepositoryFactory"\r
- cardinality="0..1">\r
- <listener ref="jcrAuthenticationProvider" bind-method="register"\r
- unbind-method="unregister" />\r
- </reference>\r
<list id="repositories" interface="javax.jcr.Repository"\r
cardinality="0..N">\r
<listener ref="repositoryFactory" bind-method="register"\r
unbind-method="unregister" />\r
</list>\r
+ <reference id="systemExecutionService" interface="org.argeo.security.SystemExecutionService" />\r
\r
<!-- SERVICES -->\r
<service ref="repositoryFactory" interface="javax.jcr.RepositoryFactory" />\r
</beans:entry>\r
</service-properties>\r
</service>\r
-\r
- <service ref="jcrAuthenticationProvider"\r
- interface="org.springframework.security.providers.AuthenticationProvider" />\r
-\r
</beans:beans>
\ No newline at end of file
<value>classpath:/org/argeo/jcr/argeo.cnd</value>
</list>
</property>
+ <property name="systemExecutor" ref="systemExecutionService" />
</bean>
<bean id="nodeJcrSession" class="org.argeo.jcr.ThreadBoundJcrSessionFactory">
<property name="workspace" value="${argeo.node.repo.workspace}" />
</bean>
- <bean id="jcrAuthenticationProvider"
- class="org.argeo.security.jackrabbit.providers.JackrabbitAuthenticationProvider" />
-
- <bean id="repositoryFactory" class="org.argeo.jackrabbit.JackrabbitRepositoryFactory">
- </bean>
+ <bean id="repositoryFactory" class="org.argeo.jackrabbit.JackrabbitRepositoryFactory"/>
</beans>
\ No newline at end of file
<bean id="importFileSystem" class="org.argeo.eclipse.ui.jcr.commands.ImportFileSystem"
scope="prototype" />
-
- <bean id="initUserHome" class="org.argeo.eclipse.ui.jcr.commands.InitUserHome"
- scope="prototype">
- <property name="session" ref="nodeJcrSession" />
- </bean>
</beans>
id="org.argeo.jcr.ui.explorer.addFileFolder"
name="Add file folder...">
</command>
- <command
- defaultHandler="org.argeo.eclipse.spring.SpringCommandHandler"
- id="org.argeo.jcr.ui.explorer.initUserHome"
- name="Initialize user home">
- </command>
<command
defaultHandler="org.argeo.eclipse.spring.SpringCommandHandler"
id="org.argeo.jcr.ui.explorer.refresh"
import java.io.File;
import java.io.InputStream;
import java.io.InputStreamReader;
+import java.io.Reader;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;
+import java.util.concurrent.Executor;
import javax.jcr.Credentials;
import javax.jcr.LoginException;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.jackrabbit.api.JackrabbitRepository;
-import org.apache.jackrabbit.commons.JcrUtils;
import org.apache.jackrabbit.commons.NamespaceHelper;
import org.apache.jackrabbit.commons.cnd.CndImporter;
import org.apache.jackrabbit.core.RepositoryImpl;
import org.apache.jackrabbit.core.config.RepositoryConfigurationParser;
import org.apache.jackrabbit.jcr2dav.Jcr2davRepositoryFactory;
import org.argeo.ArgeoException;
+import org.argeo.jcr.JcrUtils;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.context.ResourceLoaderAware;
private ResourceLoader resourceLoader;
/** Node type definitions in CND format */
- private List<byte[]> cnds = new ArrayList<byte[]>();
private List<String> cndFiles = new ArrayList<String>();
/** Namespaces to register: key is prefix, value namespace */
private Boolean autocreateWorkspaces = false;
- public void afterPropertiesSet() throws Exception {
- // Load cnds as resources
- for (String resUrl : cndFiles) {
- Resource res = resourceLoader.getResource(resUrl);
- byte[] arr = IOUtils.toByteArray(res.getInputStream());
- cnds.add(arr);
- }
+ private Executor systemExecutor;
+ public void afterPropertiesSet() throws Exception {
+ // remote repository
if (uri != null && !uri.trim().equals("")) {
Map<String, String> params = new HashMap<String, String>();
- params.put(JcrUtils.REPOSITORY_URI, uri);
+ params.put(org.apache.jackrabbit.commons.JcrUtils.REPOSITORY_URI,
+ uri);
repository = new Jcr2davRepositoryFactory().getRepository(params);
if (repository == null)
throw new ArgeoException("Remote Davex repository " + uri
+ " not found");
log.info("Initialized Jackrabbit repository " + repository
+ " from uri " + uri);
- } else {
- if (inMemory && homeDirectory.exists()) {
- FileUtils.deleteDirectory(homeDirectory);
- log.warn("Deleted Jackrabbit home directory " + homeDirectory);
- }
+ // do not perform further initialization since we assume that the
+ // remote repository has been properly configured
+ return;
+ }
- RepositoryConfig config;
- InputStream in = configuration.getInputStream();
- InputStream propsIn = null;
- try {
- Properties vars = new Properties();
- if (variables != null) {
- propsIn = variables.getInputStream();
- vars.load(propsIn);
- }
- // override with system properties
- vars.putAll(System.getProperties());
- vars.put(
- RepositoryConfigurationParser.REPOSITORY_HOME_VARIABLE,
- homeDirectory.getCanonicalPath());
- config = RepositoryConfig.create(new InputSource(in), vars);
- } catch (Exception e) {
- throw new RuntimeException("Cannot read configuration", e);
- } finally {
- IOUtils.closeQuietly(in);
- IOUtils.closeQuietly(propsIn);
+ // local repository
+ if (inMemory && homeDirectory.exists()) {
+ FileUtils.deleteDirectory(homeDirectory);
+ log.warn("Deleted Jackrabbit home directory " + homeDirectory);
+ }
+
+ RepositoryConfig config;
+ InputStream in = configuration.getInputStream();
+ InputStream propsIn = null;
+ try {
+ Properties vars = new Properties();
+ if (variables != null) {
+ propsIn = variables.getInputStream();
+ vars.load(propsIn);
}
+ // override with system properties
+ vars.putAll(System.getProperties());
+ vars.put(RepositoryConfigurationParser.REPOSITORY_HOME_VARIABLE,
+ homeDirectory.getCanonicalPath());
+ config = RepositoryConfig.create(new InputSource(in), vars);
+ } catch (Exception e) {
+ throw new RuntimeException("Cannot read configuration", e);
+ } finally {
+ IOUtils.closeQuietly(in);
+ IOUtils.closeQuietly(propsIn);
+ }
- if (inMemory)
- repository = new TransientRepository(config);
- else
- repository = RepositoryImpl.create(config);
+ if (inMemory)
+ repository = new TransientRepository(config);
+ else
+ repository = RepositoryImpl.create(config);
- log.info("Initialized Jackrabbit repository " + repository + " in "
- + homeDirectory + " with config " + configuration);
+ importNodeTypeDefinitions(repository);
+
+ log.info("Initialized Jackrabbit repository " + repository + " in "
+ + homeDirectory + " with config " + configuration);
+ }
+
+ /**
+ * Import declared node type definitions, trying to update them if they have
+ * changed. In case of failures an error will be logged but no exception
+ * will be thrown.
+ */
+ protected void importNodeTypeDefinitions(final Repository repository) {
+ if (systemExecutor == null) {
+ log.warn("No system executor found");
+ return;
}
+
+ systemExecutor.execute(new Runnable() {
+ public void run() {
+ Reader reader = null;
+ Session session = null;
+ try {
+ session = repository.login();
+ // Load cnds as resources
+ for (String resUrl : cndFiles) {
+ Resource res = resourceLoader.getResource(resUrl);
+ byte[] arr = IOUtils.toByteArray(res.getInputStream());
+ reader = new InputStreamReader(
+ new ByteArrayInputStream(arr));
+ CndImporter.registerNodeTypes(reader, session, true);
+ }
+ session.save();
+ } catch (Exception e) {
+ log.error(
+ "Cannot import node type definitions " + cndFiles,
+ e);
+ JcrUtils.discardQuietly(session);
+ } finally {
+ IOUtils.closeQuietly(reader);
+ JcrUtils.logoutQuietly(session);
+ }
+ }
+ });
+
}
public void destroy() throws Exception {
try {
NamespaceHelper namespaceHelper = new NamespaceHelper(session);
namespaceHelper.registerNamespaces(namespaces);
-
- for (byte[] arr : cnds)
- CndImporter.registerNodeTypes(new InputStreamReader(
- new ByteArrayInputStream(arr)), session, true);
} catch (Exception e) {
throw new ArgeoException("Cannot process new session", e);
}
this.uri = uri;
}
+ public void setSystemExecutor(Executor systemExecutor) {
+ this.systemExecutor = systemExecutor;
+ }
+
}
+++ /dev/null
-package org.argeo.jackrabbit.remote;
-
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.Map;
-
-import javax.jcr.Credentials;
-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;
-
-public class CachingSessionProvider implements SessionProvider {
- private static final String JCR_SESSIONS_ATTRIBUTE = "jcrSessions";
-
- private final static Log log = LogFactory
- .getLog(CachingSessionProvider.class);
-
- private Credentials credentials = null;
-
- public CachingSessionProvider() {
- }
-
- public CachingSessionProvider(Credentials credentials) {
- this.credentials = credentials;
- }
-
- @SuppressWarnings("unchecked")
- public Session getSession(HttpServletRequest request, Repository rep,
- String workspace) throws LoginException, ServletException,
- RepositoryException {
- HttpSession httpSession = request.getSession();
-
- if (httpSession.getAttribute(JCR_SESSIONS_ATTRIBUTE) == null) {
- httpSession
- .setAttribute(JCR_SESSIONS_ATTRIBUTE, Collections
- .synchronizedMap(new HashMap<String, Session>()));
- }
- Map<String, Session> sessions = (Map<String, Session>) httpSession
- .getAttribute(JCR_SESSIONS_ATTRIBUTE);
- if (!sessions.containsKey(workspace)) {
- Session session = rep.login(credentials, workspace);
- sessions.put(workspace, session);
- return session;
- } else {
- Session session = sessions.get(workspace);
- if (!session.isLive()) {
- sessions.remove(workspace);
- session = rep.login(credentials, workspace);
- sessions.put(workspace, session);
- }
- return session;
- }
- }
-
- public void releaseSession(Session session) {
- if (log.isDebugEnabled())
- log.debug("Releasing JCR session " + session);
- // session.logout();
- // FIXME: find a way to log out when the HTTP session is expired
- }
-
-}
protected void service(HttpServletRequest request,
HttpServletResponse response) throws ServletException,
java.io.IOException {
+
// see http://forum.springsource.org/showthread.php?t=53472
try {
if (log.isTraceEnabled())
import javax.servlet.http.HttpServlet;
public class JcrRemotingHandlerMapping extends AbstractJackrabbitHandlerMapping {
+
protected HttpServlet createServlet(Repository repository, String pathPrefix)
throws ServletException {
JcrRemotingServlet servlet = new JcrRemotingServlet(repository,
import java.util.HashMap;
import java.util.Map;
-import javax.jcr.Credentials;
import javax.jcr.LoginException;
import javax.jcr.Repository;
import javax.jcr.RepositoryException;
private transient Map<String, Session> sessions;
- private Credentials credentials = null;
-
public Session getSession(HttpServletRequest request, Repository rep,
String workspace) throws LoginException, ServletException,
RepositoryException {
-
- // since sessions is transient it can be restored from the session
+ // 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 {
- Session session = rep.login(credentials, workspace);
- if (log.isDebugEnabled())
- log.debug("User " + session.getUserID() + " logged into "
+ Session session = rep.login(null, workspace);
+ if (log.isTraceEnabled())
+ log.trace("User " + session.getUserID() + " logged into "
+ request.getServletPath());
sessions.put(workspace, session);
return session;
Session session = sessions.get(workspace);
if (!session.isLive()) {
sessions.remove(workspace);
- session = rep.login(credentials, workspace);
+ session = rep.login(null, workspace);
sessions.put(workspace, session);
}
return session;
}
HttpServlet remotingServlet = (HttpServlet) applicationContext
.getBean(beanName);
- return new HandlerExecutionChain(remotingServlet);
+ HandlerExecutionChain hec = new HandlerExecutionChain(remotingServlet);
+ return hec;
}
/** The repository name is the first part of the path info */
return initParameters.keys();
}
}
-
}
/** JCR types in the http://www.argeo.org/argeo namespace */
public interface ArgeoTypes {
public final static String ARGEO_LINK = "argeo:link";
- public final static String ARGEO_HOME = "argeo:home";
public final static String ARGEO_USER_HOME = "argeo:userHome";
}
import javax.jcr.nodetype.NodeType;
import javax.jcr.query.Query;
import javax.jcr.query.QueryResult;
+import javax.jcr.query.qom.Constraint;
+import javax.jcr.query.qom.DynamicOperand;
+import javax.jcr.query.qom.QueryObjectModelFactory;
+import javax.jcr.query.qom.Selector;
+import javax.jcr.query.qom.StaticOperand;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
public class JcrUtils implements ArgeoJcrConstants {
private final static Log log = LogFactory.getLog(JcrUtils.class);
+ /** Prevents instantiation */
+ private JcrUtils() {
+ }
+
/**
* Queries one single node.
*
+ uri, e);
}
}
+
+ /**
+ * Discards the current changes in a session by calling
+ * {@link Session#refresh(boolean)} with <code>false</code>, only logging
+ * potential errors when doing so. To be used typically in a catch block.
+ */
+ public static void discardQuietly(Session session) {
+ try {
+ if (session != null)
+ session.refresh(false);
+ } catch (RepositoryException e) {
+ log.warn("Cannot quietly discard session " + session + ": "
+ + e.getMessage());
+ }
+ }
+
+ /** Logs out the session, not throwing any exception, even if it is null. */
+ public static void logoutQuietly(Session session) {
+ if (session != null)
+ session.logout();
+ }
+
+ /** Returns the home node of the session user or null if none was found. */
+ public static Node getUserHome(Session session) {
+ String userID = session.getUserID();
+ return getUserHome(session, userID);
+ }
+
+ /**
+ * Returns the home node of the session user or null if none was found.
+ *
+ * @param session
+ * the session to use in order to perform the search, this can be
+ * a session with a different user ID than the one searched,
+ * typically when a system or admin session is used.
+ * @param userID
+ * the id of the user
+ */
+ public static Node getUserHome(Session session, String userID) {
+ try {
+ QueryObjectModelFactory qomf = session.getWorkspace()
+ .getQueryManager().getQOMFactory();
+
+ // query the user home for this user id
+ Selector userHomeSel = qomf.selector(ArgeoTypes.ARGEO_USER_HOME,
+ "userHome");
+ DynamicOperand userIdDop = qomf.propertyValue("userHome",
+ ArgeoNames.ARGEO_USER_ID);
+ StaticOperand userIdSop = qomf.literal(session.getValueFactory()
+ .createValue(userID));
+ Constraint constraint = qomf.comparison(userIdDop,
+ QueryObjectModelFactory.JCR_OPERATOR_EQUAL_TO, userIdSop);
+ Query query = qomf.createQuery(userHomeSel, constraint, null, null);
+ Node userHome = JcrUtils.querySingleNode(query);
+ return userHome;
+ } catch (RepositoryException e) {
+ throw new ArgeoException("Cannot find home for user " + userID, e);
+ }
+ }
}