/*
* Part of the CCNx Java Library.
*
* Copyright (C) 2008, 2009 Palo Alto Research Center, Inc.
*
* This library is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License version 2.1
* as published by the Free Software Foundation.
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details. You should have received
* a copy of the GNU Lesser General Public License along with this library;
* if not, write to the Free Software Foundation, Inc., 51 Franklin Street,
* Fifth Floor, Boston, MA 02110-1301 USA.
*/
package org.ccnx.ccn.io.content;
import java.util.Arrays;
import org.ccnx.ccn.impl.encoding.CCNProtocolDTags;
import org.ccnx.ccn.impl.encoding.GenericXMLEncodable;
import org.ccnx.ccn.impl.encoding.XMLDecoder;
import org.ccnx.ccn.impl.encoding.XMLEncodable;
import org.ccnx.ccn.impl.encoding.XMLEncoder;
import org.ccnx.ccn.impl.support.DataUtils;
import org.ccnx.ccn.protocol.CCNTime;
import org.ccnx.ccn.protocol.PublisherID;
import org.ccnx.ccn.protocol.PublisherPublicKeyDigest;
import org.ccnx.ccn.protocol.SignedInfo;
/**
* A specifier for the information that can be used to authenticate the target of a Link.
*/
public class LinkAuthenticator extends GenericXMLEncodable implements XMLEncodable, Comparable<LinkAuthenticator> {
protected PublisherID _publisher = null;
protected Integer _nameComponentCount = null;
protected CCNTime _timestamp = null;
protected SignedInfo.ContentType _type = null;
protected byte [] _contentDigest = null; // encoded DigestInfo
public LinkAuthenticator(
PublisherID publisher,
Integer nameComponentCount,
CCNTime timestamp,
SignedInfo.ContentType type,
byte [] contentDigest) {
super();
this._publisher = publisher;
this._nameComponentCount = nameComponentCount;
this._type = type;
this._contentDigest = contentDigest;
}
public LinkAuthenticator(PublisherID publisher) {
super();
this._publisher = publisher;
}
public LinkAuthenticator(PublisherPublicKeyDigest publisher) {
this(new PublisherID(publisher));
}
public LinkAuthenticator() {}
public boolean empty() {
return (emptyPublisher() &&
emptyNameComponentCount() &&
emptyTimestamp() &&
emptyContentType() &&
emptyContentDigest());
}
public boolean emptyPublisher() {
if ((null != publisherID()) && (null != publisherID().id()) && (0 != publisherID().id().length))
return false;
return true;
}
public boolean emptyNameComponentCount() {
return (null == _nameComponentCount);
}
public boolean emptyContentDigest() {
if ((null != contentDigest()) && (0 != contentDigest().length))
return false;
return true;
}
public boolean emptyContentType() {
return (null == _type);
}
public boolean emptyTimestamp() {
return (null == _timestamp);
}
public byte[] contentDigest() {
return _contentDigest;
}
public void contentDigest(byte[] hash) {
_contentDigest = hash;
}
public PublisherPublicKeyDigest publisher() {
// If PublisherID contained one of these internally, rather than a byte [], it would
// encode with an unnecessary layer of wrapping and tags.
return new PublisherPublicKeyDigest(_publisher.id());
}
public PublisherID.PublisherType publisherType() {
return _publisher.type();
}
public PublisherID publisherID() {
return _publisher;
}
public void publisher(byte[] publisher, PublisherID.PublisherType publisherType) {
this._publisher = new PublisherID(publisher, publisherType);
}
public int nameComponentCount() { return _nameComponentCount; }
public void nameComponentCount(int nameComponentCount) { _nameComponentCount = new Integer(nameComponentCount); }
public void clearNameComponentCount() { _nameComponentCount = null; }
public CCNTime timestamp() {
return _timestamp;
}
public void timestamp(CCNTime timestamp) {
this._timestamp = timestamp;
}
public SignedInfo.ContentType type() {
return _type;
}
public void type(SignedInfo.ContentType type) {
this._type = type;
}
@Override
public void decode(XMLDecoder decoder) throws ContentDecodingException {
decoder.readStartElement(getElementLabel());
if (PublisherID.peek(decoder)) {
_publisher = new PublisherID();
_publisher.decode(decoder);
}
if (decoder.peekStartElement(CCNProtocolDTags.NameComponentCount)) {
_nameComponentCount = decoder.readIntegerElement(CCNProtocolDTags.NameComponentCount);
}
if (decoder.peekStartElement(CCNProtocolDTags.Timestamp)) {
_timestamp = decoder.readDateTime(CCNProtocolDTags.Timestamp);
}
if (decoder.peekStartElement(CCNProtocolDTags.Type)) {
String strType = decoder.readUTF8Element(CCNProtocolDTags.Type);
_type = SignedInfo.nameToType(strType);
if (null == _type) {
throw new ContentDecodingException("Cannot parse authenticator type: " + strType);
}
}
if (decoder.peekStartElement(CCNProtocolDTags.ContentDigest)) {
_contentDigest = decoder.readBinaryElement(CCNProtocolDTags.ContentDigest);
if (null == _contentDigest) {
throw new ContentDecodingException("Cannot parse content hash.");
}
}
decoder.readEndElement();
}
@Override
public void encode(XMLEncoder encoder) throws ContentEncodingException {
if (!validate()) {
throw new ContentEncodingException("Cannot encode " + this.getClass().getName() + ": field values missing.");
}
encoder.writeStartElement(getElementLabel());
if (!emptyPublisher()) {
publisherID().encode(encoder);
}
if (!emptyNameComponentCount()) {
encoder.writeElement(CCNProtocolDTags.NameComponentCount, nameComponentCount());
}
if (!emptyTimestamp()) {
encoder.writeDateTime(CCNProtocolDTags.Timestamp, timestamp());
}
if (!emptyContentType()) {
encoder.writeElement(CCNProtocolDTags.Type, SignedInfo.typeToName(type()));
}
if (!emptyContentDigest()) {
encoder.writeElement(CCNProtocolDTags.ContentDigest, contentDigest());
}
encoder.writeEndElement();
}
@Override
public long getElementLabel() { return CCNProtocolDTags.LinkAuthenticator; }
@Override
public boolean validate() {
// any of the fields could be null when used
// as a partial-match pattern
return true;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + Arrays.hashCode(_contentDigest);
result = prime
* result
+ ((_nameComponentCount == null) ? 0 : _nameComponentCount
.hashCode());
result = prime * result
+ ((_publisher == null) ? 0 : _publisher.hashCode());
result = prime * result
+ ((_timestamp == null) ? 0 : _timestamp.hashCode());
result = prime * result + ((_type == null) ? 0 : _type.hashCode());
return result;
}
/**
* Approximately equals -- matches on each field of target that is non-null
*/
public boolean approximates(LinkAuthenticator target) {
if (null != target._contentDigest) {
if (null == _contentDigest)
return false;
if (!Arrays.equals(target._contentDigest, _contentDigest))
return false;
}
if (null != target._nameComponentCount) {
if (null == _nameComponentCount)
return false;
if (!target._nameComponentCount.equals(_nameComponentCount))
return false;
}
if (null != target._publisher) {
if (null == _publisher)
return false;
if (!target._publisher.equals(_publisher))
return false;
}
if (null != target._timestamp) {
if (null == _timestamp)
return false;
if (!target._timestamp.equals(_timestamp))
return false;
}
if (null != target._type) {
if (null == _type)
return false;
if (!target._type.equals(_type))
return false;
}
return true;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
LinkAuthenticator other = (LinkAuthenticator) obj;
if (!Arrays.equals(_contentDigest, other._contentDigest))
return false;
if (_nameComponentCount == null) {
if (other._nameComponentCount != null)
return false;
} else if (!_nameComponentCount.equals(other._nameComponentCount))
return false;
if (_publisher == null) {
if (other._publisher != null)
return false;
} else if (!_publisher.equals(other._publisher))
return false;
if (_timestamp == null) {
if (other._timestamp != null)
return false;
} else if (!_timestamp.equals(other._timestamp))
return false;
if (_type == null) {
if (other._type != null)
return false;
} else if (!_type.equals(other._type))
return false;
return true;
}
public int compareTo(LinkAuthenticator other) {
int result = 0;
if (this == other)
return 0;
if (other == null)
return -1;
result = DataUtils.compare(_contentDigest, other._contentDigest);
if (0 != result)
return result;
if (_nameComponentCount == null) {
if (other._nameComponentCount != null)
return -1;
} else {
result = _nameComponentCount.compareTo(other._nameComponentCount);
if (0 != result)
return result;
}
if (_publisher == null) {
if (other._publisher != null)
return -1;
} else {
result = _publisher.compareTo(other._publisher);
if (0 != result)
return result;
}
if (_timestamp == null) {
if (other._timestamp != null)
return -1;
} else {
result = _timestamp.compareTo(other._timestamp);
if (0 != result)
return result;
}
if (_type == null) {
if (other._type != null)
return -1;
} else {
result = _type.compareTo(other._type);
if (0 != result)
return result;
}
return 0;
}
@Override
public String toString() {
return "LinkAuthenticator [contentDigest="
+ DataUtils.printBytes(_contentDigest) + ", nameComponentCount="
+ _nameComponentCount + ", publisher=" + _publisher
+ ", timestamp=" + _timestamp + ", type=" + _type + "]";
}
}