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