--- /dev/null
+<?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
--- /dev/null
+<?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
* @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")) {
* @return the xml <code>Element</code>
*/
- Element unmarshall() throws ArpMarshallingException {
+ public Element unmarshall() throws ArpMarshallingException {
try {
DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
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.");
}
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());
}
}
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() {
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;
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();
+ }
+ }
}
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;
* @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);
}
}
}
/**
+ * @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()) {
}
/**
- * @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)
*/