001    /*
002     * Sonar, open source software quality management tool.
003     * Copyright (C) 2009 SonarSource SA
004     * mailto:contact AT sonarsource DOT com
005     *
006     * Sonar is free software; you can redistribute it and/or
007     * modify it under the terms of the GNU Lesser General Public
008     * License as published by the Free Software Foundation; either
009     * version 3 of the License, or (at your option) any later version.
010     *
011     * Sonar is distributed in the hope that it will be useful,
012     * but WITHOUT ANY WARRANTY; without even the implied warranty of
013     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
014     * Lesser General Public License for more details.
015     *
016     * You should have received a copy of the GNU Lesser General Public
017     * License along with Sonar; if not, write to the Free Software
018     * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02
019     */
020    package org.sonar.gwt;
021    
022    import com.google.gwt.core.client.JavaScriptException;
023    import com.google.gwt.core.client.JavaScriptObject;
024    import com.google.gwt.http.client.URL;
025    import com.google.gwt.i18n.client.DateTimeFormat;
026    import com.google.gwt.json.client.*;
027    
028    import java.util.Date;
029    
030    public final class JsonUtils {
031      private static int requestId = 0;
032    
033      private JsonUtils() {
034        // only static methods
035      }
036    
037      public interface JSONHandler {
038        void onResponse(JavaScriptObject obj);
039        void onTimeout();
040        void onError(int errorCode, String errorMessage);
041      }
042    
043      public static void requestJson(String url, JSONHandler handler) {
044        if (!url.endsWith("&") && !url.endsWith("?")) {
045          url += "&";
046        }
047        if (!url.contains("format=json")) {
048          url += "format=json&";
049        }
050        if (!url.contains("callback=")) {
051          //IMPORTANT : the url should ended with ?callback= or &callback= for JSONP calls
052          url += "callback=";
053        }
054        makeJSONRequest(requestId++, URL.encode(url), handler);
055      }
056    
057      public static native void makeJSONRequest(int requestId, String url, JSONHandler handler) /*-{
058          var callback = "callback" + requestId;
059    
060          // create SCRIPT tag, and set SRC attribute equal to JSON feed URL + callback function name
061          var script = document.createElement("script");
062          script.setAttribute("src", url+callback);
063          script.setAttribute("type", "text/javascript");
064    
065          window[callback] = function(jsonObj) {
066            @org.sonar.gwt.JsonUtils::dispatchJSON(Lcom/google/gwt/core/client/JavaScriptObject;Lorg/sonar/gwt/JsonUtils$JSONHandler;)(jsonObj, handler);
067            window[callback + "done"] = true;
068          }
069    
070          setTimeout(function() {
071            if (!window[callback + "done"]) {
072              handler.@org.sonar.gwt.JsonUtils.JSONHandler::onTimeout();
073            }
074    
075            // cleanup
076            document.body.removeChild(script);
077            if (window[callback]) {
078              delete window[callback];
079            }
080            if (window[callback + "done"]) {
081              delete window[callback + "done"];
082            }
083          }, 120000);
084    
085          document.body.appendChild(script);
086        }-*/;
087    
088      public static void dispatchJSON(JavaScriptObject jsonObj, JSONHandler handler) {
089        JSONObject obj = new JSONObject(jsonObj);
090        if (obj.isObject() != null) {
091          if (obj.containsKey("err_code")) {
092            handler.onError(new Double(obj.get("err_code").isNumber().doubleValue()).intValue(),
093                obj.get("err_msg").isString().stringValue());
094            return;
095          }
096        }
097        handler.onResponse(jsonObj);
098      }
099    
100      public static String getString(JSONObject json, String field) {
101        JSONValue jsonValue;
102        JSONString jsonString;
103        if ((jsonValue = json.get(field)) == null) {
104          return null;
105        }
106        if ((jsonString = jsonValue.isString()) == null) {
107          JSONNumber jsonNumber = jsonValue.isNumber();
108          return jsonNumber != null ? jsonNumber.toString() : null;
109        }
110        return jsonString.stringValue();
111      }
112    
113      public static Date getDate(JSONObject json, String field) {
114        DateTimeFormat frmt = DateTimeFormat.getFormat("yyyy-MM-dd'T'HH:mm:ssZ");
115        String date = getString(json, field);
116        if (date!=null && date.endsWith("Z") && date.length()>2) {
117          // see SONAR-1182
118          date = date.substring(0, date.length()-2) + "+00:00";
119        }
120        return frmt.parse(date);
121      }
122    
123      public static Boolean getBoolean(JSONObject json, String field) {
124        JSONValue jsonValue;
125        JSONBoolean jsonBoolean;
126        if ((jsonValue = json.get(field)) == null) {
127          return null;
128        }
129        if ((jsonBoolean = jsonValue.isBoolean()) == null) {
130          return null;
131        }
132        return jsonBoolean.booleanValue();
133      }
134    
135      public static Double getDouble(JSONObject json, String field) {
136        JSONValue jsonValue;
137        JSONNumber jsonNumber;
138        if ((jsonValue = json.get(field)) == null) {
139          return null;
140        }
141        if ((jsonNumber = jsonValue.isNumber()) == null) {
142          return null;
143        }
144        return jsonNumber.doubleValue();
145      }
146    
147      public static Integer getInteger(JSONObject json, String field) {
148        final Double d = getDouble(json, field);
149        if (d != null) {
150          return d.intValue();
151        }
152        return null;
153      }
154    
155      public static JSONObject getArray(JSONValue json, int i) {
156        if (json instanceof JSONArray) {
157          return ((JSONArray) json).get(i).isObject();
158        }
159        if (json instanceof JSONObject) {
160          return ((JSONObject) json).get(Integer.toString(i)).isObject();
161        }
162        throw new JavaScriptException("Not implemented");
163      }
164    
165      public static int getArraySize(JSONValue array) {
166        if (array instanceof JSONArray) {
167          return ((JSONArray) array).size();
168        }
169        if (array instanceof JSONObject) {
170          return ((JSONObject) array).size();
171        }
172        throw new JavaScriptException("Not implemented");
173      }
174    
175    }
176