rebuilding head
[mir.git] / source / mircoders / global / MirGlobal.java
index 59c61e1..2306d96 100755 (executable)
 \r
 package mircoders.global;\r
 \r
-import java.util.*;\r
+import java.util.HashMap;\r
+import java.util.Iterator;\r
+import java.util.List;\r
+import java.util.Map;\r
+import java.util.Vector;\r
 \r
+import mir.bundle.BasicBundleFactory;\r
+import mir.bundle.BundleFactory;\r
+import mir.bundle.CascadingBundleFactory;\r
+import mir.bundle.PropertiesFileBundleLoader;\r
 import mir.config.MirPropertiesConfiguration;\r
-import mir.config.MirPropertiesConfiguration.PropertiesConfigExc;\r
+import mir.entity.adapter.EntityAdapter;\r
+import mir.log.LoggerEngine;\r
+import mir.log.LoggerWrapper;\r
 import mir.misc.ConfigException;\r
+import mircoders.accesscontrol.AccessControl;\r
+import mircoders.entity.EntityComment;\r
+import mircoders.entity.EntityContent;\r
+import mircoders.entity.EntityUsers;\r
+import mircoders.localizer.MirAdminInterfaceLocalizer;\r
 import mircoders.localizer.MirCachingLocalizerDecorator;\r
-import mircoders.localizer.*;\r
-import mircoders.accesscontrol.*;\r
-import mircoders.entity.*;\r
-import mir.entity.adapter.*;\r
+import mircoders.localizer.MirLocalizer;\r
 \r
 public class MirGlobal {\r
-  static private MirPropertiesConfiguration configuration;\r
   static private MirLocalizer localizer;\r
   static private ProducerEngine producerEngine;\r
   static private Abuse abuse;\r
@@ -50,6 +61,18 @@ public class MirGlobal {
   static private AccessControl accessControl;\r
   static private Map articleOperations;\r
   static private Map commentOperations;\r
+  static private Map loggedInUsers = new HashMap();\r
+  static private Map loggedInUserIds = new HashMap();\r
+  static private LoggerWrapper logger = new LoggerWrapper("Global");\r
+  static private LoggerWrapper adminUsageLogger = new LoggerWrapper("AdminUsage");\r
+//  static private ChangeEngine changeEngine = new ChangeEngine();\r
+  static private DatabaseEngine databaseEngine;\r
+\r
+  static private BundleFactory bundleFactory =\r
+      new CascadingBundleFactory(\r
+        new BasicBundleFactory(\r
+            new PropertiesFileBundleLoader(\r
+                config().getHome())));\r
 \r
   public synchronized static MirLocalizer localizer() {\r
     String localizerClassName;\r
@@ -62,44 +85,66 @@ public class MirGlobal {
         localizerClass = Class.forName(localizerClassName);\r
       }\r
       catch (Throwable t) {\r
-        throw new ConfigException("localizer class '" + localizerClassName + "' not found: " + t.toString());\r
+        throw new ConfigException("localizer class '" +\r
+            localizerClassName + "' not found: " + t.toString());\r
       }\r
 \r
       if (!(MirLocalizer.class.isAssignableFrom(localizerClass)))\r
-        throw new ConfigException("localizer class '" + localizerClassName + "' is not assignable from MirLocalizer");\r
+        throw new ConfigException("localizer class '" +\r
+            localizerClassName + "' is not assignable from MirLocalizer");\r
 \r
       try {\r
         localizer = new MirCachingLocalizerDecorator((MirLocalizer) localizerClass.newInstance());\r
       }\r
       catch (Throwable t) {\r
-        throw new ConfigException("localizer class '" + localizerClassName + "' cannot be instantiated: " + t.toString());\r
+        throw new ConfigException("localizer class '" +\r
+            localizerClassName + "' cannot be instantiated: " + t.toString());\r
       }\r
     }\r
 \r
     return localizer;\r
   }\r
 \r
-  public static Abuse abuse() {\r
-    if (abuse==null) {\r
-      synchronized(MirGlobal.class) {\r
-        if (abuse==null)\r
-          abuse = new Abuse();\r
-      }\r
-    }\r
+  /**\r
+   * Returns a string that provides some global status information\r
+   */\r
+  public static String getStatus() {\r
+    StringBuffer result = new StringBuffer();\r
+\r
+    result.append((Runtime.getRuntime().totalMemory()-Runtime.getRuntime().freeMemory())/(1024*1024));\r
+    result.append("M in use, ");\r
+    result.append(Thread.currentThread().activeCount()).append(" threads, ");\r
+    result.append(getDatabaseEngine().getStatus());\r
+\r
+    return result.toString();\r
+  }\r
+\r
+  public synchronized static Abuse abuse() {\r
+    if (abuse==null)\r
+      abuse = new Abuse();\r
 \r
     return abuse;\r
   }\r
 \r
+  /**\r
+   * returns the global change engine (used to track changed files)\r
+   */\r
+//  public static ChangeEngine getChangeEngine() {\r
+//    return changeEngine;\r
+//  }\r
+\r
   public static MirPropertiesConfiguration config() {\r
-    try {\r
-      return MirPropertiesConfiguration.instance();\r
-    }\r
-    catch (PropertiesConfigExc e) {\r
-      throw new RuntimeException(e.getMessage());\r
-    }\r
+    return MirPropertiesConfiguration.instance();\r
+  }\r
+\r
+  public synchronized static DatabaseEngine getDatabaseEngine() {\r
+    if (databaseEngine==null)\r
+      databaseEngine = new DatabaseEngine();\r
+\r
+    return databaseEngine;\r
   }\r
 \r
-  public static ProducerEngine producerEngine() {\r
+  public static ProducerEngine getProducerEngine() {\r
     if (producerEngine == null) {\r
       producerEngine = new ProducerEngine();\r
     }\r
@@ -128,12 +173,18 @@ public class MirGlobal {
     MirAdminInterfaceLocalizer.MirSimpleEntityOperation operation = getArticleOperationForName(anOperation);\r
 \r
     try {\r
+      EntityAdapter user = null;\r
+      if (aUser!=null)\r
+          user = localizer().dataModel().adapterModel().makeEntityAdapter("user", aUser);\r
+\r
       if (operation!=null)\r
         operation.perform(\r
-            localizer().dataModel().adapterModel().makeEntityAdapter("user", aUser),\r
+            user,\r
             localizer().dataModel().adapterModel().makeEntityAdapter("content", anArticle));\r
     }\r
     catch (Throwable t) {\r
+      t.printStackTrace(logger.asPrintWriter(LoggerWrapper.DEBUG_MESSAGE));\r
+\r
       throw new RuntimeException(t.toString());\r
     }\r
   }\r
@@ -142,9 +193,13 @@ public class MirGlobal {
     MirAdminInterfaceLocalizer.MirSimpleEntityOperation operation = getCommentOperationForName(anOperation);\r
 \r
     try {\r
+      EntityAdapter user = null;\r
+      if (aUser!=null)\r
+          user = localizer().dataModel().adapterModel().makeEntityAdapter("user", aUser);\r
+\r
       if (operation!=null)\r
         operation.perform(\r
-            localizer().dataModel().adapterModel().makeEntityAdapter("user", aUser),\r
+            user,\r
             localizer().dataModel().adapterModel().makeEntityAdapter("comment", aComment));\r
     }\r
     catch (Throwable t) {\r
@@ -152,13 +207,15 @@ public class MirGlobal {
     }\r
   }\r
 \r
-  private synchronized static MirAdminInterfaceLocalizer.MirSimpleEntityOperation getArticleOperationForName(String aName) {\r
+  private synchronized static MirAdminInterfaceLocalizer.MirSimpleEntityOperation\r
+      getArticleOperationForName(String aName) {\r
     try {\r
       if (articleOperations == null) {\r
         articleOperations = new HashMap();\r
         Iterator i = localizer().adminInterface().simpleArticleOperations().iterator();\r
         while (i.hasNext()) {\r
-          MirAdminInterfaceLocalizer.MirSimpleEntityOperation operation = (MirAdminInterfaceLocalizer.MirSimpleEntityOperation) i.next();\r
+          MirAdminInterfaceLocalizer.MirSimpleEntityOperation operation =\r
+              (MirAdminInterfaceLocalizer.MirSimpleEntityOperation) i.next();\r
           articleOperations.put(operation.getName(), operation);\r
         }\r
       }\r
@@ -170,13 +227,15 @@ public class MirGlobal {
     }\r
   }\r
 \r
-  private synchronized static MirAdminInterfaceLocalizer.MirSimpleEntityOperation getCommentOperationForName(String aName) {\r
+  private synchronized static MirAdminInterfaceLocalizer.MirSimpleEntityOperation\r
+      getCommentOperationForName(String aName) {\r
     try {\r
       if (commentOperations == null) {\r
         commentOperations = new HashMap();\r
         Iterator i = localizer().adminInterface().simpleCommentOperations().iterator();\r
         while (i.hasNext()) {\r
-          MirAdminInterfaceLocalizer.MirSimpleEntityOperation operation = (MirAdminInterfaceLocalizer.MirSimpleEntityOperation) i.next();\r
+          MirAdminInterfaceLocalizer.MirSimpleEntityOperation operation =\r
+              (MirAdminInterfaceLocalizer.MirSimpleEntityOperation) i.next();\r
           commentOperations.put(operation.getName(), operation);\r
         }\r
       }\r
@@ -188,6 +247,103 @@ public class MirGlobal {
     }\r
   }\r
 \r
+  public static boolean isUserLoggedIn(String anId) {\r
+    synchronized (loggedInUserIds) {\r
+      return loggedInUserIds.containsKey(anId);\r
+    }\r
+  }\r
+\r
+  public static List getLoggedInUsers() {\r
+    List result = new Vector();\r
+\r
+    synchronized (loggedInUsers) {\r
+      Iterator i = loggedInUsers.entrySet().iterator();\r
+\r
+      while (i.hasNext()) {\r
+        Map.Entry entry = (Map.Entry) i.next();\r
+\r
+        Map item = new HashMap();\r
+        item.put("name", entry.getKey());\r
+        item.put("count", entry.getValue());\r
+        result.add(item);\r
+      }\r
+    }\r
+\r
+    return result;\r
+  }\r
+\r
+  public static BundleFactory getBundleFactory() {\r
+    return bundleFactory;\r
+  }\r
+\r
+  public static void registerLogin(String aName, String anId) {\r
+    modifyLoggedInCount(aName, anId, 1);\r
+  }\r
+\r
+  public static void registerLogout(String aName, String anId) {\r
+    modifyLoggedInCount(aName, anId, -1);\r
+  }\r
+\r
+  private static void modifyLoggedInCount(String aName, String anId, int aModifier) {\r
+    synchronized (loggedInUsers) {\r
+      Integer count = (Integer) loggedInUsers.get(aName);\r
+      if (count==null)\r
+        count = new Integer(0);\r
+\r
+      if (count.intValue()+aModifier<=0) {\r
+        loggedInUsers.remove(aName);\r
+      }\r
+      else {\r
+        loggedInUsers.put(aName, new Integer(count.intValue() + aModifier));\r
+      }\r
+    }\r
+\r
+    synchronized (loggedInUserIds) {\r
+      Integer count = (Integer) loggedInUserIds.get(anId);\r
+      if (count==null)\r
+        count = new Integer(0);\r
+\r
+      if (count.intValue()+aModifier<=0) {\r
+        loggedInUserIds.remove(anId);\r
+      }\r
+      else {\r
+        loggedInUserIds.put(anId, new Integer(count.intValue() + aModifier));\r
+      }\r
+    }\r
+  }\r
+\r
+  /**\r
+   * Called whenever a modifying admin action occurs. Used to log\r
+   * the action, if admin activity logging is turned on,\r
+   */\r
+  public static void logAdminUsage(EntityUsers aUser, String anObject, String aDescription) {\r
+    try {\r
+      if (config().getString("Mir.Admin.LogAdminActivity", "0").equals("1")) {\r
+        String user = "unknown (" + aUser.toString() + ")";\r
+        if (aUser != null)\r
+          user = aUser.getFieldValue("login");\r
+        adminUsageLogger.info(user + " | " + anObject + " | " + aDescription);\r
+      }\r
+    }\r
+    catch (Throwable t) {\r
+      logger.error("Error while logging admin usage ("+\r
+          aUser.toString()+", "+aDescription+"): " +t.toString());\r
+    }\r
+  }\r
+\r
+  /**\r
+   * Reloads all reloadable configurations, such as the producer subsystem.\r
+   */\r
+  public static void reloadConfigurations() throws MirGlobalExc, MirGlobalFailure {\r
+    getProducerEngine().reloadConfiguration();\r
+    try {\r
+      LoggerEngine.reload();\r
+    }\r
+    catch (Throwable e) {\r
+      throw new MirGlobalFailure(e);\r
+    }\r
+    getBundleFactory().reload();\r
+  }\r
 }\r
 \r
 \r