/*
* Part of the CCNx Java Library.
*
* Copyright (C) 2009-2012 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.profiles.ccnd;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import org.ccnx.ccn.CCNHandle;
import org.ccnx.ccn.impl.CCNNetworkManager.NetworkProtocol;
import org.ccnx.ccn.impl.encoding.BinaryXMLCodec;
import org.ccnx.ccn.impl.encoding.CCNProtocolDTags;
import org.ccnx.ccn.impl.encoding.GenericXMLEncodable;
import org.ccnx.ccn.impl.encoding.XMLCodecFactory;
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.Log;
import org.ccnx.ccn.io.content.ContentDecodingException;
import org.ccnx.ccn.io.content.ContentEncodingException;
import org.ccnx.ccn.protocol.Component;
import org.ccnx.ccn.protocol.ContentName;
import org.ccnx.ccn.protocol.PublisherPublicKeyDigest;
/**
*
*/
public class FaceManager extends CCNDaemonHandle /* extends GenericXMLEncodable implements XMLEncodable */ {
public enum ActionType {
NewFace ("newface"), DestroyFace ("destroyface"), QueryFace ("queryface");
ActionType(String st) { this.st = st; }
private final String st;
public String value() { return st; }
}
public static final Component CCNX = new Component("ccnx");
public static class FaceInstance extends GenericXMLEncodable implements XMLEncodable {
/* extends CCNEncodableObject<PolicyXML> */
/**
* From the XML definitions:
* <xs:element name="Action" type="xs:string" minOccurs="0" maxOccurs="1"/>
* <xs:element name="PublisherPublicKeyDigest" type="DigestType" minOccurs="0" maxOccurs="1"/>
* <xs:element name="FaceID" type="xs:nonNegativeInteger" minOccurs="0" maxOccurs="1"/>
* <xs:element name="IPProto" type="xs:nonNegativeInteger" minOccurs="0" maxOccurs="1"/>
* <xs:element name="Host" type="xs:string" minOccurs="0" maxOccurs="1"/>
* <xs:element name="Port" type="xs:nonNegativeInteger" minOccurs="0" maxOccurs="1"/>
* <xs:element name="MulticastInterface" type="xs:string" minOccurs="0" maxOccurs="1"/>
* <xs:element name="MulticastTTL" type="xs:nonNegativeInteger" minOccurs="0" maxOccurs="1"/>
* <xs:element name="FreshnessSeconds" type="xs:nonNegativeInteger" minOccurs="0" maxOccurs="1"/>
*/
protected String _action;
protected PublisherPublicKeyDigest _ccndID;
protected Integer _faceID;
protected NetworkProtocol _ipProto;
protected String _host;
protected Integer _port;
protected String _multicastInterface;
protected Integer _multicastTTL;
protected Integer _lifetime;
public FaceInstance(ActionType action, PublisherPublicKeyDigest ccndID, NetworkProtocol ipProto, String host, Integer port) {
_action = action.value();
_ccndID = ccndID;
_ipProto = ipProto;
_host = host;
_port = port;
}
public FaceInstance(ActionType action, PublisherPublicKeyDigest ccndID, Integer faceID) {
_action = action.value();
_ccndID = ccndID;
_faceID = faceID;
}
public FaceInstance(ActionType action, PublisherPublicKeyDigest ccndID, NetworkProtocol ipProto, String host, Integer port,
String multicastInterface, Integer multicastTTL, Integer lifetime) {
_action = action.value();
_ccndID = ccndID;
_ipProto = ipProto;
_host = host;
_port = port;
_multicastInterface = multicastInterface;
_multicastTTL = multicastTTL;
_lifetime = lifetime;
}
public FaceInstance(byte[] raw) {
ByteArrayInputStream bais = new ByteArrayInputStream(raw);
XMLDecoder decoder = XMLCodecFactory.getDecoder(BinaryXMLCodec.CODEC_NAME);
try {
decoder.beginDecoding(bais);
decode(decoder);
decoder.endDecoding();
} catch (ContentDecodingException e) {
String reason = e.getMessage();
Log.fine("Unexpected error decoding FaceInstance from bytes. reason: " + reason + "\n");
Log.warningStackTrace(e);
throw new IllegalArgumentException("Unexpected error decoding FaceInstance from bytes. reason: " + reason);
}
}
public FaceInstance() {
}
public Integer faceID() { return _faceID; }
public void setFaceID(Integer faceID) { _faceID = faceID; }
public String action() { return _action; }
public String toFormattedString() {
StringBuilder out = new StringBuilder(128);
if (null != _action) {
out.append("Action: "+ _action + "\n");
} else {
out.append("Action: not present\n");
}
if (null != _faceID) {
out.append("FaceID: "+ _faceID.toString() + "\n");
} else {
out.append("FaceID: not present\n");
}
if (null != _host) {
out.append("Host: "+ _host + "\n");
} else {
out.append("Host: not present\n");
}
if (null != _port) {
out.append("Port: "+ _port.toString() + "\n");
} else {
out.append("Port: not present\n");
}
return out.toString();
}
public boolean validateAction(String action) {
if (action != null){
if (action.equals(ActionType.NewFace.value()) ||
action.equals(ActionType.DestroyFace.value()) ||
action.equals(ActionType.QueryFace.value())) {
return true;
}
}
return false;
}
/**
* Used by NetworkObject to decode the object from a network stream.
* @see org.ccnx.ccn.impl.encoding.XMLEncodable
*/
public void decode(XMLDecoder decoder) throws ContentDecodingException {
decoder.readStartElement(getElementLabel());
if (decoder.peekStartElement(CCNProtocolDTags.Action)) {
_action = decoder.readUTF8Element(CCNProtocolDTags.Action);
}
if (decoder.peekStartElement(CCNProtocolDTags.PublisherPublicKeyDigest)) {
_ccndID = new PublisherPublicKeyDigest();
_ccndID.decode(decoder);
}
if (decoder.peekStartElement(CCNProtocolDTags.FaceID)) {
_faceID = decoder.readIntegerElement(CCNProtocolDTags.FaceID);
}
if (decoder.peekStartElement(CCNProtocolDTags.IPProto)) {
int pI = decoder.readIntegerElement(CCNProtocolDTags.IPProto);
_ipProto = null;
if (NetworkProtocol.TCP.value().intValue() == pI) {
_ipProto = NetworkProtocol.TCP;
} else if (NetworkProtocol.UDP.value().intValue() == pI) {
_ipProto = NetworkProtocol.UDP;
} else {
throw new ContentDecodingException("FaceInstance.decoder. Invalid " +
CCNProtocolDTags.tagToString(CCNProtocolDTags.IPProto) + " field: " + pI);
}
}
if (decoder.peekStartElement(CCNProtocolDTags.Host)) {
_host = decoder.readUTF8Element(CCNProtocolDTags.Host);
}
if (decoder.peekStartElement(CCNProtocolDTags.Port)) {
_port = decoder.readIntegerElement(CCNProtocolDTags.Port);
}
if (decoder.peekStartElement(CCNProtocolDTags.MulticastInterface)) {
_multicastInterface = decoder.readUTF8Element(CCNProtocolDTags.MulticastInterface);
}
if (decoder.peekStartElement(CCNProtocolDTags.MulticastTTL)) {
_multicastTTL = decoder.readIntegerElement(CCNProtocolDTags.MulticastTTL);
}
if (decoder.peekStartElement(CCNProtocolDTags.FreshnessSeconds)) {
_lifetime = decoder.readIntegerElement(CCNProtocolDTags.FreshnessSeconds);
}
decoder.readEndElement();
}
/**
* Used by NetworkObject to encode the object to a network stream.
* @see org.ccnx.ccn.impl.encoding.XMLEncodable
*/
public void encode(XMLEncoder encoder) throws ContentEncodingException {
if (!validate()) {
throw new ContentEncodingException("Cannot encode " + this.getClass().getName() + ": field values missing.");
}
encoder.writeStartElement(getElementLabel());
if (null != _action && _action.length() != 0)
encoder.writeElement(CCNProtocolDTags.Action, _action);
if (null != _ccndID) {
_ccndID.encode(encoder);
}
if (null != _faceID) {
encoder.writeElement(CCNProtocolDTags.FaceID, _faceID);
}
if (null != _ipProto) {
encoder.writeElement(CCNProtocolDTags.IPProto, _ipProto.value());
}
if (null != _host && _host.length() != 0) {
encoder.writeElement(CCNProtocolDTags.Host, _host);
}
if (null != _port) {
encoder.writeElement(CCNProtocolDTags.Port, _port);
}
if (null != _multicastInterface && _multicastInterface.length() != 0) {
encoder.writeElement(CCNProtocolDTags.MulticastInterface, _multicastInterface);
}
if (null != _multicastTTL) {
encoder.writeElement(CCNProtocolDTags.MulticastTTL, _multicastTTL);
}
if (null != _lifetime) {
encoder.writeElement(CCNProtocolDTags.FreshnessSeconds, _lifetime);
}
encoder.writeEndElement();
}
@Override
public long getElementLabel() { return CCNProtocolDTags.FaceInstance; }
@Override
public boolean validate() {
if (validateAction(_action)){
return true;
}
return false;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((_action == null) ? 0 : _action.hashCode());
result = prime * result + ((_ccndID == null) ? 0 : _ccndID.hashCode());
result = prime * result + ((_faceID == null) ? 0 : _faceID.hashCode());
result = prime * result + ((_ipProto == null) ? 0 : _ipProto.hashCode());
result = prime * result + ((_host == null) ? 0 : _host.hashCode());
result = prime * result + ((_port == null) ? 0 : _port.hashCode());
result = prime * result + ((_multicastInterface == null) ? 0 : _multicastInterface.hashCode());
result = prime * result + ((_multicastTTL == null) ? 0 : _multicastTTL.hashCode());
result = prime * result + ((_lifetime == null) ? 0 : _lifetime.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj) return true;
if (obj == null) return false;
if (getClass() != obj.getClass()) return false;
FaceInstance other = (FaceInstance) obj;
if (_action == null) {
if (other._action != null) return false;
} else if (!_action.equals(other._action)) return false;
if (_ccndID == null) {
if (other._ccndID != null) return false;
} else if (!_ccndID.equals(other._ccndID)) return false;
if (_faceID == null) {
if (other._faceID != null) return false;
} else if (!_faceID.equals(other._faceID)) return false;
if (_ipProto == null) {
if (other._ipProto != null) return false;
} else if (!_ipProto.equals(other._ipProto)) return false;
if (_host == null) {
if (other._host != null) return false;
} else if (!_host.equals(other._host)) return false;
if (_port == null) {
if (other._port != null) return false;
} else if (!_port.equals(other._port)) return false;
if (_multicastInterface == null) {
if (other._multicastInterface != null) return false;
} else if (!_multicastInterface.equals(other._multicastInterface)) return false;
if (_multicastTTL == null) {
if (other._multicastTTL != null) return false;
} else if (!_multicastTTL.equals(other._multicastTTL)) return false;
if (_lifetime == null) {
if (other._lifetime != null) return false;
} else if (!_lifetime.equals(other._lifetime)) return false;
return true;
}
} /* FaceInstance */
/*************************************************************************************/
/*************************************************************************************/
public FaceManager(CCNHandle handle) throws CCNDaemonException {
super(handle);
}
public FaceManager() { }
private PublisherPublicKeyDigest getId() throws CCNDaemonException {
PublisherPublicKeyDigest id = null;
try {
id = _manager.getCCNDId();
} catch (IOException e) {
throw new CCNDaemonException(e.getMessage());
}
return id;
}
public Integer createFace(NetworkProtocol ipProto, String host, Integer port)
throws CCNDaemonException {
return createFace(ipProto, host, port, null, null, null);
}
public Integer createFace(NetworkProtocol ipProto, String host, Integer port, Integer lifetime)
throws CCNDaemonException {
return createFace(ipProto, host, port, null, null, lifetime);
}
public Integer createFace(NetworkProtocol ipProto, String host, Integer port,
String multicastInterface, Integer multicastTTL, Integer lifetime)
throws CCNDaemonException {
FaceInstance face = new FaceInstance(ActionType.NewFace, getId(), ipProto, host, port,
multicastInterface, multicastTTL, lifetime);
FaceInstance returned = sendIt(face);
return returned.faceID();
}
public void deleteFace(Integer faceID) throws CCNDaemonException {
FaceInstance face = new FaceInstance(ActionType.DestroyFace, getId(), faceID);
sendIt(face);
}
public FaceInstance queryFace(Integer faceID) throws CCNDaemonException {
FaceInstance face = new FaceInstance(ActionType.QueryFace, getId(), faceID);
FaceInstance returned = sendIt(face);
return returned;
}
private FaceInstance sendIt(FaceInstance face) throws CCNDaemonException {
ContentName interestName = new ContentName(CCNX, getId().digest(), face.action());
byte[] payloadBack = super.sendIt(interestName, face, null, true);
FaceInstance faceBack = new FaceInstance(payloadBack);
String formattedFace = faceBack.toFormattedString();
Log.fine(formattedFace);
return faceBack;
} /* private FaceInstance sendIt(FaceInstance face) throws CCNDaemonException */
}