mirror of
https://github.com/apache/cloudstack.git
synced 2025-10-26 08:42:29 +01:00
263 lines
8.0 KiB
Java
263 lines
8.0 KiB
Java
/*
|
|
* 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 com.psibt.framework.net;
|
|
|
|
import java.net.*;
|
|
import java.io.*;
|
|
import java.util.*;
|
|
import org.apache.log4j.*;
|
|
|
|
/**
|
|
* This class implements a HTTP-server frame. All HTTP-requests are handled by HTTPRequestHandler
|
|
* classes which implement the <code>HTTPRequestHandler</code> interface. Every RequestHandler has
|
|
* to be registered in the PluggableHTTPServer with the <code>addRequestHandler</code> method.
|
|
* A new thread is created for each connection to handle the request. If all reply data are sent
|
|
* to the client the connection is closed and the thread ends.
|
|
* An example how to use the PluggableHTTPServer class can be found in the <code>main</code> method
|
|
* at the end of the source file.
|
|
*
|
|
* @author <a HREF="mailto:V.Mentzner@psi-bt.de">Volker Mentzner</a>
|
|
*/
|
|
public class PluggableHTTPServer implements Runnable {
|
|
|
|
public static final int DEFAULT_PORT = 80;
|
|
static Category cat = Category.getInstance("PluggableHTTPServer");
|
|
private int port;
|
|
private Vector handler;
|
|
private ServerSocket server;
|
|
|
|
/**
|
|
* Creates a new server object on the given TCP port.
|
|
* If the port is occupied by another process a IOException (java.net.BindException) is thrown.
|
|
*
|
|
* @param port - TCP port number to listen on for requests
|
|
*/
|
|
public PluggableHTTPServer(int port) throws IOException {
|
|
this.port = port;
|
|
this.handler = new Vector();
|
|
cat.setPriority(Priority.ERROR);
|
|
server = new ServerSocket(this.port);
|
|
}
|
|
|
|
/**
|
|
* Creates a new server object on the default TCP port 80
|
|
* If the port is occupied by another process a IOException (java.net.BindException) is thrown.
|
|
*/
|
|
public PluggableHTTPServer() throws IOException {
|
|
this(DEFAULT_PORT);
|
|
}
|
|
|
|
/**
|
|
* Registers the given HTTPRequestHandler
|
|
*
|
|
* @param h - the HTTPRequestHandler to register
|
|
*/
|
|
public void addRequestHandler(HTTPRequestHandler h) {
|
|
handler.add(h);
|
|
}
|
|
|
|
/**
|
|
* Unregisters the given HTTPRequestHandler
|
|
*
|
|
* @param h - the HTTPRequestHandler to unregister
|
|
*/
|
|
public void removeRequestHandler(HTTPRequestHandler h) {
|
|
handler.remove(h);
|
|
}
|
|
|
|
/**
|
|
* Sends the HTTP message 404 - File Not Found
|
|
* see RFC2616 for details
|
|
*
|
|
* @param out - Out stream for sending data to client browser
|
|
*/
|
|
public static void replyNotFound(Writer out) {
|
|
try {
|
|
out.write("HTTP/1.0 404 Not Found\r\n");
|
|
out.write("<HTML><HEAD><TITLE>Not Found</TITLE></HEAD>\r\n");
|
|
out.write("<BODY><H1>Not Found</H1>\r\n");
|
|
out.write("</BODY></HTML>\r\n");
|
|
out.flush();
|
|
} // end try
|
|
catch (IOException e) {
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Sends the HTTP message 405 - Method Not Allowed
|
|
* see RFC2616 for details
|
|
*
|
|
* @param out - Out stream for sending data to client browser
|
|
*/
|
|
public static void replyMethodNotAllowed(Writer out) {
|
|
try {
|
|
out.write("HTTP/1.1 405 Method Not Allowed\r\n");
|
|
out.write("Allow: GET, PUT\r\n");
|
|
out.write("<HTML><HEAD><TITLE>Method Not Allowed</TITLE></HEAD>\r\n");
|
|
out.write("<BODY><H1>Method Not Allowed</H1>\r\n");
|
|
out.write("</BODY></HTML>\r\n");
|
|
out.flush();
|
|
} // end try
|
|
catch (IOException e) {
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Creates the ReplyHTML data for the root page
|
|
*
|
|
* @param index - index of the RootRequestHandler
|
|
*/
|
|
public void autoCreateRootPage(int index) {
|
|
if (handler.get(index) instanceof RootRequestHandler) {
|
|
RootRequestHandler r = (RootRequestHandler)handler.get(index);
|
|
String html = "<HTML><HEAD><TITLE>"+r.getTitle()+"</TITLE></HEAD>\r\n";
|
|
html = html + "<BODY><H1>"+r.getDescription()+"</H1>\r\n";
|
|
for (int i = 0; i < handler.size(); i++) {
|
|
html = html + "<a href=\"" + ((HTTPRequestHandler)handler.get(i)).getHandledPath();
|
|
html = html + "\">" + ((HTTPRequestHandler)handler.get(i)).getDescription() + "</a><br>";
|
|
}
|
|
html = html + "</BODY></HTML>\r\n";
|
|
r.setReplyHTML(html);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Main loop of the PluggableHTTPServer
|
|
*/
|
|
public void run() {
|
|
while (true) {
|
|
try {
|
|
Socket s = server.accept();
|
|
Thread t = new ServerThread(s);
|
|
t.start();
|
|
}
|
|
catch (IOException e) {
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* This class handles the incomming connection for one request.
|
|
*/
|
|
class ServerThread extends Thread {
|
|
|
|
private Socket connection;
|
|
|
|
ServerThread(Socket s) {
|
|
this.connection = s;
|
|
}
|
|
|
|
/**
|
|
* Serves the HTTP request.
|
|
*/
|
|
public void run() {
|
|
try {
|
|
Writer out = new BufferedWriter(
|
|
new OutputStreamWriter(
|
|
connection.getOutputStream(), "ASCII"
|
|
)
|
|
);
|
|
Reader in = new InputStreamReader(
|
|
new BufferedInputStream(
|
|
connection.getInputStream()
|
|
)
|
|
);
|
|
|
|
// read the first line only; that's all we need
|
|
StringBuffer req = new StringBuffer(80);
|
|
while (true) {
|
|
int c = in.read();
|
|
if (c == '\r' || c == '\n' || c == -1) break;
|
|
req.append((char) c);
|
|
}
|
|
String get = req.toString();
|
|
cat.debug(get);
|
|
StringTokenizer st = new StringTokenizer(get);
|
|
String method = st.nextToken();
|
|
String request = st.nextToken();
|
|
String version = st.nextToken();
|
|
|
|
if (method.equalsIgnoreCase("GET")) {
|
|
boolean served = false;
|
|
for (int i = 0; i < handler.size(); i++) {
|
|
if (handler.get(i) instanceof HTTPRequestHandler) {
|
|
if (((HTTPRequestHandler)handler.get(i)).handleRequest(request, out)) {
|
|
served = true;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
if (!served)
|
|
PluggableHTTPServer.replyNotFound(out);
|
|
}
|
|
else {
|
|
PluggableHTTPServer.replyMethodNotAllowed(out);
|
|
}
|
|
} // end try
|
|
catch (IOException e) {
|
|
}
|
|
finally {
|
|
try {
|
|
if (connection != null) connection.close();
|
|
}
|
|
catch (IOException e) {}
|
|
}
|
|
} // end run
|
|
} // end class ServerThread
|
|
|
|
/**
|
|
* Demo how to use the PluggableHTTPServer.
|
|
*/
|
|
public static void main(String[] args) {
|
|
|
|
int thePort;
|
|
|
|
// create some logging stuff
|
|
BasicConfigurator.configure();
|
|
Category cat1 = Category.getInstance("cat1");
|
|
cat1.addAppender(new org.apache.log4j.ConsoleAppender(new PatternLayout("%m%n")));
|
|
Category cat2 = Category.getInstance("cat2");
|
|
cat2.setPriority(Priority.INFO);
|
|
cat2.addAppender(new org.apache.log4j.ConsoleAppender(new PatternLayout("%c - %m%n")));
|
|
|
|
// set TCP port number
|
|
try {
|
|
thePort = Integer.parseInt(args[1]);
|
|
}
|
|
catch (Exception e) {
|
|
thePort = PluggableHTTPServer.DEFAULT_PORT;
|
|
}
|
|
|
|
PluggableHTTPServer server = null;
|
|
while (server == null) {
|
|
try {
|
|
server = new PluggableHTTPServer(thePort);
|
|
server.addRequestHandler(new RootRequestHandler());
|
|
server.addRequestHandler(new Log4jRequestHandler());
|
|
server.addRequestHandler(new UserDialogRequestHandler());
|
|
server.autoCreateRootPage(0);
|
|
Thread t = new Thread(server);
|
|
t.start();
|
|
} catch (IOException e) {
|
|
server = null;
|
|
thePort++;
|
|
}
|
|
}
|
|
|
|
} // end main
|
|
}
|