001: /*
002: * regain - A file search engine providing plenty of formats
003: * Copyright (C) 2004 Til Schneider
004: *
005: * This library is free software; you can redistribute it and/or
006: * modify it under the terms of the GNU Lesser General Public
007: * License as published by the Free Software Foundation; either
008: * version 2.1 of the License, or (at your option) any later version.
009: *
010: * This library is distributed in the hope that it will be useful,
011: * but WITHOUT ANY WARRANTY; without even the implied warranty of
012: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
013: * Lesser General Public License for more details.
014: *
015: * You should have received a copy of the GNU Lesser General Public
016: * License along with this library; if not, write to the Free Software
017: * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
018: *
019: * Contact: Til Schneider, info@murfman.de
020: *
021: * CVS information:
022: * $RCSfile$
023: * $Source$
024: * $Date: 2006-08-21 11:37:35 +0200 (Mo, 21 Aug 2006) $
025: * $Author: til132 $
026: * $Revision: 232 $
027: */
028: package net.sf.regain.ui.desktop;
029:
030: import java.io.FileOutputStream;
031: import java.io.IOException;
032: import java.util.Date;
033:
034: import net.sf.regain.RegainException;
035: import net.sf.regain.RegainToolkit;
036: import net.sf.regain.crawler.Crawler;
037: import net.sf.regain.crawler.config.CrawlerConfig;
038: import net.sf.regain.crawler.config.XmlCrawlerConfig;
039:
040: import org.apache.log4j.Logger;
041:
042: /**
043: *
044: * @author Til Schneider, www.murfman.de
045: */
046: public class IndexUpdateManager implements DesktopConstants {
047:
048: /** The logger for this class */
049: private static Logger mLog = Logger
050: .getLogger(IndexUpdateManager.class);
051:
052: /** The singleton. */
053: private static IndexUpdateManager mSingleton;
054:
055: /** The check thread. */
056: private Thread mCheckThread;
057:
058: /** The crawler. Is <code>null</code> if there is currently no index update running. */
059: private Crawler mCrawler;
060:
061: /**
062: * Gets the Singleton.
063: *
064: * @return The Singleton.
065: */
066: public static IndexUpdateManager getInstance() {
067: if (mSingleton == null) {
068: mSingleton = new IndexUpdateManager();
069: }
070: return mSingleton;
071: }
072:
073: /**
074: * Initializes the IndexUpdateManager.
075: */
076: public void init() {
077: mCheckThread = new Thread() {
078: public void run() {
079: checkThreadRun();
080: }
081: };
082: mCheckThread.setPriority(Thread.MIN_PRIORITY);
083: mCheckThread.start();
084: }
085:
086: /**
087: * Gets the crawler that processes the current index update.
088: *
089: * @return The crawler that processes the current index update or
090: * <code>null</code> if there is currently no index update running.
091: */
092: public Crawler getCurrentCrawler() {
093: return mCrawler;
094: }
095:
096: /**
097: * Starts an index update.
098: *
099: * @throws RegainException If starting the index update failed.
100: */
101: public void startIndexUpdate() throws RegainException {
102: if (mCrawler != null) {
103: // The crawler is already running
104: return;
105: }
106:
107: // Create an needsupdate file
108: try {
109: FileOutputStream out = new FileOutputStream(
110: NEEDSUPDATE_FILE);
111: out.close();
112: } catch (IOException exc) {
113: throw new RegainException(
114: "Creating needsupdate file failed", exc);
115: }
116:
117: // Force a new check
118: mCheckThread.interrupt();
119:
120: // Wait until the crawler runs
121: while (mCrawler == null) {
122: try {
123: Thread.sleep(100);
124: } catch (InterruptedException exc) {
125: }
126: }
127: }
128:
129: /**
130: * Sets whether the crawler should pause.
131: *
132: * @param shouldPause Whether the crawler should pause.
133: */
134: public void setShouldPause(boolean shouldPause) {
135: // NOTE: We get a local copy of the crawler for the case that is should
136: // change in the meantime
137: Crawler crawler = mCrawler;
138: if (crawler != null) {
139: crawler.setShouldPause(shouldPause);
140: TrayIconManager.getInstance().setIndexUpdateRunning(
141: !shouldPause);
142: }
143: }
144:
145: /**
146: * The run method of the thread that checks whether an index update is
147: * nessesary.
148: */
149: protected void checkThreadRun() {
150: while (true) {
151: try {
152: checkUpdate();
153: } catch (Throwable thr) {
154: mLog.error("Updating index failed", thr);
155: }
156:
157: try {
158: Thread.sleep(10000);
159: } catch (InterruptedException exc) {
160: }
161: }
162: }
163:
164: /**
165: * Executes an index update if nessesary.
166: *
167: * @throws RegainException If updating the index failed.
168: */
169: private synchronized void checkUpdate() throws RegainException {
170: if (indexNeedsUpdate()) {
171: // The index must be updated
172: CrawlerConfig config = new XmlCrawlerConfig(
173: CRAWLER_CONFIG_FILE);
174:
175: // Check whether to show the welcome page
176: if (config.getStartUrls().length == 0) {
177: // There are no start URLs defined -> Show the welcome page
178: mLog
179: .info("There is nothing configured. Showing the welcome page.");
180: DesktopToolkit.openPageInBrowser("welcome.jsp");
181:
182: // Show the welcome page again, when the next update period is finished
183: saveIndexLastUpdate();
184: } else {
185: // Update the index
186:
187: // Create and run the crawler
188: TrayIconManager.getInstance().setIndexUpdateRunning(
189: true);
190: try {
191: mLog.info("Starting index update on " + new Date());
192: mCrawler = new Crawler(config);
193: mCrawler.run(true, false, null);
194: } catch (RegainException exc) {
195: mLog.error("Updating the index failed", exc);
196: } finally {
197: mCrawler = null;
198:
199: // Save the time when the index was last updated
200: saveIndexLastUpdate();
201:
202: // Remove the needsupdate file
203: NEEDSUPDATE_FILE.delete();
204:
205: // Run the garbage collector
206: System.gc();
207:
208: TrayIconManager.getInstance()
209: .setIndexUpdateRunning(false);
210: }
211: }
212: }
213: }
214:
215: /**
216: * Gets the timestamp of the last index update.
217: *
218: * @return The timestamp of the last index update.
219: * @throws RegainException If getting the timestamp failed.
220: */
221: private boolean indexNeedsUpdate() throws RegainException {
222: if (NEEDSUPDATE_FILE.exists()) {
223: return true;
224: } else if (LASTUPDATE_FILE.exists()) {
225: String lastUpdateAsString = RegainToolkit
226: .readStringFromFile(LASTUPDATE_FILE);
227: long lastUpdate = RegainToolkit.stringToLastModified(
228: lastUpdateAsString).getTime();
229: long interval = DesktopToolkit.getDesktopConfig()
230: .getInterval();
231: long nextUpdateTime = lastUpdate + interval * 1000 * 60;
232:
233: return System.currentTimeMillis() >= nextUpdateTime;
234: } else {
235: // The lastupdate file does not exist -> There was never an index created
236: return true;
237: }
238: }
239:
240: /**
241: * Saves the current time as the last index update.
242: */
243: private void saveIndexLastUpdate() {
244: try {
245: String lastUpdate = RegainToolkit
246: .lastModifiedToString(new Date());
247: RegainToolkit.writeToFile(lastUpdate, LASTUPDATE_FILE);
248: } catch (RegainException exc) {
249: mLog.error("Writing last update file failed", exc);
250: }
251: }
252:
253: }
|