2 * Copyright (C) 2001, 2002 The Mir-coders group
4 * This file is part of Mir.
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.
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.
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
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.
31 package mircoders.abuse;
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;
45 import java.text.SimpleDateFormat;
47 /** The FilterEngine manages a list of all filters and filter groups.
48 * Use the testPosting() method to apply all filters on an
49 * Entity (for ex. an article or a comment)
51 public class FilterEngine {
52 private Map filterTypes;
53 private List filterTypeIds;
55 private List filterGroups;
56 private Map idToFilterGroup;
57 private LoggerWrapper logger;
58 private EntityAdapterModel model;
59 private SimpleDateFormat dateFormat;
60 private MirPropertiesConfiguration configuration = MirPropertiesConfiguration.instance();
62 public FilterEngine(EntityAdapterModel aModel) {
63 logger = new LoggerWrapper("Global.Abuse.FilterEngine");
64 filterGroups = new ArrayList();
65 idToFilterGroup = new HashMap();
67 filterTypes = new HashMap();
68 filterTypeIds = new ArrayList();
70 Iterator i = MirGlobal.localizer().openPostings().getAntiAbuseFilterTypes().iterator();
72 FilterType filterType = (FilterType) i.next();
74 filterTypes.put(filterType.getName(), filterType);
75 filterTypeIds.add(filterType.getName());
79 throw new RuntimeException(t.getMessage());
84 dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
85 dateFormat.setTimeZone(TimeZone.getTimeZone(configuration.getString("Mir.DefaultTimezone")));
88 /** applies all filters from all filter groups to an Entity.
89 * The entity may be, for example, an article, or a comment.
90 * It returns a filter that matches if it finds one, null otherwise
92 public Filter testPosting(Entity anEntity, Request aRequest) {
93 Iterator i = filterGroups.iterator();
95 FilterGroup group = (FilterGroup) i.next();
96 Iterator j = group.getFilters().iterator();
98 Filter filter = (Filter) j.next();
100 if (filter.test(anEntity, aRequest)) {
104 catch (Throwable t) {
105 logger.warn("Exception thrown while testing filter " + filter.getType() + " ( " + filter.getExpression() + ") " + t.toString());
113 public List getFilterTypes() {
115 List result = new ArrayList();
117 Iterator i = filterTypeIds.iterator();
118 while (i.hasNext()) {
119 String id = (String) i.next();
121 Map action = new HashMap();
122 action.put("resource", id);
123 action.put("identifier", id);
130 catch (Throwable t) {
131 throw new RuntimeException("can't get article actions");
134 /** This class reflects a row of the filter_group
135 * database table. Filters groups allow you to organize
136 * your filters. For example: group1=spammer ,
139 public class FilterGroup {
140 private List filters;
141 private Entity entity;
142 private Map idToFilter;
144 public FilterGroup(Entity anEntity) {
145 this (anEntity, Collections.EMPTY_LIST);
148 public FilterGroup(Entity anEntity, List aFilters) {
150 filters = new ArrayList();
151 idToFilter = new HashMap();
152 Iterator i = aFilters.iterator();
154 while (i.hasNext()) {
155 Entity entity = (Entity) i.next();
157 Filter filter = new Filter(entity);
158 introduceFilter(filter);
165 public Entity getEntity() {
169 public EntityAdapter getEntityAdapter() {
170 return model.makeEntityAdapter("filterGroup", entity);
173 public List getFilterEntityAdapterList() {
174 List result = new ArrayList();
176 Iterator i = filters.iterator();
177 while (i.hasNext()) {
178 Filter filter = (Filter) i.next();
179 result.add(filter.getEntityAdapter());
185 public List getFilters() {
189 public Filter getFilterForId(String anId) {
190 Filter result = (Filter) idToFilter.get(anId);
192 throw new NullPointerException("No such filter");
198 private void introduceFilter(Filter aFilter) {
199 filters.add(aFilter);
200 idToFilter.put(aFilter.getEntity().getId(), aFilter);
203 private void removeFilter(Filter aFilter) {
204 filters.remove(aFilter);
205 idToFilter.remove(aFilter.getEntity().getId());
208 private void deleteFilter(String anId) {
209 Filter filter = getFilterForId(anId);
210 removeFilter(filter);
211 DatabaseFilter.getInstance().delete(anId);
214 public void populateFilterEntity(Entity anEntity, String aType, String anExpression,
215 String aComments, String aTag, String anArticleAction,
216 String aCommentAction) {
218 anEntity.setFieldValue("type", aType);
219 anEntity.setFieldValue("expression", anExpression);
220 anEntity.setFieldValue("comment", aComments);
221 anEntity.setFieldValue("tag", aTag);
222 anEntity.setFieldValue("articleaction", anArticleAction);
223 anEntity.setFieldValue("commentaction", aCommentAction);
226 public String updateFilter(String anId, String aType, String anExpression,
227 String aComments, String aTag, String anArticleAction,
228 String aCommentAction) {
231 getFilterTypeForId(aType).constructFilterInstance(anExpression);
234 return e.getMessage();
237 Entity entity = getFilterForId(anId).getEntity();
238 populateFilterEntity(entity, aType, anExpression, aComments, aTag,
239 anArticleAction, aCommentAction);
245 public String createFilter(String aType, String anExpression,
246 String aComments, String aTag, String anArticleAction,
247 String aCommentAction) throws DatabaseExc {
248 FilterInstance instance;
251 instance = getFilterTypeForId(aType).constructFilterInstance(anExpression);
254 return e.getMessage();
257 Entity entity = DatabaseFilter.getInstance().createNewEntity();
258 populateFilterEntity(entity, aType, anExpression, aComments, aTag,
259 anArticleAction, aCommentAction);
260 entity.setFieldValue("priority", "1");
261 entity.setFieldValue("filter_group_id", getEntity().getId());
264 Filter filter = new Filter(entity, instance);
265 introduceFilter(filter);
270 public String getName() {
271 return entity.getFieldValue("name");
275 /** This class reflects a row of the filter database table.
276 * To actually run a filter on data, use the test() method.
277 * This class will automatically retreive and use the correct
280 public class Filter {
281 private Entity entity;
282 private FilterInstance instance;
284 public Filter(Entity anEntity) throws AbuseExc {
285 this(anEntity, getFilterTypeForId(anEntity.getFieldValue("type")).constructFilterInstance(anEntity.getFieldValue("expression")));
288 public Filter(Entity anEntity, FilterInstance anInstance) {
290 instance = anInstance;
293 public Entity getEntity() {
297 public EntityAdapter getEntityAdapter() {
298 return model.makeEntityAdapter("filter", entity);
301 public void update(String aType, String anExpression, String aComments, String aTag,
302 String anArticleAction, String aCommentAction) throws AbuseExc {
304 instance = getFilterTypeForId(aType).constructFilterInstance(anExpression);
306 entity.setFieldValue("type", aType);
307 entity.setFieldValue("expression", anExpression);
308 entity.setFieldValue("tag", aType);
309 entity.setFieldValue("comment", aComments);
310 entity.setFieldValue("articleaction", anArticleAction);
311 entity.setFieldValue("commentaction", aCommentAction);
312 entity.setFieldValue("last_hit", null);
316 public void updateLastHit(Date aDate) {
317 entity.setFieldValue("last_hit", dateFormat.format(aDate));
321 public String getType() {
322 return entity.getFieldValue("type");
325 public String getExpression() {
326 return entity.getFieldValue("expression");
329 public String getTag() {
330 return entity.getFieldValue("tag");
333 public String getComment() {
334 return entity.getFieldValue("comment");
337 public String getArticleAction() {
338 return entity.getFieldValue("articleaction");
341 public String getCommentAction() {
342 return entity.getFieldValue("commentaction");
345 public FilterInstance getInstance() {
349 public boolean test(Entity anEntity, Request aRequest) {
350 return instance.test(anEntity, aRequest);
354 public synchronized void reload() {
355 filterGroups.clear();
356 idToFilterGroup.clear();
359 Iterator i = new EntityIteratorAdapter("", "priority asc", 100, model, "filterGroup");
360 while (i.hasNext()) {
361 EntityAdapter entityAdapter = (EntityAdapter) i.next();
362 List filters = new ArrayList();
363 Iterator j = (Iterator) entityAdapter.getIterator("to_filters");
364 while (j.hasNext()) {
365 filters.add(((EntityAdapter) j.next()).getEntity());
368 FilterGroup filterGroup = new FilterGroup(entityAdapter.getEntity(), filters);
369 introduceFilterGroup(filterGroup);
372 catch (Throwable e) {
373 logger.error("Can't load filters: " + e.getMessage());
377 public synchronized List getFilterGroups() {
378 List result = new ArrayList();
379 Iterator i = filterGroups.iterator();
380 while (i.hasNext()) {
381 result.add(((FilterGroup) i.next()).getEntityAdapter());
387 public synchronized void updateFilterGroup(String anId, String aName) {
388 FilterGroup filterGroup = getFilterGroupForId(anId);
389 filterGroup.getEntity().setFieldValue("name", aName);
390 filterGroup.getEntity().update();
393 public synchronized void addFilterGroup(String aName) throws DatabaseExc {
394 Entity entity = DatabaseFilterGroup.getInstance().createNewEntity();
395 entity.setFieldValue("name", aName);
396 entity.setFieldValue("priority", "1");
399 FilterGroup filterGroup = new FilterGroup(entity);
400 introduceFilterGroup(filterGroup);
403 public synchronized void deleteFilterGroup(String anId) {
405 FilterGroup filterGroup = getFilterGroupForId(anId);
406 removeFilterGroup(filterGroup);
407 DatabaseFilter.getInstance().deleteByWhereClause("filter_group_id = " + anId);
408 DatabaseFilterGroup.getInstance().delete(anId);
411 public synchronized void deleteFilter(String aGroupId, String anId) {
412 getFilterGroupForId(aGroupId).deleteFilter(anId);
416 public synchronized String updateFilter(String aGroupId, String anId,
417 String aType, String anExpression,
420 String anArticleAction,
421 String aCommentAction) {
422 return getFilterGroupForId(aGroupId).updateFilter(anId, aType,
423 anExpression, aComments, aTag, anArticleAction, aCommentAction);
426 public synchronized String addFilter(String aGroupId,
427 String aType, String anExpression,
430 String anArticleAction,
431 String aCommentAction) throws DatabaseExc {
432 return getFilterGroupForId(aGroupId).createFilter(aType, anExpression,
433 aComments, aTag, anArticleAction, aCommentAction);
437 public FilterGroup getFilterGroupForId(String anId) {
438 FilterGroup result = (FilterGroup) idToFilterGroup.get(anId);
439 if (result == null) {
440 throw new NullPointerException("No such filter group");
446 public Filter getFilterForId(String aGroupId, String anId) {
447 return getFilterGroupForId(aGroupId).getFilterForId(anId);
451 public List getFilters(String aFilterGroupId) {
452 return getFilterGroupForId(aFilterGroupId).getFilterEntityAdapterList();
455 private void introduceFilterGroup(FilterGroup aFilterGroup) {
456 filterGroups.add(aFilterGroup);
457 idToFilterGroup.put(aFilterGroup.getEntity().getId(), aFilterGroup);
460 private void removeFilterGroup(FilterGroup aFilterGroup) {
461 filterGroups.remove(aFilterGroup);
462 idToFilterGroup.remove(aFilterGroup.getEntity().getId());
465 private FilterType getFilterTypeForId(String anId) {
466 return (FilterType) filterTypes.get(anId);