Added HttpFilePage to hosts static content

This commit is contained in:
Ziver Koc 2015-03-30 01:25:36 +00:00
parent 15162b2cb0
commit 18e3175db9
7 changed files with 220 additions and 39 deletions

View file

@ -278,7 +278,7 @@ public class FileUtil {
}
/**
* Returns the extension of the file
* Returns the extension(without the dot) of the file. e.g. "png" "avi"
*
* @param file is the file
* @return The extension

View file

@ -53,7 +53,7 @@ public class LogUtil {
for(int i=1; i<stackTraceElements.length ;++i){
String name = stackTraceElements[i].getClassName();
if( !name.equals( LogUtil.class.getName() ) ){
logger.fine("Calling class: \""+name+"\"");
//logger.fine("Calling class: \""+name+"\"");
return name;
}
}

View file

@ -234,10 +234,21 @@ public class HttpPrintStream extends PrintStream{
}
}
/**
* @return if headers has been sent. The setHeader, setStatusCode, setCookie method will throw Exceptions
*/
public boolean isHeaderSent() {
return res_status_code == null && headers == null && cookies == null;
}
/**
* Sends out the buffer and clears it
*/
public void flush(){
flushBuffer();
super.flush();
}
protected void flushBuffer(){
if(buffer_enabled){
buffer_enabled = false;
printOrBuffer(buffer.toString());
@ -247,7 +258,6 @@ public class HttpPrintStream extends PrintStream{
else if(res_status_code != null || headers != null || cookies != null){
printOrBuffer("");
}
super.flush();
}
public void close(){
@ -255,30 +265,36 @@ public class HttpPrintStream extends PrintStream{
super.close();
}
public void println(){ println("");}
public void println(boolean x){ println(String.valueOf(x));}
public void println(char x){ println(String.valueOf(x));}
public void println(char[] x){ println(new String(x));}
public void println(double x){ println(String.valueOf(x));}
public void println(float x){ println(String.valueOf(x));}
public void println(int x){ println(String.valueOf(x));}
public void println(long x){ println(String.valueOf(x));}
public void println(Object x){ println(String.valueOf(x));}
public void print(boolean x){ printOrBuffer(String.valueOf(x));}
public void print(char x){ printOrBuffer(String.valueOf(x));}
public void print(char[] x){ printOrBuffer(new String(x));}
public void print(double x){ printOrBuffer(String.valueOf(x));}
public void print(float x){ printOrBuffer(String.valueOf(x));}
public void print(int x){ printOrBuffer(String.valueOf(x));}
public void print(int x) { printOrBuffer(String.valueOf(x));}
public void print(long x){ printOrBuffer(String.valueOf(x));}
public void print(Object x){ printOrBuffer(String.valueOf(x));}
/*
public void write(int b) { print((char)b);}
public void println(){ println("");}
public void println(boolean x){ println(String.valueOf(x));}
public void println(char x){ println(String.valueOf(x));}
public void println(char[] x){ println(new String(x));}
public void println(double x){ println(String.valueOf(x));}
public void println(float x) { println(String.valueOf(x));}
public void println(int x){ println(String.valueOf(x));}
public void println(long x){ println(String.valueOf(x));}
public void println(Object x){ println(String.valueOf(x));}
/* java.lang.StackOverflowError
public void write(int b) {
flushBuffer();
super.write(b);
}
public void write(byte buf[], int off, int len){
print(new String(buf, off, len));}
*/
flushBuffer();
super.write(buf, off, len);
}*/
private String getStatusString(int type){
switch(type){
case 100: return "Continue";

View file

@ -53,8 +53,6 @@ public class HttpServer extends ThreadedTCPNetworkServer{
public static final int COOKIE_TTL = 200;
public static final int SESSION_TTL = 10*60*1000; // in milliseconds
public final int server_port;
private Map<String,HttpPage> pages;
private HttpPage defaultPage;
private Map<String,Map<String,Object>> sessions;
@ -79,7 +77,6 @@ public class HttpServer extends ThreadedTCPNetworkServer{
*/
public HttpServer(int port, File keyStore, String keyStorePass){
super( port, keyStore, keyStorePass );
this.server_port = port;
pages = new ConcurrentHashMap<String,HttpPage>();
sessions = new ConcurrentHashMap<String,Map<String,Object>>();
@ -158,7 +155,7 @@ public class HttpServer extends ThreadedTCPNetworkServer{
out = new HttpPrintStream(socket.getOutputStream());
in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
this.socket = socket;
logger.fine("New Connection!!! "+socket.getInetAddress().getHostName());
logger.fine("New Connection: " + socket.getInetAddress().getHostName());
}
public void run(){
@ -169,10 +166,10 @@ public class HttpServer extends ThreadedTCPNetworkServer{
//**************************** REQUEST *********************************
try {
logger.finer("Reciving Http Request!!!");
logger.finer("Receiving Http Request");
HttpHeaderParser parser = new HttpHeaderParser(in);
logger.finest(parser.toString());
//logger.finest(parser.toString());
request = parser.getURLAttributes();
cookie = parser.getCookies();
@ -202,7 +199,7 @@ public class HttpServer extends ThreadedTCPNetworkServer{
}
else if( tmp.contains("multipart/form-data") ){
// TODO: File upload
throw new Exception( "\"multipart-form-data\" Not implemented!!!" );
throw new Exception( "\"multipart-form-data\" Not implemented." );
}
}
@ -227,17 +224,17 @@ public class HttpServer extends ThreadedTCPNetworkServer{
client_session.put( "session_id", nextSessionId );
client_session.put( "ttl", ttl_time );
sessions.put( ""+nextSessionId, client_session );
nextSessionId++;
++nextSessionId;
}
// Debug
if(logger.isLoggable(Level.FINE)){
logger.finest( "# page_url: "+parser.getRequestURL() );
logger.finest( "# client_session: "+client_session );
logger.finest( "# cookie: "+cookie );
logger.finest( "# request: "+request );
if(logger.isLoggable(Level.FINEST)){
logger.finest( "page_url: "+parser.getRequestURL() );
logger.finest( "client_session: "+client_session );
logger.finest( "cookie: "+cookie );
logger.finest( "request: "+request );
}
//**************************** RESPONSE ************************************
logger.finer("Sending Http Response!!!");
logger.finer("Sending Http Response");
out.setStatusCode(200);
out.setHeader( "Server", SERVER_VERSION );
out.setHeader( "Content-Type", "text/html" );
@ -252,15 +249,14 @@ public class HttpServer extends ThreadedTCPNetworkServer{
else{
out.setStatusCode( 404 );
out.println( "404 Page Not Found: "+parser.getRequestURL() );
logger.fine( "404 Page Not Found: "+parser.getRequestURL() );
logger.warning("Page not defined: " + parser.getRequestURL());
}
//********************************************************************************
} catch (Exception e) {
logger.log(Level.WARNING, "500 Internal Server Error", e);
try {
if(!out.isHeaderSent())
out.setStatusCode( 500 );
} catch (Exception e1) {}
if(e.getMessage() != null)
out.println( "500 Internal Server Error: "+e.getMessage() );
else if(e.getCause() != null){
@ -272,7 +268,7 @@ public class HttpServer extends ThreadedTCPNetworkServer{
}
try{
logger.fine("Connection Closed!!!");
logger.fine("Connection Closed.");
out.close();
in.close();
socket.close();

View file

@ -0,0 +1,155 @@
/*
* Copyright (c) 2015 Ziver
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package zutil.net.http.pages;
import zutil.io.IOUtil;
import zutil.io.file.FileUtil;
import zutil.log.LogUtil;
import zutil.net.http.HttpHeaderParser;
import zutil.net.http.HttpPage;
import zutil.net.http.HttpPrintStream;
import java.io.*;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
* This Http Page will host static content from the server.
*
* Created by Ziver on 2015-03-30.
*/
public class HttpFilePage implements HttpPage{
private static final Logger log = LogUtil.getLogger();
private File resource_root;
private boolean showFolders;
private boolean redirectToIndex;
/**
* @param file a reference to a root directory or a file.
*/
public HttpFilePage(File file){
this.resource_root = file;
this.showFolders = true;
this.redirectToIndex = true;
}
@Override
public void respond(HttpPrintStream out,
HttpHeaderParser client_info,
Map<String, Object> session,
Map<String, String> cookie,
Map<String, String> request) {
try {
// Is the root only one file or a folder
if (resource_root.isFile()) {
deliverFile(resource_root, out);
}
else { // Resource root is a folder
File file = new File(resource_root,
client_info.getRequestURL());
if(file.getAbsolutePath().startsWith(resource_root.getAbsolutePath())){
if(file.isDirectory() && showFolders){
File indexFile = new File(file, "index.html");
// Redirect to index.html
if(redirectToIndex && indexFile.isFile()) {
deliverFile(indexFile, out);
}
// Show folder contents
else if(showFolders){
out.println("<HTML><BODY><H1>Directory: " + client_info.getRequestURL() + "</H1>");
out.println("<HR><UL>");
for (String f : file.list()) {
out.println("<LI><A href='" + client_info.getRequestURL() + f + "'>" + f + "</A></LI>");
}
out.println("</UL><HR></BODY></HTML>");
}
}
else {
deliverFile(file, out);
}
}
else {
throw new SecurityException("File is outside of root directory: root=" + resource_root.getAbsolutePath() + " file=" + file.getAbsolutePath());
}
}
}catch (FileNotFoundException e){
if(!out.isHeaderSent())
out.setStatusCode(404);
log.log(Level.WARNING, null, e);
out.println("404 Page Not Found: " + client_info.getRequestURL());
}catch (SecurityException e){
if(!out.isHeaderSent())
out.setStatusCode(404);
log.log(Level.WARNING, null, e);
out.println("404 Page Not Found: " + client_info.getRequestURL() );
}catch (IOException e){
if(!out.isHeaderSent())
out.setStatusCode(500);
log.log(Level.WARNING, null, e);
out.println("500 Internal Server Error: "+e.getMessage() );
}
}
private void deliverFile(File file, HttpPrintStream out) throws IOException {
out.setHeader("Content-Type", getMIMEType(file));
out.flush();
BufferedInputStream in = new BufferedInputStream(new FileInputStream(file));
IOUtil.copyStream(in, out);
in.close();
}
private String getMIMEType(File file){
switch(FileUtil.getFileExtension(file)){
case "css": return "text/css";
case "cvs": return "text/csv";
case "jpg": return "image/jpeg";
case "js": return "application/javascript";
case "png": return "image/png";
case "htm":
case "html": return "text/html";
case "xml": return "text/xml";
default: return "text/plain";
}
}
/**
* Enable or disable showing of folder contents
*/
public void showFolders(boolean enabled){
this.showFolders = enabled;
}
/**
* If directory links should be redirected to index files
*/
public void redirectToIndexFile(boolean enabled){
this.redirectToIndex = enabled;
}
}

View file

@ -56,13 +56,13 @@ public class PluginData {
pluginVersion = data.getDouble("version");
pluginName = data.getString("name");
log.fine("Found plugin: "+pluginName);
log.fine("Plugin: "+this);
DataNode node = data.get("interfaces");
Iterator<String> intfIt = node.keyIterator();
while (intfIt.hasNext()) {
String intf = intfIt.next();
log.finer("Plugin interface: "+ intf+"-->"+node.get(intf).getString());
log.finer("Plugin interface: "+ intf+" --> "+node.get(intf).getString());
classMap.put(
getClassByName(intf),
getClassByName(node.get(intf).getString()));
@ -98,4 +98,8 @@ public class PluginData {
public boolean contains(Class<?> intf){
return classMap.containsKey(intf);
}
public String toString(){
return getName()+"(ver: "+getVersion()+")";
}
}

View file

@ -71,12 +71,22 @@ public class PluginManager<T> implements Iterable<PluginData>{
for(FileSearch.FileSearchItem file : search){
try {
DataNode node = JSONParser.read(IOUtil.getContentString(file.getInputStream()));
log.fine("Found plugin: "+file.getPath());
PluginData plugin = new PluginData(node);
if (!plugins.containsKey(plugin.getName()) ||
plugins.get(plugin.getName()).getVersion() < plugin.getVersion()){
if (!plugins.containsKey(plugin.getName())){
plugins.put(plugin.getName(), plugin);
}
else {
double version = plugins.get(plugin.getName()).getVersion();
if(version < plugin.getVersion())
plugins.put(plugin.getName(), plugin);
else if(version == plugin.getVersion())
log.fine("Ignoring duplicate plugin: " + plugin);
else
log.fine("Ignoring outdated plugin: "+plugin);
}
} catch (Exception e) {
e.printStackTrace();
}