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