package zeta.handler.statistic;
import java.awt.image.BufferedImage;
import java.io.BufferedInputStream;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.Date;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.sql.Timestamp;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
import java.util.zip.ZipInputStream;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import zeta.ZetaServlet;
import zeta.handler.GetHandler;
import zeta.util.DatabaseUtils;
import zeta.util.Parameter;
import zeta.util.StreamUtils;
public abstract class AbstractHandler implements GetHandler {
abstract public String createPage(Connection con) throws SQLException, ServletException;
protected String createPage(HttpServletRequest req, Connection con) throws SQLException, ServletException {
InnerPageBuffer innerPageBuffer = null;
ByteArrayOutputStream out = null;
try {
innerPageBuffer = getInnerPageBuffer();
if (innerPageBuffer == null) {
return "<tr><td colspan=\"8\"><p>This statistic is not available at moment! Please try again later.</td></tr>";
} else {
out = new ByteArrayOutputStream(10*1024);
StreamUtils.writeData(innerPageBuffer.buffer, out, false, true);
return out.toString("ISO-8859-1");
}
} catch (IOException ioe) {
throw new ServletException(ioe);
} finally {
if (innerPageBuffer != null) {
innerPageBuffer.close();
}
}
}
public BufferedImage createImage(Connection con, String imageName) throws SQLException, ServletException {
return null;
}
public AbstractHandler(ZetaServlet servlet, int diffTimeInnerPageUpdate, int diffTimePageUpdate, int diffTimeImageUpdate) {
this.servlet = servlet;
this.diffTimeInnerPageUpdate = diffTimeInnerPageUpdate;
this.diffTimePageUpdate = diffTimePageUpdate;
this.diffTimeImageUpdate = diffTimeImageUpdate;
}
public boolean isImageExpired(String imageName) {
Long time = (Long)lastImageUpdate.get(imageName);
long currentTime = System.currentTimeMillis();
if (time == null || (int)(System.currentTimeMillis() - time.longValue()) >= diffTimeImageUpdate) {
return true;
}
Date d1 = new Date(currentTime);
Date d2 = new Date(time.longValue());
return !d1.toString().equals(d2.toString());
}
public boolean isInnerPageExpired() {
return (lastInnerPageUpdate == 0 || (int)(System.currentTimeMillis() - lastInnerPageUpdate) >= diffTimeInnerPageUpdate);
}
public boolean isPageExpired() {
return (lastPageUpdate == 0 || (int)(System.currentTimeMillis() - lastPageUpdate) >= diffTimePageUpdate);
}
public int getInnerPageExpiredDiffTime() {
return diffTimeInnerPageUpdate;
}
public int getPageExpiredDiffTime() {
return diffTimePageUpdate;
}
final public void imageUpdateCompleted(String imageName) {
lastImageUpdate.put(imageName, new Long(System.currentTimeMillis()));
}
final public void pageUpdateCompleted() {
lastPageUpdate = lastInnerPageUpdate = System.currentTimeMillis();
}
public InnerPageBuffer getInnerPageBuffer() throws ServletException {
InnerPageBuffer innerPageBuffer = new InnerPageBuffer();
boolean exists = false;
if (servlet.hasSeparateFiles()) {
ZipInputStream zip = null;
Connection con = null;
Statement stmt = null;
try {
String pathPage = Parameter.getValue(null, "path_page", Parameter.GLOBAL_PARAMETER, null, 3600000);
if (pathPage == null) {
con = servlet.getConnection();
stmt = con.createStatement();
pathPage = Parameter.getValue(stmt, "path_page", Parameter.GLOBAL_PARAMETER, null, 3600000);
}
if (pathPage == null) {
pathPage = "";
} else if (pathPage.length() > 0 && pathPage.charAt(pathPage.length()-1) != '/') {
pathPage += '/';
}
File file = new File(pathPage + getClass().getName() + ".zip");
exists = true;
if (file.exists() && System.currentTimeMillis()-file.lastModified() < 4*diffTimeInnerPageUpdate+129600000) { zip = new ZipInputStream(new FileInputStream(file));
if (zip.getNextEntry() != null) {
timestampOfPage = file.lastModified();
innerPageBuffer.buffer = new BufferedInputStream(zip);
innerPageBuffer.resource = new Object[1];
innerPageBuffer.resource[0] = zip;
return innerPageBuffer;
}
}
} catch (Throwable e) {
if (innerPageBuffer != null) {
innerPageBuffer.close();
}
} finally {
DatabaseUtils.close(stmt);
DatabaseUtils.close(con);
}
} else {
Connection con = null;
Statement stmt = null;
try {
con = servlet.getConnection();
stmt = con.createStatement();
ResultSet rs = stmt.executeQuery("SELECT page,last_update FROM zeta.page WHERE classname='" + getClass().getName() + '\'');
if (rs.next()) {
exists = true;
Timestamp t = rs.getTimestamp(2);
if (System.currentTimeMillis()-t.getTime() < 4*diffTimeInnerPageUpdate+129600000) { ZipInputStream zip = new ZipInputStream(rs.getBinaryStream(1));
if (zip.getNextEntry() != null) {
timestampOfPage = (t == null)? System.currentTimeMillis() : t.getTime();
innerPageBuffer.buffer = new BufferedInputStream(zip);
innerPageBuffer.resource = new Object[3];
innerPageBuffer.resource[0] = rs;
innerPageBuffer.resource[1] = stmt;
innerPageBuffer.resource[2] = con;
return innerPageBuffer;
}
}
}
rs.close();
DatabaseUtils.close(stmt);
timestampOfPage = System.currentTimeMillis();
if (!exists) {
try {
innerPageBuffer.buffer = new BufferedInputStream(new ByteArrayInputStream(createPage(con).getBytes("ISO-8859-1")));
} finally {
DatabaseUtils.close(con);
}
}
return innerPageBuffer;
} catch (Throwable e) {
if (innerPageBuffer != null) {
innerPageBuffer.close();
}
}
}
return null;
}
public String getBufferedPage(HttpServletRequest req) throws ServletException {
synchronized (pageBuffer) {
createCompletePage(req);
String s = pageBuffer;
if (isPageExpired()) {
pageBuffer = "";
}
return s;
}
}
final public void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String imageName = req.getParameter("image");
if (imageName != null) {
ByteArrayOutputStream stream = (ByteArrayOutputStream)imageBuffer.get(imageName);
if (stream == null || isImageExpired(imageName)) {
if (stream == null) {
stream = new ByteArrayOutputStream(32*1024);
imageBuffer.put(imageName, stream);
}
boolean ok = false;
if (servlet.hasSeparateFiles()) {
Connection con = null;
Statement stmt = null;
FileInputStream in = null;
try {
String pathPage = Parameter.getValue(null, "path_page", Parameter.GLOBAL_PARAMETER, null, 3600000);
if (pathPage == null) {
con = servlet.getConnection();
stmt = con.createStatement();
pathPage = Parameter.getValue(stmt, "path_page", Parameter.GLOBAL_PARAMETER, null, 3600000);
}
if (pathPage == null) {
pathPage = "";
} else if (pathPage.charAt(pathPage.length()-1) != '/') {
pathPage += '/';
}
File file = new File(pathPage + getClass().getName() + '_' + imageName + ".png");
if (file.exists() && System.currentTimeMillis()-file.lastModified() < 129600000) { in = new FileInputStream(file);
stream.reset();
StreamUtils.writeData(in, stream, false, true);
imageUpdateCompleted(imageName);
ok = true;
}
} catch (Exception e) {
} finally {
DatabaseUtils.close(stmt);
DatabaseUtils.close(con);
StreamUtils.close(in);
}
}
if (!ok) {
Connection con = null;
try {
con = servlet.getConnection();
Statement stmt = null;
try {
stmt = con.createStatement();
ResultSet rs = stmt.executeQuery("SELECT image,last_update FROM zeta.image WHERE classname='" + getClass().getName() + "' AND imagename='" + imageName + '\'');
if (rs.next()) {
Timestamp t = rs.getTimestamp(2);
if (System.currentTimeMillis()-t.getTime() < 129600000) { stream.reset();
StreamUtils.writeData(rs.getBinaryStream(1), stream, false, true);
}
} else {
BufferedImage image = createImage(con, imageName);
if (image == null) {
throw new ServletException("No image available!");
}
stream.reset();
com.sun.jimi.core.encoder.png.PNGEncoder encoder = new com.sun.jimi.core.encoder.png.PNGEncoder();
encoder.encodeImage(com.sun.jimi.core.Jimi.createRasterImage(image.getSource()), stream);
stream.close();
}
rs.close();
imageUpdateCompleted(imageName);
} catch (com.sun.jimi.core.JimiException ex) {
} finally {
DatabaseUtils.close(stmt);
}
} catch (Exception e) {
throw new ServletException(e);
} finally {
DatabaseUtils.close(con);
}
}
}
resp.setContentType("image/png");
resp.setContentLength(stream.size());
resp.setHeader("Cache-Control", "max-age=3600"); stream.writeTo(resp.getOutputStream());
} else {
try {
String buffer = getBufferedPage(req);
resp.setContentType("text/html");
resp.setContentLength(buffer.length());
resp.getOutputStream().print(buffer);
} catch (Exception e) {
throw new ServletException(e);
}
}
}
public int getImageWidth(String imageName) {
return imgWidth;
}
public int getImageHeight(String imageName) {
return imgHeight;
}
private void createCompletePage(HttpServletRequest req) throws ServletException {
if (isPageExpired()) {
StringBuffer buffer = new StringBuffer(100*1024);
String s = servlet.getInitParameter("page.title");
if (s != null) {
buffer.append(s);
}
appendMenu(buffer);
s = servlet.getInitParameter("frame.top");
if (s != null) {
int idx = s.indexOf("@time@");
if (idx >= 0) {
buffer.append(s.substring(0, idx));
buffer.append(timeFormatter.format((timestampOfPage == 0)? new java.util.Date() : new java.util.Date(timestampOfPage)));
if (idx+6 < s.length()) {
buffer.append(s.substring(idx+6));
}
} else {
buffer.append(s);
}
}
Connection con = null;
String dbError = "The DB2 Server may be down";
try {
con = servlet.getConnection();
dbError = null;
buffer.append(createPage(req, con));
} catch (SQLException se) {
dbError = se.getMessage();
} catch (ServletException se) {
dbError = se.getMessage();
} finally {
DatabaseUtils.close(con);
}
if (dbError != null) {
buffer.append("<tr><td colspan=\"8\"><p>This statistic is not available at moment (");
buffer.append(dbError);
buffer.append(")!<p>Please try again later.</td></tr>");
}
s = servlet.getInitParameter("frame.bottom");
if (s != null) {
buffer.append(s);
}
pageBuffer = buffer.toString();
pageUpdateCompleted();
}
}
private void appendMenu(StringBuffer buffer) {
final int l = servlet.getNumberOfStatisticHandlers();
for (int i = 0; i < l; ++i) {
Class c = servlet.getStatisticHandlerClass(i);
if (c == getClass()) {
buffer.append("<tr><td BGCOLOR=\"#FFFFFF\"><img SRC=\"/zeta/images/odot.gif\" ALT=\"\" BORDER=0 / height=1 width=1></td>\n");
buffer.append("<td COLSPAN=\"");
buffer.append((i == 0)? 3 : 5);
buffer.append("\" BGCOLOR=\"#FFFFFF\"><img SRC=\"/zeta/images/odot.gif\" ALT=\"\" BORDER=0 / height=1 width=1></td>\n");
buffer.append("<td BGCOLOR=\"#FFFFFF\"><img SRC=\"/zeta/images/odot.gif\" ALT=\"\" BORDER=0 / height=1 width=1></td></tr>\n");
buffer.append("<tr><td");
if (i > 0) {
buffer.append(" COLSPAN=\"2\"");
}
buffer.append(" BGCOLOR=\"#FFFFFF\"><span class=\"nav\"></span></td>\n");
buffer.append("<td COLSPAN=\"5\" HEIGHT=\"21\" BGCOLOR=\"#FFFFFF\"><span class=\"nav\">");
buffer.append(servlet.getStatisticHandlerName(c));
buffer.append("</span></td>\n");
buffer.append("<td BGCOLOR=\"#FFFFFF\"><span class=\"nav\"></span></td></tr>\n");
buffer.append("<tr><td BGCOLOR=\"#FFFFFF\"><img SRC=\"/zeta/images/odot.gif\" ALT=\"\" BORDER=0 / height=1 width=1></td>\n");
buffer.append("<td COLSPAN=\"");
buffer.append((i == 0)? 3 : 5);
buffer.append("\" BGCOLOR=\"#FFFFFF\"><img SRC=\"/zeta/images/odot.gif\" ALT=\"\" BORDER=0 / height=1 width=1></td>\n");
buffer.append("<td BGCOLOR=\"#FFFFFF\"><img SRC=\"/zeta/images/odot.gif\" ALT=\"\" BORDER=0 / height=1 width=1></td></tr>\n");
} else {
if (i == 0) {
buffer.append("<tr><td><img SRC=\"/zeta/images/odot.gif\" ALT=\"\" BORDER=0 / height=1 width=1></td>\n");
buffer.append("<td COLSPAN=\"3\" BGCOLOR=\"#CCCCFF\"><img SRC=\"/zeta/images/odot.gif\" ALT=\"\" BORDER=0 / height=1 width=1></td>\n");
buffer.append("<td><img SRC=\"/zeta/images/odot.gif\" ALT=\"\" BORDER=0 / height=1 width=1></td></tr>\n");
}
buffer.append("<tr><td");
if (i > 0) {
buffer.append(" COLSPAN=\"2\"");
}
buffer.append("> </td>\n");
buffer.append("<td COLSPAN=\"");
buffer.append((i == 0)? 3 : 2);
buffer.append("\" HEIGHT=\"21\"><span class=\"nav\"><a href=\"");
buffer.append(servlet.getHandlerAddress(c));
buffer.append("\">");
buffer.append(servlet.getStatisticHandlerName(c));
buffer.append("</a></span></td>\n");
buffer.append("<td> </td></tr>\n");
if (i+1 == l) {
buffer.append("<tr><td><img SRC=\"/zeta/images/odot.gif\" ALT=\"\" BORDER=0 / height=1 width=1></td>\n");
buffer.append("<td COLSPAN=\"3\" BGCOLOR=\"#CCCCFF\"><img SRC=\"/zeta/images/odot.gif\" ALT=\"\" BORDER=0 / height=1 width=1></td>\n");
buffer.append("<td><img SRC=\"/zeta/images/odot.gif\" ALT=\"\" BORDER=0 / height=1 width=1></td></tr>\n");
} else if (servlet.getStatisticHandlerClass(i+1) != getClass()) {
buffer.append("<tr><td COLSPAN=\"2\"><img SRC=\"/zeta/images/odot.gif\" ALT=\"\" BORDER=0 / height=1 width=1></td>\n");
buffer.append("<td COLSPAN=\"2\" BGCOLOR=\"#CCCCFF\"><img SRC=\"/zeta/images/odot.gif\" ALT=\"\" BORDER=0 / height=1 width=1></td>\n");
buffer.append("<td><img SRC=\"/zeta/images/odot.gif\" ALT=\"\" BORDER=0 / height=1 width=1></td></tr>\n");
}
}
}
}
protected ZetaServlet servlet;
private static DateFormat timeFormatter = new SimpleDateFormat("MM/dd/yyyy HH:mm:ss", Locale.GERMANY);
protected static final int imgWidth = 700;
protected static final int imgHeight = 500;
private Map imageBuffer = new HashMap();
private Map lastImageUpdate = new HashMap();
private String pageBuffer = "";
private long lastInnerPageUpdate = 0;
private long lastPageUpdate = 0;
private int diffTimeInnerPageUpdate = 0;
private int diffTimePageUpdate = 0;
private int diffTimeImageUpdate = 0;
private long timestampOfPage = 0;
class InnerPageBuffer {
public boolean skip(String search, boolean ignoreCase) {
try {
return StreamUtils.skip(buffer, search, ignoreCase);
} catch (IOException ioe) {
return false;
}
}
public String[] getLines(String search, boolean ignoreCase) {
try {
return StreamUtils.getLines(buffer, search, ignoreCase);
} catch (IOException ioe) {
return null;
}
}
public String between(String left, String right, boolean ignoreCase) {
try {
return StreamUtils.between(buffer, left, right, ignoreCase);
} catch (IOException ioe) {
return null;
}
}
void close() throws ServletException {
if (buffer != null) {
StreamUtils.close(buffer);
buffer = null;
}
if (resource != null) {
for (int i = 0; i < resource.length; ++i) {
if (resource[i] instanceof InputStream) {
StreamUtils.close((InputStream)resource[i]);
} else if (resource[i] instanceof ResultSet) {
try {
((ResultSet)resource[i]).close();
} catch (SQLException e) {
}
} else if (resource[i] instanceof Statement) {
DatabaseUtils.close((Statement)resource[i]);
} else if (resource[i] instanceof Connection) {
DatabaseUtils.close((Connection)resource[i]);
} else {
throw new ServletException("Unknow resource!");
}
}
resource = null;
}
}
BufferedInputStream buffer = null;
Object[] resource = null;
}
}