From: <bra...@us...> - 2008-07-28 20:48:52
|
Revision: 2510 http://archive-access.svn.sourceforge.net/archive-access/?rev=2510&view=rev Author: bradtofel Date: 2008-07-28 20:49:00 +0000 (Mon, 28 Jul 2008) Log Message: ----------- INITIAL REV: likely temporary class to simplify creation of an HTML select.. Handy until we switch to JSTL. Added Paths: ----------- trunk/archive-access/projects/wayback/wayback-core/src/main/java/org/archive/wayback/util/html/ trunk/archive-access/projects/wayback/wayback-core/src/main/java/org/archive/wayback/util/html/SelectHTML.java Added: trunk/archive-access/projects/wayback/wayback-core/src/main/java/org/archive/wayback/util/html/SelectHTML.java =================================================================== --- trunk/archive-access/projects/wayback/wayback-core/src/main/java/org/archive/wayback/util/html/SelectHTML.java (rev 0) +++ trunk/archive-access/projects/wayback/wayback-core/src/main/java/org/archive/wayback/util/html/SelectHTML.java 2008-07-28 20:49:00 UTC (rev 2510) @@ -0,0 +1,50 @@ +package org.archive.wayback.util.html; + +import java.util.ArrayList; +import java.util.List; + +public class SelectHTML { + List<String[]> options = null; + String activeValue = null; + String name = null; + String props = null; + public SelectHTML(String name) { + this.name = name; + options = new ArrayList<String[]>(); + } + public void addOption(String name, String value) { + String[] newOption = {name,value}; + options.add(newOption); + } + public void addOption(String name) { + addOption(name,name); + } + public void setActive(String value) { + activeValue = value; + } + public void setProps(String props) { + this.props = props; + } + public String draw() { + StringBuilder sb = new StringBuilder(100); + sb.append("<select"); + if(props != null) { + sb.append(" ").append(props); + } + sb.append(" name=\"").append(name).append("\">"); + + for(String[] option : options) { + sb.append("<option value=\"").append(option[1]).append("\""); + if(activeValue != null) { + if(activeValue.equals(option[1])) { + sb.append(" selected"); + } + } + sb.append(">"); + sb.append(option[0]).append("</option>"); + } + + sb.append("</select>"); + return sb.toString(); + } +} This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <bra...@us...> - 2009-10-28 01:04:46
|
Revision: 2857 http://archive-access.svn.sourceforge.net/archive-access/?rev=2857&view=rev Author: bradtofel Date: 2009-10-28 01:04:33 +0000 (Wed, 28 Oct 2009) Log Message: ----------- INITIAL REV: couldn't find anything out there that had the right interface: produce HTTP message and headers from a raw InputStream, so this is here until a better and usable package out there is discovered.. Added Paths: ----------- trunk/archive-access/projects/wayback/wayback-core/src/main/java/org/archive/wayback/util/http/ trunk/archive-access/projects/wayback/wayback-core/src/main/java/org/archive/wayback/util/http/BadRequestException.java trunk/archive-access/projects/wayback/wayback-core/src/main/java/org/archive/wayback/util/http/HttpMessage.java trunk/archive-access/projects/wayback/wayback-core/src/main/java/org/archive/wayback/util/http/HttpRequest.java trunk/archive-access/projects/wayback/wayback-core/src/main/java/org/archive/wayback/util/http/HttpRequestMessage.java trunk/archive-access/projects/wayback/wayback-core/src/main/java/org/archive/wayback/util/http/HttpResponse.java trunk/archive-access/projects/wayback/wayback-core/src/main/java/org/archive/wayback/util/http/HttpResponseMessage.java Added: trunk/archive-access/projects/wayback/wayback-core/src/main/java/org/archive/wayback/util/http/BadRequestException.java =================================================================== --- trunk/archive-access/projects/wayback/wayback-core/src/main/java/org/archive/wayback/util/http/BadRequestException.java (rev 0) +++ trunk/archive-access/projects/wayback/wayback-core/src/main/java/org/archive/wayback/util/http/BadRequestException.java 2009-10-28 01:04:33 UTC (rev 2857) @@ -0,0 +1,34 @@ +/* BadRequestException + * + * $Id$ + * + * Created on 3:56:12 PM Dec 16, 2008. + * + * Copyright (C) 2008 Internet Archive. + * + * This file is part of Wayback. + * + * SocksProxyCore is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * any later version. + * + * SocksProxyCore is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser Public License for more details. + * + * You should have received a copy of the GNU Lesser Public License + * along with SocksProxyCore; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +package org.archive.wayback.util.http; + +import java.io.IOException; + +public class BadRequestException extends IOException { + private static final long serialVersionUID = -7123306169949959915L; + public BadRequestException(String message) { + super(message); + } +} Property changes on: trunk/archive-access/projects/wayback/wayback-core/src/main/java/org/archive/wayback/util/http/BadRequestException.java ___________________________________________________________________ Added: svn:executable + * Added: trunk/archive-access/projects/wayback/wayback-core/src/main/java/org/archive/wayback/util/http/HttpMessage.java =================================================================== --- trunk/archive-access/projects/wayback/wayback-core/src/main/java/org/archive/wayback/util/http/HttpMessage.java (rev 0) +++ trunk/archive-access/projects/wayback/wayback-core/src/main/java/org/archive/wayback/util/http/HttpMessage.java 2009-10-28 01:04:33 UTC (rev 2857) @@ -0,0 +1,165 @@ +/* HttpMessage + * + * $Id$ + * + * Created on 5:48:40 PM Mar 2, 2009. + * + * Copyright (C) 2009 Internet Archive. + * + * This file is part of Wayback. + * + * ProxyServletCore is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * any later version. + * + * ProxyServletCore is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser Public License for more details. + * + * You should have received a copy of the GNU Lesser Public License + * along with ProxyServletCore; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +package org.archive.wayback.util.http; + +import java.io.IOException; +import java.io.InputStream; + +import org.archive.wayback.util.http.BadRequestException; +import org.archive.wayback.util.ByteOp; + +/** + * + * + * @author brad + * @version $Date$, $Revision$ + */ + +public class HttpMessage { + private static int MAX_MESSAGE_SIZE = 4096; + public static byte SPACE = 32; + public static byte CR = 13; + public static byte LF = 10; + + public static byte[] readLine(InputStream in, int max) + throws IOException, BadRequestException { + + byte[] buffer = new byte[max]; + int pos = 0; + boolean found = false; + while(pos < max) { + int next = in.read(); + buffer[pos] = (byte) next; + if(next == LF) { + if(pos == 0) { + throw new BadRequestException( + "Message cannot start with LF"); + } + if(buffer[pos - 1] == CR) { + found = true; + break; + } + } + pos++; + } + if(!found) { + throw new BadRequestException("Message too long without CRLF"); + } + return ByteOp.copy(buffer,0,pos+1); + } + + private static int[] findSpaces(byte[] buffer, int max) + throws BadRequestException { + + int spaces[] = new int[max]; + int found = 0; + int offset = 0; + int end = buffer.length - 2; + while(offset < end) { + if(buffer[offset] == SPACE) { + spaces[found] = offset; + found++; + } + if(found == max - 1) { + break; + } + offset++; + } + if(found != max - 1) { + throw new BadRequestException("Not enough fields(" + found +") " + + "want("+max+") in (" + new String(buffer)+ ")"); + } + return spaces; + } + + public static byte[][] loadFields(byte[] buffer, int max) + throws BadRequestException { + + byte[][] fields = new byte[max][]; + int[] offsets = findSpaces(buffer, max); + int start = 0; + for(int i = 0; i < max - 1; i++) { + fields[i] = ByteOp.copy(buffer, start, offsets[i] - start); + start = offsets[i] + 1; + } + fields[max-1] = ByteOp.copy(buffer, start, (buffer.length - 2) - start); + return fields; + } + + public byte[] concatBytes(byte[][] fields, boolean addCrLf) { + int length = 1; + for(byte[] field : fields) { + length += field.length + 1; + } + if(!addCrLf) { + length -= 2; + } + byte[] buffer = new byte[length]; + int index = 0; + for(byte[] field : fields) { + System.arraycopy(field, 0, + buffer, index, field.length); + index += field.length; + if(index < length) { + buffer[index] = SPACE; + } + index++; + } + if(addCrLf) { + buffer[length - 2] = CR; + buffer[length - 1] = LF; + } + + return buffer; + } + + public static HttpResponseMessage loadResponse(byte[] buffer) + throws BadRequestException { + + byte[][] fields = loadFields(buffer,3); + + return new HttpResponseMessage(fields[0],fields[1],fields[2]); + } + + public static HttpResponseMessage loadResponse(InputStream in) + throws BadRequestException, IOException { + + return loadResponse(readLine(in, MAX_MESSAGE_SIZE)); + } + + public static HttpRequestMessage loadRequest(byte[] buffer) + throws BadRequestException { + + byte[][] fields = loadFields(buffer,3); + + return new HttpRequestMessage(fields[0],fields[1],fields[2]); + } + + public static HttpRequestMessage loadRequest(InputStream in) + throws BadRequestException, IOException { + + return loadRequest(readLine(in, MAX_MESSAGE_SIZE)); + } +} Added: trunk/archive-access/projects/wayback/wayback-core/src/main/java/org/archive/wayback/util/http/HttpRequest.java =================================================================== --- trunk/archive-access/projects/wayback/wayback-core/src/main/java/org/archive/wayback/util/http/HttpRequest.java (rev 0) +++ trunk/archive-access/projects/wayback/wayback-core/src/main/java/org/archive/wayback/util/http/HttpRequest.java 2009-10-28 01:04:33 UTC (rev 2857) @@ -0,0 +1,111 @@ +/* HttpRequest + * + * $Id$ + * + * Created on 4:49:10 PM Dec 16, 2008. + * + * Copyright (C) 2008 Internet Archive. + * + * This file is part of Wayback. + * + * SocksProxyCore is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * any later version. + * + * SocksProxyCore is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser Public License for more details. + * + * You should have received a copy of the GNU Lesser Public License + * along with SocksProxyCore; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +package org.archive.wayback.util.http; + +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStream; + +import org.archive.util.anvl.ANVLRecord; +import org.archive.wayback.util.http.BadRequestException; +import org.archive.wayback.util.ByteOp; + +/** + * + * + * @author brad + * @version $Date$, $Revision$ + */ + +public class HttpRequest { + + private static int MAX_HEADER_SIZE = 10240; + + private HttpRequestMessage message = null; + private ANVLRecord headers = null; + + private byte[] originalHeaders = null; + + public HttpRequest(HttpRequestMessage message, byte[] originalHeaders) + throws IOException { + + this.originalHeaders = originalHeaders; + this.message = message; + // If we want to keep the headers - we're not using them: + ByteArrayInputStream bais = new ByteArrayInputStream(originalHeaders); + headers = ANVLRecord.load(bais); + } + + /** + * @return the headers + */ + public ANVLRecord getHeaders() { + return headers; + } + + /** + * @param headers the headers to set + */ + public void setHeaders(ANVLRecord headers) { + this.headers = headers; + } + + /** + * @return the inputBytes + */ + public byte[] getOriginalHeaders() { + return originalHeaders; + } + public HttpRequestMessage getMessage() { + return message; + } + /** + * @return the method + */ + public String getMethod() { + return message.getMethod(); + } + + /** + * @return the url + */ + public String getPath() { + return message.getPath(); + } + + public static HttpRequest load(InputStream in) + throws IOException, BadRequestException { + + HttpRequestMessage message = HttpMessage.loadRequest(in); + + byte[] buffer = new byte[MAX_HEADER_SIZE]; + + int r = in.read(buffer, 0, MAX_HEADER_SIZE); + if(r == MAX_HEADER_SIZE) { + throw new BadRequestException("Request too long"); + } + return new HttpRequest(message, ByteOp.copy(buffer,0,r)); + } +} Added: trunk/archive-access/projects/wayback/wayback-core/src/main/java/org/archive/wayback/util/http/HttpRequestMessage.java =================================================================== --- trunk/archive-access/projects/wayback/wayback-core/src/main/java/org/archive/wayback/util/http/HttpRequestMessage.java (rev 0) +++ trunk/archive-access/projects/wayback/wayback-core/src/main/java/org/archive/wayback/util/http/HttpRequestMessage.java 2009-10-28 01:04:33 UTC (rev 2857) @@ -0,0 +1,151 @@ +/* HttpRequestMessage + * + * $Id$ + * + * Created on 5:44:56 PM Mar 2, 2009. + * + * Copyright (C) 2009 Internet Archive. + * + * This file is part of Wayback. + * + * ProxyServletCore is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * any later version. + * + * ProxyServletCore is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser Public License for more details. + * + * You should have received a copy of the GNU Lesser Public License + * along with ProxyServletCore; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +package org.archive.wayback.util.http; + +import org.archive.wayback.util.ByteOp; + + +public class HttpRequestMessage extends HttpMessage { + private static byte[] METHOD_HEAD = {'H', 'E', 'A', 'D'}; + private static byte[] METHOD_GET = {'G', 'E', 'T'}; + + private byte[] method = null; + private byte[] path = null; + private byte[] version = null; + public HttpRequestMessage(byte[] method, byte[] path, byte[] version) { + this.method = method; + this.path = path; + this.version = version; + } + public String getMethod() { + return new String(method); + } + public String getPath() { + return new String(path); + } + public String getVersion() { + return new String(version); + } + public HttpRequestMessage _clone() { + return new HttpRequestMessage(method,path,version); + } + public void setPath(byte[] path) { + this.path = path; + } + public byte[] getBytes(boolean addCrLf) { + byte[][] fields = {method,path,version}; + return concatBytes(fields,addCrLf); + } + +// public byte[] getBytes() { +// // ' ' + ' ' + \r\n = 4 +// int length = path.length + method.length + version.length + 4; +// int versionStart = path.length + method.length + 2; +// +// byte[] buffer = new byte[length]; +// +// System.arraycopy(method, 0, +// buffer, 0, method.length); +// +// buffer[method.length] = SPACE; +// +// System.arraycopy(path, 0, +// buffer, method.length + 1, path.length); +// +// buffer[versionStart - 1] = SPACE; +// +// System.arraycopy(version, 0, +// buffer, versionStart, version.length); +// buffer[versionStart + version.length] = CR; +// buffer[versionStart + version.length + 1] = LF; +// +// return buffer; +// } + + public boolean isHead() { + return ByteOp.cmp(method,METHOD_HEAD); + } + public boolean isGet() { + return ByteOp.cmp(method,METHOD_GET); + } + +// public static HttpRequestMessage load(InputStream in) +// throws BadRequestException, IOException { +// return load(HttpMessage.readLine(in,MAX_SIZE)); +// } +// +// public static HttpRequestMessage load(byte[] buffer) +// throws BadRequestException { +// +// byte[] method = null; +// byte[] path = null; +// byte[] version = null; +// +// int length = buffer.length; +// int end = length - 2; +// int firstSpace = 0; +// int lastSpace = end; +// +// +// +// // make sure ends in CRLF: +// if((buffer[length - 2] != CR) +// || (buffer[length - 1] != LF)) { +// +// throw new BadRequestException("Bed end of Message(no CRLF): " +// + new String(buffer)); +// } +// +// // find first ' ' (after METHOD): +// while(firstSpace < end) { +// if(buffer[firstSpace] == SPACE) { +// method = ByteOp.copy(buffer, 0, firstSpace); +// break; +// } +// firstSpace++; +// } +// +// // find last ' ' (before VERSION): +// while(lastSpace > firstSpace) { +// if(buffer[lastSpace] == SPACE) { +// version = ByteOp.copy(buffer, lastSpace + 1, end - (lastSpace+1)); +// break; +// } +// lastSpace--; +// } +// path = ByteOp.copy(buffer, firstSpace + 1, (lastSpace - firstSpace) - 1); +// // make sure path has no spaces: +// int position = 0; +// while(position < path.length) { +// if(path[position] == SPACE) { +// throw new BadRequestException("Too many fields in Message: " +// + new String(buffer)); +// } +// position++; +// } +//// version = "HTTP/1.0".getBytes(); +// return new HttpRequestMessage(method, path, version); +// } +} Property changes on: trunk/archive-access/projects/wayback/wayback-core/src/main/java/org/archive/wayback/util/http/HttpRequestMessage.java ___________________________________________________________________ Added: svn:executable + * Added: trunk/archive-access/projects/wayback/wayback-core/src/main/java/org/archive/wayback/util/http/HttpResponse.java =================================================================== --- trunk/archive-access/projects/wayback/wayback-core/src/main/java/org/archive/wayback/util/http/HttpResponse.java (rev 0) +++ trunk/archive-access/projects/wayback/wayback-core/src/main/java/org/archive/wayback/util/http/HttpResponse.java 2009-10-28 01:04:33 UTC (rev 2857) @@ -0,0 +1,60 @@ +/* HttpResponse + * + * $Id$ + * + * Created on 5:44:56 PM Mar 2, 2009. + * + * Copyright (C) 2009 Internet Archive. + * + * This file is part of Wayback. + * + * ProxyServletCore is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * any later version. + * + * ProxyServletCore is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser Public License for more details. + * + * You should have received a copy of the GNU Lesser Public License + * along with ProxyServletCore; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +package org.archive.wayback.util.http; + +import java.io.IOException; +import java.io.InputStream; + +import org.archive.util.anvl.ANVLRecord; +import org.archive.wayback.util.http.BadRequestException; + +public class HttpResponse { + private HttpResponseMessage message = null; + private ANVLRecord headers = null; + private InputStream bodyInputStream = null; + public HttpResponse(HttpResponseMessage message, ANVLRecord headers, + InputStream bodyInputStream) { + + this.message = message; + this.headers = headers; + this.bodyInputStream = bodyInputStream; + } + public HttpResponseMessage getMessage() { + return message; + } + public ANVLRecord getHeaders() { + return headers; + } + public InputStream getBodyInputStream() { + return bodyInputStream; + } + public static HttpResponse load(InputStream in) + throws BadRequestException, IOException { + + HttpResponseMessage message = HttpMessage.loadResponse(in); + ANVLRecord headers = ANVLRecord.load(in); + return new HttpResponse(message,headers,in); + } +} Property changes on: trunk/archive-access/projects/wayback/wayback-core/src/main/java/org/archive/wayback/util/http/HttpResponse.java ___________________________________________________________________ Added: svn:executable + * Added: trunk/archive-access/projects/wayback/wayback-core/src/main/java/org/archive/wayback/util/http/HttpResponseMessage.java =================================================================== --- trunk/archive-access/projects/wayback/wayback-core/src/main/java/org/archive/wayback/util/http/HttpResponseMessage.java (rev 0) +++ trunk/archive-access/projects/wayback/wayback-core/src/main/java/org/archive/wayback/util/http/HttpResponseMessage.java 2009-10-28 01:04:33 UTC (rev 2857) @@ -0,0 +1,62 @@ +/* HttpResponseMessage + * + * $Id$ + * + * Created on 5:44:56 PM Mar 2, 2009. + * + * Copyright (C) 2009 Internet Archive. + * + * This file is part of Wayback. + * + * ProxyServletCore is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * any later version. + * + * ProxyServletCore is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser Public License for more details. + * + * You should have received a copy of the GNU Lesser Public License + * along with ProxyServletCore; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +package org.archive.wayback.util.http; + +import org.archive.wayback.util.ByteOp; + +/** + * + * + * @author brad + * @version $Date$, $Revision$ + */ + +public class HttpResponseMessage extends HttpMessage { + private static byte[] HTTP_304 = {'3', '0', '4'}; + private byte[] version = null; + private byte[] code = null; + private byte[] text = null; + public HttpResponseMessage(byte[] version, byte[] code, byte[] text) { + this.version = version; + this.code = code; + this.text = text; + } + public String getVersion() { + return new String(version); + } + public String getCode() { + return new String(code); + } + public String getText() { + return new String(text); + } + public boolean isNotModified() { + return ByteOp.cmp(code, HTTP_304); + } + public byte[] getBytes(boolean addCrLf) { + byte[][] fields = {version,code,text}; + return concatBytes(fields, addCrLf); + } +} This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <bra...@us...> - 2009-11-05 23:02:01
|
Revision: 2879 http://archive-access.svn.sourceforge.net/archive-access/?rev=2879&view=rev Author: bradtofel Date: 2009-11-05 23:01:46 +0000 (Thu, 05 Nov 2009) Log Message: ----------- INITIAL REV: Library which sits on top of htmlparser, enabling SAX stream handling for both indexing, text & link extraction, and streaming modifications to HTML documents. Added Paths: ----------- trunk/archive-access/projects/wayback/wayback-core/src/main/java/org/archive/wayback/util/htmllex/ trunk/archive-access/projects/wayback/wayback-core/src/main/java/org/archive/wayback/util/htmllex/ContextAwareLexer.java trunk/archive-access/projects/wayback/wayback-core/src/main/java/org/archive/wayback/util/htmllex/NodeUtils.java trunk/archive-access/projects/wayback/wayback-core/src/main/java/org/archive/wayback/util/htmllex/ParseContext.java trunk/archive-access/projects/wayback/wayback-core/src/main/java/org/archive/wayback/util/htmllex/ParseEventDelegator.java trunk/archive-access/projects/wayback/wayback-core/src/main/java/org/archive/wayback/util/htmllex/ParseEventDelegatorVisitor.java trunk/archive-access/projects/wayback/wayback-core/src/main/java/org/archive/wayback/util/htmllex/ParseEventHandler.java trunk/archive-access/projects/wayback/wayback-core/src/main/java/org/archive/wayback/util/htmllex/handlers/ trunk/archive-access/projects/wayback/wayback-core/src/main/java/org/archive/wayback/util/htmllex/handlers/CSSTextHandler.java trunk/archive-access/projects/wayback/wayback-core/src/main/java/org/archive/wayback/util/htmllex/handlers/CloseTagHandler.java trunk/archive-access/projects/wayback/wayback-core/src/main/java/org/archive/wayback/util/htmllex/handlers/ContentTextHandler.java trunk/archive-access/projects/wayback/wayback-core/src/main/java/org/archive/wayback/util/htmllex/handlers/JSTextHandler.java trunk/archive-access/projects/wayback/wayback-core/src/main/java/org/archive/wayback/util/htmllex/handlers/OpenTagHandler.java trunk/archive-access/projects/wayback/wayback-core/src/main/java/org/archive/wayback/util/htmllex/handlers/ParseCompleteHandler.java trunk/archive-access/projects/wayback/wayback-core/src/main/java/org/archive/wayback/util/htmllex/handlers/RemarkTextHandler.java Added: trunk/archive-access/projects/wayback/wayback-core/src/main/java/org/archive/wayback/util/htmllex/ContextAwareLexer.java =================================================================== --- trunk/archive-access/projects/wayback/wayback-core/src/main/java/org/archive/wayback/util/htmllex/ContextAwareLexer.java (rev 0) +++ trunk/archive-access/projects/wayback/wayback-core/src/main/java/org/archive/wayback/util/htmllex/ContextAwareLexer.java 2009-11-05 23:01:46 UTC (rev 2879) @@ -0,0 +1,84 @@ +/* ContextAwareLexer + * + * $Id$ + * + * Created on 12:36:59 PM Nov 5, 2009. + * + * Copyright (C) 2008 Internet Archive. + * + * This file is part of wayback. + * + * wayback is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * any later version. + * + * wayback is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser Public License for more details. + * + * You should have received a copy of the GNU Lesser Public License + * along with wayback; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +package org.archive.wayback.util.htmllex; + +import org.htmlparser.Node; +import org.htmlparser.lexer.Lexer; +import org.htmlparser.util.ParserException; + +/** + * + * The Lexer that comes with htmlparser does not handle non-escaped HTML + * entities within SCRIPT tags - by default, something like: + * + * <script> + * for(var i=0; i<23; i++) { j+=i; } + * </script> + * + * Can cause the lexer to skip over a large part of the document. Technically, + * the above isn't legit HTML, but of course, folks do stuff like that all the + * time. So, this class uses a ParseContext object, passed in at construction, + * which observes the SCRIPT and STYLE tags, both setting properties on the + * ParseContext, and using that state information to perform a parseCDATA() + * call instead of a nextNode() call at the right time, to try to keep the + * SAX parsing in sync with the document. + * + * @author brad + * + */ +public class ContextAwareLexer extends NodeUtils { + + private Lexer lexer = null; + private ParseContext context = null; + public ContextAwareLexer(Lexer lexer, ParseContext context) { + this.lexer = lexer; + this.context = context; + } + public Node nextNode() throws ParserException { + Node node = null; + if(context.isInJS()) { + node = lexer.parseCDATA(true); + if(node != null) { + context.setInScriptText(true); + context.setInJS(false); + return node; + } + } + context.setInScriptText(false); + node = lexer.nextNode(context.isInJS()); + if(node != null) { + if(isNonEmptyOpenTagNodeNamed(node, SCRIPT_TAG_NAME)) { + context.setInJS(true); + } else if(isCloseTagNodeNamed(node, SCRIPT_TAG_NAME)) { + context.setInJS(false); + } else if(isNonEmptyOpenTagNodeNamed(node, STYLE_TAG_NAME)) { + context.setInCSS(true); + } else if(isCloseTagNodeNamed(node, STYLE_TAG_NAME)) { + context.setInCSS(false); + } + } + return node; + } +} Property changes on: trunk/archive-access/projects/wayback/wayback-core/src/main/java/org/archive/wayback/util/htmllex/ContextAwareLexer.java ___________________________________________________________________ Added: svn:keywords + Author Date Revision Id Added: trunk/archive-access/projects/wayback/wayback-core/src/main/java/org/archive/wayback/util/htmllex/NodeUtils.java =================================================================== --- trunk/archive-access/projects/wayback/wayback-core/src/main/java/org/archive/wayback/util/htmllex/NodeUtils.java (rev 0) +++ trunk/archive-access/projects/wayback/wayback-core/src/main/java/org/archive/wayback/util/htmllex/NodeUtils.java 2009-11-05 23:01:46 UTC (rev 2879) @@ -0,0 +1,83 @@ +/* NodeUtils + * + * $Id$ + * + * Created on 12:36:59 PM Nov 5, 2009. + * + * Copyright (C) 2008 Internet Archive. + * + * This file is part of wayback. + * + * wayback is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * any later version. + * + * wayback is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser Public License for more details. + * + * You should have received a copy of the GNU Lesser Public License + * along with wayback; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +package org.archive.wayback.util.htmllex; + +import org.htmlparser.Node; +import org.htmlparser.nodes.RemarkNode; +import org.htmlparser.nodes.TagNode; +import org.htmlparser.nodes.TextNode; + +public class NodeUtils { + public static final String SCRIPT_TAG_NAME = "SCRIPT"; + public static final String STYLE_TAG_NAME = "STYLE"; + + public static boolean isTagNode(Node node) { + return (node instanceof TagNode); + } + public static boolean isTextNode(Node node) { + return (node instanceof TextNode); + } + public static boolean isRemarkNode(Node node) { + return (node instanceof RemarkNode); + } + public static boolean isTagNodeNamed(Node node, String name) { + if(isTagNode(node)) { + TagNode tagNode = (TagNode) node; + String nodeName = tagNode.getTagName(); + return nodeName.equals(name); + } + return false; + } + public static boolean isOpenTagNodeNamed(Node node, String name) { + if(isTagNode(node)) { + TagNode tagNode = (TagNode) node; + if(!tagNode.isEndTag()) { + String nodeName = tagNode.getTagName(); + return nodeName.equals(name); + } + } + return false; + } + public static boolean isNonEmptyOpenTagNodeNamed(Node node, String name) { + if(isTagNode(node)) { + TagNode tagNode = (TagNode) node; + if(!tagNode.isEndTag() && !tagNode.isEmptyXmlTag()) { + String nodeName = tagNode.getTagName(); + return nodeName.equals(name); + } + } + return false; + } + public static boolean isCloseTagNodeNamed(Node node, String name) { + if(isTagNode(node)) { + TagNode tagNode = (TagNode) node; + if(tagNode.isEndTag()) { + String nodeName = tagNode.getTagName(); + return nodeName.equals(name); + } + } + return false; + } +} Property changes on: trunk/archive-access/projects/wayback/wayback-core/src/main/java/org/archive/wayback/util/htmllex/NodeUtils.java ___________________________________________________________________ Added: svn:keywords + Author Date Revision Id Added: trunk/archive-access/projects/wayback/wayback-core/src/main/java/org/archive/wayback/util/htmllex/ParseContext.java =================================================================== --- trunk/archive-access/projects/wayback/wayback-core/src/main/java/org/archive/wayback/util/htmllex/ParseContext.java (rev 0) +++ trunk/archive-access/projects/wayback/wayback-core/src/main/java/org/archive/wayback/util/htmllex/ParseContext.java 2009-11-05 23:01:46 UTC (rev 2879) @@ -0,0 +1,118 @@ +/* ParseContext + * + * $Id$ + * + * Created on 2:06:46 PM Feb 19, 2009. + * + * Copyright (C) 2009 Internet Archive. + * + * This file is part of test. + * + * test is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * any later version. + * + * test is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser Public License for more details. + * + * You should have received a copy of the GNU Lesser Public License + * along with test; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +package org.archive.wayback.util.htmllex; + +import java.net.MalformedURLException; +import java.net.URL; +import java.util.HashMap; + +/** + * Class which tracks the context and state involved with parsing an HTML + * document via SAX events. + * + * Also holds some page URL information, and provides some URL resolving + * functionality. + * + * Lastly, this class exposes a general purpose HashMap<String,String> for use + * by specific applications. + * + * @author brad + * @version $Date$, $Revision$ + */ + +public class ParseContext { + protected URL baseUrl = null; + + private boolean inCSS = false; + private boolean inJS = false; + private boolean inScriptText = false; + private HashMap<String,String> data = null; + + public ParseContext() { + data = new HashMap<String, String>(); + } + public void putData(String key, String value) { + data.put(key, value); + } + public String getData(String key) { + return data.get(key); + } + public void setBaseUrl(URL url) { + baseUrl = url; + } + public String resolve(String url) throws MalformedURLException { + URL tmp = new URL(baseUrl,url); + return tmp.toString(); + } + public String contextualizeUrl(String url) { + if(url.startsWith("javascript:")) { + return url; + } + try { + return resolve(url); + } catch (MalformedURLException e) { + e.printStackTrace(); + return url; + } + } + + /** + * @return the inCSS + */ + public boolean isInCSS() { + return inCSS; + } + /** + * @param inCSS the inCSS to set + */ + public void setInCSS(boolean inCSS) { + this.inCSS = inCSS; + } + /** + * @return the inJS + */ + public boolean isInJS() { + return inJS; + } + /** + * @param inJS the inJS to set + */ + public void setInJS(boolean inJS) { + this.inJS = inJS; + } + + /** + * @return the inScriptText + */ + public boolean isInScriptText() { + return inScriptText; + } + /** + * @param inScriptText the inScriptText to set + */ + public void setInScriptText(boolean inScriptText) { + this.inScriptText = inScriptText; + } +} Property changes on: trunk/archive-access/projects/wayback/wayback-core/src/main/java/org/archive/wayback/util/htmllex/ParseContext.java ___________________________________________________________________ Added: svn:keywords + Author Date Revision Id Added: trunk/archive-access/projects/wayback/wayback-core/src/main/java/org/archive/wayback/util/htmllex/ParseEventDelegator.java =================================================================== --- trunk/archive-access/projects/wayback/wayback-core/src/main/java/org/archive/wayback/util/htmllex/ParseEventDelegator.java (rev 0) +++ trunk/archive-access/projects/wayback/wayback-core/src/main/java/org/archive/wayback/util/htmllex/ParseEventDelegator.java 2009-11-05 23:01:46 UTC (rev 2879) @@ -0,0 +1,255 @@ +/* ParseEventDelegator + * + * $Id$ + * + * Created on 12:36:59 PM Nov 5, 2009. + * + * Copyright (C) 2008 Internet Archive. + * + * This file is part of wayback. + * + * wayback is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * any later version. + * + * wayback is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser Public License for more details. + * + * You should have received a copy of the GNU Lesser Public License + * along with wayback; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +package org.archive.wayback.util.htmllex; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.archive.wayback.util.htmllex.handlers.CSSTextHandler; +import org.archive.wayback.util.htmllex.handlers.CloseTagHandler; +import org.archive.wayback.util.htmllex.handlers.ContentTextHandler; +import org.archive.wayback.util.htmllex.handlers.JSTextHandler; +import org.archive.wayback.util.htmllex.handlers.OpenTagHandler; +import org.archive.wayback.util.htmllex.handlers.ParseCompleteHandler; +import org.archive.wayback.util.htmllex.handlers.RemarkTextHandler; +import org.htmlparser.Node; +import org.htmlparser.nodes.RemarkNode; +import org.htmlparser.nodes.TagNode; +import org.htmlparser.nodes.TextNode; + +/** + * + * This class provides an abstraction between high-level SAX events, and + * application specific low-level SAX event handlers. + * + * Any object which wishes to receive any low-level SAX events is placed in the + * parserVisitors List, and at initialization of this class, each element in + * that list is given an opportunity to register to receive whatever low-level + * SAX events it is interested in. + * + * This class also manages casting of Node objects into more event-specific + * casts, and uses the ParseContext to route specific nodes to the registered + * handlers of each low-level event types. + * + * This class attempts to be efficient about targeting specific TagNodes: + * When registering to receive events, handlers can register for a specific + * tag name, or for the global-tag ("*") name. + * + * As TagNodes are handled, all tag-specific handlers are called, followed by + * all global-tag handlers. + * + * @author brad + */ +public class ParseEventDelegator implements ParseEventHandler { + + public static final String WILDCARD_TAG_NAME = "*"; + + private Map<String,List<CloseTagHandler>> closeTagHandlers = null; + private Map<String,List<OpenTagHandler>> openTagHandlers = null; + private List<CSSTextHandler> cssTextHandlers = null; + private List<JSTextHandler> jsTextHandler = null; + private List<RemarkTextHandler> remarkTextHandler = null; + private List<ContentTextHandler> contentTextHandler = null; + private List<ParseCompleteHandler> parseCompleteHandlers = null; + + private List<ParseEventDelegatorVisitor> parserVisitors = null; + + + public void init() { + if(parserVisitors != null) { + for(ParseEventDelegatorVisitor visitor : parserVisitors) { + visitor.visit(this); + } + } + } + + public void handleNode(ParseContext context, Node node) + throws IOException { + + if(NodeUtils.isRemarkNode(node)) { + RemarkNode remarkNode = (RemarkNode) node; + handleRemarkTextNode(context,remarkNode); + + } else if(NodeUtils.isTextNode(node)) { + TextNode textNode = (TextNode) node; + if(context.isInCSS()) { + handleCSSTextNode(context,textNode); + + } else if(context.isInScriptText()) { + handleJSTextNode(context,textNode); + } else { + handleContentTextNode(context,textNode); + } + } else if(NodeUtils.isTagNode(node)) { + TagNode tagNode = (TagNode) node; + if(tagNode.isEndTag()) { + handleCloseTagNode(context,tagNode); + } else { + // assume start, possibly empty: + handleOpenTagNode(context,tagNode); + } + } else { + throw new IllegalArgumentException("Unknown node type.."); + } + } + + // CLOSE TAG: + public void addCloseTagHandler(CloseTagHandler v) { + addCloseTagHandler(v, WILDCARD_TAG_NAME); + } + public void addCloseTagHandler(CloseTagHandler v, String name) { + if(closeTagHandlers == null) { + closeTagHandlers = new HashMap<String,List<CloseTagHandler>>(); + } + if(!closeTagHandlers.containsKey(name)) { + closeTagHandlers.put(name, new ArrayList<CloseTagHandler>()); + } + closeTagHandlers.get(name).add(v); + } + public void handleCloseTagNode(ParseContext context, TagNode node) throws IOException { + String name = node.getTagName(); + if(closeTagHandlers != null) { + for(String n : new String[]{name,WILDCARD_TAG_NAME}) { + if(closeTagHandlers.containsKey(n)) { + for(CloseTagHandler v : closeTagHandlers.get(n)) { + v.handleCloseTagNode(context,node); + } + } + } + } + } + + // OPEN TAG: + public void addOpenTagHandler(OpenTagHandler v) { + addOpenTagHandler(v, WILDCARD_TAG_NAME); + } + public void addOpenTagHandler(OpenTagHandler v, String name) { + if(openTagHandlers == null) { + openTagHandlers = new HashMap<String,List<OpenTagHandler>>(); + } + if(!openTagHandlers.containsKey(name)) { + openTagHandlers.put(name, new ArrayList<OpenTagHandler>()); + } + openTagHandlers.get(name).add(v); + } + + public void handleOpenTagNode(ParseContext context, TagNode node) throws IOException { + String name = node.getTagName(); + if(openTagHandlers != null) { + for(String n : new String[]{name,WILDCARD_TAG_NAME}) { + if(openTagHandlers.containsKey(n)) { + for(OpenTagHandler v : openTagHandlers.get(n)) { + v.handleOpenTagNode(context,node); + } + } + } + } + } + public void addCSSTextHandler(CSSTextHandler v) { + if(cssTextHandlers == null) { + cssTextHandlers = new ArrayList<CSSTextHandler>(); + } + cssTextHandlers.add(v); + } + public void handleCSSTextNode(ParseContext context, TextNode node) throws IOException { + if(cssTextHandlers != null) { + for(CSSTextHandler v : cssTextHandlers) { + v.handleCSSTextNode(context,node); + } + } + } + public void addJSTextHandler(JSTextHandler v) { + if(jsTextHandler == null) { + jsTextHandler = new ArrayList<JSTextHandler>(); + } + jsTextHandler.add(v); + } + public void handleJSTextNode(ParseContext context, TextNode node) throws IOException { + if(jsTextHandler != null) { + for(JSTextHandler v : jsTextHandler) { + v.handleJSTextNode(context,node); + } + } + } + + public void addRemarkTextHandler(RemarkTextHandler v) { + if(remarkTextHandler == null) { + remarkTextHandler = new ArrayList<RemarkTextHandler>(); + } + remarkTextHandler.add(v); + } + public void handleRemarkTextNode(ParseContext context, RemarkNode node) throws IOException { + if(remarkTextHandler != null) { + for(RemarkTextHandler v : remarkTextHandler) { + v.handleRemarkTextNode(context,node); + } + } + } + + public void addContentTextHandler(ContentTextHandler v) { + if(contentTextHandler == null) { + contentTextHandler = new ArrayList<ContentTextHandler>(); + } + contentTextHandler.add(v); + } + public void handleContentTextNode(ParseContext context, TextNode node) throws IOException { + if(contentTextHandler != null) { + for(ContentTextHandler v : contentTextHandler) { + v.handleContentTextNode(context,node); + } + } + } + + public void addParseCompleteHandler(ParseCompleteHandler v) { + if(parseCompleteHandlers == null) { + parseCompleteHandlers = new ArrayList<ParseCompleteHandler>(); + } + parseCompleteHandlers.add(v); + } + public void handleParseComplete(ParseContext context) throws IOException { + if(parseCompleteHandlers != null) { + for(ParseCompleteHandler v : parseCompleteHandlers) { + v.handleParseComplete(context); + } + } + } + + /** + * @return the parserVisitors + */ + public List<ParseEventDelegatorVisitor> getParserVisitors() { + return parserVisitors; + } + + /** + * @param parserVisitors the parserVisitors to set + */ + public void setParserVisitors(List<ParseEventDelegatorVisitor> parserVisitors) { + this.parserVisitors = parserVisitors; + } +} Property changes on: trunk/archive-access/projects/wayback/wayback-core/src/main/java/org/archive/wayback/util/htmllex/ParseEventDelegator.java ___________________________________________________________________ Added: svn:keywords + Author Date Revision Id Added: trunk/archive-access/projects/wayback/wayback-core/src/main/java/org/archive/wayback/util/htmllex/ParseEventDelegatorVisitor.java =================================================================== --- trunk/archive-access/projects/wayback/wayback-core/src/main/java/org/archive/wayback/util/htmllex/ParseEventDelegatorVisitor.java (rev 0) +++ trunk/archive-access/projects/wayback/wayback-core/src/main/java/org/archive/wayback/util/htmllex/ParseEventDelegatorVisitor.java 2009-11-05 23:01:46 UTC (rev 2879) @@ -0,0 +1,42 @@ +/* ParseEventDelegatorVisitor + * + * $Id$ + * + * Created on 12:36:59 PM Nov 5, 2009. + * + * Copyright (C) 2008 Internet Archive. + * + * This file is part of wayback. + * + * wayback is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * any later version. + * + * wayback is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser Public License for more details. + * + * You should have received a copy of the GNU Lesser Public License + * along with wayback; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +package org.archive.wayback.util.htmllex; + + +/** + * + * Common interface to decouple application-specific handlers from the + * ParseEventDelegator object: Any object interested in registering for specific + * low-level events can implement this interface, and can be added to the + * ParseEventDelegator parserVisitors list, and it will be given an opportunity + * to register with the ParseEventDelegator for specific events it is + * interested in. + * + * @author brad + * + */ +public interface ParseEventDelegatorVisitor { + public void visit(ParseEventDelegator rules); +} Property changes on: trunk/archive-access/projects/wayback/wayback-core/src/main/java/org/archive/wayback/util/htmllex/ParseEventDelegatorVisitor.java ___________________________________________________________________ Added: svn:keywords + Author Date Revision Id Added: trunk/archive-access/projects/wayback/wayback-core/src/main/java/org/archive/wayback/util/htmllex/ParseEventHandler.java =================================================================== --- trunk/archive-access/projects/wayback/wayback-core/src/main/java/org/archive/wayback/util/htmllex/ParseEventHandler.java (rev 0) +++ trunk/archive-access/projects/wayback/wayback-core/src/main/java/org/archive/wayback/util/htmllex/ParseEventHandler.java 2009-11-05 23:01:46 UTC (rev 2879) @@ -0,0 +1,43 @@ +/* ParseEventHandler + * + * $Id$ + * + * Created on 12:36:59 PM Nov 5, 2009. + * + * Copyright (C) 2008 Internet Archive. + * + * This file is part of wayback. + * + * wayback is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * any later version. + * + * wayback is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser Public License for more details. + * + * You should have received a copy of the GNU Lesser Public License + * along with wayback; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +package org.archive.wayback.util.htmllex; + +import java.io.IOException; + +import org.htmlparser.Node; + +/** + * General interface used with the ContextAwareLexer to handle high-level SAX + * stream events. See ParseEventDelegator and ParseEventDelegatorVisitor for + * more detailed usage. + * + * @author brad + * + */ +public interface ParseEventHandler { + public void handleNode(ParseContext context, Node node) + throws IOException; + public void handleParseComplete(ParseContext context) throws IOException; +} Property changes on: trunk/archive-access/projects/wayback/wayback-core/src/main/java/org/archive/wayback/util/htmllex/ParseEventHandler.java ___________________________________________________________________ Added: svn:keywords + Author Date Revision Id Added: trunk/archive-access/projects/wayback/wayback-core/src/main/java/org/archive/wayback/util/htmllex/handlers/CSSTextHandler.java =================================================================== --- trunk/archive-access/projects/wayback/wayback-core/src/main/java/org/archive/wayback/util/htmllex/handlers/CSSTextHandler.java (rev 0) +++ trunk/archive-access/projects/wayback/wayback-core/src/main/java/org/archive/wayback/util/htmllex/handlers/CSSTextHandler.java 2009-11-05 23:01:46 UTC (rev 2879) @@ -0,0 +1,35 @@ +/* CSSTextHandler + * + * $Id$ + * + * Created on 12:36:59 PM Nov 5, 2009. + * + * Copyright (C) 2008 Internet Archive. + * + * This file is part of wayback. + * + * wayback is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * any later version. + * + * wayback is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser Public License for more details. + * + * You should have received a copy of the GNU Lesser Public License + * along with wayback; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +package org.archive.wayback.util.htmllex.handlers; + +import java.io.IOException; + +import org.archive.wayback.util.htmllex.ParseContext; +import org.htmlparser.nodes.TextNode; + +public interface CSSTextHandler { + public void handleCSSTextNode(ParseContext context, TextNode node) + throws IOException; +} Property changes on: trunk/archive-access/projects/wayback/wayback-core/src/main/java/org/archive/wayback/util/htmllex/handlers/CSSTextHandler.java ___________________________________________________________________ Added: svn:keywords + Author Date Revision Id Added: trunk/archive-access/projects/wayback/wayback-core/src/main/java/org/archive/wayback/util/htmllex/handlers/CloseTagHandler.java =================================================================== --- trunk/archive-access/projects/wayback/wayback-core/src/main/java/org/archive/wayback/util/htmllex/handlers/CloseTagHandler.java (rev 0) +++ trunk/archive-access/projects/wayback/wayback-core/src/main/java/org/archive/wayback/util/htmllex/handlers/CloseTagHandler.java 2009-11-05 23:01:46 UTC (rev 2879) @@ -0,0 +1,35 @@ +/* CloseTagHandler + * + * $Id$ + * + * Created on 12:36:59 PM Nov 5, 2009. + * + * Copyright (C) 2008 Internet Archive. + * + * This file is part of wayback. + * + * wayback is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * any later version. + * + * wayback is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser Public License for more details. + * + * You should have received a copy of the GNU Lesser Public License + * along with wayback; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +package org.archive.wayback.util.htmllex.handlers; + +import java.io.IOException; + +import org.archive.wayback.util.htmllex.ParseContext; +import org.htmlparser.nodes.TagNode; + +public interface CloseTagHandler { + public void handleCloseTagNode(ParseContext context, TagNode node) + throws IOException; +} Property changes on: trunk/archive-access/projects/wayback/wayback-core/src/main/java/org/archive/wayback/util/htmllex/handlers/CloseTagHandler.java ___________________________________________________________________ Added: svn:keywords + Author Date Revision Id Added: trunk/archive-access/projects/wayback/wayback-core/src/main/java/org/archive/wayback/util/htmllex/handlers/ContentTextHandler.java =================================================================== --- trunk/archive-access/projects/wayback/wayback-core/src/main/java/org/archive/wayback/util/htmllex/handlers/ContentTextHandler.java (rev 0) +++ trunk/archive-access/projects/wayback/wayback-core/src/main/java/org/archive/wayback/util/htmllex/handlers/ContentTextHandler.java 2009-11-05 23:01:46 UTC (rev 2879) @@ -0,0 +1,35 @@ +/* ContentTextHandler + * + * $Id$ + * + * Created on 12:36:59 PM Nov 5, 2009. + * + * Copyright (C) 2008 Internet Archive. + * + * This file is part of wayback. + * + * wayback is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * any later version. + * + * wayback is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser Public License for more details. + * + * You should have received a copy of the GNU Lesser Public License + * along with wayback; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +package org.archive.wayback.util.htmllex.handlers; + +import java.io.IOException; + +import org.archive.wayback.util.htmllex.ParseContext; +import org.htmlparser.nodes.TextNode; + +public interface ContentTextHandler { + public void handleContentTextNode(ParseContext context, TextNode node) + throws IOException; +} Property changes on: trunk/archive-access/projects/wayback/wayback-core/src/main/java/org/archive/wayback/util/htmllex/handlers/ContentTextHandler.java ___________________________________________________________________ Added: svn:keywords + Author Date Revision Id Added: trunk/archive-access/projects/wayback/wayback-core/src/main/java/org/archive/wayback/util/htmllex/handlers/JSTextHandler.java =================================================================== --- trunk/archive-access/projects/wayback/wayback-core/src/main/java/org/archive/wayback/util/htmllex/handlers/JSTextHandler.java (rev 0) +++ trunk/archive-access/projects/wayback/wayback-core/src/main/java/org/archive/wayback/util/htmllex/handlers/JSTextHandler.java 2009-11-05 23:01:46 UTC (rev 2879) @@ -0,0 +1,35 @@ +/* JSTextHandler + * + * $Id$ + * + * Created on 12:36:59 PM Nov 5, 2009. + * + * Copyright (C) 2008 Internet Archive. + * + * This file is part of wayback. + * + * wayback is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * any later version. + * + * wayback is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser Public License for more details. + * + * You should have received a copy of the GNU Lesser Public License + * along with wayback; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +package org.archive.wayback.util.htmllex.handlers; + +import java.io.IOException; + +import org.archive.wayback.util.htmllex.ParseContext; +import org.htmlparser.nodes.TextNode; + +public interface JSTextHandler { + public void handleJSTextNode(ParseContext context, TextNode node) + throws IOException; +} Property changes on: trunk/archive-access/projects/wayback/wayback-core/src/main/java/org/archive/wayback/util/htmllex/handlers/JSTextHandler.java ___________________________________________________________________ Added: svn:keywords + Author Date Revision Id Added: trunk/archive-access/projects/wayback/wayback-core/src/main/java/org/archive/wayback/util/htmllex/handlers/OpenTagHandler.java =================================================================== --- trunk/archive-access/projects/wayback/wayback-core/src/main/java/org/archive/wayback/util/htmllex/handlers/OpenTagHandler.java (rev 0) +++ trunk/archive-access/projects/wayback/wayback-core/src/main/java/org/archive/wayback/util/htmllex/handlers/OpenTagHandler.java 2009-11-05 23:01:46 UTC (rev 2879) @@ -0,0 +1,35 @@ +/* OpenTagHandler + * + * $Id$ + * + * Created on 12:36:59 PM Nov 5, 2009. + * + * Copyright (C) 2008 Internet Archive. + * + * This file is part of wayback. + * + * wayback is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * any later version. + * + * wayback is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser Public License for more details. + * + * You should have received a copy of the GNU Lesser Public License + * along with wayback; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +package org.archive.wayback.util.htmllex.handlers; + +import java.io.IOException; + +import org.archive.wayback.util.htmllex.ParseContext; +import org.htmlparser.nodes.TagNode; + +public interface OpenTagHandler { + public void handleOpenTagNode(ParseContext context, TagNode node) + throws IOException; +} Property changes on: trunk/archive-access/projects/wayback/wayback-core/src/main/java/org/archive/wayback/util/htmllex/handlers/OpenTagHandler.java ___________________________________________________________________ Added: svn:keywords + Author Date Revision Id Added: trunk/archive-access/projects/wayback/wayback-core/src/main/java/org/archive/wayback/util/htmllex/handlers/ParseCompleteHandler.java =================================================================== --- trunk/archive-access/projects/wayback/wayback-core/src/main/java/org/archive/wayback/util/htmllex/handlers/ParseCompleteHandler.java (rev 0) +++ trunk/archive-access/projects/wayback/wayback-core/src/main/java/org/archive/wayback/util/htmllex/handlers/ParseCompleteHandler.java 2009-11-05 23:01:46 UTC (rev 2879) @@ -0,0 +1,35 @@ +/* ParseCompleteHandler + * + * $Id$ + * + * Created on 12:36:59 PM Nov 5, 2009. + * + * Copyright (C) 2008 Internet Archive. + * + * This file is part of wayback. + * + * wayback is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * any later version. + * + * wayback is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser Public License for more details. + * + * You should have received a copy of the GNU Lesser Public License + * along with wayback; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +package org.archive.wayback.util.htmllex.handlers; + +import java.io.IOException; + +import org.archive.wayback.util.htmllex.ParseContext; + + +public interface ParseCompleteHandler { + public void handleParseComplete(ParseContext context) + throws IOException; +} Property changes on: trunk/archive-access/projects/wayback/wayback-core/src/main/java/org/archive/wayback/util/htmllex/handlers/ParseCompleteHandler.java ___________________________________________________________________ Added: svn:keywords + Author Date Revision Id Added: trunk/archive-access/projects/wayback/wayback-core/src/main/java/org/archive/wayback/util/htmllex/handlers/RemarkTextHandler.java =================================================================== --- trunk/archive-access/projects/wayback/wayback-core/src/main/java/org/archive/wayback/util/htmllex/handlers/RemarkTextHandler.java (rev 0) +++ trunk/archive-access/projects/wayback/wayback-core/src/main/java/org/archive/wayback/util/htmllex/handlers/RemarkTextHandler.java 2009-11-05 23:01:46 UTC (rev 2879) @@ -0,0 +1,35 @@ +/* RemarkTextHandler + * + * $Id$ + * + * Created on 12:36:59 PM Nov 5, 2009. + * + * Copyright (C) 2008 Internet Archive. + * + * This file is part of wayback. + * + * wayback is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * any later version. + * + * wayback is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser Public License for more details. + * + * You should have received a copy of the GNU Lesser Public License + * along with wayback; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +package org.archive.wayback.util.htmllex.handlers; + +import java.io.IOException; + +import org.archive.wayback.util.htmllex.ParseContext; +import org.htmlparser.nodes.RemarkNode; + +public interface RemarkTextHandler { + public void handleRemarkTextNode(ParseContext context, RemarkNode node) + throws IOException; +} Property changes on: trunk/archive-access/projects/wayback/wayback-core/src/main/java/org/archive/wayback/util/htmllex/handlers/RemarkTextHandler.java ___________________________________________________________________ Added: svn:keywords + Author Date Revision Id This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <bra...@us...> - 2009-11-08 00:45:30
|
Revision: 2916 http://archive-access.svn.sourceforge.net/archive-access/?rev=2916&view=rev Author: bradtofel Date: 2009-11-08 00:45:14 +0000 (Sun, 08 Nov 2009) Log Message: ----------- CLEANUP: added @SuppressWarnings Modified Paths: -------------- trunk/archive-access/projects/wayback/wayback-core/src/main/java/org/archive/wayback/util/AdaptedIterator.java trunk/archive-access/projects/wayback/wayback-core/src/main/java/org/archive/wayback/util/ObjectFilterIterator.java trunk/archive-access/projects/wayback/wayback-core/src/main/java/org/archive/wayback/util/PeekableIterator.java Modified: trunk/archive-access/projects/wayback/wayback-core/src/main/java/org/archive/wayback/util/AdaptedIterator.java =================================================================== --- trunk/archive-access/projects/wayback/wayback-core/src/main/java/org/archive/wayback/util/AdaptedIterator.java 2009-11-08 00:42:59 UTC (rev 2915) +++ trunk/archive-access/projects/wayback/wayback-core/src/main/java/org/archive/wayback/util/AdaptedIterator.java 2009-11-08 00:45:14 UTC (rev 2916) @@ -85,6 +85,7 @@ /* (non-Javadoc) * @see org.archive.wayback.util.Cleanable#clean() */ + @SuppressWarnings("unchecked") public void close() throws IOException { if(itr instanceof CloseableIterator) { CloseableIterator<S> toBeClosed = (CloseableIterator<S>) itr; Modified: trunk/archive-access/projects/wayback/wayback-core/src/main/java/org/archive/wayback/util/ObjectFilterIterator.java =================================================================== --- trunk/archive-access/projects/wayback/wayback-core/src/main/java/org/archive/wayback/util/ObjectFilterIterator.java 2009-11-08 00:42:59 UTC (rev 2915) +++ trunk/archive-access/projects/wayback/wayback-core/src/main/java/org/archive/wayback/util/ObjectFilterIterator.java 2009-11-08 00:45:14 UTC (rev 2916) @@ -75,6 +75,7 @@ return true; } + @SuppressWarnings("unchecked") public void close() { if(itr instanceof CloseableIterator) { CloseableIterator<T> citr = Modified: trunk/archive-access/projects/wayback/wayback-core/src/main/java/org/archive/wayback/util/PeekableIterator.java =================================================================== --- trunk/archive-access/projects/wayback/wayback-core/src/main/java/org/archive/wayback/util/PeekableIterator.java 2009-11-08 00:42:59 UTC (rev 2915) +++ trunk/archive-access/projects/wayback/wayback-core/src/main/java/org/archive/wayback/util/PeekableIterator.java 2009-11-08 00:45:14 UTC (rev 2916) @@ -78,6 +78,7 @@ /* (non-Javadoc) * @see org.archive.wayback.util.Cleanable#clean() */ + @SuppressWarnings("unchecked") public void close() throws IOException { if(itr instanceof CloseableIterator) { CloseableIterator<E> toBeClosed = (CloseableIterator<E>) itr; This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <bra...@us...> - 2010-04-10 02:41:38
|
Revision: 3032 http://archive-access.svn.sourceforge.net/archive-access/?rev=3032&view=rev Author: bradtofel Date: 2010-04-10 02:41:32 +0000 (Sat, 10 Apr 2010) Log Message: ----------- INITIAL REV: Code which simplifies partitioning Date-related types into partitions of human-logical sizes, Day, Hour, Two Weeks, Year, etc. Users must provide a class which maps their instance-specific type to a Date, and which adds their type to a partition. Added Paths: ----------- trunk/archive-access/projects/wayback/wayback-core/src/main/java/org/archive/wayback/util/partition/ trunk/archive-access/projects/wayback/wayback-core/src/main/java/org/archive/wayback/util/partition/ElementPartitionMap.java trunk/archive-access/projects/wayback/wayback-core/src/main/java/org/archive/wayback/util/partition/Partition.java trunk/archive-access/projects/wayback/wayback-core/src/main/java/org/archive/wayback/util/partition/PartitionSize.java trunk/archive-access/projects/wayback/wayback-core/src/main/java/org/archive/wayback/util/partition/Partitioner.java trunk/archive-access/projects/wayback/wayback-core/src/main/java/org/archive/wayback/util/partition/size/ trunk/archive-access/projects/wayback/wayback-core/src/main/java/org/archive/wayback/util/partition/size/DayPartitionSize.java trunk/archive-access/projects/wayback/wayback-core/src/main/java/org/archive/wayback/util/partition/size/HourPartitionSize.java trunk/archive-access/projects/wayback/wayback-core/src/main/java/org/archive/wayback/util/partition/size/MonthPartitionSize.java trunk/archive-access/projects/wayback/wayback-core/src/main/java/org/archive/wayback/util/partition/size/TwoMonthPartitionSize.java trunk/archive-access/projects/wayback/wayback-core/src/main/java/org/archive/wayback/util/partition/size/TwoYearPartitionSize.java trunk/archive-access/projects/wayback/wayback-core/src/main/java/org/archive/wayback/util/partition/size/WeekPartitionSize.java trunk/archive-access/projects/wayback/wayback-core/src/main/java/org/archive/wayback/util/partition/size/YearPartitionSize.java Added: trunk/archive-access/projects/wayback/wayback-core/src/main/java/org/archive/wayback/util/partition/ElementPartitionMap.java =================================================================== --- trunk/archive-access/projects/wayback/wayback-core/src/main/java/org/archive/wayback/util/partition/ElementPartitionMap.java (rev 0) +++ trunk/archive-access/projects/wayback/wayback-core/src/main/java/org/archive/wayback/util/partition/ElementPartitionMap.java 2010-04-10 02:41:32 UTC (rev 3032) @@ -0,0 +1,59 @@ +/* ElementPartitionMap + * + * $Id$: + * + * Created on Apr 8, 2010. + * + * Copyright (C) 2006 Internet Archive. + * + * This file is part of Wayback. + * + * Wayback is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * any later version. + * + * Wayback is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser Public License for more details. + * + * You should have received a copy of the GNU Lesser Public License + * along with Wayback; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +package org.archive.wayback.util.partition; + +import java.util.Date; + +/** + * @author brad + * @param <T> Specific Class which can be mapped to a Date, and added to a + * Partition + * + */ +public interface ElementPartitionMap<T> { + /** + * Convert an element to a Date ex: + * + * return element.getDate(); + * + * @param element the element to convert + * @return the Date for the element + */ + public Date elementToDate(T element); + + /** + * Add the element to a partition, possible modifying the Partition in some + * way. ex: + * + * partition.add(element); + * partition.addTotal(1); + * + * @param element to be added + * @param partition to which the element should be added + */ + public void addElementToPartition(T element, Partition<T> partition); + +} Property changes on: trunk/archive-access/projects/wayback/wayback-core/src/main/java/org/archive/wayback/util/partition/ElementPartitionMap.java ___________________________________________________________________ Added: svn:keywords + Author Date Revision Id Added: trunk/archive-access/projects/wayback/wayback-core/src/main/java/org/archive/wayback/util/partition/Partition.java =================================================================== --- trunk/archive-access/projects/wayback/wayback-core/src/main/java/org/archive/wayback/util/partition/Partition.java (rev 0) +++ trunk/archive-access/projects/wayback/wayback-core/src/main/java/org/archive/wayback/util/partition/Partition.java 2010-04-10 02:41:32 UTC (rev 3032) @@ -0,0 +1,126 @@ +package org.archive.wayback.util.partition; + +import java.util.ArrayList; +import java.util.Date; +import java.util.Iterator; +import java.util.List; + +/** + * A class which holds elements of some type for a particular Date range. + * + * This class also has two additional application-usable fields: + + * containsClosest: boolean - tracks whether this Partition holds the + * "closest" element of interest to an application + * + * total: int - independent counter for total internal application-level + * elements, useful when nesting partitions, to track the sum-of-totals + * of interior partitions + * + * @author brad + * + * @param <T> Generic type which this partition holds. + */ +public class Partition<T> { + + private Date start = null; + private Date end = null; + private List<T> list = null; + private boolean containsClosest = false; + private int total = 0; + + /** + * Create a Partition for holding elements between the two argument Date + * objects. + * @param start Date representing the start of elements held in this + * Partition, inclusive. + * @param end Date representing the end of elements held in this Partition, + * exclusive. + */ + public Partition(Date start, Date end) { + this.start = start; + this.end = new Date(end.getTime()-1); + list = new ArrayList<T>(); + total = 0; + } + + /** + * Checks if a date is within this partition + * @param d Date to check + * @return boolean true if d is >= start, and < end + */ + public boolean containsDate(Date d) { + return (start.compareTo(d) <= 0) && + (end.compareTo(d) > 0); + } + + /** + * @return the start Date for this Partition. + */ + public Date getStart() { + return start; + } + + /** + * @return the end Date for this Partition. + */ + public Date getEnd() { + return end; + } + + /** + * @return number of elements held in this Partition. + */ + public int count() { + return list.size(); + } + + /** + * @param o element to be added to this partition. + */ + public void add(T o) { + list.add(o); + } + + /** + * @return an Iterator of elements held in this Partition. + */ + public Iterator<T> iterator() { + return list.iterator(); + } + + /** + * @return a List of the elements held in this Partition. + */ + public List<T> list() { + return list; + } + + /** + * @return the containsClosest + */ + public boolean isContainsClosest() { + return containsClosest; + } + + /** + * @param containsClosest the containsClosest to set + */ + public void setContainsClosest(boolean containsClosest) { + this.containsClosest = containsClosest; + } + + /** + * Add and int to the Total count for this partition. + * @param numberToAdd number to add + */ + public void addTotal(int numberToAdd) { + total += numberToAdd; + } + /** + * @return the Total count for this partition. + */ + public int getTotal() { + return total; + } +} Property changes on: trunk/archive-access/projects/wayback/wayback-core/src/main/java/org/archive/wayback/util/partition/Partition.java ___________________________________________________________________ Added: svn:keywords + Author Date Revision Id Added: trunk/archive-access/projects/wayback/wayback-core/src/main/java/org/archive/wayback/util/partition/PartitionSize.java =================================================================== --- trunk/archive-access/projects/wayback/wayback-core/src/main/java/org/archive/wayback/util/partition/PartitionSize.java (rev 0) +++ trunk/archive-access/projects/wayback/wayback-core/src/main/java/org/archive/wayback/util/partition/PartitionSize.java 2010-04-10 02:41:32 UTC (rev 3032) @@ -0,0 +1,137 @@ +package org.archive.wayback.util.partition; + +import java.util.Calendar; + +/** + * A class which simplifies partitioning Dates based on human logical time + * intervals: Day, Week, TwoYear. + * + * Implementing classes provide methods to align Calendars at the start of the + * nearest Day, Month, Week, etc. + * + * In addition, implementors provide methods to create new Calendars based on + * their specific alignment size. + * + * @author brad + * + */ +public interface PartitionSize { + + /** + * number of milliseconds in a second.. + */ + public final static long MS_IN_SEC = 1000; + /** + * seconds in a non-leap-second hour + */ + public final static long SEC_IN_HOUR = 3600; + /** + * hours in a day: 24 + */ + public final static long HOUR_IN_DAY = 24; + /** + * days in a 7 day week... what color was his white horse? + */ + public final static long DAY_IN_WEEK = 7; + /** + * approximate days in one month, that is, 30 days + */ + public final static long DAY_IN_MONTH = 30; + /** + * days in one year, assuming a non-leap year + */ + public final static long DAY_IN_YEAR = 365; + + /** + * milliseconds in 1 hour (approximate: no leap second accounted for) + */ + public final static long MS_IN_HOUR = MS_IN_SEC * SEC_IN_HOUR; + /** + * milliseconds in 1 day (approximate: no leap second accounted for) + */ + public final static long MS_IN_DAY = MS_IN_HOUR * HOUR_IN_DAY; + /** + * milliseconds in 7 days (approximate: no leap second accounted for) + */ + public final static long MS_IN_WEEK = MS_IN_DAY * DAY_IN_WEEK; + /** + * milliseconds in one month (approximate: no leap day/sec accounted for, + * and assumes 30 days in a month) + */ + public final static long MS_IN_MONTH = MS_IN_DAY * DAY_IN_MONTH; + /** + * milliseconds in two months (approximate: no leap day/sec accounted for, + * and assumes 30 day months) + */ + public final static long MS_IN_TWO_MONTH = MS_IN_MONTH * 2; + /** + * milliseconds in one year (approximate: no leap day/sec accounted for) + */ + public final static long MS_IN_YEAR = MS_IN_DAY * DAY_IN_YEAR; + /** + * milliseconds in two years (approximate: no leap day/sec accounted for) + */ + public final static long MS_IN_TWO_YEAR = MS_IN_YEAR * 2; + + /** + * + */ + public final static String HOUR_NAME = "hour"; + /** + * + */ + public final static String DAY_NAME = "day"; + /** + * + */ + public final static String WEEK_NAME = "week"; + /** + * + */ + public final static String MONTH_NAME = "month"; + /** + * + */ + public final static String TWO_MONTH_NAME = "twomonth"; + /** + * + */ + public final static String YEAR_NAME = "year"; + /** + * + */ + public final static String TWO_YEAR_NAME = "twoyear"; + + /** + * Align the calendar argument to the start of the interval covered by + * this size. Calling this method on a DayPartitionSize will align the + * Calendar to the beginning of the Day in which the Calendar's Date object + * falls within. + * @param in Calendar object which has internal Date set + */ + public void alignStart(Calendar in); + + /** + * Create a new Calendar object, aligned relative to the Calendar argument, + * either forward or backward some number of partitions. + * @param start the returned Calendar will be aligned one day, week, month, + * etc. ahead or behind of this Calendar argument. + * @param offset the relative distance to move the returned calendar + * relative to the argument Calendar. + * @return a new Calendar aligned relative to the start Calendar. + */ + public Calendar increment(Calendar start, int offset); + + /** + * @return the estimated number of milliseconds covered by this + * PartitionSize. Note that this is estimated because of different number of + * days in a month, leap days, leap seconds, etc. + */ + public long intervalMS(); + + /** + * @return the name of this PartitionSize. Likely useful for localized + * lookup of human readable text from a properties file. + */ + public String name(); +} Property changes on: trunk/archive-access/projects/wayback/wayback-core/src/main/java/org/archive/wayback/util/partition/PartitionSize.java ___________________________________________________________________ Added: svn:keywords + Author Date Revision Id Added: trunk/archive-access/projects/wayback/wayback-core/src/main/java/org/archive/wayback/util/partition/Partitioner.java =================================================================== --- trunk/archive-access/projects/wayback/wayback-core/src/main/java/org/archive/wayback/util/partition/Partitioner.java (rev 0) +++ trunk/archive-access/projects/wayback/wayback-core/src/main/java/org/archive/wayback/util/partition/Partitioner.java 2010-04-10 02:41:32 UTC (rev 3032) @@ -0,0 +1,313 @@ +package org.archive.wayback.util.partition; + +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.Calendar; +import java.util.Date; +import java.util.Iterator; +import java.util.List; +import java.util.TimeZone; + +import org.apache.log4j.Logger; +import org.archive.wayback.util.partition.size.DayPartitionSize; +import org.archive.wayback.util.partition.size.HourPartitionSize; +import org.archive.wayback.util.partition.size.MonthPartitionSize; +import org.archive.wayback.util.partition.size.TwoMonthPartitionSize; +import org.archive.wayback.util.partition.size.TwoYearPartitionSize; +import org.archive.wayback.util.partition.size.WeekPartitionSize; +import org.archive.wayback.util.partition.size.YearPartitionSize; + +/** + * Class which divides a set of date-related objects into sub-sets by time + * ranges. + * + * This class provides methods for: + * + * 1) determining the smallest PartitionSize that can be used to cover a time + * range, using at most a set number of partitions + * 2) creating a List of Partition objects covering a span of time, each having + * a specified size + * 3) efficiently populating an iterator of date-related objects into List of + * Partition objects + * + * @author brad + * + * @param <T> generic class type to use with this Partitioner + */ +public class Partitioner<T> { + + private static final TimeZone TZ_UTC = TimeZone.getTimeZone("UTC"); + private static final Logger LOGGER = Logger.getLogger( + Partitioner.class.getName()); + + private ElementPartitionMap<T> map = null; + + /** + * PartitionSize based on Hour intervals + */ + public static PartitionSize hourSize = new HourPartitionSize(); + /** + * PartitionSize based on Day intervals + */ + public static PartitionSize daySize = new DayPartitionSize(); + /** + * PartitionSize based on Week intervals + */ + public static PartitionSize weekSize = new WeekPartitionSize(); + /** + * PartitionSize based on Month intervals + */ + public static PartitionSize monthSize = new MonthPartitionSize(); + /** + * PartitionSize based on Two Month intervals + */ + public static PartitionSize twoMonthSize = new TwoMonthPartitionSize(); + /** + * PartitionSize based on Year intervals + */ + public static PartitionSize yearSize = new YearPartitionSize(); + /** + * PartitionSize based on Two Year intervals + */ + public static PartitionSize twoYearSize = new TwoYearPartitionSize(); + + private static PartitionSize[] sizes = { + hourSize, + daySize, + weekSize, + monthSize, + twoMonthSize, + yearSize, + twoYearSize + }; + + /** + * @param map that converts from the Generic type used in this instance + * to a Date, and adds a Generic type used to a Partition + */ + public Partitioner(ElementPartitionMap<T> map) { + this.map = map; + } + /** + * Get a PartitionSize object by it's name + * @param name of the PartitionSize + * @return PartitionSize matching the name, or a TwoYearPartionSize if name + * is unknown + */ + public static PartitionSize getSize(String name) { + for(PartitionSize pa : sizes) { + if(pa.name().equals(name)) { + return pa; + } + } + return twoYearSize; + } + + /** + * Attempt to find the smallest PartitionSize implementation which, spanning + * the range first and last specified, produces at most maxP partitions. + * @param first Date of beginning of time range + * @param last Date of end of time range + * @param maxP maximum number of Partitions to use + * @return a PartitionSize object which will divide the range into at most + * maxP Partitions + */ + public PartitionSize getSize(Date first, Date last, int maxP) { + long diffMS = last.getTime() - first.getTime(); + for(PartitionSize pa : sizes) { + long maxMS = maxP * pa.intervalMS(); + if(maxMS > diffMS) { + return pa; + } + } + return twoYearSize; + } + + private void logDates(String message, Date date1, Date date2) { + SimpleDateFormat f = new SimpleDateFormat("H:mm:ss:SSS MMM d, yyyy"); + f.setTimeZone(TZ_UTC); + String pd1 = f.format(date1); + String pd2 = f.format(date2); + LOGGER.info(message + ":" + pd1 + " - " + pd2); + } + + /** + * Create a List of Partition objects of the specified size, which span the + * date range specified. + * + * @param size of Partitions to create + * @param start Date of beginning of time range to cover + * @param end Date of end of time range to cover + * @return List of Partitions spanning start and end, sized size, in date- + * ascending order. + */ + public List<Partition<T>> getRange(PartitionSize size, Date start, + Date end) { +// logDates("Constructing partitions Size(" + size.name() + ")",start,end); +// Date origStart = new Date(start.getTime()); + List<Partition<T>> partitions = new ArrayList<Partition<T>>(); + Calendar cStart = Calendar.getInstance(TZ_UTC); + cStart.setTime(start); + size.alignStart(cStart); +// logDates("AlignedStart("+size.name()+")",origStart,cStart.getTime()); + Calendar cEnd = size.increment(cStart, 1); +// logDates("AlignedEnd("+size.name()+")",cStart.getTime(),cEnd.getTime()); + while(cStart.getTime().compareTo(end) < 0) { + partitions.add(new Partition<T>(cStart.getTime(), cEnd.getTime())); + cStart = cEnd; + cEnd = size.increment(cStart, 1); +// logDates("Incremented("+size.name()+")", +// cStart.getTime(),cEnd.getTime()); + } + return partitions; + } + + /** + * Add elements from itr into the appropriate partitions. Assumes that + * all elements fit in one of the argument Partitions, that the partitions + * are in ascending order by time, and that elements returned from the + * Iterator are in ascending time order. + * + * @param partitions to populate with objects + * @param itr ascending Iterator of objects to place into the partitions + */ + public void populate(List<Partition<T>> partitions, + Iterator<T> itr) { + int idx = 0; + int size = partitions.size(); + T element = null; + while(idx < size) { + Partition<T> partition = partitions.get(idx); + if(element == null) { + if(itr.hasNext()) { + element = itr.next(); + } else { + // all done + break; + } + } + // will current result fit in the current partition? + while(partition.containsDate(map.elementToDate(element))) { + map.addElementToPartition(element, partition); + element = null; + if(itr.hasNext()) { + element = itr.next(); + } else { + break; + } + } + idx++; + } + if(itr.hasNext()) { + // eew... Likely bad usage. is this an error? + LOGGER.warn("Not all elements fit in partitions!"); + } + } + + /** + * Debugging method + * @param partitions to dump + */ + public void dumpPartitions(List<Partition<T>> partitions) { + int i = 0; + for(Partition<T> partition : partitions) { + i++; + logDates("Partition("+i+")", + partition.getStart(), partition.getEnd()); + } + } + + /* + * + * SOME UNFINISHED/UNTESTED CODE WHICH MAY BE OF INTEREST IN THE FUTURE + * FOLLOWS. NONE IS USED FOR NOW: + * + */ + +// /** +// * Create a List of Partitions centered at center, extending back in time +// * to start, and forward to end. If more than count partitions are required, +// * then the edge partitions will be grown until the range is extended to +// * start and end, with the edge partitions being non-standard size. +// * +// * @param center +// * @param start +// * @param end +// * @param count +// * @return +// */ +// public List<Partition<T>> getCentered(PartitionSize size, Date center, +// Date start, Date end, int count) { +// +// List<Partition<T>> partitions = new ArrayList<Partition<T>>(); +// Calendar cStart = Calendar.getInstance(TimeZone.getTimeZone("GMT")); +// cStart.setTime(center); +// size.alignStart(cStart); +// Calendar cEnd = size.increment(cStart, 1); +// +// partitions.add(new Partition<T>(cStart.getTime(),cEnd.getTime())); +// +// int numSides = (count - 1) / 2; +// // first add those backwards: +// Partition<T> cur = null; +// for(int i=1; i <= numSides; i++) { +// cEnd = cStart; +// cStart = size.increment(cStart, -1); +// Date curStart = cStart.getTime(); +// if(i == numSides) { +// // first partition, maybe make longer: +// if(curStart.after(start)) { +// curStart = new Date(start.getTime() - 1000); +// } +// } +// cur = new Partition<T>(curStart, cEnd.getTime()); +// partitions.add(0,cur); +// } +// +// // re-align center, and increment: +// cStart.setTime(center); +// size.alignStart(cStart); +// cStart = size.increment(cStart, 1); +// cEnd = size.increment(cStart, 1); +// +// for(int i=1; i <= numSides; i++) { +// Date curEnd = cEnd.getTime(); +// if(i == numSides) { +// // last partition, maybe make longer: +// if(curEnd.before(end)) { +// // end is exclusive, so make 1 MS more: +// curEnd = end; +// } +// } +// cur = new Partition<T>(cStart.getTime(),curEnd); +// partitions.add(cur); +// cStart = cEnd; +// cEnd = size.increment(cStart, 1); +// } +// return partitions; +// } + +// public List<Partition<T>> partitionRange(Date start, Date end, String name) { + // +// PartitionSize size = getSize(name); +// return getRange(size, start, end); +// } +// public List<Partition<T>> partitionCentered(Date center, Date start, +// Date end, int count, String name) { + // +// PartitionSize size = getSize(name); +// return getCentered(size, center, start, end, count); +// } +// public List<Partition<T>> partitionRange(Date start, Date end, int max) { + // +// PartitionSize size = getSize(start, end, max); +// return getRange(size, start, end); +// } +// public List<Partition<T>> partitionCentered(Date center, Date start, +// Date end, int count) { + // +// PartitionSize size = getSize(start,end,count); +// return getCentered(size, center, start, end, count); +// } + +} Property changes on: trunk/archive-access/projects/wayback/wayback-core/src/main/java/org/archive/wayback/util/partition/Partitioner.java ___________________________________________________________________ Added: svn:keywords + Author Date Revision Id Added: trunk/archive-access/projects/wayback/wayback-core/src/main/java/org/archive/wayback/util/partition/size/DayPartitionSize.java =================================================================== --- trunk/archive-access/projects/wayback/wayback-core/src/main/java/org/archive/wayback/util/partition/size/DayPartitionSize.java (rev 0) +++ trunk/archive-access/projects/wayback/wayback-core/src/main/java/org/archive/wayback/util/partition/size/DayPartitionSize.java 2010-04-10 02:41:32 UTC (rev 3032) @@ -0,0 +1,37 @@ +package org.archive.wayback.util.partition.size; + +import java.util.Calendar; +import java.util.TimeZone; + +import org.archive.wayback.util.partition.PartitionSize; + +/** + * PartitionSize which aligns on one Day partitions + * @author brad + * + */ +public class DayPartitionSize implements PartitionSize { + + public String name() { + return PartitionSize.DAY_NAME; + } + + public long intervalMS() { + return MS_IN_DAY; + } + + public void alignStart(Calendar in) { + in.set(Calendar.HOUR_OF_DAY,0); + in.set(Calendar.MINUTE,0); + in.set(Calendar.SECOND,0); + in.set(Calendar.MILLISECOND, 0); + } + + public Calendar increment(Calendar start, int offset) { + + Calendar end = Calendar.getInstance(TimeZone.getTimeZone("GMT")); + end.setTime(start.getTime()); + end.add(Calendar.DAY_OF_YEAR,1 * offset); + return end; + } +} Property changes on: trunk/archive-access/projects/wayback/wayback-core/src/main/java/org/archive/wayback/util/partition/size/DayPartitionSize.java ___________________________________________________________________ Added: svn:keywords + Author Date Revision Id Added: trunk/archive-access/projects/wayback/wayback-core/src/main/java/org/archive/wayback/util/partition/size/HourPartitionSize.java =================================================================== --- trunk/archive-access/projects/wayback/wayback-core/src/main/java/org/archive/wayback/util/partition/size/HourPartitionSize.java (rev 0) +++ trunk/archive-access/projects/wayback/wayback-core/src/main/java/org/archive/wayback/util/partition/size/HourPartitionSize.java 2010-04-10 02:41:32 UTC (rev 3032) @@ -0,0 +1,36 @@ +package org.archive.wayback.util.partition.size; + +import java.util.Calendar; +import java.util.TimeZone; + +import org.archive.wayback.util.partition.PartitionSize; + +/** + * PartitionSize which aligns on one Hour partitions + * @author brad + * + */ +public class HourPartitionSize implements PartitionSize { + + public String name() { + return PartitionSize.HOUR_NAME; + } + + public long intervalMS() { + return MS_IN_HOUR; + } + + public void alignStart(Calendar in) { + in.set(Calendar.MINUTE,0); + in.set(Calendar.SECOND,0); + in.set(Calendar.MILLISECOND, 0); + } + + public Calendar increment(Calendar start, int offset) { + + Calendar end = Calendar.getInstance(TimeZone.getTimeZone("GMT")); + end.setTime(start.getTime()); + end.add(Calendar.HOUR_OF_DAY,1 * offset); + return end; + } +} Property changes on: trunk/archive-access/projects/wayback/wayback-core/src/main/java/org/archive/wayback/util/partition/size/HourPartitionSize.java ___________________________________________________________________ Added: svn:keywords + Author Date Revision Id Added: trunk/archive-access/projects/wayback/wayback-core/src/main/java/org/archive/wayback/util/partition/size/MonthPartitionSize.java =================================================================== --- trunk/archive-access/projects/wayback/wayback-core/src/main/java/org/archive/wayback/util/partition/size/MonthPartitionSize.java (rev 0) +++ trunk/archive-access/projects/wayback/wayback-core/src/main/java/org/archive/wayback/util/partition/size/MonthPartitionSize.java 2010-04-10 02:41:32 UTC (rev 3032) @@ -0,0 +1,37 @@ +package org.archive.wayback.util.partition.size; + +import java.util.Calendar; +import java.util.TimeZone; + +import org.archive.wayback.util.partition.PartitionSize; + +/** + * PartitionSize which aligns on one Month partitions + * @author brad + * + */ +public class MonthPartitionSize implements PartitionSize { + + public String name() { + return PartitionSize.MONTH_NAME; + } + + public long intervalMS() { + return MS_IN_MONTH; + } + + public void alignStart(Calendar in) { + in.set(Calendar.DAY_OF_MONTH,1); + in.set(Calendar.HOUR_OF_DAY,0); + in.set(Calendar.MINUTE,0); + in.set(Calendar.SECOND,0); + in.set(Calendar.MILLISECOND, 0); + } + + public Calendar increment(Calendar start, int offset) { + Calendar end = Calendar.getInstance(TimeZone.getTimeZone("GMT")); + end.setTime(start.getTime()); + end.add(Calendar.MONTH,1 * offset); + return end; + } +} Property changes on: trunk/archive-access/projects/wayback/wayback-core/src/main/java/org/archive/wayback/util/partition/size/MonthPartitionSize.java ___________________________________________________________________ Added: svn:keywords + Author Date Revision Id Added: trunk/archive-access/projects/wayback/wayback-core/src/main/java/org/archive/wayback/util/partition/size/TwoMonthPartitionSize.java =================================================================== --- trunk/archive-access/projects/wayback/wayback-core/src/main/java/org/archive/wayback/util/partition/size/TwoMonthPartitionSize.java (rev 0) +++ trunk/archive-access/projects/wayback/wayback-core/src/main/java/org/archive/wayback/util/partition/size/TwoMonthPartitionSize.java 2010-04-10 02:41:32 UTC (rev 3032) @@ -0,0 +1,38 @@ +package org.archive.wayback.util.partition.size; + +import java.util.Calendar; +import java.util.TimeZone; + +import org.archive.wayback.util.partition.PartitionSize; + +/** + * PartitionSize which aligns on two Month partitions + * @author brad + * + */ +public class TwoMonthPartitionSize implements PartitionSize { + + public String name() { + return PartitionSize.TWO_MONTH_NAME; + } + + public long intervalMS() { + return MS_IN_TWO_MONTH; + } + + public void alignStart(Calendar in) { + in.set(Calendar.DAY_OF_MONTH,1); + in.set(Calendar.HOUR_OF_DAY,0); + in.set(Calendar.MINUTE,0); + in.set(Calendar.SECOND,0); + in.set(Calendar.MILLISECOND, 0); + } + + public Calendar increment(Calendar start, int offset) { + + Calendar end = Calendar.getInstance(TimeZone.getTimeZone("GMT")); + end.setTime(start.getTime()); + end.add(Calendar.MONTH,2 * offset); + return end; + } +} Property changes on: trunk/archive-access/projects/wayback/wayback-core/src/main/java/org/archive/wayback/util/partition/size/TwoMonthPartitionSize.java ___________________________________________________________________ Added: svn:keywords + Author Date Revision Id Added: trunk/archive-access/projects/wayback/wayback-core/src/main/java/org/archive/wayback/util/partition/size/TwoYearPartitionSize.java =================================================================== --- trunk/archive-access/projects/wayback/wayback-core/src/main/java/org/archive/wayback/util/partition/size/TwoYearPartitionSize.java (rev 0) +++ trunk/archive-access/projects/wayback/wayback-core/src/main/java/org/archive/wayback/util/partition/size/TwoYearPartitionSize.java 2010-04-10 02:41:32 UTC (rev 3032) @@ -0,0 +1,38 @@ +package org.archive.wayback.util.partition.size; + +import java.util.Calendar; +import java.util.TimeZone; + +import org.archive.wayback.util.partition.PartitionSize; + +/** + * PartitionSize which aligns on two Year partitions + * @author brad + * + */ +public class TwoYearPartitionSize implements PartitionSize { + + public String name() { + return PartitionSize.TWO_YEAR_NAME; + } + + public long intervalMS() { + return MS_IN_TWO_YEAR; + } + + public void alignStart(Calendar in) { + in.set(Calendar.DAY_OF_YEAR,1); + in.set(Calendar.HOUR_OF_DAY,0); + in.set(Calendar.MINUTE,0); + in.set(Calendar.SECOND,0); + in.set(Calendar.MILLISECOND, 0); + } + + public Calendar increment(Calendar start, int offset) { + + Calendar end = Calendar.getInstance(TimeZone.getTimeZone("GMT")); + end.setTime(start.getTime()); + end.add(Calendar.YEAR,2 * offset); + return end; + } +} Property changes on: trunk/archive-access/projects/wayback/wayback-core/src/main/java/org/archive/wayback/util/partition/size/TwoYearPartitionSize.java ___________________________________________________________________ Added: svn:keywords + Author Date Revision Id Added: trunk/archive-access/projects/wayback/wayback-core/src/main/java/org/archive/wayback/util/partition/size/WeekPartitionSize.java =================================================================== --- trunk/archive-access/projects/wayback/wayback-core/src/main/java/org/archive/wayback/util/partition/size/WeekPartitionSize.java (rev 0) +++ trunk/archive-access/projects/wayback/wayback-core/src/main/java/org/archive/wayback/util/partition/size/WeekPartitionSize.java 2010-04-10 02:41:32 UTC (rev 3032) @@ -0,0 +1,36 @@ +package org.archive.wayback.util.partition.size; + +import java.util.Calendar; +import java.util.TimeZone; + +import org.archive.wayback.util.partition.PartitionSize; + +/** + * PartitionSize which aligns on one Week partitions + * @author brad + * + */ +public class WeekPartitionSize implements PartitionSize { + + public String name() { + return PartitionSize.WEEK_NAME; + } + + public long intervalMS() { + return MS_IN_WEEK; + } + + public void alignStart(Calendar in) { + in.set(Calendar.HOUR_OF_DAY,1); + in.set(Calendar.MINUTE,1); + in.set(Calendar.SECOND,1); + in.set(Calendar.MILLISECOND, 0); + } + + public Calendar increment(Calendar start, int offset) { + Calendar end = Calendar.getInstance(TimeZone.getTimeZone("GMT")); + end.setTime(start.getTime()); + end.add(Calendar.DAY_OF_YEAR,7 * offset); + return end; + } +} Property changes on: trunk/archive-access/projects/wayback/wayback-core/src/main/java/org/archive/wayback/util/partition/size/WeekPartitionSize.java ___________________________________________________________________ Added: svn:keywords + Author Date Revision Id Added: trunk/archive-access/projects/wayback/wayback-core/src/main/java/org/archive/wayback/util/partition/size/YearPartitionSize.java =================================================================== --- trunk/archive-access/projects/wayback/wayback-core/src/main/java/org/archive/wayback/util/partition/size/YearPartitionSize.java (rev 0) +++ trunk/archive-access/projects/wayback/wayback-core/src/main/java/org/archive/wayback/util/partition/size/YearPartitionSize.java 2010-04-10 02:41:32 UTC (rev 3032) @@ -0,0 +1,37 @@ +package org.archive.wayback.util.partition.size; + +import java.util.Calendar; +import java.util.TimeZone; + +import org.archive.wayback.util.partition.PartitionSize; + +/** + * PartitionSize which aligns on one Year partitions + * @author brad + * + */ +public class YearPartitionSize implements PartitionSize { + + public String name() { + return YEAR_NAME; + } + + public long intervalMS() { + return MS_IN_YEAR; + } + + public void alignStart(Calendar in) { + in.set(Calendar.DAY_OF_YEAR,1); + in.set(Calendar.HOUR_OF_DAY,0); + in.set(Calendar.MINUTE,0); + in.set(Calendar.SECOND,0); + in.set(Calendar.MILLISECOND, 0); + } + + public Calendar increment(Calendar start, int offset) { + Calendar end = Calendar.getInstance(TimeZone.getTimeZone("GMT")); + end.setTime(start.getTime()); + end.add(Calendar.YEAR,1 * offset); + return end; + } +} Property changes on: trunk/archive-access/projects/wayback/wayback-core/src/main/java/org/archive/wayback/util/partition/size/YearPartitionSize.java ___________________________________________________________________ Added: svn:keywords + Author Date Revision Id This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <bra...@us...> - 2010-04-24 00:17:50
|
Revision: 3055 http://archive-access.svn.sourceforge.net/archive-access/?rev=3055&view=rev Author: bradtofel Date: 2010-04-24 00:17:43 +0000 (Sat, 24 Apr 2010) Log Message: ----------- INITIAL REV: Library to generate simple bar graphs, intended to be easily encoded as an opaque string and used as an IMG src in an HTML page. Added Paths: ----------- trunk/archive-access/projects/wayback/wayback-core/src/main/java/org/archive/wayback/util/graph/ trunk/archive-access/projects/wayback/wayback-core/src/main/java/org/archive/wayback/util/graph/Graph.java trunk/archive-access/projects/wayback/wayback-core/src/main/java/org/archive/wayback/util/graph/GraphConfiguration.java trunk/archive-access/projects/wayback/wayback-core/src/main/java/org/archive/wayback/util/graph/GraphElement.java trunk/archive-access/projects/wayback/wayback-core/src/main/java/org/archive/wayback/util/graph/GraphEncoder.java trunk/archive-access/projects/wayback/wayback-core/src/main/java/org/archive/wayback/util/graph/GraphEncodingException.java trunk/archive-access/projects/wayback/wayback-core/src/main/java/org/archive/wayback/util/graph/GraphRenderer.java trunk/archive-access/projects/wayback/wayback-core/src/main/java/org/archive/wayback/util/graph/RectangularGraphElement.java trunk/archive-access/projects/wayback/wayback-core/src/main/java/org/archive/wayback/util/graph/RegionData.java trunk/archive-access/projects/wayback/wayback-core/src/main/java/org/archive/wayback/util/graph/RegionGraphElement.java trunk/archive-access/projects/wayback/wayback-core/src/main/java/org/archive/wayback/util/graph/ValueGraphElement.java trunk/archive-access/projects/wayback/wayback-core/src/main/java/org/archive/wayback/util/graph/ValueGraphElements.java Added: trunk/archive-access/projects/wayback/wayback-core/src/main/java/org/archive/wayback/util/graph/Graph.java =================================================================== --- trunk/archive-access/projects/wayback/wayback-core/src/main/java/org/archive/wayback/util/graph/Graph.java (rev 0) +++ trunk/archive-access/projects/wayback/wayback-core/src/main/java/org/archive/wayback/util/graph/Graph.java 2010-04-24 00:17:43 UTC (rev 3055) @@ -0,0 +1,116 @@ +/* Graph + * + * $Id$: + * + * Created on Apr 9, 2010. + * + * Copyright (C) 2006 Internet Archive. + * + * This file is part of Wayback. + * + * Wayback is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * any later version. + * + * Wayback is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser Public License for more details. + * + * You should have received a copy of the GNU Lesser Public License + * along with Wayback; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +package org.archive.wayback.util.graph; + +import java.awt.Graphics2D; + +/** + * @author brad + * + */ +public class Graph extends RectangularGraphElement { + + private RegionGraphElement regions[] = null; + private GraphConfiguration config = null; + + /** + * @param width the width of the graph + * @param height the height of the graph + * @param data the values to draw in the graph + * @param config the configuration to use when drawing the graph + */ + public Graph(int width, int height, RegionData data[], + GraphConfiguration config) { + super(0,0,width,height); + this.config = config; + + int totalValues = 0; + int maxValue = -1; + for(RegionData datum : data) { + int array[] = datum.getValues(); + totalValues += array.length; + for(int d : array) { + if(d > maxValue) { + maxValue = d; + } + } + } + int valuesSoFar = 0; + regions = new RegionGraphElement[data.length]; + for(int i = 0; i < data.length; i++) { + int vCount = data[i].getValues().length; + + int x = Graph.xlateX(width, totalValues, valuesSoFar); + int w = Graph.xlateX(width, totalValues, valuesSoFar + vCount) - x; + data[i].setMaxValue(maxValue); + regions[i] = new RegionGraphElement(x,0,w,height,data[i],config); + valuesSoFar += vCount; + } + } + + /** + * @return the RegionGraphElements for the graph + */ + public RegionGraphElement[] getRegions() { + return regions; + } + + public void draw(Graphics2D g2d) { + + // set up rendering hints: + config.setRenderingHints(g2d); + + // draw background: + g2d.setColor(config.backgroundColor); + g2d.fillRect(1, 1, width - 2, height - 2); + + for(RegionGraphElement region : regions) { + region.draw(g2d); + } + + // draw line below values: + int labelHeight = config.regionFontSize + (config.fontPadY * 2); + int valuesHeight = (height - labelHeight) + 1; + + g2d.setColor(config.regionBorderColor); + g2d.setStroke(config.regionBorderStroke); + g2d.drawLine(1, valuesHeight, width - 2, valuesHeight); + } + + static int xlateX(int w, int c, int i) { + if(i == 0) { + return 0; + } else if(i == c) { + return w; + } + float width = w; + float count = c; + float idx = i; + float x = (idx/count) * width; + return (int) x; + } + +} Property changes on: trunk/archive-access/projects/wayback/wayback-core/src/main/java/org/archive/wayback/util/graph/Graph.java ___________________________________________________________________ Added: svn:keywords + Author Date Revision Id Added: trunk/archive-access/projects/wayback/wayback-core/src/main/java/org/archive/wayback/util/graph/GraphConfiguration.java =================================================================== --- trunk/archive-access/projects/wayback/wayback-core/src/main/java/org/archive/wayback/util/graph/GraphConfiguration.java (rev 0) +++ trunk/archive-access/projects/wayback/wayback-core/src/main/java/org/archive/wayback/util/graph/GraphConfiguration.java 2010-04-24 00:17:43 UTC (rev 3055) @@ -0,0 +1,128 @@ +/* GraphConfiguration + * + * $Id$: + * + * Created on Apr 9, 2010. + * + * Copyright (C) 2006 Internet Archive. + * + * This file is part of Wayback. + * + * Wayback is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * any later version. + * + * Wayback is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser Public License for more details. + * + * You should have received a copy of the GNU Lesser Public License + * along with Wayback; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +package org.archive.wayback.util.graph; + +import java.awt.BasicStroke; +import java.awt.Color; +import java.awt.Font; +import java.awt.Graphics2D; +import java.awt.RenderingHints; +import java.awt.Stroke; + +/** + * @author brad + * + */ +public class GraphConfiguration { + final static float dash1[] = {3.0f}; + final static BasicStroke dashed = new BasicStroke(1.0f, + BasicStroke.CAP_BUTT, + BasicStroke.JOIN_MITER, + 3.0f, dash1, 0.0f); + + /** + * Main background color for graphs + */ + public Color backgroundColor = Color.white; + + /** + * font size for Year/Month labels + */ + public int regionFontSize = 9; + /** + * font name for Year/Month labels + */ + public String regionFontName = Font.SANS_SERIF; + /** + * font style for Year/Month labels + */ + public int regionFontStyle = Font.PLAIN; + /** + * font Color for Year/Month labels + */ + public Color regionLabelColor = Color.black; + /** + * top/bottom font padding for Year/Month labels + */ + public int fontPadY = 2; + /** + * left font padding for Year/Month labels + */ + public int fontPadX = 4; + + /** + * color for Year/Month border lines + */ + public Color regionBorderColor = Color.darkGray; + /** + * Stroke for Year/Month border lines + */ + public Stroke regionBorderStroke = dashed; + + /** + * Background color for active/selected Year/Month + */ + public Color regionHighlightColor = Color.lightGray; + + /** + * color for non-active/selected graph values + */ + public Color valueColor = Color.blue; + /** + * color for active/selected graph values + */ + public Color valueHighlightColor = Color.green; + + /** + * Minimum pixel height for non-zero graph values + */ + public int valueMinHeight = 5; + + + private Font regionLabelFont = null; + /** + * @return the current Font to use for Month/Year labels, combination of + * regionFontStyle, regionFontSize, regionFontName + */ + public Font getRegionLabelFont() { + if(regionLabelFont == null) { + regionLabelFont = new Font(regionFontName, + regionFontStyle,regionFontSize); + } + return regionLabelFont; + } + /** + * Set whatever redneringHints are needed to properly draw the graph, ie. + * AntiAliasing, etc. + * @param g2d The Graphics2D objects on which the hints should be set. + */ + public void setRenderingHints(Graphics2D g2d) { + g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, + RenderingHints.VALUE_ANTIALIAS_ON); + g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, + RenderingHints.VALUE_TEXT_ANTIALIAS_ON); + } +} Property changes on: trunk/archive-access/projects/wayback/wayback-core/src/main/java/org/archive/wayback/util/graph/GraphConfiguration.java ___________________________________________________________________ Added: svn:keywords + Author Date Revision Id Added: trunk/archive-access/projects/wayback/wayback-core/src/main/java/org/archive/wayback/util/graph/GraphElement.java =================================================================== --- trunk/archive-access/projects/wayback/wayback-core/src/main/java/org/archive/wayback/util/graph/GraphElement.java (rev 0) +++ trunk/archive-access/projects/wayback/wayback-core/src/main/java/org/archive/wayback/util/graph/GraphElement.java 2010-04-24 00:17:43 UTC (rev 3055) @@ -0,0 +1,41 @@ +/* GraphElement + * + * $Id$: + * + * Created on Apr 9, 2010. + * + * Copyright (C) 2006 Internet Archive. + * + * This file is part of Wayback. + * + * Wayback is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * any later version. + * + * Wayback is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser Public License for more details. + * + * You should have received a copy of the GNU Lesser Public License + * along with Wayback; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +package org.archive.wayback.util.graph; + +import java.awt.Graphics2D; + +/** + * @author brad + * + */ +public interface GraphElement { + /** + * Draw the element onto a Graphics2D. + * + * @param g2d the Graphics2D onto which the element should be drawn. + */ + public void draw(Graphics2D g2d); +} Property changes on: trunk/archive-access/projects/wayback/wayback-core/src/main/java/org/archive/wayback/util/graph/GraphElement.java ___________________________________________________________________ Added: svn:keywords + Author Date Revision Id Added: trunk/archive-access/projects/wayback/wayback-core/src/main/java/org/archive/wayback/util/graph/GraphEncoder.java =================================================================== --- trunk/archive-access/projects/wayback/wayback-core/src/main/java/org/archive/wayback/util/graph/GraphEncoder.java (rev 0) +++ trunk/archive-access/projects/wayback/wayback-core/src/main/java/org/archive/wayback/util/graph/GraphEncoder.java 2010-04-24 00:17:43 UTC (rev 3055) @@ -0,0 +1,172 @@ +/* GraphEncoder + * + * $Id$: + * + * Created on Apr 9, 2010. + * + * Copyright (C) 2006 Internet Archive. + * + * This file is part of Wayback. + * + * Wayback is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * any later version. + * + * Wayback is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser Public License for more details. + * + * You should have received a copy of the GNU Lesser Public License + * along with Wayback; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +package org.archive.wayback.util.graph; + +/** + * @author brad + * + */ +public class GraphEncoder { + private static String DELIM = "_"; + private static String REGION_DELIM = ":"; + + /** + * convert a String-encoded graph into a usable Graph object, using + * default GraphConfiguration + * @param encodedGraph String encoded graph, as returned by getEncoded() + * @return a Graph, ready to use + * @throws GraphEncodingException if there were problems with the encoded + * data + */ + public static Graph decode(String encodedGraph) + throws GraphEncodingException { + return decode(encodedGraph, new GraphConfiguration()); + } + /** + * convert a String-encoded graph into a usable Graph object, using + * the provided GraphConfiguration. + * @param encodedGraph String encoded graph, as returned by getEncoded() + * @param config the GraphConfiguration to use + * @return a Graph, ready to use + * @throws GraphEncodingException if there were problems with the encoded + * data + */ + public static Graph decode(String encodedGraph, GraphConfiguration config) + throws GraphEncodingException { + // encoded = "800_35_REGIONDATA_REGIONDATA_REGIONDATA_REGIONDATA_..." + String parts[] = encodedGraph.split(DELIM); + int numRegions = parts.length - 2; + if(parts.length < 1) { + throw new GraphEncodingException("No regions defined!"); + } + int width; + int height; + try { + width = Integer.parseInt(parts[0]); + } catch(NumberFormatException e) { + throw new GraphEncodingException("Bad integer width:" + parts[0]); + } + try { + height = Integer.parseInt(parts[1]); + } catch(NumberFormatException e) { + throw new GraphEncodingException("Bad integer width:" + parts[0]); + } + RegionData data[] = new RegionData[numRegions]; + for(int i = 0; i < numRegions; i++) { + // REGIONDATA = "2001:-1:0ab3f70023f902f" + // LABEL:ACTIVE_IDX:HEXDATA + String regionParts[] = parts[i + 2].split(REGION_DELIM); + if(regionParts.length != 3) { + throw new GraphEncodingException("Wrong number of parts in " + + parts[i+2]); + } + int highlightedValue = Integer.parseInt(regionParts[1]); + int values[] = decodeHex(regionParts[2]); + data[i] = new RegionData(regionParts[0], highlightedValue, values); + } + return new Graph(width, height, data, config); + } + + /** + * Convert a complete Graph into an opaque String that can later be + * re-assembled into a Graph object. Note that GraphConfiguration + * information is NOT encoded into the opaque String. + * @param g Graph to encode + * @return opaque String which can later be used with decode() + */ + public static String encode(Graph g) { + RegionGraphElement rge[] = g.getRegions(); + RegionData data[] = new RegionData[rge.length]; + for(int i = 0; i < data.length; i++) { + data[i] = rge[i].getData(); + } + return encode(g.width, g.height, data); + } + + /** + * Convert a Graph fields into an opaque String that can later be + * re-assembled into a Graph object. Note that GraphConfiguration + * information is NOT encoded into the opaque String. + * @param width of the Graph + * @param height of the Graph + * @param data array of RegionData for the graph + * @return opaque String which can later be used with decode() + */ + public static String encode(int width, int height, RegionData data[]) { + StringBuilder sb = new StringBuilder(); + sb.append(width).append(DELIM); + sb.append(height); + boolean first = false; + for(RegionData datum : data) { + if(first) { + first = false; + } else { + sb.append(DELIM); + } + sb.append(datum.getLabel()).append(REGION_DELIM); + sb.append(datum.getHighlightedValue()).append(REGION_DELIM); + sb.append(encodeHex(datum.getValues())); + } + return sb.toString(); + } + + private static String encodeHex(int values[]) { + StringBuilder sb = new StringBuilder(values.length); + for(int value : values) { + if((value > 15) || (value < 0)){ + throw new IllegalArgumentException(); + } + sb.append(Integer.toHexString(value)); + } + return sb.toString(); + } + + private static int[] decodeHex(String hexString) { + int length = hexString.length(); + int values[] = new int[length]; + for(int i = 0; i < length; i++) { + char c = hexString.charAt(i); + if(c >= '0') { + if(c <= '9') { + values[i] = c - '0'; + } else { + if(c > 'f') { + throw new IllegalArgumentException(); + } else { + if(c >= 'a') { + values[i] = c - 'W'; + } else { + throw new IllegalArgumentException(); + } + } + } + } else { + throw new IllegalArgumentException(); + } + } + return values; + } +} Property changes on: trunk/archive-access/projects/wayback/wayback-core/src/main/java/org/archive/wayback/util/graph/GraphEncoder.java ___________________________________________________________________ Added: svn:keywords + Author Date Revision Id Added: trunk/archive-access/projects/wayback/wayback-core/src/main/java/org/archive/wayback/util/graph/GraphEncodingException.java =================================================================== --- trunk/archive-access/projects/wayback/wayback-core/src/main/java/org/archive/wayback/util/graph/GraphEncodingException.java (rev 0) +++ trunk/archive-access/projects/wayback/wayback-core/src/main/java/org/archive/wayback/util/graph/GraphEncodingException.java 2010-04-24 00:17:43 UTC (rev 3055) @@ -0,0 +1,46 @@ +/* GraphEncodingException + * + * $Id$: + * + * Created on Apr 14, 2010. + * + * Copyright (C) 2006 Internet Archive. + * + * This file is part of Wayback. + * + * Wayback is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * any later version. + * + * Wayback is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser Public License for more details. + * + * You should have received a copy of the GNU Lesser Public License + * along with Wayback; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +package org.archive.wayback.util.graph; + +/** + * @author brad + * + */ +public class GraphEncodingException extends Exception { + + /** + * + */ + private static final long serialVersionUID = -998274644110299354L; + + /** + * @param string message context for the exception + */ + public GraphEncodingException(String string) { + super(string); + } + +} Property changes on: trunk/archive-access/projects/wayback/wayback-core/src/main/java/org/archive/wayback/util/graph/GraphEncodingException.java ___________________________________________________________________ Added: svn:keywords + Author Date Revision Id Added: trunk/archive-access/projects/wayback/wayback-core/src/main/java/org/archive/wayback/util/graph/GraphRenderer.java =================================================================== --- trunk/archive-access/projects/wayback/wayback-core/src/main/java/org/archive/wayback/util/graph/GraphRenderer.java (rev 0) +++ trunk/archive-access/projects/wayback/wayback-core/src/main/java/org/archive/wayback/util/graph/GraphRenderer.java 2010-04-24 00:17:43 UTC (rev 3055) @@ -0,0 +1,102 @@ +/* GraphRenderer + * + * $Id$: + * + * Created on Apr 9, 2010. + * + * Copyright (C) 2006 Internet Archive. + * + * This file is part of Wayback. + * + * Wayback is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * any later version. + * + * Wayback is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser Public License for more details. + * + * You should have received a copy of the GNU Lesser Public License + * along with Wayback; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +package org.archive.wayback.util.graph; + +import java.awt.Graphics2D; +import java.awt.Rectangle; +import java.awt.image.BufferedImage; +import java.io.IOException; +import java.io.OutputStream; + +import javax.imageio.ImageIO; + +/** + * @author brad + * + */ +public class GraphRenderer { + /** + * appropriate Content-Type HTTP header value for graph image content + * produced by render(OutputStream,Graph) + */ + public final static String RENDERED_IMAGE_MIME = "image/png"; + /** + * Create both an HTML AREA map and an HTML IMG for a graph, using provided + * href targets, and titles within the AREA map. + * @param graph Graph to draw + * @param mapName name of HTML AREA map + * @param imgUrl URL to rendered Graph, see GraphEncoder.encode() + * @param targets URL href targets for the years in the Graph + * @param titles titles for the years in the graph. + * @return HTML String for the resulting AREA and IMG + */ + public static String renderHTML(Graph graph, String mapName, String imgUrl, + String targets[], String titles[]) { + + StringBuilder sb = new StringBuilder(); + sb.append("<map name=\"").append(mapName).append("\">"); + RegionGraphElement rge[] = graph.getRegions(); + int count = rge.length; + for(int i = 0; i < count; i++) { + if(targets[i] != null) { + Rectangle r = rge[i].getBoundingRectangle(); + sb.append("<area href=\"").append(targets[i]).append("\""); + if(titles[i] != null) { + sb.append(" title=\"").append(titles[i]).append("\""); + } + sb.append(" shape=\"rect\" coords=\""); + sb.append(r.x).append(","); + sb.append(r.y).append(","); + sb.append(r.x+r.width).append(","); + sb.append(r.y+r.height).append("\" border=\"1\" />"); + } + } + sb.append("</map>"); + sb.append("<image src=\"").append(imgUrl).append("\""); + sb.append(" border=\"0\" width=\"").append(graph.width).append("\""); + sb.append(" height=\"").append(graph.height).append("\""); + sb.append(" usemap=\"#").append(mapName).append("\" />"); + + return sb.toString(); + } + + /** + * Send a PNG format byte stream for the argument Graph to the provided + * OutputStream + * @param target OutputStream to write PNG format bytes + * @param graph Graph to send to the target + * @throws IOException for usual reasons. + */ + public void render(OutputStream target, Graph graph) throws IOException { + + BufferedImage bi = + new BufferedImage(graph.width, graph.height, BufferedImage.TYPE_INT_RGB); + Graphics2D g2d = bi.createGraphics(); + graph.draw(g2d); + ImageIO.write(bi, "png", target); + } + +} Property changes on: trunk/archive-access/projects/wayback/wayback-core/src/main/java/org/archive/wayback/util/graph/GraphRenderer.java ___________________________________________________________________ Added: svn:keywords + Author Date Revision Id Added: trunk/archive-access/projects/wayback/wayback-core/src/main/java/org/archive/wayback/util/graph/RectangularGraphElement.java =================================================================== --- trunk/archive-access/projects/wayback/wayback-core/src/main/java/org/archive/wayback/util/graph/RectangularGraphElement.java (rev 0) +++ trunk/archive-access/projects/wayback/wayback-core/src/main/java/org/archive/wayback/util/graph/RectangularGraphElement.java 2010-04-24 00:17:43 UTC (rev 3055) @@ -0,0 +1,76 @@ +/* RectangularGraphElement + * + * $Id$: + * + * Created on Apr 9, 2010. + * + * Copyright (C) 2006 Internet Archive. + * + * This file is part of Wayback. + * + * Wayback is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * any later version. + * + * Wayback is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser Public License for more details. + * + * You should have received a copy of the GNU Lesser Public License + * along with Wayback; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +package org.archive.wayback.util.graph; + +import java.awt.Rectangle; + +/** + * A GraphElement which allows interrogation of it's bounding java.awt.Rectangle + * @author brad + * + */ +public abstract class RectangularGraphElement implements GraphElement { + protected int x = 0; + protected int y = 0; + protected int width = 0; + protected int height = 0; + + /** + * Construct a new RectangularGraphElement with the supplied values + * @param x the rectangles x in the global coordinate space + * @param y the rectangles y in the global coordinate space + * @param width the rectangles width + * @param height the rectangles height + */ + public RectangularGraphElement(int x, int y, int width, int height) { + this.x = x; + this.y = y; + this.width = width; + this.height = height; + } + + /** + * @return the width + */ + public int getWidth() { + return width; + } + + /** + * @return the height + */ + public int getHeight() { + return height; + } + + /** + * @return the java.awt.Rectangle which bounds this GraphElement, in the + * coordinate space of the Graph which contains it. + */ + public Rectangle getBoundingRectangle() { + return new Rectangle(x, y, width, height); + } +} Property changes on: trunk/archive-access/projects/wayback/wayback-core/src/main/java/org/archive/wayback/util/graph/RectangularGraphElement.java ___________________________________________________________________ Added: svn:keywords + Author Date Revision Id Added: trunk/archive-access/projects/wayback/wayback-core/src/main/java/org/archive/wayback/util/graph/RegionData.java =================================================================== --- trunk/archive-access/projects/wayback/wayback-core/src/main/java/org/archive/wayback/util/graph/RegionData.java (rev 0) +++ trunk/archive-access/projects/wayback/wayback-core/src/main/java/org/archive/wayback/util/graph/RegionData.java 2010-04-24 00:17:43 UTC (rev 3055) @@ -0,0 +1,95 @@ +/* RegionData + * + * $Id$: + * + * Created on Apr 14, 2010. + * + * Copyright (C) 2006 Internet Archive. + * + * This file is part of Wayback. + * + * Wayback is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * any later version. + * + * Wayback is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser Public License for more details. + * + * You should have received a copy of the GNU Lesser Public License + * along with Wayback; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +package org.archive.wayback.util.graph; + +/** + * Containing object for data associated with one region (month/year/etc) in the + * graph, including the: + * label + * highlighted value index + * int array of values to graph within this region + * the global max int value across all values in the overall graph + * @author brad + * + */ +public class RegionData { + private String label = null; + private int highlightedValue = -1; + private int values[] = null; + private int maxValue = -1; + /** + * @param label the text label to draw for this region + * @param highlightedValue the index of the value to "highlight" or -1, if + * no values should be highlighted. Note that highlighting a value in a + * region causes the entire region to get a background highlight, also + * @param values int array of raw values, each between 0 and 15. + */ + public RegionData(String label, int highlightedValue, int values[]) { + this.label = label; + this.highlightedValue = highlightedValue; + this.values = values; + } + /** + * @return the String label for this region + */ + public String getLabel() { + return label; + } + /** + * @return the index of the highlighted value in this region, or -1 if none + * are highlighted + */ + public int getHighlightedValue() { + return highlightedValue; + } + /** + * @return the raw array of values for this region + */ + public int[] getValues() { + return values; + } + /** + * @return the global graph maximum value, used for normalizing values to + * ensure the values use the entire Y axis. + */ + public int getMaxValue() { + return maxValue; + } + + /** + * @param maxValue the global graph maximum value, used for normalizing + * values to ensure the values use the entire Y axis. + */ + public void setMaxValue(int maxValue) { + this.maxValue = maxValue; + } + /** + * @return true if one of the values in this region is highlighted + */ + public boolean hasHighlightedValue() { + return (highlightedValue != -1); + } +} Property changes on: trunk/archive-access/projects/wayback/wayback-core/src/main/java/org/archive/wayback/util/graph/RegionData.java ___________________________________________________________________ Added: svn:keywords + Author Date Revision Id Added: trunk/archive-access/projects/wayback/wayback-core/src/main/java/org/archive/wayback/util/graph/RegionGraphElement.java =================================================================== --- trunk/archive-access/projects/wayback/wayback-core/src/main/java/org/archive/wayback/util/graph/RegionGraphElement.java (rev 0) +++ trunk/archive-access/projects/wayback/wayback-core/src/main/java/org/archive/wayback/util/graph/RegionGraphElement.java 2010-04-24 00:17:43 UTC (rev 3055) @@ -0,0 +1,87 @@ +/* RegionGraphElement + * + * $Id$: + * + * Created on Apr 9, 2010. + * + * Copyright (C) 2006 Internet Archive. + * + * This file is part of Wayback. + * + * Wayback is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * any later version. + * + * Wayback is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser Public License for more details. + * + * You should have received a copy of the GNU Lesser Public License + * along with Wayback; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +package org.archive.wayback.util.graph; + +import java.awt.Graphics2D; + +/** + * @author brad + * + */ +public class RegionGraphElement extends RectangularGraphElement { + private RegionData data = null; + private ValueGraphElements values = null; + private GraphConfiguration config = null; + + /** + * @param x the x coordinate for the region, in the global coordinate space + * of the containing Graph + * @param y the y coordinate for the region, in the global coordinate space + * of the containing Graph + * @param width the width of this region, in pixels + * @param height the height of this region, in pixels + * @param data the data to use for this region + * @param config the GraphConfiguration for this Graph + */ + public RegionGraphElement(int x, int y, int width, int height, + RegionData data, GraphConfiguration config) { + super(x,y,width,height); +// System.err.format("Created region (%d,%d)-(%d,%d)\n",x,y,width,height); + this.data = data; + this.config = config; + int labelHeight = config.regionFontSize + (config.fontPadY * 2); + int valuesHeight = height - labelHeight; + this.values = new ValueGraphElements(x+1, y+1, width - 1, valuesHeight, + data.getHighlightedValue(), data.getValues(), + data.getMaxValue(), config); + } + + /** + * @return the RegionData for this region + */ + public RegionData getData() { + return data; + } + + public void draw(Graphics2D g2d) { + + if(data.hasHighlightedValue()) { + g2d.setColor(config.regionHighlightColor); + g2d.fillRect(x + 1, y+1, width - 1, height-2); + } + + g2d.setColor(config.regionBorderColor); + g2d.setStroke(config.regionBorderStroke); + g2d.drawLine(x, y, x, y + height); + + int fontY = (y + height) - config.fontPadY; + + g2d.setColor(config.regionLabelColor); + g2d.setFont(config.getRegionLabelFont()); + g2d.drawString(data.getLabel(), x + config.fontPadX, fontY); + values.draw(g2d); + } +} Property changes on: trunk/archive-access/projects/wayback/wayback-core/src/main/java/org/archive/wayback/util/graph/RegionGraphElement.java ___________________________________________________________________ Added: svn:keywords + Author Date Revision Id Added: trunk/archive-access/projects/wayback/wayback-core/src/main/java/org/archive/wayback/util/graph/ValueGraphElement.java =================================================================== --- trunk/archive-access/projects/wayback/wayback-core/src/main/java/org/archive/wayback/util/graph/ValueGraphElement.java (rev 0) +++ trunk/archive-access/projects/wayback/wayback-core/src/main/java/org/archive/wayback/util/graph/ValueGraphElement.java 2010-04-24 00:17:43 UTC (rev 3055) @@ -0,0 +1,59 @@ +/* ValueGraphElement + * + * $Id$: + * + * Created on Apr 9, 2010. + * + * Copyright (C) 2006 Internet Archive. + * + * This file is part of Wayback. + * + * Wayback is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * any later version. + * + * Wayback is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser Public License for more details. + * + * You should have received a copy of the GNU Lesser Public License + * along with Wayback; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +package org.archive.wayback.util.graph; + +import java.awt.Graphics2D; + +/** + * @author brad + * + */ +public class ValueGraphElement extends RectangularGraphElement { + boolean highlighted = false; + GraphConfiguration config = null; + /** + * @param x the rectangles x in the global coordinate space + * @param y the rectangles y in the global coordinate space + * @param width the rectangles width + * @param height the rectangles height + * @param highlighted true if this value is highlighted + * @param config reference to the configuration for the graph + */ + public ValueGraphElement(int x, int y, int width, int height, + boolean highlighted, GraphConfiguration config) { + super(x, y, width, height); + + this.highlighted = highlighted; + this.config = config; + } + + + public void draw(Graphics2D g2d) { + g2d.setColor(highlighted ? + config.valueHighlightColor : config.valueColor); + g2d.fillRect(x, y, width, height); + } +} Property changes on: trunk/archive-access/projects/wayback/wayback-core/src/main/java/org/archive/wayback/util/graph/ValueGraphElement.java ___________________________________________________________________ Added: svn:keywords + Author Date Revision Id Added: trunk/archive-access/projects/wayback/wayback-core/src/main/java/org/archive/wayback/util/graph/ValueGraphElements.java =================================================================== --- trunk/archive-access/projects/wayback/wayback-core/src/main/java/org/archive/wayback/util/graph/ValueGraphElements.java (rev 0) +++ trunk/archive-access/projects/wayback/wayback-core/src/main/java/org/archive/wayback/util/graph/ValueGraphElements.java 2010-04-24 00:17:43 UTC (rev 3055) @@ -0,0 +1,109 @@ +/* ValueGraphElements + * + * $Id$: + * + * Created on Apr 9, 2010. + * + * Copyright (C) 2006 Internet Archive. + * + * This file is part of Wayback. + * + * Wayback is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * any later version. + * + * Wayback is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser Public License for more details. + * + * You should have received a copy of the GNU Lesser Public License + * along with Wayback; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +package org.archive.wayback.util.graph; + +import java.awt.Graphics2D; +import java.util.NoSuchElementException; + +/** + * @author brad + * + */ +public class ValueGraphElements extends RectangularGraphElement { + private int values[] = null; + private int highlightValue = -1; + private int maxValue = -1; + private GraphConfiguration config = null; + + /** + * @param x the rectangles x in the global coordinate space + * @param y the rectangles y in the global coordinate space + * @param width the rectangles width + * @param height the rectangles height + * @param hightlightValue the index of the value to highlight + * @param values array of int values, each must be 0-15 + * @param maxValue the global maximum value across all elements in the Graph + * @param config the configuration for the Graph + */ + public ValueGraphElements(int x, int y, int width, int height, + int hightlightValue, int values[], int maxValue, + GraphConfiguration config) { + + super(x, y, width, height); +// System.err.format("Created VGEs (%d,%d)-(%d,%d)\n",x,y,width,height); + + this.highlightValue = hightlightValue; + this.values = values; + this.config = config; + this.maxValue = maxValue; + } + + /** + * return the i'th ValueGraphElement + * @param i the index of the element to return + * @return the ValueGraphElement at index i + */ + public ValueGraphElement getElement(int i) { + if((i < 0) || (i >= values.length)) { + throw new NoSuchElementException(); + } + int minHeight = config.valueMinHeight; + + // normalize height to value between 0 and 1: + float value = ((float) values[i]) / ((float) maxValue); + float usableHeight = height - minHeight; + int valueHeight = (int) (usableHeight * value) + minHeight; + + int elX = Graph.xlateX(width, values.length, i); + int elW = Graph.xlateX(width, values.length, i+1) - elX; + int elY = height - valueHeight; + boolean hot = i == highlightValue; + return new ValueGraphElement(x + elX, y + elY, elW, valueHeight, hot, config); + } + + public void draw(Graphics2D g2d) { + for(int i = 0; i < values.length; i++) { + if(values[i] > 0) { + getElement(i).draw(g2d); + } + } + } + + /** + * @return the index of the highlighted value + */ + public int getHighlightValue() { + return highlightValue; + } + + /** + * @return the raw int values for the graph + */ + public int[] getRawValues() { + return values; + } + +} Property changes on: trunk/archive-access/projects/wayback/wayback-core/src/main/java/org/archive/wayback/util/graph/ValueGraphElements.java ___________________________________________________________________ Added: svn:keywords + Author Date Revision Id This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <bra...@us...> - 2010-04-27 22:12:38
|
Revision: 3074 http://archive-access.svn.sourceforge.net/archive-access/?rev=3074&view=rev Author: bradtofel Date: 2010-04-27 22:12:31 +0000 (Tue, 27 Apr 2010) Log Message: ----------- REFACTOR: moved all the glue functionality, which ties Wayback to a ServletContext, into this package, including: * Top-level RequestFilter Filter implementation * Spring XML parsing * setting up mapping between RequestHandler (formerly ServletRequestContext) and the RequestMapper (see below) * RequestMapper functionality ** Now provides for more flexible mapping of RequestHandler to host, port, and path ** includes registration of notification of ServletContext destruction ** includes ability to register a global RequestHandler to possibly handle incoming requests before normal mapping, and after normal mapping, should no RequestHandler match the incoming request Added Paths: ----------- trunk/archive-access/projects/wayback/wayback-core/src/main/java/org/archive/wayback/util/webapp/ trunk/archive-access/projects/wayback/wayback-core/src/main/java/org/archive/wayback/util/webapp/AbstractRequestHandler.java trunk/archive-access/projects/wayback/wayback-core/src/main/java/org/archive/wayback/util/webapp/BeanNameRegistrar.java trunk/archive-access/projects/wayback/wayback-core/src/main/java/org/archive/wayback/util/webapp/PortMapper.java trunk/archive-access/projects/wayback/wayback-core/src/main/java/org/archive/wayback/util/webapp/RequestFilter.java trunk/archive-access/projects/wayback/wayback-core/src/main/java/org/archive/wayback/util/webapp/RequestHandler.java trunk/archive-access/projects/wayback/wayback-core/src/main/java/org/archive/wayback/util/webapp/RequestHandlerContext.java trunk/archive-access/projects/wayback/wayback-core/src/main/java/org/archive/wayback/util/webapp/RequestMapper.java trunk/archive-access/projects/wayback/wayback-core/src/main/java/org/archive/wayback/util/webapp/ShutdownListener.java trunk/archive-access/projects/wayback/wayback-core/src/main/java/org/archive/wayback/util/webapp/SpringReader.java trunk/archive-access/projects/wayback/wayback-core/src/main/java/org/archive/wayback/util/webapp/StaticFileRequestHandler.java Added: trunk/archive-access/projects/wayback/wayback-core/src/main/java/org/archive/wayback/util/webapp/AbstractRequestHandler.java =================================================================== --- trunk/archive-access/projects/wayback/wayback-core/src/main/java/org/archive/wayback/util/webapp/AbstractRequestHandler.java (rev 0) +++ trunk/archive-access/projects/wayback/wayback-core/src/main/java/org/archive/wayback/util/webapp/AbstractRequestHandler.java 2010-04-27 22:12:31 UTC (rev 3074) @@ -0,0 +1,47 @@ +/** + * + */ +package org.archive.wayback.util.webapp; + +import javax.servlet.ServletContext; +import javax.servlet.http.HttpServletRequest; + + +/** + * Abstract RequestHandler implementation which performs the minimal behavior + * for self registration with a RequestMapper, requiring subclasses to implement + * only handleRequest(). + * + * @author brad + * + */ +public abstract class AbstractRequestHandler implements RequestHandler { + private String beanName = null; + private ServletContext servletContext = null; + + public void setBeanName(final String beanName) { + this.beanName = beanName; + } + public String getBeanName() { + return beanName; + } + + public void setServletContext(ServletContext servletContext) { + this.servletContext = servletContext; + } + public ServletContext getServletContext() { + return servletContext; + } + + public void registerPortListener(RequestMapper requestMapper) { + BeanNameRegistrar.registerHandler(this, requestMapper); + } + + public String translateRequestPath(HttpServletRequest httpRequest) { + return RequestMapper.getRequestContextPath(httpRequest); + } + + public String translateRequestPathQuery(HttpServletRequest httpRequest) { + return RequestMapper.getRequestContextPathQuery(httpRequest); + } +} Property changes on: trunk/archive-access/projects/wayback/wayback-core/src/main/java/org/archive/wayback/util/webapp/AbstractRequestHandler.java ___________________________________________________________________ Added: svn:keywords + Author Date Revision Id Added: trunk/archive-access/projects/wayback/wayback-core/src/main/java/org/archive/wayback/util/webapp/BeanNameRegistrar.java =================================================================== --- trunk/archive-access/projects/wayback/wayback-core/src/main/java/org/archive/wayback/util/webapp/BeanNameRegistrar.java (rev 0) +++ trunk/archive-access/projects/wayback/wayback-core/src/main/java/org/archive/wayback/util/webapp/BeanNameRegistrar.java 2010-04-27 22:12:31 UTC (rev 3074) @@ -0,0 +1,150 @@ +/** + * + */ +package org.archive.wayback.util.webapp; + +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import org.apache.log4j.Logger; + +/** + * Helper static methods to implement registration of a RequestHandler with a + * RequestMapper, based on the beanName() method. + * + * @author brad + * + */ +public class BeanNameRegistrar { + + private static final Logger LOGGER = Logger.getLogger( + BeanNameRegistrar.class.getName()); + + private static final String PORT_PATTERN_STRING = + "([0-9]+):?"; + private static final String PORT_PATH_PATTERN_STRING = + "([0-9]+):([0-9a-zA-Z_.-]+)"; + private static final String HOST_PORT_PATTERN_STRING = + "([0-9a-z_.-]+):([0-9]+):?"; + private static final String HOST_PORT_PATH_PATTERN_STRING = + "([0-9a-z_.-]+):([0-9]+):([0-9a-zA-Z_.-]+)"; + + private static final Pattern PORT_PATTERN = + Pattern.compile(PORT_PATTERN_STRING); + private static final Pattern PORT_PATH_PATTERN = + Pattern.compile(PORT_PATH_PATTERN_STRING); + private static final Pattern HOST_PORT_PATTERN = + Pattern.compile(HOST_PORT_PATTERN_STRING); + private static final Pattern HOST_PORT_PATH_PATTERN = + Pattern.compile(HOST_PORT_PATH_PATTERN_STRING); + + /* + * matches: + * 8080 + * 8080: + */ + private static boolean registerPort(String name, RequestHandler handler, + RequestMapper mapper) { + Matcher m = null; + m = PORT_PATTERN.matcher(name); + if(m.matches()) { + int port = Integer.parseInt(m.group(1)); + mapper.addRequestHandler(port, null, null, handler); + return true; + } + return false; + } + /* + * matches: + * 8080:blue + * 8080:fish + */ + private static boolean registerPortPath(String name, RequestHandler handler, + RequestMapper mapper) { + Matcher m = null; + m = PORT_PATH_PATTERN.matcher(name); + if(m.matches()) { + int port = Integer.parseInt(m.group(1)); + mapper.addRequestHandler(port, null, m.group(2), handler); + return true; + } + return false; + } + /* + * matches: + * localhost.archive.org:8080 + * static.localhost.archive.org:8080 + */ + private static boolean registerHostPort(String name, RequestHandler handler, + RequestMapper mapper) { + Matcher m = null; + m = HOST_PORT_PATTERN.matcher(name); + if(m.matches()) { + int port = Integer.parseInt(m.group(2)); + mapper.addRequestHandler(port, m.group(1), null, handler); + return true; + } + return false; + } + /* + * matches: + * localhost.archive.org:8080:two + * static.localhost.archive.org:8080:fish + */ + private static boolean registerHostPortPath(String name, + RequestHandler handler, RequestMapper mapper) { + Matcher m = null; + m = HOST_PORT_PATH_PATTERN.matcher(name); + if(m.matches()) { + int port = Integer.parseInt(m.group(2)); + mapper.addRequestHandler(port, m.group(1), m.group(3), handler); + return true; + } + return false; + } + + /** + * Extract the RequestHandler objects beanName, parse it, and register the + * RequestHandler with the RequestMapper according to the beanNames + * semantics. + * @param handler The RequestHandler to register + * @param mapper the RequestMapper where the RequestHandler should be + * registered. + */ + public static void registerHandler(RequestHandler handler, + RequestMapper mapper) { + String name = handler.getBeanName(); + if(name != null) { + if(name.equals(RequestMapper.GLOBAL_PRE_REQUEST_HANDLER)) { + + mapper.addGlobalPreRequestHandler(handler); + + } else if(name.equals(RequestMapper.GLOBAL_POST_REQUEST_HANDLER)) { + + mapper.addGlobalPostRequestHandler(handler); + + } else { + try { + + boolean registered = + registerPort(name, handler, mapper) || + registerPortPath(name, handler, mapper) || + registerHostPort(name, handler, mapper) || + registerHostPortPath(name, handler, mapper); + + if(!registered) { + LOGGER.error("Unable to register (" + name + ")"); + } + } catch(NumberFormatException e) { + LOGGER.error("FAILED parseInt(" + name + ")"); + } + } + } else { + LOGGER.info("Unable to register RequestHandler - null beanName"); + } + if(handler instanceof ShutdownListener) { + ShutdownListener s = (ShutdownListener) handler; + mapper.addShutdownListener(s); + } + } +} Property changes on: trunk/archive-access/projects/wayback/wayback-core/src/main/java/org/archive/wayback/util/webapp/BeanNameRegistrar.java ___________________________________________________________________ Added: svn:keywords + Author Date Revision Id Added: trunk/archive-access/projects/wayback/wayback-core/src/main/java/org/archive/wayback/util/webapp/PortMapper.java =================================================================== --- trunk/archive-access/projects/wayback/wayback-core/src/main/java/org/archive/wayback/util/webapp/PortMapper.java (rev 0) +++ trunk/archive-access/projects/wayback/wayback-core/src/main/java/org/archive/wayback/util/webapp/PortMapper.java 2010-04-27 22:12:31 UTC (rev 3074) @@ -0,0 +1,164 @@ +/* PortMapper + * + * $Id$: + * + * Created on Mar 23, 2010. + * + * Copyright (C) 2006 Internet Archive. + * + * This file is part of Wayback. + * + * Wayback is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * any later version. + * + * Wayback is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser Public License for more details. + * + * You should have received a copy of the GNU Lesser Public License + * along with Wayback; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +package org.archive.wayback.util.webapp; + +import java.util.HashMap; + +import javax.servlet.http.HttpServletRequest; + +import org.apache.log4j.Logger; + +/** + * + * Class which allows semi-efficient translation of requests on a specific local + * port to a RequestHandler object. + * + * Mapping within a port is based on the HTTP 1.1 Host field and the first + * segment of the requested PATH, that is, whatever is after the context where + * the wayback webapp was deployed, and before the first '/'. + * + * @author brad + */ +public class PortMapper { + private static final Logger LOGGER = Logger.getLogger( + PortMapper.class.getName()); + private int port = -1; + private HashMap<String, RequestHandler> pathMap = null; + /** + * @param port which this PortMapper is responsible for handling + */ + public PortMapper(int port) { + this.port = port; + pathMap = new HashMap<String, RequestHandler>(); + } + private String hostPathToKey(String host, String firstPath) { + StringBuilder sb = null; + if((host == null) && (firstPath == null)) { + return null; + } + sb = new StringBuilder(); + if(host != null) { + sb.append(host); + } + sb.append("/"); + if(firstPath != null) { + sb.append(firstPath); + } + return sb.toString(); + } + /** + * Register the RequestHandler to accept requests for the given host and + * port. + * @param host the HTTP 1.1 "Host" header which the RequestHandler should + * match. If null, the RequestHandler matches any "Host" header value. + * @param firstPath the first path of the GET request path which the + * RequestHandler should match. This is the first path AFTER the name the + * Wayback webapp is deployed under. If null, the RequestHandler matches + * all paths. + * @param requestHandler The RequestHandler to register. + */ + public void addRequestHandler(String host, String firstPath, + RequestHandler requestHandler) { + String key = hostPathToKey(host,firstPath); + if(pathMap.containsKey(key)) { + LOGGER.warn("Duplicate port:path map for " + port + + ":" + key); + } else { + LOGGER.info("Registered requestHandler(port/host/path) (" + + port + "/" + host + "/" + firstPath + "): " + key); + pathMap.put(key,requestHandler); + } + } + + private String requestToFirstPath(HttpServletRequest request) { + String firstPath = null; + String requestPath = request.getRequestURI(); + String contextPath = request.getContextPath(); + if((contextPath.length() > 0) && requestPath.startsWith(contextPath)) { + requestPath = requestPath.substring(contextPath.length()); + } + while(requestPath.startsWith("/")) { + requestPath = requestPath.substring(1); + } + + int slashIdx = requestPath.indexOf("/",1); + if(slashIdx == -1) { + firstPath = requestPath; + } else { + firstPath = requestPath.substring(0,slashIdx); + } + return firstPath; + } + + private String requestToHost(HttpServletRequest request) { + return request.getServerName(); + } + + /** + * Attempts to locate the most strictly matching RequestHandler mapped to + * this port. Strictly matching means the lowest number in the following + * list: + * + * 1) request handler matching both HOST and PATH + * 2) request handler matching host, registered with an empty PATH + * 3) request handler matching path, registered with an empty HOST + * 4) request handler registered with empty HOST and PATH + * + * @param request the HttpServletRequest to be mapped to a RequestHandler + * @return the RequestHandlerContext, containing the RequestHandler and the + * prefix of the original request path that indicated the RequestHandler, + * or null, if no RequestHandler matches. + */ + public RequestHandlerContext getRequestHandlerContext( + HttpServletRequest request) { + String host = requestToHost(request); + String contextPath = request.getContextPath(); + StringBuilder pathPrefix = new StringBuilder(contextPath); + if(contextPath.length() == 0) { + pathPrefix.append("/"); + } + String firstPath = requestToFirstPath(request); + RequestHandler handler = pathMap.get(hostPathToKey(host,firstPath)); + if(handler != null) { + return new RequestHandlerContext(handler, + pathPrefix.append(firstPath).toString()); + } + handler = pathMap.get(hostPathToKey(host,null)); + if(handler != null) { + return new RequestHandlerContext(handler,contextPath); + } + handler = pathMap.get(hostPathToKey(null,firstPath)); + if(handler != null) { + return new RequestHandlerContext(handler, + pathPrefix.append(firstPath).toString()); + } + handler = pathMap.get(null); + if(handler != null) { + return new RequestHandlerContext(handler,contextPath); + } + return null; + } +} Property changes on: trunk/archive-access/projects/wayback/wayback-core/src/main/java/org/archive/wayback/util/webapp/PortMapper.java ___________________________________________________________________ Added: svn:keywords + Author Date Revision Id Added: trunk/archive-access/projects/wayback/wayback-core/src/main/java/org/archive/wayback/util/webapp/RequestFilter.java =================================================================== --- trunk/archive-access/projects/wayback/wayback-core/src/main/java/org/archive/wayback/util/webapp/RequestFilter.java (rev 0) +++ trunk/archive-access/projects/wayback/wayback-core/src/main/java/org/archive/wayback/util/webapp/RequestFilter.java 2010-04-27 22:12:31 UTC (rev 3074) @@ -0,0 +1,91 @@ +/* RequestHandler + * + * $Id$ + * + * Created on 4:24:06 PM Apr 20, 2007. + * + * Copyright (C) 2007 Internet Archive. + * + * This file is part of wayback-webapp. + * + * wayback-webapp is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * any later version. + * + * wayback-webapp is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser Public License for more details. + * + * You should have received a copy of the GNU Lesser Public License + * along with wayback-webapp; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +package org.archive.wayback.util.webapp; + +import java.io.IOException; + +import javax.servlet.Filter; +import javax.servlet.FilterChain; +import javax.servlet.FilterConfig; +import javax.servlet.ServletContext; +import javax.servlet.ServletException; +import javax.servlet.ServletRequest; +import javax.servlet.ServletResponse; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.apache.log4j.Logger; + +/** + * Top-Level integration point between a series of RequestHandler mappings and + * a generic ServletContext. This filter is assumed to be responsible for + * matching ALL requests received by the webapp ("*") and uses a RequestMapper + * to delegate incoming HttpServletRequests to the appropriate RequestHandler, + * via the doFilter() method. + * + * @author brad + */ +public class RequestFilter implements Filter { + private static final Logger LOGGER = Logger.getLogger(RequestFilter.class + .getName()); + private RequestMapper mapper = null; + private final static String CONFIG_PATH = "config-path"; + + public void init(FilterConfig config) throws ServletException { + ServletContext servletContext = config.getServletContext(); + + String configPath = servletContext.getInitParameter(CONFIG_PATH); + if(configPath == null) { + throw new ServletException("Missing " + CONFIG_PATH + + " parameter"); + } + String resolvedPath = servletContext.getRealPath(configPath); + + LOGGER.info("Initializing Spring config at: " + resolvedPath); + mapper = SpringReader.readSpringConfig(resolvedPath,servletContext); + LOGGER.info("Initialized Spring config at: " + resolvedPath); + } + + public void destroy() { + LOGGER.info("Shutdown starting."); + mapper.shutdown(); + LOGGER.info("Shutdown complete."); + } + + public void doFilter(ServletRequest request, ServletResponse response, + FilterChain chain) throws IOException, ServletException { + boolean handled = false; + + if(request instanceof HttpServletRequest) { + if(response instanceof HttpServletResponse) { + handled = mapper.handleRequest((HttpServletRequest) request, + (HttpServletResponse) response); + } + } + if(!handled) { + chain.doFilter(request,response); + } + } +} Property changes on: trunk/archive-access/projects/wayback/wayback-core/src/main/java/org/archive/wayback/util/webapp/RequestFilter.java ___________________________________________________________________ Added: svn:keywords + Author Date Revision Id Added: trunk/archive-access/projects/wayback/wayback-core/src/main/java/org/archive/wayback/util/webapp/RequestHandler.java =================================================================== --- trunk/archive-access/projects/wayback/wayback-core/src/main/java/org/archive/wayback/util/webapp/RequestHandler.java (rev 0) +++ trunk/archive-access/projects/wayback/wayback-core/src/main/java/org/archive/wayback/util/webapp/RequestHandler.java 2010-04-27 22:12:31 UTC (rev 3074) @@ -0,0 +1,85 @@ +/** + * + */ +package org.archive.wayback.util.webapp; + +import java.io.IOException; + +import javax.servlet.ServletContext; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.springframework.beans.factory.BeanNameAware; + +/** + * A generic handler of HttpServletRequests. very similar to an HttpServlet, but + * the handleRequest() method returns a boolean indicating if the RequestHandler + * returned data to the user. + * + * This interface further defines methods to facilitate automatic registration + * when loaded as a Spring configuration, and maintains a reference to the + * ServletContext under which it accepts incoming requests. + * + * @author brad + * + */ +public interface RequestHandler extends BeanNameAware { + + /** + * Possibly handle an incoming HttpServletRequest, much like a normal + * HttpServlet, but includes a return value. + * @param httpRequest the incoming HttpServletRequest + * @param httpResponse the HttpServletResponse to return data to the client. + * @return true if the RequestHandler returned a response to the client, + * false otherwise + * @throws ServletException for usual reasons. + * @throws IOException for usual reasons. + */ + public boolean handleRequest(HttpServletRequest httpRequest, + HttpServletResponse httpResponse) + throws ServletException, IOException; + + /** + * @return the "name" property of the bean from the SpringConfiguration + */ + public String getBeanName(); + + /** + * Called before registerPortListener(), to enable the registration process + * and subsequent handleRequest() calls to access the ServletContext, via + * the getServletContext() method. + * @param servletContext the ServletContext where the RequestHandler is + * registered. + */ + public void setServletContext(ServletContext servletContext); + + /** + * @return the ServletContext where the RequestHandler is registered. + */ + public ServletContext getServletContext(); + + /** + * Called at webapp context initialization, to allow the RequestHandler to + * register itself with the RequestMapper, which will delegate request + * handling to the appropriate RequestHandler. + * @param requestMapper the RequestMapper on which this RequestHandler + * should register itself, including to register for notification of context + * shutdown. + */ + public void registerPortListener(RequestMapper requestMapper); + + /** + * @param httpRequest the HttpServletRequest being handled + * @return the portion of the original incoming request that falls within + * this RequestHandler, not including any query information + */ + public String translateRequestPath(HttpServletRequest httpRequest); + + /** + * @param httpRequest the HttpServletRequest being handled + * @return the portion of the original incoming request that falls within + * this RequestHandler, including any query information + */ + public String translateRequestPathQuery(HttpServletRequest httpRequest); +} Property changes on: trunk/archive-access/projects/wayback/wayback-core/src/main/java/org/archive/wayback/util/webapp/RequestHandler.java ___________________________________________________________________ Added: svn:keywords + Author Date Revision Id Added: trunk/archive-access/projects/wayback/wayback-core/src/main/java/org/archive/wayback/util/webapp/RequestHandlerContext.java =================================================================== --- trunk/archive-access/projects/wayback/wayback-core/src/main/java/org/archive/wayback/util/webapp/RequestHandlerContext.java (rev 0) +++ trunk/archive-access/projects/wayback/wayback-core/src/main/java/org/archive/wayback/util/webapp/RequestHandlerContext.java 2010-04-27 22:12:31 UTC (rev 3074) @@ -0,0 +1,66 @@ +/* RequestHandlerContext + * + * $Id$: + * + * Created on Apr 26, 2010. + * + * Copyright (C) 2006 Internet Archive. + * + * This file is part of Wayback. + * + * Wayback is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * any later version. + * + * Wayback is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser Public License for more details. + * + * You should have received a copy of the GNU Lesser Public License + * along with Wayback; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +package org.archive.wayback.util.webapp; + +/** + * A simple composition of the RequestHandler which an HttpServletRequest was + * mapped to, and the path prefix which indicated the RequestHandler. This + * allows computing the portion of the original request path within the + * RequestHandler. + * + * @author brad + * + */ +public class RequestHandlerContext { + + private RequestHandler handler = null; + private String pathPrefix = null; + + /** + * Constructor + * @param handler the RequestHandler to which the incoming request was + * mapped + * @param pathPrefix the leading portion of the original request path that + * indicated the RequestHandler + */ + public RequestHandlerContext(RequestHandler handler, String pathPrefix) { + this.handler = handler; + this.pathPrefix = pathPrefix; + } + /** + * @return the RequestHandler to which the incoming request was mapped. + */ + public RequestHandler getRequestHandler() { + return handler; + } + /** + * @return the leading portion of the original request path that + * indicated the RequestHandler + */ + public String getPathPrefix() { + return pathPrefix; + } +} Property changes on: trunk/archive-access/projects/wayback/wayback-core/src/main/java/org/archive/wayback/util/webapp/RequestHandlerContext.java ___________________________________________________________________ Added: svn:keywords + Author Date Revision Id Added: trunk/archive-access/projects/wayback/wayback-core/src/main/java/org/archive/wayback/util/webapp/RequestMapper.java =================================================================== --- trunk/archive-access/projects/wayback/wayback-core/src/main/java/org/archive/wayback/util/webapp/RequestMapper.java (rev 0) +++ trunk/archive-access/projects/wayback/wayback-core/src/main/java/org/archive/wayback/util/webapp/RequestMapper.java 2010-04-27 22:12:31 UTC (rev 3074) @@ -0,0 +1,266 @@ +/* RequestMapper + * + * $Id$: + * + * Created on Mar 23, 2010. + * + * Copyright (C) 2006 Internet Archive. + * + * This file is part of Wayback. + * + * Wayback is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * any later version. + * + * Wayback is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser Public License for more details. + * + * You should have received a copy of the GNU Lesser Public License + * along with Wayback; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +package org.archive.wayback.util.webapp; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.Iterator; + +import javax.servlet.ServletContext; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.apache.log4j.Logger; + +/** + * This class maintains a mapping of RequestHandlers and ShutDownListeners, to + * allow (somewhat) efficient mapping and delegation of incoming requests to + * the appropriate RequestHandler. + * + * This class uses PortMapper to delegate some of the responsibility of mapping + * requests received on a particular port, and also allows configuration of a + * global PRE RequestHandler, which gets first dibs on EVERY incoming request, + * as well as a global POST RequestHandler, which may attempt to handle any + * incoming request not handled by the normal RequestHandler mapping. + * + * @author brad + * + */ +public class RequestMapper { + + private static final Logger LOGGER = Logger.getLogger( + RequestMapper.class.getName()); + + private ArrayList<ShutdownListener> shutdownListeners = null; + + private HashMap<Integer,PortMapper> portMap = null; + private RequestHandler globalPreRequestHandler = null; + private RequestHandler globalPostRequestHandler = null; + + private final static String REQUEST_CONTEXT_PREFIX = + "webapp-request-context-path-prefix"; + + /** + * Bean name used to register the special global PRE RequestHandler. + */ + public final static String GLOBAL_PRE_REQUEST_HANDLER = "-"; + /** + * Bean name used to register the special global POST RequestHandler. + */ + public final static String GLOBAL_POST_REQUEST_HANDLER = "+"; + + /** + * Construct a RequestMapper, for the given RequestHandler objects, on the + * specified ServletContext. This method will call setServletContext() on + * each RequestMapper, followed immediately by registerPortListener() + * + * @param requestHandlers Collection of RequestHandlers which handle + * requests + * @param servletContext the webapp ServletContext where this RequestMapper + * is configured. + */ + public RequestMapper(Collection<RequestHandler> requestHandlers, + ServletContext servletContext) { + portMap = new HashMap<Integer, PortMapper>(); + shutdownListeners = new ArrayList<ShutdownListener>(); + Iterator<RequestHandler> itr = requestHandlers.iterator(); + LOGGER.info("Registering handlers."); + while(itr.hasNext()) { + RequestHandler requestHandler = itr.next(); + requestHandler.setServletContext(servletContext); + requestHandler.registerPortListener(this); + } + LOGGER.info("Registering handlers complete."); + } + + /** + * Request the shutdownListener object to be notified of ServletContext + * shutdown. + * @param shutdownListener the object which needs to have shutdown() called + * when the ServletContext is destroyed. + */ + public void addShutdownListener(ShutdownListener shutdownListener) { + shutdownListeners.add(shutdownListener); + } + /** + * Configure the specified RequestHandler to handle ALL incoming requests + * before any other normal mapping. + * @param requestHandler the global PRE RequestHandler + */ + public void addGlobalPreRequestHandler(RequestHandler requestHandler) { + globalPreRequestHandler = requestHandler; + } + /** + * Configure the specified RequestHandler to handle ALL incoming requests + * after all other normal mapping has been attempted + * @param requestHandler the global POST RequestHandler + */ + public void addGlobalPostRequestHandler(RequestHandler requestHandler) { + globalPostRequestHandler = requestHandler; + } + /** + * Register the RequestHandler to accept requests on the given port, for the + * specified host and path. + * @param port the integer port on which the RequestHandler gets requests. + * @param host the String Host which the RequestHandler matches, or null, if + * the RequestHandler should match ALL hosts. + * @param path the String path which the RequestHandler matches, or null, if + * the RequestHandler should match ALL paths. + * @param requestHandler the RequestHandler to register. + */ + public void addRequestHandler(int port, String host, String path, + RequestHandler requestHandler) { + LOGGER.info("Registered:" + port + ":" + + (host == null ? "(null)" : host) + ":" + + (path == null ? "(null)" : path)); + Integer portInt = Integer.valueOf(port); + PortMapper portMapper = portMap.get(portInt); + if(portMapper == null) { + portMapper = new PortMapper(portInt); + portMap.put(portInt, portMapper); + } + portMapper.addRequestHandler(host, path, requestHandler); + } + + private RequestHandlerContext mapRequest(HttpServletRequest request) { + RequestHandlerContext handlerContext = null; + + int port = request.getLocalPort(); + Integer portInt = Integer.valueOf(port); + PortMapper portMapper = portMap.get(portInt); + if(portMapper != null) { + handlerContext = portMapper.getRequestHandlerContext(request); + } + return handlerContext; + } + + /** + * Map the incoming request to the appropriate RequestHandler, including + * the PRE and POST RequestHandlers, if configured. + * @param request the incoming HttpServletRequest + * @param response the HttpServletResponse to return data to the client + * @return true if a response was returned to the client. + * @throws ServletException for usual reasons. + * @throws IOException for usual reasons. + */ + public boolean handleRequest(HttpServletRequest request, + HttpServletResponse response) throws IOException, ServletException { + boolean handled = false; + if(globalPreRequestHandler != null) { + handled = + globalPreRequestHandler.handleRequest(request, response); + } + if(handled == false) { + RequestHandlerContext handlerContext = mapRequest(request); + if(handlerContext != null) { + RequestHandler requestHandler = + handlerContext.getRequestHandler(); + request.setAttribute(REQUEST_CONTEXT_PREFIX, + handlerContext.getPathPrefix() + "/"); + handled = requestHandler.handleRequest(request, response); + } + } + if(handled == false) { + if(globalPostRequestHandler != null) { + handled = + globalPostRequestHandler.handleRequest(request, response); + } + } + return handled; + } + + /** + * notify all registered ShutdownListener objects that the ServletContext is + * being destroyed. + */ + public void shutdown() { + for(ShutdownListener shutdownListener : shutdownListeners) { + try { + shutdownListener.shutdown(); + } catch(Exception e) { + LOGGER.error("failed shutdown", e); + } + } + } + + /** + * Extract the request path prefix, as computed at RequestHandler mapping, + * from the HttpServletRequest object. + * + * @param request HttpServlet request object being handled + * @return the portion of the original request path which indicated the + * RequestHandler, including the trailing '/'. + */ + public static String getRequestPathPrefix(HttpServletRequest request) { + return (String) request.getAttribute(REQUEST_CONTEXT_PREFIX); + } + + /** + * @param request HttpServlet request object being handled + * @return the portion of the incoming path within the RequestHandler + * handling the request, not including a leading "/", and not including + * query arguments. + */ + public static String getRequestContextPath(HttpServletRequest request) { + String prefix = (String) request.getAttribute(REQUEST_CONTEXT_PREFIX); + String requestUrl = request.getRequestURI(); + if(prefix == null) { + return requestUrl; + } + if(requestUrl.startsWith(prefix)) { + return requestUrl.substring(prefix.length()); + } + return requestUrl; + } + + /** + * @param request HttpServlet request object being handled + * @return the portion of the incoming path within the RequestHandler + * handling the request, not including a leading "/", including query + * arguments. + */ + public static String getRequestContextPathQuery(HttpServletRequest request) { + String prefix = (String) request.getAttribute(REQUEST_CONTEXT_PREFIX); + StringBuilder sb = new StringBuilder(request.getRequestURI()); + String requestUrl = null; + String query = request.getQueryString(); + if(query != null) { + requestUrl = sb.append("?").append(query).toString(); + } else { + requestUrl = sb.toString(); + } + if(prefix == null) { + return requestUrl; + } + if(requestUrl.startsWith(prefix)) { + return requestUrl.substring(prefix.length()); + } + return requestUrl; + } +} Property changes on: trunk/archive-access/projects/wayback/wayback-core/src/main/java/org/archive/wayback/util/webapp/RequestMapper.java ___________________________________________________________________ Added: svn:keywords + Author Date Revision Id Added: trunk/archive-access/projects/wayback/wayback-core/src/main/java/org/archive/wayback/util/webapp/ShutdownListener.java =================================================================== --- trunk/archive-access/projects/wayback/wayback-core/src/main/java/org/archive/wayback/util/webapp/ShutdownListener.java (rev 0) +++ trunk/archive-access/projects/wayback/wayback-core/src/main/java/org/archive/wayback/util/webapp/ShutdownListener.java 2010-04-27 22:12:31 UTC (rev 3074) @@ -0,0 +1,18 @@ +/** + * + */ +package org.archive.wayback.util.webapp; + +/** + * Interface representing a desire to be notified when the containing + * ServletContext is being destroyed. + * + * @author brad + * + */ +public interface ShutdownListener { + /** + * Called when the ServletContext is being destroyed. + */ + public void shutdown(); +} Property changes on: trunk/archive-access/projects/wayback/wayback-core/src/main/java/org/archive/wayback/util/webapp/ShutdownListener.java ___________________________________________________________________ Added: svn:keywords + Author Date Revision Id Added: trunk/archive-access/projects/wayback/wayback-core/src/main/java/org/archive/wayback/util/webapp/SpringReader.java =================================================================== --- trunk/archive-access/projects/wayback/wayback-core/src/main/java/org/archive/wayback/util/webapp/SpringReader.java (rev 0) +++ trunk/archive-access/projects/wayback/wayback-core/src/main/java/org/archive/wayback/util/webapp/SpringReader.java 2010-04-27 22:12:31 UTC (rev 3074) @@ -0,0 +1,61 @@ +/** + * + */ +package org.archive.wayback.util.webapp; +import java.util.Collection; +import java.util.Map; + +import javax.servlet.ServletContext; + +import org.apache.log4j.Logger; +import org.springframework.beans.factory.config.PropertyPlaceholderConfigurer; +import org.springframework.beans.factory.xml.XmlBeanFactory; +import org.springframework.core.io.FileSystemResource; +import org.springframework.core.io.Resource; + +/** + * Single static method to read a Spring XML configuration, extract + * RequestHandlers, and return a RequestMapper which delegates requests to + * those RequestHandlers. + * + * @author brad + * + */ +public class SpringReader { + private static final Logger LOGGER = Logger.getLogger( + SpringReader.class.getName()); + + /** + * Read the single Spring XML configuration file located at the specified + * path, performing PropertyPlaceHolder interpolation, extracting all beans + * which implement the RequestHandler interface, and construct a + * RequestMapper for those RequestHandlers, on the specified ServletContext. + * @param configPath the path to the Spring XML file containing the + * configuration. + * @param servletContext the ServletContext where the RequestHandlers should + * be mapped + * @return a new ReqeustMapper which delegates requests for the + * ServletContext + */ + @SuppressWarnings("unchecked") + public static RequestMapper readSpringConfig(String configPath, + ServletContext servletContext) { + LOGGER.info("Loading from config file " + configPath); + + Resource resource = new FileSystemResource(configPath); + XmlBeanFactory factory = new XmlBeanFactory(resource); + Map map = factory.getBeansOfType(PropertyPlaceholderConfigurer.class); + if(map != null) { + Collection<PropertyPlaceholderConfigurer> macros = map.values(); + for(PropertyPlaceholderConfigurer macro : macros) { + macro.postProcessBeanFactory(factory); + } + } + LOGGER.info("Pre-instanting Singletons starting"); + factory.preInstantiateSingletons(); + LOGGER.info("Pre-instanting Singletons complete"); + Map<String,RequestHandler> beans = + factory.getBeansOfType(RequestHandler.class,false,false); + return new RequestMapper(beans.values(), servletContext); + } +} Property changes on: trunk/archive-access/projects/wayback/wayback-core/src/main/java/org/archive/wayback/util/webapp/SpringReader.java ___________________________________________________________________ Added: svn:keywords + Author Date Revision Id Added: trunk/archive-access/projects/wayback/wayback-core/src/main/java/org/archive/wayback/util/webapp/StaticFileRequestHandler.java =================================================================== --- trunk/archive-access/projects/wayback/wayback-core/src/main/java/org/archive/wayback/util/webapp/StaticFileRequestHandler.java (rev 0) +++ trunk/archive-access/projects/wayback/wayback-core/src/main/java/org/archive/wayback/util/webapp/StaticFileRequestHandler.java 2010-04-27 22:12:31 UTC (rev 3074) @@ -0,0 +1,49 @@ +/** + * + */ +package org.archive.wayback.util.webapp; + +import java.io.File; +import java.io.IOException; + +import javax.servlet.RequestDispatcher; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.apache.log4j.Logger; + +/** + * RequestHandler implementation which allows serving of static files, and + * .jsp files within a ServletContext. + * + * @author brad + */ +public class StaticFileRequestHandler extends AbstractRequestHandler { + + private static final Logger LOGGER = Logger.getLogger( + StaticFileRequestHandler.class.getName()); + + public boolean handleRequest(HttpServletRequest httpRequest, + HttpServletResponse httpResponse) throws ServletException, IOException { + boolean handled = false; + String contextRelativePath = httpRequest.getServletPath(); + String absPath = getServletContext().getRealPath(contextRelativePath); + File test = new File(absPath); + // TODO: check for index.jsp(or configurable equivalent), + // if it's a directory? + if(test.isFile()) { + LOGGER.trace("static path:" + absPath); + RequestDispatcher dispatcher = + httpRequest.getRequestDispatcher(contextRelativePath); +// try { + dispatcher.forward(httpRequest, httpResponse); + handled = true; +// } catch(Exception e) { +// } + } else { + LOGGER.trace("Not-static path:" + absPath); + } + return handled; + } +} Property changes on: trunk/archive-access/projects/wayback/wayback-core/src/main/java/org/archive/wayback/util/webapp/StaticFileRequestHandler.java ___________________________________________________________________ Added: svn:keywords + Author Date Revision Id This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <bra...@us...> - 2011-06-16 17:18:16
|
Revision: 3474 http://archive-access.svn.sourceforge.net/archive-access/?rev=3474&view=rev Author: bradtofel Date: 2011-06-16 17:18:09 +0000 (Thu, 16 Jun 2011) Log Message: ----------- INITIAL REV: new classes, as yet unused, for dealing with Iterators Added Paths: ----------- trunk/archive-access/projects/wayback/wayback-core/src/main/java/org/archive/wayback/util/iterator/ trunk/archive-access/projects/wayback/wayback-core/src/main/java/org/archive/wayback/util/iterator/AbstractPeekableIterator.java trunk/archive-access/projects/wayback/wayback-core/src/main/java/org/archive/wayback/util/iterator/IPeekableIterator.java trunk/archive-access/projects/wayback/wayback-core/src/main/java/org/archive/wayback/util/iterator/PeekableIteratorComparator.java trunk/archive-access/projects/wayback/wayback-core/src/main/java/org/archive/wayback/util/iterator/SortedCompositeIterator.java Added: trunk/archive-access/projects/wayback/wayback-core/src/main/java/org/archive/wayback/util/iterator/AbstractPeekableIterator.java =================================================================== --- trunk/archive-access/projects/wayback/wayback-core/src/main/java/org/archive/wayback/util/iterator/AbstractPeekableIterator.java (rev 0) +++ trunk/archive-access/projects/wayback/wayback-core/src/main/java/org/archive/wayback/util/iterator/AbstractPeekableIterator.java 2011-06-16 17:18:09 UTC (rev 3474) @@ -0,0 +1,93 @@ +package org.archive.wayback.util.iterator; + +import java.io.BufferedReader; +import java.io.IOException; +import java.util.Comparator; +import java.util.Iterator; +import java.util.NoSuchElementException; + + +public abstract class AbstractPeekableIterator<E> implements IPeekableIterator<E> { + private E cachedNext = null; + private boolean done = false; + + // returns next E, or null if hasNext() would return false; + public abstract E getNextInner(); + + public boolean hasNext() { + if(cachedNext != null) { + return true; + } + if(done) { + return false; + } + cachedNext = getNextInner(); + return (cachedNext != null); + } + + public E next() { + if(cachedNext == null) { + if(!hasNext()) { + throw new NoSuchElementException("Call hasNext!"); + } + } + E tmp = cachedNext; + cachedNext = null; + return tmp; + } + + public void remove() { + throw new UnsupportedOperationException("No remove"); + } + + public E peek() { + if(cachedNext == null) { + if(!hasNext()) { + throw new NoSuchElementException("Call hasNext!"); + } + } + return cachedNext; + } + public static <T> IPeekableIterator<T> wrap(Iterator<T> itr) { + return new IteratorWrappedPeekableIterator<T>(itr); + } + public static IPeekableIterator<String> wrapReader(BufferedReader reader) { + return new BufferedReaderPeekableIterator(reader); + } + + private static class IteratorWrappedPeekableIterator<C> extends AbstractPeekableIterator<C> { + private Iterator<C> wrapped = null; + public IteratorWrappedPeekableIterator(Iterator<C> wrapped) { + this.wrapped = wrapped; + } + @Override + public C getNextInner() { + C next = null; + if(wrapped != null) { + if(wrapped.hasNext()) { + next = wrapped.next(); + } + } + return next; + } + } + private static class BufferedReaderPeekableIterator extends AbstractPeekableIterator<String> { + private BufferedReader reader = null; + public BufferedReaderPeekableIterator(BufferedReader reader) { + this.reader = reader; + } + @Override + public String getNextInner() { + String next = null; + if(reader != null) { + try { + next = reader.readLine(); + } catch (IOException e) { + e.printStackTrace(); + } + } + return next; + } + } + +} Property changes on: trunk/archive-access/projects/wayback/wayback-core/src/main/java/org/archive/wayback/util/iterator/AbstractPeekableIterator.java ___________________________________________________________________ Added: svn:executable + * Added: trunk/archive-access/projects/wayback/wayback-core/src/main/java/org/archive/wayback/util/iterator/IPeekableIterator.java =================================================================== --- trunk/archive-access/projects/wayback/wayback-core/src/main/java/org/archive/wayback/util/iterator/IPeekableIterator.java (rev 0) +++ trunk/archive-access/projects/wayback/wayback-core/src/main/java/org/archive/wayback/util/iterator/IPeekableIterator.java 2011-06-16 17:18:09 UTC (rev 3474) @@ -0,0 +1,7 @@ +package org.archive.wayback.util.iterator; + +import java.util.Iterator; + +public interface IPeekableIterator<E> extends Iterator<E> { + public E peek(); +} Property changes on: trunk/archive-access/projects/wayback/wayback-core/src/main/java/org/archive/wayback/util/iterator/IPeekableIterator.java ___________________________________________________________________ Added: svn:executable + * Added: trunk/archive-access/projects/wayback/wayback-core/src/main/java/org/archive/wayback/util/iterator/PeekableIteratorComparator.java =================================================================== --- trunk/archive-access/projects/wayback/wayback-core/src/main/java/org/archive/wayback/util/iterator/PeekableIteratorComparator.java (rev 0) +++ trunk/archive-access/projects/wayback/wayback-core/src/main/java/org/archive/wayback/util/iterator/PeekableIteratorComparator.java 2011-06-16 17:18:09 UTC (rev 3474) @@ -0,0 +1,44 @@ +/* + * This file is part of the Wayback archival access software + * (http://archive-access.sourceforge.net/projects/wayback/). + * + * Licensed to the Internet Archive (IA) by one or more individual + * contributors. + * + * The IA licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.archive.wayback.util.iterator; + +import java.util.Comparator; + +/** + * @author brad + * + * @param <J> type found in Iterators + */ +public class PeekableIteratorComparator<J> implements Comparator<IPeekableIterator<J>> { + private Comparator<J> comparator = null; + /** + * @param comparator to compare the iterators + */ + public PeekableIteratorComparator(Comparator<J> comparator) { + this.comparator = comparator; + } + + public int compare(IPeekableIterator<J> o1, IPeekableIterator<J> o2) { + return comparator.compare(o1.peek(), o2.peek()); + } + public static <K> Comparator<IPeekableIterator<K>> getComparator(Comparator<K> comparator) { + return new PeekableIteratorComparator<K>(comparator); + } +} Added: trunk/archive-access/projects/wayback/wayback-core/src/main/java/org/archive/wayback/util/iterator/SortedCompositeIterator.java =================================================================== --- trunk/archive-access/projects/wayback/wayback-core/src/main/java/org/archive/wayback/util/iterator/SortedCompositeIterator.java (rev 0) +++ trunk/archive-access/projects/wayback/wayback-core/src/main/java/org/archive/wayback/util/iterator/SortedCompositeIterator.java 2011-06-16 17:18:09 UTC (rev 3474) @@ -0,0 +1,56 @@ +package org.archive.wayback.util.iterator; + +import java.util.Collection; +import java.util.Comparator; +import java.util.Iterator; +import java.util.NoSuchElementException; +import java.util.PriorityQueue; + + +public class SortedCompositeIterator<E> implements Iterator<E> { + private static final int DEFAULT_CAPACITY = 10; + PriorityQueue<IPeekableIterator<E>> q = null; + + public SortedCompositeIterator(Comparator<E> comparator) { + this(DEFAULT_CAPACITY,comparator); + } + public SortedCompositeIterator(int capacity, Comparator<E> comparator) { + q = new PriorityQueue<IPeekableIterator<E>>(capacity, + new PeekableIteratorComparator<E>(comparator)); + } + public void addAll(Collection<Iterator<E>> toAdd) { + for(Iterator<E> e : toAdd) { + addIterator(e); + } + } + public void addIterator(Iterator<E> itr) { + IPeekableIterator<E> i = null; + if(itr instanceof IPeekableIterator) { + i = (IPeekableIterator<E>) itr; + } else { + i = AbstractPeekableIterator.wrap(itr); + } + if(i.hasNext()) { + q.add(i); + } + } + + public boolean hasNext() { + return (q.peek() != null); + } + + public E next() { + IPeekableIterator<E> i = q.poll(); + if(i == null) { + throw new NoSuchElementException("Call hasNext!"); + } + E tmp = i.next(); + if(i.hasNext()) { + q.add(i); + } + return tmp; + } + public void remove() { + throw new UnsupportedOperationException("No remove"); + } +} Property changes on: trunk/archive-access/projects/wayback/wayback-core/src/main/java/org/archive/wayback/util/iterator/SortedCompositeIterator.java ___________________________________________________________________ Added: svn:executable + * This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |