xapi.io.impl.AbstractIOService Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of xapi-gwt Show documentation
Show all versions of xapi-gwt Show documentation
This module exists solely to package all other gwt modules into a single
uber jar. This makes deploying to non-mavenized targets much easier.
Of course, you would be wise to inherit your dependencies individually;
the uber jar is intended for projects like collide,
which have complex configuration, and adding many jars would be a pain.
The newest version!
package xapi.io.impl;
import static xapi.collect.X_Collect.newClassMap;
import javax.inject.Provider;
import xapi.collect.X_Collect;
import xapi.collect.api.ClassTo;
import xapi.collect.api.StringDictionary;
import xapi.collect.api.StringTo.Many;
import xapi.io.IOConstants;
import xapi.io.api.IOCallback;
import xapi.io.api.IOMessage;
import xapi.io.api.IORequest;
import xapi.io.api.IORequestBuilder;
import xapi.io.service.IOService;
import xapi.log.api.LogLevel;
import xapi.util.X_Namespace;
import xapi.util.X_Properties;
import xapi.util.api.ConvertsValue;
import xapi.util.api.ReceivesValue;
import xapi.util.api.RemovalHandler;
public abstract class AbstractIOService implements IOService{
public AbstractIOService() {
}
protected static final IORequest cancelled = new IORequest() {
@Override
public boolean isPending() {
return false;
}
@Override
public boolean isSuccess() {
return false;
}
@Override
public void cancel() {
}
@Override
public String response() {
return null;
}
@Override
public Many headers() {
return X_Collect.newStringMultiMap(String.class);
}
@Override
public int getStatusCode() {
return STATUS_CANCELLED;
}
@Override
public String getStatusText() {
return "Request Cancelled";
}
};
public abstract class AbstractIORequest implements IORequest {
private boolean pending = true;
private String value;
private volatile boolean cancel;
private boolean started;
protected Provider> resultHeaders;
private int statusCode = STATUS_INCOMPLETE;
private String statusText = "Request Incomplete";
@Override
public boolean isPending() {
return pending;
}
public void start() {
this.started = true;
}
@Override
public boolean isSuccess() {
return pending == false && cancel == false && value != null;
}
@Override
public void cancel() {
this.pending = false;
this.cancel = false;
}
@Override
public Many headers() {
return resultHeaders == null ? X_Collect.newStringMultiMap(String.class) : resultHeaders.get();
}
public boolean isStarted() {
return started;
}
public boolean isCancelled() {
return cancel;
}
/**
* @return -> value
*/
public String getValue() {
return value;
}
/**
* @param value -> set value
*/
public void setValue(final String value) {
pending = false;
this.value = value;
}
public void setResultHeaders(final Provider> resultHeaders) {
this.resultHeaders = resultHeaders;
}
public void setStatus(final int statusCode, final String statusText) {
this.statusCode = statusCode;
this.statusText = statusText;
}
@Override
public int getStatusCode() {
return statusCode;
}
@Override
public String getStatusText() {
return statusText;
}
}
@SuppressWarnings("unchecked")
private static final Class> SERIAL_CLASS
= Class.class.cast(ConvertsValue.class);
@SuppressWarnings("unchecked")
private static final Class> DESERIAL_CLASS
= Class.class.cast(ConvertsValue.class);
protected final ClassTo> serializers = newClassMap(SERIAL_CLASS);
protected final ClassTo> deserializers = newClassMap(DESERIAL_CLASS);
@Override
@SuppressWarnings("unchecked") // The class key is always checked for us...
public IORequestBuilder request(final Class classLit, final String id) {
return this.createRequestBuilder()
.setUrl(toUrl(classLit, id))
.setDeserializer(ConvertsValue.class.cast(deserializers.get(classLit)))
.setSerializer(ConvertsValue.class.cast(serializers.get(classLit)))
;
}
protected IORequestBuilderDefault createRequestBuilder() {
return new IORequestBuilderDefault();
}
protected LogLevel logLevel() {
return LogLevel.DEBUG;
}
@Override
@SuppressWarnings({
"unchecked", "rawtypes"
})
public RemovalHandler registerParser(final Class classLit,
final ConvertsValue serializer,
final ConvertsValue deserializer
) {
final ConvertsValue,String> currentSerializer = serializers.put(classLit, serializer);
final ConvertsValue currentDeserialize = deserializers.put(classLit, deserializer);
// In case a user wants to wrap the existing serializers, we will send them the previous instances.
if (serializer instanceof ReceivesValue) {
((ReceivesValue)serializer).set(currentSerializer);
}
if (deserializer instanceof ReceivesValue) {
((ReceivesValue)deserializer).set(currentDeserialize);
}
return new RemovalHandler() {
@Override
public void remove() {
// check before set.
if (serializers.get(classLit) == serializer) {
serializers.put(classLit, currentSerializer);
}
if (deserializers.get(classLit) == deserializer) {
deserializers.put(classLit, currentDeserialize);
}
}
};
}
@Override
public void put(final String url, final byte[] body, final StringDictionary headers,
final IOCallback> callback) {
}
protected String uriBase() {
final String port = X_Properties.getProperty(X_Namespace.PROPERTY_SERVER_PORT, "");
return System.getProperty(X_Namespace.PROPERTY_SERVER_HOST, "0.0.0.0")
+ (port.length()==0?"":":"+port);
}
/**
* Allow subclasses to apply any settings to the connection before we open it
* @param connect - An instance of whatever transport mechanism this IO service uses, just before it is opened.
* @param modifiers - The type of connection,
* see {@link IOConstants#METHOD_GET}, {@link IOConstants#METHOD_PUT} and friends
*/
protected void applySettings(final Transport connect, final int modifiers) {
}
protected String normalize(String uri) {
if (uri.charAt(0) == '/') {
uri = uriBase() + uri;
}
if (!uri.contains("://")) {
uri = "http://"+uri;
}
return uri;
}
protected String toUrl(final Class> classLit, final String id) {
return id;
}
@Override
public void delete(final String url, final StringDictionary headers, final IOCallback> callback) {
}
}