Added HttpFilePage to hosts static content
This commit is contained in:
parent
15162b2cb0
commit
18e3175db9
7 changed files with 220 additions and 39 deletions
|
|
@ -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
|
* @param file is the file
|
||||||
* @return The extension
|
* @return The extension
|
||||||
|
|
|
||||||
|
|
@ -53,7 +53,7 @@ public class LogUtil {
|
||||||
for(int i=1; i<stackTraceElements.length ;++i){
|
for(int i=1; i<stackTraceElements.length ;++i){
|
||||||
String name = stackTraceElements[i].getClassName();
|
String name = stackTraceElements[i].getClassName();
|
||||||
if( !name.equals( LogUtil.class.getName() ) ){
|
if( !name.equals( LogUtil.class.getName() ) ){
|
||||||
logger.fine("Calling class: \""+name+"\"");
|
//logger.fine("Calling class: \""+name+"\"");
|
||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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
|
* Sends out the buffer and clears it
|
||||||
*/
|
*/
|
||||||
public void flush(){
|
public void flush(){
|
||||||
|
flushBuffer();
|
||||||
|
super.flush();
|
||||||
|
}
|
||||||
|
protected void flushBuffer(){
|
||||||
if(buffer_enabled){
|
if(buffer_enabled){
|
||||||
buffer_enabled = false;
|
buffer_enabled = false;
|
||||||
printOrBuffer(buffer.toString());
|
printOrBuffer(buffer.toString());
|
||||||
|
|
@ -247,7 +258,6 @@ public class HttpPrintStream extends PrintStream{
|
||||||
else if(res_status_code != null || headers != null || cookies != null){
|
else if(res_status_code != null || headers != null || cookies != null){
|
||||||
printOrBuffer("");
|
printOrBuffer("");
|
||||||
}
|
}
|
||||||
super.flush();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void close(){
|
public void close(){
|
||||||
|
|
@ -255,6 +265,16 @@ public class HttpPrintStream extends PrintStream{
|
||||||
super.close();
|
super.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
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(long x){ printOrBuffer(String.valueOf(x));}
|
||||||
|
public void print(Object x){ printOrBuffer(String.valueOf(x));}
|
||||||
|
|
||||||
public void println(){ println("");}
|
public void println(){ println("");}
|
||||||
public void println(boolean x){ println(String.valueOf(x));}
|
public void println(boolean x){ println(String.valueOf(x));}
|
||||||
public void println(char x){ println(String.valueOf(x));}
|
public void println(char x){ println(String.valueOf(x));}
|
||||||
|
|
@ -265,20 +285,16 @@ public class HttpPrintStream extends PrintStream{
|
||||||
public void println(long 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 println(Object x){ println(String.valueOf(x));}
|
||||||
|
|
||||||
public void print(boolean x){ printOrBuffer(String.valueOf(x));}
|
/* java.lang.StackOverflowError
|
||||||
public void print(char x){ printOrBuffer(String.valueOf(x));}
|
public void write(int b) {
|
||||||
public void print(char[] x){ printOrBuffer(new String(x));}
|
flushBuffer();
|
||||||
public void print(double x){ printOrBuffer(String.valueOf(x));}
|
super.write(b);
|
||||||
public void print(float 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 write(byte buf[], int off, int len){
|
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){
|
private String getStatusString(int type){
|
||||||
switch(type){
|
switch(type){
|
||||||
case 100: return "Continue";
|
case 100: return "Continue";
|
||||||
|
|
|
||||||
|
|
@ -53,8 +53,6 @@ public class HttpServer extends ThreadedTCPNetworkServer{
|
||||||
public static final int COOKIE_TTL = 200;
|
public static final int COOKIE_TTL = 200;
|
||||||
public static final int SESSION_TTL = 10*60*1000; // in milliseconds
|
public static final int SESSION_TTL = 10*60*1000; // in milliseconds
|
||||||
|
|
||||||
public final int server_port;
|
|
||||||
|
|
||||||
private Map<String,HttpPage> pages;
|
private Map<String,HttpPage> pages;
|
||||||
private HttpPage defaultPage;
|
private HttpPage defaultPage;
|
||||||
private Map<String,Map<String,Object>> sessions;
|
private Map<String,Map<String,Object>> sessions;
|
||||||
|
|
@ -79,7 +77,6 @@ public class HttpServer extends ThreadedTCPNetworkServer{
|
||||||
*/
|
*/
|
||||||
public HttpServer(int port, File keyStore, String keyStorePass){
|
public HttpServer(int port, File keyStore, String keyStorePass){
|
||||||
super( port, keyStore, keyStorePass );
|
super( port, keyStore, keyStorePass );
|
||||||
this.server_port = port;
|
|
||||||
|
|
||||||
pages = new ConcurrentHashMap<String,HttpPage>();
|
pages = new ConcurrentHashMap<String,HttpPage>();
|
||||||
sessions = new ConcurrentHashMap<String,Map<String,Object>>();
|
sessions = new ConcurrentHashMap<String,Map<String,Object>>();
|
||||||
|
|
@ -158,7 +155,7 @@ public class HttpServer extends ThreadedTCPNetworkServer{
|
||||||
out = new HttpPrintStream(socket.getOutputStream());
|
out = new HttpPrintStream(socket.getOutputStream());
|
||||||
in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
|
in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
|
||||||
this.socket = socket;
|
this.socket = socket;
|
||||||
logger.fine("New Connection!!! "+socket.getInetAddress().getHostName());
|
logger.fine("New Connection: " + socket.getInetAddress().getHostName());
|
||||||
}
|
}
|
||||||
|
|
||||||
public void run(){
|
public void run(){
|
||||||
|
|
@ -169,10 +166,10 @@ public class HttpServer extends ThreadedTCPNetworkServer{
|
||||||
|
|
||||||
//**************************** REQUEST *********************************
|
//**************************** REQUEST *********************************
|
||||||
try {
|
try {
|
||||||
logger.finer("Reciving Http Request!!!");
|
logger.finer("Receiving Http Request");
|
||||||
|
|
||||||
HttpHeaderParser parser = new HttpHeaderParser(in);
|
HttpHeaderParser parser = new HttpHeaderParser(in);
|
||||||
logger.finest(parser.toString());
|
//logger.finest(parser.toString());
|
||||||
request = parser.getURLAttributes();
|
request = parser.getURLAttributes();
|
||||||
cookie = parser.getCookies();
|
cookie = parser.getCookies();
|
||||||
|
|
||||||
|
|
@ -202,7 +199,7 @@ public class HttpServer extends ThreadedTCPNetworkServer{
|
||||||
}
|
}
|
||||||
else if( tmp.contains("multipart/form-data") ){
|
else if( tmp.contains("multipart/form-data") ){
|
||||||
// TODO: File upload
|
// 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( "session_id", nextSessionId );
|
||||||
client_session.put( "ttl", ttl_time );
|
client_session.put( "ttl", ttl_time );
|
||||||
sessions.put( ""+nextSessionId, client_session );
|
sessions.put( ""+nextSessionId, client_session );
|
||||||
nextSessionId++;
|
++nextSessionId;
|
||||||
}
|
}
|
||||||
// Debug
|
// Debug
|
||||||
if(logger.isLoggable(Level.FINE)){
|
if(logger.isLoggable(Level.FINEST)){
|
||||||
logger.finest( "# page_url: "+parser.getRequestURL() );
|
logger.finest( "page_url: "+parser.getRequestURL() );
|
||||||
logger.finest( "# client_session: "+client_session );
|
logger.finest( "client_session: "+client_session );
|
||||||
logger.finest( "# cookie: "+cookie );
|
logger.finest( "cookie: "+cookie );
|
||||||
logger.finest( "# request: "+request );
|
logger.finest( "request: "+request );
|
||||||
}
|
}
|
||||||
//**************************** RESPONSE ************************************
|
//**************************** RESPONSE ************************************
|
||||||
logger.finer("Sending Http Response!!!");
|
logger.finer("Sending Http Response");
|
||||||
out.setStatusCode(200);
|
out.setStatusCode(200);
|
||||||
out.setHeader( "Server", SERVER_VERSION );
|
out.setHeader( "Server", SERVER_VERSION );
|
||||||
out.setHeader( "Content-Type", "text/html" );
|
out.setHeader( "Content-Type", "text/html" );
|
||||||
|
|
@ -252,15 +249,14 @@ public class HttpServer extends ThreadedTCPNetworkServer{
|
||||||
else{
|
else{
|
||||||
out.setStatusCode( 404 );
|
out.setStatusCode( 404 );
|
||||||
out.println( "404 Page Not Found: "+parser.getRequestURL() );
|
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) {
|
} catch (Exception e) {
|
||||||
logger.log(Level.WARNING, "500 Internal Server Error", e);
|
logger.log(Level.WARNING, "500 Internal Server Error", e);
|
||||||
try {
|
if(!out.isHeaderSent())
|
||||||
out.setStatusCode( 500 );
|
out.setStatusCode( 500 );
|
||||||
} catch (Exception e1) {}
|
|
||||||
if(e.getMessage() != null)
|
if(e.getMessage() != null)
|
||||||
out.println( "500 Internal Server Error: "+e.getMessage() );
|
out.println( "500 Internal Server Error: "+e.getMessage() );
|
||||||
else if(e.getCause() != null){
|
else if(e.getCause() != null){
|
||||||
|
|
@ -272,7 +268,7 @@ public class HttpServer extends ThreadedTCPNetworkServer{
|
||||||
}
|
}
|
||||||
|
|
||||||
try{
|
try{
|
||||||
logger.fine("Connection Closed!!!");
|
logger.fine("Connection Closed.");
|
||||||
out.close();
|
out.close();
|
||||||
in.close();
|
in.close();
|
||||||
socket.close();
|
socket.close();
|
||||||
|
|
|
||||||
155
src/zutil/net/http/pages/HttpFilePage.java
Normal file
155
src/zutil/net/http/pages/HttpFilePage.java
Normal 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -56,7 +56,7 @@ public class PluginData {
|
||||||
|
|
||||||
pluginVersion = data.getDouble("version");
|
pluginVersion = data.getDouble("version");
|
||||||
pluginName = data.getString("name");
|
pluginName = data.getString("name");
|
||||||
log.fine("Found plugin: "+pluginName);
|
log.fine("Plugin: "+this);
|
||||||
|
|
||||||
DataNode node = data.get("interfaces");
|
DataNode node = data.get("interfaces");
|
||||||
Iterator<String> intfIt = node.keyIterator();
|
Iterator<String> intfIt = node.keyIterator();
|
||||||
|
|
@ -98,4 +98,8 @@ public class PluginData {
|
||||||
public boolean contains(Class<?> intf){
|
public boolean contains(Class<?> intf){
|
||||||
return classMap.containsKey(intf);
|
return classMap.containsKey(intf);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String toString(){
|
||||||
|
return getName()+"(ver: "+getVersion()+")";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -71,12 +71,22 @@ public class PluginManager<T> implements Iterable<PluginData>{
|
||||||
for(FileSearch.FileSearchItem file : search){
|
for(FileSearch.FileSearchItem file : search){
|
||||||
try {
|
try {
|
||||||
DataNode node = JSONParser.read(IOUtil.getContentString(file.getInputStream()));
|
DataNode node = JSONParser.read(IOUtil.getContentString(file.getInputStream()));
|
||||||
|
log.fine("Found plugin: "+file.getPath());
|
||||||
PluginData plugin = new PluginData(node);
|
PluginData plugin = new PluginData(node);
|
||||||
|
|
||||||
if (!plugins.containsKey(plugin.getName()) ||
|
if (!plugins.containsKey(plugin.getName())){
|
||||||
plugins.get(plugin.getName()).getVersion() < plugin.getVersion()){
|
|
||||||
plugins.put(plugin.getName(), plugin);
|
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) {
|
} catch (Exception e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue