View Javadoc
1   /*
2    * Copyright 2012-2021 CodeLibs Project and the Others.
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    *     http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
13   * either express or implied. See the License for the specific language
14   * governing permissions and limitations under the License.
15   */
16  package org.codelibs.fess.helper;
17  
18  import java.util.ArrayList;
19  import java.util.Calendar;
20  import java.util.List;
21  
22  import org.codelibs.core.lang.ThreadUtil;
23  import org.codelibs.fess.exception.FessSystemException;
24  
25  public class IntervalControlHelper {
26  
27      protected volatile boolean crawlerRunning = true;
28  
29      protected long crawlerWaitMillis = 10000;
30  
31      protected List<IntervalRule> ruleList = new ArrayList<>();
32  
33      public void checkCrawlerStatus() {
34          while (!crawlerRunning) {
35              ThreadUtil.sleepQuietly(crawlerWaitMillis);
36          }
37      }
38  
39      public void delayByRules() {
40          final long delay = getDelay();
41          if (delay > 0) {
42              ThreadUtil.sleep(delay);
43          }
44      }
45  
46      protected long getDelay() {
47          if (ruleList.isEmpty()) {
48              return 0;
49          }
50          final Calendar cal = getCurrentCal();
51          final int h = cal.get(Calendar.HOUR_OF_DAY);
52          final int m = cal.get(Calendar.MINUTE);
53          final int d = cal.get(Calendar.DAY_OF_WEEK); // SUN(1) - SAT(7)
54          for (final IntervalRule rule : ruleList) {
55              if (rule.isTarget(h, m, d)) {
56                  return rule.getDelay();
57              }
58          }
59          return 0;
60      }
61  
62      protected Calendar getCurrentCal() {
63          final Calendar cal = Calendar.getInstance();
64          cal.setTimeInMillis(System.currentTimeMillis());
65          return cal;
66      }
67  
68      public void addIntervalRule(final String from, final String to, final String days, final long delay) {
69          ruleList.add(new IntervalRule(from, to, days, delay));
70      }
71  
72      public boolean isCrawlerRunning() {
73          return crawlerRunning;
74      }
75  
76      public void setCrawlerRunning(final boolean crawlerRunning) {
77          this.crawlerRunning = crawlerRunning;
78      }
79  
80      public static class IntervalRule {
81          protected int fromHours;
82  
83          protected int fromMinutes;
84  
85          protected int toHours;
86  
87          protected int toMinutes;
88  
89          protected long delay;
90  
91          protected int[] days;
92  
93          protected boolean reverse;
94  
95          public IntervalRule(final String from, final String to, final String days, final long delay) {
96              final int[] fints = parseTime(from);
97              fromHours = fints[0];
98              fromMinutes = fints[1];
99              final int[] tints = parseTime(to);
100             toHours = tints[0];
101             toMinutes = tints[1];
102             final String[] values = days.split(",");
103             final List<Integer> list = new ArrayList<>();
104             for (final String value : values) {
105                 try {
106                     list.add(Integer.parseInt(value.trim()));
107                 } catch (final NumberFormatException e) {}
108             }
109             this.days = new int[list.size()];
110             for (int i = 0; i < list.size(); i++) {
111                 this.days[i] = list.get(i);
112             }
113             this.delay = delay;
114             reverse = compareTime(fromHours, fromMinutes, toHours, toMinutes) < 0;
115         }
116 
117         public long getDelay() {
118             return delay;
119         }
120 
121         public boolean isTarget(final int hours, final int minutes, final int day) {
122             if (!reverse) {
123                 return compareTime(fromHours, fromMinutes, hours, minutes) >= 0 && compareTime(hours, minutes, toHours, toMinutes) >= 0
124                         && isInDays(day);
125             }
126             if ((compareTime(hours, minutes, toHours, toMinutes) >= 0 && isInDays(day + 1))
127                     || (compareTime(fromHours, fromMinutes, hours, minutes) >= 0 && isInDays(day))) {
128                 return true;
129             }
130             return false;
131         }
132 
133         private boolean isInDays(final int day) {
134             if (days.length == 0) {
135                 return true;
136             }
137             int value;
138             if (day == 8) {
139                 value = 1;
140             } else {
141                 value = day;
142             }
143             for (final int d : days) {
144                 if (d == value) {
145                     return true;
146                 }
147             }
148             return false;
149         }
150 
151         protected int compareTime(final int h1, final int m1, final int h2, final int m2) {
152             if (h1 < h2) {
153                 return 1;
154             }
155             if (h1 == h2) {
156                 if (m1 == m2) {
157                     return 0;
158                 }
159                 if (m1 < m2) {
160                     return 1;
161                 }
162             }
163             return -1;
164         }
165     }
166 
167     protected static int[] parseTime(final String time) {
168         final String[] froms = time.split(":");
169         if (froms.length != 2) {
170             throw new FessSystemException("Invalid format: " + time);
171         }
172         final int[] values = new int[2];
173         values[0] = Integer.parseInt(froms[0]);
174         if (values[0] < 0 || values[0] > 23) {
175             throw new FessSystemException("Invalid format: " + time);
176         }
177         values[1] = Integer.parseInt(froms[1]);
178         if (values[1] < 0 || values[1] > 59) {
179             throw new FessSystemException("Invalid format: " + time);
180         }
181         return values;
182     }
183 
184     public void setCrawlerWaitMillis(final long crawlerWaitMillis) {
185         this.crawlerWaitMillis = crawlerWaitMillis;
186     }
187 
188 }