Commit d73e3ebf authored by toaster's avatar toaster
Browse files

token store operations

git-svn-id: https://subversion.umiacs.umd.edu/ace/trunk@28 f1b3a171-7291-4a19-a512-95ad0ad9394a
parent b0550e04
......@@ -61,6 +61,20 @@ public class DigestFactory {
return instance;
}
public boolean isRegistered(String className)
{
if (Strings.isEmpty(className))
return false;
for (DigestProvider dp : digestProviders.values())
{
if (dp.getProvider().getClass().getCanonicalName().equals(className))
return true;
}
return false;
}
public void registerProvider( String className ) {
Check.notEmpty("className", className);
try {
......
......@@ -38,8 +38,8 @@ import java.util.Iterator;
import java.util.List;
/*******************************************************************************
* Proof object.
*
* Proof object. comparison for equals/hashcode is only done on actual proof nodes
* and not metadata
*
* @version {@code $Revision$ $Date$}
*
......@@ -84,7 +84,31 @@ public final class Proof implements Iterable<ProofNode>, Serializable {
@Override
public String toString() {
return new BigInteger(leafHash).toString() + ":"
return (leafHash != null ? new BigInteger(leafHash).toString() : "nullLeaf") + ":"
+ new StringListBuilder().setDelimiter(",").append(nodes).toString();
}
@Override
public int hashCode() {
int hash = 3;
hash = 17 * hash + (this.nodes != null ? this.nodes.hashCode() : 0);
return hash;
}
@Override
public boolean equals( Object obj ) {
if ( obj == null ) {
return false;
}
if ( getClass() != obj.getClass() ) {
return false;
}
final Proof other = (Proof) obj;
if ( this.nodes != other.nodes && (this.nodes == null || !this.nodes.equals(other.nodes)) ) {
return false;
}
return true;
}
}
package edu.umiacs.ace.hashtree;
import edu.umiacs.util.Check;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
/**
* Build a new Proof from supplied elements.
*
* Note, the returned proof will only have proof elements, extra
* metadata will be null.
*
* Currently, this is NOT threadsafe.
*
* @author toaster
*/
public class ProofBuilder {
private String algorithm;
private String provider;
private List<ProofNode> elements;// = new LinkedList<ProofNode>();
private int inheritIndex;
private int writeIdx;
private byte[][] hashes;
public ProofBuilder() {
}
/**
* start new level
*
* @param levelSize total hashes in this level (including inherited digest)
*/
public void newLevel( int levelSize ) {
if ( hashes != null ) {
writeLevel();
}
this.hashes = new byte[levelSize - 1][];
writeIdx = 0;
}
public void setLevelInheritIndex( int suppliedIndex ) {
if ( suppliedIndex < 0 || suppliedIndex > hashes.length ) {
throw new IllegalArgumentException("supplied index outside hashes list: "
+ suppliedIndex + " / " + hashes.length);
}
inheritIndex = suppliedIndex;
}
public void addLevelHash( byte[] hash ) {
if ( hashes == null ) {
throw new IllegalStateException("level not open (use newLevel)");
}
Check.notNull("Hash", hash);
if ( writeIdx >= hashes.length ) {
throw new IllegalStateException("Attempting to add hash past round end: " + writeIdx);
}
hashes[writeIdx] = hash;
writeIdx++;
}
/**
*
* @param suppliedIndex
* @param hashes
*/
public void addProofLevel( int suppliedIndex, byte[]... hashes ) {
if ( hashes == null || hashes.length < 1 ) {
throw new IllegalArgumentException("hashe list must contain at leaset 1 hash");
}
newLevel(hashes.length + 1);
setLevelInheritIndex(suppliedIndex);
for ( byte[] b : hashes ) {
addLevelHash(b);
}
writeLevel();
}
private void writeLevel() {
if ( inheritIndex == -1 ) {
throw new IllegalStateException("Inherit index not set for this level");
}
if ( hashes.length != writeIdx ) {
throw new IllegalStateException("Level contains empty hashes, cannot assemble, idx: "
+ writeIdx + "/" + hashes.length);
}
List<ProofHash> hashList = new ArrayList<ProofHash>(hashes.length);
for ( int i = 0; i < hashes.length; i++ ) {
int location = (i >= inheritIndex ? i + 1 : i);
hashList.add(new ProofHash(hashes[i], location));
}
ProofNode pn = new ProofNode(hashList, inheritIndex);
if ( elements == null ) {
elements = new ArrayList<ProofNode>(5);
}
elements.add(pn);
hashes = null;
inheritIndex = -1;
}
public void setAlgorithm( String algorithm ) {
this.algorithm = algorithm;
}
public void setProvider( String provider ) {
this.provider = provider;
}
public String getAlgorithm() {
return algorithm;
}
public String getProvider() {
return provider;
}
public Proof buildProof() {
if ( hashes != null ) {
writeLevel();
}
if ( elements == null ) {
throw new IllegalStateException("No proof elements added");
}
Proof newProof = new Proof(algorithm, provider, null, elements);
elements = null;
return newProof;
}
}
......@@ -32,6 +32,7 @@ package edu.umiacs.ace.hashtree;
import java.io.Serializable;
import java.math.BigInteger;
import java.util.Arrays;
/*******************************************************************************
*
......@@ -64,4 +65,33 @@ public final class ProofHash implements Serializable {
public String toString() {
return new BigInteger(hash).toString() + "[" + index + "]";
}
@Override
public int hashCode() {
int hash = 3;
hash = 89 * hash + Arrays.hashCode(this.hash);
hash = 89 * hash + this.index;
return hash;
}
@Override
public boolean equals( Object obj ) {
if ( obj == null ) {
return false;
}
if ( getClass() != obj.getClass() ) {
return false;
}
final ProofHash other = (ProofHash) obj;
if ( !Arrays.equals(this.hash, other.hash) ) {
return false;
}
if ( this.index != other.index ) {
return false;
}
return true;
}
}
......@@ -72,4 +72,31 @@ public final class ProofNode implements Iterable<ProofHash>, Serializable {
return String.valueOf(index) + "("
+ new StringListBuilder().setDelimiter(",").append(proofItems).toString() + ")";
}
@Override
public int hashCode() {
int hash = 3;
hash = 47 * hash + (this.proofItems != null ? this.proofItems.hashCode() : 0);
hash = 47 * hash + this.index;
return hash;
}
@Override
public boolean equals( Object obj ) {
if ( obj == null ) {
return false;
}
if ( getClass() != obj.getClass() ) {
return false;
}
final ProofNode other = (ProofNode) obj;
if ( this.proofItems != other.proofItems &&
(this.proofItems == null || !this.proofItems.equals(other.proofItems)) ) {
return false;
}
if ( this.index != other.index ) {
return false;
}
return true;
}
}
package edu.umiacs.ace.token;
import edu.umiacs.ace.hashtree.Proof;
import java.util.Date;
/**
*
* @author toaster
*/
public class AceToken {
private String digestType;
private String imsService;
private String ims;
private Date date;
private long round;
private Proof tokenProof;
AceToken() {
}
void setDate( Date date ) {
this.date = date;
}
void setDigestType( String digestType ) {
this.digestType = digestType;
}
void setIms( String ims ) {
this.ims = ims;
}
void setImsService( String imsService ) {
this.imsService = imsService;
}
void setRound( long round ) {
this.round = round;
}
void setProof( Proof tokenProof ) {
this.tokenProof = tokenProof;
}
public Date getDate() {
return date;
}
public String getDigestType() {
return digestType;
}
public String getIms() {
return ims;
}
public String getImsService() {
return imsService;
}
public long getRound() {
return round;
}
public Proof getProof() {
return tokenProof;
}
@Override
public String toString() {
return (imsService + "("+date+"/"+round+")@" + ims + " "+digestType+":"+tokenProof);
}
@Override
public int hashCode() {
int hash = 7;
hash = 37 * hash + (this.digestType != null ? this.digestType.hashCode() : 0);
hash = 37 * hash + (int) (this.round ^ (this.round >>> 32));
hash = 37 * hash + (this.tokenProof != null ? this.tokenProof.hashCode() : 0);
return hash;
}
@Override
public boolean equals( Object obj ) {
if ( obj == null ) {
return false;
}
if ( getClass() != obj.getClass() ) {
return false;
}
final AceToken other = (AceToken) obj;
if ( (this.digestType == null) ? (other.digestType != null)
: !this.digestType.equals(other.digestType) ) {
return false;
}
if ( this.round != other.round ) {
return false;
}
if ( this.tokenProof != other.tokenProof &&
(this.tokenProof == null || !this.tokenProof.equals(other.tokenProof)) ) {
return false;
}
return true;
}
}
package edu.umiacs.ace.token;
import edu.umiacs.ace.hashtree.ProofBuilder;
import edu.umiacs.util.Check;
import edu.umiacs.util.Strings;
import java.util.Date;
/**
*
* @author toaster
*/
public class AceTokenBuilder {
private String ims;
private String digestAlg;
private String imsService;
private long round = -1;
private Date date;
private ProofBuilder proofBuilder = new ProofBuilder();
public void reset() {
ims = null;
digestAlg = null;
imsService = null;
round = -1;
date = null;
}
public void setRound( long round ) {
this.round = Check.isPositive("Round", round);
}
public void setImsService( String imsService ) {
this.imsService = Check.noWhitespace("IMS Service", imsService);
}
public void setIms( String ims ) {
this.ims = Check.noWhitespace("IMS", ims);
}
public void setDigestAlgorithm( String digestAlg ) {
this.digestAlg = Check.noWhitespace("Digest", digestAlg);
}
public void setDate( Date date ) {
this.date = Check.notNull("Date", date);
}
public AceToken createToken() {
if ( Strings.isEmpty(ims) || Strings.isEmpty(digestAlg) || Strings.isEmpty(imsService)
|| date == null || round == -1 ) {
throw new IllegalStateException("All token parameters not filled out");
}
AceToken token = new AceToken();
token.setDate(date);
token.setDigestType(digestAlg);
token.setIms(ims);
token.setImsService(imsService);
token.setRound(round);
token.setProof(proofBuilder.buildProof());
return token;
}
public void startProofLevel(int hashes)
{
proofBuilder.newLevel(hashes);
}
public void setLevelInheritIndex(int index)
{
proofBuilder.setLevelInheritIndex(index);
}
public void addLevelHash(byte[] ... hashes)
{
for (byte[] b : hashes)
{
proofBuilder.addLevelHash(b);
}
}
/**
* Add a proof level to the current token. proof levels should be added, starting
* at bottom of proof tree.
*
*/
public void addProofLevel( int index, byte[]... hashes ) {
proofBuilder.addProofLevel(index, hashes);
}
}
package edu.umiacs.ace.token;
import edu.umiacs.ace.hashtree.ProofHash;
import edu.umiacs.ace.hashtree.ProofNode;
import edu.umiacs.ace.util.HashValue;
import edu.umiacs.util.Check;
import edu.umiacs.util.Strings;
import java.io.OutputStream;
/**
*
* @author toaster
*/
public class AceTokenWriter extends TokenStoreWriter<AceToken>
{
public AceTokenWriter(OutputStream os) {
super(os);
}
public void startToken(AceToken token)
{
Check.notNull("Token", token);
setHeaderInformation(token.getDigestType(), token.getIms(), token.getImsService(),
token.getRound(), token.getDate());
for ( ProofNode node : token.getProof() ) {
String[] hashList = new String[node.getHashes().size() + 1];
hashList[node.getIndex()] = "X";
for ( ProofHash element : node ) {
hashList[element.getIndex()] = HashValue.asHexString(element.getHash());
}
addHashLevel(Strings.join(':', hashList));
}
}
}
package edu.umiacs.ace.token;
/**
*
* @author toaster
*/
public class TokenLoadException extends RuntimeException
{
public enum ErrorType {
IOEXCEPTION, HEADERFORMATERROR, PROOFFORMATERROR
}
public TokenLoadException(Exception e) {
super(e);
}
public TokenLoadException(ErrorType type, String line) {
super(type + ": " + line);
}
}
package edu.umiacs.ace.token;
import java.util.Collections;
import java.util.List;
/**
*
* @author toaster
*/
public class TokenStoreEntry {
private AceToken token;
private List<String> identifiers;
TokenStoreEntry() {
}
void setToken( AceToken token ) {
this.token = token;
}
void setIdentifiers( List<String> identifiers ) {
this.identifiers = Collections.unmodifiableList(identifiers);
}
public AceToken getToken() {
return token;
}
public List<String> getIdentifiers() {
return identifiers;
}
@Override
public String toString() {
return "Token: " + token + " " + identifiers;
}
}
package edu.umiacs.ace.token;
import edu.umiacs.ace.token.TokenLoadException.ErrorType;
import edu.umiacs.ace.util.HashValue;