/** * Helios, OpenSource Monitoring * Brought to you by the Helios Development Group * * Copyright 2007, Helios Development Group and individual contributors * as indicated by the @author tags. See the copyright.txt file in the * distribution for a full listing of individual contributors. * * This is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation; either version 2.1 of * the License, or (at your option) any later version. * * This software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this software; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA, or see the FSF site: http://www.fsf.org. * */ package org.helios.apmrouter.dataservice.json; import java.util.Collections; import java.util.HashMap; import java.util.Map; import java.util.TreeMap; import org.helios.apmrouter.util.StringHelper; import org.jboss.netty.channel.Channel; import org.jboss.netty.channel.Channels; import org.jboss.netty.channel.DownstreamMessageEvent; import org.json.JSONException; import org.json.JSONObject; /** * <p>Title: JsonRequest</p> * <p>Description: Encapsulates the decoded standard parts of a JSON data service request.</p> * <p>Company: Helios Development Group LLC</p> * @author Whitehead (nwhitehead AT heliosdev DOT org) * <p><code>org.helios.apmrouter.dataservice.json.AbstractJSONDataService.JsonRequest</code></p> */ public class JsonRequest { /** the type code of the request */ public final String tCode; /** The client supplied request ID */ public final long rid; /** The requested service name */ public final String serviceName; /** The requested op name */ public final String opName; /** The original request, in case there is other stuff in there that the data service needs */ public final JSONObject request; /** The channel that the request came in on. May sometimes be null */ private final Channel channel; /** The arguments supplied to the op */ public final Map<Object, Object> arguments = new TreeMap<Object, Object>(); /** * Creates a new JsonRequest * @param channel The channel that the request came in on. Ignored if null * @param tCode the type code of the request * @param rid The client supplied request ID * @param serviceName The service name requested * @param opName The op name requested * @param request The original request */ public JsonRequest(Channel channel, String tCode, long rid, String serviceName, String opName, JSONObject request) { this.channel = channel; this.tCode = tCode; this.rid = rid; this.serviceName = serviceName; this.opName = opName; this.request = request; } /** * Returns an error {@link JsonResponse} for this request * @param message The error message to send * @return an error {@link JsonResponse} for this request */ public JsonResponse error(CharSequence message) { return error(message, null); } /** * Returns an error {@link JsonResponse} for this request * @param message The error message to send * @param t The exception to render in the error message. Ignored if null. * @return an error {@link JsonResponse} for this request */ public JsonResponse error(CharSequence message, Throwable t) { JsonResponse response = new JsonResponse(rid, JsonResponse.RESP_TYPE_ERR); Map<String, String> map = new HashMap<String, String>(t==null ? 1 : 2); map.put("err", message.toString()); if(t!=null) { map.put("ex", StringHelper.formatStackTrace(t)); } response.setContent(map); return response; } /** * Returns a {@link JsonResponse} for this request * @return a {@link JsonResponse} for this request */ public JsonResponse response() { return new JsonResponse(rid, JsonResponse.RESP_TYPE_RESP); } /** * Returns a subscription send {@link JsonResponse} for the subscription issued by this request * @param subKey subKey The unique subscription identifier * @return a subscription send {@link JsonResponse} for the subscription issued by this request */ public JsonResponse subResponse(String subKey) { return new JsonSubConfirm(rid, JsonResponse.RESP_TYPE_SUB, subKey); } /** * Returns a subscription confirmation {@link JsonResponse} for the subscription initiation started by this request * @param subKey The unique subscription identifier * @return a subscription confirmation {@link JsonResponse} for the subscription initiation started by this request */ public JsonResponse subConfirm(String subKey) { return new JsonSubConfirm(rid, JsonResponse.RESP_TYPE_SUB_STARTED, subKey); } /** * Returns a subscription cancellation {@link JsonResponse} for the cancelled subscription. * @param subKey The unique subscription identifier * @return a subscription cancellation {@link JsonResponse} for the cancelled subscription. */ public JsonResponse subCancel(String subKey) { return new JsonSubConfirm(rid, JsonResponse.RESP_TYPE_SUB_STOPPED, subKey); } /** * Adds an op argument to the map * @param key The argument key (if the args was an array, this is the sequence, if it was a map, this is the key) * @param value The argument value */ public void addArg(Object key, Object value) { arguments.put(key, value); } /** * Returns the named argument from the argument map * @param key The argument key * @param defaultValue The default value to return if the key does not resolve * @return the value for the passed key */ public <T> T getArgument(String key, T defaultValue) { Object value = arguments.get(key); if(Map.class.isAssignableFrom(defaultValue.getClass()) && value instanceof JSONObject) { JSONObject jsonMap = (JSONObject)value; Map<String, Object> map = new HashMap<String, Object>(); try { for(String mapKey: JSONObject.getNames(jsonMap)) { map.put(mapKey, jsonMap.get(mapKey)); } } catch (JSONException ex) { throw new RuntimeException(ex); } return (T)map; } if(value==null || !defaultValue.getClass().isInstance(value)) { return defaultValue; } return (T)value; } /** * Returns an argument as a string * @param key The argument key * @return The string value of the argument or null if no value was found */ public String getArgument(String key) { Object value = arguments.get(key); if(value!=null) return value.toString().trim(); return null; } /** * Returns the named argument from the argument map returning null if not found * @param key The argument key * @param type The expected type of the value * @return the value for the passed key */ public <T> T getArgumentOrNull(String key, Class<T> type) { Object value = arguments.get(key); if(value==null) { return null; } return (T)value; } /** * Returns the indexed argument from the argument array * @param index The argument index * @param defaultValue The default value to return if the key does not resolve * @return the value for the passed index */ public <T> T getArgument(int index, T defaultValue) { Object value = arguments.get(index); if(value==null || !defaultValue.getClass().isInstance(value)) { return defaultValue; } return (T)value; } /** * Returns the channel that the request came in on or null if this is a synthetic request. * @return the channel */ public Channel getChannel() { return channel; } /** * {@inheritDoc} * @see java.lang.Object#toString() */ @Override public String toString() { return String .format("JsonRequest [\\n\\ttCode:%s, rid:%s, serviceName:%s, opName:%s, request:%s, arguments:%s]", tCode, rid, serviceName, opName, request, arguments); } }