Many bugfixes and improvements
This commit is contained in:
parent
c3e3bbf787
commit
363e0c6cfc
52 changed files with 2021 additions and 982 deletions
|
|
@ -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
|
||||
*
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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(){}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
45
src/zutil/db/handler/PropertiesSQLHandler.java
Normal file
45
src/zutil/db/handler/PropertiesSQLHandler.java
Normal 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;
|
||||
}
|
||||
}
|
||||
|
|
@ -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.
|
||||
*
|
||||
|
|
@ -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){
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
108
src/zutil/io/StringInputStream.java
Normal file
108
src/zutil/io/StringInputStream.java
Normal 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 );
|
||||
}
|
||||
}
|
||||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
@ -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();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
@ -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
|
||||
|
||||
}
|
||||
98
src/zutil/net/http/HttpClient.java
Normal file
98
src/zutil/net/http/HttpClient.java
Normal 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;
|
||||
}
|
||||
}
|
||||
|
|
@ -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 );
|
||||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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") ||
|
||||
|
|
|
|||
139
src/zutil/net/http/HttpURL.java
Normal file
139
src/zutil/net/http/HttpURL.java
Normal 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();
|
||||
}
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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");
|
||||
|
|
|
|||
|
|
@ -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 );
|
||||
|
|
|
|||
|
|
@ -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 =
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ import java.net.DatagramPacket;
|
|||
|
||||
/**
|
||||
* This interface is for processing received packets
|
||||
* from the TNetworkUDPServer
|
||||
* from the ThreadedUDPNetworkServer
|
||||
*
|
||||
* @author Ziver
|
||||
*
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
// ************************************
|
||||
}
|
||||
32
src/zutil/net/torrent/TorrentFile.java
Normal file
32
src/zutil/net/torrent/TorrentFile.java
Normal 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;
|
||||
}
|
||||
}
|
||||
165
src/zutil/net/torrent/TorrentMetainfo.java
Normal file
165
src/zutil/net/torrent/TorrentMetainfo.java
Normal 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();
|
||||
}
|
||||
}
|
||||
}
|
||||
26
src/zutil/net/torrent/TorrentTracker.java
Normal file
26
src/zutil/net/torrent/TorrentTracker.java
Normal 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();
|
||||
}
|
||||
}
|
||||
57
src/zutil/net/update/FileInfo.java
Normal file
57
src/zutil/net/update/FileInfo.java
Normal 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;
|
||||
}
|
||||
}
|
||||
82
src/zutil/net/update/FileListMessage.java
Normal file
82
src/zutil/net/update/FileListMessage.java
Normal 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;
|
||||
}
|
||||
}
|
||||
154
src/zutil/net/update/UpdateClient.java
Normal file
154
src/zutil/net/update/UpdateClient.java
Normal 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();
|
||||
}
|
||||
}
|
||||
15
src/zutil/net/update/UpdateConfigMessage.java
Normal file
15
src/zutil/net/update/UpdateConfigMessage.java
Normal 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;
|
||||
}
|
||||
101
src/zutil/net/update/UpdateServer.java
Normal file
101
src/zutil/net/update/UpdateServer.java
Normal 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.");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
131
src/zutil/net/update/Zupdater.java
Normal file
131
src/zutil/net/update/Zupdater.java
Normal 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);
|
||||
}
|
||||
}
|
||||
|
|
@ -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 );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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(){
|
||||
|
|
@ -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)==']' ||
|
||||
|
|
|
|||
|
|
@ -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('\"');
|
||||
|
|
|
|||
51
src/zutil/test/BoundaryBufferedInputStreamTest.java
Normal file
51
src/zutil/test/BoundaryBufferedInputStreamTest.java
Normal 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");
|
||||
}
|
||||
|
||||
}
|
||||
46
src/zutil/test/ConverterTest.java
Normal file
46
src/zutil/test/ConverterTest.java
Normal 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(") );
|
||||
}
|
||||
|
||||
}
|
||||
37
src/zutil/test/DBConnectionTest.java
Normal file
37
src/zutil/test/DBConnectionTest.java
Normal 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();
|
||||
}
|
||||
}
|
||||
}
|
||||
48
src/zutil/test/HttpURLTest.java
Normal file
48
src/zutil/test/HttpURLTest.java
Normal 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() );
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
96
src/zutil/test/SQLQueryTest.java
Normal file
96
src/zutil/test/SQLQueryTest.java
Normal 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() {
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -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+"%");
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue