📄 httpserver.java
字号:
// HttpServer.java - A multithreaded HTTP server.
//
// Copyright (C) 1999-2002 Smart Software Consulting
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
//
// Smart Software Consulting
// 1688 Silverwood Court
// Danville, CA 94526-3079
// USA
//
// http://www.smartsc.com
//
package com.smartsc.http;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.IOException;
import java.io.PrintWriter;
import java.net.InetAddress;
import java.net.MalformedURLException;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketException;
import java.net.URL;
import java.util.Date;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.Vector;
import java.util.StringTokenizer;
import javax.servlet.RequestDispatcher;
import javax.servlet.Servlet;
import javax.servlet.ServletConfig;
import javax.servlet.ServletContext;
import com.smartsc.util.AbsoluteFile;
import com.smartsc.util.Mailer;
import com.smartsc.util.NVPairParser;
import com.smartsc.util.Properties;
public class
HttpServer
implements ServletContext, HttpStatusCodes, HttpReasonPhrases, Runnable
{
public
HttpServer( Properties props)
throws IOException
{
this.props = props;
// Get verbosity from properties
boolean verbose = props.getBooleanProperty( PROP_VERBOSE);
openLog( true );
openTransferLog( true );
// Log startup message
banner( verbose);
// Setup handler counter
maxHandlers = props.getIntProperty(
PROP_MAX_HANDLERS, DEFAULT_MAX_HANDLERS);
handlerCount = 0;
int backlog = props.getIntProperty( PROP_BACKLOG, -1);
int port = props.getIntProperty( PROP_PORT, DEFAULT_PORT);
if( port == 0)
port = DEFAULT_PORT;
if( backlog > 0)
{
serverSocket = new ServerSocket( port, backlog);
}
else
{
serverSocket = new ServerSocket( port);
}
StringBuffer sb = new StringBuffer(
InetAddress.getLocalHost().getHostName());
sb.append( ":");
sb.append( port);
serverName = sb.toString();
// Parse servlet context init params
String initParams = props.getProperty( PROP_INIT_PARAMS);
if( initParams != null)
{
new NVPairParser( initParams, ",", "=")
{
public void forEachNVPair( String name, String value)
{
servletContextInitParams.put( name.trim(), value);
}
}.parse();
}
// Load servlets properties file
String servletPropFile = props.getProperty(
PROP_SERVLET_PROPS, DEFAULT_SERVLET_PROPS);
try
{
File f = AbsoluteFile.create( servletPropFile);
servletProperties.load( new FileInputStream( f));
}
// Ignore exceptions
catch( IOException ie) {}
// Process servlet properties (i.e. .startup and .mappings)
processServletProperties();
}
public
void
run()
{
Socket clientSocket;
while( true)
{
try
{
// If we have max number of handlers
if( handlerCount >= maxHandlers)
{
// Wail until some finish
synchronized( this)
{
while( handlerCount >= maxHandlers)
{
try
{
wait();
/* TINI Omit
// (wait is only a stub in TINI Beta 2.1)
Thread.sleep( 100);
//*/
}
catch( InterruptedException ie) {}
}
}
}
clientSocket = serverSocket.accept();
clientSocket.setSoTimeout(
1000 * props.getIntProperty( PROP_REQUEST_TIMEOUT));
}
catch( IOException ioe)
{
log( "Exception in accept()", ioe);
continue;
}
try
{
HttpServerHandler handler = createHandler( this, clientSocket);
new Thread( handler).start();
}
catch( HttpException he)
{
log( he);
try
{
HttpResponse.sendError(
clientSocket.getOutputStream(),
he.getStatusCode(),
he.getReasonPhrase());
}
catch( IOException ioe) {}
}
catch( Throwable t)
{
log( t);
try
{
HttpResponse.sendError(
clientSocket.getOutputStream(),
SC_INTERNAL_SERVER_ERROR,
RP_INTERNAL_SERVER_ERROR);
}
catch( IOException ioe) {}
}
}
}
protected
void
openLog( boolean append )
{
String logFileName = props.getProperty( PROP_LOG_FILE);
if( logFileName != null)
{
try
{
logFile = AbsoluteFile.create( logFileName);
logFileName = logFile.getAbsolutePath();
logWriter = new PrintWriter(
new FileOutputStream( logFileName, append ), true );
}
catch( IOException ioe)
{
System.err.println(
"Could not open log file '" +
logFileName + "' for writing.");
logWriter = new PrintWriter( System.out, true);
logFile = null;
}
}
else
{
logWriter = new PrintWriter( System.out, true);
logFile = null;
}
}
protected
void
openTransferLog( boolean append )
{
String logFileName = null;
if( logFile != null)
{
logFileName = logFile.getAbsolutePath();
}
String transferLogName = props.getProperty( PROP_TRANSFER_LOG);
if( transferLogName != null)
{
transferLogFile = AbsoluteFile.create( transferLogName);
transferLogName = transferLogFile.getAbsolutePath();
}
// Set transferLogWriter = logWriter if any one of these three
// conditions is true...
// 1) server.transferLog is not defined
// 2) server.transferLog is the same as server.logFile
// 3) server.transferLog is "-" and logFile is not defined
if( transferLogName == null || transferLogName.equals( logFileName)
||( transferLogName.equals( "-") && transferLogName == null) )
{
transferLogWriter = logWriter;
transferLogFile = logFile;
}
else if( transferLogName.equals( "-"))
{
transferLogWriter = new PrintWriter( System.out, true);
transferLogFile = null;
}
else
{
try
{
transferLogWriter = new PrintWriter(
new FileOutputStream( transferLogName, append ), true);
}
catch( IOException ioe)
{
System.err.println(
"Could not open transfer log file '" +
transferLogName + "' for writing.");
transferLogWriter = logWriter;
transferLogFile = logFile;
}
}
}
public
void
logTransfer( String msg)
{
if( transferLogWriter != null)
{
synchronized( transferLogWriter)
{
transferLogWriter.println( msg);
}
}
}
protected
HttpServerHandler
createHandler( HttpServer server, Socket clientSocket)
throws HttpException
{
return new HttpServerHandler( server, clientSocket);
}
protected synchronized
void
addHandler()
{
++handlerCount;
}
protected synchronized
void
removeHandler()
{
--handlerCount;
if( (handlerCount == 0 && getTimeSinceLastGC() > MIN_GC_TIME))
{
gc();
}
notifyAll();
}
protected synchronized
long
getTimeSinceLastGC()
{
return System.currentTimeMillis() - lastGCTime;
}
protected synchronized
void
gc()
{
// Check log file sizes
if( logFile != null)
{
synchronized( logWriter)
{
if( isLogOversized( logFile))
{
logWriter.close();
try
{
if( isMailingOversizedLogs() )
{
mailLog( logFile);
}
openLog( false );
}
catch( IOException ioe)
{
// Truncate log file then log exception
openLog( false );
log( ioe );
}
}
}
}
if( transferLogFile != null && transferLogFile != logFile)
{
synchronized( transferLogWriter)
{
if( isLogOversized( transferLogFile))
{
transferLogWriter.close();
if( isMailingOversizedLogs() )
{
try
{
mailLog( transferLogFile);
}
catch( IOException ioe)
{
log( ioe );
}
}
openTransferLog( false );
}
}
}
System.gc();
lastGCTime = System.currentTimeMillis();
}
protected void processServletProperties()
{
Enumeration e = servletProperties.keys();
while( e.hasMoreElements())
{
String propName = (String)e.nextElement();
String propValue = getServletProperty( propName );
if( propValue == null )
{
continue;
}
if( propName.endsWith( PRELOAD))
{
boolean preload = Boolean.valueOf( propValue).booleanValue();
if( preload)
{
String servletName = propName.substring( 0,
propName.length() - PRELOAD.length());
getNamedDispatcher( servletName);
}
}
else if( propName.endsWith( MAPPING))
{
String servletName = propName.substring( 0,
propName.length() - MAPPING.length());
// If prefix mapping
if( propValue.startsWith( "/" ) && propValue.endsWith( "/*" ))
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -