package service; import javax.jcr.Credentials; import javax.jcr.LoginException; import javax.jcr.RepositoryException; import javax.jcr.Session; import javax.jcr.SimpleCredentials; import org.apache.jackrabbit.core.security.authentication.CryptedSimpleCredentials; import play.libs.F.Function; public abstract class JcrSessionFactory { /** * Get a new admin session. * @returns a new admin session */ public abstract Session newAdminSession(); /** * Get a new session as the Jackrabbit user matching the given credentials. * @param credentials Jackrabbit user credentials * @returns a new session as the provided user */ public Session newUserSession(final Credentials credentials) { try { return impersonate(newAdminSession(), credentials); } catch (RepositoryException e) { throw new RuntimeException(e); } } /** * Perform the given function in an admin session. * @param a function to perform in the admin session * @throws RepositoryException * @returns return value of the function */ public <R> R inSession(Function<Session, R> func) { return inSession(newAdminSession(), func); } /** * Perform the given function in a session with the provided jackrabbit * user ID. The ID will be used to produce credentials for a Jackrabbit User, * which will be used for impersonation of a login. * * Changes will be saved on successful return. * * @param credentials the Jackrabbit credentials to use for impersonation * @param func a function to perform in the user session * @returns return value of the function */ public <R> R inSession(String userId, Function<Session, R> func) { return inSession(new SimpleCredentials(userId, new char[0]), func); } /** * Perform the given function in a session with the provided credentials. * The credentials should come from a Jackrabbit User, and will be used for * impersonation of a login. Changes will be saved on successful return. * * @param credentials the Jackrabbit credentials to use for impersonation * @param func a function to perform in the user session * @returns return value of the function */ public <R> R inSession(Credentials credentials, Function<Session, R> func) { return inSession(newUserSession(credentials), func); } /** * Perform the given function in a session, then close it after saving any * pending changes. * * @param session the JCR session to use * @param func a function to perform in the session * @throws RuntimeException wraps any exception that may have been thrown * @returns return value of the function */ protected <R> R inSession(Session session, Function<Session, R> func) { try { R result = func.apply(session); if (session.isLive() && session.hasPendingChanges()) { session.save(); } return result; } catch (Throwable e) { throw new RuntimeException(e); } finally { if (session.isLive()) { session.logout(); } } } /** * Get session impersonating this user. */ protected Session impersonate(Session session, Credentials creds) throws LoginException, RepositoryException { Credentials usableCreds; { if (creds instanceof CryptedSimpleCredentials) { usableCreds = new SimpleCredentials( ((CryptedSimpleCredentials) creds).getUserID(), new char[0]); } else if (creds instanceof SimpleCredentials) { usableCreds = creds; } else { throw new RuntimeException( "You can't impersonate with those credentials."); } } return session.impersonate(usableCreds); } }