First Commit after cleanup

Socket Bridge in java now works with UDP
Now connecting to remote ccnd nodes ( unless there is a firewall on the
way) currently connecting to borges on port 9695
Cleaned up the code and added authors to all files since new people are
joining the project.
Separated java from javascript code.
diff --git a/js/encoding/BinaryXMLCodec.js b/js/encoding/BinaryXMLCodec.js
new file mode 100644
index 0000000..b1befdd
--- /dev/null
+++ b/js/encoding/BinaryXMLCodec.js
@@ -0,0 +1,271 @@
+/*
+ * This class is used to encode and decode binary elements ( blog, type/value pairs)
+ * 
+ * @author: ucla-cs
+ */
+var XML_EXT = 0x00; 
+	
+var XML_TAG = 0x01; 
+	
+var XML_DTAG = 0x02; 
+	
+var XML_ATTR = 0x03; 
+ 
+var XML_DATTR = 0x04; 
+	
+var XML_BLOB = 0x05; 
+	
+var XML_UDATA = 0x06; 
+	
+var XML_CLOSE = 0x0;
+
+var XML_SUBTYPE_PROCESSING_INSTRUCTIONS = 16; 
+	
+
+var XML_TT_BITS = 3;
+var XML_TT_MASK = ((1 << XML_TT_BITS) - 1);
+var XML_TT_VAL_BITS = XML_TT_BITS + 1;
+var XML_TT_VAL_MASK = ((1 << (XML_TT_VAL_BITS)) - 1);
+var XML_REG_VAL_BITS = 7;
+var XML_REG_VAL_MASK = ((1 << XML_REG_VAL_BITS) - 1);
+var XML_TT_NO_MORE = (1 << XML_REG_VAL_BITS); // 0x80
+var BYTE_MASK = 0xFF;
+var LONG_BYTES = 8;
+var LONG_BITS = 64;
+	
+var bits_11 = 0x0000007FF;
+var bits_18 = 0x00003FFFF;
+var bits_32 = 0x0FFFFFFFF;
+
+
+var TypeAndVal = function TypeAndVal(_type,_val) {
+	this.type = _type;
+	this.val = _val;
+	
+};
+
+var BinaryXMLCodec = function BinaryXMLCodec(){
+	this.CODEC_NAME = "Binary";
+};
+    
+
+
+BinaryXMLCodec.prototype.encodeTypeAndValOffset = function(
+	//int
+	type,
+	//long
+	val,
+	//byte []
+	buf,
+	//int
+	offset) {
+	
+	if ((type > XML_UDATA) || (type < 0) || (val < 0)) {
+		throw new Exception("Tag and value must be positive, and tag valid.");
+	}
+	
+	// Encode backwards. Calculate how many bytes we need:
+	var/*int*/ numEncodingBytes = numEncodingBytes(val);
+	
+	if ((offset + numEncodingBytes) > buf.length) {
+		throw new Exception("Buffer space of " + (buf.length-offset) + 
+											" bytes insufficient to hold " + 
+											numEncodingBytes + " of encoded type and value.");
+	}
+	
+
+	buf[offset + numEncodingBytes - 1] = 
+		(BYTE_MASK &
+					(((XML_TT_MASK & type) | 
+					 ((XML_TT_VAL_MASK & val) << XML_TT_BITS))) |
+					 XML_TT_NO_MORE); 
+	val = val >>> XML_TT_VAL_BITS;;
+
+	var /*int*/ i = offset + numEncodingBytes - 2;
+	while ((0 != val) && (i >= offset)) {
+		buf[i] = (BYTE_MASK &
+						    (val & XML_REG_VAL_MASK)); 
+		val = val >>> XML_REG_VAL_BITS;
+		--i;
+	}
+	
+	return numEncodingBytes;
+};
+
+
+BinaryXMLCodec.prototype.encodeTypeAndVal = function(
+		//int
+		type, 
+		//long 
+		val, 
+		//byte [] 
+		buf, 
+		//int 
+		offset) {
+	
+	if ((type > XML_UDATA) || (type < 0) || (val < 0)) {
+		throw new Exception("Tag and value must be positive, and tag valid.");
+	}
+	
+	// Encode backwards. Calculate how many bytes we need:
+	//int
+	var numEncodingBytes = numEncodingBytes(val);
+	
+	if ((offset + numEncodingBytes) > buf.length) {
+		throw new Exception("Buffer space of " + (buf.length-offset) + 
+											" bytes insufficient to hold " + 
+											numEncodingBytes + " of encoded type and value.");
+	}
+	
+	// Bottom 4 bits of val go in last byte with tag.
+	buf[offset + numEncodingBytes - 1] = 
+		//(byte)
+			(BYTE_MASK &
+					(((XML_TT_MASK & type) | 
+					 ((XML_TT_VAL_MASK & val) << XML_TT_BITS))) |
+					 XML_TT_NO_MORE); // set top bit for last byte
+	val = val >>> XML_TT_VAL_BITS;;
+	
+	// Rest of val goes into preceding bytes, 7 bits per byte, top bit
+	// is "more" flag.
+	var i = offset + numEncodingBytes - 2;
+	while ((0 != val) && (i >= offset)) {
+		buf[i] = //(byte)
+				(BYTE_MASK &
+						    (val & XML_REG_VAL_MASK)); // leave top bit unset
+		val = val >>> XML_REG_VAL_BITS;
+		--i;
+	}
+	if (val != 0) {
+		throw new Exception( "This should not happen: miscalculated encoding");
+		//Log.warning(Log.FAC_ENCODING, "This should not happen: miscalculated encoding length, have " + val + " left.");
+	}
+	
+	return numEncodingBytes;
+}
+
+
+	
+BinaryXMLCodec.prototype.decodeTypeAndVal = function(
+		/*InputStream*/
+		istream) {
+	
+	/*int*/next;
+	/*int*/type = -1;
+	/*long*/val = 0;
+	/*boolean*/more = true;
+
+	do {
+		next = istream.read();
+		
+		if (next < 0) {
+			return null; 
+		}
+
+		if ((0 == next) && (0 == val)) {
+			return null;
+		}
+		
+		more = (0 == (next & XML_TT_NO_MORE));
+		
+		if  (more) {
+			val = val << XML_REG_VAL_BITS;
+			val |= (next & XML_REG_VAL_MASK);
+		} else {
+
+			type = next & XML_TT_MASK;
+			val = val << XML_TT_VAL_BITS;
+			val |= ((next >>> XML_TT_BITS) & XML_TT_VAL_MASK);
+		}
+		
+	} while (more);
+	
+	return new TypeAndVal(type, val);
+};
+
+BinaryXMLCodec.prototype.encodeUString = function(
+		//OutputStream 
+		ostream, 
+		//String 
+		ustring, 
+		//byte 
+		type,
+		offset) {
+	
+	// We elide the encoding of a 0-length UString
+	if ((null == ustring) || (ustring.length == 0)) {
+		//if (Log.isLoggable(Log.FAC_ENCODING, Level.FINER))
+			//Log.finer(Log.FAC_ENCODING, "Eliding 0-length UString.");
+		return;
+	}
+	
+	//byte [] data utils
+	/*custom*/
+	//byte[]
+	strBytes = new Array(ustring.Length);
+	var i = 0;
+	for( ;i<ustring.lengh;i++) //in InStr.ToCharArray())
+	{
+		strBytes[i] = ustring[i];
+	}
+	//strBytes = DataUtils.getBytesFromUTF8String(ustring);
+	
+	this.encodeTypeAndVal(type, 
+						(((type == XML_TAG) || (type == XML_ATTR)) ?
+								(strBytes.length-1) :
+								strBytes.length), ostream);
+	//
+	//console.log(strBytes.toString());
+	
+	ostream.write(strBytes.toString(),offset);
+	
+	// 
+};
+
+BinaryXMLCodec.prototype.encodeBlob = function(
+		//OutputStream 
+		ostream, 
+		//byte [] 
+		blob, 
+		//int 
+		offset, 
+		//int 
+		length) {
+	// We elide the encoding of a 0-length blob
+	if ((null == blob) || (length == 0)) {
+
+		return;
+	}
+	
+	encodeTypeAndVal(XML_BLOB, length, ostream,offset);
+	if (null != blob) {
+		ostream.write(blob, this.offset, length);
+		this.offset += length;
+	}
+};
+
+
+var ENCODING_LIMIT_1_BYTE = ((1 << (XML_TT_VAL_BITS)) - 1);
+var ENCODING_LIMIT_2_BYTES = ((1 << (XML_TT_VAL_BITS + XML_REG_VAL_BITS)) - 1);
+var ENCODING_LIMIT_3_BYTES = ((1 << (XML_TT_VAL_BITS + 2 * XML_REG_VAL_BITS)) - 1);
+
+var numEncodingBytes = function(
+		//long
+		x) {
+	if (x <= ENCODING_LIMIT_1_BYTE) return (1);
+	if (x <= ENCODING_LIMIT_2_BYTES) return (2);
+	if (x <= ENCODING_LIMIT_3_BYTES) return (3);
+	
+	var numbytes = 1;
+	
+	// Last byte gives you XML_TT_VAL_BITS
+	// Remainder each give you XML_REG_VAL_BITS
+	x = x >>> XML_TT_VAL_BITS;
+	while (x != 0) {
+        numbytes++;
+		x = x >>> XML_REG_VAL_BITS;
+	}
+	return (numbytes);
+}
+
+//TODO
\ No newline at end of file
diff --git a/js/encoding/BinaryXMLDecoder.js b/js/encoding/BinaryXMLDecoder.js
new file mode 100644
index 0000000..f70cca4
--- /dev/null
+++ b/js/encoding/BinaryXMLDecoder.js
@@ -0,0 +1,654 @@
+/*
+ * This class is used to encode and decode binary elements ( blog, type/value pairs)
+ * 
+ * @author: ucla-cs
+ */
+
+var XML_EXT = 0x00; 
+	
+var XML_TAG = 0x01; 
+	
+var XML_DTAG = 0x02; 
+	
+var XML_ATTR = 0x03; 
+ 
+var XML_DATTR = 0x04; 
+	
+var XML_BLOB = 0x05; 
+	
+var XML_UDATA = 0x06; 
+	
+var XML_CLOSE = 0x0;
+
+var XML_SUBTYPE_PROCESSING_INSTRUCTIONS = 16; 
+	
+
+var XML_TT_BITS = 3;
+var XML_TT_MASK = ((1 << XML_TT_BITS) - 1);
+var XML_TT_VAL_BITS = XML_TT_BITS + 1;
+var XML_TT_VAL_MASK = ((1 << (XML_TT_VAL_BITS)) - 1);
+var XML_REG_VAL_BITS = 7;
+var XML_REG_VAL_MASK = ((1 << XML_REG_VAL_BITS) - 1);
+var XML_TT_NO_MORE = (1 << XML_REG_VAL_BITS); // 0x80
+var BYTE_MASK = 0xFF;
+var LONG_BYTES = 8;
+var LONG_BITS = 64;
+	
+var bits_11 = 0x0000007FF;
+var bits_18 = 0x00003FFFF;
+var bits_32 = 0x0FFFFFFFF;
+
+
+
+//returns a string
+tagToString = function(/*long*/ tagVal) {
+	if ((tagVal >= 0) && (tagVal < CCNProtocolDTagsStrings.length)) {
+		return CCNProtocolDTagsStrings[tagVal];
+	} else if (tagVal == CCNProtocolDTags.CCNProtocolDataUnit) {
+		return CCNProtocolDTags.CCNPROTOCOL_DATA_UNIT;
+	}
+	return null;
+};
+
+//returns a Long
+stringToTag =  function(/*String*/ tagName) {
+	// the slow way, but right now we don't care.... want a static lookup for the forward direction
+	for (var i=0; i < CCNProtocolDTagsStrings.length; ++i) {
+		if ((null != CCNProtocolDTagsStrings[i]) && (CCNProtocolDTagsStrings[i] == tagName)) {
+			return i;
+		}
+	}
+	if (CCNProtocolDTags.CCNPROTOCOL_DATA_UNIT == tagName) {
+		return CCNProtocolDTags.CCNProtocolDataUnit;
+	}
+	return null;
+};
+
+//console.log(stringToTag(64));
+var BinaryXMLDecoder = function BinaryXMLDecoder(istream){
+	var MARK_LEN=512;
+	var DEBUG_MAX_LEN =  32768;
+	
+	this.istream = istream;
+	//console.log('istream is '+ this.istream);
+	this.offset = 0;
+};
+
+
+BinaryXMLDecoder.prototype.readStartElement =function(
+	//String
+	startTag,				    
+	//TreeMap<String, String>
+	attributes) {
+
+	try {
+		//this.TypeAndVal 
+		tv = this.decodeTypeAndVal(this.istream);
+
+		if (null == tv) {
+			throw new Exception("Expected start element: " + startTag + " got something not a tag.");
+		}
+		
+		//String 
+		decodedTag = null;
+		
+		if (tv.type() == XML_TAG) {
+			
+			decodedTag = this.decodeUString(this.Istream, tv.val()+1);
+			
+		} else if (tv.type() == XML_DTAG) {
+			decodedTag = tagToString(tv.val());	
+		}
+		
+		if ((null ==  decodedTag) || decodedTag != startTag) {
+			throw new Exception("Expected start element: " + startTag + " got: " + decodedTag + "(" + tv.val() + ")");
+		}
+		
+		if (null != attributes) {
+			readAttributes(attributes); 
+		}
+		
+	} catch (e) {
+		throw new Exception("readStartElement", e);
+	}
+};
+
+BinaryXMLDecoder.prototype.readAttributes = function(
+	//TreeMap<String,String> 
+	attributes){
+	
+	if (null == attributes) {
+		return;
+	}
+
+	try {
+
+		//this.TypeAndVal 
+		nextTV = this.peekTypeAndVal(this.istream);
+
+		while ((null != nextTV) && ((XML_ATTR == nextTV.type()) ||
+				(XML_DATTR == nextTV.type()))) {
+
+			//this.TypeAndVal 
+			thisTV = this.decodeTypeAndVal(this.Istream);
+
+			var attributeName = null;
+			if (XML_ATTR == thisTV.type()) {
+				
+				attributeName = this.decodeUString(this.istream, thisTV.val()+1);
+
+			} else if (XML_DATTR == thisTV.type()) {
+				// DKS TODO are attributes same or different dictionary?
+				attributeName = tagToString(thisTV.val());
+				if (null == attributeName) {
+					throw new ContentDecodingException("Unknown DATTR value" + thisTV.val());
+				}
+			}
+			
+			var attributeValue = this.decodeUString(this.istream);
+
+			attributes.put(attributeName, attributeValue);
+
+			nextTV = this.peekTypeAndVal(this.istream);
+		}
+
+	} catch ( e) {
+
+		throw new ContentDecodingException("readStartElement", e);
+	}
+};
+
+
+BinaryXMLDecoder.prototype.initializeDecoding = function() {
+		//if (!this.istream.markSupported()) {
+			//throw new IllegalArgumentException(this.getClass().getName() + ": input stream must support marking!");
+		//}
+}
+
+BinaryXMLDecoder.prototype.readStartDocument = function(){
+		// Currently no start document in binary encoding.
+	}
+
+BinaryXMLDecoder.prototype.readEndDocument = function() {
+		// Currently no end document in binary encoding.
+	};
+
+BinaryXMLDecoder.prototype.readStartElement = function(
+		//String 
+		startTag,
+		//TreeMap<String, String> 
+		attributes) {
+	
+		
+		//NOT SURE
+		//if(typeof startTag == 'number')
+			//startTag = tagToString(startTag);
+		
+		//try {
+			//TypeAndVal 
+			tv = this.decodeTypeAndVal(this.istream);
+			
+			if (null == tv) {
+				throw new Exception("Expected start element: " + startTag + " got something not a tag.");
+			}
+			
+			//String 
+			decodedTag = null;
+			//console.log(tv);
+			//console.log(typeof tv);
+			
+			//console.log(XML_TAG);
+			if (tv.type() == XML_TAG) {
+				//console.log('got here');
+				//Log.info(Log.FAC_ENCODING, "Unexpected: got tag in readStartElement; looking for tag " + startTag + " got length: " + (int)tv.val()+1);
+				// Tag value represents length-1 as tags can never be empty.
+				var valval ;
+				if(typeof tv.val() == 'string'){
+					valval = (parseInt(tv.val())) + 1;
+				}
+				else
+					valval = (tv.val())+ 1;
+				
+				//console.log('valval is ' +valval);
+				
+				decodedTag = this.decodeUString(this.istream,  valval);
+				
+			} else if (tv.type() == XML_DTAG) {
+				//console.log('gothere');
+				//console.log(tv.val());
+				//decodedTag = tagToString(tv.val());
+				//console.log()
+				decodedTag = tv.val();
+			}
+			
+			//console.log(decodedTag);
+			//console.log('startTag is '+startTag);
+			
+			
+			if ((null ==  decodedTag) || decodedTag != startTag ) {
+				console.log('expecting '+ startag + ' but got '+ decodedTag);
+				throw new Exception("Expected start element: " + startTag + " got: " + decodedTag + "(" + tv.val() + ")");
+			}
+			
+			// DKS: does not read attributes out of stream if caller doesn't
+			// ask for them. Should possibly peek and skip over them regardless.
+			// TODO: fix this
+			if (null != attributes) {
+				readAttributes(attributes); 
+			}
+			
+		//} catch ( e) {
+			//console.log(e);
+			//throw new Exception("readStartElement", e);
+		//}
+	}
+	
+
+BinaryXMLDecoder.prototype.readAttributes = function(
+	//TreeMap<String,String> 
+	attributes) {
+	
+	if (null == attributes) {
+		return;
+	}
+
+	try {
+		// Now need to get attributes.
+		//TypeAndVal 
+		nextTV = this.peekTypeAndVal(this.istream);
+
+		while ((null != nextTV) && ((XML_ATTR == nextTV.type()) ||
+				(XML_DATTR == nextTV.type()))) {
+
+			// Decode this attribute. First, really read the type and value.
+			//this.TypeAndVal 
+			thisTV = this.decodeTypeAndVal(this.istream);
+
+			//String 
+			attributeName = null;
+			if (XML_ATTR == thisTV.type()) {
+				// Tag value represents length-1 as attribute names cannot be empty.
+				var valval ;
+				if(typeof tv.val() == 'string'){
+					valval = (parseInt(tv.val())) + 1;
+				}
+				else
+					valval = (tv.val())+ 1;
+				
+				attributeName = this.decodeUString(this.istream,valval);
+
+			} else if (XML_DATTR == thisTV.type()) {
+				// DKS TODO are attributes same or different dictionary?
+				attributeName = tagToString(thisTV.val());
+				if (null == attributeName) {
+					throw new Exception("Unknown DATTR value" + thisTV.val());
+				}
+			}
+			// Attribute values are always UDATA
+			//String
+			attributeValue = this.decodeUString(this.istream);
+
+			//
+			attributes.push([attributeName, attributeValue]);
+
+			nextTV = this.peekTypeAndVal(this.istream);
+		}
+
+	} catch ( e) {
+		Log.logStackTrace(Log.FAC_ENCODING, Level.WARNING, e);
+		throw new Exception("readStartElement", e);
+	}
+};
+
+//returns a string
+BinaryXMLDecoder.prototype.peekStartElementAsString = function() {
+	//this.istream.mark(MARK_LEN);
+
+	//String 
+	decodedTag = null;
+	var previousOffset = this.offset;
+	try {
+		// Have to distinguish genuine errors from wrong tags. Could either use
+		// a special exception subtype, or redo the work here.
+		//this.TypeAndVal 
+		tv = this.decodeTypeAndVal(this.istream);
+
+		if (null != tv) {
+
+			if (tv.type() == XML_TAG) {
+				/*if (tv.val()+1 > DEBUG_MAX_LEN) {
+					throw new ContentDecodingException("Decoding error: length " + tv.val()+1 + " longer than expected maximum length!");
+				}*/
+
+				// Tag value represents length-1 as tags can never be empty.
+				var valval ;
+				if(typeof tv.val() == 'string'){
+					valval = (parseInt(tv.val())) + 1;
+				}
+				else
+					valval = (tv.val())+ 1;
+				
+				decodedTag = this.decodeUString(this.istream, valval);
+				
+				//Log.info(Log.FAC_ENCODING, "Unexpected: got text tag in peekStartElement; length: " + valval + " decoded tag = " + decodedTag);
+
+			} else if (tv.type() == XML_DTAG) {
+				decodedTag = tagToString(tv.val());					
+			}
+
+		} // else, not a type and val, probably an end element. rewind and return false.
+
+	} catch ( e) {
+
+	} finally {
+		try {
+			this.offset = previousOffset;
+		} catch ( e) {
+			Log.logStackTrace(Log.FAC_ENCODING, Level.WARNING, e);
+			throw new ContentDecodingException("Cannot reset stream! " + e.getMessage(), e);
+		}
+	}
+	return decodedTag;
+};
+
+BinaryXMLDecoder.prototype.peekStartElement = function(
+		//String 
+		startTag) {
+	//String 
+	if(typeof startTag == 'string'){
+		decodedTag = this.peekStartElementAsString();
+		
+		if ((null !=  decodedTag) && decodedTag == startTag) {
+			return true;
+		}
+		return false;
+	}
+	else if(typeof startTag == 'number'){
+		decodedTag = this.peekStartElementAsLong();
+		if ((null !=  decodedTag) && decodedTag == startTag) {
+			return true;
+		}
+		return false;
+	}
+	else{
+		throw new Exception("SHOULD BE STRING OR NUMBER");
+	}
+}
+//returns Long
+BinaryXMLDecoder.prototype.peekStartElementAsLong = function() {
+		//this.istream.mark(MARK_LEN);
+
+		//Long
+		decodedTag = null;
+		
+		var previousOffset = this.offset;
+		
+		try {
+			// Have to distinguish genuine errors from wrong tags. Could either use
+			// a special exception subtype, or redo the work here.
+			//this.TypeAndVal
+			tv = this.decodeTypeAndVal(this.istream);
+
+			if (null != tv) {
+
+				if (tv.type() == XML_TAG) {
+					if (tv.val()+1 > DEBUG_MAX_LEN) {
+						throw new ContentDecodingException("Decoding error: length " + tv.val()+1 + " longer than expected maximum length!");
+					}
+
+					var valval ;
+					if(typeof tv.val() == 'string'){
+						valval = (parseInt(tv.val())) + 1;
+					}
+					else
+						valval = (tv.val())+ 1;
+					
+					// Tag value represents length-1 as tags can never be empty.
+					//String 
+					strTag = this.decodeUString(this.istream, valval);
+					
+					decodedTag = stringToTag(strTag);
+					
+					//Log.info(Log.FAC_ENCODING, "Unexpected: got text tag in peekStartElement; length: " + valval + " decoded tag = " + decodedTag);
+					
+				} else if (tv.type() == XML_DTAG) {
+					decodedTag = tv.val();					
+				}
+
+			} // else, not a type and val, probably an end element. rewind and return false.
+
+		} catch ( e) {
+			
+		} finally {
+			try {
+				//this.istream.reset();
+				this.offset = previousOffset;
+			} catch ( e) {
+				Log.logStackTrace(Log.FAC_ENCODING, Level.WARNING, e);
+				throw new Exception("Cannot reset stream! " + e.getMessage(), e);
+			}
+		}
+		return decodedTag;
+	};
+
+
+// returns a byte[]
+BinaryXMLDecoder.prototype.readBinaryElement = function(
+		//long 
+		startTag,
+		//TreeMap<String, String> 
+		attributes){
+	//byte [] 
+	blob = null;
+	
+		this.readStartElement(startTag, attributes);
+		blob = this.readBlob();
+	
+
+	return blob;
+
+};
+	
+	
+BinaryXMLDecoder.prototype.readEndElement = function(){
+		try {
+			var next = this.istream[this.offset]; 
+			this.offset++;
+			//read();
+			if (next != XML_CLOSE) {
+				throw new ContentDecodingException("Expected end element, got: " + next);
+			}
+		} catch ( e) {
+			throw new ContentDecodingException(e);
+		}
+	};
+
+
+//String	
+BinaryXMLDecoder.prototype.readUString = function(){
+			//String 
+			ustring = this.decodeUString(this.istream);	
+			this.readEndElement();
+			return ustring;
+
+	};
+	
+
+//returns a byte[]
+BinaryXMLDecoder.prototype.readBlob = function() {
+			//byte []
+			
+			blob = this.decodeBlob(this.istream);	
+			this.readEndElement();
+			return blob;
+
+	};
+
+
+//CCNTime
+BinaryXMLDecoder.prototype.readDateTime = function(
+	//long 
+	startTag)  {
+	//byte [] 
+	
+	byteTimestamp = this.readBinaryElement(startTag);
+	//CCNTime 
+	timestamp = new CCNTime();
+	timestamp.setDateBinary(byteTimestamp);
+	
+	if (null == timestamp) {
+		throw new ContentDecodingException("Cannot parse timestamp: " + DataUtils.printHexBytes(byteTimestamp));
+	}		
+	return timestamp;
+};
+
+BinaryXMLDecoder.prototype.decodeTypeAndVal = function(
+		/*InputStream*/
+		istream) {
+	
+	/*int*/next;
+	/*int*/type = -1;
+	/*long*/val = 0;
+	/*boolean*/more = true;
+
+	
+	//var savedOffset = this.offset;
+	var count = 0;
+	
+	do {
+		
+		var next = this.istream[this.offset ];
+		
+		
+		if (next < 0) {
+			return null; 
+		}
+
+		if ((0 == next) && (0 == val)) {
+			return null;
+		}
+		
+		more = (0 == (next & XML_TT_NO_MORE));
+		
+		if  (more) {
+			val = val << XML_REG_VAL_BITS;
+			val |= (next & XML_REG_VAL_MASK);
+		} else {
+
+			type = next & XML_TT_MASK;
+			val = val << XML_TT_VAL_BITS;
+			val |= ((next >>> XML_TT_BITS) & XML_TT_VAL_MASK);
+		}
+		
+		this.offset++;
+		
+	} while (more);
+	
+	return new TypeAndVal(type, val);
+};
+
+
+
+//TypeAndVal
+BinaryXMLDecoder.peekTypeAndVal = function(
+		//InputStream 
+		istream) {
+	//TypeAndVal 
+	tv = null;
+	
+	//istream.mark(LONG_BYTES*2);		
+	
+	var previousOffset = this.offset;
+	
+	try {
+		tv = this.decodeTypeAndVal(this.istream);
+	} finally {
+		//istream.reset();
+		this.offset = previousOffset;
+	}
+	
+	return tv;
+};
+
+
+//byte[]
+BinaryXMLDecoder.prototype.decodeBlob = function(
+		//InputStream 
+		istream, 
+		//int 
+		blobLength) {
+	
+	
+	if(null == blobLength){
+		//TypeAndVal
+		tv = this.decodeTypeAndVal(this.istream);
+
+		var valval ;
+		if(typeof tv.val() == 'string'){
+			valval = (parseInt(tv.val()));
+		}
+		else
+			valval = (tv.val());
+		
+		//console.log('valval here is ' + valval);
+		return  this.decodeBlob(this.istream, valval);
+	}
+	
+	//
+	//byte [] 
+
+	bytes = this.istream.slice(this.offset, this.offset+ blobLength);
+	this.offset += blobLength;
+	
+	//int 
+	return bytes;
+	
+	count = 0;
+
+};
+
+
+
+//String
+BinaryXMLDecoder.prototype.decodeUString = function(
+		//InputStream 
+		istream, 
+		//int 
+		byteLength) {
+	
+	if(null == byteLength){
+		tv = this.decodeTypeAndVal(this.istream);
+		var valval ;
+		if(typeof tv.val() == 'string'){
+			valval = (parseInt(tv.val()));
+		}
+		else
+			valval = (tv.val());
+		
+		byteLength= this.decodeUString(this.istream, valval);
+	}
+
+	stringBytes = this.decodeBlob(this.istream, byteLength);
+	
+	tempBuffer = this.istream.slice(this.offset, this.offset+byteLength);
+	this.offset+= byteLength;
+	console.log('read the String' + tempBuffer.toString('ascii'));
+	return tempBuffer.toString('ascii');//DataUtils.getUTF8StringFromBytes(stringBytes);
+};
+
+
+//OBject containg a pair of type and value
+var TypeAndVal = function TypeAndVal(_type,_val) {
+	this.t = _type;
+	this.v = _val;
+	
+};
+
+TypeAndVal.prototype.type = function(){
+	return this.t;
+};
+
+TypeAndVal.prototype.val = function(){
+	return this.v;
+};
+//TODO
\ No newline at end of file
diff --git a/js/encoding/BinaryXMLEncoder.js b/js/encoding/BinaryXMLEncoder.js
new file mode 100644
index 0000000..f05a869
--- /dev/null
+++ b/js/encoding/BinaryXMLEncoder.js
@@ -0,0 +1,340 @@
+/*
+ * This class is used to encode and decode binary elements ( blog, type/value pairs)
+ * 
+ * @author: ucla-cs
+ */
+
+var XML_EXT = 0x00; 
+	
+var XML_TAG = 0x01; 
+	
+var XML_DTAG = 0x02; 
+	
+var XML_ATTR = 0x03; 
+ 
+var XML_DATTR = 0x04; 
+	
+var XML_BLOB = 0x05; 
+	
+var XML_UDATA = 0x06; 
+	
+var XML_CLOSE = 0x0;
+
+var XML_SUBTYPE_PROCESSING_INSTRUCTIONS = 16; 
+	
+
+var XML_TT_BITS = 3;
+var XML_TT_MASK = ((1 << XML_TT_BITS) - 1);
+var XML_TT_VAL_BITS = XML_TT_BITS + 1;
+var XML_TT_VAL_MASK = ((1 << (XML_TT_VAL_BITS)) - 1);
+var XML_REG_VAL_BITS = 7;
+var XML_REG_VAL_MASK = ((1 << XML_REG_VAL_BITS) - 1);
+var XML_TT_NO_MORE = (1 << XML_REG_VAL_BITS); // 0x80
+var BYTE_MASK = 0xFF;
+var LONG_BYTES = 8;
+var LONG_BITS = 64;
+	
+var bits_11 = 0x0000007FF;
+var bits_18 = 0x00003FFFF;
+var bits_32 = 0x0FFFFFFFF;
+
+
+var BinaryXMLEncoder = function BinaryXMLEncoder(){
+
+	this.ostream = new Array(10000);
+	
+	
+	this.offset =0;
+	
+	this.CODEC_NAME = "Binary";
+	
+};
+
+BinaryXMLEncoder.prototype.writeUString = function(/*String*/ utf8Content){
+	this.encodeUString(this.ostream, utf8Content);
+};
+
+BinaryXMLEncoder.prototype.writeBlob = function(/*byte []*/ binaryContent
+		//, /*int*/ offset, /*int*/ length
+		)  {
+	console.log(binaryContent);
+	this.encodeBlob(this.ostream, binaryContent, this.offset, binaryContent.length);
+};
+
+BinaryXMLEncoder.prototype.writeStartElement = function(/*String*/ tag, /*TreeMap<String,String>*/ attributes){
+
+	/*Long*/ dictionaryVal = tag;//stringToTag(tag);
+	
+	if (null == dictionaryVal) {
+
+		this.encodeUString(this.ostream, tag, XML_TAG);
+		
+	} else {
+		this.encodeTypeAndVal(XML_DTAG, dictionaryVal, this.ostream);
+	}
+	
+	if (null != attributes) {
+		this.writeAttributes(attributes); 
+	}
+};
+
+
+BinaryXMLEncoder.prototype.writeEndElement = function(){
+
+	this.ostream[this.offset] = XML_CLOSE;
+	this.offset+= 1;
+}
+
+BinaryXMLEncoder.prototype.writeAttributes = function(/*TreeMap<String,String>*/ attributes) {
+	
+	if (null == attributes) {
+		return;
+	}
+
+	// the keySet of a TreeMap is sorted.
+
+	for(var i=0; i<attributes.length;i++){
+		var strAttr = attributes[i].k;
+		var strValue = attributes[i].v;
+
+		var dictionaryAttr = stringToTag(strAttr);
+		if (null == dictionaryAttr) {
+			// not in dictionary, encode as attr
+			// compressed format wants length of tag represented as length-1
+			// to save that extra bit, as tag cannot be 0 length.
+			// encodeUString knows to do that.
+			this.encodeUString(this.ostream, strAttr, XML_ATTR);
+		} else {
+			this.encodeTypeAndVal(XML_DATTR, dictionaryAttr, this.ostream);
+		}
+		// Write value
+		this.encodeUString(this.ostream, strValue);
+		
+	}
+
+	
+}
+
+//returns a string
+stringToTag = function(/*long*/ tagVal) {
+	if ((tagVal >= 0) && (tagVal < CCNProtocolDTagsStrings.length)) {
+		return CCNProtocolDTagsStrings[tagVal];
+	} else if (tagVal == CCNProtocolDTags.CCNProtocolDataUnit) {
+		return CCNProtocolDTags.CCNPROTOCOL_DATA_UNIT;
+	}
+	return null;
+};
+
+//returns a Long
+tagToString =  function(/*String*/ tagName) {
+	// the slow way, but right now we don't care.... want a static lookup for the forward direction
+	for (var i=0; i < CCNProtocolDTagsStrings.length; ++i) {
+		if ((null != CCNProtocolDTagsStrings[i]) && (CCNProtocolDTagsStrings[i] == tagName)) {
+			return i;
+		}
+	}
+	if (CCNProtocolDTags.CCNPROTOCOL_DATA_UNIT == tagName) {
+		return CCNProtocolDTags.CCNProtocolDataUnit;
+	}
+	return null;
+};
+
+
+BinaryXMLEncoder.prototype.writeElement = function(
+		//long 
+		tag, 
+		//byte[] 
+		binaryContent,
+		//TreeMap<String, String> 
+		attributes) {
+	this.writeStartElement(tag, attributes);
+	// Will omit if 0-length
+	
+	this.writeBlob(binaryContent);
+	this.writeEndElement();
+}
+
+//TODO
+
+var TypeAndVal = function TypeAndVal(_type,_val) {
+	this.type = _type;
+	this.val = _val;
+	
+};
+
+BinaryXMLEncoder.prototype.encodeTypeAndVal = function(
+		//int
+		type, 
+		//long 
+		val, 
+		//byte [] 
+		buf) {
+	
+	console.log('Encoding type '+ type+ ' and value '+ val);
+	
+	if ((type > XML_UDATA) || (type < 0) || (val < 0)) {
+		throw new Exception("Tag and value must be positive, and tag valid.");
+	}
+	
+	// Encode backwards. Calculate how many bytes we need:
+	var numEncodingBytes = this.numEncodingBytes(val);
+	
+	if ((this.offset + numEncodingBytes) > buf.length) {
+		throw new Exception("Buffer space of " + (buf.length-this.offset) + 
+											" bytes insufficient to hold " + 
+											numEncodingBytes + " of encoded type and value.");
+	}
+
+	// Bottom 4 bits of val go in last byte with tag.
+	buf[this.offset + numEncodingBytes - 1] = 
+		//(byte)
+			(BYTE_MASK &
+					(((XML_TT_MASK & type) | 
+					 ((XML_TT_VAL_MASK & val) << XML_TT_BITS))) |
+					 XML_TT_NO_MORE); // set top bit for last byte
+	val = val >>> XML_TT_VAL_BITS;;
+	
+	// Rest of val goes into preceding bytes, 7 bits per byte, top bit
+	// is "more" flag.
+	var i = this.offset + numEncodingBytes - 2;
+	while ((0 != val) && (i >= this.offset)) {
+		buf[i] = //(byte)
+				(BYTE_MASK &
+						    (val & XML_REG_VAL_MASK)); // leave top bit unset
+		val = val >>> XML_REG_VAL_BITS;
+		--i;
+	}
+	if (val != 0) {
+		throw new Exception( "This should not happen: miscalculated encoding");
+		//Log.warning(Log.FAC_ENCODING, "This should not happen: miscalculated encoding length, have " + val + " left.");
+	}
+	this.offset+= numEncodingBytes;
+	
+	return numEncodingBytes;
+};
+
+BinaryXMLEncoder.prototype.encodeUString = function(
+		//OutputStream 
+		ostream, 
+		//String 
+		ustring, 
+		//byte 
+		type) {
+	
+	if ((null == ustring) || (ustring.length == 0)) {
+		return;
+	}
+	
+	
+	//byte [] data utils
+	/*custom*/
+	//byte[]
+	strBytes = new Array(ustring.Length);
+	var i = 0;
+	for( ;i<ustring.lengh;i++) //in InStr.ToCharArray())
+	{
+		strBytes[i] = ustring[i];
+	}
+	//strBytes = DataUtils.getBytesFromUTF8String(ustring);
+	
+	this.encodeTypeAndVal(type, 
+						(((type == XML_TAG) || (type == XML_ATTR)) ?
+								(strBytes.length-1) :
+								strBytes.length), ostream);
+	
+
+	this.writeString(strBytes,this.offset);
+	
+	this.offset+= strBytes.length;
+
+};
+
+
+
+BinaryXMLEncoder.prototype.encodeBlob = function(
+		//OutputStream 
+		ostream, 
+		//byte [] 
+		blob, 
+		//int 
+		offset, 
+		//int 
+		length) {
+
+
+	if ((null == blob) || (length == 0)) {
+
+		return;
+	}
+	
+	
+	this.encodeTypeAndVal(XML_BLOB, length, ostream,offset);
+	
+	if (null != blob) {
+
+		this.writeString(blob,this.offset);
+		this.offset += length;
+	}
+};
+
+var ENCODING_LIMIT_1_BYTE = ((1 << (XML_TT_VAL_BITS)) - 1);
+var ENCODING_LIMIT_2_BYTES = ((1 << (XML_TT_VAL_BITS + XML_REG_VAL_BITS)) - 1);
+var ENCODING_LIMIT_3_BYTES = ((1 << (XML_TT_VAL_BITS + 2 * XML_REG_VAL_BITS)) - 1);
+
+BinaryXMLEncoder.prototype.numEncodingBytes = function(
+		//long
+		x) {
+	if (x <= ENCODING_LIMIT_1_BYTE) return (1);
+	if (x <= ENCODING_LIMIT_2_BYTES) return (2);
+	if (x <= ENCODING_LIMIT_3_BYTES) return (3);
+	
+	var numbytes = 1;
+	
+	// Last byte gives you XML_TT_VAL_BITS
+	// Remainder each give you XML_REG_VAL_BITS
+	x = x >>> XML_TT_VAL_BITS;
+	while (x != 0) {
+        numbytes++;
+		x = x >>> XML_REG_VAL_BITS;
+	}
+	return (numbytes);
+};
+
+BinaryXMLEncoder.prototype.writeDateTime = function(
+		//String 
+		tag, 
+		//CCNTime 
+		dateTime) {
+	this.writeElement(tag, dateTime.toBinaryTime());
+};
+
+BinaryXMLEncoder.prototype.writeString = function(
+		//String 
+		input,
+		//CCNTime 
+		offset) {
+	
+	
+	for (var i = 0; i < input.length; i++) {
+	    this.ostream[this.offset+i] = (input.charCodeAt(i));
+	}
+	
+};
+
+BinaryXMLEncoder.prototype.writeBlobArray = function(
+		//String 
+		Blob,
+		//CCNTime 
+		offset) {
+	
+	for (var i = 0; i < Blob.length; i++) {
+	    this.ostream[this.offset+i] = Blob[i];
+	}
+	
+};
+BinaryXMLEncoder.prototype.getReducedOstream = function() {
+	
+	return this.ostream.slice(0,this.offset);
+	
+};
+
diff --git a/js/encoding/DataUtils.js b/js/encoding/DataUtils.js
new file mode 100644
index 0000000..92a4257
--- /dev/null
+++ b/js/encoding/DataUtils.js
@@ -0,0 +1,137 @@
+
+/*
+ * This class contains utilities to help parse the data
+ * author: ucla-cs
+ */
+ 
+var DataUtils = function DataUtils(){
+	
+	
+};
+
+
+/*
+ * NOTE THIS IS CURRENTLY NOT BEHING USED
+ * 
+ */
+
+  var keyStr = "ABCDEFGHIJKLMNOP" +
+               "QRSTUVWXYZabcdef" +
+               "ghijklmnopqrstuv" +
+               "wxyz0123456789+/" +
+               "=";
+
+DataUtils.encode64=function encode64(input) {
+     input = escape(input);
+     var output = "";
+     var chr1, chr2, chr3 = "";
+     var enc1, enc2, enc3, enc4 = "";
+     var i = 0;
+
+     do {
+        chr1 = input.charCodeAt(i++);
+        chr2 = input.charCodeAt(i++);
+        chr3 = input.charCodeAt(i++);
+
+        enc1 = chr1 >> 2;
+        enc2 = ((chr1 & 3) << 4) | (chr2 >> 4);
+        enc3 = ((chr2 & 15) << 2) | (chr3 >> 6);
+        enc4 = chr3 & 63;
+
+        if (isNaN(chr2)) {
+           enc3 = enc4 = 64;
+        } else if (isNaN(chr3)) {
+           enc4 = 64;
+        }
+
+        output = output +
+           keyStr.charAt(enc1) +
+           keyStr.charAt(enc2) +
+           keyStr.charAt(enc3) +
+           keyStr.charAt(enc4);
+        chr1 = chr2 = chr3 = "";
+        enc1 = enc2 = enc3 = enc4 = "";
+     } while (i < input.length);
+
+     return output;
+  }
+
+DataUtils.decode64 = function decode64(input) {
+     var output = "";
+     var chr1, chr2, chr3 = "";
+     var enc1, enc2, enc3, enc4 = "";
+     var i = 0;
+
+     // remove all characters that are not A-Z, a-z, 0-9, +, /, or =
+     var base64test = /[^A-Za-z0-9\+\/\=]/g;
+     if (base64test.exec(input)) {
+        alert("There were invalid base64 characters in the input text.\n" +
+              "Valid base64 characters are A-Z, a-z, 0-9, '+', '/',and '='\n" +
+              "Expect errors in decoding.");
+     }
+     input = input.replace(/[^A-Za-z0-9\+\/\=]/g, "");
+
+     do {
+        enc1 = keyStr.indexOf(input.charAt(i++));
+        enc2 = keyStr.indexOf(input.charAt(i++));
+        enc3 = keyStr.indexOf(input.charAt(i++));
+        enc4 = keyStr.indexOf(input.charAt(i++));
+
+        chr1 = (enc1 << 2) | (enc2 >> 4);
+        chr2 = ((enc2 & 15) << 4) | (enc3 >> 2);
+        chr3 = ((enc3 & 3) << 6) | enc4;
+
+        output = output + String.fromCharCode(chr1);
+
+        if (enc3 != 64) {
+           output = output + String.fromCharCode(chr2);
+        }
+        if (enc4 != 64) {
+           output = output + String.fromCharCode(chr3);
+        }
+
+        chr1 = chr2 = chr3 = "";
+        enc1 = enc2 = enc3 = enc4 = "";
+
+     } while (i < input.length);
+
+     return unescape(output);
+  };
+  
+  
+
+
+
+//byte [] 
+DataUtils.prototype.unsignedLongToByteArray= function( value) {
+	if( 0 == value )
+		return [0];
+
+	if( 0 <= value && value <= 0x00FF ) {
+		//byte [] 
+		bb = new Array[1];
+		bb[0] = (value & 0x00FF);
+		return bb;
+	}
+
+	
+	//byte [] 
+	out = null;
+	//int
+	var offset = -1;
+	for(var i = 7; i >=0; --i) {
+		//byte
+		b = ((value >> (i * 8)) & 0xFF);
+		if( out == null && b != 0 ) {
+			out = new byte[i+1];
+			offset = i;
+		}
+		if( out != null )
+			out[ offset - i ] = b;
+	}
+	return out;
+}
+
+
+
+
diff --git a/js/encoding/TextXMLCodec.js b/js/encoding/TextXMLCodec.js
new file mode 100644
index 0000000..716aa6d
--- /dev/null
+++ b/js/encoding/TextXMLCodec.js
@@ -0,0 +1,59 @@
+//TODO INCOMPLETE
+/*
+ * @author: ucla-cs
+ * 
+ * Encodes CCN object into xml tags
+ */
+var DataUtils = require('./DataUtils').DataUtils;
+	
+ 	var /*DateFormat*/ canonicalWriteDateFormat = null;
+	var /* DateFormat*/ canonicalReadDateFormat = null;
+    var /*String*/ PAD_STRING = "000000000";
+	var /*int*/ NANO_LENGTH = 9;
+
+var TextXMLCodec =  function TextXMLCodec(){
+
+	this.CCN_NAMESPACE = "http://www.parc.com/ccn"; // String
+	this.CCN_PREFIX = "ccn";	// String
+	this.CODEC_NAME = "Text";// String
+	this.BINARY_ATTRIBUTE = "ccnbencoding";// String
+	this.BINARY_ATTRIBUTE_VALUE = "base64Binary";// String
+
+
+};
+
+//returns a string
+
+TextXMLCodec.protpotype.codecName = function() { return this.CODEC_NAME; }	;
+
+//returns a string
+TextXMLCodec.protottype.encodeBinaryElement = function(/*byte []*/ element) {
+		if ((null == element) || (0 == element.length)) 
+			return new String("");
+		return new String(DataUtils.base64Encode(element));
+	};
+	
+/* returns a string */
+TextXMLCodec.prototype.encodeBinaryElement = function(/*byte []*/ element, /*int*/ offset, /*int*/ length) {
+		if ((null == element) || (0 == element.length)) 
+			return new String("");
+		ByteBuffer bbuf = ByteBuffer.wrap(element, offset, length);
+		return new String(DataUtils.base64Encode(bbuf.array()));
+	};
+
+/*returns a byte array*/
+TextXMLCodec.prototype.decodeBinaryElement = function(/*String*/ element) {
+		if ((null == element) || (0 == element.length()))
+			return new byte[0];
+		return DataUtils.base64Decode(element.getBytes());
+	}; 
+
+	
+/*
+	Decode Data
+*/
+	
+
+/*
+	Encode Date
+*/ 
\ No newline at end of file
diff --git a/js/encoding/TextXMLDecoder.js b/js/encoding/TextXMLDecoder.js
new file mode 100644
index 0000000..6af8be3
--- /dev/null
+++ b/js/encoding/TextXMLDecoder.js
@@ -0,0 +1,232 @@
+//TODO INCOMPLETE
+
+/*
+ * @author: ucla-cs
+ * 
+ * Decodes CCN object into xml
+ */
+
+var TextXMLDecoder = function TextXMLDecoder(){
+
+	this.reader = null;
+	
+};
+
+
+exports.TextXMLDecoder = TextXMLDecoder;
+
+
+exports.prototype.initializeDecoding = function(){
+	try {
+		XmlPullParserFactory factory = XmlPullParserFactory.newInstance();
+        factory.setNamespaceAware(true);
+		_reader = factory.newPullParser();
+		_reader.setInput(_istream, null);
+	} catch (XmlPullParserException e) {
+		throw new ContentDecodingException(e.getMessage(), e);
+	}		
+};
+
+exports.prototype.readStartDocument = function(){
+	try {
+		int event = _reader.getEventType();
+		_reader.next();
+		if (event != XmlPullParser.START_DOCUMENT) {
+			throw new ContentDecodingException("Expected start document, got: " + XmlPullParser.TYPES[event]);
+		}
+	} catch (XmlPullParserException e) {
+		throw new ContentDecodingException(e.getMessage(), e);
+	} catch (IOException e) {
+		throw new ContentDecodingException(e.getMessage(), e);
+	}
+};
+
+public void readEndDocument() throws ContentDecodingException {
+	int event;
+	try {
+		event = _reader.getEventType();
+	} catch (XmlPullParserException e) {
+		throw new ContentDecodingException(e.getMessage(), e);
+	}
+	if (event != XmlPullParser.END_DOCUMENT) {
+		throw new ContentDecodingException("Expected end document, got: " + XmlPullParser.TYPES[event]);
+	}
+};
+
+exports.prototype.readStartElement = function(/*String*/ startTag,
+							TreeMap<String, String> attributes) throws ContentDecodingException {
+
+	int event = readToNextTag(XmlPullParser.START_TAG);
+	if (event != XmlPullParser.START_TAG) {
+		throw new ContentDecodingException("Expected start element, got: " + XmlPullParser.TYPES[event]);
+	}
+	// Use getLocalPart to strip namespaces.
+	// Assumes we are working with a global default namespace of CCN.
+	if (!startTag.equals(_reader.getName())) {
+		// Coming back with namespace decoration doesn't match
+		throw new ContentDecodingException("Expected start element: " + startTag + " got: " + _reader.getName());
+	}	
+	if (null != attributes) {
+		// we might be expecting attributes
+		for (int i=0; i < _reader.getAttributeCount(); ++i) {
+			// may need fancier namespace handling.
+			attributes.put(_reader.getAttributeName(i), _reader.getAttributeValue(i));
+		}
+	}
+	try {
+		_reader.next();
+	} catch (XmlPullParserException e) {
+		throw new ContentDecodingException(e.getMessage());
+	} catch (IOException e) {
+		throw new ContentDecodingException(e.getMessage());
+	}
+}
+
+	public void readStartElement(long startTagLong,
+			TreeMap<String, String> attributes) throws ContentDecodingException {
+		
+		String startTag = tagToString(startTagLong);
+
+		int event = readToNextTag(XmlPullParser.START_TAG);
+		if (event != XmlPullParser.START_TAG) {
+			throw new ContentDecodingException("Expected start element, got: " + XmlPullParser.TYPES[event]);
+		}
+		// Use getLocalPart to strip namespaces.
+		// Assumes we are working with a global default namespace of CCN.
+		if (!startTag.equals(_reader.getName())) {
+			// Coming back with namespace decoration doesn't match
+			throw new ContentDecodingException("Expected start element: " + startTag + " got: " + _reader.getName());
+		}	
+		if (null != attributes) {
+			// we might be expecting attributes
+			for (int i=0; i < _reader.getAttributeCount(); ++i) {
+				// may need fancier namespace handling.
+				attributes.put(_reader.getAttributeName(i), _reader.getAttributeValue(i));
+			}
+		}
+		try {
+			_reader.next();
+		} catch (XmlPullParserException e) {
+			throw new ContentDecodingException(e.getMessage());
+		} catch (IOException e) {
+			throw new ContentDecodingException(e.getMessage());
+		}
+	}
+	public String peekStartElementAsString() throws ContentDecodingException {
+		int event = readToNextTag(XmlPullParser.START_TAG);
+		if (event != XmlPullParser.START_TAG) {
+			return null;
+		}
+		return _reader.getName();
+	}
+	
+	public Long peekStartElementAsLong() throws ContentDecodingException {
+		String strTag = peekStartElementAsString();
+		if (null == strTag) {
+			return null; // e.g. hit an end tag...
+		}
+		return stringToTag(strTag);
+	}
+	
+	/**
+	 * Helper method to decode text (UTF-8) and binary elements. Consumes the end element,
+	 * behavior which other decoders are forced to match.
+	 * @return the read data, as a String
+	 * @throws ContentDecodingException if there is a problem decoding the data
+	 */
+	public String readUString() throws ContentDecodingException {
+		StringBuffer buf = new StringBuffer();
+		try {
+			int event = _reader.getEventType();;
+			// Handles empty text element.
+			while (event == XmlPullParser.TEXT) {
+				buf.append(_reader.getText());
+				event = _reader.next();
+			}
+			if (event == XmlPullParser.START_TAG) {
+				throw new ContentDecodingException("readElementText expects start element to have been previously consumed, got: " + XmlPullParser.TYPES[event]);
+			} else if (event != XmlPullParser.END_TAG) {
+				throw new ContentDecodingException("Expected end of text element, got: " + XmlPullParser.TYPES[event]);
+			}
+			readEndElement();
+			return buf.toString();
+		} catch (XmlPullParserException e) {
+			throw new ContentDecodingException(e.getMessage(), e);
+		} catch (IOException e) {
+			throw new ContentDecodingException(e.getMessage(), e);
+		}
+	}
+
+	public void readEndElement() throws ContentDecodingException {
+		int event = readToNextTag(XmlPullParser.END_TAG);
+		if (event != XmlPullParser.END_TAG) {
+			throw new ContentDecodingException("Expected end element, got: " + XmlPullParser.TYPES[event]);
+		}
+		try {
+			_reader.next();
+		} catch (XmlPullParserException e) {
+			throw new ContentDecodingException(e.getMessage());
+		} catch (IOException e) {
+			throw new ContentDecodingException(e.getMessage());
+		}
+	}
+
+	/**
+	 * Read a BLOB. Consumes the end element, so force other versions
+	 * to match.
+	 */
+	public byte [] readBlob() throws ContentDecodingException {
+		try {
+			String strElementText = readUString();
+			// readEndElement(); // readElementText consumes end element
+			return TextXMLCodec.decodeBinaryElement(strElementText);
+		} catch (IOException e) {
+			throw new ContentDecodingException(e.getMessage(),e);
+		}
+	}
+	
+	public CCNTime readDateTime(String startTag) throws ContentDecodingException {
+		String strTimestamp = readUTF8Element(startTag);
+		CCNTime timestamp;
+		try {
+			timestamp = TextXMLCodec.parseDateTime(strTimestamp);
+		} catch (ParseException e) {
+			timestamp = null;
+		}
+		if (null == timestamp) {
+			throw new ContentDecodingException("Cannot parse timestamp: " + strTimestamp);
+		}		
+		return timestamp;
+	}
+
+	public CCNTime readDateTime(long startTag) throws ContentDecodingException {
+		String strTimestamp = readUTF8Element(startTag);
+		CCNTime timestamp;
+		try {
+			timestamp = TextXMLCodec.parseDateTime(strTimestamp);
+		} catch (ParseException e) {
+			timestamp = null;
+		}
+		if (null == timestamp) {
+			throw new ContentDecodingException("Cannot parse timestamp: " + strTimestamp);
+		}		
+		return timestamp;
+	}
+
+	private int readToNextTag(int type) throws ContentDecodingException {
+		int event;
+		try {
+			event = _reader.getEventType();
+			if (event == type)
+				return event;
+			if (event == XmlPullParser.TEXT || event == XmlPullParser.COMMENT)
+				event = _reader.next();
+		} catch (IOException e) {
+			throw new ContentDecodingException(e.getMessage(), e);
+		} catch (XmlPullParserException e) {
+			throw new ContentDecodingException(e.getMessage(), e);
+		}
+		return event;
+	}
+
+};
diff --git a/js/encoding/TextXMLEncoder.js b/js/encoding/TextXMLEncoder.js
new file mode 100644
index 0000000..495984b
--- /dev/null
+++ b/js/encoding/TextXMLEncoder.js
@@ -0,0 +1,109 @@
+//TODO INCOMPLETE
+/*
+ * @author: ucla-cs
+ * 
+ * Encodes CCN object into xml
+ */
+
+var Stream = require('stream').Stream;
+var TextXMLCodec = require('TextXMLCodec').TextXMLCodec;
+
+
+
+
+var TextXMLEncoder  = function TextXMLEncoder(){
+
+
+	this.ostream = new String();
+};
+
+exports.TextXMLEncoder = TextXMLEncoder;
+
+TextXMLEncoder.prototype.beginEncoding = function(/*OutputStream*/ ostream){
+		if (null == ostream)
+			throw new IllegalArgumentException("TextXMLEncoder: output stream cannot be null!");
+		
+		
+		/*Start by encoing the begining*/
+		//this.IStream = ostream;
+		this.ostream.write('<?xml version="1.0" encoding="UTF-8"?>');
+};
+
+TextXMLEncoder.prototype.endEncoding =function() {
+	this.IStream.end();
+}
+
+
+TextXMLEncoder.prorotype.writeStartElement(/*String*/ tag, /*TreeMap<String, String>*/ attributes) {
+		
+	
+		this.ostream.write('<'+tab);
+
+		if (null != attributes) {
+			
+			for(var i=0; i<attributes.length;i++){
+				this.ostream.write(' '+attributes[i].key +'='+attributes[i].value);
+			}
+		
+			// keySet of a TreeMap is ordered
+		}
+		this.ostream.write('>');
+};
+
+TextXMLEncoder.prototype.writeUString = function(/*String*/ utf8Content) {
+
+		this.ostream.write(utf8Content);
+
+};
+
+
+TextXMLEncoder.prototype.writeBlob =  function(/*byte []*/ binaryContent, /*int*/ offset, /*int*/ length) {
+
+		this.ostream.write(TextXMLCodec.encodeBinaryElement(binaryContent, offset, length));
+
+};
+
+TextXMLEncoder.prototype.writeElement = function(/*String*/ tag, /*byte[]*/ binaryContent,
+			/*TreeMap<String, String>*/ attributes)  {
+		
+		/*if (null == attributes) {
+		
+			attributes = new TreeMap<String,String>();
+		}*/
+		if (!attributes.containsKey(TextXMLCodec.BINARY_ATTRIBUTE)) {
+			attributes.put(TextXMLCodec.BINARY_ATTRIBUTE, TextXMLCodec.BINARY_ATTRIBUTE_VALUE);
+		}
+		super.writeElement(tag, binaryContent, attributes);
+}
+
+
+TextXMLEncoder.prototype.writeEndElement(tag) {
+
+		this.ostream.write('<'+tab+'>');
+
+	};
+
+	
+//returns number long
+stringToTag = function(/*String*/ tagName) {
+
+	if (null == tagName) {
+		return null;
+	}
+	Long tagVal = null;
+	if (null != _dictionaryStack) {
+		for (/*XMLDictionary*/ dictionary in _dictionaryStack) {
+			tagVal = dictionary.stringToTag(tagName);
+			if (null != tagVal) {
+				return tagVal;
+			}
+		}
+	}
+
+
+	if (XMLDictionaryStack.isUnknownTag(tagName)) {
+		return XMLDictionaryStack.decodeUnknownTag(tagName);
+	}
+	return null;
+};
+	
diff --git a/js/encoding/xml2object.js b/js/encoding/xml2object.js
new file mode 100644
index 0000000..c6711b6
--- /dev/null
+++ b/js/encoding/xml2object.js
@@ -0,0 +1,170 @@
+/**
+ * Simple xml 2 javascript object parser based on sax.js
+ * 
+ * https://github.com/emberfeather/node-xml2object
+ */
+var emitter = require('events').EventEmitter;
+var fs = require('fs');
+var sax = require('./sax');
+var util = require('util');
+
+var xml2object  = function(xmlFile, elements) {
+	elements = elements || [];
+	
+	this._hasStarted = false;
+
+	var self = this;
+	var currentObject;
+	var inObject = false;
+	var inObjectName;
+	var ancestors = [];
+
+	this.fileStream = fs.createReadStream(xmlFile);
+	this.saxStream = sax.createStream(true);
+
+	this.saxStream.on("opentag", function (args) {
+		if(!inObject) {
+			// If we are not in an object and not tracking the element
+			// then we don't need to do anything
+			if (elements.indexOf(args.name) < 0) {
+				return;
+			}
+
+			// Start tracking a new object
+			inObject = true;
+			inObjectName = args.name;
+
+			currentObject = {};
+		}
+
+		if (!(args.name in currentObject)) {
+			currentObject[args.name] = args.attributes;
+		} else if (!util.isArray(currentObject[args.name])) {
+			// Put the existing object in an array.
+			var newArray = [currentObject[args.name]];
+			
+			// Add the new object to the array.
+			newArray.push(args.attributes);
+			
+			// Point to the new array.
+			currentObject[args.name] = newArray;
+		} else {
+			// An array already exists, push the attributes on to it.
+			currentObject[args.name].push(args.attributes);
+		}
+
+		// Store the current (old) parent.
+		ancestors.push(currentObject);
+
+		// We are now working with this object, so it becomes the current parent.
+		if (currentObject[args.name] instanceof Array) {
+			// If it is an array, get the last element of the array.
+			currentObject = currentObject[args.name][currentObject[args.name].length - 1];
+		} else {
+			// Otherwise, use the object itself.
+			currentObject = currentObject[args.name];
+		}
+	});
+
+	this.saxStream.on("text", function (data) {
+		if(!inObject) {
+			return;
+		}
+
+		data = data.trim();
+
+		if (!data.length) {
+			return;
+		}
+
+		currentObject['$t'] = (currentObject['$t'] || "") + data;
+	});
+
+	this.saxStream.on("closetag", function (name) {
+		if(!inObject) {
+			return;
+		}
+
+		if(inObject && inObjectName === name) {
+			// Finished building the object
+			self.emit('object', name, currentObject);
+
+			inObject = false;
+			ancestors = [];
+
+			return;
+		}
+
+		if(ancestors.length) {
+			var ancestor = ancestors.pop();
+			var keys = Object.keys(currentObject);
+
+			if (keys.length == 1 && '$t' in currentObject) {
+				// Convert the text only objects into just the text
+				if (ancestor[name] instanceof Array) {
+					ancestor[name].push(ancestor[name].pop()['$t']);
+				} else {
+					ancestor[name] = currentObject['$t'];
+				}
+			} else if (!keys.length) {
+				// Remove empty keys
+				delete ancestor[name];
+			}
+
+			currentObject = ancestor;
+		} else {
+			currentObject = {};
+		}
+	});
+
+	// Rebroadcast the error and keep going
+	this.saxStream.on("error", function (e) {
+		this.emit('error', e);
+
+		// clear the error and resume
+		this._parser.error = null;
+		this._parser.resume();
+	});
+
+	// Rebroadcast the end of the file read
+	this.fileStream.on("end", function() {
+		self.emit("end");
+	});
+};
+
+util.inherits(xml2object, emitter);
+
+xml2object.prototype.start = function() {
+	// Can only start once
+	if(this._hasStarted) {
+		return;
+	}
+
+	this._hasStarted = true;
+
+	this.emit('start');
+
+	// Start the streaming!
+	this.fileStream.pipe(this.saxStream);
+};
+
+
+//TEST///////////////////////////////////////////////////////////////////////////////
+//var xml2object = require('xml2object');
+
+// Create a new xml parser with an array of xml elements to look for
+/*var parser = new xml2object('./src/encoding/ContentObject1.xml', [ 'ContentObject' ]);
+
+// Bind to the object event to work with the objects found in the XML file
+parser.on('object', function(name, obj) {
+    console.log('Found an object: %s', name);
+    console.log(obj);
+});
+
+// Bind to the file end event to tell when the file is done being streamed
+parser.on('end', function(name, obj) {
+    console.log('Finished parsing xml!');
+});
+
+// Start parsing the XML
+parser.start();*/
\ No newline at end of file