Added File System repository for ARP retrieval.
authorwassa <wassa@ab3bd59b-922f-494d-bb5f-6f0a3c29deca>
Mon, 27 Jan 2003 22:52:27 +0000 (22:52 +0000)
committerwassa <wassa@ab3bd59b-922f-494d-bb5f-6f0a3c29deca>
Mon, 27 Jan 2003 22:52:27 +0000 (22:52 +0000)
git-svn-id: https://subversion.switch.ch/svn/shibboleth/java-idp/trunk@429 ab3bd59b-922f-494d-bb5f-6f0a3c29deca

data/arp.site.xml [new file with mode: 0755]
data/arp.user.test.xml [new file with mode: 0755]
src/edu/internet2/middleware/shibboleth/aa/arp/Arp.java
src/edu/internet2/middleware/shibboleth/aa/arp/ArpRepositoryFactory.java
src/edu/internet2/middleware/shibboleth/aa/arp/ArpTests.java
src/edu/internet2/middleware/shibboleth/aa/arp/provider/BaseArpRepository.java
src/edu/internet2/middleware/shibboleth/aa/arp/provider/FileSystemArpRepository.java
src/edu/internet2/middleware/shibboleth/aa/arp/provider/MemoryArpRepository.java

diff --git a/data/arp.site.xml b/data/arp.site.xml
new file mode 100755 (executable)
index 0000000..6e82f29
--- /dev/null
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<AttributeReleasePolicy xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="urn:mace:shibboleth:arp:1.0" xsi:schemaLocation="urn:mace:shibboleth:arp:1.0 shibboleth-arp-1.0.xsd" >
+       <Description>Simplest possible ARP.</Description>
+       <Rule>
+               <Target>
+                       <AnyTarget/>
+               </Target>
+               <Attribute name="urn:mace:eduPerson:1.0:eduPersonAffiliation">
+                       <AnyValue release="permit"/>
+               </Attribute>
+       </Rule>
+</AttributeReleasePolicy>
\ No newline at end of file
diff --git a/data/arp.user.test.xml b/data/arp.user.test.xml
new file mode 100755 (executable)
index 0000000..906613c
--- /dev/null
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<AttributeReleasePolicy xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="urn:mace:shibboleth:arp:1.0" xsi:schemaLocation="urn:mace:shibboleth:arp:1.0 shibboleth-arp-1.0.xsd" >
+       <Rule>
+               <Target>
+                       <AnyTarget/>
+               </Target>
+               <Attribute name="urn:mace:eduPerson:1.0:eduPersonPrincipalName">
+                       <AnyValue release="permit"/>
+               </Attribute>
+       </Rule>
+</AttributeReleasePolicy>
\ No newline at end of file
index f414a7b..5b52662 100755 (executable)
@@ -133,7 +133,7 @@ public class Arp {
         * @param the xml <code>Element</code> containing the ARP structure.
         */
 
-       void marshall(Element xmlElement) throws ArpMarshallingException {
+       public void marshall(Element xmlElement) throws ArpMarshallingException {
 
                //Make sure we are deling with an ARP
                if (!xmlElement.getTagName().equals("AttributeReleasePolicy")) {
@@ -197,7 +197,7 @@ public class Arp {
         * @return the xml <code>Element</code>
         */
 
-       Element unmarshall() throws ArpMarshallingException {
+       public Element unmarshall() throws ArpMarshallingException {
 
                try {
                        DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
index 3832945..8fc5a6c 100755 (executable)
@@ -69,7 +69,8 @@ public class ArpRepositoryFactory {
 
        public static ArpRepository getInstance(Properties props) throws ArpRepositoryException {
 
-               if (props.getProperty("edu.internet2.middleware.shibboleth.aa.arp.ArpRepository.implementation")
+               if (props
+                       .getProperty("edu.internet2.middleware.shibboleth.aa.arp.ArpRepository.implementation")
                        == null) {
                        throw new ArpRepositoryException("No ARP Repository implementaiton specified.");
                }
@@ -94,7 +95,8 @@ public class ArpRepositoryFactory {
                        throw new ArpRepositoryException("Failed to instantiate an Arp Repository.");
                } catch (Exception e) {
                        log.error("Failed to instantiate an Arp Repository: " + e);
-                       throw new ArpRepositoryException("Failed to instantiate an Arp Repository: " + e.getMessage());
+                       throw new ArpRepositoryException(
+                               "Failed to instantiate an Arp Repository: " + e.getMessage());
 
                }
        }
index 55a34b2..05384a2 100755 (executable)
@@ -456,6 +456,38 @@ public class ArpTests extends TestCase {
                        fail("Error adding User ARP to Memory Repository.");
                }
 
+               /*
+                * Exercise the Memory Arp Repository
+                */
+
+               //create a repository
+               props.setProperty(
+                       "edu.internet2.middleware.shibboleth.aa.arp.ArpRepository.implementation",
+                       "edu.internet2.middleware.shibboleth.aa.arp.provider.FileSystemArpRepository");
+               props.setProperty(
+                       "edu.internet2.middleware.shibboleth.aa.arp.provider.FileSystemArpRepository.Path",
+                       "data");
+               props.setProperty(
+                       "edu.internet2.middleware.shibboleth.aa.arp.BaseArpRepository.ArpTTL",
+                       "65535");
+               repository = null;
+               try {
+                       repository = ArpRepositoryFactory.getInstance(props);
+               } catch (ArpRepositoryException e) {
+                       fail("Failed to create file-based Arp Repository" + e);
+               }
+               assertNotNull(
+                       "Failed to create file-based Arp Repository: Factory returned null.",
+                       repository);
+
+               try {
+                       repository.getSitePolicy();
+                       repository.getUserPolicy(new AAPrincipal("test"));
+                       repository.getAllPolicies(new AAPrincipal("test"));
+               } catch (ArpRepositoryException e) {
+                       fail("Error retrieving ARP from Repository.");
+               }
+
        }
 
        public void testPossibleReleaseSetComputation() {
index 53e19b4..f59bdfb 100755 (executable)
 
 package edu.internet2.middleware.shibboleth.aa.arp.provider;
 
+import java.io.IOException;
 import java.security.Principal;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Properties;
+import java.util.Set;
+
+import org.apache.log4j.Logger;
+import org.w3c.dom.Element;
+import org.xml.sax.SAXException;
 
 import edu.internet2.middleware.shibboleth.aa.arp.Arp;
+import edu.internet2.middleware.shibboleth.aa.arp.ArpMarshallingException;
 import edu.internet2.middleware.shibboleth.aa.arp.ArpRepository;
 import edu.internet2.middleware.shibboleth.aa.arp.ArpRepositoryException;
 
@@ -64,4 +75,214 @@ import edu.internet2.middleware.shibboleth.aa.arp.ArpRepositoryException;
 
 public abstract class BaseArpRepository implements ArpRepository {
 
+       private static Logger log = Logger.getLogger(BaseArpRepository.class.getName());
+       private ArpCache arpCache;
+
+       BaseArpRepository(Properties properties) {
+               if (properties
+                       .getProperty(
+                               "edu.internet2.middleware.shibboleth.aa.arp.BaseArpRepository.ArpTTL",
+                               null)
+                       != null) {
+                       arpCache = ArpCache.instance();
+                       arpCache.setCacheLength(
+                               Long.parseLong(
+                                       properties.getProperty(
+                                               "edu.internet2.middleware.shibboleth.aa.arp.BaseArpRepository.ArpTTL",
+                                               null)));
+               }
+       }
+
+       /**
+        * @see edu.internet2.middleware.shibboleth.aa.arp.ArpRepository#getAllPolicies(Principal)
+        */
+
+       public Arp[] getAllPolicies(Principal principal) throws ArpRepositoryException {
+               log.debug(
+                       "Received a query for all policies applicable to principal: ("
+                               + principal.getName()
+                               + ").");
+               Set allPolicies = new HashSet();
+               if (getSitePolicy() != null) {
+                       log.debug("Returning site policy.");
+                       allPolicies.add(getSitePolicy());
+               }
+               if (getUserPolicy(principal) != null) {
+                       allPolicies.add(getUserPolicy(principal));
+                       log.debug("Returning user policy.");
+               }
+               if (allPolicies.isEmpty()) {
+                       log.debug("No policies found.");
+               }
+               return (Arp[]) allPolicies.toArray(new Arp[0]);
+       }
+
+       /**
+        * @see edu.internet2.middleware.shibboleth.aa.arp.ArpRepository#getSitePolicy()
+        */
+       public Arp getSitePolicy() throws ArpRepositoryException {
+
+               try {
+                       if (arpCache != null) {
+                               Arp cachedArp = arpCache.retrieveSiteArpFromCache();
+                               if (cachedArp != null) {
+                                       log.debug("Using cached site ARP.");
+                                       return cachedArp;
+                               }
+                       }
+
+                       Element xml = retrieveSiteArpXml();
+                       if (xml == null) {
+                               return null;
+                       }
+
+                       Arp siteArp = new Arp();
+                       siteArp.marshall(xml);
+                       if (arpCache != null) {
+                               arpCache.cache(siteArp);
+                       }
+                       return siteArp;
+               } catch (ArpMarshallingException ame) {
+                       log.error("An error occurred while marshalling an ARP: " + ame);
+                       throw new ArpRepositoryException("An error occurred while marshalling an ARP.");
+               } catch (IOException ioe) {
+                       log.error("An error occurred while loading an ARP: " + ioe);
+                       throw new ArpRepositoryException("An error occurred while loading an ARP.");
+               } catch (SAXException se) {
+                       log.error("An error occurred while parsing an ARP: " + se);
+                       throw new ArpRepositoryException("An error occurred while parsing an ARP.");
+               }
+       }
+
+       /**
+        * Inheritors must return the site Arp as an xml element.
+        * @return Element
+        */
+       protected abstract Element retrieveSiteArpXml() throws IOException, SAXException;
+
+       /**
+        * @see edu.internet2.middleware.shibboleth.aa.arp.ArpRepository#getUserPolicy(Principal)
+        */
+       public Arp getUserPolicy(Principal principal) throws ArpRepositoryException {
+
+               if (arpCache != null) {
+                       Arp cachedArp = arpCache.retrieveUserArpFromCache(principal);
+                       if (cachedArp != null) {
+                               log.debug("Using cached user ARP.");
+                               return cachedArp;
+                       }
+               }
+
+               try {
+                       Element xml = retrieveUserArpXml(principal);
+                       if (xml == null) {
+                               return null;
+                       }
+
+                       Arp userArp = new Arp();
+                       userArp.setPrincipal(principal);
+
+                       userArp.marshall(xml);
+                       if (arpCache != null) {
+                               arpCache.cache(userArp);
+                       }
+                       return userArp;
+               } catch (ArpMarshallingException ame) {
+                       log.error("An error occurred while marshalling an ARP: " + ame);
+                       throw new ArpRepositoryException("An error occurred while marshalling an ARP.");
+               } catch (IOException ioe) {
+                       log.error("An error occurred while loading an ARP: " + ioe);
+                       throw new ArpRepositoryException("An error occurred while loading an ARP.");
+               } catch (SAXException se) {
+                       log.error("An error occurred while parsing an ARP: " + se);
+                       throw new ArpRepositoryException("An error occurred while parsing an ARP.");
+               }
+       }
+
+       /**
+        * Inheritors must return the user Arp as an xml element.
+        * @return Element
+        */
+       protected abstract Element retrieveUserArpXml(Principal principal)
+               throws IOException, SAXException;
+
+}
+
+class ArpCache {
+
+       private static ArpCache instance = null;
+       private long cacheLength;
+       private Map cache = new HashMap();
+
+       protected ArpCache() {
+       }
+
+       static ArpCache instance() {
+               if (instance == null) {
+                       return new ArpCache();
+               }
+               return instance;
+       }
+
+       void setCacheLength(long cacheLength) {
+               this.cacheLength = cacheLength;
+       }
+
+       void cache(Arp arp) {
+               if (arp.isSitePolicy() == false) {
+                       cache.put(arp.getPrincipal(), new CachedArp(arp, System.currentTimeMillis()));
+               } else {
+                       cache.put(new SiteCachePrincipal(), new CachedArp(arp, System.currentTimeMillis()));
+               }
+       }
+
+       Arp retrieveUserArpFromCache(Principal principal) {
+               return retrieveArpFromCache(principal);
+       }
+
+       Arp retrieveSiteArpFromCache() {
+               return retrieveArpFromCache(new SiteCachePrincipal());
+       }
+
+       private Arp retrieveArpFromCache(Principal principal) {
+               CachedArp cachedArp = (CachedArp) cache.get(principal);
+               if (cachedArp == null) {
+                       return null;
+               }
+
+               if ((System.currentTimeMillis() - cachedArp.creationTimeMillis) < cacheLength) {
+                       return cachedArp.arp;
+               }
+               cache.remove(principal);
+               return null;
+       }
+
+       class CachedArp {
+               Arp arp;
+               long creationTimeMillis;
+
+               CachedArp(Arp arp, long creationTimeMillis) {
+                       this.arp = arp;
+                       this.creationTimeMillis = creationTimeMillis;
+               }
+       }
+
+       class SiteCachePrincipal implements Principal {
+
+               public String getName() {
+                       return "ARP admin";
+               }
+
+               public boolean equals(Object object) {
+                       if (object instanceof SiteCachePrincipal) {
+                               return true;
+                       }
+                       return false;
+               }
+
+               public long hashcode() {
+                       return "edu.internet2.middleware.shibboleth.aa.arp.provider.BaseArpRepository.SiteCachePrincipal"
+                               .hashCode();
+               }
+       }
 }
index 0d904a8..f82bcf6 100755 (executable)
 
 package edu.internet2.middleware.shibboleth.aa.arp.provider;
 
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStream;
 import java.security.Principal;
+import java.util.Properties;
+
+import org.apache.log4j.Logger;
+import org.apache.xerces.parsers.DOMParser;
+import org.w3c.dom.Element;
+import org.xml.sax.InputSource;
+import org.xml.sax.SAXException;
 
 import edu.internet2.middleware.shibboleth.aa.arp.Arp;
 import edu.internet2.middleware.shibboleth.aa.arp.ArpRepository;
@@ -61,39 +73,97 @@ import edu.internet2.middleware.shibboleth.aa.arp.ArpRepositoryException;
  * @author Walter Hoehn (wassa@columbia.edu)
  */
 
-public class FileSystemArpRepository implements ArpRepository {
+public class FileSystemArpRepository extends BaseArpRepository implements ArpRepository {
 
-       /**
-        * @see edu.internet2.middleware.shibboleth.aa.arp.ArpRepository#getAllPolicies(Principal)
-        */
-       public Arp[] getAllPolicies(Principal principal) throws ArpRepositoryException {
-               return null;
+       private static Logger log = Logger.getLogger(FileSystemArpRepository.class.getName());
+       private final String siteArpFileName = "arp.site.xml";
+
+       private String dataStorePath;
+
+       public FileSystemArpRepository(Properties props) throws ArpRepositoryException {
+               super(props);
+               if (props
+                       .getProperty(
+                               "edu.internet2.middleware.shibboleth.aa.arp.provider.FileSystemArpRepository.Path",
+                               null)
+                       == null) {
+                       log.error(
+                               "Cannot initialize FileSystemArpRepository: attribute (edu.internet2.middleware.shibboleth.aa.arp.provider.FileSystemArpRepository.Path) not specified");
+                       throw new ArpRepositoryException("Cannot initialize FileSystemArpRepository");
+               }
+
+               File givenPath =
+                       new File(
+                               props.getProperty(
+                                       "edu.internet2.middleware.shibboleth.aa.arp.provider.FileSystemArpRepository.Path"));
+               if (!givenPath.isDirectory()) {
+                       log.error(
+                               "Cannot initialize FileSystemArpRepository: specified path is not a directory.");
+                       throw new ArpRepositoryException("Cannot initialize FileSystemArpRepository");
+               }
+
+               log.info(
+                       "Initializing File System Arp Repository with a root of ("
+                               + givenPath.getAbsolutePath()
+                               + ").");
+               dataStorePath =
+                       props.getProperty(
+                               "edu.internet2.middleware.shibboleth.aa.arp.provider.FileSystemArpRepository.Path");
        }
 
        /**
-        * @see edu.internet2.middleware.shibboleth.aa.arp.ArpRepository#getSitePolicy()
+        * @see edu.internet2.middleware.shibboleth.aa.arp.ArpRepository#remove(Arp)
         */
-       public Arp getSitePolicy() throws ArpRepositoryException {
-               return null;
+       public void remove(Arp arp) throws ArpRepositoryException {
+               throw new ArpRepositoryException("Remove not implemented for FileSystemArpRepository.");
        }
 
        /**
-        * @see edu.internet2.middleware.shibboleth.aa.arp.ArpRepository#getUserPolicy(Principal)
+        * @see edu.internet2.middleware.shibboleth.aa.arp.ArpRepository#update(Arp)
         */
-       public Arp getUserPolicy(Principal principal) throws ArpRepositoryException {
-               return null;
+       public void update(Arp arp) throws ArpRepositoryException {
+               throw new ArpRepositoryException("Update not implemented for FileSystemArpRepository.");
        }
 
        /**
-        * @see edu.internet2.middleware.shibboleth.aa.arp.ArpRepository#remove(Arp)
+        * @see edu.internet2.middleware.shibboleth.aa.arp.provider.BaseArpRepository#retrieveSiteArpXml()
         */
-       public void remove(Arp arp) throws ArpRepositoryException {
+       protected Element retrieveSiteArpXml() throws IOException, SAXException {
+
+               String fileName = dataStorePath + System.getProperty("file.separator") + siteArpFileName;
+               log.debug("Attempting to load site ARP from: (" + fileName + ").");
+               return retrieveArpXml(fileName);
+
+       }
+
+       private Element retrieveArpXml(String fileName)
+               throws FileNotFoundException, SAXException, IOException {
+
+               File arpFile = new File(fileName);
+               if (!arpFile.exists()) {
+                       log.debug("No ARP found.");
+                       return null;
+               }
+
+               InputStream inStream = new FileInputStream(fileName);
+               DOMParser parser = new DOMParser();
+               parser.parse(new InputSource(inStream));
+               return parser.getDocument().getDocumentElement();
        }
 
        /**
-        * @see edu.internet2.middleware.shibboleth.aa.arp.ArpRepository#update(Arp)
+        * @see edu.internet2.middleware.shibboleth.aa.arp.provider.BaseArpRepository#retrieveUserArpXml(Principal)
         */
-       public void update(Arp arp) throws ArpRepositoryException {
+       protected Element retrieveUserArpXml(Principal principal) throws IOException, SAXException {
+               String fileName =
+                       dataStorePath
+                               + System.getProperty("file.separator")
+                               + "arp.user."
+                               + principal.getName()
+                               + ".xml";
+               log.debug(
+                       "Attempting to load user (" + principal.getName() + ")ARP from: (" + fileName + ").");
+               return retrieveArpXml(fileName);
        }
 
 }
index 4c0f05b..c84a029 100755 (executable)
@@ -80,19 +80,29 @@ public class MemoryArpRepository implements ArpRepository {
        }
 
        /**
+        * @see edu.internet2.middleware.shibboleth.aa.arp.ArpRepository#getSitePolicy()
+        */
+
+       public synchronized Arp getSitePolicy() throws ArpRepositoryException {
+               return sitePolicy;
+       }
+       
+       /**
         * @see edu.internet2.middleware.shibboleth.aa.arp.ArpRepository#getAllPolicies(Principal)
         */
 
        public Arp[] getAllPolicies(Principal principal) throws ArpRepositoryException {
                log.debug(
-                       "Received a query for all policies applicable to principal: (" + principal.getName() + ").");
+                       "Received a query for all policies applicable to principal: ("
+                               + principal.getName()
+                               + ").");
                Set allPolicies = new HashSet();
-               if (sitePolicy != null) {
+               if (getSitePolicy() != null) {
                        log.debug("Returning site policy.");
-                       allPolicies.add(sitePolicy);
+                       allPolicies.add(getSitePolicy());
                }
-               if (userPolicies.containsKey(principal)) {
-                       allPolicies.add(userPolicies.get(principal));
+               if (getUserPolicy(principal) != null) {
+                       allPolicies.add(getUserPolicy(principal));
                        log.debug("Returning user policy.");
                }
                if (allPolicies.isEmpty()) {
@@ -102,14 +112,6 @@ public class MemoryArpRepository implements ArpRepository {
        }
 
        /**
-        * @see edu.internet2.middleware.shibboleth.aa.arp.ArpRepository#getSitePolicy()
-        */
-
-       public synchronized Arp getSitePolicy() throws ArpRepositoryException {
-               return sitePolicy;
-       }
-
-       /**
         * @see edu.internet2.middleware.shibboleth.aa.arp.ArpRepository#getUserPolicy(Principal)
         */