<commit_before>/**
 * 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;

import java.io.IOException;

import javax.xml.stream.XMLStreamException;

import org.ccnx.ccn.CCNHandle;
import org.ccnx.ccn.impl.security.crypto.ContentKeys;
import org.ccnx.ccn.impl.support.Log;
import org.ccnx.ccn.profiles.VersionMissingException;
import org.ccnx.ccn.profiles.VersioningProfile;
import org.ccnx.ccn.protocol.CCNTime;
import org.ccnx.ccn.protocol.ContentName;
import org.ccnx.ccn.protocol.ContentObject;
import org.ccnx.ccn.protocol.PublisherPublicKeyDigest;


/**
 * A CCNInputStream that embodies the Versioning profile. If you
 * ask to open a name that is already versioned, it opens that
 * version for you. If you ask to open a name without a version,
 * it attempts to open the latest version of that name. If you
 * attempt to open a name with a segment marker on it as well,
 * it opens that version of that content at that segment.
 * 
 * The only behavior we have to change from superclass is that
 * involved in getting the first segment -- header or regular segment.
 * We need to make an interest that gets the latest version, and
 * then fills in the version information on the name we
 * are working with, to make sure we continue to get blocks
 * from the same version (even if, say someone writes another
 * version on top of us).
 * 
 * TODO -- outstanding concern -- depending on when the header arrives,
 * the response of this class may differ (not entirely clear). Given
 * that we're moving away from headers, perhaps, this may not be an
 * issue, but it brings up the point that we have to write unit tests
 * that seed ccnd or the repo with potentially complicating data and
 * make sure we can still retrieve it.
 */
public class CCNVersionedInputStream extends CCNInputStream {

	public CCNVersionedInputStream(ContentName name) throws XMLStreamException,
															IOException {
		super(name);
	}

	public CCNVersionedInputStream(ContentName name, CCNHandle handle)
										throws XMLStreamException, IOException {
		super(name, handle);
	}

	public CCNVersionedInputStream(ContentName name, PublisherPublicKeyDigest publisher,
			CCNHandle handle) throws XMLStreamException, IOException {
		super(name, publisher, handle);
	}

	public CCNVersionedInputStream(ContentName name, Long startingSegmentNumber)
			throws XMLStreamException, IOException {
		super(name, startingSegmentNumber);
	}

	public CCNVersionedInputStream(ContentName name,
			Long startingSegmentNumber, PublisherPublicKeyDigest publisher,
			CCNHandle handle) throws XMLStreamException, IOException {
		super(name, startingSegmentNumber, publisher, handle);
	}

	public CCNVersionedInputStream(ContentName name,
			Long startingSegmentNumber, PublisherPublicKeyDigest publisher,
			ContentKeys keys, CCNHandle handle)
			throws XMLStreamException, IOException {
		super(name, startingSegmentNumber, publisher, keys, handle);
	}

	public CCNVersionedInputStream(ContentObject firstSegment,
			CCNHandle handle) throws XMLStreamException, IOException {
		super(firstSegment, handle);
	}
	
	public CCNVersionedInputStream(ContentObject firstSegment, ContentKeys keys, CCNHandle handle) throws XMLStreamException, IOException {
		super(firstSegment, keys, handle);
	}
	
	@Override
	protected ContentObject getFirstSegment() throws IOException {
		if (VersioningProfile.hasTerminalVersion(_baseName)) {
			// Get exactly this version
			return super.getFirstSegment();
		}
		Log.info("getFirstSegment: getting latest version of " + _baseName);
		ContentObject result = 
			VersioningProfile.getFirstBlockOfLatestVersion(_baseName, _startingSegmentNumber, _publisher, _timeout, this, _handle);
		if (null != result){
			Log.info("getFirstSegment: retrieved latest version object " + result.name() + " type: " + result.signedInfo().getTypeName());
			_baseName = result.name().cut(_baseName.count() + 1);
		} else {
			Log.info("getFirstSegment: no segment available for latest version of " + _baseName);
		}
		return result;
	}
	
	protected boolean isFirstSegment(ContentName desiredName, ContentObject potentialFirstSegment) {
		return VersioningProfile.isVersionedFirstSegment(desiredName, potentialFirstSegment, _startingSegmentNumber);
	}
	
	public CCNTime getVersionAsTimestamp() throws VersionMissingException {
		if (null == _baseName)
			throw new VersionMissingException("Have not yet retrieved content name!");
		return VersioningProfile.getLastVersionAsTimestamp(_baseName);
	}
}<commit_msg>Finished documentation. Cleaned up exceptions.<commit_after>/**
 * 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;

import java.io.IOException;

import javax.xml.stream.XMLStreamException;

import org.ccnx.ccn.CCNHandle;
import org.ccnx.ccn.impl.security.crypto.ContentKeys;
import org.ccnx.ccn.impl.support.Log;
import org.ccnx.ccn.profiles.VersionMissingException;
import org.ccnx.ccn.profiles.VersioningProfile;
import org.ccnx.ccn.profiles.access.AccessControlManager;
import org.ccnx.ccn.protocol.CCNTime;
import org.ccnx.ccn.protocol.ContentName;
import org.ccnx.ccn.protocol.ContentObject;
import org.ccnx.ccn.protocol.PublisherPublicKeyDigest;


/**
 * A {@link CCNInputStream} that reads and writes versioned streams.
 * Names are versioned using the {@link VersioningProfile}. If you
 * ask to open a name that is already versioned, it opens that
 * version for you. If you ask to open a name without a version,
 * it attempts to open the latest version of that name. If you
 * attempt to open a name with a segment marker on it as well,
 * it opens that version of that content at that segment.
 * 
 * The only behavior we have to change from superclass is that
 * involved in getting the first segment -- header or regular segment.
 * We need to make an interest that gets the latest version, and
 * then fills in the version information on the name we
 * are working with, to make sure we continue to get blocks
 * from the same version (even if, say someone writes another
 * version on top of us).
 */
public class CCNVersionedInputStream extends CCNInputStream {

	/**
	 * Set up an input stream to read segmented CCN content under a given versioned name. 
	 * Content is assumed to be unencrypted, or keys will be retrieved automatically via another
	 * process (for example, an {@link AccessControlManager}). 
	 * Will use the default handle given by {@link CCNHandle.getHandle()}.
	 * Note that this constructor does not currently retrieve any
	 * data; data is not retrieved until read() is called. This will change in the future, and
	 * this constructor will retrieve the first block.
	 * 
	 * @param baseName Name to read from. If it ends with a version, will retrieve that
	 * specific version. If not, will find the latest version available. If it ends with
	 * both a version and a segment number, will start to read from that segment of that version.
	 * @throws IOException Not currently thrown, will be thrown when constructors retrieve first block.
	 */
	public CCNVersionedInputStream(ContentName name) throws XMLStreamException,
															IOException {
		super(name);
	}

	/**
	 * Set up an input stream to read segmented CCN content under a given versioned name. 
	 * Content is assumed to be unencrypted, or keys will be retrieved automatically via another
	 * process (for example, an {@link AccessControlManager}). 
	 * Will use the default handle given by {@link CCNHandle.getHandle()}.
	 * Note that this constructor does not currently retrieve any
	 * data; data is not retrieved until read() is called. This will change in the future, and
	 * this constructor will retrieve the first block.
	 * 
	 * @param baseName Name to read from. If it ends with a version, will retrieve that
	 * specific version. If not, will find the latest version available. If it ends with
	 * both a version and a segment number, will start to read from that segment of that version.
	 * @param handle The CCN handle to use for data retrieval. If null, the default handle
	 * 		given by {@link CCNHandle.getHandle()} will be used.
	 * @throws IOException Not currently thrown, will be thrown when constructors retrieve first block.
	 */
	public CCNVersionedInputStream(ContentName name, CCNHandle handle)
										throws XMLStreamException, IOException {
		super(name, handle);
	}

	/**
	 * Set up an input stream to read segmented CCN content under a given versioned name. 
	 * Content is assumed to be unencrypted, or keys will be retrieved automatically via another
	 * process (for example, an {@link AccessControlManager}). 
	 * Will use the default handle given by {@link CCNHandle.getHandle()}.
	 * Note that this constructor does not currently retrieve any
	 * data; data is not retrieved until read() is called. This will change in the future, and
	 * this constructor will retrieve the first block.
	 * 
	 * @param baseName Name to read from. If it ends with a version, will retrieve that
	 * specific version. If not, will find the latest version available. If it ends with
	 * both a version and a segment number, will start to read from that segment of that version.
	 * @param publisher The key we require to have signed this content. If null, will accept any publisher
	 * 				(subject to higher-level verification).
	 * @param handle The CCN handle to use for data retrieval. If null, the default handle
	 * 		given by {@link CCNHandle.getHandle()} will be used.
	 * @throws IOException Not currently thrown, will be thrown when constructors retrieve first block.
	 */
	public CCNVersionedInputStream(ContentName name, PublisherPublicKeyDigest publisher,
			CCNHandle handle) throws XMLStreamException, IOException {
		super(name, publisher, handle);
	}

	/**
	 * Set up an input stream to read segmented CCN content under a given versioned name. 
	 * Content is assumed to be unencrypted, or keys will be retrieved automatically via another
	 * process (for example, an {@link AccessControlManager}). 
	 * Will use the default handle given by {@link CCNHandle.getHandle()}.
	 * Note that this constructor does not currently retrieve any
	 * data; data is not retrieved until read() is called. This will change in the future, and
	 * this constructor will retrieve the first block.
	 * 
	 * @param baseName Name to read from. If it ends with a version, will retrieve that
	 * specific version. If not, will find the latest version available. If it ends with
	 * both a version and a segment number, will start to read from that segment of that version.
	 * @param startingSegmentNumber Alternative specification of starting segment number. If
	 * 		null, will be {@link SegmentationProfile.baseSegment()}.
	 * @param handle The CCN handle to use for data retrieval. If null, the default handle
	 * 		given by {@link CCNHandle.getHandle()} will be used.
	 * @throws IOException Not currently thrown, will be thrown when constructors retrieve first block.
	 */
	public CCNVersionedInputStream(ContentName name, Long startingSegmentNumber, CCNHandle handle)
			throws XMLStreamException, IOException {
		super(name, startingSegmentNumber, handle);
	}

	/**
	 * Set up an input stream to read segmented CCN content under a given versioned name. 
	 * Content is assumed to be unencrypted, or keys will be retrieved automatically via another
	 * process (for example, an {@link AccessControlManager}). 
	 * Will use the default handle given by {@link CCNHandle.getHandle()}.
	 * Note that this constructor does not currently retrieve any
	 * data; data is not retrieved until read() is called. This will change in the future, and
	 * this constructor will retrieve the first block.
	 * 
	 * @param baseName Name to read from. If it ends with a version, will retrieve that
	 * specific version. If not, will find the latest version available. If it ends with
	 * both a version and a segment number, will start to read from that segment of that version.
	 * @param startingSegmentNumber Alternative specification of starting segment number. If
	 * 		null, will be {@link SegmentationProfile.baseSegment()}.
	 * @param publisher The key we require to have signed this content. If null, will accept any publisher
	 * 				(subject to higher-level verification).
	 * @param handle The CCN handle to use for data retrieval. If null, the default handle
	 * 		given by {@link CCNHandle.getHandle()} will be used.
	 * @throws IOException Not currently thrown, will be thrown when constructors retrieve first block.
	 */
	public CCNVersionedInputStream(ContentName name,
			Long startingSegmentNumber, PublisherPublicKeyDigest publisher,
			CCNHandle handle) throws XMLStreamException, IOException {
		super(name, startingSegmentNumber, publisher, handle);
	}

	/**
	 * Set up an input stream to read segmented CCN content under a given versioned name. 
	 * Will use the default handle given by {@link CCNHandle.getHandle()}.
	 * Note that this constructor does not currently retrieve any
	 * data; data is not retrieved until read() is called. This will change in the future, and
	 * this constructor will retrieve the first block.
	 * 
	 * @param baseName Name to read from. If it ends with a version, will retrieve that
	 * specific version. If not, will find the latest version available. If it ends with
	 * both a version and a segment number, will start to read from that segment of that version.
	 * @param startingSegmentNumber Alternative specification of starting segment number. If
	 * 		null, will be {@link SegmentationProfile.baseSegment()}.
	 * @param publisher The key we require to have signed this content. If null, will accept any publisher
	 * 				(subject to higher-level verification).
	 * @param keys The keys to use to decrypt this content. If null, assumes content unencrypted, or another
	 * 				process will be used to retrieve the keys (for example, an {@link AccessControlManager}).
	 * @param handle The CCN handle to use for data retrieval. If null, the default handle
	 * 		given by {@link CCNHandle.getHandle()} will be used.
	 * @throws IOException Not currently thrown, will be thrown when constructors retrieve first block.
	 */
	public CCNVersionedInputStream(ContentName name,
			Long startingSegmentNumber, PublisherPublicKeyDigest publisher,
			ContentKeys keys, CCNHandle handle)
			throws XMLStreamException, IOException {
		super(name, startingSegmentNumber, publisher, keys, handle);
	}

	/**
	 * Set up an input stream to read segmented CCN content starting with a given
	 * {@link ContentObject} that has already been retrieved.  Content is assumed
	 * to be unencrypted, or keys will be retrieved automatically via another
	 * process (for example, an {@link AccessControlManager}).
	 * @param startingSegment The first segment to read from. If this is not the
	 * 		first segment of the stream, reading will begin from this point.
	 * 		We assume that the signature on this segment was verified by our caller.
	 * @param handle The CCN handle to use for data retrieval. If null, the default handle
	 * 		given by {@link CCNHandle.getHandle()} will be used.
	 * @throws IOException
	 */
	public CCNVersionedInputStream(ContentObject startingSegment,
			CCNHandle handle) throws IOException {
		super(startingSegment, handle);
	}
	
	/**
	 * Set up an input stream to read segmented CCN content starting with a given
	 * {@link ContentObject} that has already been retrieved.  
	 * @param startingSegment The first segment to read from. If this is not the
	 * 		first segment of the stream, reading will begin from this point.
	 * 		We assume that the signature on this segment was verified by our caller.
	 * @param keys The keys to use to decrypt this content. Null if content unencrypted, or another
	 * 				process will be used to retrieve the keys (for example, an {@link AccessControlManager}).
	 * @param handle The CCN handle to use for data retrieval. If null, the default handle
	 * 		given by {@link CCNHandle.getHandle()} will be used.
	 * @throws IOException
	 */
	public CCNVersionedInputStream(ContentObject startingSegment, ContentKeys keys, CCNHandle handle) throws IOException {
		super(startingSegment, keys, handle);
	}
	
	/**
	 * Implementation of {@link #getFirstSegment()} that expects segments to be versioned. If a version
	 * (and optionally a segment) is specified in the name, gets that specific version (and segment). Otherwise,
	 * gets the latest version available. Uses {@link VersioningProfile.getFirstBlockOfLatestVersion}.
	 * @throws IOException If no block found ({@link NoMatchingContentFoundException}), or there is
	 *   an error retrieving the block.
	 */
	@Override
	protected ContentObject getFirstSegment() throws IOException {
		if (VersioningProfile.hasTerminalVersion(_baseName)) {
			// Get exactly this version
			return super.getFirstSegment();
		}
		Log.info("getFirstSegment: getting latest version of " + _baseName);
		ContentObject result = 
			VersioningProfile.getFirstBlockOfLatestVersion(_baseName, _startingSegmentNumber, _publisher, _timeout, this, _handle);
		if (null != result){
			Log.info("getFirstSegment: retrieved latest version object " + result.name() + " type: " + result.signedInfo().getTypeName());
			_baseName = result.name().cut(_baseName.count() + 1);
		} else {
			Log.info("getFirstSegment: no segment available for latest version of " + _baseName);
		}
		return result;
	}
	
	/**
	 * Determines whether a given content object is the first block of the versioned stream specified.
	 */
	@Override
	protected boolean isFirstSegment(ContentName desiredName, ContentObject potentialFirstSegment) {
		return VersioningProfile.isVersionedFirstSegment(desiredName, potentialFirstSegment, _startingSegmentNumber);
	}
	
	/**
	 * Convenience method.
	 * @return The version of this content as a {@link CCNTime}.
	 * @throws VersionMissingException If we do not yet have a versioned content name.
	 */
	public CCNTime getVersionAsTimestamp() throws VersionMissingException {
		if (null == _baseName)
			throw new VersionMissingException("Have not yet retrieved content name!");
		return VersioningProfile.getLastVersionAsTimestamp(_baseName);
	}
}
{'fraction_non_alphanumeric': 0.06692551343619087, 'fraction_numerical': 0.002247879840604884, 'mean_word_length': 4.25503355704698, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 2}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3223865', 'n_tokens_mistral': 5296, 'n_tokens_neox': 4844, 'n_words': 2357}