You are viewing a plain text version of this content. The canonical link for it is here.
Posted to scm@excalibur.apache.org by le...@apache.org on 2004/08/05 17:09:39 UTC
svn commit: rev 35739 - in excalibur/trunk/containerkit/instrument/mgr-http/src/java/org/apache/excalibur/instrument/manager/http: . server
Author: leif
Date: Thu Aug 5 08:09:39 2004
New Revision: 35739
Added:
excalibur/trunk/containerkit/instrument/mgr-http/src/java/org/apache/excalibur/instrument/manager/http/FavIconHandler.java
excalibur/trunk/containerkit/instrument/mgr-http/src/java/org/apache/excalibur/instrument/manager/http/XMLCreateSamplesHandler.java
excalibur/trunk/containerkit/instrument/mgr-http/src/java/org/apache/excalibur/instrument/manager/http/XMLSampleLeasesHandler.java
excalibur/trunk/containerkit/instrument/mgr-http/src/java/org/apache/excalibur/instrument/manager/http/favicon.ico (contents, props changed)
Modified:
excalibur/trunk/containerkit/instrument/mgr-http/src/java/org/apache/excalibur/instrument/manager/http/AbstractXMLHandler.java
excalibur/trunk/containerkit/instrument/mgr-http/src/java/org/apache/excalibur/instrument/manager/http/InstrumentManagerHTTPConnector.java
excalibur/trunk/containerkit/instrument/mgr-http/src/java/org/apache/excalibur/instrument/manager/http/SampleChartHandler.java
excalibur/trunk/containerkit/instrument/mgr-http/src/java/org/apache/excalibur/instrument/manager/http/XMLSnapshotsHandler.java
excalibur/trunk/containerkit/instrument/mgr-http/src/java/org/apache/excalibur/instrument/manager/http/server/AbstractHTTPURLHandler.java
excalibur/trunk/containerkit/instrument/mgr-http/src/java/org/apache/excalibur/instrument/manager/http/server/HTTPServer.java
excalibur/trunk/containerkit/instrument/mgr-http/src/java/org/apache/excalibur/instrument/manager/http/server/HTTPURLHandler.java
Log:
Add support for batch updates.
Handle requests for the favicon.ico image.
Add an optional access log.
Modified: excalibur/trunk/containerkit/instrument/mgr-http/src/java/org/apache/excalibur/instrument/manager/http/AbstractXMLHandler.java
==============================================================================
--- excalibur/trunk/containerkit/instrument/mgr-http/src/java/org/apache/excalibur/instrument/manager/http/AbstractXMLHandler.java (original)
+++ excalibur/trunk/containerkit/instrument/mgr-http/src/java/org/apache/excalibur/instrument/manager/http/AbstractXMLHandler.java Thu Aug 5 08:09:39 2004
@@ -85,7 +85,7 @@
+ "name=\"" + makeSafeAttribute( manager.getName() ) + "\" "
+ "description=\"" + makeSafeAttribute( manager.getDescription() ) + "\" "
+ "state-version=\"" + manager.getStateVersion() + "\" "
- + "read-only=\"" + readOnly + "\">" );
+ + "batched-updates=\"true\" read-only=\"" + readOnly + "\">" );
String childIndent = indent + INDENT;
Added: excalibur/trunk/containerkit/instrument/mgr-http/src/java/org/apache/excalibur/instrument/manager/http/FavIconHandler.java
==============================================================================
--- (empty file)
+++ excalibur/trunk/containerkit/instrument/mgr-http/src/java/org/apache/excalibur/instrument/manager/http/FavIconHandler.java Thu Aug 5 08:09:39 2004
@@ -0,0 +1,89 @@
+/*
+ * Copyright 2002-2004 The Apache Software Foundation
+ * Licensed 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.excalibur.instrument.manager.http;
+
+import com.sun.image.codec.jpeg.JPEGCodec;
+import com.sun.image.codec.jpeg.JPEGEncodeParam;
+import com.sun.image.codec.jpeg.JPEGImageEncoder;
+
+import java.awt.Graphics;
+import java.awt.image.BufferedImage;
+import java.io.BufferedInputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.io.UnsupportedEncodingException;
+import java.util.Map;
+
+import org.apache.excalibur.instrument.manager.http.server.AbstractHTTPURLHandler;
+import org.apache.excalibur.instrument.manager.http.server.HTTPRedirect;
+import org.apache.excalibur.instrument.manager.http.server.URLCoder;
+import org.apache.excalibur.instrument.manager.DefaultInstrumentManager;
+import org.apache.excalibur.instrument.manager.InstrumentSampleDescriptor;
+import org.apache.excalibur.instrument.manager.InstrumentSampleSnapshot;
+import org.apache.excalibur.instrument.manager.NoSuchInstrumentSampleException;
+
+/**
+ * Serves up a favicon.ico file.
+ *
+ * @author <a href="mailto:dev@avalon.apache.org">Avalon Development Team</a>
+ * @version CVS $Revision: 1.9 $ $Date: 2004/03/06 14:01:28 $
+ * @since 4.1
+ */
+public class FavIconHandler
+ extends AbstractHTTPURLHandler
+{
+ /*---------------------------------------------------------------
+ * Constructors
+ *-------------------------------------------------------------*/
+ /**
+ * Creates a new FavIconHandler.
+ */
+ public FavIconHandler()
+ {
+ super( "/favicon.ico", CONTENT_TYPE_IMAGE_X_ICON,
+ InstrumentManagerHTTPConnector.ENCODING );
+ }
+
+ /*---------------------------------------------------------------
+ * AbstractHandler Methods
+ *-------------------------------------------------------------*/
+ /**
+ * Handles the specified request.
+ *
+ * @param The full path being handled.
+ * @param parameters A Map of the parameters in the request.
+ * @param os The OutputStream to write the result to.
+ */
+ public void doGet( String path, Map parameters, OutputStream os )
+ throws IOException
+ {
+ String imageResource = "favicon.ico";
+ BufferedInputStream is =
+ new BufferedInputStream( getClass().getResourceAsStream( imageResource ) );
+ byte[] favIcon;
+ try {
+ favIcon = new byte[is.available()];
+ is.read( favIcon, 0, favIcon.length );
+ } finally {
+ is.close();
+ }
+ // Now write the image out to the client.
+ os.write( favIcon );
+ }
+}
+
Modified: excalibur/trunk/containerkit/instrument/mgr-http/src/java/org/apache/excalibur/instrument/manager/http/InstrumentManagerHTTPConnector.java
==============================================================================
--- excalibur/trunk/containerkit/instrument/mgr-http/src/java/org/apache/excalibur/instrument/manager/http/InstrumentManagerHTTPConnector.java (original)
+++ excalibur/trunk/containerkit/instrument/mgr-http/src/java/org/apache/excalibur/instrument/manager/http/InstrumentManagerHTTPConnector.java Thu Aug 5 08:09:39 2004
@@ -166,9 +166,12 @@
m_readOnly = configuration.getAttributeAsBoolean( "read-only", false );
+ String accessLogFile = configuration.getAttribute( "access-log", null );
+
m_httpServer = new HTTPServer( m_port, m_bindAddr );
m_httpServer.enableLogging( getLogger().getChildLogger( "server" ) );
m_httpServer.setInstrumentableName( "server" );
+ m_httpServer.setAccessLogFile( accessLogFile );
addChildInstrumentable( m_httpServer );
}
@@ -198,7 +201,11 @@
initAndRegisterHandler(
new XMLSampleLeaseHandler( m_manager, this ), nameBase + "sample-lease" );
initAndRegisterHandler(
+ new XMLSampleLeasesHandler( m_manager, this ), nameBase + "sample-leases" );
+ initAndRegisterHandler(
new XMLCreateSampleHandler( m_manager, this ), nameBase + "create-sample" );
+ initAndRegisterHandler(
+ new XMLCreateSamplesHandler( m_manager, this ), nameBase + "create-samples" );
initAndRegisterHandler( new XMLGCHandler( m_manager ), nameBase + "gc" );
}
}
@@ -217,6 +224,7 @@
nameBase + "sample" );
initAndRegisterHandler( new SampleChartHandler(
m_manager, m_chartWidth, m_chartHeight, m_antialias ), "sample-chart" );
+ initAndRegisterHandler( new FavIconHandler(), "favicon" );
if ( !m_readOnly )
{
Modified: excalibur/trunk/containerkit/instrument/mgr-http/src/java/org/apache/excalibur/instrument/manager/http/SampleChartHandler.java
==============================================================================
--- excalibur/trunk/containerkit/instrument/mgr-http/src/java/org/apache/excalibur/instrument/manager/http/SampleChartHandler.java (original)
+++ excalibur/trunk/containerkit/instrument/mgr-http/src/java/org/apache/excalibur/instrument/manager/http/SampleChartHandler.java Thu Aug 5 08:09:39 2004
@@ -64,7 +64,6 @@
/**
* Creates a new SampleChartHandler.
*
- * @param path The path handled by this handler.
* @param manager Reference to the instrument manager interface.
* @param width Default image width.
* @param height Default image height.
Added: excalibur/trunk/containerkit/instrument/mgr-http/src/java/org/apache/excalibur/instrument/manager/http/XMLCreateSamplesHandler.java
==============================================================================
--- (empty file)
+++ excalibur/trunk/containerkit/instrument/mgr-http/src/java/org/apache/excalibur/instrument/manager/http/XMLCreateSamplesHandler.java Thu Aug 5 08:09:39 2004
@@ -0,0 +1,166 @@
+/*
+ * Copyright 2002-2004 The Apache Software Foundation
+ * Licensed 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.excalibur.instrument.manager.http;
+
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.util.Map;
+
+import org.apache.excalibur.instrument.manager.http.server.HTTPRedirect;
+import org.apache.excalibur.instrument.manager.DefaultInstrumentManager;
+import org.apache.excalibur.instrument.manager.InstrumentDescriptor;
+import org.apache.excalibur.instrument.manager.InstrumentSampleDescriptor;
+import org.apache.excalibur.instrument.manager.NoSuchInstrumentException;
+
+/**
+ * Handler which can be used to create multiple samples at once.
+ *
+ * @author <a href="mailto:dev@avalon.apache.org">Avalon Development Team</a>
+ * @since 1.2
+ */
+public class XMLCreateSamplesHandler
+ extends AbstractXMLHandler
+{
+ /** Reference to the connector. */
+ private InstrumentManagerHTTPConnector m_connector;
+
+ /*---------------------------------------------------------------
+ * Constructors
+ *-------------------------------------------------------------*/
+ /**
+ * Creates a new XMLCreateSamplesHandler.
+ *
+ * @param manager Reference to the DefaultInstrumentManager.
+ * @param connector The InstrumentManagerHTTPConnector.
+ */
+ public XMLCreateSamplesHandler( DefaultInstrumentManager manager,
+ InstrumentManagerHTTPConnector connector )
+ {
+ super( "/create-samples.xml", manager );
+
+ m_connector = connector;
+ }
+
+ /*---------------------------------------------------------------
+ * AbstractHTTPURLHandler Methods
+ *-------------------------------------------------------------*/
+ /**
+ * Handles the specified request.
+ *
+ * @param The full path being handled.
+ * @param parameters A Map of the parameters in the request.
+ * @param os The PrintWriter to write the result to.
+ */
+ public void doGet( String path, Map parameters, PrintWriter out )
+ throws IOException
+ {
+ String[] names = getParameters( parameters, "name" );
+ String[] descriptions = getParameters( parameters, "description" );
+ long[] intervals = getLongParameters( parameters, "interval", 0 );
+ int[] sizes = getIntegerParameters( parameters, "size", 0 );
+ long[] leases = getLongParameters( parameters, "lease", 0 );
+ int[] types = getIntegerParameters( parameters, "type", 0 );
+ boolean packed = ( getParameter( parameters, "packed", null ) != null );
+
+ if ( names.length != descriptions.length )
+ {
+ throw new FileNotFoundException(
+ "The number of descriptions not equal to the number of names." );
+ }
+ if ( names.length != intervals.length )
+ {
+ throw new FileNotFoundException(
+ "The number of intervals not equal to the number of names." );
+ }
+ if ( names.length != sizes.length )
+ {
+ throw new FileNotFoundException(
+ "The number of sizes not equal to the number of names." );
+ }
+ if ( names.length != leases.length )
+ {
+ throw new FileNotFoundException(
+ "The number of leases not equal to the number of names." );
+ }
+ if ( names.length != types.length )
+ {
+ throw new FileNotFoundException(
+ "The number of types not equal to the number of names." );
+ }
+
+ out.println( InstrumentManagerHTTPConnector.XML_BANNER );
+ if ( names.length > 0 )
+ {
+ outputLine( out, "", packed, "<samples>" );
+
+ for ( int i = 0; i < names.length; i++ )
+ {
+ String name = names[i];
+ String description = descriptions[i];
+ long interval = intervals[i];
+ int size = sizes[i];
+ long lease = leases[i];
+ int type = types[i];
+
+ InstrumentDescriptor desc;
+ try
+ {
+ desc = getInstrumentManager().locateInstrumentDescriptor( name );
+ }
+ catch ( NoSuchInstrumentException e )
+ {
+ // Not found, ignore.
+ desc = null;
+ }
+
+ if ( desc != null )
+ {
+ // The instrument manager will do its own tests of the lease, but the
+ // restrictions on this connector may be stronger so they must be tested
+ // here as well.
+ size = Math.max( 1, Math.min( size, m_connector.getMaxLeasedSampleSize() ) );
+ lease = Math.max( 1, Math.min( lease, m_connector.getMaxLeasedSampleLease() ) );
+
+ if ( getInstrumentManager().getLeaseSampleCount()
+ >= m_connector.getMaxLeasedSamples() )
+ {
+ lease = 1;
+ }
+
+ // Register the new lease
+ InstrumentSampleDescriptor sample =
+ desc.createInstrumentSample( description, interval, size, lease, type );
+
+ outputSample( out, sample, " ", packed );
+ }
+ }
+
+ outputLine( out, "", packed, "</samples>" );
+ }
+ else
+ {
+ outputLine( out, "", packed, "<samples/>" );
+ }
+ }
+
+ /*---------------------------------------------------------------
+ * Methods
+ *-------------------------------------------------------------*/
+}
+
Added: excalibur/trunk/containerkit/instrument/mgr-http/src/java/org/apache/excalibur/instrument/manager/http/XMLSampleLeasesHandler.java
==============================================================================
--- (empty file)
+++ excalibur/trunk/containerkit/instrument/mgr-http/src/java/org/apache/excalibur/instrument/manager/http/XMLSampleLeasesHandler.java Thu Aug 5 08:09:39 2004
@@ -0,0 +1,132 @@
+/*
+ * Copyright 2002-2004 The Apache Software Foundation
+ * Licensed 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.excalibur.instrument.manager.http;
+
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.util.Map;
+
+import org.apache.excalibur.instrument.manager.DefaultInstrumentManager;
+import org.apache.excalibur.instrument.manager.InstrumentSampleDescriptor;
+import org.apache.excalibur.instrument.manager.NoSuchInstrumentSampleException;
+
+/**
+ *
+ * @author <a href="mailto:dev@avalon.apache.org">Avalon Development Team</a>
+ * @since 1.2
+ */
+public class XMLSampleLeasesHandler
+ extends AbstractXMLHandler
+{
+ /** Reference to the connector. */
+ private InstrumentManagerHTTPConnector m_connector;
+
+ /*---------------------------------------------------------------
+ * Constructors
+ *-------------------------------------------------------------*/
+ /**
+ * Creates a new XMLSampleLeasesHandler.
+ *
+ * @param manager Reference to the DefaultInstrumentManager.
+ * @param connector The InstrumentManagerHTTPConnector.
+ */
+ public XMLSampleLeasesHandler( DefaultInstrumentManager manager,
+ InstrumentManagerHTTPConnector connector )
+ {
+ super( "/sample-leases.xml", manager );
+
+ m_connector = connector;
+ }
+
+ /*---------------------------------------------------------------
+ * AbstractHTTPURLHandler Methods
+ *-------------------------------------------------------------*/
+ /**
+ * Handles the specified request.
+ *
+ * @param The full path being handled.
+ * @param parameters A Map of the parameters in the request.
+ * @param os The PrintWriter to write the result to.
+ */
+ public void doGet( String path, Map parameters, PrintWriter out )
+ throws IOException
+ {
+ String[] names = getParameters( parameters, "name" );
+ long[] leases = getLongParameters( parameters, "lease", 0 );
+ boolean packed = ( getParameter( parameters, "packed", null ) != null );
+
+ if ( names.length != leases.length )
+ {
+ throw new FileNotFoundException(
+ "The number of leases values not equal to the number of names." );
+ }
+
+ out.println( InstrumentManagerHTTPConnector.XML_BANNER );
+ if ( names.length > 0 )
+ {
+ outputLine( out, "", packed, "<samples>" );
+
+ for ( int i = 0; i < names.length; i++ )
+ {
+ String name = names[i];
+ long lease = leases[i];
+
+ InstrumentSampleDescriptor desc;
+ try
+ {
+ desc = getInstrumentManager().locateInstrumentSampleDescriptor( name );
+ }
+ catch ( NoSuchInstrumentSampleException e )
+ {
+ // Not found, ignore.
+ desc = null;
+ }
+
+ if ( desc != null )
+ {
+ // The instrument manager will do its own tests of the lease, but the
+ // restrictions on this connector may be stronger so they must be tested
+ // here as well.
+ lease = Math.max( 1, Math.min( lease, m_connector.getMaxLeasedSampleLease() ) );
+
+ if ( getInstrumentManager().getLeaseSampleCount() >= m_connector.getMaxLeasedSamples() )
+ {
+ lease = 1;
+ }
+
+ // Renew the lease
+ desc.extendLease( lease );
+
+ outputSample( out, desc, " ", packed );
+ }
+ }
+
+ outputLine( out, "", packed, "</samples>" );
+ }
+ else
+ {
+ outputLine( out, "", packed, "<samples/>" );
+ }
+ }
+
+ /*---------------------------------------------------------------
+ * Methods
+ *-------------------------------------------------------------*/
+}
+
Modified: excalibur/trunk/containerkit/instrument/mgr-http/src/java/org/apache/excalibur/instrument/manager/http/XMLSnapshotsHandler.java
==============================================================================
--- excalibur/trunk/containerkit/instrument/mgr-http/src/java/org/apache/excalibur/instrument/manager/http/XMLSnapshotsHandler.java (original)
+++ excalibur/trunk/containerkit/instrument/mgr-http/src/java/org/apache/excalibur/instrument/manager/http/XMLSnapshotsHandler.java Thu Aug 5 08:09:39 2004
@@ -41,8 +41,7 @@
/**
* Creates a new XMLSnapshotsHandler.
*
- * @param path The path handled by this handler.
- * @param contentType The content type.
+ * @param manager Reference to the DefaultInstrumentManager.
*/
public XMLSnapshotsHandler( DefaultInstrumentManager manager )
{
@@ -67,7 +66,7 @@
boolean packed = ( getParameter( parameters, "packed", null ) != null );
boolean compact = ( getParameter( parameters, "compact", null ) != null );
- if ( ( baseTimes.length == 0 ) && ( baseTimes.length > 0 ) )
+ if ( ( baseTimes.length == 0 ) && ( names.length > 0 ) )
{
baseTimes = new long[baseTimes.length];
}
@@ -106,7 +105,7 @@
outputLine( out, "", packed, "<samples/>" );
}
}
-
+
/*---------------------------------------------------------------
* Methods
*-------------------------------------------------------------*/
Added: excalibur/trunk/containerkit/instrument/mgr-http/src/java/org/apache/excalibur/instrument/manager/http/favicon.ico
==============================================================================
Binary file. No diff available.
Modified: excalibur/trunk/containerkit/instrument/mgr-http/src/java/org/apache/excalibur/instrument/manager/http/server/AbstractHTTPURLHandler.java
==============================================================================
--- excalibur/trunk/containerkit/instrument/mgr-http/src/java/org/apache/excalibur/instrument/manager/http/server/AbstractHTTPURLHandler.java (original)
+++ excalibur/trunk/containerkit/instrument/mgr-http/src/java/org/apache/excalibur/instrument/manager/http/server/AbstractHTTPURLHandler.java Thu Aug 5 08:09:39 2004
@@ -270,6 +270,26 @@
}
}
+ public int[] getIntegerParameters( Map params, String name, int defaultValue )
+ {
+ String[] values = getParameters( params, name );
+ int[] iValues = new int[values.length];
+
+ for ( int i = 0; i < values.length; i++ )
+ {
+ try
+ {
+ iValues[i] = Integer.parseInt( values[i] );
+ }
+ catch ( NumberFormatException e )
+ {
+ iValues[i] = defaultValue;
+ }
+ }
+
+ return iValues;
+ }
+
public long[] getLongParameters( Map params, String name, long defaultValue )
{
String[] values = getParameters( params, name );
Modified: excalibur/trunk/containerkit/instrument/mgr-http/src/java/org/apache/excalibur/instrument/manager/http/server/HTTPServer.java
==============================================================================
--- excalibur/trunk/containerkit/instrument/mgr-http/src/java/org/apache/excalibur/instrument/manager/http/server/HTTPServer.java (original)
+++ excalibur/trunk/containerkit/instrument/mgr-http/src/java/org/apache/excalibur/instrument/manager/http/server/HTTPServer.java Thu Aug 5 08:09:39 2004
@@ -19,7 +19,9 @@
import java.io.BufferedReader;
import java.io.ByteArrayOutputStream;
+import java.io.File;
import java.io.FileNotFoundException;
+import java.io.FileWriter;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.IOException;
@@ -28,6 +30,7 @@
import java.io.UnsupportedEncodingException;
import java.net.InetAddress;
import java.net.Socket;
+import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
@@ -52,9 +55,31 @@
/** Optimized array of the handler list that lets us avoid synchronization */
private HTTPURLHandler[] m_handlerArray;
+ /** Access log file name. Null if not configured. */
+ private String m_accessLogFile;
+
+ /** The currently open log file. May be null. */
+ private File m_currentLogFile;
+
+ /** The currently open log PrintWriter. */
+ private PrintWriter m_currentLogWriter;
+
+ /** DateFormat used when generating log file names. Only use when synchronized. */
+ private SimpleDateFormat m_dayFormat = new SimpleDateFormat( "yyyy-MM-dd" );
+
+ /** DateFormat used when generating log entries. Only use when synchronized. */
+ private SimpleDateFormat m_logTimeFormat = new SimpleDateFormat( "dd/MMM/yyyy:HH:mm:ss Z" );
+
/** Number of requests. */
private CounterInstrument m_instrumentRequests;
+ /** Number of response bytes sent to the client. Includes all bytes, not
+ * only the content. */
+ private CounterInstrument m_instrumentResponseBytes;
+
+ /** Number of request bytes received from the client. */
+ private CounterInstrument m_instrumentRequestBytes;
+
/*---------------------------------------------------------------
* Constructors
*-------------------------------------------------------------*/
@@ -70,11 +95,36 @@
super( port, bindAddress );
addInstrument( m_instrumentRequests = new CounterInstrument( "requests" ) );
+ addInstrument( m_instrumentResponseBytes = new CounterInstrument( "response-bytes" ) );
+ addInstrument( m_instrumentRequestBytes = new CounterInstrument( "request-bytes" ) );
}
/*---------------------------------------------------------------
* AbstractSocketServer Methods
*-------------------------------------------------------------*/
+
+ /**
+ * Stops the server.
+ *
+ * @throws Exception If there are any problems stopping the component.
+ */
+ public void stop()
+ throws Exception
+ {
+ super.stop();
+
+ // Close the logger if it is open.
+ synchronized( this )
+ {
+ if ( m_currentLogWriter != null )
+ {
+ m_currentLogWriter.close();
+ m_currentLogWriter = null;
+ m_currentLogFile = null;
+ }
+ }
+ }
+
/**
* Handle a newly connected socket. The implementation need not
* worry about closing the socket.
@@ -89,10 +139,12 @@
+ Thread.currentThread().getName() );
}
+ String ip = socket.getInetAddress().getHostAddress();
+
try
{
// As long as we have valid requests, keep the connection open.
- while ( handleRequest( socket.getInputStream(), socket.getOutputStream() )
+ while ( handleRequest( socket.getInputStream(), socket.getOutputStream(), ip )
&& !isStopping() )
{
}
@@ -120,6 +172,20 @@
/*---------------------------------------------------------------
* Methods
*-------------------------------------------------------------*/
+
+ /**
+ * Access log file name. Null if not configured.
+ * If the log file name contains the string "yyyy_mm_dd" then that
+ * token will be replaced with the current day and the file will
+ * be rolled each day at midnight.
+ *
+ * @param accessLogFile Name of the log file or null if disabled.
+ */
+ public void setAccessLogFile( String accessLogFile )
+ {
+ m_accessLogFile = accessLogFile;
+ }
+
/**
* Registers a new HTTP URL Handler with the server.
*
@@ -134,7 +200,91 @@
}
}
- private boolean handleRequest( InputStream is, OutputStream os )
+ private void logAccessEvent( String ip,
+ String method,
+ String url,
+ int errorCode,
+ int contentLength,
+ String referrer,
+ String userAgent )
+ {
+ if ( m_accessLogFile == null )
+ {
+ return;
+ }
+
+ Date now = new Date();
+
+ synchronized( this )
+ {
+ File file;
+ int datePos = m_accessLogFile.indexOf( "yyyy_mm_dd" );
+ if ( datePos >= 0 )
+ {
+ StringBuffer sb = new StringBuffer();
+ if ( datePos > 0 )
+ {
+ sb.append( m_accessLogFile.substring( 0, datePos ) );
+ }
+ sb.append( m_dayFormat.format( now ) );
+ if ( datePos + 10 < m_accessLogFile.length() )
+ {
+ sb.append( m_accessLogFile.substring( datePos + 10 ) );
+ }
+
+ file = new File( sb.toString() );
+ }
+ else
+ {
+ file = new File( m_accessLogFile );
+ }
+
+ if ( ( m_currentLogFile == null ) || ( !m_currentLogFile.equals( file ) ) )
+ {
+ // Open a new log file.
+ if ( m_currentLogWriter != null )
+ {
+ m_currentLogWriter.close();
+ }
+ try
+ {
+ m_currentLogWriter = new PrintWriter( new FileWriter( file ) );
+ m_currentLogFile = file;
+ }
+ catch ( IOException e )
+ {
+ getLogger().warn( "Unable to open: " + m_currentLogFile );
+ m_currentLogWriter = null;
+ m_currentLogFile = null;
+ return;
+ }
+ }
+
+ // Now log the entry.
+ StringBuffer sb = new StringBuffer();
+ sb.append( ip );
+ sb.append( " - - [" );
+ sb.append( m_logTimeFormat.format( now ) );
+ sb.append( "] \"" );
+ sb.append( method );
+ sb.append( " " );
+ sb.append( url );
+ sb.append( "\" " );
+ sb.append( errorCode );
+ sb.append( " " );
+ sb.append( contentLength );
+ sb.append( " \"" );
+ sb.append( referrer );
+ sb.append( "\" \"" );
+ sb.append( userAgent );
+ sb.append( "\"" );
+
+ m_currentLogWriter.println( sb.toString() );
+ m_currentLogWriter.flush();
+ }
+ }
+
+ private boolean handleRequest( InputStream is, OutputStream os, String ip )
throws IOException
{
// We only support the GET method and know nothing of headers so this is easy.
@@ -150,14 +300,40 @@
// EOF
return false;
}
-
- // Read any headers until we get a blank line
- String header;
- do
+
+ String referrer = "-";
+ String userAgent = "-";
+ int requestBytes = request.getBytes().length + 1;
+ try
{
- header = r.readLine();
+ // Read any headers until we get a blank line
+ String header;
+ do
+ {
+ header = r.readLine();
+ if ( header != null )
+ {
+ if ( header.startsWith( "User-Agent: " ) )
+ {
+ userAgent = header.substring( 12 );
+ }
+ else if ( header.startsWith( "Referer: " ) )
+ {
+ referrer = header.substring( 9 );
+ }
+
+ requestBytes += header.getBytes().length + 1;
+ }
+ }
+ while ( ( header != null ) && ( header.length() > 0 ) );
+ }
+ finally
+ {
+ if ( requestBytes > 0 )
+ {
+ m_instrumentRequestBytes.increment( requestBytes );
+ }
}
- while ( ( header != null ) && ( header.length() > 0 ) );
if ( getLogger().isDebugEnabled() )
{
@@ -171,12 +347,15 @@
ByteArrayOutputStream hbos = new ByteArrayOutputStream();
PrintWriter out = new PrintWriter( hbos );
+ String method = "ERROR";
+ String url = "";
+
// Parse the header to make sure it is valid.
StringTokenizer st = new StringTokenizer( request, " " );
if ( st.countTokens() == 3 )
{
- String method = st.nextToken();
- String url = st.nextToken();
+ method = st.nextToken();
+ url = st.nextToken();
String version = st.nextToken();
if ( method.equals( "GET" ) && version.startsWith( "HTTP/" ) )
@@ -272,7 +451,8 @@
// Write the contents of the headers.
out.flush();
- os.write( hbos.toByteArray() );
+ byte[] responseBytes = hbos.toByteArray();
+ os.write( responseBytes );
// Write out the actual data directly to the stream.
os.write( contents, 0, contents.length );
@@ -280,6 +460,13 @@
// Flush the stream and we are done.
os.flush();
+ // Record the total number of bytes sent to the client.
+ m_instrumentResponseBytes.increment(
+ responseBytes.length + contents.length );
+
+ // Log the request.
+ logAccessEvent( ip, method, url, 302, contents.length, referrer, userAgent );
+
// Do not close the output stream as it may be reused.
return true;
@@ -313,7 +500,8 @@
// Write the contents of the headers.
out.flush();
- os.write( hbos.toByteArray() );
+ byte[] responseBytes = hbos.toByteArray();
+ os.write( responseBytes );
// Write out the actual data directly to the stream.
os.write( contents, 0, contents.length );
@@ -321,6 +509,13 @@
// Flush the stream and we are done.
os.flush();
+ // Record the total number of bytes sent to the client.
+ m_instrumentResponseBytes.increment(
+ responseBytes.length + contents.length );
+
+ // Log the request.
+ logAccessEvent( ip, method, url, 200, contents.length, referrer, userAgent );
+
// Do not close the output stream as it may be reused.
return true;
@@ -359,8 +554,15 @@
// Write the contents of the headers.
out.flush();
- os.write( hbos.toByteArray() );
+ byte[] responseBytes = hbos.toByteArray();
+ os.write( responseBytes );
os.flush();
+
+ // Record the total number of bytes sent to the client.
+ m_instrumentResponseBytes.increment( responseBytes.length );
+
+ // Log the request.
+ logAccessEvent( ip, method, url, 404, 0, referrer, userAgent );
return false;
}
Modified: excalibur/trunk/containerkit/instrument/mgr-http/src/java/org/apache/excalibur/instrument/manager/http/server/HTTPURLHandler.java
==============================================================================
--- excalibur/trunk/containerkit/instrument/mgr-http/src/java/org/apache/excalibur/instrument/manager/http/server/HTTPURLHandler.java (original)
+++ excalibur/trunk/containerkit/instrument/mgr-http/src/java/org/apache/excalibur/instrument/manager/http/server/HTTPURLHandler.java Thu Aug 5 08:09:39 2004
@@ -30,9 +30,10 @@
*/
public interface HTTPURLHandler
{
- String CONTENT_TYPE_TEXT_HTML = "text/html";
- String CONTENT_TYPE_TEXT_XML = "text/xml";
- String CONTENT_TYPE_IMAGE_JPEG = "image/jpeg";
+ String CONTENT_TYPE_TEXT_HTML = "text/html";
+ String CONTENT_TYPE_TEXT_XML = "text/xml";
+ String CONTENT_TYPE_IMAGE_JPEG = "image/jpeg";
+ String CONTENT_TYPE_IMAGE_X_ICON = "image/x-icon";
/**
* Returns the path handled by this handler.
---------------------------------------------------------------------
To unsubscribe, e-mail: scm-unsubscribe@excalibur.apache.org
For additional commands, e-mail: scm-help@excalibur.apache.org