package org.infinispan.rest; import java.io.IOException; import java.io.ObjectInput; import java.io.ObjectOutput; import java.util.Objects; import java.util.Set; import java.util.concurrent.TimeUnit; import org.infinispan.commons.marshall.AbstractExternalizer; import org.infinispan.commons.util.Util; import org.infinispan.container.versioning.EntryVersion; import org.infinispan.metadata.Metadata; import org.jboss.marshalling.util.IdentityIntMap; /** * Metadata for MIME data stored in REST servers. * * @author Galder ZamarreƱo * @since 5.3 */ public class MimeMetadata implements Metadata { protected final String contentType; public MimeMetadata(String contentType) { this.contentType = Objects.requireNonNull(contentType); } @Override public long lifespan() { return -1; } @Override public long maxIdle() { return -1; } @Override public EntryVersion version() { return null; } @Override public Builder builder() { return new MimeMetadataBuilder().contentType(contentType); } public String contentType() { return contentType; } @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; MimeMetadata that = (MimeMetadata) o; return contentType.equals(that.contentType); } @Override public int hashCode() { return 41 + contentType.hashCode(); } @Override public String toString() { return "MimeMetadata{" + "contentType='" + contentType + '\'' + '}'; } private static final int Immortal = 0; private static final int Expirable = 1; private static final int LifespanExpirable = 2; private static final int MaxIdleExpirable = 3; private static final IdentityIntMap<Class> numbers = new IdentityIntMap<>(4); static { numbers.put(MimeMetadata.class, Immortal); numbers.put(MimeExpirableMetadata.class, Expirable); numbers.put(MimeLifespanExpirableMetadata.class, LifespanExpirable); numbers.put(MimeMaxIdleExpirableMetadata.class, MaxIdleExpirable); } public static class Externalizer extends AbstractExternalizer<MimeMetadata> { @Override public MimeMetadata readObject(ObjectInput input) throws IOException, ClassNotFoundException { String contentType = input.readUTF(); int number = input.readUnsignedByte(); switch (number) { case Immortal: return new MimeMetadata(contentType); case Expirable: long lifespan = input.readLong(); long maxIdle = input.readLong(); return new MimeExpirableMetadata(contentType, lifespan, TimeUnit.MILLISECONDS, maxIdle, TimeUnit.MILLISECONDS); case LifespanExpirable: lifespan = input.readLong(); return new MimeLifespanExpirableMetadata(contentType, lifespan, TimeUnit.MILLISECONDS); case MaxIdleExpirable: maxIdle = input.readLong(); return new MimeMaxIdleExpirableMetadata(contentType, maxIdle, TimeUnit.MILLISECONDS); default: throw new IllegalArgumentException("Unsupported type: " + number); } } @Override public void writeObject(ObjectOutput output, MimeMetadata meta) throws IOException { output.writeUTF(meta.contentType); int number = numbers.get(meta.getClass(), -1); output.write(number); switch (number) { case Immortal: // no-op break; case Expirable: output.writeLong(meta.lifespan()); output.writeLong(meta.maxIdle()); break; case LifespanExpirable: output.writeLong(meta.lifespan()); break; case MaxIdleExpirable: output.writeLong(meta.maxIdle()); break; default: throw new IllegalArgumentException("Unsupported type: " + number); } } @Override public Set<Class<? extends MimeMetadata>> getTypeClasses() { return Util.asSet(MimeMetadata.class, MimeExpirableMetadata.class, MimeLifespanExpirableMetadata.class, MimeMaxIdleExpirableMetadata.class); } } } class MimeExpirableMetadata extends MimeMetadata { private final long lifespanTime; private final TimeUnit lifespanUnit; private final long maxIdleTime; private final TimeUnit maxIdleUnit; public MimeExpirableMetadata(String contentType, long lifespanTime, TimeUnit lifespanUnit, long maxIdleTime, TimeUnit maxIdleUnit) { super(contentType); this.lifespanTime = lifespanTime; this.lifespanUnit = Objects.requireNonNull(lifespanUnit); this.maxIdleTime = maxIdleTime; this.maxIdleUnit = Objects.requireNonNull(maxIdleUnit); } @Override public long lifespan() { return lifespanUnit.toMillis(lifespanTime); } @Override public long maxIdle() { return maxIdleUnit.toMillis(maxIdleTime); } @Override public Builder builder() { return new MimeMetadataBuilder().contentType(contentType).lifespan(lifespanTime, lifespanUnit).maxIdle(maxIdleTime, maxIdleUnit); } @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; if (!super.equals(o)) return false; MimeExpirableMetadata that = (MimeExpirableMetadata) o; if (lifespanTime != that.lifespanTime) return false; if (maxIdleTime != that.maxIdleTime) return false; if (lifespanUnit != that.lifespanUnit) return false; return maxIdleUnit == that.maxIdleUnit; } @Override public int hashCode() { int result = super.hashCode(); result = 31 * result + (int) (lifespanTime ^ (lifespanTime >>> 32)); result = 31 * result + lifespanUnit.hashCode(); result = 31 * result + (int) (maxIdleTime ^ (maxIdleTime >>> 32)); result = 31 * result + maxIdleUnit.hashCode(); return result; } @Override public String toString() { return "MimeExpirableMetadata{" + "lifespanTime=" + lifespanTime + ", lifespanUnit=" + lifespanUnit + ", maxIdleTime=" + maxIdleTime + ", maxIdleUnit=" + maxIdleUnit + '}'; } } class MimeLifespanExpirableMetadata extends MimeMetadata { private final long lifespanTime; private final TimeUnit lifespanUnit; MimeLifespanExpirableMetadata(String contentType, long lifespanTime, TimeUnit lifespanUnit) { super(contentType); this.lifespanTime = lifespanTime; this.lifespanUnit = Objects.requireNonNull(lifespanUnit); } @Override public long lifespan() { return lifespanUnit.toMillis(lifespanTime); } @Override public Builder builder() { return new MimeMetadataBuilder().contentType(contentType).lifespan(lifespanTime, lifespanUnit); } @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; if (!super.equals(o)) return false; MimeLifespanExpirableMetadata that = (MimeLifespanExpirableMetadata) o; if (lifespanTime != that.lifespanTime) return false; return lifespanUnit == that.lifespanUnit; } @Override public int hashCode() { int result = super.hashCode(); result = 31 * result + (int) (lifespanTime ^ (lifespanTime >>> 32)); result = 31 * result + lifespanUnit.hashCode(); return result; } @Override public String toString() { return "MimeLifespanExpirableMetadata{" + "lifespanTime=" + lifespanTime + ", lifespanUnit=" + lifespanUnit + '}'; } } class MimeMaxIdleExpirableMetadata extends MimeMetadata { private final long maxIdleTime; private final TimeUnit maxIdleUnit; public MimeMaxIdleExpirableMetadata(String contentType, long maxIdleTime, TimeUnit maxIdleUnit) { super(contentType); this.maxIdleTime = maxIdleTime; this.maxIdleUnit = Objects.requireNonNull(maxIdleUnit); } @Override public long maxIdle() { return maxIdleUnit.toMillis(maxIdleTime); } @Override public Builder builder() { return new MimeMetadataBuilder().contentType(contentType).maxIdle(maxIdleTime, maxIdleUnit); } @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; if (!super.equals(o)) return false; MimeMaxIdleExpirableMetadata that = (MimeMaxIdleExpirableMetadata) o; if (maxIdleTime != that.maxIdleTime) return false; return maxIdleUnit == that.maxIdleUnit; } @Override public int hashCode() { int result = super.hashCode(); result = 31 * result + (int) (maxIdleTime ^ (maxIdleTime >>> 32)); result = 31 * result + maxIdleUnit.hashCode(); return result; } @Override public String toString() { return "MimeMaxIdleExpirableMetadata{" + "maxIdleTime=" + maxIdleTime + ", maxIdleUnit=" + maxIdleUnit + '}'; } }