incubator-sling-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From i..@apache.org
Subject svn commit: r794635 - in /sling/trunk: bundles/jcr/contentloader/ bundles/jcr/contentloader/src/main/java/org/apache/sling/jcr/contentloader/internal/ bundles/jcr/contentloader/src/main/java/org/apache/sling/jcr/contentloader/internal/readers/ bundles/...
Date Thu, 16 Jul 2009 11:33:43 GMT
Author: ieb
Date: Thu Jul 16 11:33:43 2009
New Revision: 794635

URL: http://svn.apache.org/viewvc?rev=794635&view=rev
Log:
SLING-981
Patch from Eric Norman applied, thanks.
  Issues was first created by myself (ieb), but the patch represented a vast improvement on
the orriginal contribution.
  This commit adds the ability to specify ACE's in the json file that would have previously
only modified properties
  on the node. In addition it allows the creation of new principals to allow the ACE's to
be added to the node.

Modified:
    sling/trunk/bundles/jcr/contentloader/pom.xml
    sling/trunk/bundles/jcr/contentloader/src/main/java/org/apache/sling/jcr/contentloader/internal/ContentCreator.java
    sling/trunk/bundles/jcr/contentloader/src/main/java/org/apache/sling/jcr/contentloader/internal/ContentLoaderService.java
    sling/trunk/bundles/jcr/contentloader/src/main/java/org/apache/sling/jcr/contentloader/internal/ContentReader.java
    sling/trunk/bundles/jcr/contentloader/src/main/java/org/apache/sling/jcr/contentloader/internal/DefaultContentCreator.java
    sling/trunk/bundles/jcr/contentloader/src/main/java/org/apache/sling/jcr/contentloader/internal/readers/JsonReader.java
    sling/trunk/bundles/jcr/contentloader/src/test/java/org/apache/sling/jcr/contentloader/internal/JsonReaderTest.java
    sling/trunk/bundles/jcr/contentloader/src/test/java/org/apache/sling/jcr/contentloader/internal/readers/XmlReaderTest.java
    sling/trunk/launchpad/bundles/pom.xml

Modified: sling/trunk/bundles/jcr/contentloader/pom.xml
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/jcr/contentloader/pom.xml?rev=794635&r1=794634&r2=794635&view=diff
==============================================================================
--- sling/trunk/bundles/jcr/contentloader/pom.xml (original)
+++ sling/trunk/bundles/jcr/contentloader/pom.xml Thu Jul 16 11:33:43 2009
@@ -144,5 +144,17 @@
             <groupId>org.jmock</groupId>
             <artifactId>jmock-junit4</artifactId>
         </dependency>
+        
+        <!-- for security content loader (users/groups/acls) -->
+        <dependency>
+            <groupId>org.apache.jackrabbit</groupId>
+            <artifactId>jackrabbit-api</artifactId>
+            <version>1.5.0</version>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.sling</groupId>
+            <artifactId>org.apache.sling.jcr.base</artifactId>
+            <version>2.0.4-incubator</version>
+        </dependency>
     </dependencies>
 </project>

Modified: sling/trunk/bundles/jcr/contentloader/src/main/java/org/apache/sling/jcr/contentloader/internal/ContentCreator.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/jcr/contentloader/src/main/java/org/apache/sling/jcr/contentloader/internal/ContentCreator.java?rev=794635&r1=794634&r2=794635&view=diff
==============================================================================
--- sling/trunk/bundles/jcr/contentloader/src/main/java/org/apache/sling/jcr/contentloader/internal/ContentCreator.java
(original)
+++ sling/trunk/bundles/jcr/contentloader/src/main/java/org/apache/sling/jcr/contentloader/internal/ContentCreator.java
Thu Jul 16 11:33:43 2009
@@ -19,6 +19,7 @@
 package org.apache.sling.jcr.contentloader.internal;
 
 import java.io.InputStream;
+import java.util.Map;
 
 import javax.jcr.RepositoryException;
 
@@ -132,4 +133,37 @@
      */
     boolean switchCurrentNode(String subPath, String newNodeType)
     throws RepositoryException;
+    
+    
+    /**
+     * Create a User in the jackrabbit UserManager
+     * @param name the name of the user
+     * @param password the password of the user
+     * @param extraProperties extra properties to assign to the created user
+     * @throws RepositoryException
+     */
+    void createUser(String name, String password, Map<String, Object> extraProperties)
+    throws RepositoryException;
+    
+    /**
+     * Create a Group in the jackrabbit UserManager
+     * @param name the name of the group
+     * @param members the members of the group (principal names)
+     * @param extraProperties extra properties to assign to the created group
+     * @throws RepositoryException
+     */
+    void createGroup(String name, String[] members, Map<String, Object> extraProperties)
+    throws RepositoryException;
+    
+    /**
+     * Creates an Access Control Entry for the current node for the specified 
+     *  principal and privileges.
+     * 
+     * @param principal the user or group id for the ACE
+     * @param grantedPrivileges the set of privileges to grant the principal
+     * @param deniedPrivileges the set of privileges to deny the principal (for users only)
+     * @throws RepositoryException
+     */
+    void createAce(String principal, String [] grantedPrivileges, String [] deniedPrivileges
)
+    throws RepositoryException;
 }

Modified: sling/trunk/bundles/jcr/contentloader/src/main/java/org/apache/sling/jcr/contentloader/internal/ContentLoaderService.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/jcr/contentloader/src/main/java/org/apache/sling/jcr/contentloader/internal/ContentLoaderService.java?rev=794635&r1=794634&r2=794635&view=diff
==============================================================================
--- sling/trunk/bundles/jcr/contentloader/src/main/java/org/apache/sling/jcr/contentloader/internal/ContentLoaderService.java
(original)
+++ sling/trunk/bundles/jcr/contentloader/src/main/java/org/apache/sling/jcr/contentloader/internal/ContentLoaderService.java
Thu Jul 16 11:33:43 2009
@@ -18,7 +18,10 @@
  */
 package org.apache.sling.jcr.contentloader.internal;
 
+import java.io.UnsupportedEncodingException;
+import java.security.NoSuchAlgorithmException;
 import java.util.Calendar;
+import java.util.Dictionary;
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.List;
@@ -32,6 +35,7 @@
 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;
@@ -66,6 +70,16 @@
 
     public static final String BUNDLE_CONTENT_NODE = "/var/sling/bundle-content";
 
+    /**
+     * To be used for the encryption. E.g. for passwords in
+     * {@link javax.jcr.SimpleCredentials#getPassword()} SimpleCredentials}
+     * 
+     * @scr.property valueRef="DEFAULT_PASSWORD_DIGEST_ALGORITHM"
+     */
+    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());
 
@@ -196,6 +210,27 @@
         }
     }
 
+    /**
+     * Digest the given password using the configured digest algorithm
+     * 
+     * @param pwd the value to digest
+     * @return the digested value
+     * @throws IllegalArgumentException
+     */
+    protected String digestPassword(String pwd) throws IllegalArgumentException {
+        try {
+            StringBuffer password = new StringBuffer();
+            password.append("{").append(passwordDigestAlgoritm).append("}");
+            password.append(Text.digest(passwordDigestAlgoritm,
+                pwd.getBytes("UTF-8")));
+            return password.toString();
+        } catch (NoSuchAlgorithmException e) {
+            throw new IllegalArgumentException(e.toString());
+        } catch (UnsupportedEncodingException e) {
+            throw new IllegalArgumentException(e.toString());
+        }
+    }
+    
     // ---------- SCR Integration ---------------------------------------------
 
     /** Activates this component, called by SCR before registering as a service */
@@ -205,6 +240,14 @@
 
         componentContext.getBundleContext().addBundleListener(this);
 
+        Dictionary<?, ?> props = componentContext.getProperties();
+        Object propValue = props.get(PROP_PASSWORD_DIGEST_ALGORITHM);
+        if (propValue instanceof String) {
+            passwordDigestAlgoritm = (String) propValue;
+        } else {
+            passwordDigestAlgoritm = DEFAULT_PASSWORD_DIGEST_ALGORITHM;
+        }
+        
         Session session = null;
         try {
             session = this.getSession();
@@ -258,6 +301,7 @@
             this.initialContentLoader.dispose();
             this.initialContentLoader = null;
         }
+        passwordDigestAlgoritm = null;
     }
 
     // ---------- internal helper ----------------------------------------------

Modified: sling/trunk/bundles/jcr/contentloader/src/main/java/org/apache/sling/jcr/contentloader/internal/ContentReader.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/jcr/contentloader/src/main/java/org/apache/sling/jcr/contentloader/internal/ContentReader.java?rev=794635&r1=794634&r2=794635&view=diff
==============================================================================
--- sling/trunk/bundles/jcr/contentloader/src/main/java/org/apache/sling/jcr/contentloader/internal/ContentReader.java
(original)
+++ sling/trunk/bundles/jcr/contentloader/src/main/java/org/apache/sling/jcr/contentloader/internal/ContentReader.java
Thu Jul 16 11:33:43 2009
@@ -31,7 +31,7 @@
 
     /**
      * Read the content from the URL and create the
-     * content throught the provided content creator.
+     * content using the provided content creator.
      * @param url The input stream.
      * @throws IOException
      */

Modified: sling/trunk/bundles/jcr/contentloader/src/main/java/org/apache/sling/jcr/contentloader/internal/DefaultContentCreator.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/jcr/contentloader/src/main/java/org/apache/sling/jcr/contentloader/internal/DefaultContentCreator.java?rev=794635&r1=794634&r2=794635&view=diff
==============================================================================
--- sling/trunk/bundles/jcr/contentloader/src/main/java/org/apache/sling/jcr/contentloader/internal/DefaultContentCreator.java
(original)
+++ sling/trunk/bundles/jcr/contentloader/src/main/java/org/apache/sling/jcr/contentloader/internal/DefaultContentCreator.java
Thu Jul 16 11:33:43 2009
@@ -19,15 +19,22 @@
 package org.apache.sling.jcr.contentloader.internal;
 
 import java.io.InputStream;
+import java.io.UnsupportedEncodingException;
+import java.security.NoSuchAlgorithmException;
+import java.security.Principal;
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.Calendar;
 import java.util.Date;
 import java.util.HashMap;
+import java.util.HashSet;
 import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
+import java.util.Set;
 import java.util.Stack;
 import java.util.StringTokenizer;
+import java.util.Map.Entry;
 
 import javax.jcr.Item;
 import javax.jcr.Node;
@@ -37,13 +44,26 @@
 import javax.jcr.Value;
 import javax.jcr.ValueFactory;
 
+import org.apache.jackrabbit.api.jsr283.security.AccessControlEntry;
+import org.apache.jackrabbit.api.jsr283.security.AccessControlList;
+import org.apache.jackrabbit.api.jsr283.security.AccessControlManager;
+import org.apache.jackrabbit.api.jsr283.security.AccessControlPolicy;
+import org.apache.jackrabbit.api.jsr283.security.AccessControlPolicyIterator;
+import org.apache.jackrabbit.api.jsr283.security.Privilege;
+import org.apache.jackrabbit.api.security.user.Authorizable;
+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;
+
 /**
  * The <code>ContentLoader</code> creates the nodes and properties.
  * @since 2.0.4
  */
 public class DefaultContentCreator implements ContentCreator {
 
-    private PathEntry configuration;
+	private PathEntry configuration;
 
     private final Stack<Node> parentNodeStack = new Stack<Node>();
 
@@ -75,6 +95,16 @@
     private List<String> createdNodes;
 
     /**
+     * A one time use seed to randomize the user location.
+     */
+    private static final long INSTANCE_SEED = System.currentTimeMillis();
+    
+    /**
+     * The number of levels folder used to store a user, could be a configuration option.
+     */
+    private static final int STORAGE_LEVELS = 3;
+    
+    /**
      * Constructor.
      * @param jcrContentHelper Helper class to get the mime type of a file
      */
@@ -603,4 +633,229 @@
         return true;
     }
 
+
+	/* (non-Javadoc)
+	 * @see org.apache.sling.jcr.contentloader.internal.ContentCreator#createGroup(java.lang.String,
java.lang.String[], java.util.Map)
+	 */
+	public void createGroup(final String name, String[] members,
+			Map<String, Object> extraProperties) throws RepositoryException {
+
+		final Node parentNode = this.parentNodeStack.peek();
+		Session session = parentNode.getSession();
+		
+        UserManager userManager = AccessControlUtil.getUserManager(session);
+        Authorizable authorizable = userManager.getAuthorizable(name);
+        if (authorizable == null) {
+            //principal does not exist yet, so create it
+        	Group group = userManager.createGroup(new Principal() {
+                    public String getName() {
+                        return name;
+                    }
+                },
+                hashPath(name));
+        	authorizable = group;
+        } else {
+        	//principal already exists, check to make sure it is the expected type
+        	if (!authorizable.isGroup()) {
+                throw new RepositoryException(
+                        "A user already exists with the requested name: "
+                            + name);
+        	} else {
+        		//group already exists so just update it below        		
+        	}
+        }
+        //update the group members
+        if (members != null) {
+        	Group group = (Group)authorizable;
+        	for (String member : members) {
+        		Authorizable memberAuthorizable = userManager.getAuthorizable(member);
+        		if (memberAuthorizable != null) {
+        			group.addMember(memberAuthorizable);
+        		}
+        	}
+        }
+        if (extraProperties != null) {
+        	ValueFactory valueFactory = session.getValueFactory();
+        	Set<Entry<String, Object>> entrySet = extraProperties.entrySet();
+        	for (Entry<String, Object> entry : entrySet) {
+        		Value value = createValue(valueFactory, entry.getValue());
+        		authorizable.setProperty(name, value);
+			}
+        }
+	}
+
+	/* (non-Javadoc)
+	 * @see org.apache.sling.jcr.contentloader.internal.ContentCreator#createUser(java.lang.String,
java.lang.String, java.util.Map)
+	 */
+	public void createUser(final String name, String password,
+			Map<String, Object> extraProperties) throws RepositoryException {
+		final Node parentNode = this.parentNodeStack.peek();
+		Session session = parentNode.getSession();
+		
+        UserManager userManager = AccessControlUtil.getUserManager(session);
+        Authorizable authorizable = userManager.getAuthorizable(name);
+        if (authorizable == null) {
+            //principal does not exist yet, so create it
+        	String digestedPassword = jcrContentHelper.digestPassword(password);
+        	User user = userManager.createUser(name, 
+        			digestedPassword, 
+        			new Principal() {
+						public String getName() {
+							return name;
+						}
+		        	},
+		        	hashPath(name));
+        	authorizable = user;
+        } else {
+        	//principal already exists, check to make sure it is the expected type
+        	if (authorizable.isGroup()) {
+                throw new RepositoryException(
+                        "A group already exists with the requested name: "
+                            + name);
+        	} else {
+        		//user already exists so just update it below        		
+        	}
+        }
+        if (extraProperties != null) {
+        	ValueFactory valueFactory = session.getValueFactory();
+        	Set<Entry<String, Object>> entrySet = extraProperties.entrySet();
+        	for (Entry<String, Object> entry : entrySet) {
+        		Value value = createValue(valueFactory, entry.getValue());
+        		authorizable.setProperty(name, value);
+			}
+        }
+	}
+	
+	/**
+	 * @param item
+	 * @return a parent path fragment for the item.
+	 */
+	protected String hashPath(String item) throws RepositoryException {
+		try {
+			String hash = Text.digest("sha1", INSTANCE_SEED + item, "UTF-8");
+			StringBuilder sb = new StringBuilder();
+			for (int i = 0; i < STORAGE_LEVELS; i++) {
+				sb.append(hash, i * 2, (i * 2) + 2).append("/");
+			}
+			return sb.toString();
+		} catch (NoSuchAlgorithmException e) {
+			throw new RepositoryException("Unable to hash the path.", e);
+		} catch (UnsupportedEncodingException e) {
+			throw new RepositoryException("Unable to hash the path.", e);
+		}
+	}
+	
+
+    /* (non-Javadoc)
+	 * @see org.apache.sling.jcr.contentloader.internal.ContentCreator#createAce(java.lang.String,
java.lang.String, java.lang.String[], java.lang.String[])
+	 */
+	public void createAce(String principalId,
+			String[] grantedPrivilegeNames, String[] deniedPrivilegeNames)
+			throws RepositoryException {
+		final Node parentNode = this.parentNodeStack.peek();
+		Session session = parentNode.getSession();
+		
+		UserManager userManager = AccessControlUtil.getUserManager(session);
+		Authorizable authorizable = userManager.getAuthorizable(principalId);
+		if (authorizable == null) {
+			throw new RepositoryException("No principal found for id: " + principalId);
+		}
+
+		String resourcePath = parentNode.getPath();
+		
+		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;
+			}
+		}
+		if (updatedAcl == null) {
+			throw new RepositoryException("Unable to find an access conrol policy to update.");
+		}
+
+		Set<String> postedPrivilegeNames = new HashSet<String>();
+		if (grantedPrivilegeNames != null) {
+			postedPrivilegeNames.addAll(Arrays.asList(grantedPrivilegeNames));
+		}
+		if (deniedPrivilegeNames != null) {
+			postedPrivilegeNames.addAll(Arrays.asList(deniedPrivilegeNames));
+		}
+			
+		List<Privilege> preserveGrantedPrivileges = new ArrayList<Privilege>();
+		List<Privilege> preserveDeniedPrivileges = new ArrayList<Privilege>();
+			
+		//keep track of the existing Aces for the target principal
+		AccessControlEntry[] accessControlEntries = updatedAcl.getAccessControlEntries();
+		List<AccessControlEntry> oldAces = new ArrayList<AccessControlEntry>();
+		for (AccessControlEntry ace : accessControlEntries) {
+			if (principalId.equals(ace.getPrincipal().getName())) {
+				oldAces.add(ace);
+
+				boolean isAllow = AccessControlUtil.isAllow(ace);
+				Privilege[] privileges = ace.getPrivileges();
+				for (Privilege privilege : privileges) {
+					String privilegeName = privilege.getName();
+					if (!postedPrivilegeNames.contains(privilegeName)) {
+						//this privilege was not posted, so record the existing state to be 
+						// preserved when the ACE is re-created below
+						if (isAllow) {
+							preserveGrantedPrivileges.add(privilege);
+						} else {
+							preserveDeniedPrivileges.add(privilege);
+						}
+					}
+				}
+			}
+		}
+
+		//remove the old aces
+		if (!oldAces.isEmpty()) {
+			for (AccessControlEntry ace : oldAces) {
+				updatedAcl.removeAccessControlEntry(ace);
+			}
+		}
+			
+		//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);
+		}
+		//add the privileges that should be preserved
+		grantedPrivilegeList.addAll(preserveGrantedPrivileges);
+			
+		if (grantedPrivilegeList.size() > 0) {
+			Principal principal = authorizable.getPrincipal();
+			updatedAcl.addAccessControlEntry(principal, grantedPrivilegeList.toArray(new Privilege[grantedPrivilegeList.size()]));
+		}
+
+		//if the authorizable is a user (not a group) process any denied privileges
+		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);
+
+			}
+			//add the privileges that should be preserved
+			deniedPrivilegeList.addAll(preserveDeniedPrivileges);
+			if (deniedPrivilegeList.size() > 0) {
+				Principal principal = authorizable.getPrincipal();
+				AccessControlUtil.addEntry(updatedAcl, principal, deniedPrivilegeList.toArray(new Privilege[deniedPrivilegeList.size()]),
false);
+			}
+		}
+
+		accessControlManager.setPolicy(resourcePath, updatedAcl);
+	}	
 }

Modified: sling/trunk/bundles/jcr/contentloader/src/main/java/org/apache/sling/jcr/contentloader/internal/readers/JsonReader.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/jcr/contentloader/src/main/java/org/apache/sling/jcr/contentloader/internal/readers/JsonReader.java?rev=794635&r1=794634&r2=794635&view=diff
==============================================================================
--- sling/trunk/bundles/jcr/contentloader/src/main/java/org/apache/sling/jcr/contentloader/internal/readers/JsonReader.java
(original)
+++ sling/trunk/bundles/jcr/contentloader/src/main/java/org/apache/sling/jcr/contentloader/internal/readers/JsonReader.java
Thu Jul 16 11:33:43 2009
@@ -23,6 +23,8 @@
 import java.io.IOException;
 import java.io.InputStream;
 import java.util.HashSet;
+import java.util.LinkedHashMap;
+import java.util.Map;
 import java.util.Set;
 
 import javax.jcr.PropertyType;
@@ -55,6 +57,17 @@
         ignoredNames.add("jcr:checkedOut");
         ignoredNames.add("jcr:created");
     }
+    
+    private static final Set<String> ignoredPrincipalPropertyNames = new HashSet<String>();
+    static {
+    	ignoredPrincipalPropertyNames.add("name");
+    	ignoredPrincipalPropertyNames.add("isgroup");
+    	ignoredPrincipalPropertyNames.add("members");
+    	ignoredPrincipalPropertyNames.add("dynamic");
+    	ignoredPrincipalPropertyNames.add("password");
+    }
+    private static final String SECURITY_PRINCIPLES = "security:principals";
+    private static final String SECURITY_ACL = "security:acl";
 
     public static final ImportProvider PROVIDER = new ImportProvider() {
         private JsonReader jsonReader;
@@ -127,7 +140,11 @@
             // skip well known objects
             if (!ignoredNames.contains(n)) {
                 Object o = obj.get(n);
-                if (o instanceof JSONObject) {
+                if (SECURITY_PRINCIPLES.equals(n)) {
+                	this.createPrincipals(o, contentCreator);
+                } else if (SECURITY_ACL.equals(n)) {
+                	this.createAcl(o, contentCreator);
+                } else if (o instanceof JSONObject) {
                     this.createNode(n, (JSONObject) o, contentCreator);
                 } else {
                     this.createProperty(n, o, contentCreator);
@@ -213,4 +230,151 @@
 
         return new String(bos.toByteArray(), encoding);
     }
+    
+    
+    /**
+     * Create or update one or more user and/or groups
+     *	<code>
+     *  {
+     *     "security:principals" : [
+     *        {
+     *           "name":"owner",
+     *           "isgroup":"true",
+     *           "members":[],
+     *           "dynamic":"true"
+     *        }
+     *     ],
+     *  }
+     *  </code>
+     */
+    protected void createPrincipals(Object obj, ContentCreator contentCreator)
+    throws JSONException, RepositoryException {
+    	if (obj instanceof JSONObject) {
+    		//single principal
+    		createPrincipal((JSONObject)obj, contentCreator);
+    	} else if (obj instanceof JSONArray) {
+    		//array of principals
+    		JSONArray jsonArray = (JSONArray)obj;
+    		for (int i=0; i < jsonArray.length(); i++) {
+    			Object object = jsonArray.get(i);
+    			if (object instanceof JSONObject) {
+    	    		createPrincipal((JSONObject)object, contentCreator);
+    			} else {
+    				throw new JSONException("Unexpected data type in principals array: " + object.getClass().getName());
+    			}
+    		}
+    	}
+    }
+    
+    /**
+     * Create or update a user or group
+     */
+    protected void createPrincipal(JSONObject json, ContentCreator contentCreator)
+    throws JSONException, RepositoryException {
+    	//create a principal
+    	String name = json.getString("name");
+    	boolean isGroup = json.optBoolean("isgroup", false);
+
+    	//collect the extra property names to assign to the new principal
+    	Map<String, Object> extraProps = new LinkedHashMap<String, Object>();
+		JSONArray names = json.names();
+		for(int p=0; p < names.length(); p++) {
+			String propName = names.getString(p);
+			if (!ignoredPrincipalPropertyNames.contains(propName)) {
+    			Object value = json.get(propName);
+    			extraProps.put(propName, value);
+			}
+		}
+
+    	if (isGroup) {
+    		String [] members = null;
+    		JSONArray membersJSONArray = json.optJSONArray("members");
+    		if (membersJSONArray != null) {
+    			members = new String[membersJSONArray.length()];
+    			for (int i=0; i < membersJSONArray.length(); i++) {
+    				members[i] = membersJSONArray.getString(i);
+    			}
+    		}
+    		contentCreator.createGroup(name, members, extraProps);
+    	} else {
+    		String password = json.getString("password");
+    		contentCreator.createUser(name, password, extraProps);
+    	}
+    }
+    
+    /**
+     * Create or update one or more access control entries for the current
+     * node.
+     * 
+     *  <code>
+     *  {
+     *   "security:acl" : [
+     *     	{
+     *     		"principal" : "username1",
+     *     		"granted" : [
+     *      		"jcr:read",
+     *      		"jcr:write"
+     *     		],
+     *     		"denied" : [
+     *     		]
+     *     	},
+     *     	{
+     *     		"principal" : "groupname1",
+     *     		"granted" : [
+     *      		"jcr:read",
+     *      		"jcr:write"
+     *     		]
+     *     	}    
+     *   ]    
+     *  }
+     *  </code>
+     */
+    protected void createAcl(Object obj, ContentCreator contentCreator)
+    throws JSONException, RepositoryException {
+    	if (obj instanceof JSONObject) {
+    		//single ace
+    		createAce((JSONObject)obj, contentCreator);
+    	} else if (obj instanceof JSONArray) {
+    		//array of aces
+    		JSONArray jsonArray = (JSONArray)obj;
+    		for (int i=0; i < jsonArray.length(); i++) {
+    			Object object = jsonArray.get(i);
+    			if (object instanceof JSONObject) {
+    	    		createAce((JSONObject)object, contentCreator);
+    			} else {
+    				throw new JSONException("Unexpected data type in acl array: " + object.getClass().getName());
+    			}
+    		}
+    	}
+    }
+    
+    /**
+     * 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) {
+			grantedPrivileges = new String[granted.length()];
+			for (int a=0; a < granted.length(); a++) {
+				grantedPrivileges[a] = granted.getString(a);
+			}
+		}
+
+		String [] deniedPrivileges = null;
+		JSONArray denied = ace.optJSONArray("denied");
+		if (denied != null) {
+			deniedPrivileges = new String[denied.length()];
+			for (int a=0; a < denied.length(); a++) {
+				deniedPrivileges[a] = denied.getString(a);
+			}
+		}
+		
+		//do the work.
+		contentCreator.createAce(principalID, grantedPrivileges, deniedPrivileges);
+    }    
+    
 }

Modified: sling/trunk/bundles/jcr/contentloader/src/test/java/org/apache/sling/jcr/contentloader/internal/JsonReaderTest.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/jcr/contentloader/src/test/java/org/apache/sling/jcr/contentloader/internal/JsonReaderTest.java?rev=794635&r1=794634&r2=794635&view=diff
==============================================================================
--- sling/trunk/bundles/jcr/contentloader/src/test/java/org/apache/sling/jcr/contentloader/internal/JsonReaderTest.java
(original)
+++ sling/trunk/bundles/jcr/contentloader/src/test/java/org/apache/sling/jcr/contentloader/internal/JsonReaderTest.java
Thu Jul 16 11:33:43 2009
@@ -237,6 +237,37 @@
         }});
         this.parse(json);
     }
+    
+    
+    @org.junit.Test public void testCreateAcl() throws Exception {
+    	String json = " { " +
+    			"\"security:acl\" : [ " +
+    			"  { " +
+    			"    \"principal\" : \"username1\"," +
+    			"    \"granted\" : [\"jcr:read\",\"jcr:write\"]," +
+    			"    \"denied\" : []" +
+    			"  }," +
+    			"  {" +
+    			"    \"principal\" : \"groupname1\"," +
+    			"    \"granted\" : [\"jcr:read\",\"jcr:write\"]" +
+    			"  }," +
+    			"  {" +
+    			"    \"principal\" : \"groupname2\"," +
+    			"    \"granted\" : [\"jcr:read\"]," +
+    			"    \"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);
+            allowing(creator).finishNode(); inSequence(mySequence);
+        }});
+        this.parse(json);
+    }
 
     //---------- internal helper ----------------------------------------------
 

Modified: sling/trunk/bundles/jcr/contentloader/src/test/java/org/apache/sling/jcr/contentloader/internal/readers/XmlReaderTest.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/jcr/contentloader/src/test/java/org/apache/sling/jcr/contentloader/internal/readers/XmlReaderTest.java?rev=794635&r1=794634&r2=794635&view=diff
==============================================================================
--- sling/trunk/bundles/jcr/contentloader/src/test/java/org/apache/sling/jcr/contentloader/internal/readers/XmlReaderTest.java
(original)
+++ sling/trunk/bundles/jcr/contentloader/src/test/java/org/apache/sling/jcr/contentloader/internal/readers/XmlReaderTest.java
Thu Jul 16 11:33:43 2009
@@ -26,6 +26,7 @@
 import java.io.InputStream;
 import java.net.URL;
 import java.util.ArrayList;
+import java.util.Map;
 
 /**
  * 	Test the XmlReader with an XSLT transform
@@ -44,7 +45,7 @@
     @SuppressWarnings("serial")
 	private static class MockContentCreator extends ArrayList<String> implements ContentCreator
{
 
-        public MockContentCreator() {
+		public MockContentCreator() {
         }
 
         public void createNode(String name, String primaryNodeType, String[] mixinNodeTypes)
throws RepositoryException {
@@ -72,5 +73,18 @@
         public boolean switchCurrentNode(String subPath, String newNodeType) throws RepositoryException
{
             return true;
         }
+        
+		public void createAce(String principal,
+				String[] grantedPrivileges, String[] deniedPrivileges)
+				throws RepositoryException {
+		}
+
+		public void createGroup(String name, String[] members,
+				Map<String, Object> extraProperties) throws RepositoryException {
+		}
+
+		public void createUser(String name, String password,
+				Map<String, Object> extraProperties) throws RepositoryException {
+		}
     }
 }

Modified: sling/trunk/launchpad/bundles/pom.xml
URL: http://svn.apache.org/viewvc/sling/trunk/launchpad/bundles/pom.xml?rev=794635&r1=794634&r2=794635&view=diff
==============================================================================
--- sling/trunk/launchpad/bundles/pom.xml (original)
+++ sling/trunk/launchpad/bundles/pom.xml Thu Jul 16 11:33:43 2009
@@ -272,7 +272,7 @@
         <dependency>
             <groupId>org.apache.sling</groupId>
             <artifactId>org.apache.sling.jcr.contentloader</artifactId>
-            <version>2.0.4-incubator</version>
+            <version>2.0.5-SNAPSHOT</version>
             <scope>provided</scope>
         </dependency>
         <dependency>



Mime
View raw message