7a61c852280932937fdb53fa3c622a31dfee8a77
[mir.git] / source / mircoders / abuse / FilterEngine.java
1 /*\r
2  * Copyright (C) 2001, 2002 The Mir-coders group\r
3  *\r
4  * This file is part of Mir.\r
5  *\r
6  * Mir is free software; you can redistribute it and/or modify\r
7  * it under the terms of the GNU General Public License as published by\r
8  * the Free Software Foundation; either version 2 of the License, or\r
9  * (at your option) any later version.\r
10  *\r
11  * Mir is distributed in the hope that it will be useful,\r
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
14  * GNU General Public License for more details.\r
15  *\r
16  * You should have received a copy of the GNU General Public License\r
17  * along with Mir; if not, write to the Free Software\r
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\r
19  *\r
20  * In addition, as a special exception, The Mir-coders gives permission to link\r
21  * the code of this program with  any library licensed under the Apache Software License,\r
22  * The Sun (tm) Java Advanced Imaging library (JAI), The Sun JIMI library\r
23  * (or with modified versions of the above that use the same license as the above),\r
24  * and distribute linked combinations including the two.  You must obey the\r
25  * GNU General Public License in all respects for all of the code used other than\r
26  * the above mentioned libraries.  If you modify this file, you may extend this\r
27  * exception to your version of the file, but you are not obligated to do so.\r
28  * If you do not wish to do so, delete this exception statement from your version.\r
29  */\r
30 \r
31 package mircoders.abuse;\r
32 \r
33 import mir.entity.Entity;\r
34 import mir.entity.adapter.EntityAdapter;\r
35 import mir.entity.adapter.EntityAdapterModel;\r
36 import mir.entity.adapter.EntityIteratorAdapter;\r
37 import mir.log.LoggerWrapper;\r
38 import mir.storage.StorageObjectExc;\r
39 import mir.session.Request;\r
40 import mir.config.MirPropertiesConfiguration;\r
41 import mircoders.storage.DatabaseFilter;\r
42 import mircoders.storage.DatabaseFilterGroup;\r
43 import mircoders.global.MirGlobal;\r
44 \r
45 import java.util.*;\r
46 import java.text.SimpleDateFormat;\r
47 \r
48 public class FilterEngine {\r
49   private Map filterTypes;\r
50   private List filterTypeIds;\r
51 \r
52   private List filterGroups;\r
53   private Map idToFilterGroup;\r
54   private LoggerWrapper logger;\r
55   private EntityAdapterModel model;\r
56   private SimpleDateFormat dateFormat;\r
57   private MirPropertiesConfiguration configuration = MirPropertiesConfiguration.instance();\r
58 \r
59   public FilterEngine(EntityAdapterModel aModel) {\r
60     logger = new LoggerWrapper("Global.Abuse.FilterEngine");\r
61     filterGroups = new ArrayList();\r
62     idToFilterGroup = new HashMap();\r
63 \r
64     filterTypes = new HashMap();\r
65     filterTypeIds = new ArrayList();\r
66     try {\r
67       Iterator i = MirGlobal.localizer().openPostings().getAntiAbuseFilterTypes().iterator();\r
68       while (i.hasNext()) {\r
69         FilterType filterType = (FilterType) i.next();\r
70 \r
71         filterTypes.put(filterType.getName(), filterType);\r
72         filterTypeIds.add(filterType.getName());\r
73       }\r
74     }\r
75     catch (Throwable t) {\r
76       throw new RuntimeException(t.getMessage());\r
77     }\r
78 \r
79     model = aModel;\r
80 \r
81     dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");\r
82     dateFormat.setTimeZone(TimeZone.getTimeZone(configuration.getString("Mir.DefaultTimezone")));\r
83     reload();\r
84   }\r
85 \r
86   public Filter testPosting(Entity anEntity, Request aRequest) {\r
87     Iterator i = filterGroups.iterator();\r
88     while (i.hasNext()) {\r
89       FilterGroup group = (FilterGroup) i.next();\r
90       Iterator j = group.getFilters().iterator();\r
91       while (j.hasNext()) {\r
92         Filter filter = (Filter) j.next();\r
93         try {\r
94           if (filter.test(anEntity, aRequest)) {\r
95             return filter;\r
96           }\r
97         }\r
98         catch (Throwable t) {\r
99           logger.warn("Exception thrown while testing filter " + filter.getType() + " ( " + filter.getExpression() + ") " + t.toString());\r
100         }\r
101       }\r
102     }\r
103 \r
104     return null;\r
105   }\r
106 \r
107   public List getFilterTypes() {\r
108     try {\r
109       List result = new ArrayList();\r
110 \r
111       Iterator i = filterTypeIds.iterator();\r
112       while (i.hasNext()) {\r
113         String id = (String) i.next();\r
114 \r
115         Map action = new HashMap();\r
116         action.put("resource", id);\r
117         action.put("identifier", id);\r
118 \r
119         result.add(action);\r
120       }\r
121 \r
122       return result;\r
123     }\r
124     catch (Throwable t) {\r
125       throw new RuntimeException("can't get article actions");\r
126     }\r
127   }\r
128 \r
129   public class FilterGroup {\r
130     private List filters;\r
131     private Entity entity;\r
132     private Map idToFilter;\r
133 \r
134     public FilterGroup(Entity anEntity) {\r
135       this (anEntity, Collections.EMPTY_LIST);\r
136     }\r
137 \r
138     public FilterGroup(Entity anEntity, List aFilters) {\r
139       entity = anEntity;\r
140       filters = new ArrayList();\r
141       idToFilter = new HashMap();\r
142       Iterator i = aFilters.iterator();\r
143 \r
144       while (i.hasNext()) {\r
145         Entity entity = (Entity) i.next();\r
146         try {\r
147           Filter filter = new Filter(entity);\r
148           introduceFilter(filter);\r
149         }\r
150         catch (AbuseExc e) {\r
151         }\r
152       }\r
153     }\r
154 \r
155     public Entity getEntity() {\r
156       return entity;\r
157     }\r
158 \r
159     public EntityAdapter getEntityAdapter() {\r
160       return model.makeEntityAdapter("filterGroup",  entity);\r
161     }\r
162 \r
163     public List getFilterEntityAdapterList() {\r
164       List result = new ArrayList();\r
165 \r
166       Iterator i = filters.iterator();\r
167       while (i.hasNext()) {\r
168         Filter filter = (Filter) i.next();\r
169         result.add(filter.getEntityAdapter());\r
170       }\r
171 \r
172       return result;\r
173     }\r
174 \r
175     public List getFilters() {\r
176       return filters;\r
177     }\r
178 \r
179     public Filter getFilterForId(String anId) {\r
180       Filter result = (Filter) idToFilter.get(anId);\r
181       if (result==null) {\r
182         throw new NullPointerException("No such filter");\r
183       }\r
184 \r
185       return result;\r
186     }\r
187 \r
188     private void introduceFilter(Filter aFilter) {\r
189       filters.add(aFilter);\r
190       idToFilter.put(aFilter.getEntity().getId(), aFilter);\r
191     }\r
192 \r
193     private void removeFilter(Filter aFilter) {\r
194       filters.remove(aFilter);\r
195       idToFilter.remove(aFilter.getEntity().getId());\r
196     }\r
197 \r
198     private void deleteFilter(String anId) {\r
199       Filter filter = getFilterForId(anId);\r
200       removeFilter(filter);\r
201       DatabaseFilter.getInstance().delete(anId);\r
202     }\r
203 \r
204     public void populateFilterEntity(Entity anEntity, String aType, String anExpression,\r
205                              String aComments, String aTag, String anArticleAction,\r
206                              String aCommentAction) {\r
207 \r
208       anEntity.setFieldValue("type", aType);\r
209       anEntity.setFieldValue("expression", anExpression);\r
210       anEntity.setFieldValue("comment", aComments);\r
211       anEntity.setFieldValue("tag", aTag);\r
212       anEntity.setFieldValue("articleaction", anArticleAction);\r
213       anEntity.setFieldValue("commentaction", aCommentAction);\r
214     }\r
215 \r
216     public String updateFilter(String anId, String aType, String anExpression,\r
217                              String aComments, String aTag, String anArticleAction,\r
218                              String aCommentAction) {\r
219 \r
220       try {\r
221         getFilterTypeForId(aType).constructFilterInstance(anExpression);\r
222       }\r
223       catch (AbuseExc e) {\r
224         return e.getMessage();\r
225       }\r
226 \r
227       Entity entity = getFilterForId(anId).getEntity();\r
228       populateFilterEntity(entity, aType, anExpression, aComments, aTag,\r
229           anArticleAction, aCommentAction);\r
230       entity.update();\r
231 \r
232       return "";\r
233     }\r
234 \r
235     public String createFilter(String aType, String anExpression,\r
236                              String aComments, String aTag, String anArticleAction,\r
237                              String aCommentAction) throws StorageObjectExc {\r
238       FilterInstance instance;\r
239 \r
240       try {\r
241         instance = getFilterTypeForId(aType).constructFilterInstance(anExpression);\r
242       }\r
243       catch (AbuseExc e) {\r
244         return e.getMessage();\r
245       }\r
246 \r
247       Entity entity = DatabaseFilter.getInstance().createNewEntity();\r
248       populateFilterEntity(entity, aType, anExpression, aComments, aTag,\r
249           anArticleAction, aCommentAction);\r
250       entity.setFieldValue("priority", "1");\r
251       entity.setFieldValue("filter_group_id", getEntity().getId());\r
252       entity.insert();\r
253 \r
254       Filter filter = new Filter(entity, instance);\r
255       introduceFilter(filter);\r
256 \r
257       return "";\r
258     }\r
259 \r
260     public String getName() {\r
261       return entity.getFieldValue("name");\r
262     }\r
263   }\r
264 \r
265   public class Filter {\r
266     private Entity entity;\r
267     private FilterInstance instance;\r
268 \r
269     public Filter(Entity anEntity) throws AbuseExc {\r
270       this(anEntity, getFilterTypeForId(anEntity.getFieldValue("type")).constructFilterInstance(anEntity.getFieldValue("expression")));\r
271     }\r
272 \r
273     public Filter(Entity anEntity, FilterInstance anInstance) {\r
274       entity = anEntity;\r
275       instance = anInstance;\r
276     }\r
277 \r
278     public Entity getEntity() {\r
279       return entity;\r
280     }\r
281 \r
282     public EntityAdapter getEntityAdapter() {\r
283       return model.makeEntityAdapter("filter", entity);\r
284     }\r
285 \r
286     public void update(String aType, String anExpression, String aComments, String aTag,\r
287                        String anArticleAction, String aCommentAction) throws AbuseExc {\r
288 \r
289       instance = getFilterTypeForId(aType).constructFilterInstance(anExpression);\r
290 \r
291       entity.setFieldValue("type", aType);\r
292       entity.setFieldValue("expression", anExpression);\r
293       entity.setFieldValue("tag", aType);\r
294       entity.setFieldValue("comment", aComments);\r
295       entity.setFieldValue("articleaction", anArticleAction);\r
296       entity.setFieldValue("commentaction", aCommentAction);\r
297       entity.setFieldValue("last_hit", null);\r
298       entity.update();\r
299    }\r
300 \r
301     public void updateLastHit(Date aDate) {\r
302       entity.setFieldValue("last_hit", dateFormat.format(aDate));\r
303       entity.update();\r
304     }\r
305 \r
306     public String getType() {\r
307       return entity.getFieldValue("type");\r
308     }\r
309 \r
310     public String getExpression() {\r
311       return entity.getFieldValue("expression");\r
312     }\r
313 \r
314     public String getTag() {\r
315       return entity.getFieldValue("tag");\r
316     }\r
317 \r
318     public String getComment() {\r
319       return entity.getFieldValue("comment");\r
320     }\r
321 \r
322     public String getArticleAction() {\r
323       return entity.getFieldValue("articleaction");\r
324     }\r
325 \r
326     public String getCommentAction() {\r
327       return entity.getFieldValue("commentaction");\r
328     }\r
329 \r
330     public FilterInstance getInstance() {\r
331       return instance;\r
332     }\r
333 \r
334     public boolean test(Entity anEntity, Request aRequest) {\r
335       return instance.test(anEntity, aRequest);\r
336     }\r
337   }\r
338 \r
339   public synchronized void reload() {\r
340     filterGroups.clear();\r
341     idToFilterGroup.clear();\r
342 \r
343     try {\r
344       Iterator i = new EntityIteratorAdapter("", "priority asc", 100, model, "filterGroup");\r
345       while (i.hasNext()) {\r
346         EntityAdapter entityAdapter = (EntityAdapter) i.next();\r
347         List filters = new ArrayList();\r
348         Iterator j = (Iterator) entityAdapter.get("to_filters");\r
349         while (j.hasNext()) {\r
350           filters.add(((EntityAdapter) j.next()).getEntity());\r
351         }\r
352 \r
353         FilterGroup filterGroup = new FilterGroup(entityAdapter.getEntity(), filters);\r
354         introduceFilterGroup(filterGroup);\r
355       }\r
356     }\r
357     catch (Throwable e) {\r
358       logger.error("Can't load filters: " + e.getMessage());\r
359     }\r
360   }\r
361 \r
362   public synchronized List getFilterGroups() {\r
363     List result = new ArrayList();\r
364     Iterator i = filterGroups.iterator();\r
365     while (i.hasNext()) {\r
366       result.add(((FilterGroup) i.next()).getEntityAdapter());\r
367     }\r
368 \r
369     return result;\r
370   }\r
371 \r
372   public synchronized void updateFilterGroup(String anId, String aName) {\r
373     FilterGroup filterGroup = getFilterGroupForId(anId);\r
374     filterGroup.getEntity().setFieldValue("name", aName);\r
375     filterGroup.getEntity().update();\r
376   }\r
377 \r
378   public synchronized void addFilterGroup(String aName) throws StorageObjectExc {\r
379     Entity entity = DatabaseFilterGroup.getInstance().createNewEntity();\r
380     entity.setFieldValue("name", aName);\r
381     entity.setFieldValue("priority", "1");\r
382     entity.insert();\r
383 \r
384     FilterGroup filterGroup = new FilterGroup(entity);\r
385     introduceFilterGroup(filterGroup);\r
386   }\r
387 \r
388   public synchronized void deleteFilterGroup(String anId) {\r
389 \r
390     FilterGroup filterGroup = getFilterGroupForId(anId);\r
391     removeFilterGroup(filterGroup);\r
392     DatabaseFilter.getInstance().deleteByWhereClause("filter_group_id = " + anId);\r
393     DatabaseFilterGroup.getInstance().delete(anId);\r
394   }\r
395 \r
396   public synchronized void deleteFilter(String aGroupId, String anId) {\r
397     getFilterGroupForId(aGroupId).deleteFilter(anId);\r
398   }\r
399 \r
400 \r
401   public synchronized String updateFilter(String aGroupId, String anId,\r
402                                         String aType, String anExpression,\r
403                                         String aComments,\r
404                                         String aTag,\r
405                                         String anArticleAction,\r
406                                         String aCommentAction) {\r
407     return getFilterGroupForId(aGroupId).updateFilter(anId, aType,\r
408         anExpression, aComments, aTag, anArticleAction, aCommentAction);\r
409   }\r
410 \r
411   public synchronized String addFilter(String aGroupId,\r
412                                        String aType, String anExpression,\r
413                                        String aComments,\r
414                                        String aTag,\r
415                                        String anArticleAction,\r
416                                        String aCommentAction) throws StorageObjectExc {\r
417     return getFilterGroupForId(aGroupId).createFilter(aType, anExpression,\r
418         aComments, aTag, anArticleAction, aCommentAction);\r
419   }\r
420 \r
421 \r
422   public FilterGroup getFilterGroupForId(String anId) {\r
423     FilterGroup result = (FilterGroup) idToFilterGroup.get(anId);\r
424     if (result == null) {\r
425       throw new NullPointerException("No such filter group");\r
426     }\r
427 \r
428     return result;\r
429   }\r
430 \r
431   public Filter getFilterForId(String aGroupId, String anId) {\r
432     return getFilterGroupForId(aGroupId).getFilterForId(anId);\r
433   }\r
434 \r
435 \r
436   public List getFilters(String aFilterGroupId) {\r
437     return getFilterGroupForId(aFilterGroupId).getFilterEntityAdapterList();\r
438   }\r
439 \r
440   private void introduceFilterGroup(FilterGroup aFilterGroup) {\r
441     filterGroups.add(aFilterGroup);\r
442     idToFilterGroup.put(aFilterGroup.getEntity().getId(), aFilterGroup);\r
443   }\r
444 \r
445   private void removeFilterGroup(FilterGroup aFilterGroup) {\r
446     filterGroups.remove(aFilterGroup);\r
447     idToFilterGroup.remove(aFilterGroup.getEntity().getId());\r
448   }\r
449 \r
450   private FilterType getFilterTypeForId(String anId) {\r
451     return (FilterType) filterTypes.get(anId);\r
452   }\r
453 }\r