Thanks. I really had to comb the mail list for an answer so I'm posting my code
for others, so they don't have to beat themselves up.
import java.util.logging.Logger;
import java.security.Principal;
import javax.security.auth.Subject;
import org.apache.jackrabbit.core.HierarchyManager;
import org.apache.jackrabbit.core.ItemId;
import org.apache.jackrabbit.core.NodeId;
import org.apache.jackrabbit.core.PropertyId;
import org.apache.jackrabbit.core.RepositoryImpl;
import org.apache.jackrabbit.core.SessionImpl;
import org.apache.jackrabbit.core.config.WorkspaceConfig;
import org.apache.jackrabbit.core.fs.FileSystem;
import org.apache.jackrabbit.core.security.AMContext;
import org.apache.jackrabbit.core.security.AccessManager;
import org.apache.jackrabbit.core.security.AnonymousPrincipal;
import org.apache.jackrabbit.core.security.SystemPrincipal;
import org.apache.jackrabbit.uuid.UUID;
public class MyAccessManager implements AccessManager {
private static final Logger LOGGER =
Logger.getLogger(PLAccessManager.class.getName());
/**
* Subject whose access rights this AccessManager should reflect
*/
protected Subject subject = null;
/**
* hierarchy manager used for ACL-based access control model
*/
protected HierarchyManager hierMgr = null;
/**
*/
protected FileSystem fs = null;
private javax.jcr.Session systemSession = null;
private Principal principal = null;
private boolean initialized = false;
protected boolean system = false;
protected boolean anon = false;
/**
* mailto:[EMAIL PROTECTED]
*/
public void init(AMContext context) throws javax.jcr.AccessDeniedException,
Exception {
if (initialized) {
throw new IllegalStateException("already initialized");
}
this.systemSession = new SystemSession(getRepositoryImpl(),
createSystemSubject(),
getWorkspaceConfig(context.getWorkspaceName()));
this.subject = context.getSubject();
this.hierMgr = context.getHierarchyManager();
this.fs = context.getFileSystem();
this.anon = !subject.getPrincipals(AnonymousPrincipal.class).isEmpty();
this.system = !subject.getPrincipals(SystemPrincipal.class).isEmpty();
// @todo This should be changed to meet your needs
java.util.Set<Principal> principals = subject.getPrincipals(Principal.class);
for (Principal p : principals) {
this.principal = p;
break;
}
this.initialized = true;
}
/**
* mailto:[EMAIL PROTECTED]
*/
public void close() throws Exception {
if (!initialized) {
throw new IllegalStateException("not initialized");
}
this.systemSession.logout();
this.systemSession = null;
this.subject = null;
this.hierMgr = null;
this.fs = null;
this.principal = null;
this.system = false;
this.anon = false;
this.initialized = false;
}
/**
* mailto:[EMAIL PROTECTED]
*/
public boolean canAccess(String workspaceName)
throws javax.jcr.NoSuchWorkspaceException, javax.jcr.RepositoryException
{
if (!initialized) {
throw new IllegalStateException("not initialized");
}
return this.system || this.anon || this.principal != null;
}
/**
* mailto:[EMAIL PROTECTED]
*/
public void checkPermission(ItemId id, int permissions)
throws javax.jcr.AccessDeniedException, javax.jcr.ItemNotFoundException,
javax.jcr.RepositoryException
{
if (!initialized) {
throw new IllegalStateException("not initialized");
}
if (!isGranted(id, permissions)) {
throw new javax.jcr.AccessDeniedException();
}
}
/**
* mailto:[EMAIL PROTECTED]
*/
public boolean isGranted(ItemId id, int permissions)
throws javax.jcr.ItemNotFoundException, javax.jcr.RepositoryException
{
boolean granted = false;
if (!initialized) {
throw new IllegalStateException("not initialized");
}
// The system user can do whatever it needs to
if (this.system) {
granted = true;
}
else if (this.anon && (permissions & this.READ) == this.READ) {
granted = true;
}
else if (this.principal == null) {
throw new IllegalStateException("No principal");
}
else {
NodeId nid = null;
UUID uuid = null;
if (id.denotesNode()) {
nid = (NodeId) id;
} else {
// It's property so get the parent node
PropertyId pid = (PropertyId) id;
nid = pid.getParentId();
}
uuid = nid.getUUID();
// Get the node
javax.jcr.Node n = this.systemSession.getNodeByUUID(uuid.toString());
// Compare permissions
if ((permissions & this.REMOVE) == this.REMOVE) {
// @todo Implement this
}
if ((permissions & this.WRITE) == this.WRITE) {
// @todo Implement this
}
if ((permissions & this.READ) == this.READ) {
// @todo Implement this
}
}
return granted;
}
private Subject createSystemSubject() {
// create subject with SystemPrincipal
java.util.Set principals = new java.util.HashSet();
principals.add(new SystemPrincipal());
Subject subject =
new Subject(true, principals,
java.util.Collections.EMPTY_SET,
java.util.Collections.EMPTY_SET);
return subject;
}
private RepositoryImpl getRepositoryImpl() {
// @todo Implement this
return null;
}
private WorkspaceConfig getWorkspaceConfig(String workspace) {
RepositoryImpl ri = getRepositoryImpl();
WorkspaceConfig wc = ri.getConfig().getWorkspaceConfig(workspace);
return wc;
}
/**
* A system session that allows the access manager to get nodes from the
* repository and by-pass the login module.
*/
private class SystemSession extends SessionImpl {
private SystemSession(RepositoryImpl ri, Subject s, WorkspaceConfig wc)
throws javax.jcr.RepositoryException
{
super(ri, s, wc);
}
/**
* mailto:[EMAIL PROTECTED]
* <p/>
* Overridden in order to create custom access manager
*
* @return access manager for system session
* @throws AccessDeniedException is never thrown
* @throws RepositoryException is never thrown
*/
protected AccessManager createAccessManager(Subject subject,
HierarchyManager hierMgr)
throws javax.jcr.AccessDeniedException, javax.jcr.RepositoryException
{
/*
* use own AccessManager implementation rather than relying on
* configurable AccessManager to handle SystemPrincipal privileges
* correctly and avoid recursive problems (AccessManager creates
* SystemSession which creates AccessManager)
*/
return new SystemAccessManager();
}
private class SystemAccessManager implements AccessManager {
/**
* mailto:[EMAIL PROTECTED]
*
* @throws AccessDeniedException is never thrown
* @throws Exception is never thrown
*/
public void init(AMContext context)
throws javax.jcr.AccessDeniedException, Exception
{
}
/**
* mailto:[EMAIL PROTECTED]
*/
public void close() throws Exception {
}
/**
* mailto:[EMAIL PROTECTED]
*
* @throws AccessDeniedException is never thrown
* @throws ItemNotFoundException is never thrown
* @throws RepositoryException is never thrown
*/
public void checkPermission(ItemId id, int permissions)
throws javax.jcr.AccessDeniedException,
javax.jcr.ItemNotFoundException,
javax.jcr.RepositoryException
{
}
/**
* mailto:[EMAIL PROTECTED]
*
* @return always <code>true</code>
* @throws ItemNotFoundException is never thrown
* @throws RepositoryException is never thrown
*/
public boolean isGranted(ItemId id, int permissions)
throws javax.jcr.ItemNotFoundException,
javax.jcr.RepositoryException
{
// allow everything
return true;
}
/**
* mailto:[EMAIL PROTECTED]
*
* @return always <code>true</code>
* @throws NoSuchWorkspaceException is never thrown
* @throws RepositoryException is never thrown
*/
public boolean canAccess(String workspaceName)
throws javax.jcr.NoSuchWorkspaceException,
javax.jcr.RepositoryException
{
return true;
}
}
}
}
From: Torgeir Veimo
Sent: Wed 8/22/2007 9:06 AM
To: [email protected]
Subject: Re: AccessManager Help?
On Wed, 2007-08-22 at 08:46 -0700, Ashley Martens wrote:
> I'm trying to modify a custom AccessManager by having it check
> properties of the node that is being accessed. However, I can't get to
> the Node from the AccessManager. I know this sounds stupid but how do
> you give the AccessManager a Session?
Either maintain a system session for this purpose, or use a cache with
uuids as keys for those nodes that are protected. Search the mailing
list for examples.
--
-Tor