/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.felix.webconsole.internal.compendium; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.PrintStream; import java.io.PrintWriter; import java.util.Enumeration; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.felix.utils.json.JSONWriter; import org.apache.felix.webconsole.SimpleWebConsolePlugin; import org.apache.felix.webconsole.WebConsoleUtil; import org.apache.felix.webconsole.internal.OsgiManagerPlugin; import org.osgi.framework.Bundle; import org.osgi.framework.Constants; import org.osgi.framework.ServiceReference; import org.osgi.service.log.LogEntry; import org.osgi.service.log.LogReaderService; import org.osgi.service.log.LogService; /** * LogServlet provides support for reading the log messages. */ public class LogServlet extends SimpleWebConsolePlugin implements OsgiManagerPlugin { private static final String LABEL = "logs"; //$NON-NLS-1$ private static final String TITLE = "%logs.pluginTitle"; //$NON-NLS-1$ private static final String CSS[] = { "/res/ui/logs.css" }; //$NON-NLS-1$ private final static int MAX_LOGS = 200; //maximum number of log entries // templates private final String TEMPLATE; /** Default constructor */ public LogServlet() { super(LABEL, TITLE, CATEGORY_OSGI, CSS); // load templates TEMPLATE = readTemplateFile( "/templates/logs.html" ); //$NON-NLS-1$ } /** * @see javax.servlet.http.HttpServlet#doPost(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse) */ protected void doPost( HttpServletRequest req, HttpServletResponse resp ) throws IOException { final int minLevel = WebConsoleUtil.getParameterInt( req, "minLevel", LogService.LOG_DEBUG ); //$NON-NLS-1$ resp.setContentType( "application/json" ); //$NON-NLS-1$ resp.setCharacterEncoding( "utf-8" ); //$NON-NLS-1$ renderJSON( resp.getWriter(), minLevel, trasesEnabled(req) ); } private static boolean trasesEnabled( final HttpServletRequest req ) { String traces = req.getParameter("traces"); //$NON-NLS-1$ return null == traces ? false : Boolean.valueOf( traces ).booleanValue(); } private final void renderJSON( final PrintWriter pw, int minLogLevel, boolean traces ) throws IOException { // create status line final LogReaderService logReaderService = ( LogReaderService ) this.getService( LogReaderService.class .getName() ); JSONWriter jw = new JSONWriter( pw ); jw.object(); jw.key( "status" ); //$NON-NLS-1$ jw.value( logReaderService == null ? Boolean.FALSE : Boolean.TRUE ); jw.key( "data" ); //$NON-NLS-1$ jw.array(); if ( logReaderService != null ) { int index = 0; for ( Enumeration logEntries = logReaderService.getLog(); logEntries.hasMoreElements() && index < MAX_LOGS; ) { LogEntry nextLog = ( LogEntry ) logEntries.nextElement(); if ( nextLog.getLevel() <= minLogLevel ) { logJson( jw, nextLog, index++, traces ); } } } jw.endArray(); jw.endObject(); } /** * @see org.apache.felix.webconsole.AbstractWebConsolePlugin#doGet(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse) */ protected void doGet( HttpServletRequest request, HttpServletResponse response ) throws ServletException, IOException { final int minLevel = WebConsoleUtil.getParameterInt( request, "minLevel", LogService.LOG_DEBUG ); //$NON-NLS-1$ final String info = request.getPathInfo(); if ( info.endsWith( ".json" ) ) //$NON-NLS-1$ { response.setContentType( "application/json" ); //$NON-NLS-1$ response.setCharacterEncoding( "UTF-8" ); //$NON-NLS-1$ PrintWriter pw = response.getWriter(); this.renderJSON( pw, minLevel, trasesEnabled(request) ); return; } super.doGet( request, response ); } /** * @see org.apache.felix.webconsole.AbstractWebConsolePlugin#renderContent(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse) */ protected void renderContent( HttpServletRequest request, HttpServletResponse response ) throws IOException { response.getWriter().print(TEMPLATE); } private static final void logJson( JSONWriter jw, LogEntry info, int index, boolean traces ) throws IOException { jw.object(); jw.key( "id" ); //$NON-NLS-1$ jw.value( String.valueOf( index ) ); jw.key( "received" ); //$NON-NLS-1$ jw.value( info.getTime() ); jw.key( "level" ); //$NON-NLS-1$ jw.value( logLevel( info.getLevel() ) ); jw.key( "raw_level" ); //$NON-NLS-1$ jw.value( info.getLevel() ); jw.key( "message" ); //$NON-NLS-1$ jw.value( info.getMessage() ); jw.key( "service" ); //$NON-NLS-1$ jw.value( serviceDescription( info.getServiceReference() ) ); jw.key( "exception" ); //$NON-NLS-1$ jw.value( exceptionMessage( info.getException(), traces ) ); Bundle bundle = info.getBundle(); if (null != bundle) { jw.key("bundleId"); //$NON-NLS-1$ jw.value(bundle.getBundleId()); String name = (String) bundle.getHeaders().get(Constants.BUNDLE_NAME); if (null == name) { name = bundle.getSymbolicName(); } if (null == name) { name = bundle.getLocation(); } jw.key("bundleName"); //$NON-NLS-1$ jw.value(name); } jw.endObject(); } private static final String serviceDescription( ServiceReference serviceReference ) { if ( serviceReference == null ) { return ""; //$NON-NLS-1$ } return serviceReference.toString(); } private static final String logLevel( int level ) { switch ( level ) { case LogService.LOG_INFO: return "INFO"; //$NON-NLS-1$ case LogService.LOG_WARNING: return "WARNING"; //$NON-NLS-1$ case LogService.LOG_ERROR: return "ERROR"; //$NON-NLS-1$ case LogService.LOG_DEBUG: default: return "DEBUG"; //$NON-NLS-1$ } } private static final ByteArrayOutputStream baos = new ByteArrayOutputStream(); private static final PrintStream printStream = new PrintStream(baos); private static final String exceptionMessage( Throwable e, boolean traces ) { if ( e == null ) { return ""; //$NON-NLS-1$ } if (traces) { String ret = null; synchronized (printStream) { try { e.printStackTrace(printStream); ret = baos.toString(); } finally { baos.reset(); } } return ret; } return e.getClass().getName() + ": " + e.getMessage(); //$NON-NLS-1$ } }