/*
* $Id: DirContainer.java,v 1.7 2002/09/16 08:05:06 jkl Exp $
*
* Copyright (c) 2002 Njet Communications Ltd. All Rights Reserved.
*
* Use is subject to license terms, as defined in
* Anvil Sofware License, Version 1.1. See LICENSE
* file, or http://njet.org/license-1.1.txt
*/
package anvil.server;
import java.io.File;
import java.io.InputStream;
import java.io.ByteArrayOutputStream;
import java.io.ByteArrayInputStream;
import java.io.PrintStream;
import java.io.FileInputStream;
import java.io.OutputStream;
import java.io.IOException;
import java.io.FileNotFoundException;
import java.net.URL;
import java.net.MalformedURLException;
import java.util.StringTokenizer;
import java.util.Comparator;
import java.util.Calendar;
import java.util.Date;
import java.text.SimpleDateFormat;
import java.text.DateFormat;
import java.text.NumberFormat;
import java.text.DecimalFormat;
import anvil.util.Conversions;
import javax.servlet.http.HttpServletRequest;
/**
* class Container
*
* @author: Jani Lehtim�ki
*/
public class DirContainer implements Container
{
private static final DateFormat DATEFORMAT = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
private static final NumberFormat NUMBERFORMAT = new DecimalFormat("###,###,###,###,###");
protected File _dir;
public DirContainer(File dir)
{
_dir = dir;
}
protected String adapt(Zone zone, String pathinfo)
{
String basepath = zone.getBasePath();
return pathinfo.substring(basepath.length()-1);
}
public URL getResourceURL(Zone zone, Address address)
{
String pathinfo = adapt(zone, address.getPathinfo());
try {
return new URL("file:" + _dir.getPath() + pathinfo);
} catch (MalformedURLException e) {
}
return null;
}
public Resource getResource(Zone zone, Address address) throws ContainerException
{
return getResource(zone, address, null);
}
public Resource getResource(Zone zone, Address address, Context context) throws ContainerException
{
String pathinfo_ = address.getPathinfo();
String pathinfo = adapt(zone, pathinfo_);
File file = new File(_dir.getPath() + pathinfo);
if (file.exists() && file.isDirectory()) {
if (!pathinfo_.endsWith("/")) {
throw new RedirectException(pathinfo_+'/');
}
String dirindex = zone.getDirectoryIndex();
if (dirindex != null) {
File indexfile = new File(file, dirindex);
if (indexfile.exists()) {
file = indexfile;
address.setPathinfo(pathinfo_ + dirindex);
}
}
}
if (file.exists()) {
if (file.isDirectory()) {
return new DirResource(file, pathinfo_, context);
} else {
String contentType;
String filename = file.toString();
int i = filename.lastIndexOf('.');
if (i>0) {
contentType = zone.getContentType(
filename.substring(i).toLowerCase());
} else {
contentType = "text/plain";
}
return new FileResource(file, pathinfo_, contentType);
}
}
throw new ContainerException(404, "Resource not found: " + pathinfo_);
}
public static class FileResource implements Resource
{
private File _file;
private String _pathinfo;
private String _contentType;
public FileResource(File file, String pathinfo, String contentType)
{
_file = file;
_pathinfo = pathinfo;
_contentType = contentType;
}
public String getPathinfo()
{
return _pathinfo;
}
public URL getURL()
{
try {
return _file.toURL();
} catch (MalformedURLException e) {
}
return null;
}
public String getContentType()
{
return _contentType;
}
public long getLastModified()
{
return _file.lastModified();
}
public int getLength()
{
return (int)_file.length();
}
public InputStream getInputStream() throws IOException
{
return new FileInputStream(_file);
}
public void writeTo(OutputStream output) throws IOException
{
FileInputStream input = null;
try {
input = new FileInputStream(_file);
byte[] buffer = new byte[1024];
for(;;) {
int read = input.read(buffer, 0, buffer.length);
if (read <= 0) {
break;
}
output.write(buffer, 0, read);
}
} finally {
if (input != null) {
try {
input.close();
} catch (Throwable t) {
}
}
}
}
public void close()
{
}
}
public static final Comparator SORT_BY_NAME = new Comparator()
{
public int compare(Object a, Object b)
{
return ((File)a).getName().compareTo(((File)b).getName());
}
};
public static final Comparator SORT_BY_SIZE = new Comparator()
{
public int compare(Object a, Object b)
{
File filea = (File)a;
File fileb = (File)b;
boolean dira = filea.isDirectory();
boolean dirb = fileb.isDirectory();
if (dira && !dirb) {
return -1;
}
if (dirb && !dira) {
return 1;
}
long sizea = filea.length();
long sizeb = fileb.length();
if (sizea<sizeb) {
return -1;
} else if (sizea>sizeb) {
return 1;
} else {
return filea.getName().compareTo(fileb.getName());
}
}
};
public static final Comparator SORT_BY_DATE = new Comparator()
{
public int compare(Object a, Object b)
{
long datea = ((File)a).lastModified();
long datab = ((File)b).lastModified();
return ((datea<datab) ? -1 : ((datea>datab) ? 1 : 0));
}
};
public static class DirResource implements Resource
{
private File _dir;
private String _pathinfo;
private ByteArrayOutputStream _output;
public DirResource(File dir, String pathinfo, Context context)
{
_dir = dir;
_pathinfo = pathinfo;
_output = new ByteArrayOutputStream();
PrintStream out = new PrintStream(_output);
String path = _pathinfo;
out.print("<html>\n" +
" <head>\n" +
" <title>Index of ");
out.print(path);
out.print("</title></head>\n" +
" <body bgcolor=\"#ffffff\">\n" +
" <table border=\"0\" cellpadding=\"0\" cellspacing=\"0\"><tr><td bgcolor=\"#b0b0d0\">\n" +
" <table border=\"0\" cellpadding=\"3\" cellspacing=\"1\">\n" +
" <tr>\n" +
" <td bgcolor=\"#f0f0ff\" colspan=\"3\">\n" +
/* " <font face=\"verdana,lucida,arial,helvetica\" size=\"3\">\n" +*/
" <code>Index of <strong>");
StringTokenizer tokenizer = new StringTokenizer(path, "/");
StringBuffer buffer = new StringBuffer();
String part = "/";
while(true) {
buffer.append(part);
out.print("<a href=\"");
out.print(buffer);
out.print("\">");
out.print(part);
out.print("</a> ");
if (!tokenizer.hasMoreTokens()) {
break;
}
part = tokenizer.nextToken()+'/';
}
out.print("</strong></code>\n" +
/* " </font>\n" +*/
" </td>\n" +
" </tr>\n" +
" <tr bgcolor=\"#f0f0ff\">\n" +
" <td><code><strong><a href=\"./?S=N\">name</a></strong></code></td>\n" +
" <td align=right><code><strong><a href=\"./?S=S\">size</strong></code></td>\n" +
" <td><code><strong><a href=\"./?S=D\">last modified</strong></code></td>\n" +
" </tr>\n");
File parent = _dir.getParentFile();
if (parent != null) {
if (_pathinfo.length()>1) {
printFile(out, "..", parent);
}
}
Comparator cmp = SORT_BY_NAME;
if (context != null) {
HttpServletRequest request = context.getRequest();
String sortby = request.getParameter("S");
if (sortby != null) {
if (sortby.equals("N")) {
cmp = SORT_BY_NAME;
} else if (sortby.equals("S")) {
cmp = SORT_BY_SIZE;
} else if (sortby.equals("D")) {
cmp = SORT_BY_DATE;
}
}
}
File[] files = _dir.listFiles();
if (files != null) {
java.util.Arrays.sort(files, cmp);
int n = files.length;
for(int i=0; i<n; i++) {
File file = files[i];
printFile(out, file.getName(), file);
}
}
out.print(" </table>\n" +
" </td></tr></table>\n" +
" <code>");
out.print(anvil.server.Server.VERSION);
out.print("</code>\n" +
" </body>\n" +
"</html>\n");
}
private void printFile(PrintStream out, String name, File file)
{
out.print(" <tr bgcolor=\"#ffffff\"><td><code>\n");
if (file.isDirectory()) {
out.print("<strong><a href=\"");
out.print(Conversions.URLEncode(name));
out.print("/\">");
out.print(Conversions.encodeEntities(name));
out.print("/</a></strong>");
out.print("</code></td><td align=right> </td>");
} else {
out.print("<a href=\"");
out.print(Conversions.URLEncode(name));
out.print("\">");
out.print(Conversions.encodeEntities(name));
out.print("</a></code></td><td align=right> <code>");
out.print(NUMBERFORMAT.format(file.length()));
out.print("</code> </td>");
}
out.print("<td><code>");
out.println(DATEFORMAT.format(new Date(file.lastModified())));
out.print("</code></td></tr>");
}
public String getPathinfo()
{
return _pathinfo;
}
public URL getURL()
{
try {
return _dir.toURL();
} catch (MalformedURLException e) {
}
return null;
}
public String getContentType()
{
return "text/html";
}
public long getLastModified()
{
return _dir.lastModified();
}
public int getLength()
{
return _output.size();
}
public InputStream getInputStream() throws IOException
{
return new ByteArrayInputStream(_output.toByteArray());
}
public void writeTo(OutputStream output) throws IOException
{
_output.writeTo(output);
}
public void close()
{
}
}
}