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.common.utils.ExceptionUtils;
042import org.nuxeo.ecm.admin.repo.RepoStat;
043import org.nuxeo.ecm.admin.repo.RepoStatInfo;
044import org.nuxeo.ecm.admin.runtime.PlatformVersionHelper;
045import org.nuxeo.ecm.admin.runtime.RuntimeInstrospection;
046import org.nuxeo.ecm.admin.runtime.SimplifiedServerInfo;
047import org.nuxeo.ecm.core.api.CoreInstance;
048import org.nuxeo.ecm.core.api.PathRef;
049import org.nuxeo.ecm.core.api.repository.Repository;
050import org.nuxeo.ecm.core.api.repository.RepositoryManager;
051import org.nuxeo.ecm.core.blob.binary.BinaryManagerStatus;
052import org.nuxeo.ecm.core.storage.sql.management.SQLRepositoryStatus;
053import org.nuxeo.ecm.platform.ui.web.auth.NXAuthConstants;
054import org.nuxeo.ecm.platform.ui.web.util.BaseURL;
055import org.nuxeo.runtime.api.Framework;
056
057/**
058 * Seam Bean to export System info.
059 */
060@Name("systemInfo")
061@Scope(CONVERSATION)
062public class SystemInfoManager implements Serializable {
063
064    private static final Log log = LogFactory.getLog(SystemInfoManager.class);
065
066    protected static final String RESTART_PATH = "site/connectClient/restartView";
067
068    private static final long serialVersionUID = 1L;
069
070    protected List<Repository> repositories;
071
072    protected String currentRepositoryName;
073
074    protected RepoStat runningStat;
075
076    protected RepoStatInfo statResult;
077
078    protected volatile boolean binaryManagerStatusInvalidation;
079
080    protected volatile BinaryManagerStatus binaryManagerStatus;
081
082    protected boolean binariesGCDelete;
083
084    protected boolean binariesWereDeleted;
085
086    // *********************************
087    // Host info Management
088
089    public String getHostInfo() {
090
091        StringBuilder sb = new StringBuilder();
092
093        sb.append("\nOS : ");
094        sb.append(System.getProperty("os.name"));
095        sb.append(" (");
096        sb.append(System.getProperty("os.arch"));
097        sb.append(")");
098
099        sb.append("\n");
100
101        sb.append("\nCPU(s) : ");
102        sb.append(Runtime.getRuntime().availableProcessors());
103
104        sb.append("\n");
105
106        sb.append("\nJVM : ");
107        sb.append(System.getProperty("java.runtime.name"));
108        sb.append(" ");
109        sb.append(System.getProperty("java.runtime.version"));
110        sb.append(" - build ");
111        sb.append(System.getProperty("java.vm.version"));
112        sb.append(" (");
113        sb.append(System.getProperty("java.vendor"));
114        sb.append(")");
115
116        sb.append("\n");
117
118        sb.append("\nPlatform language : ");
119        sb.append(System.getProperty("user.language"));
120        sb.append("  ");
121        sb.append(System.getenv("LANG"));
122
123        sb.append("\n");
124
125        sb.append("\nJava Memory:");
126        sb.append("\n  Heap size  : ");
127        sb.append(Runtime.getRuntime().totalMemory() / (1024 * 1024));
128        sb.append(" MB");
129        sb.append("\n  Used       : ");
130        sb.append((Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory()) / (1024 * 1024));
131        sb.append(" MB");
132        sb.append("\n  Free       : ");
133        sb.append(Runtime.getRuntime().freeMemory() / (1024 * 1024));
134        sb.append(" MB");
135        sb.append("\n  Max size   : ");
136        sb.append(Runtime.getRuntime().maxMemory() / (1024 * 1024));
137        sb.append(" MB");
138
139        return sb.toString();
140    }
141
142    public String getUptime() {
143        RuntimeMXBean bean = ManagementFactory.getRuntimeMXBean();
144        long ut = bean.getUptime();
145        long uts = ut / 1000;
146
147        StringBuffer sb = new StringBuffer("Nuxeo Server UpTime : ");
148        long nbDays = uts / (24 * 3600);
149        if (nbDays > 0) {
150            sb.append(nbDays + " days, ");
151            uts = uts % (24 * 3600);
152        }
153        long nbHours = uts / 3600;
154        sb.append(nbHours + " h ");
155        uts = uts % 3600;
156
157        long nbMin = uts / 60;
158        sb.append(nbMin + " m ");
159        uts = uts % 60;
160
161        sb.append(uts + " s  ");
162
163        return sb.toString();
164    }
165
166    @Factory(value = "nuxeoPlatformIdentifier", scope = ScopeType.APPLICATION)
167    public String getNuxeoPlatformIdentifier() {
168        return PlatformVersionHelper.getPlatformFilter();
169    }
170
171    @Factory(value = "nuxeoServerInfo", scope = ScopeType.EVENT)
172    public SimplifiedServerInfo getNuxeoServerInfo() {
173        return RuntimeInstrospection.getInfo();
174    }
175
176    public boolean isBundleDeployed(String bundleId) {
177        return RuntimeInstrospection.getBundleIds().contains(bundleId);
178    }
179
180    // *********************************
181    // Repo settings Management
182
183    public boolean isMultiRepo() {
184        return listAvailableRepositories().size() > 1;
185    }
186
187    public List<Repository> listAvailableRepositories() {
188        if (repositories == null) {
189            RepositoryManager repositoryManager = Framework.getLocalService(RepositoryManager.class);
190            repositories = new ArrayList<Repository>(repositoryManager.getRepositories());
191            currentRepositoryName = repositoryManager.getDefaultRepositoryName();
192        }
193        return repositories;
194    }
195
196    public String getCurrentRepositoryName() {
197        if (currentRepositoryName == null) {
198            listAvailableRepositories();
199        }
200        return currentRepositoryName;
201    }
202
203    public void setCurrentRepositoryName(String name) {
204        currentRepositoryName = name;
205    }
206
207    public int getOpenSessionNumber() {
208        return CoreInstance.getInstance().getNumberOfSessions();
209    }
210
211    public int getActiveSessionNumber() {
212        SQLRepositoryStatus status = new SQLRepositoryStatus();
213        return status.getActiveSessionsCount();
214    }
215
216    // *********************************
217    // Repo stats Management
218
219    public void startRepoStats() {
220        if (runningStat != null) {
221            return;
222        }
223
224        statResult = null;
225        runningStat = new RepoStat(getCurrentRepositoryName(), 5, true);
226        runningStat.run(new PathRef("/"));
227    }
228
229    public boolean isStatInfoInProgress() {
230        if (isStatInfoAvailable()) {
231            return false;
232        }
233        return runningStat != null;
234    }
235
236    public boolean isStatInfoAvailable() {
237        if (statResult != null) {
238            return true;
239        }
240        if (runningStat != null) {
241            if (!runningStat.isRunning()) {
242                statResult = runningStat.getInfo();
243                Contexts.getEventContext().remove("repoStatResult");
244                runningStat = null;
245                return true;
246            }
247        }
248        return false;
249    }
250
251    @Factory(value = "repoStatResult", scope = ScopeType.EVENT)
252    public RepoStatInfo getStatInfo() {
253        return statResult;
254    }
255
256    public String getRepoUsage() {
257        StringBuilder sb = new StringBuilder();
258
259        int nbSessions = CoreInstance.getInstance().getNumberOfSessions();
260
261        sb.append("Number of open repository session : ");
262        sb.append(nbSessions);
263
264        RepoStat stat = new RepoStat("default", 5, true);
265        stat.run(new PathRef("/"));
266
267        try {
268            Thread.sleep(100);
269            do {
270                Thread.sleep(1000);
271            } while (stat.isRunning());
272        } catch (InterruptedException e) {
273            throw ExceptionUtils.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}