Skip to content

JCR-5137: Update JCR commons to implement current jackrabbit-api #231

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 12 commits into from
Jul 2, 2025
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -738,6 +738,43 @@ public Node getNodeOrNull(String absPath) throws RepositoryException {
}
}

private static boolean isValidNamespaceName(String namespace) {
// the empty namespace and "internal" are valid as well, otherwise it always contains a colon (as it is a URI)
// compare with RFC 3986, Section 3 (https://datatracker.ietf.org/doc/html/rfc3986#section-3)
return namespace.isEmpty() || namespace.equals(Name.NS_REP_URI) || namespace.contains(":");
}

@Override
public String getExpandedName(Item item) throws RepositoryException {
String name = item.getName();
int pos = name.indexOf(":");
if (pos > 0) {
String prefix = name.substring(0, pos);
String uri = getNamespaceURI(prefix);
if (!isValidNamespaceName(uri)) {
throw new NamespaceException("Cannot determine expanded name for '" + name +
"' as registered namespace name '" + uri + "' is invalid");
}
return "{" + uri + "}" + name.substring(pos + 1);
}
else {
return "{}" + name;
}
}

@Override
public String getExpandedPath(Item item) throws RepositoryException {
StringBuilder result = new StringBuilder();
String name;
do {
result.insert(0, "/" + getExpandedName(item));
item = item.getParent();
name = item.getName();
// walk up to the root
} while (!name.isEmpty());
return result.toString();
}

//--------------------------------------------------------------< Session >
/**
* {@inheritDoc}
Original file line number Diff line number Diff line change
@@ -18,16 +18,21 @@

import org.apache.jackrabbit.test.AbstractJCRTest;
import org.apache.jackrabbit.test.NotExecutableException;
import org.junit.Ignore;

import javax.jcr.GuestCredentials;
import javax.jcr.Item;
import javax.jcr.NamespaceException;
import javax.jcr.Node;
import javax.jcr.Property;
import javax.jcr.RepositoryException;

import java.util.UUID;

import static org.mockito.Mockito.mock;

// Borrowed from org.apache.jackrabbit.oak.jcr.session.JackrabbitSessionTest.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we have a place for a TCK for Jackrabbit JCR Extensions?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe we can add something to jcr-tests - after all, that is not the official TCK - that was copied from it.

// Please keep in sync.

public class JackrabbitSessionTest extends AbstractJCRTest {

private JackrabbitSession s;
@@ -58,7 +63,7 @@ private static void assertEquivalentNode(Node expected, Node result) throws Exce
}

// @Ignore("Jackrabbit does not check cross-Session request")
public void ignoreTestGetParentOrNullSessionMismatch() throws Exception {
public void ignoreGetParentOrNullSessionMismatch() throws Exception {
JackrabbitSession guest = (JackrabbitSession) getHelper().getRepository().login(new GuestCredentials());
try {
guest.getParentOrNull(s.getNode(testRoot));
@@ -70,8 +75,8 @@ public void ignoreTestGetParentOrNullSessionMismatch() throws Exception {
}
}

// @Ignore("Jackrabbit does not verify that the Item was obtained from Jackrabbit")
public void ignoreTestGetParentOrNullImplMismatch() {
// @Ignore("Jackrabbit does not check cross-Session request")
public void ignoreGetParentOrNullImplMismatch() {
try {
Item item = mock(Item.class);
s.getParentOrNull(item);
@@ -80,4 +85,52 @@ public void ignoreTestGetParentOrNullImplMismatch() {
// success
}
}

public void testGetExpandedName() throws RepositoryException {
// empty namespace uri
assertEquals("{}testroot", s.getExpandedName(testRootNode));
Node n = testRootNode.addNode("test:bar");
assertEquals("{http://www.apache.org/jackrabbit/test}bar", s.getExpandedName(n));
// now remap namespace uri - should not affect expanded name
assertEquals("prefix 'test' has unexpected mapping",
"http://www.apache.org/jackrabbit/test", s.getNamespaceURI("test"));
s.setNamespacePrefix("test", "urn:foo");
assertEquals("{http://www.apache.org/jackrabbit/test}bar", s.getExpandedName(n));
// use special namespace uri
n = testRootNode.addNode("rep:bar");
assertEquals("{internal}bar", s.getExpandedName(n));
}

public void testGetExpandedNameBrokenNamespace() throws RepositoryException {
String uuid = UUID.randomUUID().toString();
String randomNamespacePrefix = "prefix-" + uuid;
// below is not a valid namespace a.k.a. namespace URI
String randomNamespaceName = "name-" + uuid;

// register broken namespace prefix/name mapping
s.getWorkspace().getNamespaceRegistry().registerNamespace(randomNamespacePrefix, randomNamespaceName);

try {
Node n = testRootNode.addNode(randomNamespacePrefix + ":qux");

// there is no expanded name, thus we expect an exception here
String result = s.getExpandedName(n);
fail("there is no expanded name in this case, so we expect the call to fail, however we get: " + result);
} catch (NamespaceException ex) {
// expected
}
//finally {
// not supported in Jackrabbit
// s.getWorkspace().getNamespaceRegistry().unregisterNamespace(randomNamespacePrefix);
// }
}

public void testGetExpandedPath() throws RepositoryException {
assertEquals("/{}testroot", s.getExpandedPath(testRootNode));
Node n = testRootNode.addNode("test:bar").addNode("rep:bar");
assertEquals("/{}testroot/{http://www.apache.org/jackrabbit/test}bar/{internal}bar", s.getExpandedPath(n));
// now remap namespace uri - should not affect expanded name
s.setNamespacePrefix("test", "urn:foo");
assertEquals("/{}testroot/{http://www.apache.org/jackrabbit/test}bar/{internal}bar", s.getExpandedPath(n));
}
}
Original file line number Diff line number Diff line change
@@ -1671,6 +1671,16 @@ public Node getNodeOrNull(String absPath) throws RepositoryException {
return null;
}

@Override
public String getExpandedName(Item item) throws UnsupportedRepositoryOperationException {
throw new UnsupportedRepositoryOperationException("see JCR-5137");
}

@Override
public String getExpandedPath(Item item) throws UnsupportedRepositoryOperationException {
throw new UnsupportedRepositoryOperationException("see JCR-5137");
}

public Repository getRepository() {
return null;
}
4 changes: 2 additions & 2 deletions jackrabbit-parent/pom.xml
Original file line number Diff line number Diff line change
@@ -54,8 +54,8 @@
<test.opts.memory>-Xmx256m</test.opts.memory>
<test.opts.modules />
<test.opts>${test.opts.modules} ${test.opts.coverage} ${test.opts.memory} -enableassertions</test.opts>
<!-- OAK version used in componenents that *implement* oak-jackrabbit-api -->
<oak-jackrabbit-api.version.implemented>1.76.0</oak-jackrabbit-api.version.implemented>
<!-- OAK version used in components that *implement* oak-jackrabbit-api -->
<oak-jackrabbit-api.version.implemented>1.80</oak-jackrabbit-api.version.implemented>
<!-- OAK version used in componenents that *use* oak-jackrabbit-api -->
<oak-jackrabbit-api.version.used>1.22.22</oak-jackrabbit-api.version.used>
<jetty.version>9.4.56.v20240826</jetty.version>