Centralize keyring
authorMathieu Baudier <mbaudier@argeo.org>
Fri, 26 Oct 2012 21:41:00 +0000 (21:41 +0000)
committerMathieu Baudier <mbaudier@argeo.org>
Fri, 26 Oct 2012 21:41:00 +0000 (21:41 +0000)
git-svn-id: https://svn.argeo.org/commons/trunk@5664 4cfe0d0a-d680-48aa-b62c-e0a02a3f76cc

security/plugins/org.argeo.security.ui/META-INF/spring/keyring.xml [new file with mode: 0644]
security/plugins/org.argeo.security.ui/META-INF/spring/osgi.xml
security/plugins/org.argeo.security.ui/securityui.properties [new file with mode: 0644]
security/runtime/org.argeo.security.core/src/main/java/org/argeo/security/crypto/AbstractKeyring.java
security/runtime/org.argeo.security.core/src/main/java/org/argeo/security/crypto/CryptoKeyring.java [new file with mode: 0644]
server/plugins/org.argeo.jcr.ui.explorer/META-INF/spring/jcr.xml
server/plugins/org.argeo.jcr.ui.explorer/META-INF/spring/osgi.xml
server/plugins/org.argeo.jcr.ui.explorer/jcrexplorer.properties [deleted file]
server/runtime/org.argeo.server.jcr/src/main/java/org/argeo/jcr/JcrUtils.java

diff --git a/security/plugins/org.argeo.security.ui/META-INF/spring/keyring.xml b/security/plugins/org.argeo.security.ui/META-INF/spring/keyring.xml
new file mode 100644 (file)
index 0000000..906c0b7
--- /dev/null
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<beans xmlns="http://www.springframework.org/schema/beans"
+       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:util="http://www.springframework.org/schema/util"
+       xmlns:p="http://www.springframework.org/schema/p"
+       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
+        http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-2.5.xsd">
+
+       <bean
+               class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
+               <property name="systemPropertiesModeName" value="SYSTEM_PROPERTIES_MODE_OVERRIDE" />
+               <property name="locations">
+                       <value>osgibundle:securityui.properties</value>
+               </property>
+       </bean>
+
+       <bean id="nodeSession" class="org.argeo.jcr.spring.ThreadBoundSession">
+               <property name="repository" ref="nodeRepository" />
+       </bean>
+
+       <bean id="keyring" class="org.argeo.security.jcr.JcrKeyring">
+               <property name="session" ref="nodeSession" />
+               <property name="defaultCallbackHandler" ref="defaultCallbackHandler" />
+               <property name="secreteKeyLength" value="${argeo.keyring.secreteKeyLength}" />
+       </bean>
+
+</beans>
index 1f93913de0d2324a83523b344afa3698ed63401d..01e21244b1261baa82cb40fd94beab8d789006e5 100644 (file)
        <!-- REFERENCES -->\r
        <reference id="secureLogger" interface="org.argeo.ArgeoLogger"\r
                cardinality="0..1" />\r
+\r
+       <reference id="nodeRepository" interface="javax.jcr.Repository"\r
+               filter="(argeo.jcr.repository.alias=node)" />\r
+\r
+       <reference id="defaultCallbackHandler" interface="javax.security.auth.callback.CallbackHandler" />\r
+\r
+       <!-- SERVICES -->\r
+       <service interface="org.argeo.security.crypto.CryptoKeyring"\r
+               ref="keyring" />\r
 </beans:beans>
\ No newline at end of file
diff --git a/security/plugins/org.argeo.security.ui/securityui.properties b/security/plugins/org.argeo.security.ui/securityui.properties
new file mode 100644 (file)
index 0000000..0228d47
--- /dev/null
@@ -0,0 +1 @@
+argeo.keyring.secreteKeyLength=256
\ No newline at end of file
index b69fff95a4b96b0fd0f14aea18f44055179cbb1e..4f666dcf2d4b734d42beef27dd3c89ba830d9c6d 100644 (file)
@@ -47,7 +47,7 @@ import org.argeo.util.security.Keyring;
 import org.bouncycastle.jce.provider.BouncyCastleProvider;
 
 /** username / password based keyring. TODO internationalize */
-public abstract class AbstractKeyring implements Keyring {
+public abstract class AbstractKeyring implements Keyring, CryptoKeyring {
        static {
                Security.addProvider(new BouncyCastleProvider());
        }
diff --git a/security/runtime/org.argeo.security.core/src/main/java/org/argeo/security/crypto/CryptoKeyring.java b/security/runtime/org.argeo.security.core/src/main/java/org/argeo/security/crypto/CryptoKeyring.java
new file mode 100644 (file)
index 0000000..6781760
--- /dev/null
@@ -0,0 +1,12 @@
+package org.argeo.security.crypto;
+
+import org.argeo.util.security.Keyring;
+
+/**
+ * Advanced keyring based on cryptography that can easily be centralized and
+ * coordinated with {@link KeyringLoginModule} (since they ar ein the same
+ * package)
+ */
+public interface CryptoKeyring extends Keyring {
+
+}
index 9eb9fc9ad4efe7b3f99e74900b9103b9362f7346..e074154ed7fda12f5fef80dcbb1a78d07857f45c 100644 (file)
@@ -5,24 +5,6 @@
        xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
         http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-2.5.xsd">
 
-       <bean
-               class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
-               <property name="systemPropertiesModeName" value="SYSTEM_PROPERTIES_MODE_OVERRIDE" />
-               <property name="locations">
-                       <value>osgibundle:jcrexplorer.properties</value>
-               </property>
-       </bean>
-
-       <bean id="nodeSession" class="org.argeo.jcr.spring.ThreadBoundSession">
-               <property name="repository" ref="nodeRepository" />
-       </bean>
-
-       <bean id="keyring" class="org.argeo.security.jcr.JcrKeyring">
-               <property name="session" ref="nodeSession" />
-               <property name="defaultCallbackHandler" ref="defaultCallbackHandler" />
-               <property name="secreteKeyLength" value="${argeo.keyring.secreteKeyLength}" />
-       </bean>
-
        <bean id="repositoryRegister" class="org.argeo.jcr.DefaultRepositoryRegister" />
 
 </beans>
index 7c415e0cccdbcfb477e1828517b4d91e3a9aad55..255462be41f70ba029f698b1126817dd277619ba 100644 (file)
@@ -18,6 +18,6 @@
                filter="(argeo.jcr.repository.alias=node)" />\r
        <reference id="repositoryFactory" interface="javax.jcr.RepositoryFactory" />\r
 \r
-       <reference id="defaultCallbackHandler" interface="javax.security.auth.callback.CallbackHandler" />\r
+       <reference id="keyring" interface="org.argeo.security.crypto.CryptoKeyring" />\r
 \r
 </beans:beans>
\ No newline at end of file
diff --git a/server/plugins/org.argeo.jcr.ui.explorer/jcrexplorer.properties b/server/plugins/org.argeo.jcr.ui.explorer/jcrexplorer.properties
deleted file mode 100644 (file)
index 0228d47..0000000
+++ /dev/null
@@ -1 +0,0 @@
-argeo.keyring.secreteKeyLength=256
\ No newline at end of file
index 83ab7a0b1cf776032e5919a286dfc13aed8e2d69..442e70d777577aa19403064f6f8b1780f7ad3696 100644 (file)
@@ -71,7 +71,7 @@ import org.argeo.util.security.SimplePrincipal;
 /** Utility methods to simplify common JCR operations. */
 public class JcrUtils implements ArgeoJcrConstants {
 
-       private final static Log log = LogFactory.getLog(JcrUtils.class);
+       final private static Log log = LogFactory.getLog(JcrUtils.class);
 
        /**
         * Not complete yet. See
@@ -401,14 +401,6 @@ public class JcrUtils implements ArgeoJcrConstants {
                return mkdirsSafe(session, path, null);
        }
 
-       /**
-        * Creates the nodes making the path as {@link NodeType#NT_FOLDER}
-        */
-       public static Node mkfolders(Session session, String path) {
-               return mkdirs(session, path, NodeType.NT_FOLDER, NodeType.NT_FOLDER,
-                               false);
-       }
-
        /**
         * Creates the nodes making path, if they don't exist. This is up to the
         * caller to save the session. Use with caution since it can create
@@ -702,79 +694,6 @@ public class JcrUtils implements ArgeoJcrConstants {
                }
        }
 
-       /**
-        * Copy only nt:folder and nt:file, without their additional types and
-        * properties.
-        * 
-        * @param recursive
-        *            if true copies folders as well, otherwise only first level
-        *            files
-        * @return how many files were copied
-        */
-       public static Long copyFiles(Node fromNode, Node toNode, Boolean recursive,
-                       ArgeoMonitor monitor) {
-               long count = 0l;
-
-               Binary binary = null;
-               InputStream in = null;
-               try {
-                       NodeIterator fromChildren = fromNode.getNodes();
-                       while (fromChildren.hasNext()) {
-                               if (monitor != null && monitor.isCanceled())
-                                       throw new ArgeoException(
-                                                       "Copy cancelled before it was completed");
-
-                               Node fromChild = fromChildren.nextNode();
-                               String fileName = fromChild.getName();
-                               if (fromChild.isNodeType(NodeType.NT_FILE)) {
-                                       if (monitor != null)
-                                               monitor.subTask("Copy " + fileName);
-                                       binary = fromChild.getNode(Node.JCR_CONTENT)
-                                                       .getProperty(Property.JCR_DATA).getBinary();
-                                       in = binary.getStream();
-                                       copyStreamAsFile(toNode, fileName, in);
-                                       IOUtils.closeQuietly(in);
-                                       JcrUtils.closeQuietly(binary);
-
-                                       // save session
-                                       toNode.getSession().save();
-                                       count++;
-
-                                       if (log.isDebugEnabled())
-                                               log.debug("Copied file " + fromChild.getPath());
-                                       if (monitor != null)
-                                               monitor.worked(1);
-                               } else if (fromChild.isNodeType(NodeType.NT_FOLDER)
-                                               && recursive) {
-                                       Node toChildFolder;
-                                       if (toNode.hasNode(fileName)) {
-                                               toChildFolder = toNode.getNode(fileName);
-                                               if (!toChildFolder.isNodeType(NodeType.NT_FOLDER))
-                                                       throw new ArgeoException(toChildFolder
-                                                                       + " is not of type nt:folder");
-                                       } else {
-                                               toChildFolder = toNode.addNode(fileName,
-                                                               NodeType.NT_FOLDER);
-
-                                               // save session
-                                               toNode.getSession().save();
-                                       }
-                                       count = count
-                                                       + copyFiles(fromChild, toChildFolder, recursive,
-                                                                       monitor);
-                               }
-                       }
-                       return count;
-               } catch (RepositoryException e) {
-                       throw new ArgeoException("Cannot copy files between " + fromNode
-                                       + " and " + toNode);
-               } finally {
-                       // in case there was an exception
-                       IOUtils.closeQuietly(in);
-                       JcrUtils.closeQuietly(binary);
-               }
-       }
-
        /**
         * Check whether all first-level properties (except jcr:* properties) are
         * equal. Skip jcr:* properties
@@ -1031,93 +950,6 @@ public class JcrUtils implements ArgeoJcrConstants {
                }
        }
 
-       /**
-        * Copy a file as an nt:file, assuming an nt:folder hierarchy. The session
-        * is NOT saved.
-        * 
-        * @return the created file node
-        */
-       public static Node copyFile(Node folderNode, File file) {
-               InputStream in = null;
-               try {
-                       in = new FileInputStream(file);
-                       return copyStreamAsFile(folderNode, file.getName(), in);
-               } catch (IOException e) {
-                       throw new ArgeoException("Cannot copy file " + file + " under "
-                                       + folderNode, e);
-               } finally {
-                       IOUtils.closeQuietly(in);
-               }
-       }
-
-       /** Copy bytes as an nt:file */
-       public static Node copyBytesAsFile(Node folderNode, String fileName,
-                       byte[] bytes) {
-               InputStream in = null;
-               try {
-                       in = new ByteArrayInputStream(bytes);
-                       return copyStreamAsFile(folderNode, fileName, in);
-               } catch (Exception e) {
-                       throw new ArgeoException("Cannot copy file " + fileName + " under "
-                                       + folderNode, e);
-               } finally {
-                       IOUtils.closeQuietly(in);
-               }
-       }
-
-       /**
-        * Copy a stream as an nt:file, assuming an nt:folder hierarchy. The session
-        * is NOT saved.
-        * 
-        * @return the created file node
-        */
-       public static Node copyStreamAsFile(Node folderNode, String fileName,
-                       InputStream in) {
-               Binary binary = null;
-               try {
-                       Node fileNode;
-                       Node contentNode;
-                       if (folderNode.hasNode(fileName)) {
-                               fileNode = folderNode.getNode(fileName);
-                               if (!fileNode.isNodeType(NodeType.NT_FILE))
-                                       throw new ArgeoException(fileNode
-                                                       + " is not of type nt:file");
-                               // we assume that the content node is already there
-                               contentNode = fileNode.getNode(Node.JCR_CONTENT);
-                       } else {
-                               fileNode = folderNode.addNode(fileName, NodeType.NT_FILE);
-                               contentNode = fileNode.addNode(Node.JCR_CONTENT,
-                                               NodeType.NT_RESOURCE);
-                       }
-                       binary = contentNode.getSession().getValueFactory()
-                                       .createBinary(in);
-                       contentNode.setProperty(Property.JCR_DATA, binary);
-                       return fileNode;
-               } catch (Exception e) {
-                       throw new ArgeoException("Cannot create file node " + fileName
-                                       + " under " + folderNode, e);
-               } finally {
-                       closeQuietly(binary);
-               }
-       }
-
-       /** Computes the checksum of an nt:file */
-       public static String checksumFile(Node fileNode, String algorithm) {
-               Binary data = null;
-               InputStream in = null;
-               try {
-                       data = fileNode.getNode(Node.JCR_CONTENT)
-                                       .getProperty(Property.JCR_DATA).getBinary();
-                       in = data.getStream();
-                       return DigestUtils.digest(algorithm, in);
-               } catch (RepositoryException e) {
-                       throw new ArgeoException("Cannot checksum file " + fileNode, e);
-               } finally {
-                       IOUtils.closeQuietly(in);
-                       closeQuietly(data);
-               }
-       }
-
        /**
         * Creates depth from a string (typically a username) by adding levels based
         * on its first characters: "aBcD",2 => a/aB
@@ -1441,4 +1273,196 @@ public class JcrUtils implements ArgeoJcrConstants {
                        }
                }
        }
+
+       /*
+        * FILES UTILITIES
+        */
+       /**
+        * Creates the nodes making the path as {@link NodeType#NT_FOLDER}
+        */
+       public static Node mkfolders(Session session, String path) {
+               return mkdirs(session, path, NodeType.NT_FOLDER, NodeType.NT_FOLDER,
+                               false);
+       }
+
+       /**
+        * Copy only nt:folder and nt:file, without their additional types and
+        * properties.
+        * 
+        * @param recursive
+        *            if true copies folders as well, otherwise only first level
+        *            files
+        * @return how many files were copied
+        */
+       public static Long copyFiles(Node fromNode, Node toNode, Boolean recursive,
+                       ArgeoMonitor monitor) {
+               long count = 0l;
+
+               Binary binary = null;
+               InputStream in = null;
+               try {
+                       NodeIterator fromChildren = fromNode.getNodes();
+                       while (fromChildren.hasNext()) {
+                               if (monitor != null && monitor.isCanceled())
+                                       throw new ArgeoException(
+                                                       "Copy cancelled before it was completed");
+
+                               Node fromChild = fromChildren.nextNode();
+                               String fileName = fromChild.getName();
+                               if (fromChild.isNodeType(NodeType.NT_FILE)) {
+                                       if (monitor != null)
+                                               monitor.subTask("Copy " + fileName);
+                                       binary = fromChild.getNode(Node.JCR_CONTENT)
+                                                       .getProperty(Property.JCR_DATA).getBinary();
+                                       in = binary.getStream();
+                                       copyStreamAsFile(toNode, fileName, in);
+                                       IOUtils.closeQuietly(in);
+                                       closeQuietly(binary);
+
+                                       // save session
+                                       toNode.getSession().save();
+                                       count++;
+
+                                       if (log.isDebugEnabled())
+                                               log.debug("Copied file " + fromChild.getPath());
+                                       if (monitor != null)
+                                               monitor.worked(1);
+                               } else if (fromChild.isNodeType(NodeType.NT_FOLDER)
+                                               && recursive) {
+                                       Node toChildFolder;
+                                       if (toNode.hasNode(fileName)) {
+                                               toChildFolder = toNode.getNode(fileName);
+                                               if (!toChildFolder.isNodeType(NodeType.NT_FOLDER))
+                                                       throw new ArgeoException(toChildFolder
+                                                                       + " is not of type nt:folder");
+                                       } else {
+                                               toChildFolder = toNode.addNode(fileName,
+                                                               NodeType.NT_FOLDER);
+
+                                               // save session
+                                               toNode.getSession().save();
+                                       }
+                                       count = count
+                                                       + copyFiles(fromChild, toChildFolder, recursive,
+                                                                       monitor);
+                               }
+                       }
+                       return count;
+               } catch (RepositoryException e) {
+                       throw new ArgeoException("Cannot copy files between " + fromNode
+                                       + " and " + toNode);
+               } finally {
+                       // in case there was an exception
+                       IOUtils.closeQuietly(in);
+                       closeQuietly(binary);
+               }
+       }
+
+       /**
+        * Iteratively count all file nodes in subtree, inefficient but can be
+        * useful when query are poorly supported, such as in remoting.
+        */
+       public static Long countFiles(Node node) {
+               Long localCount = 0l;
+               try {
+                       for (NodeIterator nit = node.getNodes(); nit.hasNext();) {
+                               Node child = nit.nextNode();
+                               if (child.isNodeType(NodeType.NT_FOLDER))
+                                       localCount = localCount + countFiles(child);
+                               else if (child.isNodeType(NodeType.NT_FILE))
+                                       localCount = localCount + 1;
+                       }
+               } catch (RepositoryException e) {
+                       throw new ArgeoException("Cannot count all children of " + node);
+               }
+               return localCount;
+       }
+
+       /**
+        * Copy a file as an nt:file, assuming an nt:folder hierarchy. The session
+        * is NOT saved.
+        * 
+        * @return the created file node
+        */
+       public static Node copyFile(Node folderNode, File file) {
+               InputStream in = null;
+               try {
+                       in = new FileInputStream(file);
+                       return copyStreamAsFile(folderNode, file.getName(), in);
+               } catch (IOException e) {
+                       throw new ArgeoException("Cannot copy file " + file + " under "
+                                       + folderNode, e);
+               } finally {
+                       IOUtils.closeQuietly(in);
+               }
+       }
+
+       /** Copy bytes as an nt:file */
+       public static Node copyBytesAsFile(Node folderNode, String fileName,
+                       byte[] bytes) {
+               InputStream in = null;
+               try {
+                       in = new ByteArrayInputStream(bytes);
+                       return copyStreamAsFile(folderNode, fileName, in);
+               } catch (Exception e) {
+                       throw new ArgeoException("Cannot copy file " + fileName + " under "
+                                       + folderNode, e);
+               } finally {
+                       IOUtils.closeQuietly(in);
+               }
+       }
+
+       /**
+        * Copy a stream as an nt:file, assuming an nt:folder hierarchy. The session
+        * is NOT saved.
+        * 
+        * @return the created file node
+        */
+       public static Node copyStreamAsFile(Node folderNode, String fileName,
+                       InputStream in) {
+               Binary binary = null;
+               try {
+                       Node fileNode;
+                       Node contentNode;
+                       if (folderNode.hasNode(fileName)) {
+                               fileNode = folderNode.getNode(fileName);
+                               if (!fileNode.isNodeType(NodeType.NT_FILE))
+                                       throw new ArgeoException(fileNode
+                                                       + " is not of type nt:file");
+                               // we assume that the content node is already there
+                               contentNode = fileNode.getNode(Node.JCR_CONTENT);
+                       } else {
+                               fileNode = folderNode.addNode(fileName, NodeType.NT_FILE);
+                               contentNode = fileNode.addNode(Node.JCR_CONTENT,
+                                               NodeType.NT_RESOURCE);
+                       }
+                       binary = contentNode.getSession().getValueFactory()
+                                       .createBinary(in);
+                       contentNode.setProperty(Property.JCR_DATA, binary);
+                       return fileNode;
+               } catch (Exception e) {
+                       throw new ArgeoException("Cannot create file node " + fileName
+                                       + " under " + folderNode, e);
+               } finally {
+                       closeQuietly(binary);
+               }
+       }
+
+       /** Computes the checksum of an nt:file */
+       public static String checksumFile(Node fileNode, String algorithm) {
+               Binary data = null;
+               InputStream in = null;
+               try {
+                       data = fileNode.getNode(Node.JCR_CONTENT)
+                                       .getProperty(Property.JCR_DATA).getBinary();
+                       in = data.getStream();
+                       return DigestUtils.digest(algorithm, in);
+               } catch (RepositoryException e) {
+                       throw new ArgeoException("Cannot checksum file " + fileNode, e);
+               } finally {
+                       IOUtils.closeQuietly(in);
+                       closeQuietly(data);
+               }
+       }
+
 }