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