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