// ---------------------------------------------------------------------------
// jWebSocket - JSON Token Processor
// Copyright (c) 2010 jWebSocket.org, Alexander Schulze, Innotrade GmbH
// ---------------------------------------------------------------------------
// This program 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 3 of the License, or (at your
// option) any later version.
// This program 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 program; if not, see <http://www.gnu.org/licenses/lgpl.html>.
// ---------------------------------------------------------------------------
package org.jwebsocket.packetProcessors;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import javolution.util.FastList;
import javolution.util.FastMap;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import org.json.JSONTokener;
import org.jwebsocket.api.WebSocketPacket;
import org.jwebsocket.kit.RawPacket;
import org.jwebsocket.token.MapToken;
import org.jwebsocket.token.Token;
/**
* converts JSON formatted data packets into tokens and vice versa.
*
* @author Alexander Schulze, Roderick Baier (improvements regarding JSON
* array), Quentin Ambard (add support for Map and List for
* PacketToToken and tokeToPacket).
*/
@SuppressWarnings("rawtypes")
public class JSONProcessor {
/**
* @param aObject
* @return an object which is the JSON representation of aObject
*/
@SuppressWarnings("unchecked")
private static Object convertJsonToJavaObject(Object aObject) {
if (aObject instanceof JSONArray) {
return jsonArrayToList((JSONArray) aObject);
} else if (aObject instanceof JSONObject) {
return jsonObjectToMap((JSONObject) aObject);
} else {
return aObject;
}
}
/**
* Quentin: Recursivly convert a JSONArray to a List of List, Map or Object.
* (also convert all the JSONObject to Map) Example: jsonArrayToList(
* JSONArray [[1,2,3],{"value": "a"}]) will retour a List{{1,2,3},{"value" =>
* "b"}}
*
* @param aJsonArray
* @return the list
*/
@SuppressWarnings("unchecked")
public static List jsonArrayToList(JSONArray aJsonArray) {
List lList = new FastList();
for (int i = 0; i < aJsonArray.length(); i++) {
try {
Object lSubObject = aJsonArray.get(i);
lList.add(convertJsonToJavaObject(lSubObject));
} catch (JSONException e) {
// Sould never happen: aJsonArray.get(i)
// will always exists
}
}
return lList;
}
/**
* Quentin: Recursivly convert a JSONObject to a Map of List, Map or Object.
* (also convert all the JSONArray to List)
*
* @param aJsonArray
* @return the list
*/
@SuppressWarnings("unchecked")
public static Map jsonObjectToMap(JSONObject aJsonObject) {
FastMap lFastMap = new FastMap();
Iterator iterator = aJsonObject.keys();
while (iterator.hasNext()) {
try {
Object aKey = iterator.next();
Object aValue = convertJsonToJavaObject(aJsonObject.get(String
.valueOf(aKey)));
lFastMap.put(aKey, aValue);
} catch (JSONException e) {
// Sould never happen:
// aJsonObject.get(String.valueOf(aKey))
// will always exists
}
}
return lFastMap;
}
/**
* Convert a json string to a token. If the json string isn't a valide one, return an empty token
* Note that if you need a more generic conversion (other subprotocol than json), you may also use the following:
* Token lToken = TokenServer.packetToToken(aConnector, new RawPacket(aJsonString))
* Depending of the SubProtocol of aConnector, the token will be automatically created
* (if the SubProtocol is WS_SUBPROT_JSON, the conversion will be done internally using this method)
* @param aJsonString a json string
* @return the token corresponding to the json string, or an empty token
*/
public static Token jsonStringToToken(String aJsonString) {
Token lToken = new MapToken();
try {
String lStr = aJsonString;
JSONTokener lJT = new JSONTokener(lStr);
JSONObject lJO = new JSONObject(lJT);
for (Iterator lIterator = lJO.keys(); lIterator.hasNext();) {
String lKey = (String) lIterator.next();
Object lValue = lJO.get(lKey);
lToken.setValidated(lKey, convertJsonToJavaObject(lValue));
}
} catch (Exception ex) {
// TODO: process exception
// log.error(ex.getClass().getSimpleName() + ": " +
// ex.getMessage());
}
return lToken;
}
/**
* converts a JSON formatted data packet into a token.
*
* @param aDataPacket
* @return
*/
public static Token packetToToken(WebSocketPacket aDataPacket) {
Token lToken = new MapToken();
try {
String lStr = aDataPacket.getString("UTF-8");
return jsonStringToToken(lStr);
} catch (Exception ex) {
// // TODO: process exception
// log.error(ex.getClass().getSimpleName() + ": " +
// ex.getMessage());
}
return lToken;
}
public static WebSocketPacket tokenToPacket(Token token) {
WebSocketPacket packet = null;
try {
JSONObject lJO = tokenToJSON(token);
String data = lJO.toString();
packet = new RawPacket(data, "UTF-8");
} catch (Exception ex) {
// TODO: process exception
// log.error(ex.getClass().getSimpleName() + ": " +
// ex.getMessage());
}
return packet;
}
/**
* transform a list to a JSONArray
* @param aList
* @return a JSONArray which represents aList
* @throws JSONException
*/
public static JSONArray listToJsonArray(List aList) throws JSONException {
JSONArray lArray = new JSONArray();
for (Object item : aList) {
lArray.put(convertObjectToJson(item));
}
return lArray;
}
/**
* transform a list of objects to a JSONArray
* @param aObjectList
* @return a JSONArray which represents aObjectList
* @throws JSONException
*/
public static JSONArray objectListToJsonArray(Object[] aObjectList)
throws JSONException {
JSONArray lArray = new JSONArray();
for (int lIdx = 0; lIdx < aObjectList.length; lIdx++) {
Object lObj = aObjectList[lIdx];
lArray.put(convertObjectToJson(lObj));
}
return lArray;
}
/**
* transform a map to a JSONObject
* @param aMap
* @return a JSONObject which represents aMap. All the keys values are passed
* as String using the toString method of the key.
* @throws JSONException
*/
public static JSONObject mapToJsonObject(Map<?, ?> aMap)
throws JSONException {
JSONObject lObject = new JSONObject();
for (Entry<?, ?> lEntry : aMap.entrySet()) {
String lKey = lEntry.getKey().toString();
Object lValue = convertObjectToJson(lEntry.getValue());
lObject.put(lKey, lValue);
}
return lObject;
}
/**
* transform an object to another JSON object (match all possibilities)
* @param aObject
* @return an Object which represents aObject (looks for List, Token and Maps)
* @throws JSONException
*/
public static Object convertObjectToJson(Object aObject)
throws JSONException {
if (aObject instanceof List) {
return listToJsonArray((List) aObject);
} else if (aObject instanceof Token) {
return tokenToJSON((Token) aObject);
} else if (aObject instanceof Object[]) {
return objectListToJsonArray((Object[]) aObject);
} else if (aObject instanceof Map) {
return mapToJsonObject((Map<?, ?>) aObject);
} else {
return aObject;
}
}
/**
* transform a token to a json object
* @param aToken
* @return a JSONObject which represents aToken (looks for List, Token and
* Maps)
* @throws JSONException
*/
public static JSONObject tokenToJSON(Token aToken) throws JSONException {
JSONObject lJSO = new JSONObject();
Iterator<String> iterator = aToken.getKeyIterator();
while (iterator.hasNext()) {
String key = iterator.next();
Object value = aToken.getObject(key);
lJSO.put(key, convertObjectToJson(value));
}
return lJSO;
}
}