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
|
||||
* @return The extension
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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";
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
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,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()+")";
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue