All Downloads are FREE. Search and download functionalities are using the official Maven repository.

net.named_data.jndn.Data Maven / Gradle / Ivy

Go to download

jNDN is a new implementation of a Named Data Networking client library written in Java. It is wire format compatible with the new NDN-TLV encoding, with NDNx and PARC's CCNx.

There is a newer version: 0.25
Show newest version
/**
 * Copyright (C) 2013-2017 Regents of the University of California.
 * @author: Jeff Thompson 
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program 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 program.  If not, see .
 * A copy of the GNU Lesser General Public License is in the file COPYING.
 */

package net.named_data.jndn;

import java.nio.ByteBuffer;
import net.named_data.jndn.encoding.EncodingException;
import net.named_data.jndn.encoding.WireFormat;
import net.named_data.jndn.encoding.SignatureHolder;
import net.named_data.jndn.lp.IncomingFaceId;
import net.named_data.jndn.lp.LpPacket;
import net.named_data.jndn.util.Blob;
import net.named_data.jndn.util.ChangeCounter;
import net.named_data.jndn.util.ChangeCountable;
import net.named_data.jndn.util.Common;
import net.named_data.jndn.util.SignedBlob;

public class Data implements ChangeCountable, SignatureHolder {
  /**
   * Create a new Data object with default values and where the signature is a
   * blank Sha256WithRsaSignature.
   */
  public Data()
  {
  }

  /**
   * Create a new Data object with the given name and default values and where
   * the signature is a blank Sha256WithRsaSignature.
   * @param name The name which is copied.
   */
  public Data(Name name)
  {
    name_.set(new Name(name));
  }

  /**
   * Create a deep copy of the given data object, including a clone of the
   * signature object.
   * @param data The data object to copy.
   */
  public Data(Data data)
  {
    try {
      signature_.set(data.signature_ == null ?
        new Sha256WithRsaSignature() : (Signature)data.getSignature().clone());
    }
    catch (CloneNotSupportedException e) {
      // We don't expect this to happen, so just treat it as if we got a null pointer.
      throw new NullPointerException
        ("Data.setSignature: unexpected exception in clone(): " + e.getMessage());
    }

    name_.set(new Name(data.getName()));
    metaInfo_.set(new MetaInfo(data.getMetaInfo()));
    content_ = data.content_;
    setDefaultWireEncoding(data.getDefaultWireEncoding(), null);
    defaultFullName_ = new Name(data.defaultFullName_);
  }

  /**
   * Encode this Data for a particular wire format. If wireFormat is the default
   * wire format, also set the defaultWireEncoding field to the encoded result.
   * @param wireFormat A WireFormat object used to encode the input.
   * @return The encoded buffer.
   */
  public final SignedBlob
  wireEncode(WireFormat wireFormat)
  {
    if (!getDefaultWireEncoding().isNull() &&
        getDefaultWireEncodingFormat() == wireFormat)
      // We already have an encoding in the desired format.
      return getDefaultWireEncoding();

    int[] signedPortionBeginOffset = new int[1];
    int[] signedPortionEndOffset = new int[1];
    Blob encoding = wireFormat.encodeData
      (this, signedPortionBeginOffset, signedPortionEndOffset);
    SignedBlob wireEncoding = new SignedBlob
      (encoding, signedPortionBeginOffset[0], signedPortionEndOffset[0]);

    if (wireFormat == WireFormat.getDefaultWireFormat())
      // This is the default wire encoding.
      setDefaultWireEncoding(wireEncoding, WireFormat.getDefaultWireFormat());

    return wireEncoding;
  }

  /**
   * Encode this Data for the default wire format WireFormat.getDefaultWireFormat().
   * Also set the defaultWireEncoding field to the encoded result.
   * @return The encoded buffer.
   */
  public final SignedBlob
  wireEncode()
  {
    return wireEncode(WireFormat.getDefaultWireFormat());
  }

  /**
   * Decode the input using a particular wire format and update this Data. If
   * wireFormat is the default wire format, also set the defaultWireEncoding
   * field another pointer to the input Blob.
   * @param input The input Blob to decode.  This reads from buf().position() to
   * buf().limit(), but does not change the position.
   * @param wireFormat A WireFormat object used to decode the input.
   * @throws EncodingException For invalid encoding.
   */
  public void
  wireDecode(Blob input, WireFormat wireFormat) throws EncodingException
  {
    int[] signedPortionBeginOffset = new int[1];
    int[] signedPortionEndOffset = new int[1];
    wireFormat.decodeData
      (this, input.buf(), signedPortionBeginOffset, signedPortionEndOffset,
       false);

    if (wireFormat == WireFormat.getDefaultWireFormat())
      // This is the default wire encoding.
      setDefaultWireEncoding
        (new SignedBlob(input, signedPortionBeginOffset[0],
         signedPortionEndOffset[0]), WireFormat.getDefaultWireFormat());
    else
      setDefaultWireEncoding(new SignedBlob(), null);
  }

  /**
   * Decode the input using the default wire format
   * WireFormat.getDefaultWireFormat() and update this Data. Also set the
   * defaultWireEncoding field another pointer to the input Blob.
   * @param input The input Blob to decode.  This reads from buf().position() to
   * buf().limit(), but does not change the position.
   * @throws EncodingException For invalid encoding.
   */
  public final void
  wireDecode(Blob input) throws EncodingException
  {
    wireDecode(input, WireFormat.getDefaultWireFormat());
  }

  /**
   * Decode the input using a particular wire format and update this Data. If
   * wireFormat is the default wire format, also set the defaultWireEncoding
   * field to a copy of the input. (To not copy the input, see
   * wireDecode(Blob).)
   * @param input The input buffer to decode.  This reads from position() to
   * limit(), but does not change the position.
   * @param wireFormat A WireFormat object used to decode the input.
   * @throws EncodingException For invalid encoding.
   */
  public final void
  wireDecode(ByteBuffer input, WireFormat wireFormat) throws EncodingException
  {
    wireDecode(new Blob(input, true), wireFormat);
  }

  /**
   * Decode the input using the default wire format
   * WireFormat.getDefaultWireFormat() and update this Data. Also set the
   * defaultWireEncoding field to the input.
   * @param input The input buffer to decode.  This reads from position() to
   * limit(), but does not change the position.
   * @throws EncodingException For invalid encoding.
   */
  public final void
  wireDecode(ByteBuffer input) throws EncodingException
  {
    wireDecode(input, WireFormat.getDefaultWireFormat());
  }

  public final Signature
  getSignature() { return (Signature)signature_.get(); }

  public final Name
  getName() { return (Name)name_.get(); }

  public final MetaInfo
  getMetaInfo() { return (MetaInfo)metaInfo_.get(); }

  public final Blob
  getContent() { return content_; }

  /**
   * Get the incoming face ID according to the incoming packet header.
   * @return The incoming face ID. If not specified, return -1.
   */
  public final long
  getIncomingFaceId()
  {
    IncomingFaceId field = 
      lpPacket_ == null ? null : IncomingFaceId.getFirstHeader(lpPacket_);
    return field == null ? -1 : field.getFaceId();
  }

  /**
   * Get the Data packet's full name, which includes the final
   * ImplicitSha256Digest component based on the wire encoding for a particular
   * wire format.
   * @param wireFormat A WireFormat object used to encode the Data packet.
   * @return The full name. You must not change the Name object - if you need
   * to change it then make a copy.
   */
  public final Name
  getFullName(WireFormat wireFormat) throws EncodingException
  {
    // The default full name depends on the default wire encoding.
    if (!getDefaultWireEncoding().isNull() && defaultFullName_.size() > 0 &&
        getDefaultWireEncodingFormat() == wireFormat)
      // We already have a full name. A non-null default wire encoding means
      // that the Data packet fields have not changed.
      return defaultFullName_;

    Name fullName = new Name(getName());
    // wireEncode will use the cached encoding if possible.
    fullName.appendImplicitSha256Digest
      (Common.digestSha256(wireEncode(wireFormat).buf()));

    if (wireFormat == WireFormat.getDefaultWireFormat())
      // wireEncode has already set defaultWireEncodingFormat_.
      defaultFullName_ = fullName;

    return fullName;
  }

  /**
   * Get the Data packet's full name, which includes the final
   * ImplicitSha256Digest component based on the wire encoding for the default
   * wire format.
   * @return The full name. You must not change the Name objects - if you need
   * to change it then make a copy.
   */
  public final Name
  getFullName() throws EncodingException
  {
    return getFullName(WireFormat.getDefaultWireFormat());
  }

  /**
   * Return a pointer to the defaultWireEncoding, which was encoded with
   * getDefaultWireEncodingFormat().
   * @return The default wire encoding. Its pointer may be null.
   */
  public final SignedBlob
  getDefaultWireEncoding()
  {
    if (getDefaultWireEncodingChangeCount_ != getChangeCount()) {
      // The values have changed, so the default wire encoding is invalidated.
      defaultWireEncoding_ = new SignedBlob();
      defaultWireEncodingFormat_ = null;
      getDefaultWireEncodingChangeCount_ = getChangeCount();
    }

    return defaultWireEncoding_;
  }

  /**
   * Get the WireFormat which is used by getDefaultWireEncoding().
   * @return The WireFormat, which is only meaningful if the
   * getDefaultWireEncoding() does not have a null pointer.
   */
  WireFormat
  getDefaultWireEncodingFormat() { return defaultWireEncodingFormat_; }

  /**
   * Set the signature to a copy of the given signature.
   * @param signature The signature object which is cloned.
   * @return This Data so that you can chain calls to update values.
   */
  public final Data
  setSignature(Signature signature)
  {
    try {
      signature_.set(signature == null ?
        new Sha256WithRsaSignature() : (Signature)signature.clone());
    }
    catch (CloneNotSupportedException e) {
      // We don't expect this to happen, so just treat it as if we got a null
      //   pointer.
      throw new NullPointerException
        ("Data.setSignature: unexpected exception in clone(): " + e.getMessage());
    }

    ++changeCount_;
    return this;
  }

  /**
   * Set name to a copy of the given Name.  This is not final so that a subclass
   * can override to validate the name.
   * @param name The Name which is copied.
   * @return This Data so that you can chain calls to update values.
   */
  public Data
  setName(Name name)
  {
    name_.set(name == null ? new Name() : new Name(name));
    ++changeCount_;
    return this;
  }

  /**
   * Set metaInfo to a copy of the given MetaInfo.
   * @param metaInfo The MetaInfo which is copied.
   * @return This Data so that you can chain calls to update values.
   */
  public final Data
  setMetaInfo(MetaInfo metaInfo)
  {
    metaInfo_.set(metaInfo == null ? new MetaInfo() : new MetaInfo(metaInfo));
    ++changeCount_;
    return this;
  }

  public final Data
  setContent(Blob content)
  {
    content_ = (content == null ? new Blob() : content);
    ++changeCount_;
    return this;
  }

  /**
   * An internal library method to set the LpPacket for an incoming packet. The
   * application should not call this.
   * @param lpPacket The LpPacket. This does not make a copy.
   * @return This Data so that you can chain calls to update values.
   * @note This is an experimental feature. This API may change in the future.
   */
  final Data
  setLpPacket(LpPacket lpPacket)
  {
    lpPacket_ = lpPacket;
    // Don't update changeCount_ since this doesn't affect the wire encoding.
    return this;
  }

  /**
   * Get the change count, which is incremented each time this object
   * (or a child object) is changed.
   * @return The change count.
   */
  public final long
  getChangeCount()
  {
    // Make sure each of the checkChanged is called.
    boolean changed = signature_.checkChanged();
    changed = name_.checkChanged() || changed;
    changed = metaInfo_.checkChanged() || changed;
    if (changed)
      // A child object has changed, so update the change count.
      ++changeCount_;

    return changeCount_;
  }

  private void
  setDefaultWireEncoding
    (SignedBlob defaultWireEncoding, WireFormat defaultWireEncodingFormat)
  {
    defaultWireEncoding_ = defaultWireEncoding;
    defaultWireEncodingFormat_ = defaultWireEncodingFormat;
    // Set getDefaultWireEncodingChangeCount_ so that the next call to
    //   getDefaultWireEncoding() won't clear defaultWireEncoding_.
    getDefaultWireEncodingChangeCount_ = getChangeCount();
  }

  private final ChangeCounter signature_ =
    new ChangeCounter(new Sha256WithRsaSignature());
  private final ChangeCounter name_ = new ChangeCounter(new Name());
  private final ChangeCounter metaInfo_ =
    new ChangeCounter(new MetaInfo());
  private Blob content_ = new Blob();
  private LpPacket lpPacket_ = null;
  private SignedBlob defaultWireEncoding_ = new SignedBlob();
  private Name defaultFullName_ = new Name();
  private WireFormat defaultWireEncodingFormat_;
  private long getDefaultWireEncodingChangeCount_ = 0;
  private long changeCount_ = 0;
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy