/* (c) 2014 - 2016 Open Source Geospatial Foundation - all rights reserved
* This code is licensed under the GPL 2.0 license, available at the root
* application directory.
*/
package org.geoserver.wps.remote.plugin;
import java.net.URLDecoder;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.geoserver.wps.remote.RemoteProcessClientListener;
import org.geoserver.wps.remote.RemoteProcessFactoryListener;
import org.geoserver.wps.remote.RemoteServiceDescriptor;
import org.geotools.data.Parameter;
import org.geotools.feature.NameImpl;
import org.geotools.text.Text;
import org.geotools.util.logging.Logging;
import org.jivesoftware.smack.packet.Message;
import org.jivesoftware.smack.packet.Packet;
import org.opengis.feature.type.Name;
import org.opengis.util.InternationalString;
import net.sf.json.JSONArray;
import net.sf.json.JSONObject;
import net.sf.json.JSONSerializer;
/**
* Listens for "REGISTER" messages from XMPP service channels and takes action accordingly.
*
* @author Alessio Fabiani, GeoSolutions
*
*/
public class XMPPRegisterMessage implements XMPPMessage {
/** The LOGGER */
public static final Logger LOGGER = Logging.getLogger(XMPPMessage.class.getPackage().getName());
@Override
public boolean canHandle(Map<String, String> signalArgs) {
if (signalArgs != null && signalArgs.get("topic") != null)
return signalArgs.get("topic").equals("register");
return false;
}
@Override
public void handleSignal(XMPPClient xmppClient, Packet packet, Message message,
Map<String, String> signalArgs) {
final String serviceName[] = signalArgs.get("service").split("\\.");
if (serviceName.length <= 1)
return;
final Name name = new NameImpl(serviceName[0], serviceName[1]);
try {
String serviceDescriptorString = URLDecoder.decode(signalArgs.get("message"), "UTF-8");
JSONObject serviceDescriptorJSON = (JSONObject) JSONSerializer
.toJSON(serviceDescriptorString);
final String title = (String) serviceDescriptorJSON.get("title");
final String description = (String) serviceDescriptorJSON.get("description");
JSONArray input = (JSONArray) serviceDescriptorJSON.get("input");
JSONArray output = (JSONArray) serviceDescriptorJSON.get("output");
// INPUTS
Map<String, Parameter<?>> inputs = new HashMap<String, Parameter<?>>();
if (input != null) {
for (int ii = 0; ii < input.size(); ii++) {
final Object obj = input.get(ii);
if (obj instanceof JSONArray) {
final JSONArray jsonArray = (JSONArray) obj;
final String paramName = (String) jsonArray.get(0);
String ss = ((String) jsonArray.get(1));
ss = ss.substring(1, ss.length() - 1);
final JSONObject paramType = (JSONObject) JSONSerializer.toJSON(ss);
final String className = (String) paramType.get("type");
final ParameterTemplate paramTemplate = xmppClient.convertToJavaClass(
className, XMPPClient.class.getClassLoader(),
paramType.get("default"));
final InternationalString inputTitle = (paramType.get("title") != null
&& paramType.get("title") instanceof String
? Text.text((String) paramType.get("title"))
: Text.text(paramName));
final InternationalString inputDescription = (paramType
.get("description") != null
&& paramType.get("description") instanceof String
? Text.text((String) paramType.get("description"))
: Text.text(paramName));
inputs.put(paramName,
new Parameter(paramName, paramTemplate.getClazz(), inputTitle,
inputDescription,
paramType.get("min") == null
|| (Integer) paramType.get("min") > 0,
paramType.get("min") != null ? (Integer) paramType.get("min") : 1,
paramType.get("max") != null ? (Integer) paramType.get("max") : -1,
paramTemplate.getDefaultValue(), null));
}
}
}
// OUTPUTS
Map<String, Parameter<?>> outputs = new HashMap<String, Parameter<?>>();
if (output != null) {
for (int oo = 0; oo < output.size(); oo++) {
Object obj = output.get(oo);
if (obj instanceof JSONArray) {
final JSONArray jsonArray = (JSONArray) obj;
final String paramName = (String) jsonArray.get(0);
String ss = ((String) jsonArray.get(1));
ss = ss.substring(1, ss.length() - 1);
final JSONObject paramType = (JSONObject) JSONSerializer.toJSON(ss);
final String className = (String) paramType.get("type");
ParameterTemplate paramTemplate = xmppClient.convertToJavaClass(className,
XMPPClient.class.getClassLoader(), paramType.get("default"));
final String choosenOutputMimeTypeParam = paramName + "OutputMimeType";
if (paramTemplate.getMeta() != null
&& paramTemplate.getMeta().get("mimeTypes") != null
&& (paramType.get("output_mime_type") instanceof String)) {
paramTemplate.getMeta().put("chosenMimeType",
choosenOutputMimeTypeParam);
final Parameter outputChoosenMimeTypeParam = new Parameter(
choosenOutputMimeTypeParam, String.class, Text.text(""),
Text.text(""), false, 0, 1,
paramType.get("output_mime_type").toString(), null);
outputs.put(choosenOutputMimeTypeParam, outputChoosenMimeTypeParam);
}
final InternationalString outputTitle = (paramType.get("title") != null
&& paramType.get("title") instanceof String
? Text.text((String) paramType.get("title"))
: Text.text(paramName));
final InternationalString outputDescription = (paramType
.get("description") != null
&& paramType.get("description") instanceof String
? Text.text((String) paramType.get("description"))
: Text.text(paramName));
outputs.put(paramName,
new Parameter(paramName, paramTemplate.getClazz(), outputTitle,
outputDescription,
paramType.get("min") == null
|| (Integer) paramType.get("min") > 0,
paramType.get("min") != null ? (Integer) paramType.get("min") : 1,
paramType.get("max") != null ? (Integer) paramType.get("max") : 0,
paramTemplate.getDefaultValue(), paramTemplate.getMeta()));
}
}
}
// NOTIFY LISTENERS
Map<String, Object> metadata = new HashMap<String, Object>();
metadata.put("serviceJID", packet.getFrom());
for (RemoteProcessFactoryListener listener : xmppClient.getRemoteFactoryListeners()) {
listener.registerProcess(new RemoteServiceDescriptor(name, title, description,
inputs, outputs, metadata));
}
} catch (Exception e) {
LOGGER.log(Level.SEVERE, e.getMessage(), e);
// NOTIFY LISTENERS
final Set<RemoteProcessClientListener> remoteClientListeners = xmppClient
.getRemoteClientListeners();
synchronized (remoteClientListeners) {
for (RemoteProcessClientListener listener : remoteClientListeners) {
Map<String, Object> metadata = new HashMap<String, Object>();
metadata.put("serviceJID", packet.getFrom());
final String pID = (signalArgs != null ? signalArgs.get("id") : null);
listener.exceptionOccurred(pID, e, metadata);
}
}
}
}
}