Commit f748670d96e0d63028fe8fb7f6b1d53b899ae154

Authored by 赵康
1 parent c249b9af01
Exists in master

branch release

Showing 45 changed files with 0 additions and 4701 deletions Inline Diff

TraceSDK/.classpath
1 <?xml version="1.0" encoding="UTF-8"?> File was deleted
2 <classpath>
3 <classpathentry kind="src" path="src"/>
4 <classpathentry kind="src" path="gen"/>
5 <classpathentry kind="con" path="com.android.ide.eclipse.adt.ANDROID_FRAMEWORK"/>
6 <classpathentry exported="true" kind="con" path="com.android.ide.eclipse.adt.LIBRARIES"/>
7 <classpathentry exported="true" kind="con" path="com.android.ide.eclipse.adt.DEPENDENCIES"/>
8 <classpathentry kind="output" path="bin/classes"/>
9 </classpath>
10 1 <?xml version="1.0" encoding="UTF-8"?>
TraceSDK/.fatjar
1 #Fat Jar Configuration File File was deleted
2 #Wed Sep 03 15:36:15 CST 2014
3 onejar.license.required=true
4 manifest.classpath=
5 manifest.removesigners=true
6 onejar.checkbox=false
7 jarname=TraceSDK.jar
8 manifest.mergeall=true
9 manifest.mainclass=
10 manifest.file=<createnew>
11 jarname.isextern=false
12 onejar.expand=
13 excludes=<po|TraceSDK>~com/~mobithink/~tracksdk/;<jar|android-support-v4.jar>
14 includes=
15 1 #Fat Jar Configuration File
TraceSDK/.project
1 <?xml version="1.0" encoding="UTF-8"?> File was deleted
2 <projectDescription>
3 <name>TraceSDK</name>
4 <comment></comment>
5 <projects>
6 </projects>
7 <buildSpec>
8 <buildCommand>
9 <name>com.android.ide.eclipse.adt.ResourceManagerBuilder</name>
10 <arguments>
11 </arguments>
12 </buildCommand>
13 <buildCommand>
14 <name>com.android.ide.eclipse.adt.PreCompilerBuilder</name>
15 <arguments>
16 </arguments>
17 </buildCommand>
18 <buildCommand>
19 <name>org.eclipse.jdt.core.javabuilder</name>
20 <arguments>
21 </arguments>
22 </buildCommand>
23 <buildCommand>
24 <name>com.android.ide.eclipse.adt.ApkBuilder</name>
25 <arguments>
26 </arguments>
27 </buildCommand>
28 </buildSpec>
29 <natures>
30 <nature>com.android.ide.eclipse.adt.AndroidNature</nature>
31 <nature>org.eclipse.jdt.core.javanature</nature>
32 </natures>
33 </projectDescription>
34 1 <?xml version="1.0" encoding="UTF-8"?>
TraceSDK/AndroidManifest.xml
1 <manifest xmlns:android="http://schemas.android.com/apk/res/android" File was deleted
2 package="com.mobithink.tracksdk"
3 android:versionCode="1"
4 android:versionName="1.0" >
5
6 <uses-sdk
7 android:minSdkVersion="8"
8 android:targetSdkVersion="19" />
9
10 <application
11 android:allowBackup="true"
12 android:icon="@drawable/ic_launcher"
13 android:label="@string/app_name"
14 android:theme="@style/AppTheme" >
15 </application>
16
17 </manifest>
18 1 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
TraceSDK/libs/android-support-v4.jar
No preview for this file type
TraceSDK/proguard-project.txt
1 # To enable ProGuard in your project, edit project.properties File was deleted
2 # to define the proguard.config property as described in that file.
3 #
4 # Add project specific ProGuard rules here.
5 # By default, the flags in this file are appended to flags specified
6 # in ${sdk.dir}/tools/proguard/proguard-android.txt
7 # You can edit the include path and order by changing the ProGuard
8 # include property in project.properties.
9 #
10 # For more details, see
11 # http://developer.android.com/guide/developing/tools/proguard.html
12
13 # Add any project specific keep options here:
14
15 # If your project uses WebView with JS, uncomment the following
16 # and specify the fully qualified class name to the JavaScript interface
17 # class:
18 #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
19 # public *;
20 #}
21 1 # To enable ProGuard in your project, edit project.properties
TraceSDK/project.properties
1 # This file is automatically generated by Android Tools. File was deleted
2 # Do not modify this file -- YOUR CHANGES WILL BE ERASED!
3 #
4 # This file must be checked in Version Control Systems.
5 #
6 # To customize properties used by the Ant build system edit
7 # "ant.properties", and override values to adapt the script to your
8 # project structure.
9 #
10 # To enable ProGuard to shrink and obfuscate your code, uncomment this (available properties: sdk.dir, user.home):
11 #proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt
12
13 # Project target.
14 target=android-19
15 android.library=true
16 1 # This file is automatically generated by Android Tools.
TraceSDK/res/drawable-hdpi/ic_launcher.png

9.18 KB

TraceSDK/res/drawable-mdpi/ic_launcher.png

5.11 KB

TraceSDK/res/drawable-xhdpi/ic_launcher.png

14 KB

TraceSDK/res/values-v11/styles.xml
1 <resources> File was deleted
2
3 <!--
4 Base application theme for API 11+. This theme completely replaces
5 AppBaseTheme from res/values/styles.xml on API 11+ devices.
6 -->
7 <style name="AppBaseTheme" parent="android:Theme.Holo.Light">
8 <!-- API 11 theme customizations can go here. -->
9 </style>
10
11 </resources>
12 1 <resources>
TraceSDK/res/values-v14/styles.xml
1 <resources> File was deleted
2
3 <!--
4 Base application theme for API 14+. This theme completely replaces
5 AppBaseTheme from BOTH res/values/styles.xml and
6 res/values-v11/styles.xml on API 14+ devices.
7 -->
8 <style name="AppBaseTheme" parent="android:Theme.Holo.Light.DarkActionBar">
9 <!-- API 14 theme customizations can go here. -->
10 </style>
11
12 </resources>
13 1 <resources>
TraceSDK/res/values/strings.xml
1 <resources> File was deleted
2
3 <string name="app_name">TraceSDK</string>
4
5 </resources>
6 1 <resources>
TraceSDK/res/values/styles.xml
1 <resources> File was deleted
2
3 <!--
4 Base application theme, dependent on API level. This theme is replaced
5 by AppBaseTheme from res/values-vXX/styles.xml on newer devices.
6 -->
7 <style name="AppBaseTheme" parent="android:Theme.Light">
8 <!--
9 Theme customizations available in newer API levels can go in
10 res/values-vXX/styles.xml, while customizations related to
11 backward-compatibility can go here.
12 -->
13 </style>
14
15 <!-- Application theme. -->
16 <style name="AppTheme" parent="AppBaseTheme">
17 <!-- All customizations that are NOT specific to a particular API-level can go here. -->
18 </style>
19
20 </resources>
21 1 <resources>
TraceSDK/src/com/mobithink/tracesdk/Conf.java
1 package com.mobithink.tracesdk; File was deleted
2
3 public class Conf {
4
5 public final class App {
6 public static final int VERSION = 1;
7
8 public static final String API_SERVER = "http://dt.mtafftracking.com/";
9 }
10
11 public static class Env {
12 public static boolean LOG_ON = true;
13 }
14 }
15 1 package com.mobithink.tracesdk;
TraceSDK/src/com/mobithink/tracesdk/TraceAgent.java
1 package com.mobithink.tracesdk; File was deleted
2
3 import java.util.List;
4 import java.util.Map;
5
6 import org.apache.http.HttpStatus;
7
8 import android.content.Context;
9 import android.text.TextUtils;
10 import android.util.Log;
11
12 import com.mobithink.tracesdk.event.EventDBUtil;
13 import com.mobithink.tracesdk.event.Event;
14 import com.mobithink.tracesdk.json.JSONArray;
15 import com.mobithink.tracesdk.json.JSONException;
16 import com.mobithink.tracesdk.json.JSONObject;
17 import com.mobithink.tracesdk.rest.client.DefaultRESTClient;
18 import com.mobithink.tracesdk.rest.client.RequestEntityImplJSON;
19 import com.mobithink.tracesdk.rest.client.Response;
20 import com.mobithink.tracesdk.utils.LogUtil;
21 import com.mobithink.tracesdk.utils.Util;
22
23 public class TraceAgent {
24
25 private static final String TAG = "TraceAgent";
26
27 private static long sessionPauseTime = 0L;
28
29 private static String ofId;
30
31 public static void active(final Context context, final String offerId) {
32 ofId = offerId;
33 new Thread() {
34
35 @Override
36 public void run() {
37 DefaultRESTClient client = DefaultRESTClient.create();
38 client.path("conversion/").query("os", "android").query("version", android.os.Build.VERSION.RELEASE).query("manufacturer", android.os.Build.MANUFACTURER)
39 .query("model", android.os.Build.MODEL).query("build", android.os.Build.VERSION.INCREMENTAL).query("imei", Util.getIMEI(context))
40 .query("device_id", Util.getAndroidId(context)).query("mac_addr", Util.getMacAddr(context)).query("sdk_version", Conf.App.VERSION)
41 .query("offer_id", offerId).query("uniq_id", Util.getUniqueId(context)).get();
42 }
43 }.start();
44 }
45
46 public static void setLogEnable(boolean enable) {
47 Conf.Env.LOG_ON = enable;
48 }
49
50 public static void onResume(final Context Act) {
51 long now = System.currentTimeMillis();
52 if (now - sessionPauseTime > 10000)
53 new Thread() {
54
55 @Override
56 public void run() {
57 List<Event> events = null;
58 int retry = 0;
59 do {
60 events = EventDBUtil.getInstance(Act).getEvents(300);
61 if (events == null || events.isEmpty())
62 break;
63 DefaultRESTClient client = DefaultRESTClient.create();
64 client.setRequestEntity(new RequestEntityImplJSON());
65 Response resp = client.path("event/index.php").query("os", "android").query("version", android.os.Build.VERSION.RELEASE)
66 .query("manufacturer", android.os.Build.MANUFACTURER).query("model", android.os.Build.MODEL).query("build", android.os.Build.VERSION.INCREMENTAL)
67 .query("imei", Util.getIMEI(Act)).query("device_id", Util.getAndroidId(Act)).query("mac_addr", Util.getMacAddr(Act))
68 .query("sdk_version", Conf.App.VERSION).query("offer_id", ofId).query("uniq_id", Util.getUniqueId(Act)).query("event", formatJson(events)).post();
69 Log.d(TAG, "resp code:" + resp.getHttpStatus());
70 if (resp != null && resp.getHttpStatus() == HttpStatus.SC_OK) {
71 EventDBUtil.getInstance(Act).clearEvent(events);
72 retry = 0;
73 } else
74 retry++;
75 } while (events != null && !events.isEmpty() && retry < 3);
76 }
77
78 }.start();
79 }
80
81 public static void onPause(Context act) {
82 sessionPauseTime = System.currentTimeMillis();
83 }
84
85 public static void onEvent(Context context, String eventId) {
86 onEvent(context, eventId, "");
87 }
88
89 public static void onEvent(Context context, String eventId, String label) {
90 Event event = new Event(eventId, label);
91 EventDBUtil dbUtil = EventDBUtil.getInstance(context.getApplicationContext());
92 boolean result = dbUtil.saveEvent(event);
93 LogUtil.i(TAG, "record event " + (result ? "success" : "error"));
94 }
95
96 public static void onEvent(Context context, String eventId, Map<String, String> parameters) {
97 if (parameters != null) {
98 Event event = new Event(eventId, "");
99 for (Map.Entry<String, String> entry : parameters.entrySet()) {
100 // obj.put(entry.getKey(), entry.getValue());
101 event.addParam(entry.getKey(), entry.getValue());
102 }
103 EventDBUtil dbUtil = EventDBUtil.getInstance(context.getApplicationContext());
104 boolean result = dbUtil.saveEvent(event);
105 LogUtil.i(TAG, "record event " + (result ? "success" : "error"));
106 }
107 }
108
109 private static JSONArray formatJson(List<Event> events) {
110 if (events != null && !events.isEmpty()) {
111 JSONArray array = new JSONArray();
112 for (Event event : events) {
113 JSONObject item = new JSONObject();
114 try {
115 item.put("type", event.getEventId());
116 item.put("time", event.getOccurtime());
117 item.put("timezone", event.getTimeZone());
118 JSONObject param = event.getParams();
119 if (!TextUtils.isEmpty(event.getLabel()))
120 param.put("def", event.getLabel());
121 item.put("data", param);
122 array.put(item);
123 } catch (JSONException e) {
124 e.printStackTrace();
125 }
126 }
127 return array;
128 }
129 return new JSONArray();
130 }
131 }
132 1 package com.mobithink.tracesdk;
TraceSDK/src/com/mobithink/tracesdk/event/Event.java
1 package com.mobithink.tracesdk.event; File was deleted
2
3 import java.util.ArrayList;
4 import java.util.Calendar;
5 import java.util.List;
6
7 import android.content.ContentValues;
8 import android.database.Cursor;
9 import android.provider.BaseColumns;
10
11 import com.mobithink.tracesdk.json.JSONException;
12 import com.mobithink.tracesdk.json.JSONObject;
13
14 public class Event implements BaseColumns {
15
16 public static final String TABLE_NAME = "mt_trace";
17
18 private long rid;
19 private String eventId;
20 private JSONObject params;
21 private String label = "";
22 private long occurtime;
23 private String timeZone;
24 private int status;
25
26 private Event() {
27 }
28
29 public Event(String eventId, String label) {
30 this.eventId = eventId;
31 this.label = label;
32 occurtime = System.currentTimeMillis();
33 timeZone = Calendar.getInstance().getTimeZone().getID();
34 params = new JSONObject();
35 }
36
37 public long getRid() {
38 return rid;
39 }
40
41 public void setRid(long rid) {
42 this.rid = rid;
43 }
44
45 public String getEventId() {
46 return eventId;
47 }
48
49 public String getLabel() {
50 return label;
51 }
52
53 public JSONObject getParams() {
54 return params;
55 }
56
57 // public void setParams(JSONObject params) {
58 // this.params = params;
59 // }
60
61 public String getTimeZone() {
62 return timeZone;
63 }
64
65 public long getOccurtime() {
66 return occurtime;
67 }
68
69 public int getStatus() {
70 return status;
71 }
72
73 public void setStatus(int status) {
74 this.status = status;
75 }
76
77 public void addParam(String key, String val) {
78 try {
79 params.put(key, val);
80 } catch (JSONException e) {
81 e.printStackTrace();
82 }
83 }
84
85 public static String COLUMN_EVENT_ID = "event_id";
86 public static String COLUMN_LABEL = "label";
87 public static String COLUMN_PARAMS = "param_map";
88 public static String COLUMN_OCCURTIME = "occurtime";
89 public static String COLUMN_TIME_ZONE = "time_zone";
90 public static String COLUMN_STATUS = "status";
91
92 public static final String[] COLUMNS = { _ID, COLUMN_EVENT_ID, COLUMN_LABEL, COLUMN_OCCURTIME, COLUMN_PARAMS, COLUMN_TIME_ZONE, COLUMN_STATUS };
93
94 public static final String CREATE_TABLE = "CREATE TABLE IF NOT EXISTS " + TABLE_NAME + "(" + _ID + " INTEGER PRIMARY KEY AUTOINCREMENT,"//
95 + COLUMN_EVENT_ID + " TEXT,"//
96 + COLUMN_LABEL + " TEXT,"//
97 + COLUMN_OCCURTIME + " INTEGER,"//
98 + COLUMN_TIME_ZONE + " TEXT,"// 时区
99 + COLUMN_PARAMS + " TEXT,"//
100 + COLUMN_STATUS + " INTEGER"//
101 + ");";
102
103 public ContentValues toContentValues() {
104 ContentValues values = new ContentValues();
105 values.put(COLUMN_EVENT_ID, eventId);
106 values.put(COLUMN_LABEL, label);
107 values.put(COLUMN_OCCURTIME, occurtime);
108 values.put(COLUMN_STATUS, status);
109 values.put(COLUMN_TIME_ZONE, timeZone);
110 // if (params != null)
111 values.put(COLUMN_PARAMS, params.toString());
112 return values;
113 }
114
115 public static List<Event> parseCursor(Cursor cursor) {
116 if (cursor == null)
117 return null;
118 List<Event> ret = new ArrayList<Event>();
119 while (cursor.moveToNext()) {
120 Event event = new Event();
121 event.rid = cursor.getLong(cursor.getColumnIndexOrThrow(_ID));
122 event.eventId = cursor.getString(cursor.getColumnIndexOrThrow(COLUMN_EVENT_ID));
123 event.label = cursor.getString(cursor.getColumnIndexOrThrow(COLUMN_LABEL));
124 event.occurtime = cursor.getLong(cursor.getColumnIndexOrThrow(COLUMN_OCCURTIME));
125 event.timeZone = cursor.getString(cursor.getColumnIndexOrThrow(COLUMN_TIME_ZONE));
126 event.status = cursor.getInt(cursor.getColumnIndexOrThrow(COLUMN_STATUS));
127 String paramStr = cursor.getString(cursor.getColumnIndexOrThrow(COLUMN_PARAMS));
128 try {
129 event.params = new JSONObject(paramStr);
130 } catch (JSONException e) {
131 e.printStackTrace();
132 }
133 ret.add(event);
134 }
135 return ret;
136 }
137 }
138 1 package com.mobithink.tracesdk.event;
TraceSDK/src/com/mobithink/tracesdk/event/EventDBUtil.java
1 package com.mobithink.tracesdk.event; File was deleted
2
3 import java.util.List;
4
5 import android.content.Context;
6 import android.database.Cursor;
7 import android.database.sqlite.SQLiteDatabase;
8 import android.database.sqlite.SQLiteOpenHelper;
9
10 public class EventDBUtil {
11
12 private static final int version = 1;
13
14 private static final String DB_NAME = "mt_trace.db";
15
16 private static EventDBUtil instance = null;
17
18 private DBHelper helper;
19
20 private EventDBUtil(Context context) {
21 helper = new DBHelper(context);
22 }
23
24 public static EventDBUtil getInstance(Context context) {
25 if (instance == null)
26 instance = new EventDBUtil(context);
27 return instance;
28 }
29
30 public boolean saveEvent(Event event) {
31 SQLiteDatabase db = helper.getWritableDatabase();
32 long rowId = db.insert(Event.TABLE_NAME, null, event.toContentValues());
33 return rowId != -1;
34 }
35
36 public boolean clearEvent(Event event) {
37 SQLiteDatabase db = helper.getWritableDatabase();
38 int count = db.delete(Event.TABLE_NAME, Event._ID + "=?", new String[] { event.getRid() + "" });
39 return count > 0;
40 }
41
42 public void clearEvent(List<Event> events) {
43 SQLiteDatabase db = helper.getWritableDatabase();
44 for (Event event : events) {
45 try {
46 db.delete(Event.TABLE_NAME, Event._ID + "=?", new String[] { event.getRid() + "" });
47 } catch (Exception e) {
48 e.printStackTrace();
49 event.setStatus(-1);
50 db.update(Event.TABLE_NAME, event.toContentValues(), Event._ID + "=" + event.getRid(), null);
51 }
52 }
53 }
54
55 public boolean clearEventAll() {
56 SQLiteDatabase db = helper.getWritableDatabase();
57 int count = db.delete(Event.TABLE_NAME, null, null);
58 return count > 0;
59 }
60
61 public List<Event> getEvents(int limit) {
62 SQLiteDatabase db = helper.getWritableDatabase();
63 Cursor cursor = db.query(Event.TABLE_NAME, Event.COLUMNS, Event.COLUMN_STATUS + ">-1", null, null, null, null, limit + "");
64 List<Event> events = Event.parseCursor(cursor);
65 return events;
66 }
67
68 class DBHelper extends SQLiteOpenHelper {
69
70 public DBHelper(Context context) {
71 super(context, DB_NAME, null, version);
72 }
73
74 @Override
75 public void onCreate(SQLiteDatabase db) {
76 db.execSQL(Event.CREATE_TABLE);
77 }
78
79 @Override
80 public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
81
82 }
83
84 }
85 }
86 1 package com.mobithink.tracesdk.event;
TraceSDK/src/com/mobithink/tracesdk/json/JSON.java
1 /* File was deleted
2 * Copyright (C) 2010 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 package com.mobithink.tracesdk.json;
18
19 class JSON {
20 /**
21 * Returns the input if it is a JSON-permissible value; throws otherwise.
22 */
23 static double checkDouble(double d) throws JSONException {
24 if (Double.isInfinite(d) || Double.isNaN(d)) {
25 throw new JSONException("Forbidden numeric value: " + d);
26 }
27 return d;
28 }
29
30 static Boolean toBoolean(Object value) {
31 if (value instanceof Boolean) {
32 return (Boolean) value;
33 } else if (value instanceof String) {
34 String stringValue = (String) value;
35 if ("true".equalsIgnoreCase(stringValue)) {
36 return true;
37 } else if ("false".equalsIgnoreCase(stringValue)) {
38 return false;
39 }
40 }
41 return null;
42 }
43
44 static Double toDouble(Object value) {
45 if (value instanceof Double) {
46 return (Double) value;
47 } else if (value instanceof Number) {
48 return ((Number) value).doubleValue();
49 } else if (value instanceof String) {
50 try {
51 return Double.valueOf((String) value);
52 } catch (NumberFormatException ignored) {
53 }
54 }
55 return null;
56 }
57
58 static Integer toInteger(Object value) {
59 if (value instanceof Integer) {
60 return (Integer) value;
61 } else if (value instanceof Number) {
62 return ((Number) value).intValue();
63 } else if (value instanceof String) {
64 try {
65 return (int) Double.parseDouble((String) value);
66 } catch (NumberFormatException ignored) {
67 }
68 }
69 return null;
70 }
71
72 static Long toLong(Object value) {
73 if (value instanceof Long) {
74 return (Long) value;
75 } else if (value instanceof Number) {
76 return ((Number) value).longValue();
77 } else if (value instanceof String) {
78 try {
79 return (long) Double.parseDouble((String) value);
80 } catch (NumberFormatException ignored) {
81 }
82 }
83 return null;
84 }
85
86 static String toString(Object value) {
87 if (value instanceof String) {
88 return (String) value;
89 } else if (value != null) {
90 return String.valueOf(value);
91 }
92 return null;
93 }
94
95 public static JSONException typeMismatch(Object indexOrName, Object actual,
96 String requiredType) throws JSONException {
97 if (actual == null) {
98 throw new JSONException("Value at " + indexOrName + " is null.");
99 } else {
100 throw new JSONException("Value " + actual + " at " + indexOrName
101 + " of type " + actual.getClass().getName()
102 + " cannot be converted to " + requiredType);
103 }
104 }
105
106 public static JSONException typeMismatch(Object actual, String requiredType)
107 throws JSONException {
108 if (actual == null) {
109 throw new JSONException("Value is null.");
110 } else {
111 throw new JSONException("Value " + actual
112 + " of type " + actual.getClass().getName()
113 + " cannot be converted to " + requiredType);
114 }
115 }
116 }
117 1 /*
TraceSDK/src/com/mobithink/tracesdk/json/JSONArray.java
1 /* File was deleted
2 * Copyright (C) 2010 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 package com.mobithink.tracesdk.json;
18
19 import java.util.ArrayList;
20 import java.util.Collection;
21 import java.util.List;
22
23 // Note: this class was written without inspecting the non-free org.json sourcecode.
24
25 /**
26 * A dense indexed sequence of values. Values may be any mix of
27 * {@link JSONObject JSONObjects}, other {@link JSONArray JSONArrays}, Strings,
28 * Booleans, Integers, Longs, Doubles, {@code null} or {@link JSONObject#NULL}.
29 * Values may not be {@link Double#isNaN() NaNs}, {@link Double#isInfinite()
30 * infinities}, or of any type not listed here.
31 *
32 * <p>{@code JSONArray} has the same type coercion behavior and
33 * optional/mandatory accessors as {@link JSONObject}. See that class'
34 * documentation for details.
35 *
36 * <p><strong>Warning:</strong> this class represents null in two incompatible
37 * ways: the standard Java {@code null} reference, and the sentinel value {@link
38 * JSONObject#NULL}. In particular, {@code get} fails if the requested index
39 * holds the null reference, but succeeds if it holds {@code JSONObject.NULL}.
40 *
41 * <p>Instances of this class are not thread safe. Although this class is
42 * nonfinal, it was not designed for inheritance and should not be subclassed.
43 * In particular, self-use by overridable methods is not specified. See
44 * <i>Effective Java</i> Item 17, "Design and Document or inheritance or else
45 * prohibit it" for further information.
46 */
47 public class JSONArray {
48
49 private final List<Object> values;
50
51 /**
52 * Creates a {@code JSONArray} with no values.
53 */
54 public JSONArray() {
55 values = new ArrayList<Object>();
56 }
57
58 /**
59 * Creates a new {@code JSONArray} by copying all values from the given
60 * collection.
61 *
62 * @param copyFrom a collection whose values are of supported types.
63 * Unsupported values are not permitted and will yield an array in an
64 * inconsistent state.
65 */
66 /* Accept a raw type for API compatibility */
67 public JSONArray(Collection copyFrom) {
68 this();
69 Collection<?> copyFromTyped = (Collection<?>) copyFrom;
70 values.addAll(copyFromTyped);
71 }
72
73 /**
74 * Creates a new {@code JSONArray} with values from the next array in the
75 * tokener.
76 *
77 * @param readFrom a tokener whose nextValue() method will yield a
78 * {@code JSONArray}.
79 * @throws JSONException if the parse fails or doesn't yield a
80 * {@code JSONArray}.
81 */
82 public JSONArray(JSONTokener readFrom) throws JSONException {
83 /*
84 * Getting the parser to populate this could get tricky. Instead, just
85 * parse to temporary JSONArray and then steal the data from that.
86 */
87 Object object = readFrom.nextValue();
88 if (object instanceof JSONArray) {
89 values = ((JSONArray) object).values;
90 } else {
91 throw JSON.typeMismatch(object, "JSONArray");
92 }
93 }
94
95 /**
96 * Creates a new {@code JSONArray} with values from the JSON string.
97 *
98 * @param json a JSON-encoded string containing an array.
99 * @throws JSONException if the parse fails or doesn't yield a {@code
100 * JSONArray}.
101 */
102 public JSONArray(String json) throws JSONException {
103 this(new JSONTokener(json));
104 }
105
106 /**
107 * Returns the number of values in this array.
108 */
109 public int length() {
110 return values.size();
111 }
112
113 /**
114 * Appends {@code value} to the end of this array.
115 *
116 * @return this array.
117 */
118 public JSONArray put(boolean value) {
119 values.add(value);
120 return this;
121 }
122
123 /**
124 * Appends {@code value} to the end of this array.
125 *
126 * @param value a finite value. May not be {@link Double#isNaN() NaNs} or
127 * {@link Double#isInfinite() infinities}.
128 * @return this array.
129 */
130 public JSONArray put(double value) throws JSONException {
131 values.add(JSON.checkDouble(value));
132 return this;
133 }
134
135 /**
136 * Appends {@code value} to the end of this array.
137 *
138 * @return this array.
139 */
140 public JSONArray put(int value) {
141 values.add(value);
142 return this;
143 }
144
145 /**
146 * Appends {@code value} to the end of this array.
147 *
148 * @return this array.
149 */
150 public JSONArray put(long value) {
151 values.add(value);
152 return this;
153 }
154
155 /**
156 * Appends {@code value} to the end of this array.
157 *
158 * @param value a {@link JSONObject}, {@link JSONArray}, String, Boolean,
159 * Integer, Long, Double, {@link JSONObject#NULL}, or {@code null}. May
160 * not be {@link Double#isNaN() NaNs} or {@link Double#isInfinite()
161 * infinities}. Unsupported values are not permitted and will cause the
162 * array to be in an inconsistent state.
163 * @return this array.
164 */
165 public JSONArray put(Object value) {
166 values.add(value);
167 return this;
168 }
169
170 /**
171 * Sets the value at {@code index} to {@code value}, null padding this array
172 * to the required length if necessary. If a value already exists at {@code
173 * index}, it will be replaced.
174 *
175 * @return this array.
176 */
177 public JSONArray put(int index, boolean value) throws JSONException {
178 return put(index, (Boolean) value);
179 }
180
181 /**
182 * Sets the value at {@code index} to {@code value}, null padding this array
183 * to the required length if necessary. If a value already exists at {@code
184 * index}, it will be replaced.
185 *
186 * @param value a finite value. May not be {@link Double#isNaN() NaNs} or
187 * {@link Double#isInfinite() infinities}.
188 * @return this array.
189 */
190 public JSONArray put(int index, double value) throws JSONException {
191 return put(index, (Double) value);
192 }
193
194 /**
195 * Sets the value at {@code index} to {@code value}, null padding this array
196 * to the required length if necessary. If a value already exists at {@code
197 * index}, it will be replaced.
198 *
199 * @return this array.
200 */
201 public JSONArray put(int index, int value) throws JSONException {
202 return put(index, (Integer) value);
203 }
204
205 /**
206 * Sets the value at {@code index} to {@code value}, null padding this array
207 * to the required length if necessary. If a value already exists at {@code
208 * index}, it will be replaced.
209 *
210 * @return this array.
211 */
212 public JSONArray put(int index, long value) throws JSONException {
213 return put(index, (Long) value);
214 }
215
216 /**
217 * Sets the value at {@code index} to {@code value}, null padding this array
218 * to the required length if necessary. If a value already exists at {@code
219 * index}, it will be replaced.
220 *
221 * @param value a {@link JSONObject}, {@link JSONArray}, String, Boolean,
222 * Integer, Long, Double, {@link JSONObject#NULL}, or {@code null}. May
223 * not be {@link Double#isNaN() NaNs} or {@link Double#isInfinite()
224 * infinities}.
225 * @return this array.
226 */
227 public JSONArray put(int index, Object value) throws JSONException {
228 if (value instanceof Number) {
229 // deviate from the original by checking all Numbers, not just floats & doubles
230 JSON.checkDouble(((Number) value).doubleValue());
231 }
232 while (values.size() <= index) {
233 values.add(null);
234 }
235 values.set(index, value);
236 return this;
237 }
238
239 /**
240 * Returns true if this array has no value at {@code index}, or if its value
241 * is the {@code null} reference or {@link JSONObject#NULL}.
242 */
243 public boolean isNull(int index) {
244 Object value = opt(index);
245 return value == null || value == JSONObject.NULL;
246 }
247
248 /**
249 * Returns the value at {@code index}.
250 *
251 * @throws JSONException if this array has no value at {@code index}, or if
252 * that value is the {@code null} reference. This method returns
253 * normally if the value is {@code JSONObject#NULL}.
254 */
255 public Object get(int index) throws JSONException {
256 try {
257 Object value = values.get(index);
258 if (value == null) {
259 throw new JSONException("Value at " + index + " is null.");
260 }
261 return value;
262 } catch (IndexOutOfBoundsException e) {
263 throw new JSONException("Index " + index + " out of range [0.." + values.size() + ")");
264 }
265 }
266
267 /**
268 * Returns the value at {@code index}, or null if the array has no value
269 * at {@code index}.
270 */
271 public Object opt(int index) {
272 if (index < 0 || index >= values.size()) {
273 return null;
274 }
275 return values.get(index);
276 }
277
278 /**
279 * Returns the value at {@code index} if it exists and is a boolean or can
280 * be coerced to a boolean.
281 *
282 * @throws JSONException if the value at {@code index} doesn't exist or
283 * cannot be coerced to a boolean.
284 */
285 public boolean getBoolean(int index) throws JSONException {
286 Object object = get(index);
287 Boolean result = JSON.toBoolean(object);
288 if (result == null) {
289 throw JSON.typeMismatch(index, object, "boolean");
290 }
291 return result;
292 }
293
294 /**
295 * Returns the value at {@code index} if it exists and is a boolean or can
296 * be coerced to a boolean. Returns false otherwise.
297 */
298 public boolean optBoolean(int index) {
299 return optBoolean(index, false);
300 }
301
302 /**
303 * Returns the value at {@code index} if it exists and is a boolean or can
304 * be coerced to a boolean. Returns {@code fallback} otherwise.
305 */
306 public boolean optBoolean(int index, boolean fallback) {
307 Object object = opt(index);
308 Boolean result = JSON.toBoolean(object);
309 return result != null ? result : fallback;
310 }
311
312 /**
313 * Returns the value at {@code index} if it exists and is a double or can
314 * be coerced to a double.
315 *
316 * @throws JSONException if the value at {@code index} doesn't exist or
317 * cannot be coerced to a double.
318 */
319 public double getDouble(int index) throws JSONException {
320 Object object = get(index);
321 Double result = JSON.toDouble(object);
322 if (result == null) {
323 throw JSON.typeMismatch(index, object, "double");
324 }
325 return result;
326 }
327
328 /**
329 * Returns the value at {@code index} if it exists and is a double or can
330 * be coerced to a double. Returns {@code NaN} otherwise.
331 */
332 public double optDouble(int index) {
333 return optDouble(index, Double.NaN);
334 }
335
336 /**
337 * Returns the value at {@code index} if it exists and is a double or can
338 * be coerced to a double. Returns {@code fallback} otherwise.
339 */
340 public double optDouble(int index, double fallback) {
341 Object object = opt(index);
342 Double result = JSON.toDouble(object);
343 return result != null ? result : fallback;
344 }
345
346 /**
347 * Returns the value at {@code index} if it exists and is an int or
348 * can be coerced to an int.
349 *
350 * @throws JSONException if the value at {@code index} doesn't exist or
351 * cannot be coerced to a int.
352 */
353 public int getInt(int index) throws JSONException {
354 Object object = get(index);
355 Integer result = JSON.toInteger(object);
356 if (result == null) {
357 throw JSON.typeMismatch(index, object, "int");
358 }
359 return result;
360 }
361
362 /**
363 * Returns the value at {@code index} if it exists and is an int or
364 * can be coerced to an int. Returns 0 otherwise.
365 */
366 public int optInt(int index) {
367 return optInt(index, 0);
368 }
369
370 /**
371 * Returns the value at {@code index} if it exists and is an int or
372 * can be coerced to an int. Returns {@code fallback} otherwise.
373 */
374 public int optInt(int index, int fallback) {
375 Object object = opt(index);
376 Integer result = JSON.toInteger(object);
377 return result != null ? result : fallback;
378 }
379
380 /**
381 * Returns the value at {@code index} if it exists and is a long or
382 * can be coerced to a long.
383 *
384 * @throws JSONException if the value at {@code index} doesn't exist or
385 * cannot be coerced to a long.
386 */
387 public long getLong(int index) throws JSONException {
388 Object object = get(index);
389 Long result = JSON.toLong(object);
390 if (result == null) {
391 throw JSON.typeMismatch(index, object, "long");
392 }
393 return result;
394 }
395
396 /**
397 * Returns the value at {@code index} if it exists and is a long or
398 * can be coerced to a long. Returns 0 otherwise.
399 */
400 public long optLong(int index) {
401 return optLong(index, 0L);
402 }
403
404 /**
405 * Returns the value at {@code index} if it exists and is a long or
406 * can be coerced to a long. Returns {@code fallback} otherwise.
407 */
408 public long optLong(int index, long fallback) {
409 Object object = opt(index);
410 Long result = JSON.toLong(object);
411 return result != null ? result : fallback;
412 }
413
414 /**
415 * Returns the value at {@code index} if it exists, coercing it if
416 * necessary.
417 *
418 * @throws JSONException if no such value exists.
419 */
420 public String getString(int index) throws JSONException {
421 Object object = get(index);
422 String result = JSON.toString(object);
423 if (result == null) {
424 throw JSON.typeMismatch(index, object, "String");
425 }
426 return result;
427 }
428
429 /**
430 * Returns the value at {@code index} if it exists, coercing it if
431 * necessary. Returns the empty string if no such value exists.
432 */
433 public String optString(int index) {
434 return optString(index, "");
435 }
436
437 /**
438 * Returns the value at {@code index} if it exists, coercing it if
439 * necessary. Returns {@code fallback} if no such value exists.
440 */
441 public String optString(int index, String fallback) {
442 Object object = opt(index);
443 String result = JSON.toString(object);
444 return result != null ? result : fallback;
445 }
446
447 /**
448 * Returns the value at {@code index} if it exists and is a {@code
449 * JSONArray}.
450 *
451 * @throws JSONException if the value doesn't exist or is not a {@code
452 * JSONArray}.
453 */
454 public JSONArray getJSONArray(int index) throws JSONException {
455 Object object = get(index);
456 if (object instanceof JSONArray) {
457 return (JSONArray) object;
458 } else {
459 throw JSON.typeMismatch(index, object, "JSONArray");
460 }
461 }
462
463 /**
464 * Returns the value at {@code index} if it exists and is a {@code
465 * JSONArray}. Returns null otherwise.
466 */
467 public JSONArray optJSONArray(int index) {
468 Object object = opt(index);
469 return object instanceof JSONArray ? (JSONArray) object : null;
470 }
471
472 /**
473 * Returns the value at {@code index} if it exists and is a {@code
474 * JSONObject}.
475 *
476 * @throws JSONException if the value doesn't exist or is not a {@code
477 * JSONObject}.
478 */
479 public JSONObject getJSONObject(int index) throws JSONException {
480 Object object = get(index);
481 if (object instanceof JSONObject) {
482 return (JSONObject) object;
483 } else {
484 throw JSON.typeMismatch(index, object, "JSONObject");
485 }
486 }
487
488 /**
489 * Returns the value at {@code index} if it exists and is a {@code
490 * JSONObject}. Returns null otherwise.
491 */
492 public JSONObject optJSONObject(int index) {
493 Object object = opt(index);
494 return object instanceof JSONObject ? (JSONObject) object : null;
495 }
496
497 /**
498 * Returns a new object whose values are the values in this array, and whose
499 * names are the values in {@code names}. Names and values are paired up by
500 * index from 0 through to the shorter array's length. Names that are not
501 * strings will be coerced to strings. This method returns null if either
502 * array is empty.
503 */
504 public JSONObject toJSONObject(JSONArray names) throws JSONException {
505 JSONObject result = new JSONObject();
506 int length = Math.min(names.length(), values.size());
507 if (length == 0) {
508 return null;
509 }
510 for (int i = 0; i < length; i++) {
511 String name = JSON.toString(names.opt(i));
512 result.put(name, opt(i));
513 }
514 return result;
515 }
516
517 /**
518 * Returns a new string by alternating this array's values with {@code
519 * separator}. This array's string values are quoted and have their special
520 * characters escaped. For example, the array containing the strings '12"
521 * pizza', 'taco' and 'soda' joined on '+' returns this:
522 * <pre>"12\" pizza"+"taco"+"soda"</pre>
523 */
524 public String join(String separator) throws JSONException {
525 JSONStringer stringer = new JSONStringer();
526 stringer.open(JSONStringer.Scope.NULL, "");
527 for (int i = 0, size = values.size(); i < size; i++) {
528 if (i > 0) {
529 stringer.out.append(separator);
530 }
531 stringer.value(values.get(i));
532 }
533 stringer.close(JSONStringer.Scope.NULL, JSONStringer.Scope.NULL, "");
534 return stringer.out.toString();
535 }
536
537 /**
538 * Encodes this array as a compact JSON string, such as:
539 * <pre>[94043,90210]</pre>
540 */
541 @Override public String toString() {
542 try {
543 JSONStringer stringer = new JSONStringer();
544 writeTo(stringer);
545 return stringer.toString();
546 } catch (JSONException e) {
547 return null;
548 }
549 }
550
551 /**
552 * Encodes this array as a human readable JSON string for debugging, such
553 * as:
554 * <pre>
555 * [
556 * 94043,
557 * 90210
558 * ]</pre>
559 *
560 * @param indentSpaces the number of spaces to indent for each level of
561 * nesting.
562 */
563 public String toString(int indentSpaces) throws JSONException {
564 JSONStringer stringer = new JSONStringer(indentSpaces);
565 writeTo(stringer);
566 return stringer.toString();
567 }
568
569 void writeTo(JSONStringer stringer) throws JSONException {
570 stringer.array();
571 for (Object value : values) {
572 stringer.value(value);
573 }
574 stringer.endArray();
575 }
576
577 @Override public boolean equals(Object o) {
578 return o instanceof JSONArray && ((JSONArray) o).values.equals(values);
579 }
580
581 @Override public int hashCode() {
582 // diverge from the original, which doesn't implement hashCode
583 return values.hashCode();
584 }
585 }
586 1 /*
TraceSDK/src/com/mobithink/tracesdk/json/JSONException.java
1 /* File was deleted
2 * Copyright (C) 2010 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 package com.mobithink.tracesdk.json;
18
19 // Note: this class was written without inspecting the non-free org.json sourcecode.
20
21 /**
22 * Thrown to indicate a problem with the JSON API. Such problems include:
23 * <ul>
24 * <li>Attempts to parse or construct malformed documents
25 * <li>Use of null as a name
26 * <li>Use of numeric types not available to JSON, such as {@link
27 * Double#isNaN() NaNs} or {@link Double#isInfinite() infinities}.
28 * <li>Lookups using an out of range index or nonexistent name
29 * <li>Type mismatches on lookups
30 * </ul>
31 *
32 * <p>Although this is a checked exception, it is rarely recoverable. Most
33 * callers should simply wrap this exception in an unchecked exception and
34 * rethrow:
35 * <pre> public JSONArray toJSONObject() {
36 * try {
37 * JSONObject result = new JSONObject();
38 * ...
39 * } catch (JSONException e) {
40 * throw new RuntimeException(e);
41 * }
42 * }</pre>
43 */
44 public class JSONException extends Exception {
45
46 public JSONException(String s) {
47 super(s);
48 }
49 }
50 1 /*
TraceSDK/src/com/mobithink/tracesdk/json/JSONObject.java
1 /* File was deleted
2 * Copyright (C) 2010 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 package com.mobithink.tracesdk.json;
18
19 import java.util.ArrayList;
20 import java.util.HashMap;
21 import java.util.Iterator;
22 import java.util.Map;
23
24 // Note: this class was written without inspecting the non-free org.json sourcecode.
25
26 /**
27 * A modifiable set of name/value mappings. Names are unique, non-null strings.
28 * Values may be any mix of {@link JSONObject JSONObjects}, {@link JSONArray
29 * JSONArrays}, Strings, Booleans, Integers, Longs, Doubles or {@link #NULL}.
30 * Values may not be {@code null}, {@link Double#isNaN() NaNs}, {@link
31 * Double#isInfinite() infinities}, or of any type not listed here.
32 *
33 * <p>This class can coerce values to another type when requested.
34 * <ul>
35 * <li>When the requested type is a boolean, strings will be coerced using a
36 * case-insensitive comparison to "true" and "false".
37 * <li>When the requested type is a double, other {@link Number} types will
38 * be coerced using {@link Number#doubleValue() doubleValue}. Strings
39 * that can be coerced using {@link Double#valueOf(String)} will be.
40 * <li>When the requested type is an int, other {@link Number} types will
41 * be coerced using {@link Number#intValue() intValue}. Strings
42 * that can be coerced using {@link Double#valueOf(String)} will be,
43 * and then cast to int.
44 * <li>When the requested type is a long, other {@link Number} types will
45 * be coerced using {@link Number#longValue() longValue}. Strings
46 * that can be coerced using {@link Double#valueOf(String)} will be,
47 * and then cast to long. This two-step conversion is lossy for very
48 * large values. For example, the string "9223372036854775806" yields the
49 * long 9223372036854775807.
50 * <li>When the requested type is a String, other non-null values will be
51 * coerced using {@link String#valueOf(Object)}. Although null cannot be
52 * coerced, the sentinel value {@link JSONObject#NULL} is coerced to the
53 * string "null".
54 * </ul>
55 *
56 * <p>This class can look up both mandatory and optional values:
57 * <ul>
58 * <li>Use <code>get<i>Type</i>()</code> to retrieve a mandatory value. This
59 * fails with a {@code JSONException} if the requested name has no value
60 * or if the value cannot be coerced to the requested type.
61 * <li>Use <code>opt<i>Type</i>()</code> to retrieve an optional value. This
62 * returns a system- or user-supplied default if the requested name has no
63 * value or if the value cannot be coerced to the requested type.
64 * </ul>
65 *
66 * <p><strong>Warning:</strong> this class represents null in two incompatible
67 * ways: the standard Java {@code null} reference, and the sentinel value {@link
68 * JSONObject#NULL}. In particular, calling {@code put(name, null)} removes the
69 * named entry from the object but {@code put(name, JSONObject.NULL)} stores an
70 * entry whose value is {@code JSONObject.NULL}.
71 *
72 * <p>Instances of this class are not thread safe. Although this class is
73 * nonfinal, it was not designed for inheritance and should not be subclassed.
74 * In particular, self-use by overrideable methods is not specified. See
75 * <i>Effective Java</i> Item 17, "Design and Document or inheritance or else
76 * prohibit it" for further information.
77 */
78 public class JSONObject {
79
80 private static final Double NEGATIVE_ZERO = -0d;
81
82 /**
83 * A sentinel value used to explicitly define a name with no value. Unlike
84 * {@code null}, names with this value:
85 * <ul>
86 * <li>show up in the {@link #names} array
87 * <li>show up in the {@link #keys} iterator
88 * <li>return {@code true} for {@link #has(String)}
89 * <li>do not throw on {@link #get(String)}
90 * <li>are included in the encoded JSON string.
91 * </ul>
92 *
93 * <p>This value violates the general contract of {@link Object#equals} by
94 * returning true when compared to {@code null}. Its {@link #toString}
95 * method returns "null".
96 */
97 public static final Object NULL = new Object() {
98 @Override public boolean equals(Object o) {
99 return o == this || o == null; // API specifies this broken equals implementation
100 }
101 @Override public String toString() {
102 return "null";
103 }
104 };
105
106 private final Map<String, Object> nameValuePairs;
107
108 /**
109 * Creates a {@code JSONObject} with no name/value mappings.
110 */
111 public JSONObject() {
112 nameValuePairs = new HashMap<String, Object>();
113 }
114
115 /**
116 * Creates a new {@code JSONObject} by copying all name/value mappings from
117 * the given map.
118 *
119 * @param copyFrom a map whose keys are of type {@link String} and whose
120 * values are of supported types.
121 * @throws NullPointerException if any of the map's keys are null.
122 */
123 /* (accept a raw type for API compatibility) */
124 public JSONObject(Map copyFrom) {
125 this();
126 Map<?, ?> contentsTyped = (Map<?, ?>) copyFrom;
127 for (Map.Entry<?, ?> entry : contentsTyped.entrySet()) {
128 /*
129 * Deviate from the original by checking that keys are non-null and
130 * of the proper type. (We still defer validating the values).
131 */
132 String key = (String) entry.getKey();
133 if (key == null) {
134 throw new NullPointerException();
135 }
136 nameValuePairs.put(key, entry.getValue());
137 }
138 }
139
140 /**
141 * Creates a new {@code JSONObject} with name/value mappings from the next
142 * object in the tokener.
143 *
144 * @param readFrom a tokener whose nextValue() method will yield a
145 * {@code JSONObject}.
146 * @throws JSONException if the parse fails or doesn't yield a
147 * {@code JSONObject}.
148 */
149 public JSONObject(JSONTokener readFrom) throws JSONException {
150 /*
151 * Getting the parser to populate this could get tricky. Instead, just
152 * parse to temporary JSONObject and then steal the data from that.
153 */
154 Object object = readFrom.nextValue();
155 if (object instanceof JSONObject) {
156 this.nameValuePairs = ((JSONObject) object).nameValuePairs;
157 } else {
158 throw JSON.typeMismatch(object, "JSONObject");
159 }
160 }
161
162 /**
163 * Creates a new {@code JSONObject} with name/value mappings from the JSON
164 * string.
165 *
166 * @param json a JSON-encoded string containing an object.
167 * @throws JSONException if the parse fails or doesn't yield a {@code
168 * JSONObject}.
169 */
170 public JSONObject(String json) throws JSONException {
171 this(new JSONTokener(json));
172 }
173
174 /**
175 * Creates a new {@code JSONObject} by copying mappings for the listed names
176 * from the given object. Names that aren't present in {@code copyFrom} will
177 * be skipped.
178 */
179 public JSONObject(JSONObject copyFrom, String[] names) throws JSONException {
180 this();
181 for (String name : names) {
182 Object value = copyFrom.opt(name);
183 if (value != null) {
184 nameValuePairs.put(name, value);
185 }
186 }
187 }
188
189 /**
190 * Returns the number of name/value mappings in this object.
191 */
192 public int length() {
193 return nameValuePairs.size();
194 }
195
196 /**
197 * Maps {@code name} to {@code value}, clobbering any existing name/value
198 * mapping with the same name.
199 *
200 * @return this object.
201 */
202 public JSONObject put(String name, boolean value) throws JSONException {
203 nameValuePairs.put(checkName(name), value);
204 return this;
205 }
206
207 /**
208 * Maps {@code name} to {@code value}, clobbering any existing name/value
209 * mapping with the same name.
210 *
211 * @param value a finite value. May not be {@link Double#isNaN() NaNs} or
212 * {@link Double#isInfinite() infinities}.
213 * @return this object.
214 */
215 public JSONObject put(String name, double value) throws JSONException {
216 nameValuePairs.put(checkName(name), JSON.checkDouble(value));
217 return this;
218 }
219
220 /**
221 * Maps {@code name} to {@code value}, clobbering any existing name/value
222 * mapping with the same name.
223 *
224 * @return this object.
225 */
226 public JSONObject put(String name, int value) throws JSONException {
227 nameValuePairs.put(checkName(name), value);
228 return this;
229 }
230
231 /**
232 * Maps {@code name} to {@code value}, clobbering any existing name/value
233 * mapping with the same name.
234 *
235 * @return this object.
236 */
237 public JSONObject put(String name, long value) throws JSONException {
238 nameValuePairs.put(checkName(name), value);
239 return this;
240 }
241
242 /**
243 * Maps {@code name} to {@code value}, clobbering any existing name/value
244 * mapping with the same name. If the value is {@code null}, any existing
245 * mapping for {@code name} is removed.
246 *
247 * @param value a {@link JSONObject}, {@link JSONArray}, String, Boolean,
248 * Integer, Long, Double, {@link #NULL}, or {@code null}. May not be
249 * {@link Double#isNaN() NaNs} or {@link Double#isInfinite()
250 * infinities}.
251 * @return this object.
252 */
253 public JSONObject put(String name, Object value) throws JSONException {
254 if (value == null) {
255 nameValuePairs.remove(name);
256 return this;
257 }
258 if (value instanceof Number) {
259 // deviate from the original by checking all Numbers, not just floats & doubles
260 JSON.checkDouble(((Number) value).doubleValue());
261 }
262 nameValuePairs.put(checkName(name), value);
263 return this;
264 }
265
266 /**
267 * Equivalent to {@code put(name, value)} when both parameters are non-null;
268 * does nothing otherwise.
269 */
270 public JSONObject putOpt(String name, Object value) throws JSONException {
271 if (name == null || value == null) {
272 return this;
273 }
274 return put(name, value);
275 }
276
277 /**
278 * Appends {@code value} to the array already mapped to {@code name}. If
279 * this object has no mapping for {@code name}, this inserts a new mapping.
280 * If the mapping exists but its value is not an array, the existing
281 * and new values are inserted in order into a new array which is itself
282 * mapped to {@code name}. In aggregate, this allows values to be added to a
283 * mapping one at a time.
284 *
285 * @param value a {@link JSONObject}, {@link JSONArray}, String, Boolean,
286 * Integer, Long, Double, {@link #NULL} or null. May not be {@link
287 * Double#isNaN() NaNs} or {@link Double#isInfinite() infinities}.
288 */
289 public JSONObject accumulate(String name, Object value) throws JSONException {
290 Object current = nameValuePairs.get(checkName(name));
291 if (current == null) {
292 return put(name, value);
293 }
294
295 // check in accumulate, since array.put(Object) doesn't do any checking
296 if (value instanceof Number) {
297 JSON.checkDouble(((Number) value).doubleValue());
298 }
299
300 if (current instanceof JSONArray) {
301 JSONArray array = (JSONArray) current;
302 array.put(value);
303 } else {
304 JSONArray array = new JSONArray();
305 array.put(current);
306 array.put(value);
307 nameValuePairs.put(name, array);
308 }
309 return this;
310 }
311
312 String checkName(String name) throws JSONException {
313 if (name == null) {
314 throw new JSONException("Names must be non-null");
315 }
316 return name;
317 }
318
319 /**
320 * Removes the named mapping if it exists; does nothing otherwise.
321 *
322 * @return the value previously mapped by {@code name}, or null if there was
323 * no such mapping.
324 */
325 public Object remove(String name) {
326 return nameValuePairs.remove(name);
327 }
328
329 /**
330 * Returns true if this object has no mapping for {@code name} or if it has
331 * a mapping whose value is {@link #NULL}.
332 */
333 public boolean isNull(String name) {
334 Object value = nameValuePairs.get(name);
335 return value == null || value == NULL;
336 }
337
338 /**
339 * Returns true if this object has a mapping for {@code name}. The mapping
340 * may be {@link #NULL}.
341 */
342 public boolean has(String name) {
343 return nameValuePairs.containsKey(name);
344 }
345
346 /**
347 * Returns the value mapped by {@code name}.
348 *
349 * @throws JSONException if no such mapping exists.
350 */
351 public Object get(String name) throws JSONException {
352 Object result = nameValuePairs.get(name);
353 if (result == null) {
354 throw new JSONException("No value for " + name);
355 }
356 return result;
357 }
358
359 /**
360 * Returns the value mapped by {@code name}, or null if no such mapping
361 * exists.
362 */
363 public Object opt(String name) {
364 return nameValuePairs.get(name);
365 }
366
367 /**
368 * Returns the value mapped by {@code name} if it exists and is a boolean or
369 * can be coerced to a boolean.
370 *
371 * @throws JSONException if the mapping doesn't exist or cannot be coerced
372 * to a boolean.
373 */
374 public boolean getBoolean(String name) throws JSONException {
375 Object object = get(name);
376 Boolean result = JSON.toBoolean(object);
377 if (result == null) {
378 throw JSON.typeMismatch(name, object, "boolean");
379 }
380 return result;
381 }
382
383 /**
384 * Returns the value mapped by {@code name} if it exists and is a boolean or
385 * can be coerced to a boolean. Returns false otherwise.
386 */
387 public boolean optBoolean(String name) {
388 return optBoolean(name, false);
389 }
390
391 /**
392 * Returns the value mapped by {@code name} if it exists and is a boolean or
393 * can be coerced to a boolean. Returns {@code fallback} otherwise.
394 */
395 public boolean optBoolean(String name, boolean fallback) {
396 Object object = opt(name);
397 Boolean result = JSON.toBoolean(object);
398 return result != null ? result : fallback;
399 }
400
401 /**
402 * Returns the value mapped by {@code name} if it exists and is a double or
403 * can be coerced to a double.
404 *
405 * @throws JSONException if the mapping doesn't exist or cannot be coerced
406 * to a double.
407 */
408 public double getDouble(String name) throws JSONException {
409 Object object = get(name);
410 Double result = JSON.toDouble(object);
411 if (result == null) {
412 throw JSON.typeMismatch(name, object, "double");
413 }
414 return result;
415 }
416
417 /**
418 * Returns the value mapped by {@code name} if it exists and is a double or
419 * can be coerced to a double. Returns {@code NaN} otherwise.
420 */
421 public double optDouble(String name) {
422 return optDouble(name, Double.NaN);
423 }
424
425 /**
426 * Returns the value mapped by {@code name} if it exists and is a double or
427 * can be coerced to a double. Returns {@code fallback} otherwise.
428 */
429 public double optDouble(String name, double fallback) {
430 Object object = opt(name);
431 Double result = JSON.toDouble(object);
432 return result != null ? result : fallback;
433 }
434
435 /**
436 * Returns the value mapped by {@code name} if it exists and is an int or
437 * can be coerced to an int.
438 *
439 * @throws JSONException if the mapping doesn't exist or cannot be coerced
440 * to an int.
441 */
442 public int getInt(String name) throws JSONException {
443 Object object = get(name);
444 Integer result = JSON.toInteger(object);
445 if (result == null) {
446 throw JSON.typeMismatch(name, object, "int");
447 }
448 return result;
449 }
450
451 /**
452 * Returns the value mapped by {@code name} if it exists and is an int or
453 * can be coerced to an int. Returns 0 otherwise.
454 */
455 public int optInt(String name) {
456 return optInt(name, 0);
457 }
458
459 /**
460 * Returns the value mapped by {@code name} if it exists and is an int or
461 * can be coerced to an int. Returns {@code fallback} otherwise.
462 */
463 public int optInt(String name, int fallback) {
464 Object object = opt(name);
465 Integer result = JSON.toInteger(object);
466 return result != null ? result : fallback;
467 }
468
469 /**
470 * Returns the value mapped by {@code name} if it exists and is a long or
471 * can be coerced to a long.
472 *
473 * @throws JSONException if the mapping doesn't exist or cannot be coerced
474 * to a long.
475 */
476 public long getLong(String name) throws JSONException {
477 Object object = get(name);
478 Long result = JSON.toLong(object);
479 if (result == null) {
480 throw JSON.typeMismatch(name, object, "long");
481 }
482 return result;
483 }
484
485 /**
486 * Returns the value mapped by {@code name} if it exists and is a long or
487 * can be coerced to a long. Returns 0 otherwise.
488 */
489 public long optLong(String name) {
490 return optLong(name, 0L);
491 }
492
493 /**
494 * Returns the value mapped by {@code name} if it exists and is a long or
495 * can be coerced to a long. Returns {@code fallback} otherwise.
496 */
497 public long optLong(String name, long fallback) {
498 Object object = opt(name);
499 Long result = JSON.toLong(object);
500 return result != null ? result : fallback;
501 }
502
503 /**
504 * Returns the value mapped by {@code name} if it exists, coercing it if
505 * necessary.
506 *
507 * @throws JSONException if no such mapping exists.
508 */
509 public String getString(String name) throws JSONException {
510 Object object = get(name);
511 String result = JSON.toString(object);
512 if (result == null) {
513 throw JSON.typeMismatch(name, object, "String");
514 }
515 return result;
516 }
517
518 /**
519 * Returns the value mapped by {@code name} if it exists, coercing it if
520 * necessary. Returns the empty string if no such mapping exists.
521 */
522 public String optString(String name) {
523 return optString(name, "");
524 }
525
526 /**
527 * Returns the value mapped by {@code name} if it exists, coercing it if
528 * necessary. Returns {@code fallback} if no such mapping exists.
529 */
530 public String optString(String name, String fallback) {
531 Object object = opt(name);
532 String result = JSON.toString(object);
533 return result != null ? result : fallback;
534 }
535
536 /**
537 * Returns the value mapped by {@code name} if it exists and is a {@code
538 * JSONArray}.
539 *
540 * @throws JSONException if the mapping doesn't exist or is not a {@code
541 * JSONArray}.
542 */
543 public JSONArray getJSONArray(String name) throws JSONException {
544 Object object = get(name);
545 if (object instanceof JSONArray) {
546 return (JSONArray) object;
547 } else {
548 throw JSON.typeMismatch(name, object, "JSONArray");
549 }
550 }
551
552 /**
553 * Returns the value mapped by {@code name} if it exists and is a {@code
554 * JSONArray}. Returns null otherwise.
555 */
556 public JSONArray optJSONArray(String name) {
557 Object object = opt(name);
558 return object instanceof JSONArray ? (JSONArray) object : null;
559 }
560
561 /**
562 * Returns the value mapped by {@code name} if it exists and is a {@code
563 * JSONObject}.
564 *
565 * @throws JSONException if the mapping doesn't exist or is not a {@code
566 * JSONObject}.
567 */
568 public JSONObject getJSONObject(String name) throws JSONException {
569 Object object = get(name);
570 if (object instanceof JSONObject) {
571 return (JSONObject) object;
572 } else {
573 throw JSON.typeMismatch(name, object, "JSONObject");
574 }
575 }
576
577 /**
578 * Returns the value mapped by {@code name} if it exists and is a {@code
579 * JSONObject}. Returns null otherwise.
580 */
581 public JSONObject optJSONObject(String name) {
582 Object object = opt(name);
583 return object instanceof JSONObject ? (JSONObject) object : null;
584 }
585
586 /**
587 * Returns an array with the values corresponding to {@code names}. The
588 * array contains null for names that aren't mapped. This method returns
589 * null if {@code names} is either null or empty.
590 */
591 public JSONArray toJSONArray(JSONArray names) throws JSONException {
592 JSONArray result = new JSONArray();
593 if (names == null) {
594 return null;
595 }
596 int length = names.length();
597 if (length == 0) {
598 return null;
599 }
600 for (int i = 0; i < length; i++) {
601 String name = JSON.toString(names.opt(i));
602 result.put(opt(name));
603 }
604 return result;
605 }
606
607 /**
608 * Returns an iterator of the {@code String} names in this object. The
609 * returned iterator supports {@link Iterator#remove() remove}, which will
610 * remove the corresponding mapping from this object. If this object is
611 * modified after the iterator is returned, the iterator's behavior is
612 * undefined. The order of the keys is undefined.
613 */
614 /* Return a raw type for API compatibility */
615 public Iterator keys() {
616 return nameValuePairs.keySet().iterator();
617 }
618
619 /**
620 * Returns an array containing the string names in this object. This method
621 * returns null if this object contains no mappings.
622 */
623 public JSONArray names() {
624 return nameValuePairs.isEmpty()
625 ? null
626 : new JSONArray(new ArrayList<String>(nameValuePairs.keySet()));
627 }
628
629 /**
630 * Encodes this object as a compact JSON string, such as:
631 * <pre>{"query":"Pizza","locations":[94043,90210]}</pre>
632 */
633 @Override public String toString() {
634 try {
635 JSONStringer stringer = new JSONStringer();
636 writeTo(stringer);
637 return stringer.toString();
638 } catch (JSONException e) {
639 return null;
640 }
641 }
642
643 /**
644 * Encodes this object as a human readable JSON string for debugging, such
645 * as:
646 * <pre>
647 * {
648 * "query": "Pizza",
649 * "locations": [
650 * 94043,
651 * 90210
652 * ]
653 * }</pre>
654 *
655 * @param indentSpaces the number of spaces to indent for each level of
656 * nesting.
657 */
658 public String toString(int indentSpaces) throws JSONException {
659 JSONStringer stringer = new JSONStringer(indentSpaces);
660 writeTo(stringer);
661 return stringer.toString();
662 }
663
664 void writeTo(JSONStringer stringer) throws JSONException {
665 stringer.object();
666 for (Map.Entry<String, Object> entry : nameValuePairs.entrySet()) {
667 stringer.key(entry.getKey()).value(entry.getValue());
668 }
669 stringer.endObject();
670 }
671
672 /**
673 * Encodes the number as a JSON string.
674 *
675 * @param number a finite value. May not be {@link Double#isNaN() NaNs} or
676 * {@link Double#isInfinite() infinities}.
677 */
678 public static String numberToString(Number number) throws JSONException {
679 if (number == null) {
680 throw new JSONException("Number must be non-null");
681 }
682
683 double doubleValue = number.doubleValue();
684 JSON.checkDouble(doubleValue);
685
686 // the original returns "-0" instead of "-0.0" for negative zero
687 if (number.equals(NEGATIVE_ZERO)) {
688 return "-0";
689 }
690
691 long longValue = number.longValue();
692 if (doubleValue == (double) longValue) {
693 return Long.toString(longValue);
694 }
695
696 return number.toString();
697 }
698
699 /**
700 * Encodes {@code data} as a JSON string. This applies quotes and any
701 * necessary character escaping.
702 *
703 * @param data the string to encode. Null will be interpreted as an empty
704 * string.
705 */
706 public static String quote(String data) {
707 if (data == null) {
708 return "\"\"";
709 }
710 try {
711 JSONStringer stringer = new JSONStringer();
712 stringer.open(JSONStringer.Scope.NULL, "");
713 stringer.value(data);
714 stringer.close(JSONStringer.Scope.NULL, JSONStringer.Scope.NULL, "");
715 return stringer.toString();
716 } catch (JSONException e) {
717 throw new AssertionError();
718 }
719 }
720 }
721 1 /*
TraceSDK/src/com/mobithink/tracesdk/json/JSONStringer.java
1 /* File was deleted
2 * Copyright (C) 2010 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 package com.mobithink.tracesdk.json;
18
19 import java.util.ArrayList;
20 import java.util.Arrays;
21 import java.util.List;
22
23 // Note: this class was written without inspecting the non-free org.json sourcecode.
24
25 /**
26 * Implements {@link JSONObject#toString} and {@link JSONArray#toString}. Most
27 * application developers should use those methods directly and disregard this
28 * API. For example:<pre>
29 * JSONObject object = ...
30 * String json = object.toString();</pre>
31 *
32 * <p>Stringers only encode well-formed JSON strings. In particular:
33 * <ul>
34 * <li>The stringer must have exactly one top-level array or object.
35 * <li>Lexical scopes must be balanced: every call to {@link #array} must
36 * have a matching call to {@link #endArray} and every call to {@link
37 * #object} must have a matching call to {@link #endObject}.
38 * <li>Arrays may not contain keys (property names).
39 * <li>Objects must alternate keys (property names) and values.
40 * <li>Values are inserted with either literal {@link #value(Object) value}
41 * calls, or by nesting arrays or objects.
42 * </ul>
43 * Calls that would result in a malformed JSON string will fail with a
44 * {@link JSONException}.
45 *
46 * <p>This class provides no facility for pretty-printing (ie. indenting)
47 * output. To encode indented output, use {@link JSONObject#toString(int)} or
48 * {@link JSONArray#toString(int)}.
49 *
50 * <p>Some implementations of the API support at most 20 levels of nesting.
51 * Attempts to create more than 20 levels of nesting may fail with a {@link
52 * JSONException}.
53 *
54 * <p>Each stringer may be used to encode a single top level value. Instances of
55 * this class are not thread safe. Although this class is nonfinal, it was not
56 * designed for inheritance and should not be subclassed. In particular,
57 * self-use by overrideable methods is not specified. See <i>Effective Java</i>
58 * Item 17, "Design and Document or inheritance or else prohibit it" for further
59 * information.
60 */
61 public class JSONStringer {
62
63 /** The output data, containing at most one top-level array or object. */
64 final StringBuilder out = new StringBuilder();
65
66 /**
67 * Lexical scoping elements within this stringer, necessary to insert the
68 * appropriate separator characters (ie. commas and colons) and to detect
69 * nesting errors.
70 */
71 enum Scope {
72
73 /**
74 * An array with no elements requires no separators or newlines before
75 * it is closed.
76 */
77 EMPTY_ARRAY,
78
79 /**
80 * A array with at least one value requires a comma and newline before
81 * the next element.
82 */
83 NONEMPTY_ARRAY,
84
85 /**
86 * An object with no keys or values requires no separators or newlines
87 * before it is closed.
88 */
89 EMPTY_OBJECT,
90
91 /**
92 * An object whose most recent element is a key. The next element must
93 * be a value.
94 */
95 DANGLING_KEY,
96
97 /**
98 * An object with at least one name/value pair requires a comma and
99 * newline before the next element.
100 */
101 NONEMPTY_OBJECT,
102
103 /**
104 * A special bracketless array needed by JSONStringer.join() and
105 * JSONObject.quote() only. Not used for JSON encoding.
106 */
107 NULL,
108 }
109
110 /**
111 * Unlike the original implementation, this stack isn't limited to 20
112 * levels of nesting.
113 */
114 private final List<Scope> stack = new ArrayList<Scope>();
115
116 /**
117 * A string containing a full set of spaces for a single level of
118 * indentation, or null for no pretty printing.
119 */
120 private final String indent;
121
122 public JSONStringer() {
123 indent = null;
124 }
125
126 JSONStringer(int indentSpaces) {
127 char[] indentChars = new char[indentSpaces];
128 Arrays.fill(indentChars, ' ');
129 indent = new String(indentChars);
130 }
131
132 /**
133 * Begins encoding a new array. Each call to this method must be paired with
134 * a call to {@link #endArray}.
135 *
136 * @return this stringer.
137 */
138 public JSONStringer array() throws JSONException {
139 return open(Scope.EMPTY_ARRAY, "[");
140 }
141
142 /**
143 * Ends encoding the current array.
144 *
145 * @return this stringer.
146 */
147 public JSONStringer endArray() throws JSONException {
148 return close(Scope.EMPTY_ARRAY, Scope.NONEMPTY_ARRAY, "]");
149 }
150
151 /**
152 * Begins encoding a new object. Each call to this method must be paired
153 * with a call to {@link #endObject}.
154 *
155 * @return this stringer.
156 */
157 public JSONStringer object() throws JSONException {
158 return open(Scope.EMPTY_OBJECT, "{");
159 }
160
161 /**
162 * Ends encoding the current object.
163 *
164 * @return this stringer.
165 */
166 public JSONStringer endObject() throws JSONException {
167 return close(Scope.EMPTY_OBJECT, Scope.NONEMPTY_OBJECT, "}");
168 }
169
170 /**
171 * Enters a new scope by appending any necessary whitespace and the given
172 * bracket.
173 */
174 JSONStringer open(Scope empty, String openBracket) throws JSONException {
175 if (stack.isEmpty() && out.length() > 0) {
176 throw new JSONException("Nesting problem: multiple top-level roots");
177 }
178 beforeValue();
179 stack.add(empty);
180 out.append(openBracket);
181 return this;
182 }
183
184 /**
185 * Closes the current scope by appending any necessary whitespace and the
186 * given bracket.
187 */
188 JSONStringer close(Scope empty, Scope nonempty, String closeBracket) throws JSONException {
189 Scope context = peek();
190 if (context != nonempty && context != empty) {
191 throw new JSONException("Nesting problem");
192 }
193
194 stack.remove(stack.size() - 1);
195 if (context == nonempty) {
196 newline();
197 }
198 out.append(closeBracket);
199 return this;
200 }
201
202 /**
203 * Returns the value on the top of the stack.
204 */
205 private Scope peek() throws JSONException {
206 if (stack.isEmpty()) {
207 throw new JSONException("Nesting problem");
208 }
209 return stack.get(stack.size() - 1);
210 }
211
212 /**
213 * Replace the value on the top of the stack with the given value.
214 */
215 private void replaceTop(Scope topOfStack) {
216 stack.set(stack.size() - 1, topOfStack);
217 }
218
219 /**
220 * Encodes {@code value}.
221 *
222 * @param value a {@link JSONObject}, {@link JSONArray}, String, Boolean,
223 * Integer, Long, Double or null. May not be {@link Double#isNaN() NaNs}
224 * or {@link Double#isInfinite() infinities}.
225 * @return this stringer.
226 */
227 public JSONStringer value(Object value) throws JSONException {
228 if (stack.isEmpty()) {
229 throw new JSONException("Nesting problem");
230 }
231
232 if (value instanceof JSONArray) {
233 ((JSONArray) value).writeTo(this);
234 return this;
235
236 } else if (value instanceof JSONObject) {
237 ((JSONObject) value).writeTo(this);
238 return this;
239 }
240
241 beforeValue();
242
243 if (value == null
244 || value instanceof Boolean
245 || value == JSONObject.NULL) {
246 out.append(value);
247
248 } else if (value instanceof Number) {
249 out.append(JSONObject.numberToString((Number) value));
250
251 } else {
252 string(value.toString());
253 }
254
255 return this;
256 }
257
258 /**
259 * Encodes {@code value} to this stringer.
260 *
261 * @return this stringer.
262 */
263 public JSONStringer value(boolean value) throws JSONException {
264 if (stack.isEmpty()) {
265 throw new JSONException("Nesting problem");
266 }
267 beforeValue();
268 out.append(value);
269 return this;
270 }
271
272 /**
273 * Encodes {@code value} to this stringer.
274 *
275 * @param value a finite value. May not be {@link Double#isNaN() NaNs} or
276 * {@link Double#isInfinite() infinities}.
277 * @return this stringer.
278 */
279 public JSONStringer value(double value) throws JSONException {
280 if (stack.isEmpty()) {
281 throw new JSONException("Nesting problem");
282 }
283 beforeValue();
284 out.append(JSONObject.numberToString(value));
285 return this;
286 }
287
288 /**
289 * Encodes {@code value} to this stringer.
290 *
291 * @return this stringer.
292 */
293 public JSONStringer value(long value) throws JSONException {
294 if (stack.isEmpty()) {
295 throw new JSONException("Nesting problem");
296 }
297 beforeValue();
298 out.append(value);
299 return this;
300 }
301
302 private void string(String value) {
303 out.append("\"");
304 for (int i = 0, length = value.length(); i < length; i++) {
305 char c = value.charAt(i);
306
307 /*
308 * From RFC 4627, "All Unicode characters may be placed within the
309 * quotation marks except for the characters that must be escaped:
310 * quotation mark, reverse solidus, and the control characters
311 * (U+0000 through U+001F)."
312 */
313 switch (c) {
314 case '"':
315 case '\\':
316 case '/':
317 out.append('\\').append(c);
318 break;
319
320 case '\t':
321 out.append("\\t");
322 break;
323
324 case '\b':
325 out.append("\\b");
326 break;
327
328 case '\n':
329 out.append("\\n");
330 break;
331
332 case '\r':
333 out.append("\\r");
334 break;
335
336 case '\f':
337 out.append("\\f");
338 break;
339
340 default:
341 if (c <= 0x1F) {
342 out.append(String.format("\\u%04x", (int) c));
343 } else {
344 out.append(c);
345 }
346 break;
347 }
348
349 }
350 out.append("\"");
351 }
352
353 private void newline() {
354 if (indent == null) {
355 return;
356 }
357
358 out.append("\n");
359 for (int i = 0; i < stack.size(); i++) {
360 out.append(indent);
361 }
362 }
363
364 /**
365 * Encodes the key (property name) to this stringer.
366 *
367 * @param name the name of the forthcoming value. May not be null.
368 * @return this stringer.
369 */
370 public JSONStringer key(String name) throws JSONException {
371 if (name == null) {
372 throw new JSONException("Names must be non-null");
373 }
374 beforeKey();
375 string(name);
376 return this;
377 }
378
379 /**
380 * Inserts any necessary separators and whitespace before a name. Also
381 * adjusts the stack to expect the key's value.
382 */
383 private void beforeKey() throws JSONException {
384 Scope context = peek();
385 if (context == Scope.NONEMPTY_OBJECT) { // first in object
386 out.append(',');
387 } else if (context != Scope.EMPTY_OBJECT) { // not in an object!
388 throw new JSONException("Nesting problem");
389 }
390 newline();
391 replaceTop(Scope.DANGLING_KEY);
392 }
393
394 /**
395 * Inserts any necessary separators and whitespace before a literal value,
396 * inline array, or inline object. Also adjusts the stack to expect either a
397 * closing bracket or another element.
398 */
399 private void beforeValue() throws JSONException {
400 if (stack.isEmpty()) {
401 return;
402 }
403
404 Scope context = peek();
405 if (context == Scope.EMPTY_ARRAY) { // first in array
406 replaceTop(Scope.NONEMPTY_ARRAY);
407 newline();
408 } else if (context == Scope.NONEMPTY_ARRAY) { // another in array
409 out.append(',');
410 newline();
411 } else if (context == Scope.DANGLING_KEY) { // value for key
412 out.append(indent == null ? ":" : ": ");
413 replaceTop(Scope.NONEMPTY_OBJECT);
414 } else if (context != Scope.NULL) {
415 throw new JSONException("Nesting problem");
416 }
417 }
418
419 /**
420 * Returns the encoded JSON string.
421 *
422 * <p>If invoked with unterminated arrays or unclosed objects, this method's
423 * return value is undefined.
424 *
425 * <p><strong>Warning:</strong> although it contradicts the general contract
426 * of {@link Object#toString}, this method returns null if the stringer
427 * contains no data.
428 */
429 @Override public String toString() {
430 return out.length() == 0 ? null : out.toString();
431 }
432 }
433 1 /*
TraceSDK/src/com/mobithink/tracesdk/json/JSONTokener.java
1 /* File was deleted
2 * Copyright (C) 2010 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 package com.mobithink.tracesdk.json;
18
19 // Note: this class was written without inspecting the non-free org.json sourcecode.
20
21 /**
22 * Parses a JSON (<a href="http://www.ietf.org/rfc/rfc4627.txt">RFC 4627</a>)
23 * encoded string into the corresponding object. Most clients of
24 * this class will use only need the {@link #JSONTokener(String) constructor}
25 * and {@link #nextValue} method. Example usage: <pre>
26 * String json = "{"
27 * + " \"query\": \"Pizza\", "
28 * + " \"locations\": [ 94043, 90210 ] "
29 * + "}";
30 *
31 * JSONObject object = (JSONObject) new JSONTokener(json).nextValue();
32 * String query = object.getString("query");
33 * JSONArray locations = object.getJSONArray("locations");</pre>
34 *
35 * <p>For best interoperability and performance use JSON that complies with
36 * RFC 4627, such as that generated by {@link JSONStringer}. For legacy reasons
37 * this parser is lenient, so a successful parse does not indicate that the
38 * input string was valid JSON. All of the following syntax errors will be
39 * ignored:
40 * <ul>
41 * <li>End of line comments starting with {@code //} or {@code #} and ending
42 * with a newline character.
43 * <li>C-style comments starting with {@code /*} and ending with
44 * {@code *}{@code /}. Such comments may not be nested.
45 * <li>Strings that are unquoted or {@code 'single quoted'}.
46 * <li>Hexadecimal integers prefixed with {@code 0x} or {@code 0X}.
47 * <li>Octal integers prefixed with {@code 0}.
48 * <li>Array elements separated by {@code ;}.
49 * <li>Unnecessary array separators. These are interpreted as if null was the
50 * omitted value.
51 * <li>Key-value pairs separated by {@code =} or {@code =>}.
52 * <li>Key-value pairs separated by {@code ;}.
53 * </ul>
54 *
55 * <p>Each tokener may be used to parse a single JSON string. Instances of this
56 * class are not thread safe. Although this class is nonfinal, it was not
57 * designed for inheritance and should not be subclassed. In particular,
58 * self-use by overrideable methods is not specified. See <i>Effective Java</i>
59 * Item 17, "Design and Document or inheritance or else prohibit it" for further
60 * information.
61 */
62 public class JSONTokener {
63
64 /** The input JSON. */
65 private final String in;
66
67 /**
68 * The index of the next character to be returned by {@link #next}. When
69 * the input is exhausted, this equals the input's length.
70 */
71 private int pos;
72
73 /**
74 * @param in JSON encoded string. Null is not permitted and will yield a
75 * tokener that throws {@code NullPointerExceptions} when methods are
76 * called.
77 */
78 public JSONTokener(String in) {
79 // consume an optional byte order mark (BOM) if it exists
80 if (in != null && in.startsWith("\ufeff")) {
81 in = in.substring(1);
82 }
83 this.in = in;
84 }
85
86 /**
87 * Returns the next value from the input.
88 *
89 * @return a {@link JSONObject}, {@link JSONArray}, String, Boolean,
90 * Integer, Long, Double or {@link JSONObject#NULL}.
91 * @throws JSONException if the input is malformed.
92 */
93 public Object nextValue() throws JSONException {
94 int c = nextCleanInternal();
95 switch (c) {
96 case -1:
97 throw syntaxError("End of input");
98
99 case '{':
100 return readObject();
101
102 case '[':
103 return readArray();
104
105 case '\'':
106 case '"':
107 return nextString((char) c);
108
109 default:
110 pos--;
111 return readLiteral();
112 }
113 }
114
115 private int nextCleanInternal() throws JSONException {
116 while (pos < in.length()) {
117 int c = in.charAt(pos++);
118 switch (c) {
119 case '\t':
120 case ' ':
121 case '\n':
122 case '\r':
123 continue;
124
125 case '/':
126 if (pos == in.length()) {
127 return c;
128 }
129
130 char peek = in.charAt(pos);
131 switch (peek) {
132 case '*':
133 // skip a /* c-style comment */
134 pos++;
135 int commentEnd = in.indexOf("*/", pos);
136 if (commentEnd == -1) {
137 throw syntaxError("Unterminated comment");
138 }
139 pos = commentEnd + 2;
140 continue;
141
142 case '/':
143 // skip a // end-of-line comment
144 pos++;
145 skipToEndOfLine();
146 continue;
147
148 default:
149 return c;
150 }
151
152 case '#':
153 /*
154 * Skip a # hash end-of-line comment. The JSON RFC doesn't
155 * specify this behavior, but it's required to parse
156 * existing documents. See http://b/2571423.
157 */
158 skipToEndOfLine();
159 continue;
160
161 default:
162 return c;
163 }
164 }
165
166 return -1;
167 }
168
169 /**
170 * Advances the position until after the next newline character. If the line
171 * is terminated by "\r\n", the '\n' must be consumed as whitespace by the
172 * caller.
173 */
174 private void skipToEndOfLine() {
175 for (; pos < in.length(); pos++) {
176 char c = in.charAt(pos);
177 if (c == '\r' || c == '\n') {
178 pos++;
179 break;
180 }
181 }
182 }
183
184 /**
185 * Returns the string up to but not including {@code quote}, unescaping any
186 * character escape sequences encountered along the way. The opening quote
187 * should have already been read. This consumes the closing quote, but does
188 * not include it in the returned string.
189 *
190 * @param quote either ' or ".
191 * @throws NumberFormatException if any unicode escape sequences are
192 * malformed.
193 */
194 public String nextString(char quote) throws JSONException {
195 /*
196 * For strings that are free of escape sequences, we can just extract
197 * the result as a substring of the input. But if we encounter an escape
198 * sequence, we need to use a StringBuilder to compose the result.
199 */
200 StringBuilder builder = null;
201
202 /* the index of the first character not yet appended to the builder. */
203 int start = pos;
204
205 while (pos < in.length()) {
206 int c = in.charAt(pos++);
207 if (c == quote) {
208 if (builder == null) {
209 // a new string avoids leaking memory
210 return new String(in.substring(start, pos - 1));
211 } else {
212 builder.append(in, start, pos - 1);
213 return builder.toString();
214 }
215 }
216
217 if (c == '\\') {
218 if (pos == in.length()) {
219 throw syntaxError("Unterminated escape sequence");
220 }
221 if (builder == null) {
222 builder = new StringBuilder();
223 }
224 builder.append(in, start, pos - 1);
225 builder.append(readEscapeCharacter());
226 start = pos;
227 }
228 }
229
230 throw syntaxError("Unterminated string");
231 }
232
233 /**
234 * Unescapes the character identified by the character or characters that
235 * immediately follow a backslash. The backslash '\' should have already
236 * been read. This supports both unicode escapes "u000A" and two-character
237 * escapes "\n".
238 *
239 * @throws NumberFormatException if any unicode escape sequences are
240 * malformed.
241 */
242 private char readEscapeCharacter() throws JSONException {
243 char escaped = in.charAt(pos++);
244 switch (escaped) {
245 case 'u':
246 if (pos + 4 > in.length()) {
247 throw syntaxError("Unterminated escape sequence");
248 }
249 String hex = in.substring(pos, pos + 4);
250 pos += 4;
251 return (char) Integer.parseInt(hex, 16);
252
253 case 't':
254 return '\t';
255
256 case 'b':
257 return '\b';
258
259 case 'n':
260 return '\n';
261
262 case 'r':
263 return '\r';
264
265 case 'f':
266 return '\f';
267
268 case '\'':
269 case '"':
270 case '\\':
271 default:
272 return escaped;
273 }
274 }
275
276 /**
277 * Reads a null, boolean, numeric or unquoted string literal value. Numeric
278 * values will be returned as an Integer, Long, or Double, in that order of
279 * preference.
280 */
281 private Object readLiteral() throws JSONException {
282 String literal = nextToInternal("{}[]/\\:,=;# \t\f");
283
284 if (literal.length() == 0) {
285 throw syntaxError("Expected literal value");
286 } else if ("null".equalsIgnoreCase(literal)) {
287 return JSONObject.NULL;
288 } else if ("true".equalsIgnoreCase(literal)) {
289 return Boolean.TRUE;
290 } else if ("false".equalsIgnoreCase(literal)) {
291 return Boolean.FALSE;
292 }
293
294 /* try to parse as an integral type... */
295 if (literal.indexOf('.') == -1) {
296 int base = 10;
297 String number = literal;
298 if (number.startsWith("0x") || number.startsWith("0X")) {
299 number = number.substring(2);
300 base = 16;
301 } else if (number.startsWith("0") && number.length() > 1) {
302 number = number.substring(1);
303 base = 8;
304 }
305 try {
306 long longValue = Long.parseLong(number, base);
307 if (longValue <= Integer.MAX_VALUE && longValue >= Integer.MIN_VALUE) {
308 return (int) longValue;
309 } else {
310 return longValue;
311 }
312 } catch (NumberFormatException e) {
313 /*
314 * This only happens for integral numbers greater than
315 * Long.MAX_VALUE, numbers in exponential form (5e-10) and
316 * unquoted strings. Fall through to try floating point.
317 */
318 }
319 }
320
321 /* ...next try to parse as a floating point... */
322 try {
323 return Double.valueOf(literal);
324 } catch (NumberFormatException ignored) {
325 }
326
327 /* ... finally give up. We have an unquoted string */
328 return new String(literal); // a new string avoids leaking memory
329 }
330
331 /**
332 * Returns the string up to but not including any of the given characters or
333 * a newline character. This does not consume the excluded character.
334 */
335 private String nextToInternal(String excluded) {
336 int start = pos;
337 for (; pos < in.length(); pos++) {
338 char c = in.charAt(pos);
339 if (c == '\r' || c == '\n' || excluded.indexOf(c) != -1) {
340 return in.substring(start, pos);
341 }
342 }
343 return in.substring(start);
344 }
345
346 /**
347 * Reads a sequence of key/value pairs and the trailing closing brace '}' of
348 * an object. The opening brace '{' should have already been read.
349 */
350 private JSONObject readObject() throws JSONException {
351 JSONObject result = new JSONObject();
352
353 /* Peek to see if this is the empty object. */
354 int first = nextCleanInternal();
355 if (first == '}') {
356 return result;
357 } else if (first != -1) {
358 pos--;
359 }
360
361 while (true) {
362 Object name = nextValue();
363 if (!(name instanceof String)) {
364 if (name == null) {
365 throw syntaxError("Names cannot be null");
366 } else {
367 throw syntaxError("Names must be strings, but " + name
368 + " is of type " + name.getClass().getName());
369 }
370 }
371
372 /*
373 * Expect the name/value separator to be either a colon ':', an
374 * equals sign '=', or an arrow "=>". The last two are bogus but we
375 * include them because that's what the original implementation did.
376 */
377 int separator = nextCleanInternal();
378 if (separator != ':' && separator != '=') {
379 throw syntaxError("Expected ':' after " + name);
380 }
381 if (pos < in.length() && in.charAt(pos) == '>') {
382 pos++;
383 }
384
385 result.put((String) name, nextValue());
386
387 switch (nextCleanInternal()) {
388 case '}':
389 return result;
390 case ';':
391 case ',':
392 continue;
393 default:
394 throw syntaxError("Unterminated object");
395 }
396 }
397 }
398
399 /**
400 * Reads a sequence of values and the trailing closing brace ']' of an
401 * array. The opening brace '[' should have already been read. Note that
402 * "[]" yields an empty array, but "[,]" returns a two-element array
403 * equivalent to "[null,null]".
404 */
405 private JSONArray readArray() throws JSONException {
406 JSONArray result = new JSONArray();
407
408 /* to cover input that ends with ",]". */
409 boolean hasTrailingSeparator = false;
410
411 while (true) {
412 switch (nextCleanInternal()) {
413 case -1:
414 throw syntaxError("Unterminated array");
415 case ']':
416 if (hasTrailingSeparator) {
417 result.put(null);
418 }
419 return result;
420 case ',':
421 case ';':
422 /* A separator without a value first means "null". */
423 result.put(null);
424 hasTrailingSeparator = true;
425 continue;
426 default:
427 pos--;
428 }
429
430 result.put(nextValue());
431
432 switch (nextCleanInternal()) {
433 case ']':
434 return result;
435 case ',':
436 case ';':
437 hasTrailingSeparator = true;
438 continue;
439 default:
440 throw syntaxError("Unterminated array");
441 }
442 }
443 }
444
445 /**
446 * Returns an exception containing the given message plus the current
447 * position and the entire input string.
448 */
449 public JSONException syntaxError(String message) {
450 return new JSONException(message + this);
451 }
452
453 /**
454 * Returns the current position and the entire input string.
455 */
456 @Override public String toString() {
457 // consistent with the original implementation
458 return " at character " + pos + " of " + in;
459 }
460
461 /*
462 * Legacy APIs.
463 *
464 * None of the methods below are on the critical path of parsing JSON
465 * documents. They exist only because they were exposed by the original
466 * implementation and may be used by some clients.
467 */
468
469 /**
470 * Returns true until the input has been exhausted.
471 */
472 public boolean more() {
473 return pos < in.length();
474 }
475
476 /**
477 * Returns the next available character, or the null character '\0' if all
478 * input has been exhausted. The return value of this method is ambiguous
479 * for JSON strings that contain the character '\0'.
480 */
481 public char next() {
482 return pos < in.length() ? in.charAt(pos++) : '\0';
483 }
484
485 /**
486 * Returns the next available character if it equals {@code c}. Otherwise an
487 * exception is thrown.
488 */
489 public char next(char c) throws JSONException {
490 char result = next();
491 if (result != c) {
492 throw syntaxError("Expected " + c + " but was " + result);
493 }
494 return result;
495 }
496
497 /**
498 * Returns the next character that is not whitespace and does not belong to
499 * a comment. If the input is exhausted before such a character can be
500 * found, the null character '\0' is returned. The return value of this
501 * method is ambiguous for JSON strings that contain the character '\0'.
502 */
503 public char nextClean() throws JSONException {
504 int nextCleanInt = nextCleanInternal();
505 return nextCleanInt == -1 ? '\0' : (char) nextCleanInt;
506 }
507
508 /**
509 * Returns the next {@code length} characters of the input.
510 *
511 * <p>The returned string shares its backing character array with this
512 * tokener's input string. If a reference to the returned string may be held
513 * indefinitely, you should use {@code new String(result)} to copy it first
514 * to avoid memory leaks.
515 *
516 * @throws JSONException if the remaining input is not long enough to
517 * satisfy this request.
518 */
519 public String next(int length) throws JSONException {
520 if (pos + length > in.length()) {
521 throw syntaxError(length + " is out of bounds");
522 }
523 String result = in.substring(pos, pos + length);
524 pos += length;
525 return result;
526 }
527
528 /**
529 * Returns the {@link String#trim trimmed} string holding the characters up
530 * to but not including the first of:
531 * <ul>
532 * <li>any character in {@code excluded}
533 * <li>a newline character '\n'
534 * <li>a carriage return '\r'
535 * </ul>
536 *
537 * <p>The returned string shares its backing character array with this
538 * tokener's input string. If a reference to the returned string may be held
539 * indefinitely, you should use {@code new String(result)} to copy it first
540 * to avoid memory leaks.
541 *
542 * @return a possibly-empty string
543 */
544 public String nextTo(String excluded) {
545 if (excluded == null) {
546 throw new NullPointerException();
547 }
548 return nextToInternal(excluded).trim();
549 }
550
551 /**
552 * Equivalent to {@code nextTo(String.valueOf(excluded))}.
553 */
554 public String nextTo(char excluded) {
555 return nextToInternal(String.valueOf(excluded)).trim();
556 }
557
558 /**
559 * Advances past all input up to and including the next occurrence of
560 * {@code thru}. If the remaining input doesn't contain {@code thru}, the
561 * input is exhausted.
562 */
563 public void skipPast(String thru) {
564 int thruStart = in.indexOf(thru, pos);
565 pos = thruStart == -1 ? in.length() : (thruStart + thru.length());
566 }
567
568 /**
569 * Advances past all input up to but not including the next occurrence of
570 * {@code to}. If the remaining input doesn't contain {@code to}, the input
571 * is unchanged.
572 */
573 public char skipTo(char to) {
574 int index = in.indexOf(to, pos);
575 if (index != -1) {
576 pos = index;
577 return to;
578 } else {
579 return '\0';
580 }
581 }
582
583 /**
584 * Unreads the most recent character of input. If no input characters have
585 * been read, the input is unchanged.
586 */
587 public void back() {
588 if (--pos == -1) {
589 pos = 0;
590 }
591 }
592
593 /**
594 * Returns the integer [0..15] value for the given hex character, or -1
595 * for non-hex input.
596 *
597 * @param hex a character in the ranges [0-9], [A-F] or [a-f]. Any other
598 * character will yield a -1 result.
599 */
600 public static int dehexchar(char hex) {
601 if (hex >= '0' && hex <= '9') {
602 return hex - '0';
603 } else if (hex >= 'A' && hex <= 'F') {
604 return hex - 'A' + 10;
605 } else if (hex >= 'a' && hex <= 'f') {
606 return hex - 'a' + 10;
607 } else {
608 return -1;
609 }
610 }
611 }
612 1 /*
TraceSDK/src/com/mobithink/tracesdk/rest/client/AbstractClient.java
1 package com.mobithink.tracesdk.rest.client; File was deleted
2
3 import java.net.URI;
4 import java.text.SimpleDateFormat;
5 import java.util.Date;
6
7 import org.apache.http.cookie.Cookie;
8
9 /**
10 * Common implementation of IClient.
11 *
12 */
13 public abstract class AbstractClient implements IClient {
14
15 UriBuilder uriBuilder;
16
17 MultivaluedMap<String, String> headers = new MetadataMap<String, String>();
18
19 protected AbstractClient(URI baseUri) {
20 this.uriBuilder = new UriBuilder(baseUri);
21 }
22
23 @Override
24 public IClient type(MediaType ct) {
25 return type(ct.getTypeName());
26 }
27
28 @Override
29 public IClient type(String type) {
30 headers.putSingle(HttpHeaders.CONTENT_TYPE, type);
31 return this;
32 }
33
34 @Override
35 public IClient accept(MediaType... types) {
36 for (MediaType type : types) {
37 headers.addNoDuplicateValue(HttpHeaders.ACCEPT, type.getTypeName());
38 }
39 return this;
40 }
41
42 @Override
43 public IClient accept(String... types) {
44 for (String type : types) {
45 headers.addNoDuplicateValue(HttpHeaders.ACCEPT, type);
46 }
47 return this;
48 }
49
50 @Override
51 public IClient language(String language) {
52 headers.putSingle(HttpHeaders.CONTENT_LANGUAGE, language);
53 return this;
54 }
55
56 @Override
57 public IClient acceptLanguage(String... languages) {
58 for (String s : languages) {
59 headers.addNoDuplicateValue(HttpHeaders.ACCEPT_LANGUAGE, s);
60 }
61 return this;
62 }
63
64 @Override
65 public IClient encoding(String encoding) {
66 headers.putSingle(HttpHeaders.CONTENT_ENCODING, encoding);
67 return this;
68 }
69
70 @Override
71 public IClient acceptEncoding(String... encodings) {
72 for (String s : encodings) {
73 headers.addNoDuplicateValue(HttpHeaders.ACCEPT_ENCODING, s);
74 }
75 return this;
76 }
77
78 @Override
79 public IClient match(String tag, boolean ifNot) {
80 String hName = ifNot ? HttpHeaders.IF_NONE_MATCH : HttpHeaders.IF_MATCH;
81 headers.putSingle(hName, tag);
82 return this;
83 }
84
85 @Override
86 public IClient modified(Date date, boolean ifNot) {
87 SimpleDateFormat dateFormat = Utils.getHttpDateFormat();
88 String hName = ifNot ? HttpHeaders.IF_UNMODIFIED_SINCE : HttpHeaders.IF_MODIFIED_SINCE;
89 headers.putSingle(hName, dateFormat.format(date));
90 return this;
91 }
92
93 @Override
94 public IClient cookie(Cookie cookie) {
95 headers.addNoDuplicateValue(HttpHeaders.COOKIE, cookie.toString());
96 return this;
97 }
98
99 @Override
100 public IClient header(String name, Object... values) {
101 if (values == null) {
102 throw new IllegalArgumentException();
103 }
104 for (Object o : values) {
105 headers.addNoDuplicateValue(name, o.toString());
106 }
107 return this;
108 }
109
110 @Override
111 public IClient headers(MultivaluedMap<String, String> map) {
112 headers.putAll(map);
113 return this;
114 }
115
116 @Override
117 public IClient reset() {
118 headers.clear();
119 return this;
120 }
121
122 @Override
123 public MultivaluedMap<String, String> getHeaders() {
124 return headers;
125 }
126
127 @Override
128 public URI getBaseURI() {
129 return uriBuilder.getBaseUri();
130 }
131
132 @Override
133 public URI getCurrentURI() {
134 return uriBuilder.build();
135 }
136
137 @Override
138 public abstract Response getResponse();
139
140 }
141 1 package com.mobithink.tracesdk.rest.client;
TraceSDK/src/com/mobithink/tracesdk/rest/client/DefaultRESTClient.java
1 package com.mobithink.tracesdk.rest.client; File was deleted
2
3 import com.mobithink.tracesdk.Conf;
4
5 public class DefaultRESTClient extends RESTClient {
6
7 // private static final String BASE_URI = "http://mtafftracking.com/";
8
9 protected DefaultRESTClient(String baseUri) {
10 super(baseUri);
11 }
12
13 public static DefaultRESTClient create() {
14 return DefaultRESTClient.create(Conf.App.API_SERVER);
15 }
16
17 public static DefaultRESTClient create(String baseUri) {
18 DefaultRESTClient client = new DefaultRESTClient(baseUri);
19 DefaultRESTClient.DEBUG = true;
20 client.setRequestEntity(new RequestEntityImplString());
21 client.setEntityReader(new EntityReaderImplString());
22 client.type(MediaType.APPLICATION_FORM_URLENCODED);
23 client.accept(MediaType.TEXT_JSON);
24 client.acceptEncoding(EntityReader.ENCODING_GZIP);
25 return client;
26 }
27
28 }
29 1 package com.mobithink.tracesdk.rest.client;
TraceSDK/src/com/mobithink/tracesdk/rest/client/EntityReader.java
1 package com.mobithink.tracesdk.rest.client; File was deleted
2
3 import java.io.IOException;
4 import java.io.InputStream;
5 import java.util.zip.GZIPInputStream;
6
7 import org.apache.http.HttpEntity;
8 import org.apache.http.entity.HttpEntityWrapper;
9
10 /**
11 * Read entity content to the target type.
12 */
13 public abstract class EntityReader<T> {
14
15 public static final String ENCODING_GZIP = "gzip";
16
17 public abstract T read(HttpEntity entity);
18
19 protected String debug;
20
21 public String getDebug() {
22 return this.debug;
23 }
24
25 public static class GzipDecompressingEntity extends HttpEntityWrapper {
26
27 public GzipDecompressingEntity(final HttpEntity entity) {
28 super(entity);
29 }
30
31 @Override
32 public InputStream getContent() throws IOException, IllegalStateException {
33 // the wrapped entity's getContent() decides about repeatability
34 InputStream wrappedin = wrappedEntity.getContent();
35 return new GZIPInputStream(wrappedin);
36 }
37
38 @Override
39 public long getContentLength() {
40 // length of ungzipped content is not known
41 return -1;
42 }
43 }
44 }
45 1 package com.mobithink.tracesdk.rest.client;
TraceSDK/src/com/mobithink/tracesdk/rest/client/EntityReaderImplJSON.java
1 package com.mobithink.tracesdk.rest.client; File was deleted
2
3 import java.io.IOException;
4
5 import org.apache.http.Header;
6 import org.apache.http.HttpEntity;
7 import org.apache.http.ParseException;
8 import org.apache.http.protocol.HTTP;
9 import org.apache.http.util.EntityUtils;
10
11 import com.mobithink.tracesdk.json.JSONException;
12 import com.mobithink.tracesdk.json.JSONObject;
13
14 public class EntityReaderImplJSON extends EntityReader<JSONObject> {
15
16 @Override
17 public JSONObject read(HttpEntity entity) {
18 Header encodingHead = entity.getContentEncoding();
19 if (encodingHead != null && encodingHead.getValue() != null && encodingHead.getValue().contains(ENCODING_GZIP)) {
20 entity = new GzipDecompressingEntity(entity);
21 }
22 try {
23 String result = EntityUtils.toString(entity, HTTP.UTF_8);
24 if (RESTClient.DEBUG) {
25 this.debug = result;
26 }
27 if (result != null && result.length() >= 3) {
28 return new JSONObject(result);
29 } else {
30 return null;
31 }
32 } catch (ParseException e) {
33 e.printStackTrace();
34 } catch (JSONException e) {
35 e.printStackTrace();
36 } catch (IOException e) {
37 e.printStackTrace();
38 }
39
40 return null;
41 }
42 }
43 1 package com.mobithink.tracesdk.rest.client;
TraceSDK/src/com/mobithink/tracesdk/rest/client/EntityReaderImplString.java
1 package com.mobithink.tracesdk.rest.client; File was deleted
2
3 import java.io.IOException;
4
5 import org.apache.http.Header;
6 import org.apache.http.HttpEntity;
7 import org.apache.http.ParseException;
8 import org.apache.http.protocol.HTTP;
9 import org.apache.http.util.EntityUtils;
10
11 public class EntityReaderImplString extends EntityReader<String> {
12
13 @Override
14 public String read(HttpEntity entity) {
15 Header encodingHead = entity.getContentEncoding();
16 if (encodingHead != null && encodingHead.getValue() != null && encodingHead.getValue().contains(ENCODING_GZIP)) {
17 entity = new GzipDecompressingEntity(entity);
18 }
19 try {
20 String result = EntityUtils.toString(entity, HTTP.UTF_8);
21 if (RESTClient.DEBUG) {
22 this.debug = result;
23 }
24 return result;
25 } catch (ParseException e) {
26 e.printStackTrace();
27 } catch (IOException e) {
28 e.printStackTrace();
29 }
30
31 return null;
32 }
33 }
34 1 package com.mobithink.tracesdk.rest.client;
TraceSDK/src/com/mobithink/tracesdk/rest/client/HttpExecutor.java
1 package com.mobithink.tracesdk.rest.client; File was deleted
2
3 import java.io.IOException;
4 import java.util.List;
5 import java.util.Map;
6
7 import org.apache.http.Header;
8 import org.apache.http.HttpEntity;
9 import org.apache.http.HttpResponse;
10 import org.apache.http.client.ClientProtocolException;
11 import org.apache.http.client.methods.HttpDelete;
12 import org.apache.http.client.methods.HttpGet;
13 import org.apache.http.client.methods.HttpOptions;
14 import org.apache.http.client.methods.HttpPost;
15 import org.apache.http.client.methods.HttpPut;
16 import org.apache.http.client.methods.HttpUriRequest;
17 import org.apache.http.conn.ClientConnectionManager;
18 import org.apache.http.impl.client.DefaultHttpClient;
19 import org.apache.http.params.BasicHttpParams;
20 import org.apache.http.params.HttpConnectionParams;
21 import org.apache.http.params.HttpParams;
22
23 import android.util.Log;
24
25 public class HttpExecutor {
26
27 public static enum HTTP_METHOD {
28 GET, POST, PUT, DELETE, OPTIONS
29 };
30
31 public static final int TIMEOUT_CONNECTION = 15000;
32 public static final int TIMEOUT_SOCKET = 10000;
33
34 private DefaultHttpClient client;
35
36 /**
37 * Do send the http request.
38 *
39 * @param uriBuilder
40 * The UriBuilder
41 * @param method
42 * HTTP method
43 * @param headers
44 * Multiple values map
45 * @param requestEntity
46 * Use on POST or PUT request
47 * @param entityReader
48 * Read the entity return
49 * @return The Response instance
50 */
51 public Response execute(UriBuilder uriBuilder, HTTP_METHOD method, MultivaluedMap<String, String> headers, RequestEntity requestEntity, EntityReader<?> entityReader) {
52 client = getHttpClient();
53 HttpUriRequest request = getHttpRequest(uriBuilder, method, headers, requestEntity);
54 ResponseImpl response = new ResponseImpl();
55 try {
56 HttpResponse httpResponse = client.execute(request);
57 for (Header header : httpResponse.getAllHeaders()) {
58 response.setHeader(header.getName(), header.getValue());
59 }
60 HttpEntity entity = httpResponse.getEntity();
61 if (entity != null) {
62 response.setEntity(entityReader.read(entity));
63 response.setDebug(entityReader.getDebug());
64 }
65 int httpStatus = httpResponse.getStatusLine().getStatusCode();
66 response.setHttpStatus(httpStatus);
67
68 } catch (ClientProtocolException e) {
69 e.printStackTrace();
70 response.setErrorCode(Response.ERROR_CLIENT_NETWORK);
71 } catch (IOException e) {
72 e.printStackTrace();
73 response.setErrorCode(Response.ERROR_CLIENT_IO);
74 } catch (Exception e) {
75 e.printStackTrace();
76 response.setErrorCode(Response.ERROR_CLIENT_UNKNOWN);
77 } finally {
78 try {
79 client.getConnectionManager().shutdown();
80 } catch (Exception e) {
81 e.printStackTrace();
82 }
83 }
84 return response;
85 }
86
87 public DefaultHttpClient getHttpClient() {
88 HttpParams httpParams = new BasicHttpParams();
89 HttpConnectionParams.setConnectionTimeout(httpParams, TIMEOUT_CONNECTION);
90 HttpConnectionParams.setSoTimeout(httpParams, TIMEOUT_SOCKET);
91 return new DefaultHttpClient(httpParams);
92 }
93
94 public HttpUriRequest getHttpRequest(UriBuilder uriBuilder, HTTP_METHOD method, MultivaluedMap<String, String> headers, RequestEntity entityGenerator) {
95 switch (method) {
96 case GET:
97 return getRequest_GET(uriBuilder, headers);
98 case POST:
99 return getRequest_POST(uriBuilder, headers, entityGenerator);
100 case PUT:
101 return getRequest_PUT(uriBuilder, headers, entityGenerator);
102 case DELETE:
103 return getRequest_DELETE(uriBuilder, headers);
104 case OPTIONS:
105 return getRequest_OPTIONS(uriBuilder, headers);
106 }
107 return null;
108 }
109
110 public HttpUriRequest getRequest_GET(UriBuilder uriBuilder, MultivaluedMap<String, String> headers) {
111 HttpGet get = new HttpGet(uriBuilder.buildIncludeParams());
112 addToHeader(get, headers);
113 return get;
114 }
115
116 public HttpUriRequest getRequest_POST(UriBuilder uriBuilder, MultivaluedMap<String, String> headers, RequestEntity requestEntity) {
117 HttpPost post = new HttpPost(uriBuilder.build());
118 addToHeader(post, headers);
119 if (requestEntity != null) {
120 HttpEntity entity = requestEntity.get(uriBuilder, headers);
121 if (entity != null) {
122 post.setEntity(entity);
123 }
124 }
125 return post;
126 }
127
128 public HttpUriRequest getRequest_PUT(UriBuilder uriBuilder, MultivaluedMap<String, String> headers, RequestEntity entityGenerator) {
129 HttpPut put = new HttpPut(uriBuilder.build());
130 addToHeader(put, headers);
131 if (entityGenerator != null) {
132 HttpEntity entity = entityGenerator.get(uriBuilder, headers);
133 if (entity != null) {
134 put.setEntity(entity);
135 }
136 }
137 return put;
138 }
139
140 public HttpUriRequest getRequest_DELETE(UriBuilder uriBuilder, MultivaluedMap<String, String> headers) {
141 HttpDelete delete = new HttpDelete(uriBuilder.buildIncludeParams());
142 addToHeader(delete, headers);
143 return delete;
144 }
145
146 public HttpUriRequest getRequest_OPTIONS(UriBuilder uriBuilder, MultivaluedMap<String, String> headers) {
147 HttpOptions opt = new HttpOptions(uriBuilder.buildIncludeParams());
148 addToHeader(opt, headers);
149 return opt;
150 }
151
152 private void addToHeader(HttpUriRequest request, MultivaluedMap<String, String> headers) {
153 if (headers != null && headers.size() > 0) {
154 for (Map.Entry<String, List<String>> entry : headers.entrySet()) {
155 String k = entry.getKey();
156 for (String v : entry.getValue()) {
157 request.addHeader(k, v);
158 }
159 }
160 }
161 }
162
163 public void close() {
164 if (client != null) {
165 try {
166 ClientConnectionManager manager = client.getConnectionManager();
167 if (manager != null) {
168 manager.shutdown();
169 }
170 } catch (Exception e) {
171 e.printStackTrace();
172 }
173 }
174 }
175 }
176 1 package com.mobithink.tracesdk.rest.client;
TraceSDK/src/com/mobithink/tracesdk/rest/client/HttpHeaders.java
1 package com.mobithink.tracesdk.rest.client; File was deleted
2
3 import java.util.List;
4 import java.util.Locale;
5 import java.util.Map;
6
7 import org.apache.http.cookie.Cookie;
8
9 public abstract interface HttpHeaders {
10 public static final String ACCEPT = "Accept";
11 public static final String ACCEPT_CHARSET = "Accept-Charset";
12 public static final String ACCEPT_ENCODING = "Accept-Encoding";
13 public static final String ACCEPT_LANGUAGE = "Accept-Language";
14 public static final String AUTHORIZATION = "Authorization";
15 public static final String CACHE_CONTROL = "Cache-Control";
16 public static final String CONTENT_ENCODING = "Content-Encoding";
17 public static final String CONTENT_LANGUAGE = "Content-Language";
18 public static final String CONTENT_LENGTH = "Content-Length";
19 public static final String CONTENT_LOCATION = "Content-Location";
20 public static final String CONTENT_TYPE = "Content-Type";
21 public static final String DATE = "Date";
22 public static final String ETAG = "ETag";
23 public static final String EXPIRES = "Expires";
24 public static final String HOST = "Host";
25 public static final String IF_MATCH = "If-Match";
26 public static final String IF_MODIFIED_SINCE = "If-Modified-Since";
27 public static final String IF_NONE_MATCH = "If-None-Match";
28 public static final String IF_UNMODIFIED_SINCE = "If-Unmodified-Since";
29 public static final String LAST_MODIFIED = "Last-Modified";
30 public static final String LOCATION = "Location";
31 public static final String USER_AGENT = "User-Agent";
32 public static final String VARY = "Vary";
33 public static final String WWW_AUTHENTICATE = "WWW-Authenticate";
34 public static final String COOKIE = "Cookie";
35 public static final String SET_COOKIE = "Set-Cookie";
36
37 public abstract List<String> getRequestHeader(String paramString);
38
39 public abstract Map<String, String> getRequestHeaders();
40
41 public abstract List<MediaType> getAcceptableMediaTypes();
42
43 public abstract List<Locale> getAcceptableLanguages();
44
45 public abstract MediaType getMediaType();
46
47 public abstract Locale getLanguage();
48
49 public abstract Map<String, Cookie> getCookies();
50 }
TraceSDK/src/com/mobithink/tracesdk/rest/client/IClient.java
1 /** File was deleted
2 * Licensed to the Apache Software Foundation (ASF) under one
3 * or more contributor license agreements. See the NOTICE file
4 * distributed with this work for additional information
5 * regarding copyright ownership. The ASF licenses this file
6 * to you under the Apache License, Version 2.0 (the
7 * "License"); you may not use this file except in compliance
8 * with the License. You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing,
13 * software distributed under the License is distributed on an
14 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 * KIND, either express or implied. See the License for the
16 * specific language governing permissions and limitations
17 * under the License.
18 */
19 package com.mobithink.tracesdk.rest.client;
20
21 import java.net.URI;
22 import java.util.Date;
23
24 import org.apache.http.cookie.Cookie;
25
26 /**
27 * Represents common proxy and http-centric client capabilities
28 *
29 */
30 public interface IClient {
31
32 /**
33 * sets HTTP Content-Type header
34 * @param MediaType representing Content-Type value
35 * @return the updated Client
36 */
37 IClient type(MediaType ct);
38
39 /**
40 * sets HTTP Content-Type header
41 * @param type Content-Type value
42 * @return the updated Client
43 */
44 IClient type(String type);
45
46 /**
47 * sets HTTP Accept header
48 * @param types list of MediaTypes representing Accept header values
49 * @return the updated Client
50 */
51 IClient accept(MediaType... types);
52
53 /**
54 * sets HTTP Accept header
55 * @param types list of Accept header values
56 * @return the updated Client
57 */
58 IClient accept(String... types);
59
60 /**
61 * sets HTTP Content-Language header
62 * @param language Content-Language header value
63 * @return the updated Client
64 */
65 IClient language(String language);
66
67 /**
68 * sets HTTP Accept-Language header
69 * @param languages list of Accept-Language header values
70 * @return the updated Client
71 */
72 IClient acceptLanguage(String ...languages);
73
74 /**
75 * sets HTTP Content-Encoding header
76 * @param encoding Content-Encoding header value
77 * @return the updated Client
78 */
79 IClient encoding(String encoding);
80
81 /**
82 * sets HTTP Accept-Encoding header
83 * @param encodings list of Accept-Encoding header value
84 * @return the updated Client
85 */
86 IClient acceptEncoding(String ...encodings);
87
88 /**
89 * sets HTTP If-Match or If-None-Match header
90 * @param tag ETag value
91 * @param ifNot if true then If-None-Match is set, If-Match otherwise
92 * @return the updated Client
93 */
94 IClient match(String tag, boolean ifNot);
95
96 /**
97 * sets HTTP If-Modified-Since or If-Unmodified-Since header
98 * @param date Date value, will be formated as "EEE, dd MMM yyyy HH:mm:ss zzz"
99 * @param ifNot if true then If-Unmodified-Since is set, If-Modified-Since otherwise
100 * @return the updated Client
101 */
102 IClient modified(Date date, boolean ifNot);
103
104 /**
105 * sets HTTP Cookie header
106 * @param cookie Cookie value
107 * @return the updated Client
108 */
109 IClient cookie(Cookie cookie);
110
111 /**
112 * Sets arbitrary HTTP Header
113 * @param name header name
114 * @param values list of header values
115 * @return the updated Client
116 */
117 IClient header(String name, Object... values);
118
119 /**
120 * Sets HTTP Headers
121 * @param map headers
122 * @return the updated Client
123 */
124 IClient headers(MultivaluedMap<String, String> map);
125
126 /**
127 * Resets the headers and response state if any
128 * @return the updated Client
129 */
130 IClient reset();
131
132 /**
133 * Gets the copy of request headers
134 * @return request headers
135 */
136 MultivaluedMap<String, String> getHeaders();
137
138 /**
139 * Gets the base URI this Client has been intialized with
140 * @return base URI
141 */
142 URI getBaseURI();
143
144 /**
145 * Gets the current URI this Client is working with
146 * @return current URI
147 */
148 URI getCurrentURI();
149
150 /**
151 * Gets the response state if any
152 * @return Response response
153 */
154 Response getResponse();
155 }
156 1 /**
TraceSDK/src/com/mobithink/tracesdk/rest/client/MediaType.java
1 package com.mobithink.tracesdk.rest.client; File was deleted
2
3 public class MediaType {
4
5 public static final MediaType TEXT_JSON = new MediaType("text/json");
6 public static final MediaType TEXT_XML = new MediaType("text/xml");
7 public static final MediaType TEXT_HTML = new MediaType("text/html");
8 public static final MediaType APPLICATION_FORM_URLENCODED = new MediaType("application/x-www-form-urlencoded");
9 public static final MediaType APPLICATION_PROTOBUF = new MediaType("application/protobuf");
10
11 private String type;
12
13 protected MediaType(String type) {
14 this.type = type;
15 }
16
17 public String getTypeName() {
18 return this.type;
19 }
20
21 public String toString() {
22 return this.type;
23 }
24
25 public boolean equals(String typeName) {
26 return this.type.equalsIgnoreCase(typeName);
27 }
28 }
29 1 package com.mobithink.tracesdk.rest.client;
TraceSDK/src/com/mobithink/tracesdk/rest/client/MetadataMap.java
1 /** File was deleted
2 * Licensed to the Apache Software Foundation (ASF) under one
3 * or more contributor license agreements. See the NOTICE file
4 * distributed with this work for additional information
5 * regarding copyright ownership. The ASF licenses this file
6 * to you under the Apache License, Version 2.0 (the
7 * "License"); you may not use this file except in compliance
8 * with the License. You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing,
13 * software distributed under the License is distributed on an
14 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 * KIND, either express or implied. See the License for the
16 * specific language governing permissions and limitations
17 * under the License.
18 */
19
20 package com.mobithink.tracesdk.rest.client;
21
22 import java.util.ArrayList;
23 import java.util.Arrays;
24 import java.util.Collection;
25 import java.util.Collections;
26 import java.util.Comparator;
27 import java.util.LinkedHashMap;
28 import java.util.List;
29 import java.util.Map;
30 import java.util.Set;
31 import java.util.TreeSet;
32
33 public class MetadataMap<K, V> implements MultivaluedMap<K, V> {
34
35 private boolean caseInsensitive;
36 private Map<K, List<V>> m;
37
38 public MetadataMap() {
39 this.m = new LinkedHashMap<K, List<V>>();
40 }
41
42 public MetadataMap(int size) {
43 this.m = new LinkedHashMap<K, List<V>>(size);
44 }
45
46 public MetadataMap(Map<K, List<V>> store) {
47 this(store, false, false);
48 }
49
50 public MetadataMap(boolean readOnly, boolean caseInsensitive) {
51 this(null, readOnly, caseInsensitive);
52 }
53
54 public MetadataMap(Map<K, List<V>> store, boolean readOnly, boolean caseInsensitive) {
55
56 this(store, true, readOnly, caseInsensitive);
57
58 }
59
60 // TODO: Review the use of this constructor,
61 // refactor the code, copyStore and readOnly are duplicates
62 public MetadataMap(Map<K, List<V>> store, boolean copyStore, boolean readOnly, boolean caseInsensitive) {
63
64 if (copyStore) {
65 this.m = new LinkedHashMap<K, List<V>>();
66 if (store != null) {
67 for (Map.Entry<K, List<V>> entry : store.entrySet()) {
68 List<V> values = new ArrayList<V>(entry.getValue());
69 m.put(entry.getKey(), readOnly ? Collections.unmodifiableList(values) : values);
70 }
71 }
72 if (readOnly) {
73 this.m = Collections.unmodifiableMap(m);
74 }
75 } else {
76 this.m = store;
77 }
78 this.caseInsensitive = caseInsensitive;
79
80 }
81
82 public void add(K key, V value) {
83 addValue(key, value, true);
84 }
85
86 private void addValue(K key, V value, boolean last) {
87 List<V> data = getList(key);
88 if (last) {
89 data.add(value);
90 } else {
91 data.add(0, value);
92 }
93 }
94
95 private List<V> getList(K key) {
96 List<V> data = this.get(key);
97 if (data == null) {
98 data = new ArrayList<V>();
99 m.put(key, data);
100 }
101 return data;
102 }
103
104 public V getFirst(K key) {
105 List<V> data = this.get(key);
106 return data == null ? null : data.get(0);
107 }
108
109 public void putSingle(K key, V value) {
110 List<V> data = new ArrayList<V>();
111 data.add(value);
112 this.put(key, data);
113 }
114
115 public void clear() {
116 m.clear();
117 }
118
119 public boolean containsKey(Object key) {
120 if (!caseInsensitive) {
121 return m.containsKey(key);
122 }
123 return getMatchingKey(key) != null;
124 }
125
126 public boolean containsValue(Object value) {
127 return m.containsValue(value);
128 }
129
130 public Set<Entry<K, List<V>>> entrySet() {
131 return m.entrySet();
132 }
133
134 public List<V> get(Object key) {
135 if (!caseInsensitive) {
136 return m.get(key);
137 }
138 K realKey = getMatchingKey(key);
139 return realKey == null ? null : m.get(realKey);
140 }
141
142 private K getMatchingKey(Object key) {
143 for (K entry : m.keySet()) {
144 if (entry.toString().equalsIgnoreCase(key.toString())) {
145 return entry;
146 }
147 }
148 return null;
149 }
150
151 public boolean isEmpty() {
152 return m.isEmpty();
153 }
154
155 public Set<K> keySet() {
156 if (!caseInsensitive) {
157 return m.keySet();
158 } else {
159 Set<K> set = new TreeSet<K>(new KeyComparator<K>());
160 set.addAll(m.keySet());
161 return set;
162 }
163 }
164
165 public List<V> put(K key, List<V> value) {
166 K realKey = !caseInsensitive ? key : getMatchingKey(key);
167 return m.put(realKey == null ? key : realKey, value);
168 }
169
170 public void putAll(Map<? extends K, ? extends List<V>> map) {
171 if (!caseInsensitive) {
172 m.putAll(map);
173 } else {
174 for (Map.Entry<? extends K, ? extends List<V>> entry : map.entrySet()) {
175 this.put(entry.getKey(), entry.getValue());
176 }
177 }
178 }
179
180 public List<V> remove(Object key) {
181 if (caseInsensitive) {
182 K realKey = getMatchingKey(key);
183 return m.remove(realKey == null ? key : realKey);
184 } else {
185 return m.remove(key);
186 }
187 }
188
189 public int size() {
190 return m.size();
191 }
192
193 public Collection<List<V>> values() {
194 return m.values();
195 }
196
197 @Override
198 public int hashCode() {
199 return m.hashCode();
200 }
201
202 @Override
203 public boolean equals(Object o) {
204 return m.equals(o);
205 }
206
207 public String toString() {
208 return m.toString();
209 }
210
211 private static class KeyComparator<K> implements Comparator<K> {
212
213 public int compare(K k1, K k2) {
214 String s1 = k1.toString();
215 String s2 = k2.toString();
216 return s1.compareToIgnoreCase(s2);
217 }
218
219 }
220
221 public void addAll(K key, V... newValues) {
222 this.addAllValues(key, Arrays.asList(newValues));
223 }
224
225 public void addAll(K key, List<V> newValues) {
226 this.addAllValues(key, newValues);
227 }
228
229 private void addAllValues(K key, List<V> newValues) {
230 if (newValues == null) {
231 throw new NullPointerException("List is empty");
232 }
233 if (newValues.isEmpty()) {
234 return;
235 }
236 getList(key).addAll(newValues);
237 }
238
239 public void addFirst(K key, V value) {
240 addValue(key, value, false);
241 }
242
243 public boolean equalsIgnoreValueOrder(MultivaluedMap<K, V> map) {
244 Set<K> mapKeys = map.keySet();
245 if (mapKeys.size() != m.keySet().size()) {
246 return false;
247 }
248
249 for (K key : mapKeys) {
250 List<V> localValues = this.get(key);
251 List<V> mapValues = map.get(key);
252 if (localValues == null || localValues.size() != mapValues.size() || !localValues.containsAll(mapValues)) {
253 return false;
254 }
255 }
256 return true;
257 }
258
259 @Override
260 public void addNoDuplicateValue(K key, V value) {
261 if (!isDuplicate(key, value)) {
262 add(key, value);
263 }
264 }
265
266 private boolean isDuplicate(K key, V value) {
267 List<V> values = get(key);
268 return values != null && values.contains(value) ? true : false;
269 }
270 }
271 1 /**
TraceSDK/src/com/mobithink/tracesdk/rest/client/MultivaluedMap.java
1 package com.mobithink.tracesdk.rest.client; File was deleted
2
3 import java.util.List;
4 import java.util.Map;
5
6 public abstract interface MultivaluedMap<K, V> extends Map<K, List<V>> {
7
8 public abstract void putSingle(K paramK, V paramV);
9
10 public abstract void add(K paramK, V paramV);
11
12 public abstract void addNoDuplicateValue(K paramK, V paramV);
13
14 public abstract V getFirst(K paramK);
15 }
TraceSDK/src/com/mobithink/tracesdk/rest/client/RESTClient.java
1 package com.mobithink.tracesdk.rest.client; File was deleted
2
3 import java.net.URI;
4 import java.util.Date;
5
6 import org.apache.http.cookie.Cookie;
7
8 import com.mobithink.tracesdk.rest.client.HttpExecutor.HTTP_METHOD;
9
10 public class RESTClient extends AbstractClient {
11
12 public static boolean DEBUG = false;
13
14 RequestEntity requestEntity = new RequestEntityImplString();
15
16 EntityReader<?> entityReader = new EntityReaderImplJSON();
17
18 HttpExecutor httpExecutor;
19
20 Response response;
21
22 public static RESTClient create(String baseUri) {
23 return new RESTClient(baseUri);
24 }
25
26 public static RESTClient create(URI baseUri) {
27 return new RESTClient(baseUri);
28 }
29
30 protected RESTClient(String baseUri) {
31 super(URI.create(baseUri));
32 }
33
34 protected RESTClient(URI baseUri) {
35 super(baseUri);
36 }
37
38 public RESTClient path(String path) {
39 uriBuilder.addPath(path);
40 return this;
41 }
42
43 public RESTClient query(String key, Object value) {
44 uriBuilder.addQuery(key, value);
45 return this;
46 }
47
48 public Response get() {
49 handle(HTTP_METHOD.GET);
50 return getResponse();
51 }
52
53 public Response post() {
54 handle(HTTP_METHOD.POST);
55 return getResponse();
56 }
57
58 public Response put() {
59 handle(HTTP_METHOD.PUT);
60 return getResponse();
61 }
62
63 public Response delete() {
64 handle(HTTP_METHOD.DELETE);
65 return getResponse();
66 }
67
68 /**
69 * Do handle request
70 *
71 * @param method
72 */
73 private void handle(HTTP_METHOD method) {
74 httpExecutor = new HttpExecutor();
75 this.response = httpExecutor.execute(uriBuilder, method, headers, requestEntity, entityReader);
76 }
77
78 @Override
79 public Response getResponse() {
80 return this.response;
81 }
82
83 @Override
84 public RESTClient type(MediaType ct) {
85 return (RESTClient) super.type(ct);
86 }
87
88 @Override
89 public RESTClient type(String type) {
90 return (RESTClient) super.type(type);
91 }
92
93 @Override
94 public RESTClient accept(MediaType... types) {
95 return (RESTClient) super.accept(types);
96 }
97
98 @Override
99 public RESTClient accept(String... types) {
100 return (RESTClient) super.accept(types);
101 }
102
103 @Override
104 public RESTClient language(String language) {
105 return (RESTClient) super.language(language);
106 }
107
108 @Override
109 public RESTClient acceptLanguage(String... languages) {
110 return (RESTClient) super.acceptLanguage(languages);
111 }
112
113 @Override
114 public RESTClient encoding(String encoding) {
115 return (RESTClient) super.encoding(encoding);
116 }
117
118 @Override
119 public RESTClient acceptEncoding(String... encodings) {
120 return (RESTClient) super.acceptEncoding(encodings);
121 }
122
123 @Override
124 public RESTClient match(String tag, boolean ifNot) {
125 return (RESTClient) super.match(tag, ifNot);
126 }
127
128 @Override
129 public RESTClient modified(Date date, boolean ifNot) {
130 return (RESTClient) super.modified(date, ifNot);
131 }
132
133 @Override
134 public RESTClient cookie(Cookie cookie) {
135 return (RESTClient) super.cookie(cookie);
136 }
137
138 @Override
139 public RESTClient header(String name, Object... values) {
140 return (RESTClient) super.header(name, values);
141 }
142
143 @Override
144 public RESTClient headers(MultivaluedMap<String, String> map) {
145 return (RESTClient) super.headers(map);
146 }
147
148 @Override
149 public RESTClient reset() {
150 return (RESTClient) super.reset();
151 }
152
153 /**
154 * set a RequestEntity that the request will format params.
155 *
156 * @param requestEntity
157 * @return
158 */
159 public RESTClient setRequestEntity(RequestEntity requestEntity) {
160 this.requestEntity = requestEntity;
161 return this;
162 }
163
164 /**
165 * Set an EntityReader which to read the response entity and parse it to the target format.
166 *
167 * @param reader
168 * @return
169 */
170 public RESTClient setEntityReader(EntityReader<?> reader) {
171 this.entityReader = reader;
172 return this;
173 }
174
175 public void close() {
176 if (httpExecutor != null) {
177 httpExecutor.close();
178 }
179 }
180 }
181 1 package com.mobithink.tracesdk.rest.client;
TraceSDK/src/com/mobithink/tracesdk/rest/client/RequestEntity.java
1 package com.mobithink.tracesdk.rest.client; File was deleted
2
3 import java.io.UnsupportedEncodingException;
4
5 import org.apache.http.HttpEntity;
6 import org.apache.http.entity.StringEntity;
7 import org.apache.http.protocol.HTTP;
8
9 public abstract class RequestEntity {
10
11 public abstract HttpEntity get(UriBuilder uriBuilder, MultivaluedMap<String, String> headers);
12
13 protected StringEntity getStringEntity(String params) {
14 try {
15 return new StringEntity(params, HTTP.UTF_8);
16 } catch (UnsupportedEncodingException e) {
17 e.printStackTrace();
18 }
19 return null;
20 }
21 }
22 1 package com.mobithink.tracesdk.rest.client;
TraceSDK/src/com/mobithink/tracesdk/rest/client/RequestEntityImplJSON.java
1 package com.mobithink.tracesdk.rest.client; File was deleted
2
3 import org.apache.http.HttpEntity;
4
5 import android.util.Log;
6
7 import com.mobithink.tracesdk.json.JSONObject;
8
9 public class RequestEntityImplJSON extends RequestEntity {
10
11 @Override
12 public HttpEntity get(UriBuilder uriBuilder, MultivaluedMap<String, String> headers) {
13 String entityStr = new JSONObject(uriBuilder.getQuery()).toString();
14 return getStringEntity(entityStr);
15 }
16 }
17 1 package com.mobithink.tracesdk.rest.client;
TraceSDK/src/com/mobithink/tracesdk/rest/client/RequestEntityImplString.java
1 package com.mobithink.tracesdk.rest.client; File was deleted
2
3 import org.apache.http.HttpEntity;
4
5 import android.util.Log;
6
7 public class RequestEntityImplString extends RequestEntity {
8
9 @Override
10 public HttpEntity get(UriBuilder uriBuilder, MultivaluedMap<String, String> headers) {
11 String params = uriBuilder.assambleParams();
12 Log.d("RequestEntityImplString", "params str:"+params);
13 return getStringEntity(params);
14 }
15
16 }
17 1 package com.mobithink.tracesdk.rest.client;
TraceSDK/src/com/mobithink/tracesdk/rest/client/Response.java
1 package com.mobithink.tracesdk.rest.client; File was deleted
2
3 public abstract class Response {
4
5 public static final int ERROR_CLIENT_NETWORK = -100;
6 public static final int ERROR_CLIENT_IO = -200;
7 public static final int ERROR_CLIENT_UNKNOWN = -300;
8
9 public abstract Object getEntity();
10
11 public abstract int getHttpStatus();
12
13 public abstract int getErrorCode();
14
15 public abstract MultivaluedMap<String, Object> getHeaderMetadata();
16
17 // ///////////////////////////////////////////////
18
19 public abstract String getContentType();
20
21 public abstract String getContentEncoding();
22
23 public abstract String getContentLanguage();
24
25 public abstract String getLocation();
26
27 public abstract String getContentLocation();
28
29 public abstract String getETag();
30
31 public abstract String getLastModified();
32
33 public abstract String getCacheControl();
34
35 public abstract String getExpires();
36
37 public abstract long getExpiresTime();
38
39 public abstract String getCookie();
40
41 public abstract String getDebug();
42
43 }
44 1 package com.mobithink.tracesdk.rest.client;
TraceSDK/src/com/mobithink/tracesdk/rest/client/ResponseImpl.java
1 package com.mobithink.tracesdk.rest.client; File was deleted
2
3 import java.text.ParseException;
4 import java.text.SimpleDateFormat;
5 import java.util.Date;
6
7 public final class ResponseImpl extends Response {
8
9 private int httpStatus;
10 private int errorCode;
11 private Object entity;
12 private MultivaluedMap<String, Object> metadata = new MetadataMap<String, Object>();
13
14 private String debug;
15
16 public void setDebug(String debugStr) {
17 this.debug = debugStr;
18 }
19
20 public String getDebug() {
21 return this.debug;
22 }
23
24 @Override
25 public Object getEntity() {
26 return this.entity;
27 }
28
29 @Override
30 public int getHttpStatus() {
31 return this.httpStatus;
32 }
33
34 @Override
35 public MultivaluedMap<String, Object> getHeaderMetadata() {
36 return this.metadata;
37 }
38
39 @Override
40 public int getErrorCode() {
41 return this.errorCode;
42 }
43
44 protected void setHttpStatus(int s) {
45 this.httpStatus = s;
46 }
47
48 public void setErrorCode(int code) {
49 this.errorCode = code;
50 }
51
52 protected void setEntity(Object paramObject) {
53 this.entity = paramObject;
54 }
55
56 @Override
57 public String getContentType() {
58 return getHeaderValue(HttpHeaders.CONTENT_TYPE).toString();
59 }
60
61 @Override
62 public String getContentEncoding() {
63 return getHeaderValue(HttpHeaders.CONTENT_ENCODING).toString();
64 }
65
66 @Override
67 public String getContentLanguage() {
68 return getHeaderValue(HttpHeaders.CONTENT_LANGUAGE).toString();
69 }
70
71 @Override
72 public String getLocation() {
73 return getHeaderValue(HttpHeaders.LOCATION).toString();
74 }
75
76 @Override
77 public String getContentLocation() {
78 return getHeaderValue(HttpHeaders.CONTENT_LOCATION).toString();
79 }
80
81 @Override
82 public String getETag() {
83 return getHeaderValue(HttpHeaders.ETAG).toString();
84 }
85
86 @Override
87 public String getLastModified() {
88 return getHeaderValue(HttpHeaders.LAST_MODIFIED).toString();
89 }
90
91 @Override
92 public String getCacheControl() {
93 return getHeaderValue(HttpHeaders.CACHE_CONTROL).toString();
94 }
95
96 @Override
97 public String getExpires() {
98 return getHeaderValue(HttpHeaders.EXPIRES).toString();
99 }
100
101 @Override
102 public long getExpiresTime() {
103 String ex = getHeaderValue("Cache-Expires").toString();
104 if (ex == null || ex.length() == 0) {
105 return 0;
106 }
107 try {
108 return Long.valueOf(ex) * 1000;
109 } catch (Exception e) {
110 return 0;
111 }
112 }
113
114 @Override
115 public String getCookie() {
116 return getHeaderValue(HttpHeaders.SET_COOKIE).toString();
117 }
118
119 public void setHeader(String name, String value) {
120 if (value == null) {
121 metadata.remove(name);
122 } else {
123 metadata.putSingle(name, value.toString());
124 }
125 }
126
127 private Object getHeaderValue(String name) {
128 Object value = metadata.getFirst(name);
129 if (value == null) {
130 return "";
131 }
132 return value;
133 }
134
135 public String toHttpDate(Date date) {
136 SimpleDateFormat format = Utils.getHttpDateFormat();
137 return format.format(date);
138 }
139
140 public Date toDate(String dateOfGMT) {
141 SimpleDateFormat format = Utils.getHttpDateFormat();
142 try {
143 return format.parse(dateOfGMT);
144 } catch (ParseException e) {
145 e.printStackTrace();
146 return null;
147 }
148 }
149
150 }
TraceSDK/src/com/mobithink/tracesdk/rest/client/UriBuilder.java
1 package com.mobithink.tracesdk.rest.client; File was deleted
2
3 import java.io.UnsupportedEncodingException;
4 import java.net.URI;
5 import java.net.URLEncoder;
6 import java.util.ArrayList;
7 import java.util.Iterator;
8 import java.util.LinkedHashMap;
9 import java.util.List;
10 import java.util.Map.Entry;
11
12 import android.util.Log;
13
14 public class UriBuilder {
15
16 private URI baseUri;
17 private List<String> paths = new ArrayList<String>();
18 private LinkedHashMap<String, Object> query = new LinkedHashMap<String, Object>();
19
20 public UriBuilder(URI uri) {
21 this.baseUri = uri;
22 }
23
24 public void addPath(String path) {
25 paths.add(path);
26 }
27
28 public void addQuery(String key, Object value) {
29 query.put(key, value);
30 }
31
32 public URI getBaseUri() {
33 return baseUri;
34 }
35
36 public URI build() {
37 return URI.create(baseUri.toString() + assamblePath());
38 }
39
40 public URI buildIncludeParams() {
41 return URI.create(baseUri.toString() + assamblePathAndParams());
42 }
43
44 private String assamblePathAndParams() {
45 StringBuilder strBuilder = new StringBuilder(assamblePath());
46 String params = assambleParams();
47 if (params != null && params.length() > 0) {
48 strBuilder.append("?").append(params);
49 }
50 return strBuilder.toString();
51 }
52
53 private String assamblePath() {
54 if (paths != null && paths.size() > 0) {
55 StringBuilder strBuilder = new StringBuilder();
56 Iterator<String> iter = paths.iterator();
57 while (iter.hasNext()) {
58 strBuilder.append("/").append(iter.next());
59 }
60 return strBuilder.toString();
61 }
62 return "";
63 }
64
65 public String assambleParams() {
66 if (query != null && query.size() > 0) {
67 StringBuilder strBuilder = new StringBuilder();
68 int i = 0;
69 for (Entry<String, Object> entry : query.entrySet()) {
70 if (i > 0) {
71 strBuilder.append("&");
72 }
73 try {
74 Object v = entry.getValue();
75 strBuilder.append(entry.getKey()).append("=").append(URLEncoder.encode(v == null ? "" : v.toString(), "utf-8"));
76 } catch (UnsupportedEncodingException e) {
77 e.printStackTrace();
78 }
79 i++;
80 }
81 return strBuilder.toString();
82 }
83 return "";
84 }
85
86 public LinkedHashMap<String, Object> getQuery() {
87 return this.query;
88 }
89 }
90 1 package com.mobithink.tracesdk.rest.client;
TraceSDK/src/com/mobithink/tracesdk/rest/client/Utils.java
1 package com.mobithink.tracesdk.rest.client; File was deleted
2
3 import java.text.ParseException;
4 import java.text.SimpleDateFormat;
5 import java.util.Date;
6 import java.util.Locale;
7 import java.util.TimeZone;
8
9 public class Utils {
10
11 public static SimpleDateFormat getHttpDateFormat() {
12 SimpleDateFormat dateFormat = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss zzz", Locale.US);
13 TimeZone tZone = TimeZone.getTimeZone("GMT");
14 dateFormat.setTimeZone(tZone);
15 return dateFormat;
16 }
17
18 public static long GMT2LocaleTime(long time_GMT) {
19 try {
20 SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.US);
21 String timeStr_GMT = dateFormat.format(new Date(time_GMT));
22 dateFormat.setTimeZone(TimeZone.getTimeZone("GMT"));
23 Date date = dateFormat.parse(timeStr_GMT);
24
25 dateFormat.setTimeZone(TimeZone.getDefault());
26 String timeStr_locale = dateFormat.format(date);
27 return dateFormat.parse(timeStr_locale).getTime();
28 } catch (ParseException e) {
29 e.printStackTrace();
30 }
31
32 return 0;
33 }
34
35 public static long getTime(String timeStr) {
36 SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.US);
37 try {
38 return dateFormat.parse(timeStr).getTime();
39 } catch (ParseException e) {
40 e.printStackTrace();
41 }
42 return 0;
43 }
44 }
45 1 package com.mobithink.tracesdk.rest.client;
TraceSDK/src/com/mobithink/tracesdk/utils/LogUtil.java
1 package com.mobithink.tracesdk.utils; File was deleted
2
3 import com.mobithink.tracesdk.Conf;
4
5 import android.util.Log;
6
7 public class LogUtil {
8
9 public static void d(String tag, String msg) {
10 if (Conf.Env.LOG_ON)
11 Log.d(tag, msg);
12 }
13
14 public static void i(String tag, String msg) {
15 if (Conf.Env.LOG_ON)
16 Log.i(tag, msg);
17 }
18
19 public static void w(String tag, String msg) {
20 if (Conf.Env.LOG_ON)
21 Log.w(tag, msg);
22 }
23
24 public static void e(String tag, String msg) {
25 if (Conf.Env.LOG_ON)
26 Log.e(tag, msg);
27 }
28 }
29 1 package com.mobithink.tracesdk.utils;
TraceSDK/src/com/mobithink/tracesdk/utils/Util.java
1 package com.mobithink.tracesdk.utils; File was deleted
2
3 import java.security.MessageDigest;
4 import java.security.NoSuchAlgorithmException;
5 import java.util.UUID;
6
7 import android.bluetooth.BluetoothAdapter;
8 import android.content.Context;
9 import android.net.wifi.WifiInfo;
10 import android.net.wifi.WifiManager;
11 import android.provider.Settings;
12 import android.provider.Settings.Secure;
13 import android.telephony.TelephonyManager;
14 import android.text.TextUtils;
15
16 public class Util {
17
18 public static String getIMEI(Context context) {
19 TelephonyManager tm = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
20 String imei = tm.getDeviceId();
21 return imei;
22 }
23
24 public static String getMacAddr(Context context) {
25 WifiManager wm = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
26 if (wm.getWifiState() == WifiManager.WIFI_STATE_ENABLED)
27 return wm.getConnectionInfo().getMacAddress();
28 else
29 return "";
30 }
31
32 public static String getAndroidId(Context context) {
33 // fetch androidId
34 String androidId = Secure.getString(context.getContentResolver(), Secure.ANDROID_ID);
35 return androidId;
36 }
37
38 public static String getUniqueId(Context context) {
39 String did = Settings.System.getString(context.getContentResolver(), "deviceId");
40 if (did == null || did.length() == 0) {
41 try {
42 // fetch imei
43 TelephonyManager tm = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
44 String imei = tm.getDeviceId();
45 String simSN = tm.getSimSerialNumber();
46 // fetch bluetooth mac addr
47 BluetoothAdapter m_BluetoothAdapter = null; // Local Bluetooth
48 // adapter
49 m_BluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
50 String BTMAC = m_BluetoothAdapter.getAddress();
51 // fetch wifi mac
52 WifiManager wifiMan = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
53 WifiInfo wifiInf = wifiMan.getConnectionInfo();
54
55 String macAddr = wifiInf.getMacAddress();
56 if (macAddr != null) {
57 macAddr = macAddr.replace(":", "");
58 }
59 // fetch androidId
60 String androidId = Secure.getString(context.getContentResolver(), Secure.ANDROID_ID);
61
62 String figureStr = imei + simSN + BTMAC + macAddr + androidId;
63 if (!TextUtils.isEmpty(figureStr))
64 did = md5(figureStr);
65 else
66 did = UUID.randomUUID().toString();
67 Settings.System.putString(context.getContentResolver(), "deviceId", did);
68 } catch (Exception ex) {
69 ex.printStackTrace();
70 }
71 }
72 return did;
73 }
74
75 public static String md5(String input) {
76 MessageDigest m = null;
77 try {
78 m = MessageDigest.getInstance("MD5");
79 } catch (NoSuchAlgorithmException e) {
80 e.printStackTrace();
81 }
82 m.update(input.getBytes(), 0, input.length());
83 byte p_md5Data[] = m.digest();
84
85 String mOutput = new String();
86 for (int i = 0; i < p_md5Data.length; i++) {
87 int b = (0xFF & p_md5Data[i]);
88 // if it is a single digit, make sure it have 0 in front (proper
89 // padding)
90 if (b <= 0xF)
91 mOutput += "0";
92 // add number to string
93 mOutput += Integer.toHexString(b);
94 }
95 // hex string to uppercase
96 return mOutput.toUpperCase();
97 }
98 }
99 1 package com.mobithink.tracesdk.utils;