package org.archive.accesscontrol.model; import java.util.Calendar; import java.util.Date; import java.util.GregorianCalendar; /** * An access control rules. Rules are organized into a tree based on SURT * components. The leafmost (most specific) matching rule takes precedence. In * the case that there are multiple matching rules for a particular node, allow * takes precedence over deny which takes precedence over robots. * * @author aosborne * */ public class Rule implements Comparable<Rule> { // in decreasing order of precedence //public static final String[] POLICIES = { "allow", "block", "robots" }; private Long id; private String policy; private String surt; private Date captureStart; private Date captureEnd; private Date retrievalStart; private Date retrievalEnd; private Integer secondsSinceCapture; private String who; private String privateComment; private String publicComment; private Boolean enabled; private Boolean exactMatch = Boolean.FALSE; public Rule() { super(); } public Rule(String policy, String surt) { this(); this.policy = policy; this.surt = surt; } public Rule(String policy, String surt, Integer secondsSinceCapture) { this(); this.policy = policy; this.surt = surt; this.secondsSinceCapture = secondsSinceCapture; } public Rule(String policy, String surt, String who) { this(policy, surt); this.who = who; } public Rule(String policy, String surt, boolean exact) { this(policy, surt); this.exactMatch = exact; } /** * @return the enabled */ public Boolean getEnabled() { return enabled; } /** * @param enabled the enabled to set */ public void setEnabled(Boolean enabled) { this.enabled = enabled; } /** * Populate the rule data fields by copying them from a given rule. */ public void copyFrom(Rule rule) { setPolicy(rule.getPolicy()); setCaptureStart(rule.getCaptureStart()); setCaptureEnd(rule.getCaptureEnd()); setPrivateComment(rule.getPrivateComment()); setPublicComment(rule.getPublicComment()); setRetrievalStart(rule.getRetrievalStart()); setRetrievalEnd(rule.getRetrievalEnd()); setSecondsSinceCapture(rule.getSecondsSinceCapture()); setSurt(rule.getSurt()); setWho(rule.getWho()); setEnabled(rule.getEnabled()); setExactMatch(rule.isExactMatch()); } /** * @return the id */ public Long getId() { return id; } /** * @param id * the id to set */ public void setId(Long id) { this.id = id; } /** * @return the policy */ public String getPolicy() { return policy; } /** * @param policy * the policy to set */ public void setPolicy(String policy) { this.policy = policy; } /** * @return the surt */ public String getSurt() { return surt; } /** * @param surt * the surt to set */ public void setSurt(String surt) { this.surt = surt; } /** * @return the captureStart */ public Date getCaptureStart() { return captureStart; } /** * @param captureStart * the captureStart to set */ public void setCaptureStart(Date captureStart) { this.captureStart = captureStart; } /** * @return the captureEnd */ public Date getCaptureEnd() { return captureEnd; } /** * @param captureEnd * the captureEnd to set */ public void setCaptureEnd(Date captureEnd) { this.captureEnd = captureEnd; } /** * @return the retrievalStart */ public Date getRetrievalStart() { return retrievalStart; } /** * @param retrievalStart * the retrievalStart to set */ public void setRetrievalStart(Date retrievalStart) { this.retrievalStart = retrievalStart; } /** * @return the retrievalEnd */ public Date getRetrievalEnd() { return retrievalEnd; } /** * @param retrievalEnd * the retrievalEnd to set */ public void setRetrievalEnd(Date retrievalEnd) { this.retrievalEnd = retrievalEnd; } /** * @return the secondsSinceCapture */ public Integer getSecondsSinceCapture() { return secondsSinceCapture; } /** * @param secondsSinceCapture * the secondsSinceCapture to set */ public void setSecondsSinceCapture(Integer secondsSinceCapture) { this.secondsSinceCapture = secondsSinceCapture; } /** * @return the who */ public String getWho() { return who; } /** * @param who * the who to set */ public void setWho(String who) { this.who = who; } /** * @return the privateComment */ public String getPrivateComment() { return privateComment; } /** * @param privateComment * the privateComment to set */ public void setPrivateComment(String privateComment) { this.privateComment = privateComment; } /** * @return the publicComment */ public String getPublicComment() { return publicComment; } /** * @param publicComment * the publicComment to set */ public void setPublicComment(String publicComment) { this.publicComment = publicComment; } // public Integer getPolicyId() { // return ArrayUtils.indexOf(POLICIES, getPolicy()); // } @SuppressWarnings({ "rawtypes", "unchecked" }) public int doCompare(Comparable mine, Comparable other) { if ((mine == null) && (other == null)) { return 0; } if ((mine != null) && (other != null)) { return -mine.compareTo(other); } return -((mine == null) ? -1 : 1); } /* * Rules are sorted in descending order of "specificity". * So we order first by SURT, exact-match, * then group, then policy. */ public int compareTo(Rule o) { int i; i = doCompare(this.getSurt(), o.getSurt()); if (i != 0) { return i; } // exact matches come after non-exact i = doCompare(this.getExactMatch(), o.getExactMatch()); if (i != 0) { return i; } // Compare by accessGroup, specific accessGroups take precedence i = doCompare(this.getWho(), o.getWho()); if (i != 0) { return i; } // if we're still equal try capture date start i = doCompare(this.getCaptureStart(), o.getCaptureStart()); if (i != 0) { return i; } // and retrieval date i = doCompare(this.getRetrievalStart(), o.getRetrievalStart()); if (i != 0) { return i; } i = doCompare(this.getSecondsSinceCapture(), o.getSecondsSinceCapture()); return i; } /** * @see #matches(String, Date, Date, String) */ public boolean matches(String surt) { String mySurt = getSurt(); return (isExactMatch() ? surt.equals(mySurt) : surt.startsWith(mySurt)); } /** * @see #matches(String, Date, Date, String) */ public boolean matches(String surt, Date captureDate) { if (captureDate == null) { return matches(surt); } return matches(surt) && (getCaptureStart() == null || captureDate.after(getCaptureStart())) && (getCaptureEnd() == null || captureDate.before(getCaptureEnd())); } /** * @see #matches(String, Date, Date, String) */ public boolean matches(String surt, Date captureDate, Date retrievalDate) { if (retrievalDate == null) { return matches(surt, captureDate); } // embargo period if (getSecondsSinceCapture() != null) { GregorianCalendar periodEnd = new GregorianCalendar(); periodEnd.setTime(captureDate); periodEnd.add(Calendar.SECOND, getSecondsSinceCapture()); if (retrievalDate.before(periodEnd.getTime())) { return false; } } return matches(surt, captureDate) && (getRetrievalStart() == null || retrievalDate.after(getRetrievalStart())) && (getRetrievalEnd() == null || retrievalDate.before(getRetrievalEnd())); } /** * Return true if the given request matches against this rule. * * @param surt SURT of requested document * @param captureDate Capture date of document * @param retrievalDate * @param who2 Group name of requesting user * @return */ public boolean matches(String surt, Date captureDate, Date retrievalDate, String who2) { return (who == null || who.length() == 0 || who.equals(who2)) && matches(surt, captureDate, retrievalDate); } public boolean isExactMatch() { return exactMatch.booleanValue(); } public Boolean getExactMatch() { return exactMatch; } public void setExactMatch(Boolean exactMatch) { this.exactMatch = ((exactMatch == null) ? Boolean.FALSE : exactMatch); } }