Commit f748670d96e0d63028fe8fb7f6b1d53b899ae154
1 parent
c249b9af01
Exists in
master
branch release
Showing 45 changed files with 0 additions and 4701 deletions Inline Diff
- TraceSDK/.classpath
- TraceSDK/.fatjar
- TraceSDK/.project
- TraceSDK/AndroidManifest.xml
- TraceSDK/libs/android-support-v4.jar
- TraceSDK/proguard-project.txt
- TraceSDK/project.properties
- TraceSDK/res/drawable-hdpi/ic_launcher.png
- TraceSDK/res/drawable-mdpi/ic_launcher.png
- TraceSDK/res/drawable-xhdpi/ic_launcher.png
- TraceSDK/res/values-v11/styles.xml
- TraceSDK/res/values-v14/styles.xml
- TraceSDK/res/values/strings.xml
- TraceSDK/res/values/styles.xml
- TraceSDK/src/com/mobithink/tracesdk/Conf.java
- TraceSDK/src/com/mobithink/tracesdk/TraceAgent.java
- TraceSDK/src/com/mobithink/tracesdk/event/Event.java
- TraceSDK/src/com/mobithink/tracesdk/event/EventDBUtil.java
- TraceSDK/src/com/mobithink/tracesdk/json/JSON.java
- TraceSDK/src/com/mobithink/tracesdk/json/JSONArray.java
- TraceSDK/src/com/mobithink/tracesdk/json/JSONException.java
- TraceSDK/src/com/mobithink/tracesdk/json/JSONObject.java
- TraceSDK/src/com/mobithink/tracesdk/json/JSONStringer.java
- TraceSDK/src/com/mobithink/tracesdk/json/JSONTokener.java
- TraceSDK/src/com/mobithink/tracesdk/rest/client/AbstractClient.java
- TraceSDK/src/com/mobithink/tracesdk/rest/client/DefaultRESTClient.java
- TraceSDK/src/com/mobithink/tracesdk/rest/client/EntityReader.java
- TraceSDK/src/com/mobithink/tracesdk/rest/client/EntityReaderImplJSON.java
- TraceSDK/src/com/mobithink/tracesdk/rest/client/EntityReaderImplString.java
- TraceSDK/src/com/mobithink/tracesdk/rest/client/HttpExecutor.java
- TraceSDK/src/com/mobithink/tracesdk/rest/client/HttpHeaders.java
- TraceSDK/src/com/mobithink/tracesdk/rest/client/IClient.java
- TraceSDK/src/com/mobithink/tracesdk/rest/client/MediaType.java
- TraceSDK/src/com/mobithink/tracesdk/rest/client/MetadataMap.java
- TraceSDK/src/com/mobithink/tracesdk/rest/client/MultivaluedMap.java
- TraceSDK/src/com/mobithink/tracesdk/rest/client/RESTClient.java
- TraceSDK/src/com/mobithink/tracesdk/rest/client/RequestEntity.java
- TraceSDK/src/com/mobithink/tracesdk/rest/client/RequestEntityImplJSON.java
- TraceSDK/src/com/mobithink/tracesdk/rest/client/RequestEntityImplString.java
- TraceSDK/src/com/mobithink/tracesdk/rest/client/Response.java
- TraceSDK/src/com/mobithink/tracesdk/rest/client/ResponseImpl.java
- TraceSDK/src/com/mobithink/tracesdk/rest/client/UriBuilder.java
- TraceSDK/src/com/mobithink/tracesdk/rest/client/Utils.java
- TraceSDK/src/com/mobithink/tracesdk/utils/LogUtil.java
- TraceSDK/src/com/mobithink/tracesdk/utils/Util.java
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; |