1
2
3
4
5
6
7
8
9
10
11
12
13
14 package net.sf.mmapps.modules.lucenesearch;
15
16 import java.io.File;
17 import java.util.Calendar;
18 import java.util.Date;
19 import java.util.Timer;
20 import java.util.TimerTask;
21
22 import net.sf.mmapps.modules.cloudprovider.CloudProvider;
23 import net.sf.mmapps.modules.cloudprovider.CloudProviderFactory;
24
25 import org.apache.commons.logging.Log;
26 import org.apache.commons.logging.LogFactory;
27 import org.mmbase.bridge.Cloud;
28 import org.mmbase.bridge.CloudContext;
29 import org.mmbase.bridge.ContextProvider;
30 import org.mmbase.module.Module;
31 import org.mmbase.module.core.MMBase;
32 import org.mmbase.module.core.MMBaseContext;
33
34 /***
35 * This module enables the Lucene fulltext search engine to be used to index the MMBase cloud.
36 *
37 * @author Wouter Heijke
38 * @version $Revision: 1.2 $
39 */
40 public class LuceneModule extends Module {
41 private static Log log = LogFactory.getLog(LuceneModule.class);
42
43 private static CloudProvider cloudProvider = CloudProviderFactory.getCloudProvider();
44
45
46 private static Timer timer = null;
47
48
49 private long interval;
50
51 private int startHour;
52
53
54 private boolean indexOnStartup = true;
55
56 private String configFile = "lucenemodule.xml";
57
58 private LuceneManager config = null;
59
60 private String configroot;
61
62 /*** The mmbase instance */
63 private MMBase mmb = null;
64
65 /***
66 * Number of tries to get cloud. A second between each try.
67 */
68 private static final int GETCLOUD_NUM_OF_TRIES = 60;
69
70 /***
71 * Time to waite between tries.
72 */
73 private static final long GETCLOUD_INTERVAL_TRIES = 1000L;
74
75 /***
76 * Number of seconds to wait before starting on-startup-index.
77 */
78 private Integer onStartupWait = null;
79
80 /***
81 * @see org.mmbase.module.Module#onload()
82 */
83 public void onload() {
84
85 }
86
87 /***
88 * @see org.mmbase.module.Module#init()
89 */
90 public void init() {
91
92
93 mmb = (MMBase) Module.getModule("mmbaseroot");
94
95
96 String intervalStr = getInitParameter("interval");
97 if (intervalStr == null) {
98 throw new IllegalArgumentException("interval");
99 } else {
100 interval = Long.parseLong(intervalStr) * 1000L * 60L;
101 }
102
103 String startHourStr = getInitParameter("starthour");
104 if (startHourStr == null) {
105 throw new IllegalArgumentException("starthour");
106 } else {
107 startHour = Integer.parseInt(startHourStr);
108 }
109
110
111 String indexOnStartupStr = getInitParameter("index-on-startup");
112 if (indexOnStartupStr != null) {
113 indexOnStartup = Boolean.valueOf(indexOnStartupStr).booleanValue();
114 } else {
115 log.warn("index-on-startup property not set");
116 }
117
118 String onStartupWaitStr = getInitParameter("index-on-startup-wait");
119 if (onStartupWaitStr != null) {
120 onStartupWait = new Integer(onStartupWaitStr);
121 }
122
123 String userConfigFile = getInitParameter("configfile");
124 if (userConfigFile == null) {
125 throw new IllegalArgumentException("configfile");
126 } else {
127 configFile = userConfigFile;
128 }
129
130 config = new LuceneManager();
131
132 configroot = MMBaseContext.getConfigPath();
133
134 config.readConfig(configroot + File.separator + configFile);
135
136
137 if (indexOnStartup) {
138 Thread runOnce = new Thread(new IndexingTimerTask());
139 runOnce.setDaemon(true);
140 runOnce.start();
141 }
142
143
144 timer = new Timer(true);
145
146
147 Calendar cal = Calendar.getInstance();
148 cal.set(Calendar.HOUR_OF_DAY, startHour);
149 cal.set(Calendar.MINUTE, 0);
150 cal.set(Calendar.SECOND, 0);
151
152
153 if (Calendar.getInstance().after(cal)) {
154 cal.add(Calendar.DAY_OF_YEAR, 1);
155 }
156 Date time = cal.getTime();
157
158
159 timer.scheduleAtFixedRate(new IndexingTimerTask(), time, interval);
160 }
161
162 private class IndexingTimerTask extends TimerTask {
163 /***
164 * The thread in which the external links will be checked
165 */
166 public void run() {
167 if (onStartupWait != null) {
168 log.debug("LuceneModule waiting for " + onStartupWait + " seconds");
169 try {
170 Thread.sleep(onStartupWait.intValue() * 1000L);
171 } catch (InterruptedException e) {
172
173 }
174
175 onStartupWait = null;
176 }
177
178 log.info("LuceneModule thread started");
179 startIndexing();
180 }
181 }
182
183 public LuceneManager getLuceneManager() {
184 return config;
185 }
186
187 /***
188 * Start indexing the cloud after MMBase has really started.
189 */
190 private void startIndexing() {
191 try {
192 while (!mmb.hasStarted()) {
193
194 Thread.sleep(60000);
195 }
196 } catch (InterruptedException e) {
197 }
198 Cloud cloud = getCloud();
199
200 log.info("LuceneModule start indexing");
201 config.collectAll(cloud);
202 }
203
204 /***
205 * Get a cloud reference. Wait for one if no reference available yet.
206 *
207 * @return a cloud reference
208 * @throws RuntimeException when timed out
209 */
210 public Cloud getCloud() {
211 RuntimeException lastEx = null;
212 for (int i = 0; i < GETCLOUD_NUM_OF_TRIES; i++) {
213 try {
214 return cloudProvider.getCloud();
215 } catch (RuntimeException ex) {
216 lastEx = ex;
217 try {
218 Thread.sleep(GETCLOUD_INTERVAL_TRIES);
219 } catch (InterruptedException e) {
220
221 }
222 }
223 }
224
225 log.error("can't get cloud: " + lastEx);
226 throw lastEx == null ? new RuntimeException("can't get cloud") : lastEx;
227 }
228 }