package edu.uw.zookeeper.protocol;
import static com.google.common.base.Preconditions.checkNotNull;
import java.util.Arrays;
import java.util.concurrent.TimeUnit;
import com.google.common.base.Function;
import com.google.common.base.MoreObjects;
import com.google.common.base.Objects;
import com.google.common.base.Optional;
import edu.uw.zookeeper.common.Hex;
import edu.uw.zookeeper.common.TimeValue;
public final class Session {
private static final long UNINITIALIZED_ID = 0;
private static final Session UNINITIALIZED = new Session(UNINITIALIZED_ID, Parameters.uninitialized());
public static Session uninitialized() {
return UNINITIALIZED;
}
public static Session create(long id, Parameters parameters) {
return new Session(id, parameters);
}
public static String toString(long id) {
return String.format("0x%s", Hex.toPaddedHexString(id));
}
private final long id;
private final Parameters parameters;
private Session(long id, Parameters parameters) {
this.id = id;
this.parameters = checkNotNull(parameters);
}
public long id() {
return id;
}
public Parameters parameters() {
return parameters;
}
@Override
public String toString() {
return MoreObjects.toStringHelper(this).add("id", toString(id))
.add("parameters", parameters).toString();
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
Session other = (Session) obj;
return Objects.equal(id, other.id)
&& Objects.equal(parameters, other.parameters);
}
@Override
public int hashCode() {
return Objects.hashCode(id);
}
public static enum State implements Function<State, Optional<State>> {
SESSION_UNINITIALIZED {
@Override
public Optional<State> apply(State nextState) {
switch (nextState) {
case SESSION_UNINITIALIZED:
return Optional.absent();
case SESSION_OPENED:
return Optional.of(nextState);
default:
throw new IllegalArgumentException();
}
}
},
SESSION_OPENED {
@Override
public Optional<State> apply(State nextState) {
switch (nextState) {
case SESSION_OPENED:
return Optional.absent();
case SESSION_EXPIRED:
case SESSION_CLOSED:
return Optional.of(nextState);
default:
throw new IllegalArgumentException();
}
}
},
SESSION_EXPIRED {
@Override
public Optional<State> apply(State nextState) {
switch (nextState) {
case SESSION_EXPIRED:
return Optional.absent();
case SESSION_CLOSED:
return Optional.of(nextState);
default:
throw new IllegalArgumentException();
}
}
},
SESSION_CLOSED {
@Override
public Optional<State> apply(State nextState) {
switch (nextState) {
case SESSION_CLOSED:
return Optional.absent();
default:
throw new IllegalArgumentException();
}
}
};
}
public static class Parameters {
private static final long NO_TIMEOUT = 0L;
private static final byte[] NO_PASSWORD = new byte[0];
private static final TimeUnit TIMEOUT_UNIT = TimeUnit.MILLISECONDS;
private static final Parameters UNINITIALIZED_PARAMETERS = create(NO_TIMEOUT, NO_PASSWORD);
public static long noTimeout() {
return NO_TIMEOUT;
}
public static TimeUnit timeoutUnit() {
return TIMEOUT_UNIT;
}
public static Parameters uninitialized() {
return UNINITIALIZED_PARAMETERS;
}
public static Parameters create(long timeOut) {
return create(timeOut, NO_PASSWORD);
}
public static Parameters create(TimeValue timeOut, byte[] password) {
return new Parameters(timeOut.convert(TIMEOUT_UNIT), checkNotNull(password));
}
public static Parameters create(long timeOut, byte[] password) {
return new Parameters(TimeValue.create(timeOut, TIMEOUT_UNIT), checkNotNull(password));
}
private final TimeValue timeOut;
private final byte[] password;
private Parameters(TimeValue timeOut, byte[] password) {
this.timeOut = timeOut;
this.password = password;
}
public TimeValue timeOut() {
return timeOut;
}
/**
* Returns a copy
*/
public byte[] password() {
return password.clone();
}
@Override
public String toString() {
String passwordStr;
if (password == null) {
passwordStr = "null";
} else if (password.length == 0) {
passwordStr = "";
} else {
// just output a hash
passwordStr = String.format("0x%08x", password.hashCode());
// BigInteger bi = new BigInteger(1, password);
// passwordStr = String.format("0x%0" + (password.length << 1) +
// "X", bi);
}
return MoreObjects.toStringHelper(this).add("password", passwordStr)
.add("timeOut", timeOut)
.toString();
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
Parameters other = (Parameters) obj;
return Arrays.equals(password, other.password)
&& Objects.equal(timeOut, other.timeOut);
}
@Override
public int hashCode() {
return Objects.hashCode(password);
}
}
}