Many bugfixes and improvements

This commit is contained in:
Ziver Koc 2011-06-24 23:20:59 +00:00
parent c3e3bbf787
commit 363e0c6cfc
52 changed files with 2021 additions and 982 deletions

View file

@ -21,7 +21,7 @@ public class Hasher {
* @return a String with the hash
*/
public static String hash(File file, String hashType) throws NoSuchAlgorithmException, IOException {
MessageDigest digest = MessageDigest.getInstance(hashType);//"MD5"
MessageDigest digest = MessageDigest.getInstance(hashType); //"MD5"
InputStream is = new FileInputStream(file);
String output = "";
byte[] buffer = new byte[8192];
@ -72,6 +72,22 @@ public class Hasher {
return null;
}
/**
* Returns the MD5 hash of the given file
*
* @param object is the file to hash
* @return an String containing the hash
*/
public static String MD5(File file) throws IOException{
try {
return hash(file, "MD5");
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
return null;
}
/**
* Returns the SHA-1 hash of the given object
*

View file

@ -7,7 +7,7 @@ package zutil;
* @author Ziver
*
*/
public interface ProgressListener<T> {
public interface ProgressListener<S,D> {
/**
* This method is called when the progress is updated
@ -16,5 +16,5 @@ public interface ProgressListener<T> {
* @param info is some information from the source object
* @param percent is the progress of the object (0-100)
*/
public void progressUpdate(Object source, T info, double percent);
public void progressUpdate(S source, D info, double percent);
}

View file

@ -17,7 +17,6 @@ public class Converter {
*
* @param object the object to convert.
* @return the associated byte array.
* @throws IOException
*/
public static byte[] toBytes(Object object) throws IOException{
ByteArrayOutputStream baos = new ByteArrayOutputStream();
@ -45,7 +44,7 @@ public class Converter {
}
/**
* Converts a Integer to an byte
* Converts a Integer to a byte
*
* @param num is the number to convert
* @return an byte
@ -54,13 +53,53 @@ public class Converter {
return (byte)(num & 0xff);
}
/**
* Converts hex chars to a byte
*
* @param quad1 is the first hex value
* @param quad2 is the second hex value
* @return a byte that corresponds to the hex
*/
public static int hexToByte( char quad1, char quad2){
byte b = hexToByte( quad2 );
b |= hexToByte( quad1 ) << 4;
return toInt(b);
}
/**
* Converts a hex chars to a byte
*
* @param quad1 is the hex value
* @return a byte that corresponds to the hex
*/
public static byte hexToByte( char hex ){
switch( Character.toLowerCase(hex) ){
case '0': return 0x00;
case '1': return 0x01;
case '2': return 0x02;
case '3': return 0x03;
case '4': return 0x04;
case '5': return 0x05;
case '6': return 0x06;
case '7': return 0x07;
case '8': return 0x08;
case '9': return 0x09;
case 'a': return 0x0a;
case 'b': return 0x0b;
case 'c': return 0x0c;
case 'd': return 0x0d;
case 'e': return 0x0e;
case 'f': return 0x0f;
}
return (byte)0;
}
/**
* Converts an array of bytes back to its constituent object. The
* input array is assumed to have been created from the original object.
*
* @param bytes the byte array to convert.
* @return the associated object.
* @throws Exception
*/
public static Object toObject(byte[] bytes) throws Exception{
Object object = null;
@ -78,7 +117,6 @@ public class Converter {
*
* @param bytes the byte array to convert.
* @return the associated object.
* @throws Exception
*/
public static Object toObject(DynamicByteArrayStream bytes) throws Exception{
Object object = null;
@ -233,6 +271,16 @@ public class Converter {
return ret;
}
/**
* Converts a byte to a integer
*
* @param num is the byte to convert
* @return an integer
*/
public static int toInt(byte b){
return (int)(b & 0xff);
}
/**
* Converts a Integer to a BitSet
*
@ -283,4 +331,40 @@ public class Converter {
}
return null;
}
/**
* Replaces reserved and unsafe characters in URLs with hex values
*/
public static String urlEncode( String str ){
StringBuilder out = new StringBuilder();
for( char c : str.toCharArray() ){
if( c>='0' && c<='9' || c>='A' && c<='Z' || c>='a' && c<='z' ||
c=='$' || c=='-' || c=='_' || c=='.' || c=='+' || c=='!' ||
c=='*' || c=='\'' || c=='(' || c==')' || c==',' )
out.append( c );
else{
out.append( '%' ).append( toHexString((byte)c) );
}
}
return out.toString();
}
/**
* Replaces hex values from a URL with the proper characters
*/
public static String urlDecode( String str ){
StringBuilder out = new StringBuilder();
char[] array = str.toCharArray();
for( int i=0; i<array.length ;i++ ){
char c = array[i];
if( c == '%' && i+2<array.length ){
out.append( (char)hexToByte( array[++i], array[++i]) );
}
else
out.append( c );
}
return out.toString();
}
}

View file

@ -13,7 +13,7 @@ import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.sql.DataSource;
import zutil.db.handler.SimpleResultHandler;
import zutil.db.handler.SimpleSQLHandler;
import zutil.log.LogUtil;
public class DBConnection{
@ -93,7 +93,7 @@ public class DBConnection{
*/
public Object getLastInsertID(){
try{
return exec("SELECT LAST_INSERT_ID()", new SimpleResultHandler<Object>());
return exec("SELECT LAST_INSERT_ID()", new SimpleSQLHandler<Object>());
}catch(SQLException e){
logger.log(Level.WARNING, null, e);
}

View file

@ -25,7 +25,7 @@ import zutil.log.LogUtil;
* <XMP>
* The class that extends this will be able to save its state to a DB.
* Fields that are transient will be ignored, and fields that extend
* DBBean will be replaced by the id field of that class.
* DBBean will be replaced with the id field of that class in the database.
*
* Supported fields:
* *Boolean
@ -54,8 +54,10 @@ public abstract class DBBean {
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface DBTable {
/** This is the name of the table, SQL rules apply, No " or whitespace **/
/** This is the name of the table, SQL rules apply should not contain any strange characters or spaces **/
String value();
/** Change the id column name of the bean, default column name is "id", SQL rules apply should not contain any strange characters or spaces **/
String idColumn() default "id";
/** Sets if the fields in the super classes is also part of the bean **/
boolean superBean() default false;
}
@ -66,11 +68,11 @@ public abstract class DBBean {
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface DBLinkTable {
/** The name of the Link table, should not contain any strange characters or spaces */
String name();
/** The name of the Link table, SQL rules apply should not contain any strange characters or spaces */
String table();
/** The class of the linked bean */
Class<? extends DBBean> beanClass();
/** The name of the column that contains the main objects id */
/** The name of the column that contains the main objects id, SQL rules apply should not contain any strange characters or spaces */
String idColumn() default "";
}
@ -78,9 +80,11 @@ public abstract class DBBean {
* A Class that contains information about a bean
*/
protected static class DBBeanConfig{
/** The name of the table in the DB */
/** The name of the table in the DB **/
protected String tableName;
/** All the fields in the bean */
/** The name of the id column **/
protected String idColumn;
/** All the fields in the bean **/
protected ArrayList<Field> fields;
protected DBBeanConfig(){
@ -128,8 +132,14 @@ public abstract class DBBean {
DBBeanConfig config = new DBBeanConfig();
// Find the table name
DBTable tableAnn = c.getAnnotation(DBTable.class);
if( tableAnn != null )
config.tableName = tableAnn.value().replace('\"', '_');
if( tableAnn != null ){
config.tableName = tableAnn.value();
config.idColumn = tableAnn.idColumn();
}
else{
config.tableName = c.getSimpleName();
config.idColumn = "id";
}
// Add the fields in the bean and all the super classes fields
for(Class<?> cc = c; cc != DBBean.class ;cc = cc.getSuperclass()){
Field[] fields = cc.getDeclaredFields();
@ -196,7 +206,7 @@ public abstract class DBBean {
query.append( " SET" );
query.append( params );
if( id != null )
query.append( " WHERE id=?" );
query.append(" WHERE ").append(config.idColumn).append("=?");
}
logger.finest("Save query("+c.getName()+" id:"+this.getId()+"): "+query.toString());
PreparedStatement stmt = db.getPreparedStatement( query.toString() );
@ -243,7 +253,7 @@ public abstract class DBBean {
List<DBBean> list = (List<DBBean>)getFieldValue(field);
if( list != null ){
DBLinkTable linkTable = field.getAnnotation( DBLinkTable.class );
String subtable = linkTable.name();
String subtable = linkTable.table();
String idcol = (linkTable.idColumn().isEmpty() ? config.tableName : linkTable.idColumn() );
String sub_idcol = "id";
@ -257,8 +267,10 @@ public abstract class DBBean {
continue;
}
// Get the Sub object configuration
if(subConfig == null)
if(subConfig == null){
subConfig = getBeanConfig( subobj.getClass() );
sub_idcol = subConfig.idColumn;
}
// Save links in link table
String subsql = "";
if( subtable.equals(subConfig.tableName) )
@ -294,7 +306,7 @@ public abstract class DBBean {
if( this.getId() == null )
throw new NoSuchElementException("ID field is null( Has the bean been saved?)!");
String sql = "DELETE FROM "+config.tableName+" WHERE id=?";
String sql = "DELETE FROM "+config.tableName+" WHERE "+config.idColumn+"=?";
logger.fine("Delete query("+c.getName()+" id:"+this.getId()+"): "+sql);
PreparedStatement stmt = db.getPreparedStatement( sql );
// Put in the variables in the SQL
@ -336,7 +348,7 @@ public abstract class DBBean {
// Initiate a BeanConfig if there is non
DBBeanConfig config = getBeanConfig( c );
// Generate query
String sql = "SELECT * FROM "+config.tableName+" WHERE id=? LIMIT 1";
String sql = "SELECT * FROM "+config.tableName+" WHERE "+config.idColumn+"=? LIMIT 1";
logger.fine("Load query("+c.getName()+" id:"+id+"): "+sql);
PreparedStatement stmt = db.getPreparedStatement( sql );
stmt.setObject(1, id );
@ -357,7 +369,7 @@ public abstract class DBBean {
query.append("CREATE TABLE "+config.tableName+" ( ");
// ID
query.append(" id ");
query.append(" ").append(config.idColumn).append(" ");
query.append( classToDBName( Long.class ) );
query.append(" PRIMARY KEY AUTO_INCREMENT, ");
@ -424,7 +436,10 @@ public abstract class DBBean {
*/
protected void setFieldValue(Field field, Object o){
try {
if( !Modifier.isPublic( field.getModifiers()))
field.setAccessible(true);
// Set basic datatype
if( o == null && !Object.class.isAssignableFrom( field.getType() ) ){
logger.fine("Trying to set primitive data type to null!");
if( field.getType() == Integer.TYPE ) field.setInt(this, 0);
@ -449,4 +464,9 @@ public abstract class DBBean {
public Long getId(){
return id;
}
/**
* Will be called whenever the bean has been updated from the database.
*/
protected void updatePerformed(){}
}

View file

@ -95,7 +95,7 @@ public class DBBeanSQLResultHandler<T> implements SQLResultHandler<T>{
}
/**
* Is called to handle an result from an query.
* Is called to handle a result from a query.
*
* @param stmt is the query
* @param result is the ResultSet
@ -179,13 +179,13 @@ public class DBBeanSQLResultHandler<T> implements SQLResultHandler<T>{
if(db != null){
DBLinkTable linkTable = field.getAnnotation( DBLinkTable.class );
DBBeanConfig subConfig = DBBean.getBeanConfig( linkTable.beanClass() );
String linkTableName = linkTable.name();
String linkTableName = linkTable.table();
String subTable = subConfig.tableName;
String idcol = (linkTable.idColumn().isEmpty() ? bean_config.tableName : linkTable.idColumn() );
// Load list from link table
//String subsql = "SELECT * FROM "+linkTableName+" NATURAL JOIN "+subConfig.tableName+" WHERE "+idcol+"=?";
String subsql = "SELECT obj.* FROM "+linkTableName+" as link, "+subTable+" as obj WHERE obj."+idcol+"=? AND obj.id=link.id";
String subsql = "SELECT obj.* FROM "+linkTableName+" as link, "+subTable+" as obj WHERE obj."+idcol+"=? AND obj."+bean_config.idColumn+"=link.id";
logger.finest("List Load Query: "+subsql);
PreparedStatement subStmt = db.getPreparedStatement( subsql );
subStmt.setObject(1, obj.getId() );
@ -203,6 +203,8 @@ public class DBBeanSQLResultHandler<T> implements SQLResultHandler<T>{
} finally{
obj.processing_update = false;
}
obj.updatePerformed();
}
/**

View file

@ -0,0 +1,45 @@
package zutil.db.handler;
import java.sql.SQLException;
import java.sql.Statement;
import java.sql.ResultSet;
import java.util.Properties;
import zutil.db.SQLResultHandler;
/**
* Adds the result of the query to a Properties object,
*
* The handler sets the first column of the result as
* the key and the second column as the value
*
* @author Ziver
*/
public class PropertiesSQLHandler implements SQLResultHandler<Properties> {
private Properties prop;
/**
* Creates a new Properties object to be filled
*/
public PropertiesSQLHandler(){
this.prop = new Properties();
}
/**
* Adds data to a existing Properties object
*/
public PropertiesSQLHandler(Properties p){
this.prop = p;
}
/**
* Is called to handle an result from an query.
*/
public Properties handleQueryResult(Statement stmt, ResultSet result) throws SQLException{
while( result.next() )
prop.setProperty(result.getString(0), result.getString(1));
return prop;
}
}

View file

@ -11,7 +11,7 @@ import zutil.db.SQLResultHandler;
*
* @author Ziver
*/
public class SimpleResultHandler<T> implements SQLResultHandler<T> {
public class SimpleSQLHandler<T> implements SQLResultHandler<T> {
/**
* Is called to handle an result from an query.
*

View file

@ -14,7 +14,7 @@ import zutil.ProgressListener;
*/
public abstract class ImageFilterProcessor {
private BufferedImage img;
private ProgressListener<?> progress;
private ProgressListener<ImageFilterProcessor,?> progress;
public ImageFilterProcessor(BufferedImage img){
this.img = img;
@ -24,14 +24,14 @@ public abstract class ImageFilterProcessor {
* Sets the listener
* @param listener is the listener, null to disable the progress
*/
public void setProgressListener(ProgressListener<?> listener){
public void setProgressListener(ProgressListener<ImageFilterProcessor,?> listener){
this.progress = listener;
}
/**
* Returns the listener
*/
public ProgressListener<?> getProgressListener(){
public ProgressListener<?,?> getProgressListener(){
return this.progress;
}
@ -59,7 +59,6 @@ public abstract class ImageFilterProcessor {
* Adds the chosen effect to the image
*
* @return The Image with the effect
* @throws InterruptedException
*/
public BufferedImage process() throws InterruptedException{
int cols = img.getWidth();
@ -78,18 +77,17 @@ public abstract class ImageFilterProcessor {
}
/**
* Creates a Integer array with the pixel data of the image
* Creates a Integer array with the pixel data of the image <XMP>
* int[row][col][4]
* 0 -> Alpha data
* Red data
* Green data
* 4 -> Blue data
* 4 -> Blue data </XMP>
*
* @param img is the image to convert
* @param cols is the columns of the image
* @param rows is the rows of the image
* @return A is the integer array
* @throws InterruptedException
*/
public static int[][][] convertToArray(BufferedImage img, int cols, int rows) throws InterruptedException{
int[][][] data = new int[rows][cols][4];
@ -156,6 +154,7 @@ public abstract class ImageFilterProcessor {
/**
* Runs the image thru the processor
*
* @param data is the raw image to apply the effect to. This will NOT be altered
*/
public int[][][] process(int[][][] data){

View file

@ -41,7 +41,8 @@ public class BoundaryBufferedInputStream extends FilterInputStream{
*/
public BoundaryBufferedInputStream(InputStream in, int buf_size){
super(in);
reset();
buf_end = 0;
buf_pos = 0;
buffer = new byte[buf_size];
}
@ -64,29 +65,19 @@ public class BoundaryBufferedInputStream extends FilterInputStream{
return n+leftover;
}
/**
* Resets the buffer
*
* @throws IOException
*/
public synchronized void reset(){
buf_end = 0;
buf_pos = 0;
}
/**
* @return the next byte in the buffer
*/
public final int read() throws IOException{
if(buf_pos >= buf_end) {
if(buf_pos >= buf_end-boundary.length) {
if(fillBuffer() < 0)
return -1;
}
if(buf_end == 0) {
return -1;
} else {
buf_pos++;
return buffer[buf_pos-1];
return buffer[buf_pos++];
}
}
@ -94,7 +85,7 @@ public class BoundaryBufferedInputStream extends FilterInputStream{
* Fills the given array with data from the buffer
*
* @param b is the array that will be filled
* @return the amount of bytes read or -1 if eof
* @return the amount of bytes read or -1 if EOF
*/
public int read(byte b[]) throws IOException {
return read(b, 0, b.length);
@ -106,10 +97,10 @@ public class BoundaryBufferedInputStream extends FilterInputStream{
* @param b is the array that will be filled
* @param off is the offset in the array
* @param len is the amount to read
* @return the amount of bytes read or -1 if eof
* @return the amount of bytes read or -1 if EOF
*/
public int read(byte b[], int off, int len) throws IOException {
if(buf_pos >= buf_end) {
if(buf_pos >= buf_end-boundary.length) {
if(fillBuffer() < 0)
return -1; // EOF
}
@ -129,6 +120,13 @@ public class BoundaryBufferedInputStream extends FilterInputStream{
return leftover;
}
/**
* TODO: Skips over the boundary
*/
public void next(){
}
/**
* @param n the number of bytes to be skipped.
* @return the actual number of bytes skipped.
@ -142,6 +140,21 @@ public class BoundaryBufferedInputStream extends FilterInputStream{
return buf_pos += n;
}
/**
* Sets the boundary for the stream
*/
public void setBoundary(String b){
this.boundary = b.getBytes();
}
/**
* Sets the boundary for the stream
*/
public void setBoundary(byte[] b){
boundary = new byte[b.length];
System.arraycopy(b, 0, boundary, 0, b.length);
}
/**
* @return an estimate of the number of bytes that can be read (or skipped
* over) from this input stream without blocking.
@ -152,7 +165,10 @@ public class BoundaryBufferedInputStream extends FilterInputStream{
}
/**
* Unimplemented
* Tests if this input stream supports the mark and
* reset methods.
*/
public synchronized void mark(int readlimit) {}
public boolean markSupported(){
return false;
}
}

View file

@ -0,0 +1,108 @@
package zutil.io;
import java.io.InputStream;
/**
* This class saves all the input data in to an StringBuffer
*
* @author Ziver
*
*/
public class StringInputStream extends InputStream{
// The buffer
protected StringBuilder buffer;
/**
* Creates an new instance of this class
*/
public StringInputStream(){
clear();
}
/**
* Returns an estimate of the number of bytes
* that can be read (or skipped over) from this
* input stream without blocking by the next
* invocation of a method for this input stream.
*/
public int available(){
return buffer.length();
}
/**
* Reads the next byte of data from the input stream.
*/
public int read(){
int ret = Character.getNumericValue( buffer.charAt( 0 ));
buffer.deleteCharAt( 0 );
return ret;
}
/**
* Reads some number of bytes from the input stream
* and stores them into the buffer array b.
*/
public int read(byte[] b){
return read( b, 0, b.length );
}
/**
* Reads up to len bytes of data from the input stream
* into an array of bytes.
*/
public int read(byte[] b, int off, int len){
if( buffer.length() < len ){
len = buffer.length();
}
char[] ctmp = new char[len];
buffer.getChars(0, len, ctmp, 0);
byte[] btmp = new String( ctmp ).getBytes();
System.arraycopy(btmp, 0, b, off, len);
return len;
}
/**
* Skips over and discards n bytes of data from this
* input stream.
*
* @param n is the amount characters to skip
*/
public long skip(long n){
if( buffer.length() < n ){
int len = buffer.length();
buffer.delete(0, len);
return len;
}
else{
buffer.delete(0, (int) n);
return n;
}
}
/**
* Tests if this input stream supports the mark and
* reset methods.
*/
public boolean markSupported(){
return false;
}
/**
* Closes this input stream and releases any system
* resources associated with the stream.
*/
public void close(){
clear();
}
public void clear(){
buffer = new StringBuilder();
}
public void add( String data ){
buffer.append( data );
}
}

View file

@ -10,10 +10,12 @@ import java.net.URL;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.logging.Logger;
import java.util.regex.Matcher;
import zutil.io.IOUtil;
import zutil.io.MultiPrintStream;
import zutil.log.LogUtil;
/**
* File path utilities
@ -21,6 +23,7 @@ import zutil.io.MultiPrintStream;
* @author Ziver
*/
public class FileUtil {
public static final Logger logger = LogUtil.getLogger();
/**
* Returns a String with a relative path from the given path
@ -30,6 +33,8 @@ public class FileUtil {
* @return A String with a relative path
*/
public static String relativePath(File file, String path){
if( file == null || path == null )
return null;
String absolute = file.getAbsolutePath();
String tmpPath = path.replaceAll(
"[/\\\\]",
@ -231,10 +236,11 @@ public class FileUtil {
for(int i=0; i<temp.length ;i++){
file = new File(dir.getPath()+File.separator+temp[i]);
if(file.isDirectory()){
logger.finer("Found Folder: "+file);
search(new File(dir.getPath()+File.separator+temp[i]+File.separator), fileList, folders, recurse);
}
else if(file.isFile()){
MultiPrintStream.out.println("File Found: "+file);
logger.finer("Found File: "+file);
fileList.add(file);
}
}

View file

@ -33,9 +33,9 @@ import zutil.StringUtil;
import zutil.io.file.FileUtil;
import zutil.jee.upload.FileUploadListener.Status;
import zutil.log.LogUtil;
import zutil.parser.json.JSONNode;
import zutil.parser.DataNode;
import zutil.parser.DataNode.DataType;
import zutil.parser.json.JSONWriter;
import zutil.parser.json.JSONNode.JSONType;
/**
* <XMP>
@ -139,7 +139,7 @@ public abstract class AjaxFileUpload extends HttpServlet {
}
// Generate JSON
JSONNode root = new JSONNode( JSONType.List );
DataNode root = new DataNode( DataType.List );
Iterator<FileUploadListener> it = list.iterator();
while( it.hasNext() ) {
FileUploadListener listener = it.next();

View file

@ -3,8 +3,8 @@ package zutil.jee.upload;
import org.apache.commons.fileupload.ProgressListener;
import zutil.StringUtil;
import zutil.parser.json.JSONNode;
import zutil.parser.json.JSONNode.JSONType;
import zutil.parser.DataNode;
import zutil.parser.DataNode.DataType;
/**
@ -121,18 +121,18 @@ public class FileUploadListener implements ProgressListener{
return (int)((100 * bytes) / length);
}
public JSONNode getJSON() {
JSONNode node = new JSONNode( JSONType.Map );
node.add("id", id);
public DataNode getJSON() {
DataNode node = new DataNode( DataType.Map );
node.set("id", id);
node.add("status", status.toString());
node.add("message", message.replaceAll("\"", "\\\"") );
node.add("filename", filename);
node.add("percent", getPercentComplete());
node.set("status", status.toString());
node.set("message", message.replaceAll("\"", "\\\"") );
node.set("filename", filename);
node.set("percent", getPercentComplete());
node.add("uploaded", StringUtil.formatBytesToString( bytes ));
node.add("total", StringUtil.formatBytesToString( length ));
node.add("speed", StringUtil.formatBytesToString( speed )+"/s");
node.set("uploaded", StringUtil.formatBytesToString( bytes ));
node.set("total", StringUtil.formatBytesToString( length ));
node.set("speed", StringUtil.formatBytesToString( speed )+"/s");
return node;
}
}

View file

@ -1,5 +1,6 @@
package zutil.log;
import java.io.PrintStream;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
@ -7,13 +8,15 @@ import java.util.logging.Formatter;
import java.util.logging.LogRecord;
import java.util.regex.Pattern;
import zutil.io.StringOutputStream;
public class CompactLogFormatter extends Formatter{
// The split pattern where the
private static final Pattern splitter = Pattern.compile("\n");
// the stream should print time stamp
private boolean timeStamp = true;
//The time stamp style
private SimpleDateFormat dateFormatter = new SimpleDateFormat("HH:mm:ss ");
private SimpleDateFormat dateFormatter = new SimpleDateFormat();
// If displaying class names are enabled
private boolean className = true;
// If displaying method names are enabled
@ -32,17 +35,19 @@ public class CompactLogFormatter extends Formatter{
if( timeStamp ){
date.setTime( record.getMillis() );
data.append( dateFormatter.format(date) );
data.append(' ');
}
switch( record.getLevel().intValue() ){
case /* SEVERE */ 1000: data.append("SEVERE "); break;
case /* WARNING */ 900 : data.append("WARNING "); break;
case /* INFO */ 800 : data.append("INFO "); break;
case /* CONFIG */ 700 : data.append("CONFIG "); break;
case /* FINE */ 500 : data.append("FINE "); break;
case /* FINER */ 400 : data.append("FINER "); break;
case /* FINEST */ 300 : data.append("FINEST "); break;
case /* SEVERE */ 1000: data.append("[SEVERE] "); break;
case /* WARNING */ 900 : data.append("[WARNING]"); break;
case /* INFO */ 800 : data.append("[INFO] "); break;
case /* CONFIG */ 700 : data.append("[CONFIG] "); break;
case /* FINE */ 500 : data.append("[FINE] "); break;
case /* FINER */ 400 : data.append("[FINER] "); break;
case /* FINEST */ 300 : data.append("[FINEST] "); break;
}
data.append(' ');
if( className ){
data.append( paddClassName(record.getSourceClassName()) );
@ -53,6 +58,7 @@ public class CompactLogFormatter extends Formatter{
data.append( ": " );
StringBuffer ret = new StringBuffer();
if( record.getMessage() != null ){
String[] array = splitter.split( record.getMessage() );
for( int i=0; i<array.length ;++i ){
if( i!=0 )
@ -61,7 +67,21 @@ public class CompactLogFormatter extends Formatter{
ret.append( data );
ret.append( array[i] );
}
}
ret.append( '\n' );
if( record.getThrown() != null ){
StringOutputStream out = new StringOutputStream();
record.getThrown().printStackTrace(new PrintStream(out));
String[] array = splitter.split( out.toString() );
for( int i=0; i<array.length ;++i ){
if( i!=0 )
ret.append( '\n' );
if( data.length() > 0 )
ret.append( data );
ret.append( array[i] );
}
ret.append( '\n' );
}
return ret.toString();
}

View file

@ -52,6 +52,18 @@ public class LogUtil {
}
}
/**
* Adds the log formatter
*
* @param f is the formatter class
*/
public static void setFormatter(String name, Formatter f){
Logger root = Logger.getLogger(name);
for (Handler handler : root.getHandlers()) {
handler.setFormatter(f);
}
}
/**
* Sets the global log level
*/

View file

@ -1,134 +0,0 @@
package zutil.net;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.Socket;
import java.util.ArrayList;
import zutil.ProgressListener;
import zutil.io.MultiPrintStream;
import zutil.io.file.FileUtil;
/**
* This class connects to a update server and updates a path
* with the servers
*
* @author Ziver
*
*/
public class UpdateClient{
private ArrayList<FileHash> clientFileList;
private Socket socket;
private String path;
private ProgressListener progress;
private int speed;
private long totalReceived;
/**
* Creates a UpdateClient
*
* @param address Address to the UpdateServer
* @param port The port on the server
* @param path Path to the files to update
* @throws Exception
*/
public UpdateClient(String address, int port, String path) throws Exception{
clientFileList = UpdateServer.getFileList(path);
socket = new Socket(address, port);
this.path = path;
}
public void setProgressListener(ProgressListener p){
progress = p;
}
/**
* Updates the files
*
* @throws Exception
*/
public void update() throws Exception{
ObjectOutputStream out = new ObjectOutputStream(socket.getOutputStream());
ObjectInputStream in = new ObjectInputStream(socket.getInputStream());
// send client file list
out.writeObject(clientFileList);
out.flush();
// receive file updates
FileHash fileInfo = (FileHash)in.readObject();
File tmpPath = FileUtil.find(path);
while(!fileInfo.path.isEmpty()){
MultiPrintStream.out.println("Updating: "+path+fileInfo.path);
// reading new file data
File file = new File(tmpPath.getAbsolutePath()+fileInfo.path);
File tmpFile = File.createTempFile(file.getName(), ".tmp", tmpPath);
tmpFile.getParentFile().mkdirs();
tmpFile.deleteOnExit();
FileOutputStream fileOut = new FileOutputStream(tmpFile);
byte[] buffer = new byte[socket.getReceiveBufferSize()];
int bytesReceived = 0;
totalReceived = 0;
long time = System.currentTimeMillis();
long timeTotalRecived = 0;
while((bytesReceived = in.read(buffer)) > 0) {
fileOut.write(buffer, 0, bytesReceived);
if(time+1000 < System.currentTimeMillis()){
time = System.currentTimeMillis();
speed = (int)(totalReceived - timeTotalRecived);
timeTotalRecived = totalReceived;
}
totalReceived += bytesReceived;
if(progress != null) progress.progressUpdate(this, fileInfo, (double)totalReceived/fileInfo.size*100);
}
fileOut.close();
speed = 0;
// delete old file and replace whit new
file.delete();
if(!tmpFile.renameTo(file)){
throw new Exception("Cannot update file: "+file.getAbsolutePath());
}
// read new message
fileInfo = (FileHash)in.readObject();
}
MultiPrintStream.out.println("Update Done!!");
}
/**
* Returns the speed of the transfer
*
* @return The speed in bytes/s
*/
public int speed(){
return speed;
}
/**
* Returns the total amount of data received for the
* current file
*
* @return The speed in bytes/s
*/
public long totalReceived(){
return totalReceived;
}
/**
* Closes the connection
*
* @throws IOException
*/
public void close() throws IOException{
socket.close();
}
}

View file

@ -1,166 +0,0 @@
package zutil.net;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.URISyntaxException;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.List;
import zutil.Hasher;
import zutil.io.MultiPrintStream;
import zutil.io.file.FileUtil;
public class UpdateServer extends Thread{
private ArrayList<FileHash> fileList;
private ServerSocket server;
private boolean close;
private String path;
/**
* Creates a UpdateServer Thread
*
* @param path The path to sync the clients with
* @throws IOException
* @throws URISyntaxException
* @throws NoSuchAlgorithmException
*/
public UpdateServer(int port, String path) throws Exception{
fileList = getFileList(path);
server = new ServerSocket(port);
close = false;
this.path = path;
this.start();
MultiPrintStream.out.println("Update Server Online!!!");
}
public void run(){
while (!close){
try {
new UpdateServerThread(server.accept()).start();
MultiPrintStream.out.println("Update Server: Client Connected!!!");
} catch (IOException e) {
e.printStackTrace();
}
}
}
/**
* Handles all the connecting clients
*
* @author Ziver
*/
class UpdateServerThread extends Thread{
private ObjectOutputStream out;
private ObjectInputStream in;
private Socket client;
/**
* Creates a UpdateServerThread
* @param client The socket to the client
* @throws IOException
*/
public UpdateServerThread(Socket c) throws IOException {
client = c;
out = new ObjectOutputStream(client.getOutputStream());
in = new ObjectInputStream(client.getInputStream());
}
@SuppressWarnings("unchecked")
public void run(){
try {
// receive the clients filelist
ArrayList<FileHash> clientFileList = (ArrayList<FileHash>)in.readObject();
File tmpPath = FileUtil.find(path);
for(FileHash file : fileList){
if(!clientFileList.contains(file)){
// send new file to client
out.writeObject(file);
out.flush();
// send file data
FileInputStream input = new FileInputStream(tmpPath.getAbsolutePath()+file.path);
byte[] nextBytes = new byte[client.getSendBufferSize()];
int bytesRead = 0;
while((bytesRead = input.read(nextBytes)) > 0){
out.write(nextBytes,0,bytesRead);
}
}
}
// send update done message
out.writeObject(new FileHash("","",0));
out.flush();
out.close();
in.close();
client.close();
} catch (Exception e) {
MultiPrintStream.out.println("Update Server: Client Error!!! "+e.getMessage());
} finally {
MultiPrintStream.out.println("Update Server: Client Update Done!!!");
}
}
}
/**
* Returns a ArrayList with all the files in the specified folder and there
* MD5 hashes
*
* @param path The path to search
* @return A ArrayList with all the files in the path
* @throws URISyntaxException
* @throws NoSuchAlgorithmException
* @throws IOException
*/
public static ArrayList<FileHash> getFileList(String path) throws Exception{
ArrayList<FileHash> fileHash = new ArrayList<FileHash>();
List<File> files = FileUtil.search(FileUtil.find(path));
for(File file : files){
fileHash.add(new FileHash(
FileUtil.relativePath(file, path),
Hasher.hash(file, "MD5"),
file.length()));
}
return fileHash;
}
}
/**
* This class is used to store the files
* and there hashes
*
* @author Ziver
*/
class FileHash implements Serializable{
private static final long serialVersionUID = 1L;
public String path;
public String hash;
public long size;
public FileHash(String p, String h, long s){
path = p;
hash = h;
size = s;
}
public boolean equals(Object comp){
FileHash tmp = (FileHash)comp;
return path.equals(tmp.path) && hash.equals(tmp.hash);
}
public String toString(){
return path;
}
}

View file

@ -1,232 +0,0 @@
/*
* Zupdater.java
*
* Created on den 27 juli 2008, 23:32
*/
package zutil.net;
import java.awt.Dimension;
import zutil.ProgressListener;
import zutil.StringUtil;
/**
*
* @author Ziver
*/
public class Zupdater extends javax.swing.JFrame implements ProgressListener{
private static final long serialVersionUID = 1L;
/** Creates new form Zupdater */
public Zupdater() {
super("Zupdater");
initComponents();
centerScreen();
setVisible(true);
}
public void centerScreen(){
Dimension screen = getToolkit().getScreenSize();
this.setBounds(
(screen.width-getWidth())/2,
(screen.height-getHeight())/2,
getWidth(),
getHeight() );
}
public void progressUpdate(Object source, Object info, double percent) {
if(info instanceof FileHash){
FileHash fileHash = (FileHash) info;
fileLabel.setText(fileHash.toString());
fileProgressBar.setValue((int)percent);
percentLabel.setText((int)percent+"%");
speedLabel.setText(StringUtil.formatBytesToString(((UpdateClient)source).speed())+"/s");
transferedLabel.setText(StringUtil.formatBytesToString(((UpdateClient)source).totalReceived())+
" / "+StringUtil.formatBytesToString(fileHash.size));
}
}
/** This method is called from within the constructor to
* initialize the form.
* WARNING: Do NOT modify this code. The content of this method is
* always regenerated by the Form Editor.
*/
// <editor-fold defaultstate="collapsed" desc="Generated Code">
private void initComponents() {
jSeparator1 = new javax.swing.JSeparator();
cancelButton = new javax.swing.JButton();
jPanel1 = new javax.swing.JPanel();
jLabel1 = new javax.swing.JLabel();
totalProgressBar = new javax.swing.JProgressBar();
jLabel2 = new javax.swing.JLabel();
fileProgressBar = new javax.swing.JProgressBar();
fileLabel = new javax.swing.JLabel();
totalProgressLabel = new javax.swing.JLabel();
speedLabel = new javax.swing.JLabel();
percentLabel = new javax.swing.JLabel();
transferedLabel = new javax.swing.JLabel();
etaLabel = new javax.swing.JLabel();
jLabel3 = new javax.swing.JLabel();
setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
cancelButton.setText("Cancel");
cancelButton.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
cancel();
}
});
jPanel1.setBorder(javax.swing.BorderFactory.createTitledBorder("Update"));
jLabel1.setFont(new java.awt.Font("Tahoma", 1, 11));
jLabel1.setText("Total Progress:");
totalProgressBar.setIndeterminate(true);
jLabel2.setFont(new java.awt.Font("Tahoma", 1, 11));
jLabel2.setText("File: ");
fileLabel.setFont(new java.awt.Font("Tahoma", 0, 11));
fileLabel.setText("file");
totalProgressLabel.setFont(new java.awt.Font("Tahoma", 0, 11));
totalProgressLabel.setText("totalProgress");
speedLabel.setFont(new java.awt.Font("Tahoma", 1, 11));
speedLabel.setHorizontalAlignment(javax.swing.SwingConstants.RIGHT);
speedLabel.setText("speed");
percentLabel.setFont(new java.awt.Font("Tahoma", 1, 11));
percentLabel.setHorizontalAlignment(javax.swing.SwingConstants.CENTER);
percentLabel.setText("0%");
transferedLabel.setFont(new java.awt.Font("Tahoma", 2, 11));
transferedLabel.setHorizontalAlignment(javax.swing.SwingConstants.RIGHT);
transferedLabel.setText("transfer");
etaLabel.setFont(new java.awt.Font("Tahoma", 0, 11));
etaLabel.setHorizontalAlignment(javax.swing.SwingConstants.LEFT);
etaLabel.setText("eta");
jLabel3.setFont(new java.awt.Font("Tahoma", 1, 11));
jLabel3.setText("ETA:");
javax.swing.GroupLayout jPanel1Layout = new javax.swing.GroupLayout(jPanel1);
jPanel1.setLayout(jPanel1Layout);
jPanel1Layout.setHorizontalGroup(
jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(jPanel1Layout.createSequentialGroup()
.addContainerGap()
.addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(jPanel1Layout.createSequentialGroup()
.addComponent(jLabel1)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(totalProgressLabel, javax.swing.GroupLayout.DEFAULT_SIZE, 464, Short.MAX_VALUE))
.addComponent(totalProgressBar, javax.swing.GroupLayout.DEFAULT_SIZE, 555, Short.MAX_VALUE)
.addComponent(fileProgressBar, javax.swing.GroupLayout.DEFAULT_SIZE, 555, Short.MAX_VALUE)
.addGroup(jPanel1Layout.createSequentialGroup()
.addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(jLabel2)
.addComponent(jLabel3))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(jPanel1Layout.createSequentialGroup()
.addComponent(etaLabel, javax.swing.GroupLayout.PREFERRED_SIZE, 175, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(percentLabel, javax.swing.GroupLayout.PREFERRED_SIZE, 130, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(transferedLabel, javax.swing.GroupLayout.DEFAULT_SIZE, 207, Short.MAX_VALUE))
.addGroup(jPanel1Layout.createSequentialGroup()
.addComponent(fileLabel, javax.swing.GroupLayout.PREFERRED_SIZE, 399, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(speedLabel, javax.swing.GroupLayout.DEFAULT_SIZE, 119, Short.MAX_VALUE)))))
.addContainerGap())
);
jPanel1Layout.setVerticalGroup(
jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(jPanel1Layout.createSequentialGroup()
.addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(jLabel1)
.addComponent(totalProgressLabel))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(totalProgressBar, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(jLabel2)
.addComponent(fileLabel)
.addComponent(speedLabel))
.addGap(6, 6, 6)
.addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(jLabel3)
.addComponent(etaLabel)
.addComponent(transferedLabel)
.addComponent(percentLabel))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(fileProgressBar, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
);
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
getContentPane().setLayout(layout);
layout.setHorizontalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addContainerGap()
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(jSeparator1, javax.swing.GroupLayout.DEFAULT_SIZE, 587, Short.MAX_VALUE)
.addComponent(jPanel1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(cancelButton, javax.swing.GroupLayout.Alignment.TRAILING))
.addContainerGap())
);
layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addContainerGap()
.addComponent(jPanel1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(jSeparator1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(cancelButton)
.addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
);
pack();
}// </editor-fold>
public void cancel(){
System.exit(0);
}
/**
* @param args the command line arguments
*/
public static void main(String args[]) {
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
new Zupdater().setVisible(true);
}
});
}
// Variables declaration - do not modify
private javax.swing.JButton cancelButton;
private javax.swing.JLabel etaLabel;
private javax.swing.JLabel fileLabel;
private javax.swing.JProgressBar fileProgressBar;
private javax.swing.JLabel jLabel1;
private javax.swing.JLabel jLabel2;
private javax.swing.JLabel jLabel3;
private javax.swing.JPanel jPanel1;
private javax.swing.JSeparator jSeparator1;
private javax.swing.JLabel percentLabel;
private javax.swing.JLabel speedLabel;
private javax.swing.JProgressBar totalProgressBar;
private javax.swing.JLabel totalProgressLabel;
private javax.swing.JLabel transferedLabel;
// End of variables declaration
}

View file

@ -0,0 +1,98 @@
package zutil.net.http;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.Socket;
import java.net.URL;
import java.util.HashMap;
import zutil.net.http.HttpPrintStream.HttpMessageType;
/**
* This class connects to a HTTP server and
* parses the result
*
* @author Ziver
*/
public class HttpClient {
public static enum HttpRequestType{
GET, POST
}
private HttpURL url;
private HttpRequestType type;
private HashMap<String,String> headers;
private HashMap<String,String> cookies;
public static HttpClient POST(){
return new HttpClient( HttpRequestType.POST );
}
public static HttpClient GET(){
return new HttpClient( HttpRequestType.GET );
}
private HttpClient(HttpRequestType type){
this.type = type;
headers = new HashMap<String,String>();
cookies = new HashMap<String,String>();
}
public void setURL( URL url){
this.url = new HttpURL( url );
}
/**
* Adds a parameter to the request
*/
public void setParameter( String key, String value ){
url.setParameter(key, value);
}
/**
* Adds a cookie to the request
*/
public void setCookie( String key, String value ){
cookies.put(key, value);
}
/**
* Adds a header value to the request
*/
public void setHeader( String key, String value ){
headers.put(key, value);
}
public HttpHeaderParser send() throws IOException{
Socket conn = new Socket( url.getHost(), url.getPort());
// Request
HttpPrintStream request = new HttpPrintStream( conn.getOutputStream(), HttpMessageType.REQUEST );
request.setRequestType( type.toString() );
request.setRequestURL( url.getHttpURL() );
request.setHeaders( headers );
request.setCookies( cookies );
if( type == HttpRequestType.POST ){
String data = url.getParameterString();
request.setHeader("Content-Length", data);
request.println();
request.print( data );
}
else
request.println("");
request.flush();
// Response
BufferedReader in = new BufferedReader(new InputStreamReader(conn.getInputStream()));
HttpHeaderParser response = new HttpHeaderParser( in );
conn.close();
return response;
}
}

View file

@ -6,7 +6,7 @@ import java.util.HashMap;
import java.util.Scanner;
import java.util.regex.Pattern;
public class HTTPHeaderParser {
public class HttpHeaderParser {
// Some Cached regex's
private static final Pattern colonPattern = Pattern.compile(":");
private static final Pattern equalPattern = Pattern.compile("=");
@ -30,7 +30,7 @@ public class HTTPHeaderParser {
* @param in is the stream
* @throws IOException
*/
public HTTPHeaderParser(BufferedReader in) throws IOException{
public HttpHeaderParser(BufferedReader in) throws IOException{
url_attr = new HashMap<String, String>();
headers = new HashMap<String, String>();
cookies = new HashMap<String, String>();
@ -50,7 +50,7 @@ public class HTTPHeaderParser {
*
* @param in is the string
*/
public HTTPHeaderParser(String in){
public HttpHeaderParser(String in){
url_attr = new HashMap<String, String>();
headers = new HashMap<String, String>();
cookies = new HashMap<String, String>();
@ -92,7 +92,7 @@ public class HTTPHeaderParser {
if(index > -1){
url = line.substring(0, index );
line = line.substring( index+1, line.length());
parseUrlAttributes(line, url_attr);
parseURLParameters(line, url_attr);
}
else{
url = line;
@ -108,9 +108,9 @@ public class HTTPHeaderParser {
*
* @param attributes is the String containing all the attributes
*/
public static HashMap<String, String> parseUrlAttributes( String attributes ){
public static HashMap<String, String> parseURLParameters( String attributes ){
HashMap<String, String> map = new HashMap<String, String>();
parseUrlAttributes(attributes, map);
parseURLParameters(attributes, map);
return map;
}
@ -121,7 +121,7 @@ public class HTTPHeaderParser {
* @param attributes is the String containing all the attributes
* @param map is the HashMap to put all the values into
*/
public static void parseUrlAttributes(String attributes, HashMap<String, String> map){
public static void parseURLParameters(String attributes, HashMap<String, String> map){
String[] tmp;
// get the variables
String[] data = andPattern.split( attributes );

View file

@ -13,13 +13,13 @@ import java.util.HashMap;
*/
public class HttpPrintStream extends PrintStream{
// Defines the type of message
public enum HTTPMessageType{
public enum HttpMessageType{
REQUEST,
RESPONSE
}
// This defines the type of message that will be generated
private HTTPMessageType message_type;
private HttpMessageType message_type;
// The status code of the message, ONLY for response
private Integer res_status_code;
// The request type of the message ONLY for request
@ -27,9 +27,9 @@ public class HttpPrintStream extends PrintStream{
// The requesting url ONLY for request
private String req_url;
// An Map of all the header values
private HashMap<String, String> header;
private HashMap<String, String> headers;
// An Map of all the cookies
private HashMap<String, String> cookie;
private HashMap<String, String> cookies;
// The buffered header
private StringBuffer buffer;
// If the header buffering is enabled
@ -42,7 +42,7 @@ public class HttpPrintStream extends PrintStream{
* @param out is the OutputStream to send the message
*/
public HttpPrintStream(OutputStream out) {
this( out, HTTPMessageType.RESPONSE );
this( out, HttpMessageType.RESPONSE );
}
/**
* Creates an new instance of HttpPrintStream with
@ -51,13 +51,13 @@ public class HttpPrintStream extends PrintStream{
* @param out is the OutputStream to send the message
* @param type is the type of message
*/
public HttpPrintStream(OutputStream out, HTTPMessageType type) {
public HttpPrintStream(OutputStream out, HttpMessageType type) {
super(out);
this.message_type = type;
res_status_code = 0;
header = new HashMap<String, String>();
cookie = new HashMap<String, String>();
headers = new HashMap<String, String>();
cookies = new HashMap<String, String>();
buffer = new StringBuffer();
buffer_enabled = false;
}
@ -84,9 +84,9 @@ public class HttpPrintStream extends PrintStream{
* @throws Exception Throws exception if the header has already been sent
*/
public void setCookie(String key, String value) throws RuntimeException{
if(cookie == null)
if(cookies == null)
throw new RuntimeException("Header already sent!!!");
cookie.put(key, value);
cookies.put(key, value);
}
/**
@ -97,9 +97,9 @@ public class HttpPrintStream extends PrintStream{
* @throws Exception Throws exception if the header has already been sent
*/
public void setHeader(String key, String value) throws RuntimeException{
if(header == null)
if(headers == null)
throw new RuntimeException("Header already sent!!!");
header.put(key, value);
headers.put(key, value);
}
/**
@ -111,7 +111,7 @@ public class HttpPrintStream extends PrintStream{
public void setStatusCode(int code) throws RuntimeException{
if( res_status_code == null )
throw new RuntimeException("Header already sent!!!");
if( message_type != HTTPMessageType.RESPONSE )
if( message_type != HttpMessageType.RESPONSE )
throw new RuntimeException("Status Code is only available in HTTP RESPONSE!!!");
res_status_code = code;
}
@ -125,7 +125,7 @@ public class HttpPrintStream extends PrintStream{
public void setRequestType(String req_type) throws RuntimeException{
if( req_type == null )
throw new RuntimeException("Header already sent!!!");
if( message_type != HTTPMessageType.REQUEST )
if( message_type != HttpMessageType.REQUEST )
throw new RuntimeException("Request Message Type is only available in HTTP REQUEST!!!");
this.req_type = req_type;
}
@ -138,11 +138,18 @@ public class HttpPrintStream extends PrintStream{
public void setRequestURL(String req_url) throws RuntimeException{
if( req_url == null )
throw new RuntimeException("Header already sent!!!");
if( message_type != HTTPMessageType.REQUEST )
if( message_type != HttpMessageType.REQUEST )
throw new RuntimeException("Request URL is only available in HTTP REQUEST!!!");
this.req_url = req_url;
}
protected void setHeaders( HashMap<String,String> map ){
headers = map;
}
protected void setCookies( HashMap<String,String> map ){
cookies = map;
}
/**
* Prints with a new line
*/
@ -166,40 +173,40 @@ public class HttpPrintStream extends PrintStream{
}
else{
if(res_status_code != null){
if( message_type==HTTPMessageType.REQUEST )
super.print(req_type+" "+req_url+" HTTP/1.1");
if( message_type==HttpMessageType.REQUEST )
super.print(req_type+" "+req_url+" HTTP/1.0");
else
super.print("HTTP/1.1 "+res_status_code+" "+getStatusString(res_status_code));
super.print("HTTP/1.0 "+res_status_code+" "+getStatusString(res_status_code));
super.println();
res_status_code = null;
req_type = null;
req_url = null;
}
if(header != null){
for(String key : header.keySet()){
super.print(key+": "+header.get(key));
if(headers != null){
for(String key : headers.keySet()){
super.print(key+": "+headers.get(key));
super.println();
}
header = null;
headers = null;
}
if(cookie != null){
if( !cookie.isEmpty() ){
if( message_type==HTTPMessageType.REQUEST ){
if(cookies != null){
if( !cookies.isEmpty() ){
if( message_type==HttpMessageType.REQUEST ){
super.print("Cookie: ");
for(String key : cookie.keySet()){
super.print(key+"="+cookie.get(key)+"; ");
for(String key : cookies.keySet()){
super.print(key+"="+cookies.get(key)+"; ");
}
super.println();
}
else{
for(String key : cookie.keySet()){
super.print("Set-Cookie: "+key+"="+cookie.get(key)+";");
for(String key : cookies.keySet()){
super.print("Set-Cookie: "+key+"="+cookies.get(key)+";");
super.println();
}
}
}
super.println();
cookie = null;
cookies = null;
}
super.print(s);
}
@ -215,7 +222,7 @@ public class HttpPrintStream extends PrintStream{
buffer.delete(0, buffer.length());
buffer_enabled = true;
}
else if(res_status_code != null || header != null || cookie != null){
else if(res_status_code != null || headers != null || cookies != null){
printOrBuffer("");
}
super.flush();

View file

@ -151,7 +151,7 @@ public class HttpServer extends ThreadedTCPNetworkServer{
try {
logger.finer("Reciving Http Request!!!");
HTTPHeaderParser parser = new HTTPHeaderParser(in);
HttpHeaderParser parser = new HttpHeaderParser(in);
logger.finest(parser.toString());
client_info = parser.getHeaders();
request = parser.getURLAttributes();
@ -173,7 +173,7 @@ public class HttpServer extends ThreadedTCPNetworkServer{
tmp = parser.getHeader("Content-Type");
if( tmp.contains("application/x-www-form-urlencoded") ){
// get the variables
HTTPHeaderParser.parseUrlAttributes( tmpb.toString(), request );
HttpHeaderParser.parseURLParameters( tmpb.toString(), request );
}
else if( tmp.contains("application/soap+xml" ) ||
tmp.contains("text/xml") ||

View file

@ -0,0 +1,139 @@
package zutil.net.http;
import java.net.URL;
import java.util.HashMap;
/**
* Handles URLs in the HTTP protocol
*
* @author Ziver
*/
public class HttpURL {
public static final String PROTOCOL_SEPARATOR = "://";
public static final String PORT_SEPARATOR = ":";
public static final String PATH_SEPARATOR = "/";
public static final String PARAMETER_SEPARATOR = "?";
public static final String ANCHOR_SEPARATOR = "#";
private String protocol = "";
private String host = "127.0.0.1";
private int port = -1;
private String path;
private String anchor;
private HashMap<String,String> parameters = new HashMap<String,String>();
public HttpURL(){}
public HttpURL( URL url ){
this.setProtocol( url.getProtocol() );
this.setHost( url.getHost() );
this.setPort( url.getPort() );
this.setPath( url.getPath() );
}
public String getProtocol( ){
return protocol;
}
public String getHost( ){
return host;
}
public int getPort( ){
return port;
}
public String getPath( ){
return path;
}
public String getAnchor( ){
return anchor;
}
public void setProtocol( String prot ){
this.protocol = prot;
}
public void setHost( String host ){
this.host = host;
}
public void setPort( int port ){
this.port = port;
}
public void setPath( String path ){
if( path.length() >= 1 && !path.startsWith(PATH_SEPARATOR))
path = PATH_SEPARATOR + path;
this.path = path;
}
public void setAnchor( String anch ){
this.anchor = anch;
}
public void setParameter( String key, String value ){
this.parameters.put(key, value);
}
protected void setParameters( HashMap<String,String> pars ){
this.parameters = pars;
}
/**
* Generates the parameter string in a URL.
*
* e.g.
* "key=value&key2=value&..."
*/
public String getParameterString(){
StringBuilder param = new StringBuilder();
for(String key : parameters.keySet()){
param.append(key);
param.append('=');
param.append( parameters.get(key) );
param.append('&');
}
if( param.length() > 0 )
param.deleteCharAt( param.length()-1 );
return param.toString();
}
/**
* Generates a path that are used in the HTTP header
*/
public String getHttpURL(){
StringBuilder url = new StringBuilder();
url.append( path );
if( !parameters.isEmpty() )
url.append( PARAMETER_SEPARATOR ).append( getParameterString() );
return url.toString();
}
/**
* Generates a full URL
*/
public String getURL(){
return toString();
}
/**
* Generates the whole URL
*/
public String toString(){
StringBuilder url = new StringBuilder();
url.append( protocol );
url.append( PROTOCOL_SEPARATOR );
url.append( host );
if( port > 0 )
url.append( PORT_SEPARATOR ).append( port );
if( path != null )
url.append( path );
else
url.append( PATH_SEPARATOR );
if( !parameters.isEmpty() )
url.append( PARAMETER_SEPARATOR ).append( getParameterString() );
if( anchor != null )
url.append( ANCHOR_SEPARATOR ).append( anchor );
return url.toString();
}
}

View file

@ -13,7 +13,7 @@ import java.util.List;
import javax.servlet.http.HttpServletRequest;
import zutil.ProgressListener;
import zutil.net.http.HTTPHeaderParser;
import zutil.net.http.HttpHeaderParser;
/**
* Parses a multipart/form-data http request,
@ -35,11 +35,11 @@ public class MultipartParser {
private BufferedReader in;
/** This is the listener that will listen on the progress */
private ProgressListener<MultipartField> listener;
private ProgressListener<MultipartParser,MultipartField> listener;
public MultipartParser(BufferedReader in, HTTPHeaderParser header){
public MultipartParser(BufferedReader in, HttpHeaderParser header){
this.in = in;
String cotype = header.getHeader("Content-type");
@ -69,7 +69,7 @@ public class MultipartParser {
/**
* @param listener is the listener that will be called for progress
*/
public void setListener(ProgressListener<MultipartField> listener){
public void setListener(ProgressListener<MultipartParser,MultipartField> listener){
this.listener = listener;
}

View file

@ -10,7 +10,7 @@ import java.util.logging.Logger;
import zutil.io.StringOutputStream;
import zutil.log.LogUtil;
import zutil.net.http.HTTPHeaderParser;
import zutil.net.http.HttpHeaderParser;
import zutil.net.http.HttpPrintStream;
import zutil.net.threaded.ThreadedUDPNetwork;
import zutil.net.threaded.ThreadedUDPNetworkThread;
@ -75,7 +75,7 @@ public class SSDPClient extends ThreadedUDPNetwork implements ThreadedUDPNetwork
// Generate an SSDP discover message
StringOutputStream msg = new StringOutputStream();
HttpPrintStream http = new HttpPrintStream( msg, HttpPrintStream.HTTPMessageType.REQUEST );
HttpPrintStream http = new HttpPrintStream( msg, HttpPrintStream.HttpMessageType.REQUEST );
http.setRequestType("M-SEARCH");
http.setRequestURL("*");
http.setHeader("Host", SSDPServer.SSDP_MULTICAST_ADDR+":"+SSDPServer.SSDP_PORT );
@ -150,7 +150,7 @@ public class SSDPClient extends ThreadedUDPNetwork implements ThreadedUDPNetwork
* Location: http://localhost:80
*/
public void receivedPacket(DatagramPacket packet, ThreadedUDPNetwork network) {
HTTPHeaderParser header = new HTTPHeaderParser( new String( packet.getData() ) );
HttpHeaderParser header = new HttpHeaderParser( new String( packet.getData() ) );
logger.log(Level.FINEST, "*********** Recived\n"+header);
String usn = header.getHeader("USN");

View file

@ -12,7 +12,7 @@ import java.util.logging.Logger;
import zutil.io.MultiPrintStream;
import zutil.io.StringOutputStream;
import zutil.log.LogUtil;
import zutil.net.http.HTTPHeaderParser;
import zutil.net.http.HttpHeaderParser;
import zutil.net.http.HttpPrintStream;
import zutil.net.threaded.ThreadedUDPNetworkThread;
import zutil.net.threaded.ThreadedUDPNetwork;
@ -155,7 +155,7 @@ public class SSDPServer extends ThreadedUDPNetwork implements ThreadedUDPNetwork
try {
String msg = new String( packet.getData() );
HTTPHeaderParser header = new HTTPHeaderParser( msg );
HttpHeaderParser header = new HttpHeaderParser( msg );
logger.log(Level.FINEST, "**** Received:\n"+header);
// ******* Respond
@ -233,7 +233,7 @@ public class SSDPServer extends ThreadedUDPNetwork implements ThreadedUDPNetwork
try {
// Generate the SSDP response
StringOutputStream msg = new StringOutputStream();
HttpPrintStream http = new HttpPrintStream( msg, HttpPrintStream.HTTPMessageType.REQUEST );
HttpPrintStream http = new HttpPrintStream( msg, HttpPrintStream.HttpMessageType.REQUEST );
http.setRequestType("NOTIFY");
http.setRequestURL("*");
http.setHeader("Server", SERVER_INFO );
@ -284,7 +284,7 @@ public class SSDPServer extends ThreadedUDPNetwork implements ThreadedUDPNetwork
try {
// Generate the SSDP response
StringOutputStream msg = new StringOutputStream();
HttpPrintStream http = new HttpPrintStream( msg, HttpPrintStream.HTTPMessageType.REQUEST );
HttpPrintStream http = new HttpPrintStream( msg, HttpPrintStream.HttpMessageType.REQUEST );
http.setRequestType("NOTIFY");
http.setRequestURL("*");
http.setHeader("Server", SERVER_INFO );

View file

@ -8,19 +8,22 @@ import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.cert.CertificateException;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.net.ssl.SSLServerSocketFactory;
import zutil.io.MultiPrintStream;
import zutil.log.LogUtil;
/**
* A simple web server that handles both cookies and
* sessions for all the clients
* A simple network server that handles TCP communication
*
* @author Ziver
*/
public abstract class ThreadedTCPNetworkServer extends Thread{
public static final Logger logger = LogUtil.getLogger();
public final int port;
private File keyStore;
private String keyStorePass;
@ -64,18 +67,18 @@ public abstract class ThreadedTCPNetworkServer extends Thread{
if( t!=null )
new Thread( t ).start();
else{
MultiPrintStream.out.println("Unable to instantiate ThreadedTCPNetworkServerThread, closing connection!");
logger.severe("Unable to instantiate ThreadedTCPNetworkServerThread, closing connection!");
s.close();
}
}
} catch(Exception e) {
e.printStackTrace( MultiPrintStream.out );
logger.log(Level.SEVERE, null, e);
}
if( ss!=null ){
try{
ss.close();
}catch(IOException e){ e.printStackTrace( MultiPrintStream.out ); }
}catch(IOException e){ logger.log(Level.SEVERE, null, e); }
}
}
@ -94,7 +97,6 @@ public abstract class ThreadedTCPNetworkServer extends Thread{
*
* @param port The port to listen to
* @return The SSLServerSocket
* @throws IOException
*/
private ServerSocket initSSL(int port) throws IOException{
SSLServerSocketFactory sslserversocketfactory =

View file

@ -1,7 +1,7 @@
package zutil.net.threaded;
/**
* The class that will handle the TCP connection will incclude
* The class that will handle the a TCP connection will include
* this interface
*
* @author Ziver

View file

@ -10,8 +10,7 @@ import java.net.SocketException;
/**
* A simple web server that handles both cookies and
* sessions for all the clients
* * A simple network server that handles UDP communication
*
* @author Ziver
*/

View file

@ -4,7 +4,7 @@ import java.net.DatagramPacket;
/**
* This interface is for processing received packets
* from the TNetworkUDPServer
* from the ThreadedUDPNetworkServer
*
* @author Ziver
*

View file

@ -1,102 +0,0 @@
package zutil.net.torrent;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import zutil.io.file.FileUtil;
public class Torrent {
// Name of the torrent
private String name;
// Comment
private String comment;
// Creation date as unix timestamp
private long date;
// Files in the torrent
private ArrayList<String> file_list;
// Size of of the full torrent (after download)
private long size;
// Signature of the software which created the torrent
private String created_by;
// tracker (the tracker the torrent has been received from)
private String main_tracker;
// List of known trackers for the torrent
private ArrayList<String> tracker_list;
private HashMap<String,Object> info_hash;
// Torrent is marked as 'private'.
private boolean is_private;
public Torrent(File torrent) throws IOException{
this(FileUtil.getFileContent( torrent ));
}
public Torrent(String data){
reset();
decode(data);
}
private void reset(){
// Reset
name = "";
comment = "";
date = 0;
file_list = new ArrayList<String>();
size = 0;
created_by = "";
main_tracker = "";
tracker_list = new ArrayList<String>();
info_hash = new HashMap<String,Object>();
is_private = false;
}
@SuppressWarnings("unchecked")
private void decode(String data){
HashMap<?,?> dataMap = (HashMap<?,?>)TorrentParser.decode(data);
name = (String)dataMap.get("name");
comment = (String)dataMap.get("comment");
date = (Long)dataMap.get("creation date");
file_list = new ArrayList<String>();
size = (Long)dataMap.get("length");
created_by = (String)dataMap.get("created by");
main_tracker = (String)dataMap.get("announce");
tracker_list = (ArrayList<String>)dataMap.get("announce-list");
info_hash = (HashMap<String, Object>)dataMap.get("info");
is_private = (((Integer)dataMap.get("private")) != 0);
}
// ************** GETTER **************
public String getName(){
return name;
}
public String getComments(){
return comment;
}
public long getDate(){
return date;
}
public ArrayList<String> getFileList(){
return file_list;
}
public long getSize(){
return size;
}
public String getAuthor(){
return created_by;
}
public String getMainTracker(){
return main_tracker;
}
public ArrayList<String> getTrackerList(){
return tracker_list;
}
public HashMap<String,Object> getInfoHash(){
return info_hash;
}
public boolean isPrivate(){
return is_private;
}
// ************************************
}

View file

@ -0,0 +1,32 @@
package zutil.net.torrent;
import zutil.Dumpable;
/**
* This class represents a File for download
*
* @author Ziver
*/
public class TorrentFile implements Dumpable{
private String filename;
private long length;
public TorrentFile(String filename, long length){
this.filename = filename;
this.length = length;
}
public String getFilename() {
return filename;
}
public void setFilename(String filename) {
this.filename = filename;
}
public long getLength() {
return length;
}
public void setLength(long length) {
this.length = length;
}
}

View file

@ -0,0 +1,165 @@
package zutil.net.torrent;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Iterator;
import zutil.io.MultiPrintStream;
import zutil.io.file.FileUtil;
import zutil.parser.BEncodedParser;
import zutil.parser.DataNode;
public class TorrentMetainfo {
/** Comment (optional) **/
private String comment;
/** Signature of the software which created the torrent (optional) **/
private String created_by;
/** Creation date as Unix timestamp (optional) **/
private long creation_date;
/** The main Tracker (the tracker the torrent has been received from) **/
private String announce;
/** List of known trackers for the torrent (optional) **/
private ArrayList<String> announce_list;
/** The encoding of the Strings (optional) **/
private String encoding;
/** Size of of the full torrent (after download) **/
private long size;
/** Number of bytes in each piece **/
private long piece_length;
/** String consisting of the concatenation of all 20-byte SHA1 hash values, one per piece **/
private ArrayList<String> piece_hashes;
/** Torrent is private. No other trackers allowed other then those listed. (optional) **/
private boolean is_private;
// Files in the torrent
private ArrayList<TorrentFile> file_list;
public TorrentMetainfo(File torrent) throws IOException{
this(FileUtil.getFileContent( torrent ));
}
public TorrentMetainfo(String data){
decode(data);
}
private void decode(String data){
DataNode metainfo = BEncodedParser.parse(data);
// Main values
announce = metainfo.getString("announce");
created_by = metainfo.getString("created by");
comment = metainfo.getString("comment");
encoding = metainfo.getString("encoding");
if( metainfo.get("creation date") != null )
creation_date = metainfo.getLong("creation date");
if( metainfo.get("announce-list") != null ){
DataNode tmp = metainfo.get("announce-list");
announce_list = new ArrayList<String>();
for( DataNode tracker : tmp )
announce_list.add( tracker.getString() );
}
// info data
DataNode info = metainfo.get("info");
String name = info.getString("name");
piece_length = info.getLong("piece length");
if( info.get("private") != null )
is_private = (info.getInt("private") != 0);
// Split the hashes
String hashes = info.getString("pieces");
piece_hashes = new ArrayList<String>();
for(int i=0; i<hashes.length() ;i++){
String hash = "";
for(; i%20!=0 ;i++)
hash += hashes.charAt(i);
piece_hashes.add(hash);
}
// File data
file_list = new ArrayList<TorrentFile>();
// Single-file torrent
if( info.get("files") == null ){
Long length = info.getLong("length");
file_list.add( new TorrentFile(name, length) );
}
// Multi-file torrent
else{
DataNode files = info.get("files");
for( DataNode file : files ){
String filename = "";
DataNode tmp = file.get("path");
// File in subdir
if( tmp.isList() ){
Iterator<DataNode> it = tmp.iterator();
while( it.hasNext() ){
filename += it.next().getString();
if(it.hasNext()) filename += File.separator;
}
}
// File in root dir
else
filename = tmp.getString();
Long length = file.getLong("length");
filename = name + File.separator + filename;
file_list.add( new TorrentFile(filename, length) );
}
}
}
public String getComment() {
return comment;
}
public String getCreated_by() {
return created_by;
}
public long getCreation_date() {
return creation_date;
}
public String getAnnounce() {
return announce;
}
public ArrayList<String> getAnnounce_list() {
return announce_list;
}
public String getEncoding() {
return encoding;
}
public long getSize() {
return size;
}
public long getPiece_length() {
return piece_length;
}
public ArrayList<String> getPiece_hashes() {
return piece_hashes;
}
public boolean isIs_private() {
return is_private;
}
public ArrayList<TorrentFile> getFile_list() {
return file_list;
}
/**
* Example use
*/
public static void main(String[] args){
try {
TorrentMetainfo tmp = new TorrentMetainfo(FileUtil.find("C:\\Users\\Ziver\\Desktop\\test.torrent"));
MultiPrintStream.out.dump(tmp);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}

View file

@ -0,0 +1,26 @@
package zutil.net.torrent;
import java.io.IOException;
import java.net.URL;
import zutil.net.http.HttpClient;
import zutil.net.http.HttpHeaderParser;
/**
* This tracker represents a tracker client
* that connects to a tracker
*
* @author Ziver
*/
public class TorrentTracker {
/** The address to the tracker **/
private URL trackerURL;
private void update() throws IOException {
HttpClient request = HttpClient.GET();
request.setURL( trackerURL );
HttpHeaderParser response = request.send();
}
}

View file

@ -0,0 +1,57 @@
package zutil.net.update;
import java.io.File;
import java.io.IOException;
import java.io.Serializable;
import zutil.Hasher;
import zutil.io.file.FileUtil;
/**
* This class is used to store the files
* and there hashes
*
* @author Ziver
*/
public class FileInfo implements Serializable{
private static final long serialVersionUID = 1L;
private transient File file;
private String path;
private String hash;
private long size;
public FileInfo(String root, File file) throws IOException{
path = FileUtil.relativePath(file, root);
hash = Hasher.MD5(file);
size = file.length();
this.file = file;
}
public String getPath() {
return path;
}
public String getHash() {
return hash;
}
public long getSize() {
return size;
}
public File getFile(){
return file;
}
public boolean equals(Object comp){
if(comp instanceof FileInfo){
FileInfo tmp = (FileInfo)comp;
return path.equals(tmp.path) && hash.equals(tmp.hash);
}
return false;
}
public String toString(){
return path;
}
}

View file

@ -0,0 +1,82 @@
package zutil.net.update;
import java.io.File;
import java.io.IOException;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import zutil.io.file.FileUtil;
/**
* This class is used to store the files
* and there hashes
*
* @author Ziver
*/
class FileListMessage implements Serializable{
private static final long serialVersionUID = 1L;
private ArrayList<FileInfo> fileList;
private long totalSize;
private FileListMessage(){}
/**
* Returns a ArrayList of FileInfo object for all the files in the specified folder
*
* @param path is the path to scan
**/
public FileListMessage(String path) throws IOException{
fileList = new ArrayList<FileInfo>();
List<File> files = FileUtil.search(FileUtil.find(path));
long totalSize = 0;
for(File file : files){
FileInfo fileInfo = new FileInfo(path, file);
fileList.add( fileInfo );
totalSize += fileInfo.getSize();
}
this.totalSize = totalSize;
}
public long getTotalSize() {
return totalSize;
}
public ArrayList<FileInfo> getFileList(){
return fileList;
}
/**
* Compares the files and returns the files that differ from this file list
*
* @param comp is the file list to compare with
* @return
*/
public FileListMessage getDiff( FileListMessage comp){
FileListMessage diff = new FileListMessage();
long diffSize = 0;
diff.fileList = new ArrayList<FileInfo>();
for(FileInfo file : this.fileList){
if( !comp.fileList.contains( file)){
diff.fileList.add( file );
diffSize += file.getSize();
}
}
diff.totalSize = diffSize;
return diff;
}
public boolean equals(Object comp){
if(comp instanceof FileListMessage){
FileListMessage tmp = (FileListMessage)comp;
return fileList.equals(tmp.fileList) && totalSize == tmp.totalSize;
}
return false;
}
}

View file

@ -0,0 +1,154 @@
package zutil.net.update;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.Socket;
import java.util.logging.Level;
import java.util.logging.Logger;
import zutil.ProgressListener;
import zutil.io.file.FileUtil;
import zutil.log.LogUtil;
/**
* This class connects to a update server and updates a path
* with the servers
*
* @author Ziver
*
*/
public class UpdateClient{
public static final Logger logger = LogUtil.getLogger();
private String path;
private Socket socket;
private FileListMessage fileList;
private long speed;
private long totalReceived;
private long expectedSize;
private ProgressListener<UpdateClient,FileInfo> progress;
/**
* Creates a UpdateClient
*
* @param address Address to the UpdateServer
* @param port The port on the server
* @param path Path to the files to update
* @throws Exception
*/
public UpdateClient(String address, int port, String path) throws Exception{
fileList = new FileListMessage(path);
socket = new Socket(address, port);
this.path = path;
}
public void setProgressListener(ProgressListener<UpdateClient,FileInfo> p){
progress = p;
}
/**
* Updates the files
*/
public void update() throws IOException{
try{
ObjectOutputStream out = new ObjectOutputStream( socket.getOutputStream());
ObjectInputStream in = new ObjectInputStream ( socket.getInputStream() );
// send client file list
out.writeObject( fileList );
out.flush();
// get update list
FileListMessage updateList = (FileListMessage) in.readObject();
expectedSize = updateList.getTotalSize();
// receive file updates
File tmpPath = FileUtil.find(path);
totalReceived = 0;
for(FileInfo info : updateList.getFileList() ){
// reading new file data
File file = new File( tmpPath, info.getPath() );
logger.fine("Updating file: "+file);
if( !file.getParentFile().exists() && !file.getParentFile().mkdirs() ){
throw new IOException("Unable to create folder: "+file.getParentFile());
}
File tmpFile = File.createTempFile(file.getName(), ".tmp", tmpPath);
tmpFile.deleteOnExit();
FileOutputStream fileOut = new FileOutputStream(tmpFile);
byte[] buffer = new byte[socket.getReceiveBufferSize()];
long bytesReceived = 0;
int byteRead = 0;
long time = System.currentTimeMillis();
long timeTotalRecived = 0;
while( bytesReceived < info.getSize() ) {
byteRead = in.read(buffer);
fileOut.write(buffer, 0, byteRead);
bytesReceived += byteRead;
if(time+1000 < System.currentTimeMillis()){
time = System.currentTimeMillis();
speed = (int)(totalReceived - timeTotalRecived);
timeTotalRecived = totalReceived;
}
totalReceived += byteRead;
if(progress != null) progress.progressUpdate(this, info, ((double)totalReceived/updateList.getTotalSize())*100);
}
fileOut.close();
speed = 0;
// delete old file and replace whit new
file.delete();
if( !tmpFile.renameTo(file) ){
throw new IOException("Can not move downloaded file: "+tmpFile.getAbsolutePath()+" to: "+file);
}
}
}catch(ClassNotFoundException e){
logger.log(Level.SEVERE, null, e);
}
logger.info("Update done.");
}
/**
* Returns the speed of the transfer
*
* @return The speed in bytes/s
*/
public long getSpeed(){
return speed;
}
/**
* Returns the total amount of data received
*
* @return a long that represents bytes
*/
public long getTotalReceived(){
return totalReceived;
}
/**
* Returns the expected total amount of data that will be received
*
* @return a long that represents bytes
*/
public long getTotalSize(){
return expectedSize;
}
/**
* Closes the connection
*
* @throws IOException
*/
public void close() throws IOException{
socket.close();
}
}

View file

@ -0,0 +1,15 @@
package zutil.net.update;
import java.io.Serializable;
/**
* A class that contains configuration information
*
* @author Ziver
*/
class UpdateConfigMessage implements Serializable{
private static final long serialVersionUID = 1L;
protected String hashAlgorithm;
protected boolean compression;
}

View file

@ -0,0 +1,101 @@
package zutil.net.update;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.Socket;
import java.util.logging.Level;
import java.util.logging.Logger;
import zutil.io.MultiPrintStream;
import zutil.log.LogUtil;
import zutil.net.threaded.ThreadedTCPNetworkServer;
import zutil.net.threaded.ThreadedTCPNetworkServerThread;
public class UpdateServer extends ThreadedTCPNetworkServer{
public static final Logger logger = LogUtil.getLogger();
private FileListMessage fileList;
/**
* Creates a UpdateServer Thread
*
* @param path The path to sync the clients with
*/
public UpdateServer(int port, String path) throws Exception{
super(port);
fileList = new FileListMessage(path);
MultiPrintStream.out.dump(fileList);
this.start();
logger.info("Update Server Ready.");
}
@Override
protected ThreadedTCPNetworkServerThread getThreadInstance(Socket s) {
return new UpdateServerThread(s);
}
/**
* Handles all the connecting clients
*
* @author Ziver
*/
class UpdateServerThread implements ThreadedTCPNetworkServerThread{
private ObjectOutputStream out;
private ObjectInputStream in;
private Socket socket;
/**
* Creates a UpdateServerThread
*
* @param client is the socket to the client
*/
public UpdateServerThread(Socket c){
socket = c;
try {
out = new ObjectOutputStream( socket.getOutputStream());
in = new ObjectInputStream ( socket.getInputStream() );
} catch (IOException e) {
logger.log(Level.SEVERE, null, e);
}
}
public void run(){
try {
logger.info("Client["+socket.getInetAddress()+"] connectiong...");
// receive the clients file list
FileListMessage clientFileList = (FileListMessage)in.readObject();
MultiPrintStream.out.dump(clientFileList);
FileListMessage diff = fileList.getDiff( clientFileList );
MultiPrintStream.out.dump(diff);
out.writeObject( diff );
logger.info("Updating client["+socket.getInetAddress()+"]...");
for(FileInfo info : diff.getFileList()){
// send file data
FileInputStream input = new FileInputStream( info.getFile() );
byte[] nextBytes = new byte[ socket.getSendBufferSize() ];
int bytesRead = 0;
while((bytesRead = input.read(nextBytes)) > 0){
out.write(nextBytes,0,bytesRead);
}
out.flush();
input.close();
}
out.flush();
socket.close();
logger.info("Client["+socket.getInetAddress()+"] update done.");
} catch (Exception e) {
logger.log(Level.SEVERE, "Update error Client["+socket.getInetAddress()+"].", e);
} finally {
logger.info("Client["+socket.getInetAddress()+"] disconnected.");
}
}
}
}

View file

@ -0,0 +1,131 @@
package zutil.net.update;
import java.awt.EventQueue;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.border.EmptyBorder;
import javax.swing.GroupLayout;
import javax.swing.GroupLayout.Alignment;
import javax.swing.JLabel;
import javax.swing.JProgressBar;
import javax.swing.LayoutStyle.ComponentPlacement;
import javax.swing.SwingConstants;
import javax.swing.JSeparator;
import javax.swing.JButton;
import zutil.ProgressListener;
import zutil.StringUtil;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
import java.awt.Dialog.ModalExclusionType;
public class Zupdater extends JFrame implements ProgressListener<UpdateClient, FileInfo>{
private static final long serialVersionUID = 1L;
private JPanel contentPane;
private JLabel lblSpeed;
private JLabel lblFile;
private JProgressBar progressBar;
/**
* Launch the application.
*/
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
Zupdater frame = new Zupdater();
frame.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
public void progressUpdate(UpdateClient source, FileInfo info, double percent) {
lblFile.setText( info.getPath() );
progressBar.setValue( (int)percent );
progressBar.setString( StringUtil.formatBytesToString( source.getTotalReceived() ) +
" / "+StringUtil.formatBytesToString( source.getTotalSize() ));
lblSpeed.setText( StringUtil.formatBytesToString(((UpdateClient)source).getSpeed())+"/s" );
}
/**
* Create the frame.
*/
public Zupdater() {
setModalExclusionType(ModalExclusionType.APPLICATION_EXCLUDE);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setAlwaysOnTop(true);
setResizable(false);
setTitle("Updating...");
setBounds(100, 100, 537, 124);
contentPane = new JPanel();
contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
setContentPane(contentPane);
progressBar = new JProgressBar();
progressBar.setString("2.5 MB / 5 MB");
progressBar.setValue(50);
progressBar.setStringPainted(true);
progressBar.setToolTipText("");
lblFile = new JLabel("apa.zip");
lblSpeed = new JLabel("200 kb/s");
lblSpeed.setHorizontalAlignment(SwingConstants.RIGHT);
JSeparator separator = new JSeparator();
JButton btnCancel = new JButton("Cancel");
btnCancel.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
System.exit(0);
}
});
JLabel lblFile_1 = new JLabel("File:");
GroupLayout gl_contentPane = new GroupLayout(contentPane);
gl_contentPane.setHorizontalGroup(
gl_contentPane.createParallelGroup(Alignment.TRAILING)
.addGroup(gl_contentPane.createSequentialGroup()
.addGap(10)
.addComponent(progressBar, GroupLayout.DEFAULT_SIZE, 501, Short.MAX_VALUE)
.addGap(10))
.addComponent(separator, GroupLayout.DEFAULT_SIZE, 521, Short.MAX_VALUE)
.addGroup(gl_contentPane.createSequentialGroup()
.addContainerGap()
.addComponent(lblFile_1)
.addPreferredGap(ComponentPlacement.RELATED)
.addComponent(lblFile, GroupLayout.PREFERRED_SIZE, 331, GroupLayout.PREFERRED_SIZE)
.addGap(60)
.addComponent(lblSpeed, GroupLayout.DEFAULT_SIZE, 84, Short.MAX_VALUE)
.addContainerGap())
.addGroup(gl_contentPane.createSequentialGroup()
.addContainerGap()
.addComponent(btnCancel))
);
gl_contentPane.setVerticalGroup(
gl_contentPane.createParallelGroup(Alignment.LEADING)
.addGroup(gl_contentPane.createSequentialGroup()
.addGroup(gl_contentPane.createParallelGroup(Alignment.BASELINE)
.addComponent(lblSpeed)
.addComponent(lblFile)
.addComponent(lblFile_1))
.addPreferredGap(ComponentPlacement.RELATED)
.addComponent(progressBar, GroupLayout.PREFERRED_SIZE, 25, GroupLayout.PREFERRED_SIZE)
.addPreferredGap(ComponentPlacement.RELATED)
.addComponent(separator, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)
.addPreferredGap(ComponentPlacement.RELATED)
.addComponent(btnCancel)
.addContainerGap(14, Short.MAX_VALUE))
);
contentPane.setLayout(gl_contentPane);
}
}

View file

@ -1,34 +1,13 @@
package zutil.net.torrent;
package zutil.parser;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.HashMap;
import java.util.LinkedList;
import zutil.io.MultiPrintStream;
import zutil.io.file.FileUtil;
import zutil.parser.DataNode.DataType;
/**
* http://wiki.theory.org/BitTorrentSpecification
* @author Ziver
*
*/
public class TorrentParser {
/**
* Example use
*/
public static void main(String[] args){
try {
String tmp = FileUtil.getFileContent(FileUtil.find("C:\\Users\\Ziver\\Desktop\\test.torrent"));
MultiPrintStream.out.dump(TorrentParser.decode(tmp));
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
public class BEncodedParser {
/**
* Returns the representation of the data in the BEncoded string
@ -36,7 +15,7 @@ public class TorrentParser {
* @param data The data to be decoded
* @return
*/
public static Object decode(String data){
public static DataNode parse(String data){
return decode_BEncoded(new StringBuffer(data));
}
@ -47,7 +26,7 @@ public class TorrentParser {
* @param index The index in data to start from
* @return
*/
private static Object decode_BEncoded(StringBuffer data){
private static DataNode decode_BEncoded(StringBuffer data){
String tmp;
char c = ' ';
@ -63,7 +42,7 @@ public class TorrentParser {
tmp = data.substring(0, data.indexOf("e"));
data.delete(0, tmp.length() + 1);
//System.out.println(tmp);
return new Long(tmp);
return new DataNode( new Long(tmp));
/**
* Lists are prefixed with a l and terminated by an e. The list
* should contain a series of bEncoded elements. For example, the
@ -74,15 +53,15 @@ public class TorrentParser {
case 'l':
//System.out.println("Found List at "+index);
data.deleteCharAt(0);
LinkedList<Object> list = new LinkedList<Object>();
DataNode list = new DataNode( DataType.List );
c = data.charAt(0);
while(c != 'e'){
list.add(decode_BEncoded(data));
list.add( decode_BEncoded(data) );
c = data.charAt(0);
}
data.deleteCharAt(0);
//MultiPrintStream.out.dump(list);
if(list.size() == 1) return list.poll();
if(list.size() == 1) return list.get(0);
else return list;
/**
* Dictionaries are prefixed with a d and terminated by an e. They
@ -93,11 +72,11 @@ public class TorrentParser {
case 'd':
//System.out.println("Found Dictionary at "+index);
data.deleteCharAt(0);
HashMap<Object,Object> map = new HashMap<Object,Object>();
DataNode map = new DataNode( DataType.Map );
c = data.charAt(0);
while(c != 'e'){
Object tmp2 = decode_BEncoded(data);
map.put(tmp2, decode_BEncoded(data));
DataNode tmp2 = decode_BEncoded(data);
map.set(tmp2.getString(), decode_BEncoded(data));
c = data.charAt(0);
}
data.deleteCharAt(0);
@ -116,7 +95,7 @@ public class TorrentParser {
String ret = data.substring(0, length);
data.delete(0, length);
//System.out.println(data.substring(i, i+length));
return ret;
return new DataNode( ret );
}
}
}

View file

@ -1,4 +1,4 @@
package zutil.parser.json;
package zutil.parser;
import java.util.HashMap;
import java.util.Iterator;
@ -8,66 +8,65 @@ import java.util.Map;
/**
* This is an node in an JSON tree,
* it may contain a Map, list or value
* This is a data node used in JSON and BEncoding and other types
*
* @author Ziver
*/
public class JSONNode implements Iterable<JSONNode>{
public enum JSONType{
public class DataNode implements Iterable<DataNode>{
public enum DataType{
Map, List, String, Number, Boolean
}
private Map<String,JSONNode> map = null;
private List<JSONNode> list = null;
private Map<String,DataNode> map = null;
private List<DataNode> list = null;
private String value = null;
private JSONType type;
private DataType type;
/**
* Creates an instance with an Boolean value
*/
public JSONNode(boolean value){
this.type = JSONType.Boolean;
public DataNode(boolean value){
this.type = DataType.Boolean;
this.value = ""+value;
}
/**
* Creates an instance with an int value
*/
public JSONNode(int value){
this.type = JSONType.Number;
public DataNode(int value){
this.type = DataType.Number;
this.value = ""+value;
}
/**
* Creates an instance with an double value
*/
public JSONNode(double value){
this.type = JSONType.Number;
public DataNode(double value){
this.type = DataType.Number;
this.value = ""+value;
}
/**
* Creates an instance with an long value
*/
public JSONNode(long value){
this.type = JSONType.Number;
public DataNode(long value){
this.type = DataType.Number;
this.value = ""+value;
}
/**
* Creates an instance with an String value
*/
public JSONNode(String value){
this.type = JSONType.String;
public DataNode(String value){
this.type = DataType.String;
this.value = value;
}
/**
* Creates an instance with a specific type
*/
public JSONNode(JSONType type){
public DataNode(DataType type){
this.type = type;
switch(type){
case Map:
map = new HashMap<String,JSONNode>(); break;
map = new HashMap<String,DataNode>(); break;
case List:
list = new LinkedList<JSONNode>(); break;
list = new LinkedList<DataNode>(); break;
}
}
@ -75,7 +74,7 @@ public class JSONNode implements Iterable<JSONNode>{
* @param index is the index of the List or Map
* @return an JSONNode that contains the next level of the List or Map
*/
public JSONNode get(int index){
public DataNode get(int index){
if(map != null)
return map.get(""+index);
else if(list != null)
@ -86,7 +85,7 @@ public class JSONNode implements Iterable<JSONNode>{
* @param index is the key in the Map
* @return an JSONNode that contains the next level of the Map
*/
public JSONNode get(String index){
public DataNode get(String index){
if(map != null)
return map.get(index);
return null;
@ -95,7 +94,7 @@ public class JSONNode implements Iterable<JSONNode>{
/**
* @return a iterator for the Map or List or null if the node contains a value
*/
public Iterator<JSONNode> iterator(){
public Iterator<DataNode> iterator(){
if(map != null)
return map.values().iterator();
else if(list != null)
@ -125,51 +124,51 @@ public class JSONNode implements Iterable<JSONNode>{
/**
* Adds a node to the List
*/
public void add(JSONNode node){
public void add(DataNode node){
list.add(node);
}
public void add(boolean value){
list.add(new JSONNode( value ));
list.add(new DataNode( value ));
}
public void add(int value){
list.add(new JSONNode( value ));
list.add(new DataNode( value ));
}
public void add(double value){
list.add(new JSONNode( value ));
list.add(new DataNode( value ));
}
public void add(long value){
list.add(new JSONNode( value ));
list.add(new DataNode( value ));
}
public void add(String value){
list.add(new JSONNode( value ));
list.add(new DataNode( value ));
}
/**
* Adds a node to the Map
*/
public void add(String key, JSONNode node){
public void set(String key, DataNode node){
map.put(key, node);
}
public void add(String key, boolean value){
map.put(key, new JSONNode(value));
public void set(String key, boolean value){
map.put(key, new DataNode(value));
}
public void add(String key, int value){
map.put(key, new JSONNode(value));
public void set(String key, int value){
map.put(key, new DataNode(value));
}
public void add(String key, double value){
map.put(key, new JSONNode(value));
public void set(String key, double value){
map.put(key, new DataNode(value));
}
public void add(String key, long value){
map.put(key, new JSONNode(value));
public void set(String key, long value){
map.put(key, new DataNode(value));
}
public void add(String key, String value){
map.put(key, new JSONNode(value));
public void set(String key, String value){
map.put(key, new DataNode(value));
}
/**
* Sets the value of the node, but only if it is setup as an JSONType.Value
*/
public void set(int value){
if( !this.isValue() ) throw new NullPointerException("The node is not setup as a value");
type = JSONType.Number;
type = DataType.Number;
this.value = ""+value;
}
/**
@ -177,7 +176,7 @@ public class JSONNode implements Iterable<JSONNode>{
*/
public void set(double value){
if( !this.isValue() ) throw new NullPointerException("The node is not setup as a value");
type = JSONType.Number;
type = DataType.Number;
this.value = ""+value;
}
/**
@ -185,7 +184,7 @@ public class JSONNode implements Iterable<JSONNode>{
*/
public void set(boolean value){
if( !this.isValue() ) throw new NullPointerException("The node is not setup as a value");
type = JSONType.Boolean;
type = DataType.Boolean;
this.value = ""+value;
}
/**
@ -193,7 +192,7 @@ public class JSONNode implements Iterable<JSONNode>{
*/
public void set(long value){
if( !this.isValue() ) throw new NullPointerException("The node is not setup as a value");
type = JSONType.Number;
type = DataType.Number;
this.value = ""+value;
}
/**
@ -201,7 +200,7 @@ public class JSONNode implements Iterable<JSONNode>{
*/
public void set(String value){
if( !this.isValue() ) throw new NullPointerException("The node is not setup as a value");
type = JSONType.String;
type = DataType.String;
this.value = value;
}
@ -210,28 +209,71 @@ public class JSONNode implements Iterable<JSONNode>{
* @return if this node contains an Map
*/
public boolean isMap(){
return type == JSONType.Map;
return type == DataType.Map;
}
/**
* @return if this node contains an List
*/
public boolean isList(){
return type == JSONType.List;
return type == DataType.List;
}
/**
* @return if this node contains an value
*/
public boolean isValue(){
return type != JSONType.Map && type != JSONType.List;
return type != DataType.Map && type != DataType.List;
}
/**
* @return the type of the node
*/
public JSONType getType(){
public DataType getType(){
return type;
}
/**
* @return the String value in this map
*/
public String getString(String key){
if( !this.isMap() ) throw new NullPointerException("The node is not setup as a map");
if( !this.map.containsKey(key) )
return null;
return this.get(key).getString();
}
/**
* @return the boolean value in this map
*/
public boolean getBoolean(String key){
if( !this.isMap() ) throw new NullPointerException("The node is not setup as a map");
if( !this.map.containsKey(key) ) throw new NullPointerException("No such key in map");
return this.get(key).getBoolean();
}
/**
* @return the integer value in this map
*/
public int getInt(String key){
if( !this.isMap() ) throw new NullPointerException("The node is not setup as a map");
if( !this.map.containsKey(key) ) throw new NullPointerException("No such key in map");
return this.get(key).getInt();
}
/**
* @return the double value in this map
*/
public double getDouble(String key){
if( !this.isMap() ) throw new NullPointerException("The node is not setup as a map");
if( !this.map.containsKey(key) ) throw new NullPointerException("No such key in map");
return this.get(key).getDouble();
}
/**
* @return the long value in this map
*/
public long getLong(String key){
if( !this.isMap() ) throw new NullPointerException("The node is not setup as a map");
if( !this.map.containsKey(key) ) throw new NullPointerException("No such key in map");
return this.get(key).getLong();
}
/**
* @return the String value in this node, null if its a Map or List
*/
@ -256,6 +298,12 @@ public class JSONNode implements Iterable<JSONNode>{
public double getDouble(){
return Double.parseDouble(value);
}
/**
* @return the long value in this node
*/
public long getLong(){
return Long.parseLong(value);
}
public String toString(){

View file

@ -1,7 +1,8 @@
package zutil.parser.json;
import zutil.io.MultiPrintStream;
import zutil.parser.json.JSONNode.JSONType;
import zutil.parser.DataNode;
import zutil.parser.DataNode.DataType;
/**
* This is a JSON parser class
@ -28,7 +29,7 @@ public class JSONParser{
" { \"type\": \"fax\", \"number\": \"646 555-4567\" }"+
" ]"+
"}");
JSONNode node = parser.read();
DataNode node = parser.read();
MultiPrintStream.out.dump( node );
JSONWriter writer = new JSONWriter( System.out );
writer.write(node);
@ -48,7 +49,7 @@ public class JSONParser{
*
* @return a JSONNode object that is the root of the JSON
*/
public JSONNode read(){
public DataNode read(){
return parse(new StringBuffer(json));
}
@ -67,10 +68,10 @@ public class JSONParser{
* @param json
* @return
*/
protected static JSONNode parse(StringBuffer json){
JSONNode root = null;
JSONNode key = null;
JSONNode node = null;
protected static DataNode parse(StringBuffer json){
DataNode root = null;
DataNode key = null;
DataNode node = null;
int next_index;
while(Character.isWhitespace( json.charAt(0) ) ||
@ -84,26 +85,26 @@ public class JSONParser{
case '}':
return null;
case '{':
root = new JSONNode(JSONType.Map);
root = new DataNode(DataType.Map);
while((key = parse( json )) != null && (node = parse( json )) != null){
root.add( key.toString(), node );
root.set( key.toString(), node );
}
break;
case '[':
root = new JSONNode(JSONType.List);
root = new DataNode(DataType.List);
while((node = parse( json )) != null){
root.add( node );
}
break;
// Parse String
case '\"':
root = new JSONNode(JSONType.String);
root = new DataNode(DataType.String);
next_index = json.indexOf("\"");
root.set( json.substring(0, next_index) );
json.delete(0, next_index+1);
break;
default:
root = new JSONNode(JSONType.Number);
root = new DataNode(DataType.Number);
for(next_index=0; next_index<json.length() ;++next_index)
if( json.charAt(next_index)==',' ||
json.charAt(next_index)==']' ||

View file

@ -5,7 +5,8 @@ import java.io.PrintStream;
import java.io.PrintWriter;
import java.util.Iterator;
import zutil.parser.json.JSONNode.JSONType;
import zutil.parser.DataNode;
import zutil.parser.DataNode.DataType;
/**
* Writes An JSONNode to an String or stream
@ -47,7 +48,7 @@ public class JSONWriter{
*
* @param root is the root node
*/
public void write(JSONNode root){
public void write(DataNode root){
boolean first = true;
switch(root.getType()){
// Write Map
@ -74,7 +75,7 @@ public class JSONWriter{
// Write an list
case List:
out.print('[');
for(JSONNode node : root){
for(DataNode node : root){
if(!first)
out.print(", ");
write( node );
@ -83,7 +84,7 @@ public class JSONWriter{
out.print(']');
break;
default:
if(root.getString() != null && root.getType() == JSONType.String){
if(root.getString() != null && root.getType() == DataType.String){
out.print('\"');
out.print(root.toString());
out.print('\"');

View file

@ -0,0 +1,51 @@
package zutil.test;
import static org.junit.Assert.*;
import java.io.IOException;
import org.junit.Test;
import zutil.io.BoundaryBufferedInputStream;
import zutil.io.StringInputStream;
public class BoundaryBufferedInputStreamTest {
@Test
public void testReadB1() throws IOException {
StringInputStream inin = new StringInputStream();
BoundaryBufferedInputStream in = new BoundaryBufferedInputStream(inin);
inin.add("aaa#aaaaaaaaaaaaaaaa#aaaaaaaaaaaaaaa#");
in.setBoundary("#");
int n = 0;
for(n=0; in.read() != -1 ;n++);
assertEquals(3, n);
in.next();
n = 0;
for(n=0; in.read() != -1 ;n++);
assertEquals(16, n);
in.next();
n = 0;
for(n=0; in.read() != -1 ;n++);
assertEquals(15, n);
in.next();
assertEquals(-1, in.read());
}
@Test
public void testReadByteArray() {
fail("Not yet implemented");
}
@Test
public void testReadByteArrayIntInt() {
fail("Not yet implemented");
}
}

View file

@ -0,0 +1,46 @@
package zutil.test;
import static org.junit.Assert.*;
import org.junit.Test;
import zutil.converters.Converter;
public class ConverterTest {
@Test
public void testHexToByte() {
assertEquals( (byte)1, Converter.hexToByte('1') );
assertEquals( (byte)5, Converter.hexToByte('5') );
assertEquals( (byte)10, Converter.hexToByte('A') );
assertEquals( (byte)10, Converter.hexToByte('a') );
}
@Test
public void testHexToByte2() {
assertEquals( 0x00, Converter.hexToByte('0','0') );
assertEquals( 0x11, Converter.hexToByte('1','1') );
assertEquals( 0x75, Converter.hexToByte('7','5') );
assertEquals( 0xDA, Converter.hexToByte('D','A') );
assertEquals( 0xFA, Converter.hexToByte('F','a') );
assertEquals( 0xFF, Converter.hexToByte('f','f') );
}
@Test
public void testUrlEncode() {
assertEquals( "fas8dg7%20a0d1%2313f9g8d7%200h9a%a4%25h0",
Converter.urlEncode("fas8dg7 a0d1#13f9g8d7 0h9a¤%h0") );
assertEquals( "9i34%e5%202y92%a452%25%2623%20463765%a4(%2f%26(",
Converter.urlEncode("9i34å 2y92¤52%&23 463765¤(/&(") );
}
@Test
public void testUrlDecode() {
assertEquals( "fas8dg7 a0d1#13f9g8d7 0h9a%h0",
Converter.urlDecode("fas8dg7%20a0d1%2313f9g8d7%200h9a%25h0") );
assertEquals( "9i34å 2y9252%&23 463765(/&(",
Converter.urlDecode("9i34%e5%202y9252%25%2623%20463765(%2f%26(") );
}
}

View file

@ -0,0 +1,37 @@
package zutil.test;
import java.sql.PreparedStatement;
import zutil.db.DBConnection;
import zutil.db.handler.SimpleSQLHandler;
public class DBConnectionTest {
public static void main(String[] args){
try {
DBConnection db = new DBConnection("koc.se","db","user","password");
// Query 1
PreparedStatement sql = db.getPreparedStatement("SELECT ?");
sql.setInt(1, 1);
DBConnection.exec(sql);
// Query 2
db.exec("UPDATE ...");
// Query 3
String s = db.exec("SELECT hello", new SimpleSQLHandler<String>());
System.out.println( s );
// Query 4
PreparedStatement sql2 = db.getPreparedStatement("SELECT ?");
sql2.setString(1, "hello");
String s2 = DBConnection.exec(sql2, new SimpleSQLHandler<String>());
System.out.println( s2 );
db.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}

View file

@ -0,0 +1,48 @@
package zutil.test;
import static org.junit.Assert.*;
import org.junit.Test;
import zutil.net.http.HttpURL;
public class HttpURLTest {
@Test
public void fullURLTest() {
HttpURL url = new HttpURL();
url.setProtocol("http");
assertEquals( "http://127.0.0.1/", url.getURL() );
url.setHost("koc.se");
assertEquals( "http://koc.se/", url.getURL() );
url.setPort( 80 );
assertEquals( "http://koc.se:80/", url.getURL() );
url.setPath("test/index.html");
assertEquals( "http://koc.se:80/test/index.html", url.getURL() );
url.setParameter("key", "value");
assertEquals( "http://koc.se:80/test/index.html?key=value", url.getURL() );
url.setAnchor( "anch" );
assertEquals( "http://koc.se:80/test/index.html?key=value#anch", url.getURL() );
}
@Test
public void urlParameterTest() {
HttpURL url = new HttpURL();
url.setParameter("key1", "value1");
assertEquals( "key1=value1", url.getParameterString() );
url.setParameter("key1", "value1");
assertEquals( "key1=value1", url.getParameterString() );
url.setParameter("key2", "value2");
assertEquals( "key2=value2&key1=value1", url.getParameterString() );
}
}

View file

@ -0,0 +1,96 @@
package zutil.test;
import org.junit.*;
import static org.junit.Assert.*;
import zutil.db.SQLQuery;
public class SQLQueryTest {
@Test
public void selectTest() {
assertEquals( "SELECT * FROM test1",
""+SQLQuery.SELECT().FROM("test1") );
assertEquals( "SELECT * FROM test1",
""+SQLQuery.SELECT("*").FROM("test1") );
assertEquals( "SELECT test1,test2 FROM test1",
""+SQLQuery.SELECT("test1","test2").FROM("test1") );
}
@Test
public void selectJoinTest() {
assertEquals( "SELECT * FROM test1 JOIN test2",
""+SQLQuery.SELECT("*").FROM("test1").JOIN("test2") );
assertEquals( "SELECT * FROM test1 NATURAL JOIN test2",
""+SQLQuery.SELECT("*").FROM("test1").NATURAL_JOIN("test2") );
assertEquals( "SELECT * FROM test1 UNION test2",
""+SQLQuery.SELECT("*").FROM("test1").UNION("test2") );
assertEquals( "SELECT * FROM test1 JOIN test2 NATURAL JOIN test3 UNION test4",
""+SQLQuery.SELECT("*").FROM("test1").JOIN("test2").NATURAL_JOIN("test3").UNION("test4") );
assertEquals( "SELECT * FROM test1 NATURAL JOIN test2 NATURAL JOIN test3 NATURAL JOIN test4",
""+SQLQuery.SELECT("*").FROM().NATURAL_JOIN("test1","test2","test3","test4") );
assertEquals( "SELECT * FROM test1 JOIN test2 JOIN test3 JOIN test4",
""+SQLQuery.SELECT("*").FROM().JOIN("test1","test2","test3","test4") );
assertEquals( "SELECT * FROM test1 UNION test2 UNION test3 UNION test4",
""+SQLQuery.SELECT("*").FROM().UNION("test1","test2","test3","test4") );
}
@Test
public void selectWhereTest() {
assertEquals( "SELECT * FROM test1 WHERE arg=value",
""+SQLQuery.SELECT("*").FROM("test1").WHERE().EQ("arg","value") );
}
@Test
public void selectGroupByTest() {
assertEquals( "SELECT * FROM test1 GROUP BY col1",
""+SQLQuery.SELECT("*").FROM("test1").GROUP_BY("col1") );
assertEquals( "SELECT * FROM test1 WHERE arg=value GROUP BY col1",
""+SQLQuery.SELECT("*").FROM("test1").WHERE().EQ("arg","value").GROUP_BY("col1") );
assertEquals( "SELECT * FROM test1 WHERE arg=value GROUP BY col1 ASC",
""+SQLQuery.SELECT("*").FROM("test1").WHERE().EQ("arg","value").GROUP_BY("col1").ASC() );
assertEquals( "SELECT * FROM test1 WHERE arg=value GROUP BY col1 DESC",
""+SQLQuery.SELECT("*").FROM("test1").WHERE().EQ("arg","value").GROUP_BY("col1").DESC() );
}
@Test
public void selectOrderByTest() {
assertEquals( "SELECT * FROM test1 WHERE arg=value ORDER BY col1",
""+SQLQuery.SELECT("*").FROM("test1").WHERE().EQ("arg","value").ORDER_BY("col1") );
assertEquals( "SELECT * FROM test1 WHERE arg=value ORDER BY col1 ASC",
""+SQLQuery.SELECT("*").FROM("test1").WHERE().EQ("arg","value").ORDER_BY("col1").ASC() );
assertEquals( "SELECT * FROM test1 WHERE arg=value ORDER BY col1 DESC",
""+SQLQuery.SELECT("*").FROM("test1").WHERE().EQ("arg","value").ORDER_BY("col1").DESC() );
assertEquals( "SELECT * FROM test1 WHERE arg=value GROUP BY col1 ORDER BY col2 DESC",
""+SQLQuery.SELECT("*").FROM("test1").WHERE().EQ("arg","value").GROUP_BY("col1").ORDER_BY("col2").DESC() );
assertEquals( "SELECT * FROM test1 WHERE arg=value GROUP BY col1 ASC ORDER BY col2 DESC",
""+SQLQuery.SELECT("*").FROM("test1").WHERE().EQ("arg","value").GROUP_BY("col1").ASC().ORDER_BY("col2").DESC() );
}
@Test
public void selectLimitTest() {
assertEquals( "SELECT * FROM test1 LIMIT 1",
""+SQLQuery.SELECT("*").FROM("test1").LIMIT(1) );
assertEquals( "SELECT * FROM test1 LIMIT 1 4",
""+SQLQuery.SELECT("*").FROM("test1").LIMIT(1).TO(4) );
assertEquals( "SELECT * FROM test1 WHERE arg=value LIMIT 1",
""+SQLQuery.SELECT("*").FROM("test1").WHERE().EQ("arg","value").LIMIT(1) );
assertEquals( "SELECT * FROM test1 WHERE arg=value ORDER BY col1 DESC LIMIT 1",
""+SQLQuery.SELECT("*").FROM("test1").WHERE().EQ("arg","value").ORDER_BY("col1").DESC().LIMIT(1) );
assertEquals( "SELECT * FROM test1 WHERE arg=value GROUP BY col1 ORDER BY col2 DESC LIMIT 1",
""+SQLQuery.SELECT("*").FROM("test1").WHERE().EQ("arg","value").GROUP_BY("col1").ORDER_BY("col2").DESC().LIMIT(1) );
}
@Test
public void updateTest() {
}
@Test
public void deleteTest() {
}
@Test
public void createTest() {
}
}

View file

@ -1,20 +1,43 @@
package zutil.test;
import zutil.ProgressListener;
import zutil.net.UpdateClient;
import zutil.net.Zupdater;
import java.awt.EventQueue;
import java.util.logging.Level;
public class UpdateClientTest implements ProgressListener{
import zutil.ProgressListener;
import zutil.log.CompactLogFormatter;
import zutil.log.LogUtil;
import zutil.net.update.FileInfo;
import zutil.net.update.UpdateClient;
import zutil.net.update.Zupdater;
public class UpdateClientTest implements ProgressListener<UpdateClient, FileInfo>{
public static void main(String[] args){
LogUtil.setLevel("zutil", Level.FINEST);
LogUtil.setFormatter("zutil", new CompactLogFormatter());
UpdateClientTest client = new UpdateClientTest();
client.start();
}
public void start(){
try {
UpdateClient client = new UpdateClient("localhost", 2000, "client");
final UpdateClient client = new UpdateClient("localhost", 2000, "C:\\Users\\Ziver\\Desktop\\client");
client.setProgressListener(new Zupdater());
//client.setProgressListener(this);
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
Zupdater gui = new Zupdater();
client.setProgressListener(gui);
gui.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
client.update();
client.close();
} catch (Exception e) {
@ -22,7 +45,7 @@ public class UpdateClientTest implements ProgressListener{
}
}
public void progressUpdate(Object source, Object info, double percent) {
public void progressUpdate(UpdateClient source, FileInfo info, double percent) {
System.out.println(info+": "+percent+"%");
}
}

View file

@ -1,11 +1,18 @@
package zutil.test;
import zutil.net.UpdateServer;
import java.util.logging.Level;
import zutil.log.CompactLogFormatter;
import zutil.log.LogUtil;
import zutil.net.update.UpdateServer;
public class UpdateServerTest {
public static void main(String[] args){
try {
new UpdateServer(2000, "server");
LogUtil.setGlobalLevel(Level.FINEST);
LogUtil.setGlobalFormatter(new CompactLogFormatter());
new UpdateServer(2000, "C:\\Users\\Ziver\\Desktop\\server");
}catch (Exception e) {
e.printStackTrace();
}