I'm programming my own AccessManager and I have two issues. The first is with actual jacrabbit version 1.0.1. In attached file Dummy.java line 70 there is a comment about this. In the development version this bug is gone.
But a have another bug in the development version of Jackrabbit. This is
a weir error because I can't reproduce it always. But with this code it
raises very often:
for (int i=0; i<100; i++) {
Node n1 = myRoot.addNode("pepe "+i, "nt:hierarchyNode");
}
The exception is thrown in line 93 of MyAccessManager.java. There is a
comment on it. The exception says me that HierarchyManager can't build a
path.
--
Paco Avila <[EMAIL PROTECTED]>
repository2.xml
Description: application/xml
/**
*
*/
package es.git.openkm.test;
import javax.jcr.AccessDeniedException;
import javax.jcr.ItemNotFoundException;
import javax.jcr.NoSuchWorkspaceException;
import javax.jcr.Node;
import javax.jcr.Property;
import javax.jcr.PropertyIterator;
import javax.jcr.RepositoryException;
import javax.jcr.Session;
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.SessionImpl;
import org.apache.jackrabbit.core.security.AMContext;
import org.apache.jackrabbit.core.security.AccessManager;
import org.apache.jackrabbit.core.security.UserPrincipal;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* @author Paco Avila
*
*/
public class MyAccessManager implements AccessManager {
private static Logger log = LoggerFactory.getLogger(MyAccessManager.class);
private Subject subject = null;
private HierarchyManager hierMgr = null;
/*
* (non-Javadoc)
*
* @see org.apache.jackrabbit.core.security.AccessManager#init(org.apache.jackrabbit.core.security.AMContext)
*/
public void init(AMContext context) throws AccessDeniedException, Exception {
log.debug("init(" + context + ")");
subject = context.getSubject();
log.debug("##### "+subject.getPrincipals());
hierMgr = context.getHierarchyManager();
log.debug("init: void");
}
/*
* (non-Javadoc)
*
* @see org.apache.jackrabbit.core.security.AccessManager#close()
*/
public void close() throws Exception {
log.debug("close()");
log.debug("close: void");
}
/*
* (non-Javadoc)
*
* @see org.apache.jackrabbit.core.security.AccessManager#checkPermission(org.apache.jackrabbit.core.ItemId,
* int)
*/
public void checkPermission(ItemId id, int permissions)
throws AccessDeniedException, ItemNotFoundException,
RepositoryException {
log.debug("checkPermission()");
log.debug("checkPermission: void");
}
/*
* (non-Javadoc)
*
* @see org.apache.jackrabbit.core.security.AccessManager#isGranted(org.apache.jackrabbit.core.ItemId,
* int)
*/
public boolean isGranted(ItemId id, int permissions)
throws ItemNotFoundException, RepositoryException {
log.debug("isGranted(" + subject.getPrincipals() + ", " + id + ", "
+ (permissions == AccessManager.READ ? "READ"
: (permissions == AccessManager.WRITE ? "WRITE"
: (permissions == AccessManager.REMOVE ? "REMOVE"
: "NONE"))) + ")");
boolean access = false;
Session systemSession = Dummy.getSystemSession();
NodeId nodeId = null;
log.debug(subject.getPrincipals()+" Item Id: "+id);
// Sometimes I have this error in the next line:
// java.jcr.ItemNotFoundException: failed to build path of ....
log.debug(subject.getPrincipals()+" Item Path: "+hierMgr.getPath(id));
if (subject.getPrincipals().contains(new UserPrincipal(systemSession.getUserID()))) {
// If user is System access is always TRUE to avoid infinite access check loop
access = true;
} else {
if (id instanceof NodeId) {
nodeId = (NodeId) id;
log.debug(subject.getPrincipals()+" This is a NODE");
} else {
PropertyId propertyId = (PropertyId) id;
nodeId = propertyId.getParentId();
log.debug(subject.getPrincipals()+" This is a PROPERTY");
}
Node node = ((SessionImpl) systemSession).getNodeById(nodeId);
log.debug(subject.getPrincipals()+" Node Name: " + node.getPath());
log.debug(subject.getPrincipals()+" Node Type: " + node.getPrimaryNodeType().getName());
if (hierMgr.getPath(nodeId).denotesRoot()) {
// Root node has full access
access = true;
} else {
// Check for user node access
if (permissions == AccessManager.READ) {
for (PropertyIterator pi = node.getProperties(); pi.hasNext(); ) {
Property property = (Property) pi.nextProperty();
log.debug("Property: " + property.getName());
//try { Thread.sleep(250); } catch (Exception e) { e.printStackTrace(); }
}
access = true;
} else if (permissions == AccessManager.WRITE) {
for (PropertyIterator pi = node.getProperties(); pi.hasNext(); ) {
Property property = (Property) pi.nextProperty();
log.debug("Property: " + property.getName());
//try { Thread.sleep(250); } catch (Exception e) { e.printStackTrace(); }
}
access = true;
} else if (permissions == AccessManager.REMOVE) {
for (PropertyIterator pi = node.getProperties(); pi.hasNext(); ) {
Property property = (Property) pi.nextProperty();
log.debug("Property: " + property.getName());
//try { Thread.sleep(250); } catch (Exception e) { e.printStackTrace(); }
}
}
}
}
log.debug(subject.getPrincipals()+" Path: " + hierMgr.getPath(id));
log.debug(subject.getPrincipals()+" isGranted: " + access);
log.debug("--------------------------");
return access;
}
/*
* (non-Javadoc)
*
* @see org.apache.jackrabbit.core.security.AccessManager#canAccess(java.lang.String)
*/
public boolean canAccess(String workspaceName)
throws NoSuchWorkspaceException, RepositoryException {
boolean access = true;
log.debug("canAccess(" + workspaceName + ")");
log.debug("canAccess: " + access);
return access;
}
}
package es.git.openkm.test;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.Calendar;
import javax.jcr.AccessDeniedException;
import javax.jcr.InvalidItemStateException;
import javax.jcr.ItemExistsException;
import javax.jcr.ItemNotFoundException;
import javax.jcr.LoginException;
import javax.jcr.NamespaceException;
import javax.jcr.NoSuchWorkspaceException;
import javax.jcr.Node;
import javax.jcr.NodeIterator;
import javax.jcr.PathNotFoundException;
import javax.jcr.Repository;
import javax.jcr.RepositoryException;
import javax.jcr.Session;
import javax.jcr.SimpleCredentials;
import javax.jcr.UnsupportedRepositoryOperationException;
import javax.jcr.ValueFormatException;
import javax.jcr.Workspace;
import javax.jcr.lock.LockException;
import javax.jcr.nodetype.ConstraintViolationException;
import javax.jcr.nodetype.NoSuchNodeTypeException;
import javax.jcr.query.InvalidQueryException;
import javax.jcr.query.Query;
import javax.jcr.query.QueryManager;
import javax.jcr.query.QueryResult;
import javax.jcr.version.VersionException;
import javax.naming.NamingException;
import org.apache.commons.io.FileUtils;
import org.apache.jackrabbit.core.RepositoryImpl;
import org.apache.jackrabbit.core.config.RepositoryConfig;
import org.apache.jackrabbit.core.jndi.RegistryHelper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class Dummy {
private static Logger log = LoggerFactory.getLogger(Dummy.class);
private static String repHomeDir = "repotest2";
private static Session systemSession = null;
private static Repository repository = null;
public static void main(String[] args) throws NamingException,
RepositoryException, FileNotFoundException {
log.debug("*** DESTROY REPOSITORY ***");
removeRepository();
log.debug("*** CREATE REPOSITORY ***");
createRepository();
log.debug("*** USER LOGIN ***");
Session userSession = login("paco", "pepe");
log.debug("*** GET MY ROOT NODE ***");
Node rootNode = userSession.getRootNode();
Node myRoot = rootNode.getNode("my:root");
log.debug("*** ADD A DOCUMENT NODE ***");
Node fileNode = myRoot.addNode("perico", "nt:file");
// With Jackrabbot 1.0.1 I have always a bug in the next line:
// javax.jcr.PathNotFoundException: /my:root/perico
Node contentNode = fileNode.addNode("jcr:content", "nt:resource");
log.debug("*** ADD DOCUMENT NODE PROPERTIES ***");
log.debug("*** PROPERTIES #1 ***");
contentNode.setProperty("jcr:data", new ByteArrayInputStream("Texto de pruebas".getBytes()));
log.debug("*** PROPERTIES #2 ***");
contentNode.setProperty("jcr:mimeType", "text/plain");
log.debug("*** PROPERTIES #3 ***");
contentNode.setProperty("jcr:lastModified", Calendar.getInstance());
log.debug("*** SERIALIZE THE ADDED NODE ***");
myRoot.save();
for (int i=0; i<100; i++) {
Node n1 = myRoot.addNode("pepe "+i, "nt:hierarchyNode");
}
myRoot.save();
/*
addDocument(session, okmRoot, "documentos/Orden del Temple.txt");
addDocument(session, okmRoot, "documentos/Orden del Temple.pdf");
addDocument(session, okmRoot, "documentos/Orden del Temple.doc");
addDocument(session, okmRoot, "documentos/Orden del Temple.odt");
search(session, "temple");
*/
log.debug("*** SAY BYE ***");
userSession.logout();
getSystemSession().logout();
}
/**
*
*/
private static void removeRepository() {
try {
FileUtils.deleteDirectory(new File(repHomeDir));
} catch (IOException e) {
System.err.println("No previous repo");
}
}
/**
* @return
* @throws NamingException
* @throws RepositoryException
* @throws LoginException
* @throws NoSuchWorkspaceException
*/
public static Session login(String user, String pass) throws NamingException,
RepositoryException, LoginException, NoSuchWorkspaceException {
Repository repository = getRepository();
Session session = repository.login(new SimpleCredentials(user, pass.toCharArray()), null);
log.debug("Session: "+session);
return session;
}
/**
* @return
* @throws RepositoryException
*/
public static Repository getRepository() throws RepositoryException {
if (repository == null) {
// Repository config
String repositoryConfig = "repository2.xml";
String repositoryHome = "repotest2";
RepositoryConfig config = RepositoryConfig.create(repositoryConfig, repositoryHome);
repository = RepositoryImpl.create(config);
log.debug("*** System repository created "+repository);
}
return repository;
}
/**
* @return
* @throws LoginException
* @throws NoSuchWorkspaceException
* @throws RepositoryException
*/
public static Session getSystemSession() throws LoginException, NoSuchWorkspaceException, RepositoryException {
if (systemSession == null) {
// System User Session
systemSession = repository.login(new SimpleCredentials("system", "".toCharArray()), null);
log.debug("*** System user created "+systemSession.getUserID());
}
return systemSession;
}
/**
* @param session
* @return
* @throws NamespaceException
* @throws UnsupportedRepositoryOperationException
* @throws AccessDeniedException
* @throws RepositoryException
* @throws ItemExistsException
* @throws PathNotFoundException
* @throws NoSuchNodeTypeException
* @throws LockException
* @throws VersionException
* @throws ConstraintViolationException
* @throws InvalidItemStateException
*/
public static Node createRepository()
throws NamespaceException, UnsupportedRepositoryOperationException,
AccessDeniedException, RepositoryException, ItemExistsException,
PathNotFoundException, NoSuchNodeTypeException, LockException,
VersionException, ConstraintViolationException,
InvalidItemStateException {
// Initialize repository
Repository repository = getRepository();
Session systemSession = getSystemSession();
// Namespace registration
Workspace ws = systemSession.getWorkspace();
ws.getNamespaceRegistry().registerNamespace("my", "http://www.guia-ubuntu.org/1.0");
// Node creation
Node root = systemSession.getRootNode();
Node okmRoot = root.addNode("my:root", "nt:folder");
okmRoot.addMixin("mix:referenceable");
systemSession.save();
log.info("****** Repository created *******");
return okmRoot;
}
/**
* @param session
* @param okmRoot
* @param fileName
* @throws ItemExistsException
* @throws PathNotFoundException
* @throws NoSuchNodeTypeException
* @throws LockException
* @throws VersionException
* @throws ConstraintViolationException
* @throws RepositoryException
* @throws ValueFormatException
* @throws FileNotFoundException
* @throws AccessDeniedException
* @throws InvalidItemStateException
*/
public static void addDocument(Session session, Node okmRoot,
String fileName) throws ItemExistsException, PathNotFoundException,
NoSuchNodeTypeException, LockException, VersionException,
ConstraintViolationException, RepositoryException,
ValueFormatException, FileNotFoundException, AccessDeniedException,
InvalidItemStateException {
// Add document
Node fileNode = okmRoot.addNode(new File(fileName).getName(), "nt:file");
fileNode.addMixin("mix:referenceable");
fileNode.addMixin("mix:lockable");
fileNode.addMixin("mix:versionable");
Node resNode = fileNode.addNode("jcr:content", "nt:resource");
resNode.setProperty("jcr:mimeType", getMime(fileName));
resNode.setProperty("jcr:data", new FileInputStream(fileName));
resNode.setProperty("jcr:lastModified", Calendar.getInstance());
session.save();
log.info("File '"+fileName+"' added.");
}
/**
* @param fileName
* @return
*/
public static String getMime(String fileName) {
if (fileName.endsWith(".doc")) {
return "application/msword";
} else if (fileName.endsWith(".odt")) {
return "application/vnd.oasis.opendocument.text";
} else if (fileName.endsWith(".pdf")) {
return "application/pdf";
} else if (fileName.endsWith(".txt")) {
return "text/plain";
}
return "application/octect-stream";
}
/**
* @param session
* @param words
* @throws RepositoryException
* @throws InvalidQueryException
* @throws UnsupportedRepositoryOperationException
* @throws ItemNotFoundException
* @throws AccessDeniedException
*/
public static void search(Session session, String words)
throws RepositoryException, InvalidQueryException,
UnsupportedRepositoryOperationException, ItemNotFoundException,
AccessDeniedException {
// Search
String statement = "/jcr:root/my:root//element(*,nt:resource)[jcr:contains(.,'" + words + "')]";
Workspace workspace = session.getWorkspace();
QueryManager queryManager = workspace.getQueryManager();
Query query = queryManager.createQuery(statement, javax.jcr.query.Query.XPATH);
QueryResult result = query.execute();
log.info("Search results:");
for (NodeIterator it = result.getNodes(); it.hasNext();) {
Node sNode = (Node) it.next();
log.info(" * "+sNode.getParent().getName());
}
}
}
