You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sling.apache.org by ro...@apache.org on 2017/11/07 09:49:32 UTC
[sling-org-apache-sling-jcr-repoinit] 05/17: SLING-5842,
SLING-5843 - implement the register namespace and nodetype
operations in the jcr.repoinit module
This is an automated email from the ASF dual-hosted git repository.
rombert pushed a commit to annotated tag org.apache.sling.jcr.repoinit-1.0.2
in repository https://gitbox.apache.org/repos/asf/sling-org-apache-sling-jcr-repoinit.git
commit 552a1314e7881c9aad130248a5999cd542ec183d
Author: Bertrand Delacretaz <bd...@apache.org>
AuthorDate: Tue Jul 19 15:54:38 2016 +0000
SLING-5842, SLING-5843 - implement the register namespace and nodetype operations in the jcr.repoinit module
git-svn-id: https://svn.apache.org/repos/asf/sling/trunk/bundles/jcr/repoinit@1753399 13f79535-47bb-0310-9956-ffa450edef68
---
.../sling/jcr/repoinit/impl/DoNothingVisitor.java | 87 ++++++++++++++++++++++
.../repoinit/impl/JcrRepoInitOpsProcessorImpl.java | 19 ++++-
.../sling/jcr/repoinit/impl/NamespacesVisitor.java | 48 ++++++++++++
.../sling/jcr/repoinit/impl/NodetypesVisitor.java | 49 ++++++++++++
...ationVisitor.java => ServiceAndAclVisitor.java} | 29 ++------
.../sling/jcr/repoinit/ExecutionOrderTest.java | 71 ++++++++++++++++++
.../sling/jcr/repoinit/RegisterNamespacesTest.java | 70 +++++++++++++++++
.../sling/jcr/repoinit/RegisterNodetypesTest.java | 69 +++++++++++++++++
.../apache/sling/jcr/repoinit/impl/TestUtil.java | 27 ++++++-
9 files changed, 440 insertions(+), 29 deletions(-)
diff --git a/src/main/java/org/apache/sling/jcr/repoinit/impl/DoNothingVisitor.java b/src/main/java/org/apache/sling/jcr/repoinit/impl/DoNothingVisitor.java
new file mode 100644
index 0000000..3c4d08c
--- /dev/null
+++ b/src/main/java/org/apache/sling/jcr/repoinit/impl/DoNothingVisitor.java
@@ -0,0 +1,87 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.sling.jcr.repoinit.impl;
+
+import javax.jcr.Session;
+
+import org.apache.sling.repoinit.parser.operations.CreatePath;
+import org.apache.sling.repoinit.parser.operations.CreateServiceUser;
+import org.apache.sling.repoinit.parser.operations.DeleteServiceUser;
+import org.apache.sling.repoinit.parser.operations.OperationVisitor;
+import org.apache.sling.repoinit.parser.operations.RegisterNamespace;
+import org.apache.sling.repoinit.parser.operations.RegisterNodetypes;
+import org.apache.sling.repoinit.parser.operations.SetAclPaths;
+import org.apache.sling.repoinit.parser.operations.SetAclPrincipals;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/** Base class for specialized OperationVisitors.
+ */
+class DoNothingVisitor implements OperationVisitor {
+
+ protected final Logger log = LoggerFactory.getLogger(getClass());
+
+ protected final Session session;
+
+ /** Create a visitor using the supplied JCR Session.
+ * @param s must have sufficient rights to create users
+ * and set ACLs.
+ */
+ protected DoNothingVisitor(Session s) {
+ session = s;
+ }
+
+ protected void report(Exception e, String message) {
+ throw new RuntimeException(message, e);
+ }
+
+ protected static String excerpt(String s, int maxLength) {
+ if(s.length() < maxLength) {
+ return s;
+ } else {
+ return s.substring(0, maxLength -1) + "...";
+ }
+ }
+
+ @Override
+ public void visitCreateServiceUser(CreateServiceUser s) {
+ }
+
+ @Override
+ public void visitDeleteServiceUser(DeleteServiceUser s) {
+ }
+
+ @Override
+ public void visitSetAclPrincipal(SetAclPrincipals s) {
+ }
+
+ @Override
+ public void visitSetAclPaths(SetAclPaths s) {
+ }
+
+ @Override
+ public void visitCreatePath(CreatePath cp) {
+ }
+
+ @Override
+ public void visitRegisterNamespace(RegisterNamespace rn) {
+ }
+
+ @Override
+ public void visitRegisterNodetypes(RegisterNodetypes rn) {
+ }
+}
diff --git a/src/main/java/org/apache/sling/jcr/repoinit/impl/JcrRepoInitOpsProcessorImpl.java b/src/main/java/org/apache/sling/jcr/repoinit/impl/JcrRepoInitOpsProcessorImpl.java
index 4b633d2..bcf96b7 100644
--- a/src/main/java/org/apache/sling/jcr/repoinit/impl/JcrRepoInitOpsProcessorImpl.java
+++ b/src/main/java/org/apache/sling/jcr/repoinit/impl/JcrRepoInitOpsProcessorImpl.java
@@ -24,15 +24,28 @@ import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.Service;
import org.apache.sling.jcr.repoinit.JcrRepoInitOpsProcessor;
import org.apache.sling.repoinit.parser.operations.Operation;
+import org.apache.sling.repoinit.parser.operations.OperationVisitor;
/** Apply Operations produced by the repoinit parser to a JCR Repository */
@Component
@Service(JcrRepoInitOpsProcessor.class)
public class JcrRepoInitOpsProcessorImpl implements JcrRepoInitOpsProcessor {
+
+ /** Apply the supplied operations: first the namespaces and nodetypes
+ * registrations, then the service users, paths and ACLs.
+ */
public void apply(Session session, List<Operation> ops) {
- final JcrRepoInitOperationVisitor v = new JcrRepoInitOperationVisitor(session);
- for(Operation op : ops) {
- op.accept(v);
+
+ final OperationVisitor [] visitors = {
+ new NamespacesVisitor(session),
+ new NodetypesVisitor(session),
+ new ServiceAndAclVisitor(session)
+ };
+
+ for(OperationVisitor v : visitors) {
+ for(Operation op : ops) {
+ op.accept(v);
+ }
}
}
}
diff --git a/src/main/java/org/apache/sling/jcr/repoinit/impl/NamespacesVisitor.java b/src/main/java/org/apache/sling/jcr/repoinit/impl/NamespacesVisitor.java
new file mode 100644
index 0000000..b4d0ebb
--- /dev/null
+++ b/src/main/java/org/apache/sling/jcr/repoinit/impl/NamespacesVisitor.java
@@ -0,0 +1,48 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.sling.jcr.repoinit.impl;
+
+import javax.jcr.NamespaceRegistry;
+import javax.jcr.Session;
+
+import org.apache.sling.repoinit.parser.operations.RegisterNamespace;
+
+/** OperationVisitor which processes only operations related to
+ * namespaces and nodetypes. Having several such specialized visitors
+ * makes it easy to control the execution order.
+ */
+class NamespacesVisitor extends DoNothingVisitor {
+
+ /** Create a visitor using the supplied JCR Session.
+ * @param s must have sufficient rights to create users
+ * and set ACLs.
+ */
+ public NamespacesVisitor(Session s) {
+ super(s);
+ }
+
+ @Override
+ public void visitRegisterNamespace(RegisterNamespace rn) {
+ try {
+ final NamespaceRegistry reg = session.getWorkspace().getNamespaceRegistry();
+ log.info("Registering namespace from {}", rn);
+ reg.registerNamespace(rn.getPrefix(), rn.getURI());
+ } catch(Exception e) {
+ report(e, "Unable to register namespace from " + rn);
+ }
+ }
+}
diff --git a/src/main/java/org/apache/sling/jcr/repoinit/impl/NodetypesVisitor.java b/src/main/java/org/apache/sling/jcr/repoinit/impl/NodetypesVisitor.java
new file mode 100644
index 0000000..e1a4534
--- /dev/null
+++ b/src/main/java/org/apache/sling/jcr/repoinit/impl/NodetypesVisitor.java
@@ -0,0 +1,49 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.sling.jcr.repoinit.impl;
+
+import java.io.StringReader;
+
+import javax.jcr.Session;
+
+import org.apache.jackrabbit.commons.cnd.CndImporter;
+import org.apache.sling.repoinit.parser.operations.RegisterNodetypes;
+
+/** OperationVisitor which processes only operations related to
+ * namespaces and nodetypes. Having several such specialized visitors
+ * makes it easy to control the execution order.
+ */
+class NodetypesVisitor extends DoNothingVisitor {
+
+ /** Create a visitor using the supplied JCR Session.
+ * @param s must have sufficient rights to create users
+ * and set ACLs.
+ */
+ public NodetypesVisitor(Session s) {
+ super(s);
+ }
+
+ @Override
+ public void visitRegisterNodetypes(RegisterNodetypes rn) {
+ try {
+ log.info("Registering nodetypes from {}", excerpt(rn.getCndStatements(), 100));
+ CndImporter.registerNodeTypes(new StringReader(rn.getCndStatements()), session);
+ } catch(Exception e) {
+ report(e, "Unable to register nodetypes from " + rn);
+ }
+ }
+}
diff --git a/src/main/java/org/apache/sling/jcr/repoinit/impl/JcrRepoInitOperationVisitor.java b/src/main/java/org/apache/sling/jcr/repoinit/impl/ServiceAndAclVisitor.java
similarity index 88%
rename from src/main/java/org/apache/sling/jcr/repoinit/impl/JcrRepoInitOperationVisitor.java
rename to src/main/java/org/apache/sling/jcr/repoinit/impl/ServiceAndAclVisitor.java
index 53a2af5..4d71c6b 100644
--- a/src/main/java/org/apache/sling/jcr/repoinit/impl/JcrRepoInitOperationVisitor.java
+++ b/src/main/java/org/apache/sling/jcr/repoinit/impl/ServiceAndAclVisitor.java
@@ -38,23 +38,18 @@ import org.apache.sling.repoinit.parser.operations.SetAclPrincipals;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-/** JCR visitor for the Operations produced by the repoinit parser */
-class JcrRepoInitOperationVisitor implements OperationVisitor {
+/** OperationVisitor which processes only operations related to
+ * service users and ACLs. Having several such specialized visitors
+ * makes it easy to control the execution order.
+ */
+class ServiceAndAclVisitor extends DoNothingVisitor {
- private final Logger log = LoggerFactory.getLogger(getClass());
-
- private Session session;
-
/** Create a visitor using the supplied JCR Session.
* @param s must have sufficient rights to create users
* and set ACLs.
*/
- public JcrRepoInitOperationVisitor(Session s) {
- session = s;
- }
-
- private void report(Exception e, String message) {
- throw new RuntimeException(message, e);
+ public ServiceAndAclVisitor(Session s) {
+ super(s);
}
@Override
@@ -141,14 +136,4 @@ class JcrRepoInitOperationVisitor implements OperationVisitor {
throw new RuntimeException("Session.save failed: "+ e, e);
}
}
-
- @Override
- public void visitRegisterNamespace(RegisterNamespace rn) {
- throw new UnsupportedOperationException(rn.toString());
- }
-
- @Override
- public void visitRegisterNodetypes(RegisterNodetypes b) {
- throw new UnsupportedOperationException(b.getClass().getName());
- }
}
diff --git a/src/test/java/org/apache/sling/jcr/repoinit/ExecutionOrderTest.java b/src/test/java/org/apache/sling/jcr/repoinit/ExecutionOrderTest.java
new file mode 100644
index 0000000..0369d88
--- /dev/null
+++ b/src/test/java/org/apache/sling/jcr/repoinit/ExecutionOrderTest.java
@@ -0,0 +1,71 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.sling.jcr.repoinit;
+
+import static org.junit.Assert.assertEquals;
+import java.util.UUID;
+
+import javax.jcr.Node;
+import javax.jcr.PathNotFoundException;
+import javax.jcr.RepositoryException;
+
+import org.apache.sling.jcr.repoinit.impl.TestUtil;
+import org.apache.sling.repoinit.parser.RepoInitParsingException;
+import org.apache.sling.testing.mock.sling.ResourceResolverType;
+import org.apache.sling.testing.mock.sling.junit.SlingContext;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+
+/** Verify that namespaces and nodetypes are executed before path creation */
+public class ExecutionOrderTest {
+
+ @Rule
+ public final SlingContext context = new SlingContext(ResourceResolverType.JCR_OAK);
+
+ private TestUtil U;
+
+ private static final String TEST_ID = UUID.randomUUID().toString();
+ private static final String NS_PREFIX = ExecutionOrderTest.class.getSimpleName();
+ private static final String NS_URI = "uri:" + NS_PREFIX + ":" + TEST_ID;
+ private static final String REL_PATH = ExecutionOrderTest.class.getSimpleName() + "-" + TEST_ID;
+
+ @Before
+ public void setup() throws RepositoryException, RepoInitParsingException {
+ U = new TestUtil(context);
+
+ final String stmt =
+ "create path (" + NS_PREFIX + ":foo) /" + REL_PATH + "\n"
+ + U.getTestCndStatement(NS_PREFIX, NS_URI) + "\n"
+ + "register namespace (" + NS_PREFIX + ") " + NS_URI + "\n";
+ ;
+
+ U.parseAndExecute(stmt);
+ }
+
+ @After
+ public void cleanup() throws RepositoryException, RepoInitParsingException {
+ U.cleanup();
+ }
+
+ @Test
+ public void pathCreated() throws PathNotFoundException, RepositoryException {
+ final Node n = U.getAdminSession().getNode("/" + REL_PATH);
+ assertEquals(NS_PREFIX + ":foo", n.getProperty("jcr:primaryType").getString());
+ }
+}
\ No newline at end of file
diff --git a/src/test/java/org/apache/sling/jcr/repoinit/RegisterNamespacesTest.java b/src/test/java/org/apache/sling/jcr/repoinit/RegisterNamespacesTest.java
new file mode 100644
index 0000000..03d1df9
--- /dev/null
+++ b/src/test/java/org/apache/sling/jcr/repoinit/RegisterNamespacesTest.java
@@ -0,0 +1,70 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.sling.jcr.repoinit;
+
+import static org.junit.Assert.assertEquals;
+
+import java.util.UUID;
+
+import javax.jcr.NamespaceRegistry;
+import javax.jcr.RepositoryException;
+
+import org.apache.sling.jcr.repoinit.impl.TestUtil;
+import org.apache.sling.repoinit.parser.RepoInitParsingException;
+import org.apache.sling.testing.mock.sling.ResourceResolverType;
+import org.apache.sling.testing.mock.sling.junit.SlingContext;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+
+/** Test register namespace statements */
+public class RegisterNamespacesTest {
+
+ @Rule
+ public final SlingContext context = new SlingContext(ResourceResolverType.JCR_OAK);
+
+ private TestUtil U;
+ private NamespaceRegistry ns;
+
+ private static final String TEST_ID = UUID.randomUUID().toString();
+ private static final String NS1 = "uri:ns:test1:" + TEST_ID;
+ private static final String NS2 = "http://example.com/ns/" + TEST_ID;
+
+ @Before
+ public void setup() throws RepositoryException, RepoInitParsingException {
+ U = new TestUtil(context);
+ U.parseAndExecute("register namespace (one) " + NS1);
+ U.parseAndExecute("register namespace (two) " + NS2);
+ ns = U.getAdminSession().getWorkspace().getNamespaceRegistry();
+ }
+
+ @After
+ public void cleanup() throws RepositoryException, RepoInitParsingException {
+ U.cleanup();
+ }
+
+ @Test
+ public void NS1registered() throws Exception {
+ assertEquals(NS1, ns.getURI("one"));
+ }
+
+ @Test
+ public void NS2registered() throws Exception {
+ assertEquals(NS2, ns.getURI("two"));
+ }
+}
diff --git a/src/test/java/org/apache/sling/jcr/repoinit/RegisterNodetypesTest.java b/src/test/java/org/apache/sling/jcr/repoinit/RegisterNodetypesTest.java
new file mode 100644
index 0000000..8b652d1
--- /dev/null
+++ b/src/test/java/org/apache/sling/jcr/repoinit/RegisterNodetypesTest.java
@@ -0,0 +1,69 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.sling.jcr.repoinit;
+
+import static org.junit.Assert.assertEquals;
+
+import java.util.UUID;
+
+import javax.jcr.NamespaceRegistry;
+import javax.jcr.RepositoryException;
+
+import org.apache.sling.jcr.repoinit.impl.TestUtil;
+import org.apache.sling.repoinit.parser.RepoInitParsingException;
+import org.apache.sling.testing.mock.sling.ResourceResolverType;
+import org.apache.sling.testing.mock.sling.junit.SlingContext;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+
+/** Test register nodetypes statements. Also registers a namespace */
+public class RegisterNodetypesTest {
+
+ @Rule
+ public final SlingContext context = new SlingContext(ResourceResolverType.JCR_OAK);
+
+ private TestUtil U;
+
+ private static final String TEST_ID = UUID.randomUUID().toString();
+ private static final String NS_PREFIX = RegisterNodetypesTest.class.getSimpleName();
+ private static final String NS_URI = "uri:" + NS_PREFIX + ":" + TEST_ID;
+
+ @Before
+ public void setup() throws RepositoryException, RepoInitParsingException {
+ U = new TestUtil(context);
+ U.parseAndExecute("register namespace (" + NS_PREFIX + ") " + NS_URI);
+ U.parseAndExecute(U.getTestCndStatement(NS_PREFIX, NS_URI));
+ }
+
+ @After
+ public void cleanup() throws RepositoryException, RepoInitParsingException {
+ U.cleanup();
+ }
+
+ @Test
+ public void NSregistered() throws Exception {
+ final NamespaceRegistry ns = U.getAdminSession().getWorkspace().getNamespaceRegistry();
+ assertEquals(NS_URI, ns.getURI(NS_PREFIX));
+ }
+
+ @Test
+ public void fooNodetypeRegistered() throws Exception {
+ U.getAdminSession().getRootNode().addNode("test_" + TEST_ID, NS_PREFIX + ":foo");
+ }
+ }
\ No newline at end of file
diff --git a/src/test/java/org/apache/sling/jcr/repoinit/impl/TestUtil.java b/src/test/java/org/apache/sling/jcr/repoinit/impl/TestUtil.java
index 2561ad1..615e5db 100644
--- a/src/test/java/org/apache/sling/jcr/repoinit/impl/TestUtil.java
+++ b/src/test/java/org/apache/sling/jcr/repoinit/impl/TestUtil.java
@@ -93,10 +93,8 @@ public class TestUtil {
}
public void parseAndExecute(String input) throws RepositoryException, RepoInitParsingException {
- final JcrRepoInitOperationVisitor v = new JcrRepoInitOperationVisitor(adminSession);
- for(Operation o : parse(input)) {
- o.accept(v);
- }
+ final JcrRepoInitOpsProcessorImpl p = new JcrRepoInitOpsProcessorImpl();
+ p.apply(adminSession, parse(input));
adminSession.save();
}
@@ -109,4 +107,25 @@ public class TestUtil {
final SimpleCredentials cred = new SimpleCredentials(serviceUsername, new char[0]);
return adminSession.impersonate(cred);
}
+
+ public Session getAdminSession() {
+ return adminSession;
+ }
+
+ public void cleanup() {
+ adminSession.logout();
+ }
+
+ public String getTestCndStatement(String nsPrefix, String nsURI) throws RepositoryException, RepoInitParsingException {
+ return "register nodetypes\n"
+ + "<<===\n"
+ + getTestCND(nsPrefix, nsURI)
+ + "===>>\n"
+ ;
+ }
+
+ public String getTestCND(String nsPrefix, String nsURI) {
+ return "<" + nsPrefix + "='" + nsURI + "'>\n"
+ + "[" + nsPrefix + ":foo] > nt:unstructured\n";
+ }
}
--
To stop receiving notification emails like this one, please contact
"commits@sling.apache.org" <co...@sling.apache.org>.