001: /*
002: * Copyright (c) 2004-2005, Hewlett-Packard Company and Massachusetts
003: * Institute of Technology. All rights reserved.
004: *
005: * Redistribution and use in source and binary forms, with or without
006: * modification, are permitted provided that the following conditions are
007: * met:
008: *
009: * - Redistributions of source code must retain the above copyright
010: * notice, this list of conditions and the following disclaimer.
011: *
012: * - Redistributions in binary form must reproduce the above copyright
013: * notice, this list of conditions and the following disclaimer in the
014: * documentation and/or other materials provided with the distribution.
015: *
016: * - Neither the name of the Hewlett-Packard Company nor the name of the
017: * Massachusetts Institute of Technology nor the names of their
018: * contributors may be used to endorse or promote products derived from
019: * this software without specific prior written permission.
020: *
021: * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
022: * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
023: * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
024: * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
025: * HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
026: * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
027: * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
028: * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
029: * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
030: * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
031: * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
032: * DAMAGE.
033: */
034:
035: package org.dspace.checker;
036:
037: import java.io.FileInputStream;
038: import java.io.FileNotFoundException;
039: import java.io.IOException;
040: import java.text.ParseException;
041: import java.util.Enumeration;
042: import java.util.HashMap;
043: import java.util.Iterator;
044: import java.util.List;
045: import java.util.Map;
046: import java.util.Properties;
047: import java.util.regex.Matcher;
048: import java.util.regex.Pattern;
049:
050: import org.apache.log4j.Logger;
051: import org.dspace.core.ConfigurationManager;
052: import org.dspace.core.Utils;
053:
054: /**
055: * Manages the deletion of results from the checksum history. It uses the
056: * dspace.cfg file as the default configuration file for the deletion settings
057: * and can use a different configuration file if it is passed in.
058: *
059: * @author Jim Downing
060: * @author Grace Carpenter
061: * @author Nathan Sarr
062: *
063: *
064: */
065: public final class ResultsPruner {
066:
067: /**
068: * Default logger.
069: */
070: private static final Logger LOG = Logger
071: .getLogger(ResultsPruner.class);
072:
073: /**
074: * Factory method for the default results pruner configuration using
075: * dspace.cfg
076: *
077: * @return a ResultsPruner that represent the default retention policy
078: */
079: public static ResultsPruner getDefaultPruner() {
080: try {
081: return getPruner(ConfigurationManager.getProperties());
082: } catch (FileNotFoundException e) {
083: throw new RuntimeException(
084: "VeryExceptionalException - config file not there! ",
085: e);
086: }
087:
088: }
089:
090: /**
091: * Factory method for ResultsPruners
092: *
093: * @param propsFile
094: * to configure the results pruner.
095: * @return the configured results pruner.
096: * @throws FileNotFoundException
097: * it the configuration file cannot be found.
098: */
099: public static ResultsPruner getPruner(String propsFile)
100: throws FileNotFoundException {
101: Properties props = new Properties();
102: FileInputStream fin = null;
103: try {
104: fin = new FileInputStream(propsFile);
105: props.load(fin);
106:
107: return getPruner(props);
108: } catch (IOException e) {
109: throw new RuntimeException(
110: "Problem loading properties file: "
111: + e.getMessage(), e);
112: } finally {
113: if (fin != null)
114: try {
115: fin.close();
116: } catch (IOException e) {
117: LOG.warn(e);
118: }
119: }
120: }
121:
122: /**
123: * Factory method for ResultsPruners (used to load ConfigurationManager
124: * properties.
125: *
126: * @param props
127: * @return
128: * @throws FileNotFoundException
129: */
130: public static ResultsPruner getPruner(Properties props)
131: throws FileNotFoundException {
132:
133: ResultsPruner rp = new ResultsPruner();
134: Pattern retentionPattern = Pattern
135: .compile("checker\\.retention\\.(.*)");
136: for (Enumeration en = props.propertyNames(); en
137: .hasMoreElements();) {
138: String name = (String) en.nextElement();
139: Matcher matcher = retentionPattern.matcher(name);
140: if (!matcher.matches())
141: continue;
142: String resultCode = matcher.group(1);
143: long duration;
144: try {
145: duration = Utils.parseDuration(props.getProperty(name));
146: } catch (ParseException e) {
147: throw new RuntimeException("Problem parsing duration: "
148: + e.getMessage(), e);
149: }
150: if ("default".equals(resultCode)) {
151: rp.setDefaultDuration(duration);
152: } else {
153: rp.addInterested(resultCode, duration);
154: }
155: }
156: return rp;
157:
158: }
159:
160: /** Ten years */
161: private long defaultDuration = 31536000000L;
162:
163: /**
164: * Map of retention durations, keyed by result code name
165: */
166: Map interests = new HashMap();
167:
168: /**
169: * Checksum results database Data access
170: */
171: private ChecksumResultDAO checksumResultDAO = null;
172:
173: /**
174: * Checksum history database data access.
175: */
176: private ChecksumHistoryDAO checksumHistoryDAO = null;
177:
178: /**
179: * Default Constructor
180: */
181: public ResultsPruner() {
182: checksumResultDAO = new ChecksumResultDAO();
183: checksumHistoryDAO = new ChecksumHistoryDAO();
184: }
185:
186: /**
187: * Add a result and the length of time before the history with this type of
188: * result is removed from the database.
189: *
190: * @param result
191: * code in the database.
192: *
193: * @param duration
194: * before bitstreams with the specified result type in the
195: * checksum history is removed.
196: */
197: public void addInterested(String result, long duration) {
198: interests.put(result, new Long(duration));
199: }
200:
201: /**
202: * Add a result and the length of time before it is removed from the
203: * checksum history table.
204: *
205: * @param result
206: * code in the database.
207: *
208: * @param duration
209: * before bitstreams with the specified result type in the
210: * checksum history is removed.
211: *
212: * @throws ParseException
213: * if the duration cannot be parsed into a long value.
214: */
215: public void addInterested(String result, String duration)
216: throws ParseException {
217: addInterested(result, Utils.parseDuration(duration));
218: }
219:
220: /**
221: * The default amount of time before a result is removed.
222: *
223: * @return the default duration.
224: */
225: public long getDefaultDuration() {
226: return defaultDuration;
227: }
228:
229: /**
230: * Prunes the results retaining results as configured by the interests
231: * registered with this object.
232: *
233: * @return number of results removed.
234: */
235: public int prune() {
236: List codes = checksumResultDAO.listAllCodes();
237: for (Iterator iter = codes.iterator(); iter.hasNext();) {
238: String code = (String) iter.next();
239: if (!interests.containsKey(code)) {
240: interests.put(code, new Long(defaultDuration));
241: }
242:
243: }
244: return checksumHistoryDAO.prune(interests);
245: }
246:
247: /**
248: * The default duration before records are removed from the checksum history
249: * table.
250: *
251: * @param defaultDuration
252: * used before records are removed from the checksum history.
253: */
254: public void setDefaultDuration(long defaultDuration) {
255: this.defaultDuration = defaultDuration;
256: }
257: }
|