001/*
002 * (C) Copyright 2006-2011 Nuxeo SA (http://nuxeo.com/) and others.
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 *     http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 *
016 * Contributors:
017 *     Thierry Delprat
018 *     Florent Guillaume
019 */
020package org.nuxeo.ecm.admin;
021
022import static org.jboss.seam.ScopeType.CONVERSATION;
023
024import java.io.IOException;
025import java.io.Serializable;
026import java.lang.management.ManagementFactory;
027import java.lang.management.RuntimeMXBean;
028import java.util.ArrayList;
029import java.util.List;
030
031import javax.faces.context.FacesContext;
032import javax.servlet.http.HttpServletRequest;
033
034import org.apache.commons.logging.Log;
035import org.apache.commons.logging.LogFactory;
036import org.jboss.seam.ScopeType;
037import org.jboss.seam.annotations.Factory;
038import org.jboss.seam.annotations.Name;
039import org.jboss.seam.annotations.Scope;
040import org.jboss.seam.contexts.Contexts;
041import org.nuxeo.ecm.admin.repo.RepoStat;
042import org.nuxeo.ecm.admin.repo.RepoStatInfo;
043import org.nuxeo.ecm.admin.runtime.PlatformVersionHelper;
044import org.nuxeo.ecm.admin.runtime.RuntimeInstrospection;
045import org.nuxeo.ecm.admin.runtime.SimplifiedServerInfo;
046import org.nuxeo.ecm.core.api.CoreSessionService;
047import org.nuxeo.ecm.core.api.PathRef;
048import org.nuxeo.ecm.core.api.repository.Repository;
049import org.nuxeo.ecm.core.api.repository.RepositoryManager;
050import org.nuxeo.ecm.core.blob.binary.BinaryManagerStatus;
051import org.nuxeo.ecm.core.storage.sql.management.SQLRepositoryStatus;
052import org.nuxeo.ecm.platform.ui.web.auth.NXAuthConstants;
053import org.nuxeo.ecm.platform.ui.web.util.BaseURL;
054import org.nuxeo.runtime.api.Framework;
055
056/**
057 * Seam Bean to export System info.
058 */
059@Name("systemInfo")
060@Scope(CONVERSATION)
061public class SystemInfoManager implements Serializable {
062
063    private static final Log log = LogFactory.getLog(SystemInfoManager.class);
064
065    protected static final String RESTART_PATH = "site/connectClient/restartView";
066
067    private static final long serialVersionUID = 1L;
068
069    protected List<Repository> repositories;
070
071    protected String currentRepositoryName;
072
073    protected RepoStat runningStat;
074
075    protected RepoStatInfo statResult;
076
077    protected volatile boolean binaryManagerStatusInvalidation;
078
079    protected volatile BinaryManagerStatus binaryManagerStatus;
080
081    protected boolean binariesGCDelete;
082
083    protected boolean binariesWereDeleted;
084
085    // *********************************
086    // Host info Management
087
088    public String getHostInfo() {
089
090        StringBuilder sb = new StringBuilder();
091
092        sb.append("\nOS : ");
093        sb.append(System.getProperty("os.name"));
094        sb.append(" (");
095        sb.append(System.getProperty("os.arch"));
096        sb.append(")");
097
098        sb.append("\n");
099
100        sb.append("\nCPU(s) : ");
101        sb.append(Runtime.getRuntime().availableProcessors());
102
103        sb.append("\n");
104
105        sb.append("\nJVM : ");
106        sb.append(System.getProperty("java.runtime.name"));
107        sb.append(" ");
108        sb.append(System.getProperty("java.runtime.version"));
109        sb.append(" - build ");
110        sb.append(System.getProperty("java.vm.version"));
111        sb.append(" (");
112        sb.append(System.getProperty("java.vendor"));
113        sb.append(")");
114
115        sb.append("\n");
116
117        sb.append("\nPlatform language : ");
118        sb.append(System.getProperty("user.language"));
119        sb.append("  ");
120        sb.append(System.getenv("LANG"));
121
122        sb.append("\n");
123
124        sb.append("\nJava Memory:");
125        sb.append("\n  Heap size  : ");
126        sb.append(Runtime.getRuntime().totalMemory() / (1024 * 1024));
127        sb.append(" MB");
128        sb.append("\n  Used       : ");
129        sb.append((Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory()) / (1024 * 1024));
130        sb.append(" MB");
131        sb.append("\n  Free       : ");
132        sb.append(Runtime.getRuntime().freeMemory() / (1024 * 1024));
133        sb.append(" MB");
134        sb.append("\n  Max size   : ");
135        sb.append(Runtime.getRuntime().maxMemory() / (1024 * 1024));
136        sb.append(" MB");
137
138        return sb.toString();
139    }
140
141    public String getUptime() {
142        RuntimeMXBean bean = ManagementFactory.getRuntimeMXBean();
143        long ut = bean.getUptime();
144        long uts = ut / 1000;
145
146        StringBuffer sb = new StringBuffer("Nuxeo Server UpTime : ");
147        long nbDays = uts / (24 * 3600);
148        if (nbDays > 0) {
149            sb.append(nbDays + " days, ");
150            uts = uts % (24 * 3600);
151        }
152        long nbHours = uts / 3600;
153        sb.append(nbHours + " h ");
154        uts = uts % 3600;
155
156        long nbMin = uts / 60;
157        sb.append(nbMin + " m ");
158        uts = uts % 60;
159
160        sb.append(uts + " s  ");
161
162        return sb.toString();
163    }
164
165    @Factory(value = "nuxeoPlatformIdentifier", scope = ScopeType.APPLICATION)
166    public String getNuxeoPlatformIdentifier() {
167        return PlatformVersionHelper.getPlatformFilter();
168    }
169
170    @Factory(value = "nuxeoServerInfo", scope = ScopeType.EVENT)
171    public SimplifiedServerInfo getNuxeoServerInfo() {
172        return RuntimeInstrospection.getInfo();
173    }
174
175    public boolean isBundleDeployed(String bundleId) {
176        return RuntimeInstrospection.getBundleIds().contains(bundleId);
177    }
178
179    // *********************************
180    // Repo settings Management
181
182    public boolean isMultiRepo() {
183        return listAvailableRepositories().size() > 1;
184    }
185
186    public List<Repository> listAvailableRepositories() {
187        if (repositories == null) {
188            RepositoryManager repositoryManager = Framework.getService(RepositoryManager.class);
189            repositories = new ArrayList<Repository>(repositoryManager.getRepositories());
190            currentRepositoryName = repositoryManager.getDefaultRepositoryName();
191        }
192        return repositories;
193    }
194
195    public String getCurrentRepositoryName() {
196        if (currentRepositoryName == null) {
197            listAvailableRepositories();
198        }
199        return currentRepositoryName;
200    }
201
202    public void setCurrentRepositoryName(String name) {
203        currentRepositoryName = name;
204    }
205
206    public int getOpenSessionNumber() {
207        return Framework.getService(CoreSessionService.class).getNumberOfOpenCoreSessions();
208    }
209
210    public int getActiveSessionNumber() {
211        SQLRepositoryStatus status = new SQLRepositoryStatus();
212        return status.getActiveSessionsCount();
213    }
214
215    // *********************************
216    // Repo stats Management
217
218    public void startRepoStats() {
219        if (runningStat != null) {
220            return;
221        }
222
223        statResult = null;
224        runningStat = new RepoStat(getCurrentRepositoryName(), 5, true);
225        runningStat.run(new PathRef("/"));
226    }
227
228    public boolean isStatInfoInProgress() {
229        if (isStatInfoAvailable()) {
230            return false;
231        }
232        return runningStat != null;
233    }
234
235    public boolean isStatInfoAvailable() {
236        if (statResult != null) {
237            return true;
238        }
239        if (runningStat != null) {
240            if (!runningStat.isRunning()) {
241                statResult = runningStat.getInfo();
242                Contexts.getEventContext().remove("repoStatResult");
243                runningStat = null;
244                return true;
245            }
246        }
247        return false;
248    }
249
250    @Factory(value = "repoStatResult", scope = ScopeType.EVENT)
251    public RepoStatInfo getStatInfo() {
252        return statResult;
253    }
254
255    public String getRepoUsage() {
256        StringBuilder sb = new StringBuilder();
257
258        int nbSessions = Framework.getService(CoreSessionService.class).getNumberOfOpenCoreSessions();
259
260        sb.append("Number of open repository session : ");
261        sb.append(nbSessions);
262
263        RepoStat stat = new RepoStat("default", 5, true);
264        stat.run(new PathRef("/"));
265
266        try {
267            Thread.sleep(100);
268            do {
269                Thread.sleep(1000);
270            } while (stat.isRunning());
271        } catch (InterruptedException e) {
272            Thread.currentThread().interrupt();
273            throw new RuntimeException(e);
274        }
275
276        sb.append(stat.getInfo().toString());
277
278        return sb.toString();
279    }
280
281    // *********************************
282    // Server restart
283
284    public String restartServer() {
285        FacesContext context = FacesContext.getCurrentInstance();
286        HttpServletRequest request = (HttpServletRequest) context.getExternalContext().getRequest();
287        request.setAttribute(NXAuthConstants.DISABLE_REDIRECT_REQUEST_KEY, Boolean.TRUE);
288        String restartUrl = BaseURL.getBaseURL(request) + RESTART_PATH;
289        try {
290            context.getExternalContext().redirect(restartUrl);
291        } catch (IOException e) {
292            log.error("Error while redirecting to restart page", e);
293        }
294        return null;
295    }
296
297    // *********************************
298    // Binaries GC
299
300    public void setBinariesGCDelete(boolean binariesGCDelete) {
301        this.binariesGCDelete = binariesGCDelete;
302    }
303
304    public boolean getBinariesGCDelete() {
305        return binariesGCDelete;
306    }
307
308    public boolean getBinariesWereDeleted() {
309        return binariesWereDeleted;
310    }
311
312    public void startBinariesGC() {
313        if (isBinariesGCInProgress()) {
314            return;
315        }
316        binaryManagerStatus = null;
317        binaryManagerStatusInvalidation = false;
318        Runnable gcTask = new BinariesGCTask(binariesGCDelete);
319        Thread t = new Thread(gcTask, "NuxeoBinariesGCUI");
320        t.setDaemon(true);
321        t.start();
322        binariesWereDeleted = binariesGCDelete;
323        binariesGCDelete = false;
324    }
325
326    public boolean isBinariesGCInProgress() {
327        return new SQLRepositoryStatus().isBinariesGCInProgress();
328    }
329
330    public boolean isBinaryManagerStatusAvailable() {
331        if (binaryManagerStatusInvalidation) {
332            // invalidate Seam value in context
333            Contexts.getEventContext().remove("binaryManagerStatus");
334            binaryManagerStatusInvalidation = false;
335        }
336        return binaryManagerStatus != null;
337    }
338
339    @Factory(value = "binaryManagerStatus", scope = ScopeType.EVENT)
340    public BinaryManagerStatus getBinaryManagerStatus() {
341        return binaryManagerStatus;
342
343    }
344
345    public class BinariesGCTask implements Runnable {
346        public boolean delete;
347
348        public BinariesGCTask(boolean delete) {
349            this.delete = delete;
350        }
351
352        @Override
353        public void run() {
354            try {
355                binaryManagerStatus = new SQLRepositoryStatus().gcBinaries(delete);
356                binaryManagerStatusInvalidation = true;
357            } catch (RuntimeException e) {
358                log.error("Error while executing BinariesGCTask", e);
359            }
360        }
361    }
362
363}