/*
* Copyright 2013 Jeanfrancois Arcand
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package org.zodiark.service;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.atmosphere.cpr.AtmosphereResource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.zodiark.protocol.Envelope;
import org.zodiark.protocol.Message;
import org.zodiark.server.EventBus;
import org.zodiark.server.Reply;
import org.zodiark.server.ReplyException;
import org.zodiark.service.db.result.Status;
import java.util.concurrent.ConcurrentHashMap;
public class EndpointUtils<T extends EndpointAdapter> {
public static final String ERROR_SERVICE = "/error";
private final Logger logger = LoggerFactory.getLogger(EndpointUtils.class);
private final EventBus eventBus;
private final ObjectMapper mapper;
private final ConcurrentHashMap<String, T> endpoints;
public EndpointUtils(EventBus eventBus, ObjectMapper mapper, ConcurrentHashMap<String, T> endpoints) {
this.eventBus = eventBus;
this.mapper = mapper;
this.endpoints = endpoints;
}
public void statusEvent(final String path, final Envelope e) {
String uuid = e.getUuid();
final T p = endpoints.get(uuid);
statusEvent(path, e, p);
}
public void statusEvent(final String path, final Envelope e, final T p) {
if (!validateAll(p, e)) ;
statusEvent(path, e, p, new Reply<Status, String>() {
@Override
public void ok(Status status) {
logger.trace("Status {}", status);
response(e, p, constructMessage(path, writeAsString(status), e.getMessage().getUUID()));
}
@Override
public void fail(ReplyException replyException) {
error(e, p, errorMessage(writeAsString(new Error().error("Unauthorized")), e.getMessage().getUUID()));
}
});
}
public void statusEvent(final String path, final Envelope e, final T p, Reply<Status, String> r) {
eventBus.message(path, new RetrieveMessage(p.uuid(), e.getMessage()), r);
}
public void passthroughEvent(final String path, final Envelope e) {
passthroughEvent(path, e, retrieve(e.getUuid()));
}
public void passthroughEvent(final String path, final Envelope e, final T p) {
if (!validate(p, e)) return;
if (!validateShowId(p, e)) return;
eventBus.message(path, new RetrieveMessage(p.uuid(), e.getMessage()), new Reply<String, String>() {
@Override
public void ok(String passthrough) {
succesPassThrough(e, p, path, passthrough);
}
@Override
public void fail(ReplyException replyException) {
failPassThrough(e, p, replyException);
}
});
}
public boolean validate(T p, Envelope e) {
if (p == null) {
error(e, p, errorMessage(writeAsString(new Error().error("Unauthorized")), e.getMessage().getUUID()));
return false;
}
return true;
}
public boolean validateShowId(T p, Envelope e) {
if (p == null) {
error(e, p, constructMessage(e.getMessage().getPath(), writeAsString(new Error().error("Unauthorized")), e.getMessage().getUUID()));
return false;
}
return true;
}
public boolean validateAll(T p, Envelope e) {
if (!validate(p, e)) return false;
if (!validateShowId(p, e)) return false;
return true;
}
public void succesPassThrough(Envelope e, T p, String path, String passthrough) {
logger.trace("Passthrough succeed {}", passthrough);
response(e, p, constructMessage(path, passthrough, e.getMessage().getUUID()));
}
public void failPassThrough(Envelope e, T p, ReplyException passthrough) {
logger.trace("Passthrough failed {}", passthrough);
error(e, p, errorMessage(passthrough.throwable().getMessage(), e.getMessage().getUUID()));
}
public void error(Envelope e, T endpoint, Message m) {
AtmosphereResource r = endpoint.resource();
// TODO: Validate
endpoints.remove(endpoint);
error(e, r, m);
}
public void error(Envelope e, AtmosphereResource r, Message m) {
Envelope error = Envelope.newServerReply(e, errorMessage("/error", e.getMessage().getUUID()));
eventBus.ioEvent(error, r);
}
public String writeAsString(Object o) {
try {
return mapper.writeValueAsString(o);
} catch (JsonProcessingException e) {
return "{\"error\":\"" + e.getMessage() + "\"}";
}
}
public Message constructMessage(String path, String status, String uuid) {
Message m = new Message();
m.setPath(path);
m.setData(status);
m.setUUID(uuid);
return m;
}
public Message errorMessage(String status, String uuid) {
Message m = new Message();
m.setPath(ERROR_SERVICE);
m.setData(status);
m.setUUID(uuid);
return m;
}
/**
* {@inheritDoc}
*/
public void response(Envelope e, T endpoint, Message m) {
AtmosphereResource r = endpoint.resource();
Envelope newResponse = Envelope.newServerReply(e, m);
try {
r.write(mapper.writeValueAsString(newResponse));
} catch (JsonProcessingException e1) {
logger.debug("Unable to write {} {}", endpoint, m);
}
}
public T retrieve(String uuid) {
T p = endpoints.get(uuid);
return p;
}
}