[maven-scm] copy for tag org.apache.sling.jcr.contentloader-2.0.6
git-svn-id: https://svn.apache.org/repos/asf/sling/tags/org.apache.sling.jcr.contentloader-2.0.6@909520 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/NOTICE b/NOTICE
index 4543b0a..85d221f 100644
--- a/NOTICE
+++ b/NOTICE
@@ -1,5 +1,5 @@
Apache Sling Initial Content Loader
-Copyright 2008-2009 The Apache Software Foundation
+Copyright 2008-2010 The Apache Software Foundation
Apache Sling is based on source code originally developed
by Day Software (http://www.day.com/).
diff --git a/pom.xml b/pom.xml
index 582e49c..ae95f18 100644
--- a/pom.xml
+++ b/pom.xml
@@ -90,29 +90,38 @@
<artifactId>org.osgi.compendium</artifactId>
</dependency>
<dependency>
+ <groupId>javax.jcr</groupId>
+ <artifactId>jcr</artifactId>
+ </dependency>
+ <dependency>
<groupId>org.apache.sling</groupId>
<artifactId>org.apache.sling.jcr.api</artifactId>
- <version>2.0.2-incubator</version>
+ <version>2.0.6</version>
+ <scope>provided</scope>
</dependency>
<dependency>
<groupId>org.apache.sling</groupId>
<artifactId>org.apache.sling.commons.json</artifactId>
<version>2.0.2-incubator</version>
+ <scope>provided</scope>
</dependency>
<dependency>
<groupId>org.apache.sling</groupId>
<artifactId>org.apache.sling.commons.mime</artifactId>
<version>2.0.2-incubator</version>
+ <scope>provided</scope>
</dependency>
<dependency>
<groupId>org.apache.sling</groupId>
<artifactId>org.apache.sling.commons.osgi</artifactId>
<version>2.0.2-incubator</version>
+ <scope>provided</scope>
</dependency>
<dependency>
<groupId>org.apache.sling</groupId>
<artifactId>org.apache.sling.engine</artifactId>
<version>2.0.6</version>
+ <scope>provided</scope>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
@@ -134,6 +143,7 @@
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>1.4</version>
+ <scope>provided</scope>
</dependency>
<!-- Testing -->
<dependency>
@@ -150,11 +160,13 @@
<groupId>org.apache.jackrabbit</groupId>
<artifactId>jackrabbit-api</artifactId>
<version>1.5.0</version>
+ <scope>provided</scope>
</dependency>
<dependency>
<groupId>org.apache.sling</groupId>
<artifactId>org.apache.sling.jcr.base</artifactId>
<version>2.0.4-incubator</version>
+ <scope>provided</scope>
</dependency>
</dependencies>
</project>
diff --git a/src/main/java/org/apache/sling/jcr/contentloader/internal/ContentLoaderService.java b/src/main/java/org/apache/sling/jcr/contentloader/internal/ContentLoaderService.java
index 0ce1039..24d6e35 100644
--- a/src/main/java/org/apache/sling/jcr/contentloader/internal/ContentLoaderService.java
+++ b/src/main/java/org/apache/sling/jcr/contentloader/internal/ContentLoaderService.java
@@ -35,7 +35,6 @@
import javax.jcr.Value;
import javax.jcr.lock.LockException;
-import org.apache.jackrabbit.util.Text;
import org.apache.sling.commons.mime.MimeTypeService;
import org.apache.sling.engine.SlingSettingsService;
import org.apache.sling.jcr.api.SlingRepository;
@@ -79,7 +78,7 @@
private static final String PROP_PASSWORD_DIGEST_ALGORITHM = "password.digest.algorithm";
private static final String DEFAULT_PASSWORD_DIGEST_ALGORITHM = "sha1";
private String passwordDigestAlgoritm = null;
-
+
/** default log */
final Logger log = LoggerFactory.getLogger(getClass());
@@ -221,7 +220,7 @@
try {
StringBuffer password = new StringBuffer();
password.append("{").append(passwordDigestAlgoritm).append("}");
- password.append(Text.digest(passwordDigestAlgoritm,
+ password.append(DefaultContentCreator.digest(passwordDigestAlgoritm,
pwd.getBytes("UTF-8")));
return password.toString();
} catch (NoSuchAlgorithmException e) {
@@ -230,7 +229,7 @@
throw new IllegalArgumentException(e.toString());
}
}
-
+
// ---------- SCR Integration ---------------------------------------------
/** Activates this component, called by SCR before registering as a service */
@@ -247,7 +246,7 @@
} else {
passwordDigestAlgoritm = DEFAULT_PASSWORD_DIGEST_ALGORITHM;
}
-
+
Session session = null;
try {
session = this.getSession();
diff --git a/src/main/java/org/apache/sling/jcr/contentloader/internal/DefaultContentCreator.java b/src/main/java/org/apache/sling/jcr/contentloader/internal/DefaultContentCreator.java
index 18a483c..d9efe3a 100644
--- a/src/main/java/org/apache/sling/jcr/contentloader/internal/DefaultContentCreator.java
+++ b/src/main/java/org/apache/sling/jcr/contentloader/internal/DefaultContentCreator.java
@@ -20,6 +20,7 @@
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
+import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.Principal;
import java.text.ParseException;
@@ -57,7 +58,6 @@
import org.apache.jackrabbit.api.security.user.Group;
import org.apache.jackrabbit.api.security.user.User;
import org.apache.jackrabbit.api.security.user.UserManager;
-import org.apache.jackrabbit.util.Text;
import org.apache.sling.jcr.base.util.AccessControlUtil;
/**
@@ -333,7 +333,11 @@
node.setProperty(name, value, propertyType);
}
} else {
- node.setProperty(name, value, propertyType);
+ if (propertyType == PropertyType.UNDEFINED) {
+ node.setProperty(name, value);
+ } else {
+ node.setProperty(name, value, propertyType);
+ }
}
}
@@ -780,7 +784,7 @@
*/
protected String hashPath(String item) throws RepositoryException {
try {
- String hash = Text.digest("sha1", INSTANCE_SEED + item, "UTF-8");
+ String hash = digest("sha1", (INSTANCE_SEED + item).getBytes("UTF-8"));
StringBuilder sb = new StringBuilder();
for (int i = 0; i < STORAGE_LEVELS; i++) {
sb.append(hash, i * 2, (i * 2) + 2).append("/");
@@ -813,16 +817,24 @@
AccessControlManager accessControlManager = AccessControlUtil.getAccessControlManager(session);
AccessControlList updatedAcl = null;
- AccessControlPolicyIterator applicablePolicies = accessControlManager.getApplicablePolicies(resourcePath);
- while (applicablePolicies.hasNext()) {
- AccessControlPolicy policy = applicablePolicies.nextAccessControlPolicy();
- if (policy instanceof AccessControlList) {
- updatedAcl = (AccessControlList)policy;
- break;
- }
+ AccessControlPolicy[] policies = accessControlManager.getPolicies(resourcePath);
+ for (AccessControlPolicy policy : policies) {
+ if (policy instanceof AccessControlList) {
+ updatedAcl = (AccessControlList)policy;
+ break;
+ }
}
if (updatedAcl == null) {
- throw new RepositoryException("Unable to find an access conrol policy to update.");
+ AccessControlPolicyIterator applicablePolicies = accessControlManager.getApplicablePolicies(resourcePath);
+ while (applicablePolicies.hasNext()) {
+ AccessControlPolicy policy = applicablePolicies.nextAccessControlPolicy();
+ if (policy instanceof AccessControlList) {
+ updatedAcl = (AccessControlList)policy;
+ }
+ }
+ }
+ if (updatedAcl == null) {
+ throw new RepositoryException("Unable to find or create an access control policy to update for " + resourcePath);
}
Set<String> postedPrivilegeNames = new HashSet<String>();
@@ -869,12 +881,14 @@
//add a fresh ACE with the granted privileges
List<Privilege> grantedPrivilegeList = new ArrayList<Privilege>();
- for (String name : grantedPrivilegeNames) {
- if (name.length() == 0) {
- continue; //empty, skip it.
- }
- Privilege privilege = accessControlManager.privilegeFromName(name);
- grantedPrivilegeList.add(privilege);
+ if (grantedPrivilegeNames != null) {
+ for (String name : grantedPrivilegeNames) {
+ if (name.length() == 0) {
+ continue; //empty, skip it.
+ }
+ Privilege privilege = accessControlManager.privilegeFromName(name);
+ grantedPrivilegeList.add(privilege);
+ }
}
//add the privileges that should be preserved
grantedPrivilegeList.addAll(preserveGrantedPrivileges);
@@ -888,13 +902,14 @@
if (!authorizable.isGroup()) {
//add a fresh ACE with the denied privileges
List<Privilege> deniedPrivilegeList = new ArrayList<Privilege>();
- for (String name : deniedPrivilegeNames) {
- if (name.length() == 0) {
- continue; //empty, skip it.
- }
- Privilege privilege = accessControlManager.privilegeFromName(name);
- deniedPrivilegeList.add(privilege);
-
+ if (deniedPrivilegeNames != null) {
+ for (String name : deniedPrivilegeNames) {
+ if (name.length() == 0) {
+ continue; //empty, skip it.
+ }
+ Privilege privilege = accessControlManager.privilegeFromName(name);
+ deniedPrivilegeList.add(privilege);
+ }
}
//add the privileges that should be preserved
deniedPrivilegeList.addAll(preserveDeniedPrivileges);
@@ -906,4 +921,33 @@
accessControlManager.setPolicy(resourcePath, updatedAcl);
}
+
+ /**
+ * used for the md5
+ */
+ private static final char[] hexTable = "0123456789abcdef".toCharArray();
+
+ /**
+ * Digest the plain string using the given algorithm.
+ *
+ * @param algorithm The alogrithm for the digest. This algorithm must be
+ * supported by the MessageDigest class.
+ * @param data the data to digest with the given algorithm
+ * @return The digested plain text String represented as Hex digits.
+ * @throws java.security.NoSuchAlgorithmException if the desired algorithm is not supported by
+ * the MessageDigest class.
+ */
+ public static String digest(String algorithm, byte[] data)
+ throws NoSuchAlgorithmException {
+
+ MessageDigest md = MessageDigest.getInstance(algorithm);
+ byte[] digest = md.digest(data);
+ StringBuffer res = new StringBuffer(digest.length * 2);
+ for (int i = 0; i < digest.length; i++) {
+ byte b = digest[i];
+ res.append(hexTable[(b >> 4) & 15]);
+ res.append(hexTable[b & 15]);
+ }
+ return res.toString();
+ }
}
diff --git a/src/main/java/org/apache/sling/jcr/contentloader/internal/readers/JsonReader.java b/src/main/java/org/apache/sling/jcr/contentloader/internal/readers/JsonReader.java
index a357d42..1e65518 100644
--- a/src/main/java/org/apache/sling/jcr/contentloader/internal/readers/JsonReader.java
+++ b/src/main/java/org/apache/sling/jcr/contentloader/internal/readers/JsonReader.java
@@ -42,39 +42,39 @@
* The <code>JsonReader</code> Parses a Json document on content load and creates the
* corresponding node structure with properties. Will not update protected nodes and
* properties like rep:Policy and children.
- *
+ *
* <pre>
* Nodes, Properties and in fact complete subtrees may be described in JSON files
* using the following skeleton structure (see http://www.json.org for information
* on the syntax of JSON) :
- *
+ *
* # the name of the node is taken from the name of the file without the .json ext.
* {
- *
+ *
* # optional primary node type, default "nt:unstructured"
* "jcr:primaryType":"sling:ScriptedComponent",
* # optional mixin node types as array
* "jcr:mixinTypes": [ ],
- *
- *
+ *
+ *
* # "properties" are added as key value pairs, the name of the key being the name
- * # of the property. The value is either the string property value, array for
- * # multi-values or an object whose value[s] property denotes the property
+ * # of the property. The value is either the string property value, array for
+ * # multi-values or an object whose value[s] property denotes the property
* # value(s) and whose type property denotes the property type
* "sling:contentClass": "com.day.sling.jcr.test.Test",
* "sampleMulti": [ "v1", "v2" ],
* "sampleStruct": 1,
* "sampleStructMulti": [ 1, 2, 3 ],
- *
+ *
* # reference properties start with jcr:reference
* "jcr:reference:sampleReference": "/test/content",
- *
+ *
* # path propertie start with jcr:path
* "jcr:path:sampleReference": "/test/path",
- *
- * # nested nodes are added as nested maps.
+ *
+ * # nested nodes are added as nested maps.
* "sling:scripts": {
- *
+ *
* "jcr:primaryType": "sling:ScriptList",
* "script1" :{
* "primaryNodeType": "sling:Script",
@@ -84,7 +84,7 @@
* }
* }
* }
- *
+ *
* </pre>
*/
public class JsonReader implements ContentReader {
@@ -104,7 +104,7 @@
ignoredNames.add("jcr:checkedOut");
ignoredNames.add("jcr:created");
}
-
+
private static final Set<String> ignoredPrincipalPropertyNames = new HashSet<String>();
static {
ignoredPrincipalPropertyNames.add("name");
@@ -239,7 +239,7 @@
}
// fall back to default
- return PropertyType.STRING;
+ return PropertyType.UNDEFINED;
}
protected String getName(String name) {
@@ -278,8 +278,8 @@
return new String(bos.toByteArray(), encoding);
}
-
-
+
+
/**
* Create or update one or more user and/or groups
* <code>
@@ -313,7 +313,7 @@
}
}
}
-
+
/**
* Create or update a user or group
*/
@@ -349,11 +349,11 @@
contentCreator.createUser(name, password, extraProps);
}
}
-
+
/**
* Create or update one or more access control entries for the current
* node.
- *
+ *
* <code>
* {
* "security:acl" : [
@@ -372,8 +372,8 @@
* "jcr:read",
* "jcr:write"
* ]
- * }
- * ]
+ * }
+ * ]
* }
* </code>
*/
@@ -395,14 +395,14 @@
}
}
}
-
+
/**
* Create or update an access control entry
*/
protected void createAce(JSONObject ace, ContentCreator contentCreator)
throws JSONException, RepositoryException {
String principalID = ace.getString("principal");
-
+
String [] grantedPrivileges = null;
JSONArray granted = ace.optJSONArray("granted");
if (granted != null) {
@@ -420,9 +420,9 @@
deniedPrivileges[a] = denied.getString(a);
}
}
-
+
//do the work.
contentCreator.createAce(principalID, grantedPrivileges, deniedPrivileges);
- }
-
+ }
+
}
diff --git a/src/main/java/org/apache/sling/jcr/contentloader/internal/readers/XmlReader.java b/src/main/java/org/apache/sling/jcr/contentloader/internal/readers/XmlReader.java
index 4f16bd6..8cd74e1 100644
--- a/src/main/java/org/apache/sling/jcr/contentloader/internal/readers/XmlReader.java
+++ b/src/main/java/org/apache/sling/jcr/contentloader/internal/readers/XmlReader.java
@@ -156,10 +156,10 @@
/**
- * @see org.apache.sling.jcr.contentloader.internal.ContentReader#parse(java.net.URL, org.apache.sling.jcr.contentloader.internal.ContentCreator)
+ * @see org.apache.sling.jcr.contentloader.internal.ContentReader#parse(URL, org.apache.sling.jcr.contentloader.internal.ContentCreator)
*/
- public synchronized void parse(java.net.URL url, ContentCreator creator)
- throws IOException, RepositoryException {
+ public synchronized void parse(final URL url, final ContentCreator creator)
+ throws IOException, RepositoryException {
BufferedInputStream bufferedInput = null;
try {
// We need to buffer input, so that we can reset the stream if we encounter an XSL stylesheet reference
@@ -172,8 +172,11 @@
}
}
- private void parseInternal(InputStream bufferedInput, ContentCreator creator, java.net.URL xmlLocation) throws XmlPullParserException, IOException, RepositoryException {
- final StringBuffer contentBuffer = new StringBuffer();
+ private void parseInternal(final InputStream bufferedInput,
+ final ContentCreator creator,
+ final URL xmlLocation)
+ throws XmlPullParserException, IOException, RepositoryException {
+ final StringBuilder contentBuffer = new StringBuilder();
// Mark the beginning of the stream. We assume that if there's an XSL processing instruction,
// it will occur in the first gulp - which makes sense, as processing instructions must be
// specified before the root elemeent of an XML file.
@@ -223,7 +226,7 @@
} else if (ELEM_FILE_NAME.equals(currentElement) && ELEM_FILE_NAMESPACE.equals(this.xmlParser.getNamespace())) {
int attributeCount = this.xmlParser.getAttributeCount();
if (attributeCount < 2 || attributeCount > 3) {
- throw new IOException("File element must have these attributes: url, mimeType and lastModified");
+ throw new IOException("File element must have these attributes: url, mimeType and lastModified: " + xmlLocation);
}
try {
AttributeMap attributes = AttributeMap.getInstance();
@@ -232,7 +235,7 @@
FileDescription.SHARED.setValues(attributes);
attributes.clear();
} catch (ParseException e) {
- IOException ioe = new IOException("Error parsing file description");
+ IOException ioe = new IOException("Error parsing file description: " + xmlLocation);
ioe.initCause(e);
throw ioe;
}
@@ -257,12 +260,21 @@
}
} else if (ELEM_VALUE.equals(qName)) {
+ if ( currentProperty == null ) {
+ throw new IOException("XML file does not seem to contain valid content xml. Unexpected " + ELEM_VALUE + " element in : " + xmlLocation);
+ }
currentProperty.addValue(content);
} else if (ELEM_VALUES.equals(qName)) {
+ if ( currentProperty == null ) {
+ throw new IOException("XML file does not seem to contain valid content xml. Unexpected " + ELEM_VALUE + " element in : " + xmlLocation);
+ }
currentProperty.isMultiValue = true;
} else if (ELEM_TYPE.equals(qName)) {
+ if ( currentProperty == null ) {
+ throw new IOException("XML file does not seem to contain valid content xml. Unexpected " + ELEM_VALUE + " element in : " + xmlLocation);
+ }
currentProperty.type = content;
} else if (ELEM_NODE.equals(qName)) {
@@ -271,13 +283,13 @@
} else if (ELEM_PRIMARY_NODE_TYPE.equals(qName)) {
if ( currentNode == null ) {
- throw new IOException("Element is not allowed at this location: " + qName);
+ throw new IOException("Element is not allowed at this location: " + qName + " in " + xmlLocation);
}
currentNode.primaryNodeType = content;
} else if (ELEM_MIXIN_NODE_TYPE.equals(qName)) {
if ( currentNode == null ) {
- throw new IOException("Element is not allowed at this location: " + qName);
+ throw new IOException("Element is not allowed at this location: " + qName + " in " + xmlLocation);
}
currentNode.addMixinType(content);
}
@@ -321,7 +333,7 @@
* @throws IOException
*/
public void startTransform() throws IOException {
- final URL xslResource = new java.net.URL(xmlLocation, this.xslHref);
+ final URL xslResource = new URL(xmlLocation, this.xslHref);
/*
if (xslResource == null) {
diff --git a/src/main/resources/META-INF/NOTICE b/src/main/resources/META-INF/NOTICE
index da7213c..7ee7fe7 100644
--- a/src/main/resources/META-INF/NOTICE
+++ b/src/main/resources/META-INF/NOTICE
@@ -1,5 +1,5 @@
Apache Sling Initial Content Loader
-Copyright 2008-2009 The Apache Software Foundation
+Copyright 2008-2010 The Apache Software Foundation
Apache Sling is based on source code originally developed
by Day Software (http://www.day.com/).
diff --git a/src/test/java/org/apache/sling/jcr/contentloader/internal/JsonReaderTest.java b/src/test/java/org/apache/sling/jcr/contentloader/internal/JsonReaderTest.java
index e7916d1..ad90a46 100644
--- a/src/test/java/org/apache/sling/jcr/contentloader/internal/JsonReaderTest.java
+++ b/src/test/java/org/apache/sling/jcr/contentloader/internal/JsonReaderTest.java
@@ -127,7 +127,7 @@
this.mockery.checking(new Expectations() {{
allowing(creator).createNode(null, null, null); inSequence(mySequence);
- allowing(creator).createProperty("property", PropertyType.STRING, ""); inSequence(mySequence);
+ allowing(creator).createProperty("property", PropertyType.UNDEFINED, ""); inSequence(mySequence);
allowing(creator).finishNode(); inSequence(mySequence);
}});
this.parse(json);
@@ -138,7 +138,7 @@
this.mockery.checking(new Expectations() {{
allowing(creator).createNode(null, null, null); inSequence(mySequence);
- allowing(creator).createProperty("p1", PropertyType.STRING, "v1"); inSequence(mySequence);
+ allowing(creator).createProperty("p1", PropertyType.UNDEFINED, "v1"); inSequence(mySequence);
allowing(creator).finishNode(); inSequence(mySequence);
}});
this.parse(json);
@@ -160,8 +160,8 @@
this.mockery.checking(new Expectations() {{
allowing(creator).createNode(null, null, null); inSequence(mySequence);
- allowing(creator).createProperty("p1", PropertyType.STRING, "v1"); inSequence(mySequence);
- allowing(creator).createProperty("p2", PropertyType.STRING, "v2"); inSequence(mySequence);
+ allowing(creator).createProperty("p1", PropertyType.UNDEFINED, "v1"); inSequence(mySequence);
+ allowing(creator).createProperty("p2", PropertyType.UNDEFINED, "v2"); inSequence(mySequence);
allowing(creator).finishNode(); inSequence(mySequence);
}});
this.parse(json);
@@ -172,7 +172,7 @@
this.mockery.checking(new Expectations() {{
allowing(creator).createNode(null, null, null); inSequence(mySequence);
- allowing(creator).createProperty("p1", PropertyType.STRING, new String[] {"v1"}); inSequence(mySequence);
+ allowing(creator).createProperty("p1", PropertyType.UNDEFINED, new String[] {"v1"}); inSequence(mySequence);
allowing(creator).finishNode(); inSequence(mySequence);
}});
this.parse(json);
@@ -253,14 +253,14 @@
this.mockery.checking(new Expectations() {{
allowing(creator).createNode(null, null, null); inSequence(mySequence);
allowing(creator).createNode("c1", null, null); inSequence(mySequence);
- allowing(creator).createProperty("c1p1", PropertyType.STRING, "v1");
+ allowing(creator).createProperty("c1p1", PropertyType.UNDEFINED, "v1");
allowing(creator).finishNode(); inSequence(mySequence);
allowing(creator).finishNode(); inSequence(mySequence);
}});
this.parse(json);
}
-
-
+
+
@org.junit.Test public void testCreateAcl() throws Exception {
String json = " { " +
"\"security:acl\" : [ " +
@@ -279,10 +279,10 @@
" \"denied\" : [\"jcr:write\"]" +
" }" +
"]" +
- "}";
+ "}";
this.mockery.checking(new Expectations() {{
allowing(creator).createNode(null, null, null); inSequence(mySequence);
-
+
allowing(creator).createAce("username1",new String[]{"jcr:read","jcr:write"},new String[]{}); inSequence(mySequence);
allowing(creator).createAce("groupname1",new String[]{"jcr:read","jcr:write"},null); inSequence(mySequence);
allowing(creator).createAce("groupname2",new String[]{"jcr:read"},new String[]{"jcr:write"}); inSequence(mySequence);