keycloak-uncached

Details

diff --git a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/server-info.html b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/server-info.html
index 34c9a84..5590f95 100755
--- a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/server-info.html
+++ b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/server-info.html
@@ -8,10 +8,81 @@
         </tr>
         <tr>
             <td>Server Time</td>
-            <td>{{serverInfo.serverTime}} (<a data-ng-click="serverInfoUpdate()">update</a>)</td>
+            <td>{{serverInfo.serverTime}} (<a style="cursor: pointer" data-ng-click="serverInfoUpdate()">update</a>)</td>
+        </tr>
+        <tr>
+            <td>Server Uptime</td>
+            <td>{{serverInfo.serverUptime}}</td>
+        </tr>
+        <tr>
+            <td>Current Working Directory</td>
+            <td>{{serverInfo.systemInfo.userDir}}</td>
+        </tr>
+        <tr>
+            <td>Java Version</td>
+            <td>{{serverInfo.systemInfo.javaVersion}}</td>
+        </tr>
+        <tr>
+            <td>Java Vendor</td>
+            <td>{{serverInfo.systemInfo.javaVendor}}</td>
+        </tr>
+        <tr>
+            <td>Java Runtime</td>
+            <td>{{serverInfo.systemInfo.javaRuntime}}</td>
+        </tr>
+        <tr>
+            <td>Java VM</td>
+            <td>{{serverInfo.systemInfo.javaVm}}</td>
+        </tr>
+        <tr>
+            <td>Java VM Version</td>
+            <td>{{serverInfo.systemInfo.javaVmVersion}}</td>
+        </tr>
+        <tr>
+            <td>Java Home</td>
+            <td>{{serverInfo.systemInfo.javaHome}}</td>
+        </tr>
+        <tr>
+            <td>User Name</td>
+            <td>{{serverInfo.systemInfo.userName}}</td>
+        </tr>
+        <tr>
+            <td>User Timezone</td>
+            <td>{{serverInfo.systemInfo.userTimezone}}</td>
+        </tr>
+        <tr>
+            <td>User Locale</td>
+            <td>{{serverInfo.systemInfo.userLocale}}</td>
+        </tr>
+        <tr>
+            <td>System Encoding</td>
+            <td>{{serverInfo.systemInfo.fileEncoding}}</td>
+        </tr>
+        <tr>
+            <td>Operating System</td>
+            <td>{{serverInfo.systemInfo.osName}} {{serverInfo.systemInfo.osVersion}}</td>
+        </tr>
+        <tr>
+            <td>OS Architecture</td>
+            <td>{{serverInfo.systemInfo.osArchitecture}}</td>
         </tr>
     </table>
-
+    
+    <h3>Java VM Memory Statistics</h3>
+    <table class="table table-striped table-bordered">
+        <tr>
+            <td>Total Memory</td>
+            <td>{{serverInfo.memoryInfo.totalFormated}}</td>
+        </tr>
+        <tr>
+            <td>Free Memory</td>
+            <td>{{serverInfo.memoryInfo.freeFormated}} ({{serverInfo.memoryInfo.freePercentage}}%)</td>
+        </tr>
+        <tr>
+            <td>Used Memory</td>
+            <td>{{serverInfo.memoryInfo.usedFormated}}</td>
+        </tr>
+   	</table>
     <fieldset>
         <legend collapsed>Providers</legend>
 
diff --git a/model/api/src/main/java/org/keycloak/models/KeycloakSessionFactory.java b/model/api/src/main/java/org/keycloak/models/KeycloakSessionFactory.java
index cbb3da2..8266550 100755
--- a/model/api/src/main/java/org/keycloak/models/KeycloakSessionFactory.java
+++ b/model/api/src/main/java/org/keycloak/models/KeycloakSessionFactory.java
@@ -18,6 +18,8 @@ public interface KeycloakSessionFactory extends ProviderEventManager {
     <T extends Provider> ProviderFactory<T> getProviderFactory(Class<T> clazz, String id);
 
     List<ProviderFactory> getProviderFactories(Class<? extends Provider> clazz);
+    
+    long getServerStartupTimestamp();
 
     void close();
 }
diff --git a/services/src/main/java/org/keycloak/services/DefaultKeycloakSessionFactory.java b/services/src/main/java/org/keycloak/services/DefaultKeycloakSessionFactory.java
index e312aa0..c5be21b 100755
--- a/services/src/main/java/org/keycloak/services/DefaultKeycloakSessionFactory.java
+++ b/services/src/main/java/org/keycloak/services/DefaultKeycloakSessionFactory.java
@@ -28,6 +28,8 @@ public class DefaultKeycloakSessionFactory implements KeycloakSessionFactory {
     private Map<Class<? extends Provider>, Map<String, ProviderFactory>> factoriesMap = new HashMap<Class<? extends Provider>, Map<String, ProviderFactory>>();
     protected CopyOnWriteArrayList<ProviderEventListener> listeners = new CopyOnWriteArrayList<ProviderEventListener>();
 
+    protected long serverStartupTimestamp;
+    
     @Override
     public void register(ProviderEventListener listener) {
         listeners.add(listener);
@@ -46,6 +48,8 @@ public class DefaultKeycloakSessionFactory implements KeycloakSessionFactory {
     }
 
     public void init() {
+        serverStartupTimestamp = System.currentTimeMillis();
+        
         ProviderManager pm = new ProviderManager(getClass().getClassLoader(), Config.scope().getArray("providers"));
 
         for (Spi spi : ServiceLoader.load(Spi.class, getClass().getClassLoader())) {
@@ -148,4 +152,12 @@ public class DefaultKeycloakSessionFactory implements KeycloakSessionFactory {
         return factory.getClass().getPackage().getName().startsWith("org.keycloak");
     }
 
+    /**
+     * @return timestamp of Keycloak server startup
+     */
+    @Override
+    public long getServerStartupTimestamp() {
+        return serverStartupTimestamp;
+    }
+
 }
diff --git a/services/src/main/java/org/keycloak/services/resources/admin/ServerInfoAdminResource.java b/services/src/main/java/org/keycloak/services/resources/admin/ServerInfoAdminResource.java
index 4f1c225..c600b92 100755
--- a/services/src/main/java/org/keycloak/services/resources/admin/ServerInfoAdminResource.java
+++ b/services/src/main/java/org/keycloak/services/resources/admin/ServerInfoAdminResource.java
@@ -1,5 +1,18 @@
 package org.keycloak.services.resources.admin;
 
+import java.util.Collections;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+import java.util.ServiceLoader;
+import java.util.Set;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.core.Context;
+
 import org.keycloak.Version;
 import org.keycloak.broker.provider.IdentityProvider;
 import org.keycloak.broker.provider.IdentityProviderFactory;
@@ -24,17 +37,6 @@ import org.keycloak.representations.idm.ProtocolMapperRepresentation;
 import org.keycloak.representations.idm.ProtocolMapperTypeRepresentation;
 import org.keycloak.social.SocialIdentityProvider;
 
-import javax.ws.rs.GET;
-import javax.ws.rs.core.Context;
-import java.util.Collections;
-import java.util.Date;
-import java.util.HashMap;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Map;
-import java.util.ServiceLoader;
-import java.util.Set;
-
 /**
  * @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
  */
@@ -55,6 +57,7 @@ public class ServerInfoAdminResource {
         ServerInfoRepresentation info = new ServerInfoRepresentation();
         info.version = Version.VERSION;
         info.serverTime = new Date().toString();
+        info.serverStartupTime = session.getKeycloakSessionFactory().getServerStartupTimestamp();
         setSocialProviders(info);
         setIdentityProviders(info);
         setThemes(info);
@@ -187,12 +190,115 @@ public class ServerInfoAdminResource {
             info.clientImporters.add(data);
         }
     }
+    
+    public static class MemoryInfo{
+        
+        public long getTotal(){
+            return Runtime.getRuntime().maxMemory();
+        }
+        
+        public String getTotalFormated(){
+            return formatMemory(getTotal());
+        }
+        
+        public long getFree(){
+            return getTotal() - getUsed();
+        }
+
+        public String getFreeFormated(){
+            return formatMemory(getFree());
+        }
+
+        public long getUsed(){
+            return Runtime.getRuntime().totalMemory();
+        }
+        
+        public String getUsedFormated(){
+            return formatMemory(getUsed());
+        }
+        
+        public long getFreePercentage(){
+            return getFree()*100/getTotal();
+        }
+        
+        private String formatMemory(long bytes){
+            if(bytes > 1024L*1024L){
+                return bytes/(1024L *1024L) + " MB"; 
+            } else if(bytes > 1024L){
+                return bytes/(1024L) + " kB"; 
+            } else {
+                return bytes + " B";
+            }
+        }
+        
+    }
 
+    public static class SystemInfo {
+        public String getJavaVersion(){
+            return System.getProperty("java.version");
+        }
+        
+        public String getJavaVendor(){
+            return System.getProperty("java.vendor");
+        }
+        
+        public String getJavaVm(){
+            return System.getProperty("java.vm.name");
+        }
+        
+        public String getJavaVmVersion(){
+            return System.getProperty("java.vm.version");
+        }
+
+        public String getJavaRuntime(){
+            return System.getProperty("java.runtime.name");
+        }
+
+        public String getJavaHome(){
+            return System.getProperty("java.home");
+        }
+        
+        public String getOsName(){
+            return System.getProperty("os.name");
+        }
+        
+        public String getOsArchitecture(){
+            return System.getProperty("os.arch");
+        }
+        
+        public String getOsVersion(){
+            return System.getProperty("os.version");
+        }
+
+        public String getFileEncoding(){
+            return System.getProperty("file.encoding");
+        }
+        
+        public String getUserName(){
+            return System.getProperty("user.name");
+        }
+        
+        public String getUserDir(){
+            return System.getProperty("user.dir");
+        }
+        
+        public String getUserTimezone(){
+            return System.getProperty("user.timezone");
+        }
+        
+        public String getUserLocale(){
+            return (new Locale(System.getProperty("user.country"),System.getProperty("user.language")).toString());
+        }
+        
+    }
+    
     public static class ServerInfoRepresentation {
 
         private String version;
 
         private String serverTime;
+        
+        private long serverStartupTime;
 
         private Map<String, List<String>> themes;
 
@@ -211,10 +317,55 @@ public class ServerInfoAdminResource {
 
         public ServerInfoRepresentation() {
         }
+        
+        public SystemInfo getSystemInfo(){
+            return new SystemInfo();
+        }
+        
+        public MemoryInfo getMemoryInfo(){
+            return new MemoryInfo();
+        }
 
         public String getServerTime() {
             return serverTime;
         }
+        
+        /**
+         * @return server startup time formatted
+         */
+        public String getServerStartupTime() {
+            return (new Date(serverStartupTime)).toString();
+        }
+        
+        /**
+         * @return server uptime in millis
+         */
+        public long getServerUptimeMillis(){
+            return System.currentTimeMillis() - serverStartupTime;
+        }
+        
+        /**
+         * @return server uptime formatted like "0 days, 10 hours, 24 minutes, 55 seconds"
+         */
+        public String getServerUptime(){
+            long diffInSeconds = getServerUptimeMillis()/1000;
+            long diff[] = new long[] { 0, 0, 0, 0 };
+            /* sec */diff[3] = (diffInSeconds >= 60 ? diffInSeconds % 60 : diffInSeconds);
+            /* min */diff[2] = (diffInSeconds = (diffInSeconds / 60)) >= 60 ? diffInSeconds % 60 : diffInSeconds;
+            /* hours */diff[1] = (diffInSeconds = (diffInSeconds / 60)) >= 24 ? diffInSeconds % 24 : diffInSeconds;
+            /* days */diff[0] = (diffInSeconds = (diffInSeconds / 24));
+
+            return String.format(
+                "%d day%s, %d hour%s, %d minute%s, %d second%s",
+                diff[0],
+                diff[0] != 1 ? "s" : "",
+                diff[1],
+                diff[1] != 1 ? "s" : "",
+                diff[2],
+                diff[2] != 1 ? "s" : "",
+                diff[3],
+                diff[3] != 1 ? "s" : "");
+        }
 
         public String getVersion() {
             return version;