cd486ad11698d4fed55dc44583b998cdbfdfedfb
[mir.git] / source / mircoders / global / MirGlobal.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.global;
32
33 import mir.bundle.BasicBundleFactory;
34 import mir.bundle.BundleFactory;
35 import mir.bundle.CascadingBundleFactory;
36 import mir.bundle.PropertiesFileBundleLoader;
37 import mir.config.MirPropertiesConfiguration;
38 import mir.entity.adapter.EntityAdapter;
39 import mir.log.LoggerEngine;
40 import mir.log.LoggerWrapper;
41 import mircoders.accesscontrol.AccessControl;
42 import mircoders.entity.EntityComment;
43 import mircoders.entity.EntityContent;
44 import mircoders.entity.EntityUsers;
45 import mircoders.localizer.MirAdminInterfaceLocalizer;
46 import mircoders.localizer.MirCachingLocalizerDecorator;
47 import mircoders.localizer.MirLocalizer;
48 import mircoders.localizer.MirLocalizerExc;
49 import mircoders.localizer.MirLocalizerFailure;
50
51 import java.util.ArrayList;
52 import java.util.HashMap;
53 import java.util.Iterator;
54 import java.util.List;
55 import java.util.Map;
56
57 public class MirGlobal {
58   static private MirLocalizer localizer;
59   static private ProducerEngine producerEngine;
60   static private Abuse abuse;
61   static private MRUCache mruCache;
62   static private AccessControl accessControl;
63   static private Map articleOperations;
64   static private Map commentOperations;
65   static private final Map loggedInUsers = new HashMap();
66   static private final Map loggedInUserIds = new HashMap();
67   static private LoggerWrapper logger = new LoggerWrapper("Global");
68   static private LoggerWrapper adminUsageLogger = new LoggerWrapper("AdminUsage");
69 //  static private ChangeEngine changeEngine = new ChangeEngine();
70   static private DatabaseEngine databaseEngine;
71
72   static private BundleFactory bundleFactory =
73       new CascadingBundleFactory(
74         new BasicBundleFactory(
75             new PropertiesFileBundleLoader(
76                 config().getHome())));
77
78   private MirGlobal() {
79   }
80
81   public synchronized static MirLocalizer localizer() {
82     String localizerClassName;
83     Class localizerClass;
84
85     if (localizer == null ) {
86       localizerClassName = config().getString("Mir.Localizer", "mirlocal.localizer.basic.MirBasicLocalizer");
87
88       try {
89         localizerClass = Class.forName(localizerClassName);
90       }
91       catch (Throwable t) {
92         throw new MirLocalizerFailure("localizer class '" +
93             localizerClassName + "' not found: ", t);
94       }
95
96       if (!MirLocalizer.class.isAssignableFrom(localizerClass)) {
97         throw new MirLocalizerFailure("localizer class '" +
98             localizerClassName + "' is not assignable from MirLocalizer");
99       }
100
101       try {
102         localizer = new MirCachingLocalizerDecorator((MirLocalizer) localizerClass.newInstance());
103       }
104       catch (Throwable t) {
105         throw new MirLocalizerFailure("localizer class '" +
106             localizerClassName + "' cannot be instantiated: " + t.getMessage(), t);
107       }
108     }
109
110     return localizer;
111   }
112
113   /**
114    * Returns a string that provides some global status information
115    */
116   public static String getStatus() {
117     StringBuffer result = new StringBuffer();
118
119     result.append((Runtime.getRuntime().totalMemory()-Runtime.getRuntime().freeMemory())/(1024*1024));
120     result.append("M in use, ");
121     result.append(Thread.activeCount()).append(" threads, ");
122     result.append(getDatabaseEngine().getStatus());
123
124     return result.toString();
125   }
126
127   synchronized public static Abuse abuse() {
128     if (abuse==null) {
129       try {
130         abuse = new Abuse(localizer().dataModel().adapterModel());
131       }
132       catch (MirLocalizerExc e) {
133         throw new RuntimeException(e.getMessage());
134       }
135     }
136
137     return abuse;
138   }
139
140   /**
141    * returns the global change engine (used to track changed files)
142    */
143 //  public static ChangeEngine getChangeEngine() {
144 //    return changeEngine;
145 //  }
146
147   public static MirPropertiesConfiguration config() {
148     return MirPropertiesConfiguration.instance();
149   }
150
151   synchronized public static DatabaseEngine getDatabaseEngine() {
152     if (databaseEngine==null) {
153       databaseEngine = new DatabaseEngine();
154     }
155
156     return databaseEngine;
157   }
158
159   public static ProducerEngine getProducerEngine() {
160     if (producerEngine == null) {
161       producerEngine = new ProducerEngine();
162     }
163
164     return producerEngine;
165   }
166
167   public static MRUCache mruCache() {
168     synchronized(MirGlobal.class) {
169       if (mruCache == null) {
170         mruCache = new MRUCache();
171       }
172       return mruCache;
173     }
174   }
175
176   synchronized public static AccessControl accessControl() {
177     if (accessControl == null) {
178       accessControl=new AccessControl();
179     }
180
181     return accessControl;
182   }
183
184   public static void performArticleOperation(EntityUsers aUser, EntityContent  anArticle, String anOperation) {
185     MirAdminInterfaceLocalizer.MirSimpleEntityOperation operation = getArticleOperationForName(anOperation);
186
187     try {
188       EntityAdapter user = null;
189       if (aUser!=null) {
190           user = localizer().dataModel().adapterModel().makeEntityAdapter("user", aUser);
191       }
192
193       if (operation!=null) {
194         operation.perform(
195             user,
196             localizer().dataModel().adapterModel().makeEntityAdapter("content", anArticle));
197       }
198     }
199     catch (Throwable t) {
200       throw new MirGlobalFailure(t.getMessage(), t);
201     }
202   }
203
204   public static void performCommentOperation(EntityUsers aUser, EntityComment  aComment, String anOperation) {
205     MirAdminInterfaceLocalizer.MirSimpleEntityOperation operation = getCommentOperationForName(anOperation);
206
207     try {
208       EntityAdapter user = null;
209       if (aUser!=null) {
210           user = localizer().dataModel().adapterModel().makeEntityAdapter("user", aUser);
211       }
212
213       if (operation!=null) {
214         operation.perform(
215             user,
216             localizer().dataModel().adapterModel().makeEntityAdapter("comment", aComment));
217       }
218     }
219     catch (Throwable t) {
220       throw new MirGlobalFailure(t.getMessage(), t);
221     }
222   }
223
224   private synchronized static MirAdminInterfaceLocalizer.MirSimpleEntityOperation
225       getArticleOperationForName(String aName) {
226     try {
227       if (articleOperations == null) {
228         articleOperations = new HashMap();
229         Iterator i = localizer().adminInterface().simpleArticleOperations().iterator();
230         while (i.hasNext()) {
231           MirAdminInterfaceLocalizer.MirSimpleEntityOperation operation =
232               (MirAdminInterfaceLocalizer.MirSimpleEntityOperation) i.next();
233           articleOperations.put(operation.getName(), operation);
234         }
235       }
236
237       return (MirAdminInterfaceLocalizer.MirSimpleEntityOperation) articleOperations.get(aName);
238     }
239     catch (Throwable t) {
240       throw new MirGlobalFailure(t.getMessage(), t);
241     }
242   }
243
244   private synchronized static MirAdminInterfaceLocalizer.MirSimpleEntityOperation
245       getCommentOperationForName(String aName) {
246     try {
247       if (commentOperations == null) {
248         commentOperations = new HashMap();
249         Iterator i = localizer().adminInterface().simpleCommentOperations().iterator();
250         while (i.hasNext()) {
251           MirAdminInterfaceLocalizer.MirSimpleEntityOperation operation =
252               (MirAdminInterfaceLocalizer.MirSimpleEntityOperation) i.next();
253           commentOperations.put(operation.getName(), operation);
254         }
255       }
256
257       return (MirAdminInterfaceLocalizer.MirSimpleEntityOperation) commentOperations.get(aName);
258     }
259     catch (Throwable t) {
260       throw new MirGlobalFailure(t.getMessage(), t);
261     }
262   }
263
264   public static boolean isUserLoggedIn(String anId) {
265     synchronized (loggedInUserIds) {
266       return loggedInUserIds.containsKey(anId);
267     }
268   }
269
270   public static List getLoggedInUsers() {
271     List result = new ArrayList();
272
273     synchronized (loggedInUsers) {
274       Iterator i = loggedInUsers.entrySet().iterator();
275
276       while (i.hasNext()) {
277         Map.Entry entry = (Map.Entry) i.next();
278
279         Map item = new HashMap();
280         item.put("name", entry.getKey());
281         item.put("count", entry.getValue());
282         result.add(item);
283       }
284     }
285
286     return result;
287   }
288
289   public static BundleFactory getBundleFactory() {
290     return bundleFactory;
291   }
292
293   public static void registerLogin(String aName, String anId) {
294     modifyLoggedInCount(aName, anId, 1);
295   }
296
297   public static void registerLogout(String aName, String anId) {
298     modifyLoggedInCount(aName, anId, -1);
299   }
300
301   private static void modifyLoggedInCount(String aName, String anId, int aModifier) {
302     synchronized (loggedInUsers) {
303       Integer count = (Integer) loggedInUsers.get(aName);
304       if (count==null)
305         count = new Integer(0);
306
307       if (count.intValue()+aModifier<=0) {
308         loggedInUsers.remove(aName);
309       }
310       else {
311         loggedInUsers.put(aName, new Integer(count.intValue() + aModifier));
312       }
313     }
314
315     synchronized (loggedInUserIds) {
316       Integer count = (Integer) loggedInUserIds.get(anId);
317       if (count==null)
318         count = new Integer(0);
319
320       if (count.intValue()+aModifier<=0) {
321         loggedInUserIds.remove(anId);
322       }
323       else {
324         loggedInUserIds.put(anId, new Integer(count.intValue() + aModifier));
325       }
326     }
327   }
328
329   /**
330    * Called whenever a modifying admin action occurs. Used to log
331    * the action, if admin activity logging is turned on,
332    */
333   public static void logAdminUsage(EntityUsers aUser, String anObject, String aDescription) {
334     try {
335       if (config().getString("Mir.Admin.LogAdminActivity", "0").equals("1")) {
336         String user = "unknown (" + aUser.toString() + ")";
337         if (aUser != null)
338           user = aUser.getFieldValue("login");
339         adminUsageLogger.info(user + " | " + anObject + " | " + aDescription);
340       }
341     }
342     catch (Throwable t) {
343       logger.error("Error while logging admin usage ("+
344           aUser.toString()+", "+aDescription+"): " +t.toString());
345     }
346   }
347
348   /**
349    * Reloads all reloadable configurations, such as the producer subsystem.
350    */
351   public static void reloadConfigurations() throws MirGlobalExc, MirGlobalFailure {
352     getProducerEngine().reloadConfiguration();
353     try {
354       LoggerEngine.reload();
355     }
356     catch (Throwable e) {
357       throw new MirGlobalFailure(e);
358     }
359     getBundleFactory().reload();
360   }
361 }
362
363