jackrabbit-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From ang...@apache.org
Subject svn commit: r1081433 - in /jackrabbit/trunk: jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/ jackrabbit-core/src/test/java/org/apache/jackrabbit/core/security/authorization/ jackrabbit-jcr-commons/src/main/java/org/apac...
Date Mon, 14 Mar 2011 16:00:40 GMT
Author: angela
Date: Mon Mar 14 16:00:40 2011
New Revision: 1081433

URL: http://svn.apache.org/viewvc?rev=1081433&view=rev
Log:
JCR-2887 : Split PrivilegeRegistry in a per-session manager instance and a repository level registry [work in progress]

Added:
    jackrabbit/trunk/jackrabbit-jcr-commons/src/main/java/org/apache/jackrabbit/commons/privilege/
    jackrabbit/trunk/jackrabbit-jcr-commons/src/main/java/org/apache/jackrabbit/commons/privilege/ParseException.java   (with props)
    jackrabbit/trunk/jackrabbit-jcr-commons/src/main/java/org/apache/jackrabbit/commons/privilege/PrivilegeDefinition.java   (with props)
    jackrabbit/trunk/jackrabbit-jcr-commons/src/main/java/org/apache/jackrabbit/commons/privilege/PrivilegeDefinitionReader.java   (with props)
    jackrabbit/trunk/jackrabbit-jcr-commons/src/main/java/org/apache/jackrabbit/commons/privilege/PrivilegeDefinitionWriter.java   (with props)
    jackrabbit/trunk/jackrabbit-jcr-commons/src/main/java/org/apache/jackrabbit/commons/privilege/PrivilegeHandler.java   (with props)
    jackrabbit/trunk/jackrabbit-jcr-commons/src/main/java/org/apache/jackrabbit/commons/privilege/PrivilegeXmlHandler.java   (with props)
Modified:
    jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/PrivilegeManagerImpl.java
    jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/PrivilegeRegistry.java
    jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/security/authorization/PrivilegeRegistryTest.java

Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/PrivilegeManagerImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/PrivilegeManagerImpl.java?rev=1081433&r1=1081432&r2=1081433&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/PrivilegeManagerImpl.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/PrivilegeManagerImpl.java Mon Mar 14 16:00:40 2011
@@ -84,10 +84,10 @@ public final class PrivilegeManagerImpl 
      * @return all registered privileges.
      */
     public Privilege[] getRegisteredPrivileges() throws RepositoryException {
-        PrivilegeRegistry.PrivilegeDefinition[] allDefs = registry.getAll();
+        PrivilegeRegistry.Definition[] allDefs = registry.getAll();
         if (allDefs.length != cache.size()) {
             synchronized (cache) {
-                for (PrivilegeRegistry.PrivilegeDefinition def : allDefs) {
+                for (PrivilegeRegistry.Definition def : allDefs) {
                     if (!cache.containsKey(def.getName())) {
                         cache.put(def.getName(), new PrivilegeImpl(def));
                     }
@@ -204,7 +204,7 @@ public final class PrivilegeManagerImpl 
         int bits = PrivilegeRegistry.NO_PRIVILEGE;
         for (String privName : privilegeNames) {
             try {
-                PrivilegeRegistry.PrivilegeDefinition def = registry.get(resolver.getQName(privName));
+                PrivilegeRegistry.Definition def = registry.get(resolver.getQName(privName));
                 if (def == null) {
                     throw new AccessControlException("Unknown privilege name '" + privName + "'.");
                 } else {
@@ -257,7 +257,7 @@ public final class PrivilegeManagerImpl 
             if (cache.containsKey(name)) {
                 privilege = cache.get(name);
             } else {
-                PrivilegeRegistry.PrivilegeDefinition def = registry.get(name);
+                PrivilegeRegistry.Definition def = registry.get(name);
                 if (def != null) {
                     privilege = new PrivilegeImpl(def);
                     cache.put(name, privilege);
@@ -288,12 +288,12 @@ public final class PrivilegeManagerImpl 
      */
     private class PrivilegeImpl implements Privilege {
 
-        private final PrivilegeRegistry.PrivilegeDefinition definition;
+        private final PrivilegeRegistry.Definition definition;
 
         private final Privilege[] declaredAggregates;
         private final Privilege[] aggregates;
 
-        private PrivilegeImpl(PrivilegeRegistry.PrivilegeDefinition definition) throws RepositoryException {
+        private PrivilegeImpl(PrivilegeRegistry.Definition definition) throws RepositoryException {
             this.definition = definition;
 
             Name[] aggrNames = definition.getDeclaredAggregateNames();

Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/PrivilegeRegistry.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/PrivilegeRegistry.java?rev=1081433&r1=1081432&r2=1081433&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/PrivilegeRegistry.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/PrivilegeRegistry.java Mon Mar 14 16:00:40 2011
@@ -17,6 +17,10 @@
 package org.apache.jackrabbit.core.security.authorization;
 
 import org.apache.commons.collections.map.ReferenceMap;
+import org.apache.jackrabbit.commons.privilege.ParseException;
+import org.apache.jackrabbit.commons.privilege.PrivilegeDefinition;
+import org.apache.jackrabbit.commons.privilege.PrivilegeDefinitionReader;
+import org.apache.jackrabbit.commons.privilege.PrivilegeDefinitionWriter;
 import org.apache.jackrabbit.core.NamespaceRegistryImpl;
 import org.apache.jackrabbit.core.fs.FileSystem;
 import org.apache.jackrabbit.core.fs.FileSystemException;
@@ -35,16 +39,17 @@ import javax.jcr.NamespaceRegistry;
 import javax.jcr.RepositoryException;
 import javax.jcr.security.AccessControlException;
 import javax.jcr.security.Privilege;
-import java.io.BufferedReader;
 import java.io.IOException;
-import java.io.InputStreamReader;
-import java.io.OutputStreamWriter;
-import java.io.Writer;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.Collections;
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.Iterator;
 import java.util.LinkedHashMap;
+import java.util.List;
 import java.util.Map;
 import java.util.Set;
 
@@ -106,7 +111,7 @@ public final class PrivilegeRegistry {
     private static final String CUSTOM_PRIVILEGES_RESOURCE_NAME = "/privileges/custom_privileges.xml";
 
     
-    private final Map<Name, PrivilegeDefinition> registeredPrivileges = new HashMap<Name, PrivilegeDefinition>();
+    private final Map<Name, Definition> registeredPrivileges = new HashMap<Name, Definition>();
     private final Map<Integer, Set<Name>> bitsToNames = new HashMap<Integer, Set<Name>>();
 
     @SuppressWarnings("unchecked")    
@@ -115,9 +120,6 @@ public final class PrivilegeRegistry {
     private final NamespaceRegistry namespaceRegistry;
     private final CustomPrivilegeStore customPrivilegesStore;
 
-    /**
-     * @deprecated For backwards compatibility only.
-     */
     private final NameResolver resolver;
 
     private int nextBits = RETENTION_MNGMT << 1;
@@ -131,12 +133,14 @@ public final class PrivilegeRegistry {
 
         try {
             Map<Name, DefinitionStub> customDefs = customPrivilegesStore.load();
-            Map<Name, PrivilegeDefinition> definitions = createPrivilegeDefinitions(customDefs);
+            Map<Name, Definition> definitions = createPrivilegeDefinitions(customDefs);
             registerDefinitions(definitions);
         } catch (IOException e) {
             throw new RepositoryException("Failed to load custom privileges", e);
         } catch (FileSystemException e) {
             throw new RepositoryException("Failed to load custom privileges", e);
+        } catch (ParseException e) {
+            throw new RepositoryException("Failed to load custom privileges", e);
         }
 
         this.resolver = new DefaultNamePathResolver(namespaceRegistry);
@@ -234,7 +238,7 @@ public final class PrivilegeRegistry {
                 } else if (NameConstants.JCR_WRITE.equals(n)) {
                     bits |= createJcrWriteDefinition().bits;
                 } else if (REP_WRITE_NAME.equals(n)) {
-                    PrivilegeDefinition jcrWrite = createJcrWriteDefinition();
+                    Definition jcrWrite = createJcrWriteDefinition();
                     bits |= createRepWriteDefinition(jcrWrite.bits).bits;
                 } else if (NameConstants.JCR_ALL.equals(n)) {
                     for (Name pn : PRIVILEGE_NAMES.keySet()) {
@@ -371,7 +375,7 @@ public final class PrivilegeRegistry {
         }
         synchronized (registeredPrivileges) {
             Map<Name, DefinitionStub> stubs = Collections.singletonMap(privilegeName, new DefinitionStub(privilegeName, isAbstract, declaredAggregateNames, true));
-            Map<Name, PrivilegeDefinition> definitions = createPrivilegeDefinitions(stubs);
+            Map<Name, Definition> definitions = createPrivilegeDefinitions(stubs);
             try {
                 // write the new custom privilege to the store and upon successful
                 // update of the file system resource add finally it to the map of
@@ -383,6 +387,8 @@ public final class PrivilegeRegistry {
                 throw new RepositoryException("Failed to register custom privilege " + privilegeName.toString(), e);
             } catch (FileSystemException e) {
                 throw new RepositoryException("Failed to register custom privilege " + privilegeName.toString(), e);
+            } catch (ParseException e) {
+                throw new RepositoryException("Failed to register custom privilege " + privilegeName.toString(), e);
             }
         }
 
@@ -396,8 +402,8 @@ public final class PrivilegeRegistry {
      *
      * @return all registered internal privileges
      */
-    PrivilegeDefinition[] getAll() {
-        return registeredPrivileges.values().toArray(new PrivilegeDefinition[registeredPrivileges.size()]);
+    Definition[] getAll() {
+        return registeredPrivileges.values().toArray(new Definition[registeredPrivileges.size()]);
     }
 
     /**
@@ -406,7 +412,7 @@ public final class PrivilegeRegistry {
      * @param name Name of the internal privilege.
      * @return the internal privilege with the specified name or <code>null</code>
      */
-    PrivilegeDefinition get(Name name) {
+    Definition get(Name name) {
         return registeredPrivileges.get(name);
     }
 
@@ -466,7 +472,7 @@ public final class PrivilegeRegistry {
             }
 
             // include matching custom privilege names 
-            for (PrivilegeDefinition def : registeredPrivileges.values()) {
+            for (Definition def : registeredPrivileges.values()) {
                 if (def.isCustom && ((bits & def.bits) == def.bits)) {
                     names.add(def.name);
                 }
@@ -490,25 +496,25 @@ public final class PrivilegeRegistry {
      * 
      * @param definitions
      */
-    private void registerDefinitions(Map<Name, PrivilegeDefinition> definitions) {
+    private void registerDefinitions(Map<Name, Definition> definitions) {
         registeredPrivileges.putAll(definitions);
-        for (PrivilegeDefinition def : definitions.values()) {
+        for (Definition def : definitions.values()) {
             bitsToNames.put(def.bits, Collections.singleton(def.name));
         }
 
         if (!definitions.containsKey(NameConstants.JCR_ALL)) {
             // redefine the jcr:all privilege definition
-            PrivilegeDefinition all = registeredPrivileges.get(NameConstants.JCR_ALL);
+            Definition all = registeredPrivileges.get(NameConstants.JCR_ALL);
 
             Set<Name> allAggrNames = all.declaredAggregateNames;
             allAggrNames.addAll(definitions.keySet());
 
             int allBits = all.bits;
-            for (PrivilegeDefinition def : definitions.values()) {
+            for (Definition def : definitions.values()) {
                 allBits |= def.bits;
             }
 
-            all = new PrivilegeDefinition(NameConstants.JCR_ALL, false, allAggrNames, allBits);
+            all = new Definition(NameConstants.JCR_ALL, false, allAggrNames, allBits);
             registeredPrivileges.put(NameConstants.JCR_ALL, all);
             bitsToNames.put(all.bits, Collections.singleton(NameConstants.JCR_ALL));
         }
@@ -519,24 +525,24 @@ public final class PrivilegeRegistry {
      * 
      * @return definitions for all built-in privileges.
      */
-    private Map<Name,PrivilegeDefinition> createBuiltInPrivilegeDefinitions() {
-        Map<Name, PrivilegeDefinition> defs = new HashMap<Name, PrivilegeDefinition>();
+    private Map<Name, Definition> createBuiltInPrivilegeDefinitions() {
+        Map<Name, Definition> defs = new HashMap<Name, Definition>();
 
         // all non-aggregate privileges
         int jcrAllBits = NO_PRIVILEGE;
         for (Name privilegeName : PRIVILEGE_NAMES.keySet()) {
             int bits = PRIVILEGE_NAMES.get(privilegeName);
-            PrivilegeDefinition def = new PrivilegeDefinition(privilegeName, false, bits);
+            Definition def = new Definition(privilegeName, false, bits);
             defs.put(privilegeName, def);
             jcrAllBits |= bits;
         }
 
         // jcr:write
-        PrivilegeDefinition jcrWrite = createJcrWriteDefinition();
+        Definition jcrWrite = createJcrWriteDefinition();
         defs.put(jcrWrite.name, jcrWrite);
 
         // rep:write
-        PrivilegeDefinition repWrite = createRepWriteDefinition(jcrWrite.bits);
+        Definition repWrite = createRepWriteDefinition(jcrWrite.bits);
         defs.put(repWrite.name, repWrite);
 
         // jcr:all
@@ -552,7 +558,7 @@ public final class PrivilegeRegistry {
         jcrAllAggregates.add(NameConstants.JCR_WRITE);
         jcrAllAggregates.add(REP_WRITE_NAME);
 
-        PrivilegeDefinition jcrAll = new PrivilegeDefinition(NameConstants.JCR_ALL, false, jcrAllAggregates, jcrAllBits);
+        Definition jcrAll = new Definition(NameConstants.JCR_ALL, false, jcrAllAggregates, jcrAllBits);
         defs.put(jcrAll.name, jcrAll);
 
         return defs;
@@ -568,8 +574,8 @@ public final class PrivilegeRegistry {
      * @return new privilege definitions.
      * @throws RepositoryException If any of the specified stubs is invalid.
      */
-    private Map<Name, PrivilegeDefinition> createPrivilegeDefinitions(Map<Name, DefinitionStub> toRegister) throws RepositoryException {
-        Map<Name, PrivilegeDefinition> definitions = new HashMap<Name, PrivilegeDefinition>(toRegister.size());
+    private Map<Name, Definition> createPrivilegeDefinitions(Map<Name, DefinitionStub> toRegister) throws RepositoryException {
+        Map<Name, Definition> definitions = new HashMap<Name, Definition>(toRegister.size());
         Set<DefinitionStub> aggregates = new HashSet<DefinitionStub>();
 
         for (DefinitionStub stub : toRegister.values()) {
@@ -592,7 +598,7 @@ public final class PrivilegeRegistry {
             // validate aggregates
             if (stub.declaredAggregateNames.isEmpty()) {
                 // not an aggregate priv definition.
-                definitions.put(name, new PrivilegeDefinition(stub, nextBits()));
+                definitions.put(name, new Definition(stub, nextBits()));
             } else {
                 for (Name declaredAggregateName : stub.declaredAggregateNames) {
                     if (name.equals(declaredAggregateName)) {
@@ -629,7 +635,7 @@ public final class PrivilegeRegistry {
                     throw new RepositoryException("Custom aggregate privilege '" + stub.name + "' is already covered by '" + existingName.toString() + "'");
                 }
                 if (bts != NO_PRIVILEGE) {
-                    PrivilegeDefinition def = new PrivilegeDefinition(stub, bts);
+                    Definition def = new Definition(stub, bts);
                     definitions.put(def.name, def);
                     itr.remove();
                 }
@@ -660,13 +666,13 @@ public final class PrivilegeRegistry {
      * @param toRegister
      * @return
      */
-    private int getAggregateBits(Set<Name> declaredAggregateNames, Map<Name, PrivilegeDefinition> toRegister) {
+    private int getAggregateBits(Set<Name> declaredAggregateNames, Map<Name, Definition> toRegister) {
         int bts = NO_PRIVILEGE;
         for (Name n : declaredAggregateNames) {
             if (registeredPrivileges.containsKey(n)) {
                 bts |= registeredPrivileges.get(n).bits;
             } else if (toRegister.containsKey(n)) {
-                PrivilegeDefinition def = toRegister.get(n);
+                Definition def = toRegister.get(n);
                 if (def.bits == NO_PRIVILEGE) {
                     // not yet processed dependency -> wait for next iteration.
                     return NO_PRIVILEGE;
@@ -709,7 +715,7 @@ public final class PrivilegeRegistry {
     /**
      * @return PrivilegeDefinition for the jcr:write privilege
      */
-    private static PrivilegeDefinition createJcrWriteDefinition() {
+    private static Definition createJcrWriteDefinition() {
         Set<Name> jcrWriteAggregates = new HashSet<Name>(4);
         jcrWriteAggregates.add(NameConstants.JCR_MODIFY_PROPERTIES);
         jcrWriteAggregates.add(NameConstants.JCR_ADD_CHILD_NODES);
@@ -720,16 +726,16 @@ public final class PrivilegeRegistry {
         for (Name privilegeName : jcrWriteAggregates) {
             jcrWriteBits |= PRIVILEGE_NAMES.get(privilegeName);
         }
-        return new PrivilegeDefinition(NameConstants.JCR_WRITE, false, jcrWriteAggregates, jcrWriteBits);
+        return new Definition(NameConstants.JCR_WRITE, false, jcrWriteAggregates, jcrWriteBits);
     }
 
-    private static PrivilegeDefinition createRepWriteDefinition(int jcrWriteBits) {
+    private static Definition createRepWriteDefinition(int jcrWriteBits) {
         Set<Name> repWriteAggregates = new HashSet<Name>(2);
         repWriteAggregates.add(NameConstants.JCR_WRITE);
         repWriteAggregates.add(NameConstants.JCR_NODE_TYPE_MANAGEMENT);
 
         int repWriteBits = jcrWriteBits | PRIVILEGE_NAMES.get(NameConstants.JCR_NODE_TYPE_MANAGEMENT);
-        return new PrivilegeDefinition(REP_WRITE_NAME, false, repWriteAggregates, repWriteBits);
+        return new Definition(REP_WRITE_NAME, false, repWriteAggregates, repWriteBits);
     }
 
     //--------------------------------------------------------------------------
@@ -799,23 +805,23 @@ public final class PrivilegeRegistry {
     /**
      * Internal definition of a jcr level privilege.
      */
-    static class PrivilegeDefinition extends DefinitionStub {
+    static class Definition extends DefinitionStub {
 
         private final int bits;
 
-        private PrivilegeDefinition(DefinitionStub stub, int bits) {
+        private Definition(DefinitionStub stub, int bits) {
             this(stub.name, stub.isAbstract, stub.declaredAggregateNames, bits, stub.isCustom);
         }
 
-        private PrivilegeDefinition(Name name, boolean isAbstract, int bits) {
+        private Definition(Name name, boolean isAbstract, int bits) {
             this(name, isAbstract, Collections.<Name>emptySet(), bits, false);
         }
 
-        private PrivilegeDefinition(Name name, boolean isAbstract, Set<Name> declaredAggregateNames, int bits) {
+        private Definition(Name name, boolean isAbstract, Set<Name> declaredAggregateNames, int bits) {
             this(name, isAbstract, declaredAggregateNames, bits, false);
         }
 
-        private PrivilegeDefinition(Name name, boolean isAbstract, Set<Name> declaredAggregateNames, int bits, boolean isCustom) {
+        private Definition(Name name, boolean isAbstract, Set<Name> declaredAggregateNames, int bits, boolean isCustom) {
             super(name, isAbstract, declaredAggregateNames, isCustom);
             if (bits == NO_PRIVILEGE) {
                 throw new IllegalArgumentException("Failed to build int representation of PrivilegeDefinition.");
@@ -871,76 +877,79 @@ public final class PrivilegeRegistry {
             }
         }
 
-        private Map<Name, DefinitionStub> load() throws IOException, FileSystemException, RepositoryException {
+        private Map<Name, DefinitionStub> load() throws FileSystemException, RepositoryException, ParseException, IOException {
             Map<Name, DefinitionStub> stubs = new LinkedHashMap<Name, DefinitionStub>();
 
             if (customPrivilegesResource.exists()) {
-                BufferedReader reader = new BufferedReader(new InputStreamReader(customPrivilegesResource.getInputStream(), "utf-8"));
+                InputStream in = customPrivilegesResource.getInputStream();
                 try {
-                    String line;
-                    while ((line = reader.readLine()) != null) {
-                        String[] params = Text.explode(line, ';', true);
-
-                        if (params.length < 1) {
-                            // empty line
-                            continue;
-                        }
+                    PrivilegeDefinitionReader pr = new PrivilegeDefinitionReader(in, "text/xml");
+                    for (PrivilegeDefinition def : pr.getPrivilegeDefinitions()) {
 
-                        Name privName = NAME_FACTORY.create(params[0]);
-                        boolean isAbstract = false;
+                        Name privName = getName(def.getName());
+                        boolean isAbstract = def.isAbstract();
                         Set<Name> declaredAggrNames = new HashSet<Name>();
-
-                        if (params.length >= 2) {
-                            isAbstract = "abstract".equals(params[1]);
-                        }
-                        if (params.length >= 3) {
-                            String[] declExpNames = Text.explode(params[2], ',');
-                            for (String declExpName : declExpNames) {
-                                declaredAggrNames.add(NAME_FACTORY.create(declExpName));
-                            }
+                        for (String dan : def.getDeclaredAggregateNames()) {
+                            declaredAggrNames.add(getName(dan));
                         }
 
                         if (stubs.containsKey(privName)) {
                             throw new RepositoryException("Duplicate entry for custom privilege with name " + privName.toString());
                         }
                         stubs.put(privName, new DefinitionStub(privName, isAbstract, declaredAggrNames, true));
-
                     }
                 } finally {
-                    reader.close();
+                    in.close();
                 }
             }
             return stubs;
         }
 
-        private void append(Map<Name, PrivilegeDefinition> newPrivilegeDefinitions) throws IOException, FileSystemException, RepositoryException {
-            Map<Name, DefinitionStub> defs = load();
-            defs.putAll(newPrivilegeDefinitions);
+        private Name getName(String jcrName) throws RepositoryException {
+            String uri = namespaceRegistry.getURI(Text.getNamespacePrefix(jcrName));
+            return NAME_FACTORY.create(uri, Text.getLocalName(jcrName));
+        }
 
-            Writer writer = new OutputStreamWriter(customPrivilegesResource.getOutputStream(), "utf-8");
-            try {
-                for (DefinitionStub def : defs.values()) {
-                    StringBuilder sb = new StringBuilder();
-                    sb.append(def.name.toString()).append(';');
-                    if (def.isAbstract) {
-                        sb.append("abstract");
-                    }
-                    sb.append(";");
-                    if (!def.declaredAggregateNames.isEmpty()) {
-                        int cnt = 0;
-                        for (Name dan : def.declaredAggregateNames) {
-                            if (cnt > 0) {
-                                sb.append(",");
-                            }
-                            sb.append(dan.toString());
-                            cnt++;
-                        }
-                    }
-                    writer.write(sb.toString());
-                    writer.write("\n");
+        private void append(Map<Name, Definition> newPrivilegeDefinitions) throws IOException, FileSystemException, RepositoryException, ParseException {
+            List<PrivilegeDefinition> jcrDefs;
+            Map<String, String> nsMapping;
+
+            if (customPrivilegesResource.exists()) {
+                InputStream in = customPrivilegesResource.getInputStream();
+                try {
+                    PrivilegeDefinitionReader pr = new PrivilegeDefinitionReader(in, "text/xml");
+                    jcrDefs = new ArrayList<PrivilegeDefinition>(Arrays.asList(pr.getPrivilegeDefinitions()));
+                    nsMapping = pr.getNamespaces();
+                } finally {
+                    in.close();
+                }
+            } else {
+                jcrDefs = new ArrayList<PrivilegeDefinition>();
+                nsMapping = new HashMap<String, String>();
+            }
+
+            for (Definition d : newPrivilegeDefinitions.values()) {
+                String name = resolver.getJCRName(d.name);
+                String uri = d.name.getNamespaceURI();
+                nsMapping.put(namespaceRegistry.getPrefix(uri), uri);
+
+                String[] aggrNames = new String[d.declaredAggregateNames.size()];
+                int i = 0;
+                for (Name dan : d.declaredAggregateNames) {
+                    aggrNames[i++] = resolver.getJCRName(dan);
+                    uri = d.name.getNamespaceURI();
+                    nsMapping.put(namespaceRegistry.getPrefix(uri), uri);
                 }
+                PrivilegeDefinition pd = new PrivilegeDefinition(name, d.isAbstract, aggrNames);
+                jcrDefs.add(pd);
+            }
+
+            OutputStream out = customPrivilegesResource.getOutputStream();
+            try {
+                PrivilegeDefinitionWriter pdw = new PrivilegeDefinitionWriter("text/xml");
+                pdw.writeDefinitions(out, jcrDefs.toArray(new PrivilegeDefinition[jcrDefs.size()]), nsMapping);
             } finally {
-                writer.close();
+                out.close();
             }
         }
     }

Modified: jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/security/authorization/PrivilegeRegistryTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/security/authorization/PrivilegeRegistryTest.java?rev=1081433&r1=1081432&r2=1081433&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/security/authorization/PrivilegeRegistryTest.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/security/authorization/PrivilegeRegistryTest.java Mon Mar 14 16:00:40 2011
@@ -27,7 +27,6 @@ import org.apache.jackrabbit.spi.commons
 import org.apache.jackrabbit.spi.commons.name.NameConstants;
 import org.apache.jackrabbit.test.AbstractJCRTest;
 
-import javax.jcr.NamespaceException;
 import javax.jcr.RepositoryException;
 import javax.jcr.security.AccessControlException;
 import javax.jcr.security.Privilege;
@@ -60,9 +59,9 @@ public class PrivilegeRegistryTest exten
 
     public void testGetAll() throws RepositoryException {
 
-        PrivilegeRegistry.PrivilegeDefinition[] defs = privilegeRegistry.getAll();
+        PrivilegeRegistry.Definition[] defs = privilegeRegistry.getAll();
 
-        List<PrivilegeRegistry.PrivilegeDefinition> l = new ArrayList<PrivilegeRegistry.PrivilegeDefinition>(Arrays.asList(defs));
+        List<PrivilegeRegistry.Definition> l = new ArrayList<PrivilegeRegistry.Definition>(Arrays.asList(defs));
         assertTrue(l.remove(privilegeRegistry.get(NameConstants.JCR_READ)));
         assertTrue(l.remove(privilegeRegistry.get(NameConstants.JCR_ADD_CHILD_NODES)));
         assertTrue(l.remove(privilegeRegistry.get(NameConstants.JCR_REMOVE_CHILD_NODES)));
@@ -85,9 +84,9 @@ public class PrivilegeRegistryTest exten
 
     public void testGet() throws RepositoryException {
 
-        for (PrivilegeRegistry.PrivilegeDefinition def : privilegeRegistry.getAll()) {
+        for (PrivilegeRegistry.Definition def : privilegeRegistry.getAll()) {
 
-            PrivilegeRegistry.PrivilegeDefinition d = privilegeRegistry.get(def.name);
+            PrivilegeRegistry.Definition d = privilegeRegistry.get(def.name);
             assertEquals(def, d);
 
             assertNotNull(d.name);
@@ -107,14 +106,14 @@ public class PrivilegeRegistryTest exten
 
     public void testAggregates() throws RepositoryException {
 
-        for (PrivilegeRegistry.PrivilegeDefinition def : privilegeRegistry.getAll()) {
+        for (PrivilegeRegistry.Definition def : privilegeRegistry.getAll()) {
             if (def.declaredAggregateNames.isEmpty()) {
                 continue; // ignore non aggregate
             }
 
             List<Name> l = Arrays.asList(def.getDeclaredAggregateNames());
             for (Name n : l) {
-                PrivilegeRegistry.PrivilegeDefinition d = privilegeRegistry.get(n);
+                PrivilegeRegistry.Definition d = privilegeRegistry.get(n);
                 assertNotNull(d);
                 Name[] names = privilegeRegistry.getNames(d.getBits());
                 assertNotNull(names);
@@ -126,7 +125,7 @@ public class PrivilegeRegistryTest exten
 
     public void testPrivilegeDefinition() throws RepositoryException {
 
-        for (PrivilegeRegistry.PrivilegeDefinition def : privilegeRegistry.getAll()) {
+        for (PrivilegeRegistry.Definition def : privilegeRegistry.getAll()) {
 
             assertNotNull(def.name);
             assertEquals(def.name, def.getName());
@@ -144,7 +143,7 @@ public class PrivilegeRegistryTest exten
     }
 
     public void testJcrAll() throws RepositoryException {
-        PrivilegeRegistry.PrivilegeDefinition p = privilegeRegistry.get(NameConstants.JCR_ALL);
+        PrivilegeRegistry.Definition p = privilegeRegistry.get(NameConstants.JCR_ALL);
         assertEquals(p.getName(), NameConstants.JCR_ALL);
         assertFalse(p.declaredAggregateNames.isEmpty());
         assertFalse(p.isAbstract());
@@ -165,7 +164,7 @@ public class PrivilegeRegistryTest exten
 
     public void testJcrWrite() throws RepositoryException {
         Name rw = resolver.getQName(PrivilegeRegistry.REP_WRITE);
-        PrivilegeRegistry.PrivilegeDefinition p = privilegeRegistry.get(rw);
+        PrivilegeRegistry.Definition p = privilegeRegistry.get(rw);
 
         assertEquals(p.getName(), rw);
         assertFalse(p.declaredAggregateNames.isEmpty());
@@ -178,7 +177,7 @@ public class PrivilegeRegistryTest exten
     }
 
     public void testRepWrite() throws RepositoryException {
-        PrivilegeRegistry.PrivilegeDefinition p = privilegeRegistry.get(NameConstants.JCR_WRITE);
+        PrivilegeRegistry.Definition p = privilegeRegistry.get(NameConstants.JCR_WRITE);
         assertEquals(p.getName(), NameConstants.JCR_WRITE);
         assertFalse(p.declaredAggregateNames.isEmpty());
         assertFalse(p.isAbstract());
@@ -436,7 +435,7 @@ public class PrivilegeRegistryTest exten
             resource.makeParentDirs();
         }
         StringBuilder sb = new StringBuilder();
-        sb.append("test;;test2\n");
+        sb.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?><privileges><privilege isAbstract=\"false\" name=\"test\"><contains name=\"test2\"/></privilege></privileges>");
 
         Writer writer = new OutputStreamWriter(resource.getOutputStream(), "utf-8");
         writer.write(sb.toString());
@@ -446,7 +445,7 @@ public class PrivilegeRegistryTest exten
         try {
             new PrivilegeRegistry(superuser.getWorkspace().getNamespaceRegistry(), fs);
             fail("Invalid names must be detected upon registry startup.");
-        } catch (IllegalArgumentException e) {
+        } catch (RepositoryException e) {
             // success
         } finally {
             fs.deleteFolder("/privileges");
@@ -537,12 +536,13 @@ public class PrivilegeRegistryTest exten
 
             Map<Name, Set<Name>> newCustomPrivs = new HashMap<Name, Set<Name>>();
             newCustomPrivs.put(resolver.getQName("new"), Collections.<Name>emptySet());
+            newCustomPrivs.put(resolver.getQName("test:new"), Collections.<Name>emptySet());
 
             for (Name name : newCustomPrivs.keySet()) {
                 boolean isAbstract = true;
                 Set<Name> aggrNames = newCustomPrivs.get(name);
                 pr.registerDefinition(name, isAbstract, aggrNames);
-                PrivilegeRegistry.PrivilegeDefinition definition = pr.get(name);
+                PrivilegeRegistry.Definition definition = pr.get(name);
 
                 assertNotNull(definition);
                 assertEquals(name, definition.getName());
@@ -558,7 +558,7 @@ public class PrivilegeRegistryTest exten
 
                 // re-read the filesystem resource and check if definition is correct
                 PrivilegeRegistry registry = new PrivilegeRegistry(superuser.getWorkspace().getNamespaceRegistry(), fs);
-                PrivilegeRegistry.PrivilegeDefinition def = registry.get(name);
+                PrivilegeRegistry.Definition def = registry.get(name);
                 assertEquals(isAbstract, def.isAbstract);
                 assertEquals(aggrNames.size(), def.declaredAggregateNames.size());
                 for (Name n : aggrNames) {
@@ -571,12 +571,13 @@ public class PrivilegeRegistryTest exten
             newAggregates.put(resolver.getQName("newA1"), createNameSet(NameConstants.JCR_READ, NameConstants.JCR_RETENTION_MANAGEMENT));
             // a new aggregate of custom and built-in privilege
             newAggregates.put(resolver.getQName("newA2"), createNameSet(resolver.getQName("new"), NameConstants.JCR_READ));
+            newAggregates.put(resolver.getQName("newA3"), createNameSet(resolver.getQName("test:new"), resolver.getQName("new")));
 
             for (Name name : newAggregates.keySet()) {
                 boolean isAbstract = false;
                 Set<Name> aggrNames = newAggregates.get(name);
                 pr.registerDefinition(name, isAbstract, aggrNames);
-                PrivilegeRegistry.PrivilegeDefinition definition = pr.get(name);
+                PrivilegeRegistry.Definition definition = pr.get(name);
 
                 assertNotNull(definition);
                 assertEquals(name, definition.getName());
@@ -592,7 +593,7 @@ public class PrivilegeRegistryTest exten
 
                 // re-read the filesystem resource and check if definition is correct
                 PrivilegeRegistry registry = new PrivilegeRegistry(superuser.getWorkspace().getNamespaceRegistry(), fs);
-                PrivilegeRegistry.PrivilegeDefinition def = registry.get(name);
+                PrivilegeRegistry.Definition def = registry.get(name);
                 assertEquals(isAbstract, def.isAbstract);
                 assertEquals(isAbstract, def.isAbstract);
                 assertEquals(aggrNames.size(), def.declaredAggregateNames.size());

Added: jackrabbit/trunk/jackrabbit-jcr-commons/src/main/java/org/apache/jackrabbit/commons/privilege/ParseException.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-jcr-commons/src/main/java/org/apache/jackrabbit/commons/privilege/ParseException.java?rev=1081433&view=auto
==============================================================================
--- jackrabbit/trunk/jackrabbit-jcr-commons/src/main/java/org/apache/jackrabbit/commons/privilege/ParseException.java (added)
+++ jackrabbit/trunk/jackrabbit-jcr-commons/src/main/java/org/apache/jackrabbit/commons/privilege/ParseException.java Mon Mar 14 16:00:40 2011
@@ -0,0 +1,31 @@
+/*
+ * 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.jackrabbit.commons.privilege;
+
+/**
+ * <code>ParseException</code>...
+ */
+public class ParseException extends Exception {
+
+    public ParseException(Throwable throwable) {
+        super(throwable);
+    }
+
+    public ParseException(String s, Throwable throwable) {
+        super(s, throwable);
+    }
+}
\ No newline at end of file

Propchange: jackrabbit/trunk/jackrabbit-jcr-commons/src/main/java/org/apache/jackrabbit/commons/privilege/ParseException.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: jackrabbit/trunk/jackrabbit-jcr-commons/src/main/java/org/apache/jackrabbit/commons/privilege/ParseException.java
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision Rev URL

Added: jackrabbit/trunk/jackrabbit-jcr-commons/src/main/java/org/apache/jackrabbit/commons/privilege/PrivilegeDefinition.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-jcr-commons/src/main/java/org/apache/jackrabbit/commons/privilege/PrivilegeDefinition.java?rev=1081433&view=auto
==============================================================================
--- jackrabbit/trunk/jackrabbit-jcr-commons/src/main/java/org/apache/jackrabbit/commons/privilege/PrivilegeDefinition.java (added)
+++ jackrabbit/trunk/jackrabbit-jcr-commons/src/main/java/org/apache/jackrabbit/commons/privilege/PrivilegeDefinition.java Mon Mar 14 16:00:40 2011
@@ -0,0 +1,44 @@
+/*
+ * 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.jackrabbit.commons.privilege;
+
+/**
+ * <code>PrivilegeDefinition</code>
+ */
+public class PrivilegeDefinition {
+    private final String name;
+    private final boolean isAbstract;
+    private final String[] declaredAggregateNames;
+
+    public PrivilegeDefinition(String name, boolean isAbstract, String[] declaredAggregateNames) {
+        this.name = name;
+        this.isAbstract = isAbstract;
+        this.declaredAggregateNames = declaredAggregateNames;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public boolean isAbstract() {
+        return isAbstract;
+    }
+
+    public String[] getDeclaredAggregateNames() {
+        return declaredAggregateNames;
+    }
+}
\ No newline at end of file

Propchange: jackrabbit/trunk/jackrabbit-jcr-commons/src/main/java/org/apache/jackrabbit/commons/privilege/PrivilegeDefinition.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: jackrabbit/trunk/jackrabbit-jcr-commons/src/main/java/org/apache/jackrabbit/commons/privilege/PrivilegeDefinition.java
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision Rev URL

Added: jackrabbit/trunk/jackrabbit-jcr-commons/src/main/java/org/apache/jackrabbit/commons/privilege/PrivilegeDefinitionReader.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-jcr-commons/src/main/java/org/apache/jackrabbit/commons/privilege/PrivilegeDefinitionReader.java?rev=1081433&view=auto
==============================================================================
--- jackrabbit/trunk/jackrabbit-jcr-commons/src/main/java/org/apache/jackrabbit/commons/privilege/PrivilegeDefinitionReader.java (added)
+++ jackrabbit/trunk/jackrabbit-jcr-commons/src/main/java/org/apache/jackrabbit/commons/privilege/PrivilegeDefinitionReader.java Mon Mar 14 16:00:40 2011
@@ -0,0 +1,72 @@
+/*
+ * 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.jackrabbit.commons.privilege;
+
+import java.io.InputStream;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * Reads privilege definitions for the specified <code>InputStream</code>. Note,
+ * that this reader will not apply any validation.
+ */
+public class PrivilegeDefinitionReader {
+
+    private final PrivilegeDefinition[] privilegeDefinitions;
+    private final Map<String, String> namespaces = new HashMap<String, String>();
+
+    /**
+     * Creates a new <code>PrivilegeDefinitionReader</code> for the given
+     * input stream. The specified content type is used in order to determine
+     * the type of privilege serialization.
+     *
+     * @param in The input stream to read the privilege definitions from.
+     * @param contentType Currently only types supported by
+     * {@link PrivilegeXmlHandler#isSupportedContentType(String)PrivilegeXmlHandler}
+     * are allowed.
+     * @throws ParseException If an error occurs.
+     * @throws IllegalArgumentException if the specified content type is not supported.
+     */
+    public PrivilegeDefinitionReader(InputStream in, String contentType) throws ParseException {
+        if (PrivilegeXmlHandler.isSupportedContentType(contentType)) {
+            PrivilegeHandler pxh = new PrivilegeXmlHandler();
+            privilegeDefinitions = pxh.readDefinitions(in, namespaces);
+        } else {
+            // not yet supported
+            throw new IllegalArgumentException("Unsupported content type " + contentType);
+        }
+    }
+
+    /**
+     * Returns the privilege definitions retrieved from the input stream.
+     *
+     * @return an array of <code>PrivilegeDefinition</code>
+     */
+    public PrivilegeDefinition[] getPrivilegeDefinitions() {
+        return privilegeDefinitions;
+    }
+
+    /**
+     * Returns the namespace mappings such as retrieved during parsing.
+     *
+     * @return a mapping of namespace prefix to uri used by the privilege
+     * definitions.
+     */
+    public Map<String,String> getNamespaces() {
+        return namespaces;
+    }
+}
\ No newline at end of file

Propchange: jackrabbit/trunk/jackrabbit-jcr-commons/src/main/java/org/apache/jackrabbit/commons/privilege/PrivilegeDefinitionReader.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: jackrabbit/trunk/jackrabbit-jcr-commons/src/main/java/org/apache/jackrabbit/commons/privilege/PrivilegeDefinitionReader.java
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision Rev URL

Added: jackrabbit/trunk/jackrabbit-jcr-commons/src/main/java/org/apache/jackrabbit/commons/privilege/PrivilegeDefinitionWriter.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-jcr-commons/src/main/java/org/apache/jackrabbit/commons/privilege/PrivilegeDefinitionWriter.java?rev=1081433&view=auto
==============================================================================
--- jackrabbit/trunk/jackrabbit-jcr-commons/src/main/java/org/apache/jackrabbit/commons/privilege/PrivilegeDefinitionWriter.java (added)
+++ jackrabbit/trunk/jackrabbit-jcr-commons/src/main/java/org/apache/jackrabbit/commons/privilege/PrivilegeDefinitionWriter.java Mon Mar 14 16:00:40 2011
@@ -0,0 +1,60 @@
+/*
+ * 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.jackrabbit.commons.privilege;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.util.Map;
+
+/**
+ * Writes privilege definitions to an output stream.
+ */
+public class PrivilegeDefinitionWriter {
+
+    private final PrivilegeHandler ph;
+
+    /**
+     * Creates a new <code>PrivilegeDefinitionWriter</code>.
+     *
+     * @param contentType The content type used to determine the type of
+     * serialization.
+     * @throws IllegalArgumentException if the specified content type is not
+     * supported.
+     */
+    public PrivilegeDefinitionWriter(String contentType) {
+        if (PrivilegeXmlHandler.isSupportedContentType(contentType)) {
+            ph = new PrivilegeXmlHandler();
+        } else {
+            // not yet supported
+            throw new IllegalArgumentException("Unsupported content type");
+        }
+    }
+
+    /**
+     * Writes the privilege definitions to the specified output stream.
+     * 
+     * @param out The output stream.
+     * @param privilegeDefinitions The privilege definitions to write to the
+     * given output stream.
+     * @param namespaces The namespace mapping (prefix to uri) used by the
+     * specified definitions.
+     * @throws IOException If an error occurs.
+     */
+    public void writeDefinitions(OutputStream out, PrivilegeDefinition[] privilegeDefinitions, Map<String, String> namespaces) throws IOException {
+        ph.writeDefinitions(out, privilegeDefinitions, namespaces);
+    }
+}
\ No newline at end of file

Propchange: jackrabbit/trunk/jackrabbit-jcr-commons/src/main/java/org/apache/jackrabbit/commons/privilege/PrivilegeDefinitionWriter.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: jackrabbit/trunk/jackrabbit-jcr-commons/src/main/java/org/apache/jackrabbit/commons/privilege/PrivilegeDefinitionWriter.java
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision Rev URL

Added: jackrabbit/trunk/jackrabbit-jcr-commons/src/main/java/org/apache/jackrabbit/commons/privilege/PrivilegeHandler.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-jcr-commons/src/main/java/org/apache/jackrabbit/commons/privilege/PrivilegeHandler.java?rev=1081433&view=auto
==============================================================================
--- jackrabbit/trunk/jackrabbit-jcr-commons/src/main/java/org/apache/jackrabbit/commons/privilege/PrivilegeHandler.java (added)
+++ jackrabbit/trunk/jackrabbit-jcr-commons/src/main/java/org/apache/jackrabbit/commons/privilege/PrivilegeHandler.java Mon Mar 14 16:00:40 2011
@@ -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.jackrabbit.commons.privilege;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.Map;
+
+/**
+ * Interface used to define the (de)serialization mode of the privilege definitions.
+ */
+public interface PrivilegeHandler {
+
+    /**
+     * Read the privilege definitions and update the specified namespace mapping.
+     *
+     * @param in
+     * @param namespaces
+     * @return the privilege definitions contained in the specified stream.
+     * @throws ParseException
+     */
+    PrivilegeDefinition[] readDefinitions(InputStream in, Map<String, String> namespaces) throws ParseException;
+
+    /**
+     * Write the specified privilege definitions to the given output stream.
+     * 
+     * @param out
+     * @param definitions
+     * @param namespaces
+     * @throws IOException
+     */
+    void writeDefinitions(OutputStream out, PrivilegeDefinition[] definitions, Map<String, String> namespaces) throws IOException;
+}
\ No newline at end of file

Propchange: jackrabbit/trunk/jackrabbit-jcr-commons/src/main/java/org/apache/jackrabbit/commons/privilege/PrivilegeHandler.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: jackrabbit/trunk/jackrabbit-jcr-commons/src/main/java/org/apache/jackrabbit/commons/privilege/PrivilegeHandler.java
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision Rev URL

Added: jackrabbit/trunk/jackrabbit-jcr-commons/src/main/java/org/apache/jackrabbit/commons/privilege/PrivilegeXmlHandler.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-jcr-commons/src/main/java/org/apache/jackrabbit/commons/privilege/PrivilegeXmlHandler.java?rev=1081433&view=auto
==============================================================================
--- jackrabbit/trunk/jackrabbit-jcr-commons/src/main/java/org/apache/jackrabbit/commons/privilege/PrivilegeXmlHandler.java (added)
+++ jackrabbit/trunk/jackrabbit-jcr-commons/src/main/java/org/apache/jackrabbit/commons/privilege/PrivilegeXmlHandler.java Mon Mar 14 16:00:40 2011
@@ -0,0 +1,240 @@
+/*
+ * 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.jackrabbit.commons.privilege;
+
+import org.w3c.dom.Attr;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.NamedNodeMap;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+import org.xml.sax.SAXException;
+import org.xml.sax.helpers.DefaultHandler;
+
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.transform.Transformer;
+import javax.xml.transform.TransformerFactory;
+import javax.xml.transform.dom.DOMSource;
+import javax.xml.transform.stream.StreamResult;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * <code>PrivilegeXmlHandler</code> 
+ */
+class PrivilegeXmlHandler implements PrivilegeHandler {
+
+    private static final String TEXT_XML = "text/xml";
+    private static final String APPLICATION_XML = "application/xml";
+
+    private static final String XML_PRIVILEGES = "privileges";
+    private static final String XML_PRIVILEGE = "privilege";
+    private static final String XML_CONTAINS = "contains";
+
+    private static final String ATTR_NAME = "name";
+    private static final String ATTR_ABSTRACT = "abstract";
+
+    private static final String ATTR_XMLNS = "xmlns:";
+
+    /**
+     * Constant for <code>DocumentBuilderFactory</code>.
+     */
+    private static DocumentBuilderFactory DOCUMENT_BUILDER_FACTORY = createFactory();
+
+    private static DocumentBuilderFactory createFactory() {
+        DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
+        factory.setNamespaceAware(true);
+        factory.setIgnoringComments(true);
+        factory.setIgnoringElementContentWhitespace(true);
+        return factory;
+    }
+
+    /**
+     * Constant for <code>TransformerFactory</code>
+     */
+    private static TransformerFactory TRANSFORMER_FACTORY = TransformerFactory.newInstance();
+
+    /**
+     * Create a new instance.
+     */
+    PrivilegeXmlHandler() {
+
+    }
+
+    /**
+     * Returns <code>true</code> if the specified content type can be handled by this class.
+     *
+     * @param contentType
+     * @return <code>true</code> if the specified content type can be handled
+     * by this class; <code>false</code> otherwise.
+     */
+    static boolean isSupportedContentType(String contentType) {
+        return TEXT_XML.equals(contentType) || APPLICATION_XML.equals(contentType);
+    }
+
+    //---------------------------------------------------< PrivilegeHandler >---
+    /**
+     * @see PrivilegeHandler#readDefinitions(java.io.InputStream, java.util.Map)
+     */
+    public PrivilegeDefinition[] readDefinitions(InputStream in, Map<String, String> namespaces) throws ParseException {
+        try {
+            List<PrivilegeDefinition> defs = new ArrayList<PrivilegeDefinition>();
+
+            DocumentBuilder builder = createDocumentBuilder();
+            Document doc = builder.parse(in);
+            Element root = doc.getDocumentElement();
+            if (!XML_PRIVILEGES.equals(root.getNodeName())) {
+                throw new IllegalArgumentException("root element must be named 'privileges'");
+            }
+
+            updateNamespaceMapping(root, namespaces);
+
+            NodeList nl = root.getElementsByTagName(XML_PRIVILEGE);
+            for (int i = 0; i < nl.getLength(); i++) {
+                Node n = nl.item(i);
+                PrivilegeDefinition def = parseDefinition(n, namespaces);
+                if (def != null) {
+                    defs.add(def);
+                }
+            }
+            return defs.toArray(new PrivilegeDefinition[defs.size()]);
+
+        } catch (SAXException e) {
+            throw new ParseException(e);
+        } catch (IOException e) {
+            throw new ParseException(e);
+        } catch (ParserConfigurationException e) {
+            throw new ParseException(e);
+        }
+
+    }
+
+    /**
+     * @see PrivilegeHandler#writeDefinitions(java.io.OutputStream, PrivilegeDefinition[], java.util.Map) 
+     */
+    public void writeDefinitions(OutputStream out, PrivilegeDefinition[] definitions, Map<String, String> namespaces) throws IOException {
+        try {
+            DocumentBuilder builder = createDocumentBuilder();
+            Document doc = builder.newDocument();
+            Element privileges = (Element) doc.appendChild(doc.createElement(XML_PRIVILEGES));
+
+            for (String prefix : namespaces.keySet()) {
+                privileges.setAttribute(ATTR_XMLNS + prefix, namespaces.get(prefix));
+            }
+
+            for (PrivilegeDefinition def : definitions) {
+                Element priv = (Element) privileges.appendChild(doc.createElement(XML_PRIVILEGE));
+                priv.setAttribute(ATTR_NAME, def.getName());
+                priv.setAttribute(ATTR_ABSTRACT, Boolean.valueOf(def.isAbstract()).toString());
+
+                for (String aggrName : def.getDeclaredAggregateNames()) {
+                    Element contains = (Element) priv.appendChild(doc.createElement(XML_CONTAINS));
+                    contains.setAttribute(ATTR_NAME, aggrName);
+                }
+            }
+
+            Transformer transformer = TRANSFORMER_FACTORY.newTransformer();
+            transformer.transform(new DOMSource(doc), new StreamResult(out));
+
+        } catch (Exception e) {
+            IOException io = new IOException(e.getMessage());
+            io.initCause(e);
+            throw io;
+        }
+    }
+
+    //--------------------------------------------------------------------------
+    /**
+     * Build a new <code>PrivilegeDefinition</code> from the given XML node.
+     * @param n
+     * @param namespaces
+     * @return
+     */
+    private PrivilegeDefinition parseDefinition(Node n, Map<String, String> namespaces) {
+        if (n.getNodeType() == Node.ELEMENT_NODE) {
+            Element elem = (Element) n;
+
+            updateNamespaceMapping(elem, namespaces);
+
+            String name = elem.getAttribute(ATTR_NAME);
+            boolean isAbstract = Boolean.parseBoolean(elem.getAttribute(ATTR_ABSTRACT));
+
+            List<String> aggrNames = new ArrayList<String>();
+            NodeList nodeList = elem.getChildNodes();
+            for (int i = 0; i < nodeList.getLength(); i++) {
+                Node contains = nodeList.item(i);
+                if (isElement(n) && XML_CONTAINS.equals(contains.getNodeName())) {
+                    String aggrName = ((Element) contains).getAttribute(ATTR_NAME);
+                    if (aggrName != null) {
+                        aggrNames.add(aggrName);
+                    }
+                }
+            }
+            return new PrivilegeDefinition(name, isAbstract, aggrNames.toArray(new String[aggrNames.size()]));
+        }
+
+        // could not parse into privilege definition
+        return null;
+    }
+
+    /**
+     * Create a new <code>DocumentBuilder</code>
+     *
+     * @return a new <code>DocumentBuilder</code>
+     * @throws ParserConfigurationException
+     */
+    private static DocumentBuilder createDocumentBuilder() throws ParserConfigurationException {
+        DocumentBuilder builder = DOCUMENT_BUILDER_FACTORY.newDocumentBuilder();
+        builder.setErrorHandler(new DefaultHandler());
+        return builder;
+    }
+
+    /**
+     * Update the specified namespace mappings with the namespace declarations
+     * defined by the given XML element.
+     * 
+     * @param elem
+     * @param namespaces
+     */
+    private static void updateNamespaceMapping(Element elem, Map<String, String> namespaces) {
+        NamedNodeMap attributes = elem.getAttributes();
+        for (int i = 0; i < attributes.getLength(); i++) {
+            Attr attr = (Attr) attributes.item(i);
+            if (attr.getName().startsWith(ATTR_XMLNS)) {
+                String prefix = attr.getName().substring(ATTR_XMLNS.length());
+                String uri = attr.getValue();
+                namespaces.put(prefix, uri);
+            }
+        }
+    }
+
+    /**
+     * Returns <code>true</code> if the given XML node is an element.
+     *
+     * @param n
+     * @return <code>true</code> if the given XML node is an element; <code>false</code> otherwise.
+     */
+    private static boolean isElement(Node n) {
+        return n.getNodeType() == Node.ELEMENT_NODE;
+    }
+}
\ No newline at end of file

Propchange: jackrabbit/trunk/jackrabbit-jcr-commons/src/main/java/org/apache/jackrabbit/commons/privilege/PrivilegeXmlHandler.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: jackrabbit/trunk/jackrabbit-jcr-commons/src/main/java/org/apache/jackrabbit/commons/privilege/PrivilegeXmlHandler.java
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision Rev URL



Mime
View raw message