diff options
Diffstat (limited to 'libs/networking')
16 files changed, 964 insertions, 0 deletions
diff --git a/libs/networking/.gitignore b/libs/networking/.gitignore new file mode 100644 index 000000000..df914c258 --- /dev/null +++ b/libs/networking/.gitignore @@ -0,0 +1,23 @@ +# generated files +build/ + +# Local configuration file (sdk path, etc) +local.properties +tools/deploy-mvn-artifact.conf + +# Intellij project files +*.iml +*.ipr +*.iws +.idea/ + +# Gradle +.gradle/ +gradle.properties + +# Idea +.idea/workspace.xml +*.iml + +# OS X +.DS_Store diff --git a/libs/networking/WordPressNetworking/build.gradle b/libs/networking/WordPressNetworking/build.gradle new file mode 100644 index 000000000..c0e937773 --- /dev/null +++ b/libs/networking/WordPressNetworking/build.gradle @@ -0,0 +1,49 @@ +buildscript { + repositories { + jcenter() + } + dependencies { + classpath 'com.android.tools.build:gradle:2.2.0' + } +} + +repositories { + jcenter() + maven { url 'http://wordpress-mobile.github.io/WordPress-Android' } +} + +apply plugin: 'com.android.library' +apply plugin: 'maven' + +android { + publishNonDefault true + + compileSdkVersion 24 + buildToolsVersion "24.0.2" + + defaultConfig { + minSdkVersion 14 + targetSdkVersion 24 + versionName "1.0.0" + } +} + +dependencies { + compile 'org.wordpress:utils:1.11.0' + compile 'com.automattic:rest:1.0.7' +} + +uploadArchives { + repositories { + mavenDeployer { + def repo_url = "" + if (project.hasProperty("repository")) { + repo_url = project.repository + } + repository(url: repo_url) + pom.version = android.defaultConfig.versionName + pom.groupId = "org.wordpress" + pom.artifactId = "wordpress-networking" + } + } +} diff --git a/libs/networking/WordPressNetworking/gradle.properties-example b/libs/networking/WordPressNetworking/gradle.properties-example new file mode 100644 index 000000000..5a17295c3 --- /dev/null +++ b/libs/networking/WordPressNetworking/gradle.properties-example @@ -0,0 +1,2 @@ +wp.db_secret = wordpress +repository = file:///Users/max/work/automattic/WordPress-Android-gh-pages/ diff --git a/libs/networking/WordPressNetworking/src/main/AndroidManifest.xml b/libs/networking/WordPressNetworking/src/main/AndroidManifest.xml new file mode 100644 index 000000000..f19a8bd89 --- /dev/null +++ b/libs/networking/WordPressNetworking/src/main/AndroidManifest.xml @@ -0,0 +1,3 @@ +<manifest xmlns:android="http://schemas.android.com/apk/res/android" + package="org.wordpress.android.networking"> +</manifest> diff --git a/libs/networking/WordPressNetworking/src/main/java/org/wordpress/android/networking/Authenticator.java b/libs/networking/WordPressNetworking/src/main/java/org/wordpress/android/networking/Authenticator.java new file mode 100644 index 000000000..cf7bd78bb --- /dev/null +++ b/libs/networking/WordPressNetworking/src/main/java/org/wordpress/android/networking/Authenticator.java @@ -0,0 +1,13 @@ +package org.wordpress.android.networking; + +/** + * Interface that provides a method that should perform the necessary task to make sure + * the provided AuthenticatorRequest will be authenticated. + * + * The Authenticator must call AuthenticatorRequest.send() when it has completed its operations. For + * convenience the AuthenticatorRequest class provides AuthenticatorRequest.setAccessToken so the Authenticator can + * easily update the access token. + */ +public interface Authenticator { + void authenticate(final AuthenticatorRequest authenticatorRequest); +} diff --git a/libs/networking/WordPressNetworking/src/main/java/org/wordpress/android/networking/AuthenticatorRequest.java b/libs/networking/WordPressNetworking/src/main/java/org/wordpress/android/networking/AuthenticatorRequest.java new file mode 100644 index 000000000..40d2af7f3 --- /dev/null +++ b/libs/networking/WordPressNetworking/src/main/java/org/wordpress/android/networking/AuthenticatorRequest.java @@ -0,0 +1,96 @@ +package org.wordpress.android.networking; + +import com.android.volley.VolleyError; +import com.wordpress.rest.Oauth; +import com.wordpress.rest.RestClient; +import com.wordpress.rest.RestRequest; +import com.wordpress.rest.RestRequest.ErrorListener; + +/** + * Encapsulates the behaviour for asking the Authenticator for an access token. This + * allows the request maker to disregard the authentication state when making requests. + */ +public class AuthenticatorRequest { + private RestRequest mRequest; + private RestRequest.ErrorListener mListener; + private RestClient mRestClient; + private Authenticator mAuthenticator; + + protected AuthenticatorRequest(RestRequest request, ErrorListener listener, RestClient restClient, + Authenticator authenticator) { + mRequest = request; + mListener = listener; + mRestClient = restClient; + mAuthenticator = authenticator; + } + + public String getSiteId() { + return extractSiteIdFromUrl(mRestClient.getEndpointURL(), mRequest.getUrl()); + } + + /** + * Parse out the site ID from an URL. + * Note: For batch REST API calls, only the first siteID is returned + * + * @return The site ID + */ + public static String extractSiteIdFromUrl(String restEndpointUrl, String url) { + if (url == null) { + return null; + } + + final String sitePrefix = restEndpointUrl.endsWith("/") ? restEndpointUrl + "sites/" : restEndpointUrl + "/sites/"; + final String batchCallPrefix = restEndpointUrl.endsWith("/") ? restEndpointUrl + "batch/?urls%5B%5D=%2Fsites%2F" + : restEndpointUrl + "/batch/?urls%5B%5D=%2Fsites%2F"; + + if (url.startsWith(sitePrefix) && !sitePrefix.equals(url)) { + int marker = sitePrefix.length(); + if (url.indexOf("/", marker) < marker) { + return null; + } + return url.substring(marker, url.indexOf("/", marker)); + } else if (url.startsWith(batchCallPrefix) && !batchCallPrefix.equals(url)) { + int marker = batchCallPrefix.length(); + if (url.indexOf("%2F", marker) < marker) { + return null; + } + return url.substring(marker, url.indexOf("%2F", marker)); + } + + // not a sites/$siteId request or a batch request + return null; + } + + /** + * Attempt to send the request, checks to see if we have an access token and if not + * asks the Authenticator to authenticate the request. + * + * If no Authenticator is provided the request is always sent. + */ + protected void send(){ + if (mAuthenticator == null) { + mRestClient.send(mRequest); + } else { + mAuthenticator.authenticate(this); + } + } + + public void sendWithAccessToken(String token){ + mRequest.setAccessToken(token); + mRestClient.send(mRequest); + } + + public void sendWithAccessToken(Oauth.Token token){ + sendWithAccessToken(token.toString()); + } + + /** + * If an access token cannot be obtained the request can be aborted and the + * handler's onFailure method is called + */ + public void abort(VolleyError error){ + if (mListener != null) { + mListener.onErrorResponse(error); + } + } +} diff --git a/libs/networking/WordPressNetworking/src/main/java/org/wordpress/android/networking/RestClientFactory.java b/libs/networking/WordPressNetworking/src/main/java/org/wordpress/android/networking/RestClientFactory.java new file mode 100644 index 000000000..492b2b99f --- /dev/null +++ b/libs/networking/WordPressNetworking/src/main/java/org/wordpress/android/networking/RestClientFactory.java @@ -0,0 +1,19 @@ +package org.wordpress.android.networking; + +import com.android.volley.RequestQueue; +import com.wordpress.rest.RestClient; + +public class RestClientFactory { + private static RestClientFactoryAbstract sFactory; + + public static RestClient instantiate(RequestQueue queue) { + return instantiate(queue, RestClient.REST_CLIENT_VERSIONS.V1); + } + + public static RestClient instantiate(RequestQueue queue, RestClient.REST_CLIENT_VERSIONS version) { + if (sFactory == null) { + sFactory = new RestClientFactoryDefault(); + } + return sFactory.make(queue, version); + } +} diff --git a/libs/networking/WordPressNetworking/src/main/java/org/wordpress/android/networking/RestClientFactoryAbstract.java b/libs/networking/WordPressNetworking/src/main/java/org/wordpress/android/networking/RestClientFactoryAbstract.java new file mode 100644 index 000000000..799a5a8e8 --- /dev/null +++ b/libs/networking/WordPressNetworking/src/main/java/org/wordpress/android/networking/RestClientFactoryAbstract.java @@ -0,0 +1,9 @@ +package org.wordpress.android.networking; + +import com.android.volley.RequestQueue; +import com.wordpress.rest.RestClient; + +public interface RestClientFactoryAbstract { + public RestClient make(RequestQueue queue); + public RestClient make(RequestQueue queue, RestClient.REST_CLIENT_VERSIONS version); +} diff --git a/libs/networking/WordPressNetworking/src/main/java/org/wordpress/android/networking/RestClientFactoryDefault.java b/libs/networking/WordPressNetworking/src/main/java/org/wordpress/android/networking/RestClientFactoryDefault.java new file mode 100644 index 000000000..b87d4b40f --- /dev/null +++ b/libs/networking/WordPressNetworking/src/main/java/org/wordpress/android/networking/RestClientFactoryDefault.java @@ -0,0 +1,14 @@ +package org.wordpress.android.networking; + +import com.android.volley.RequestQueue; +import com.wordpress.rest.RestClient; + +public class RestClientFactoryDefault implements RestClientFactoryAbstract { + public RestClient make(RequestQueue queue) { + return new RestClient(queue); + } + + public RestClient make(RequestQueue queue, RestClient.REST_CLIENT_VERSIONS version) { + return new RestClient(queue, version); + } +} diff --git a/libs/networking/WordPressNetworking/src/main/java/org/wordpress/android/networking/RestClientUtils.java b/libs/networking/WordPressNetworking/src/main/java/org/wordpress/android/networking/RestClientUtils.java new file mode 100644 index 000000000..6e06cfeee --- /dev/null +++ b/libs/networking/WordPressNetworking/src/main/java/org/wordpress/android/networking/RestClientUtils.java @@ -0,0 +1,475 @@ +/** + * Interface to the WordPress.com REST API. + */ +package org.wordpress.android.networking; + +import android.content.Context; +import android.net.Uri; +import android.text.TextUtils; + +import com.android.volley.DefaultRetryPolicy; +import com.android.volley.Request; +import com.android.volley.Request.Method; +import com.android.volley.RequestQueue; +import com.android.volley.RetryPolicy; +import com.android.volley.toolbox.RequestFuture; +import com.wordpress.rest.JsonRestRequest; +import com.wordpress.rest.RestClient; +import com.wordpress.rest.RestRequest; +import com.wordpress.rest.RestRequest.ErrorListener; +import com.wordpress.rest.RestRequest.Listener; + +import org.json.JSONObject; +import org.wordpress.android.util.LanguageUtils; + +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.TimeoutException; + +public class RestClientUtils { + private static final String NOTIFICATION_FIELDS = "id,type,unread,body,subject,timestamp,meta"; + private static final String COMMENT_REPLY_CONTENT_FIELD = "content"; + private static String sUserAgent = "WordPress Networking Android"; + + private RestClient mRestClient; + private Authenticator mAuthenticator; + private Context mContext; + + /** + * Socket timeout in milliseconds for rest requests + */ + public static final int REST_TIMEOUT_MS = 30000; + + /** + * Default number of retries for POST rest requests + */ + public static final int REST_MAX_RETRIES_POST = 0; + + /** + * Default number of retries for GET rest requests + */ + public static final int REST_MAX_RETRIES_GET = 3; + + /** + * Default backoff multiplier for rest requests + */ + public static final float REST_BACKOFF_MULT = 2f; + + public static void setUserAgent(String userAgent) { + sUserAgent = userAgent; + } + + public RestClientUtils(Context context, RequestQueue queue, Authenticator authenticator, RestRequest.OnAuthFailedListener onAuthFailedListener) { + this(context, queue, authenticator, onAuthFailedListener, RestClient.REST_CLIENT_VERSIONS.V1); + } + + public RestClientUtils(Context context, RequestQueue queue, Authenticator authenticator, RestRequest.OnAuthFailedListener onAuthFailedListener, RestClient.REST_CLIENT_VERSIONS version) { + // load an existing access token from prefs if we have one + mContext = context; + mAuthenticator = authenticator; + mRestClient = RestClientFactory.instantiate(queue, version); + if (onAuthFailedListener != null) { + mRestClient.setOnAuthFailedListener(onAuthFailedListener); + } + mRestClient.setUserAgent(sUserAgent); + } + + public Authenticator getAuthenticator() { + return mAuthenticator; + } + + public RestClient getRestClient() { + return mRestClient; + } + + public void getCategories(String siteId, Listener listener, ErrorListener errorListener) { + String path = String.format("sites/%s/categories", siteId); + get(path, null, null, listener, errorListener); + } + + /** + * get a list of recent comments + * <p/> + * https://developer.wordpress.com/docs/api/1.1/get/sites/%24site/comments/ + */ + public void getComments(String siteId, Map<String, String> params, final Listener listener, ErrorListener errorListener) { + String path = String.format("sites/%s/comments", siteId); + get(path, params, null, listener, errorListener); + } + + /** + * Reply to a comment + * <p/> + * https://developer.wordpress.com/docs/api/1/post/sites/%24site/posts/%24post_ID/replies/new/ + */ + public void replyToComment(String reply, String path, Listener listener, ErrorListener errorListener) { + Map<String, String> params = new HashMap<String, String>(); + params.put(COMMENT_REPLY_CONTENT_FIELD, reply); + post(path, params, null, listener, errorListener); + } + + /** + * Reply to a comment. + * <p/> + * https://developer.wordpress.com/docs/api/1/post/sites/%24site/posts/%24post_ID/replies/new/ + */ + public void replyToComment(long siteId, long commentId, String content, Listener listener, + ErrorListener errorListener) { + Map<String, String> params = new HashMap<String, String>(); + params.put(COMMENT_REPLY_CONTENT_FIELD, content); + String path = String.format("sites/%d/comments/%d/replies/new", siteId, commentId); + post(path, params, null, listener, errorListener); + } + + /** + * Follow a site given an ID or domain + * <p/> + * https://developer.wordpress.com/docs/api/1/post/sites/%24site/follows/new/ + */ + public void followSite(String siteId, Listener listener, ErrorListener errorListener) { + String path = String.format("sites/%s/follows/new", siteId); + post(path, listener, errorListener); + } + + /** + * Unfollow a site given an ID or domain + * <p/> + * https://developer.wordpress.com/docs/api/1/post/sites/%24site/follows/mine/delete/ + */ + public void unfollowSite(String siteId, Listener listener, ErrorListener errorListener) { + String path = String.format("sites/%s/follows/mine/delete", siteId); + post(path, listener, errorListener); + } + + /** + * Get notifications with the provided params. + * <p/> + * https://developer.wordpress.com/docs/api/1/get/notifications/ + */ + public void getNotifications(Map<String, String> params, Listener listener, ErrorListener errorListener) { + params.put("number", "40"); + params.put("num_note_items", "20"); + params.put("fields", NOTIFICATION_FIELDS); + get("notifications", params, null, listener, errorListener); + } + + /** + * Get notifications with default params. + * <p/> + * https://developer.wordpress.com/docs/api/1/get/notifications/ + */ + public void getNotifications(Listener listener, ErrorListener errorListener) { + getNotifications(new HashMap<String, String>(), listener, errorListener); + } + + /** + * Update the seen timestamp. + * <p/> + * https://developer.wordpress.com/docs/api/1/post/notifications/seen + */ + public void markNotificationsSeen(String timestamp, Listener listener, ErrorListener errorListener) { + Map<String, String> params = new HashMap<String, String>(); + params.put("time", timestamp); + post("notifications/seen", params, null, listener, errorListener); + } + + /** + * Moderate a comment. + * <p/> + * http://developer.wordpress.com/docs/api/1/sites/%24site/comments/%24comment_ID/ + */ + public void moderateComment(String siteId, String commentId, String status, Listener listener, + ErrorListener errorListener) { + Map<String, String> params = new HashMap<String, String>(); + params.put("status", status); + String path = String.format("sites/%s/comments/%s/", siteId, commentId); + post(path, params, null, listener, errorListener); + } + + /** + * Edit the content of a comment + */ + public void editCommentContent(long siteId, long commentId, String content, Listener listener, + ErrorListener errorListener) { + Map<String, String> params = new HashMap<String, String>(); + params.put("content", content); + String path = String.format("sites/%d/comments/%d/", siteId, commentId); + post(path, params, null, listener, errorListener); + } + + /** + * Like or unlike a comment. + */ + public void likeComment(String siteId, String commentId, boolean isLiked, Listener listener, + ErrorListener errorListener) { + Map<String, String> params = new HashMap<String, String>(); + String path = String.format("sites/%s/comments/%s/likes/", siteId, commentId); + + if (!isLiked) { + path += "mine/delete"; + } else { + path += "new"; + } + + post(path, params, null, listener, errorListener); + } + + public void getFreeSearchThemes(String siteId, int limit, int offset, String searchTerm, Listener listener, ErrorListener errorListener) { + getSearchThemes("free", siteId, limit, offset, searchTerm, listener, errorListener); + } + + public void getSearchThemes(String tier, String siteId, int limit, int offset, String searchTerm, Listener listener, ErrorListener errorListener) { + String path = String.format("sites/%s/themes?tier=" + tier + "&number=%d&offset=%d&search=%s", siteId, limit, offset, searchTerm); + get(path, listener, errorListener); + } + + public void getFreeThemes(String siteId, int limit, int offset, Listener listener, ErrorListener errorListener) { + getThemes("free", siteId, limit, offset, listener, errorListener); + } + + public void getPurchasedThemes(String siteId, Listener listener, ErrorListener errorListener) { + String path = String.format("sites/%s/themes/purchased", siteId); + get(path, listener, errorListener); + } + + /** + * Get all a site's themes + */ + public void getThemes(String tier, String siteId, int limit, int offset, Listener listener, ErrorListener errorListener) { + String path = String.format("sites/%s/themes/?tier=" + tier + "&number=%d&offset=%d", siteId, limit, offset); + get(path, listener, errorListener); + } + + /** + * Set a site's theme + */ + public void setTheme(String siteId, String themeId, Listener listener, ErrorListener errorListener) { + Map<String, String> params = new HashMap<>(); + params.put("theme", themeId); + String path = String.format("sites/%s/themes/mine", siteId); + post(path, params, null, listener, errorListener); + } + + /** + * Get a site's current theme + */ + public void getCurrentTheme(String siteId, Listener listener, ErrorListener errorListener) { + String path = String.format("sites/%s/themes/mine", siteId); + get(path, listener, errorListener); + } + + public void getGeneralSettings(String siteId, Listener listener, ErrorListener errorListener) { + String path = String.format("sites/%s/settings", siteId); + Map<String, String> params = new HashMap<String, String>(); + get(path, params, null, listener, errorListener); + } + + public void setGeneralSiteSettings(String siteId, Listener listener, ErrorListener errorListener, + Map<String, String> params) { + String path = String.format("sites/%s/settings", siteId); + post(path, params, null, listener, errorListener); + } + + /** + * Delete a site + */ + public void deleteSite(String siteId, Listener listener, ErrorListener errorListener) { + String path = String.format("sites/%s/delete", siteId); + post(path, listener, errorListener); + } + + public void getSitePurchases(String siteId, Listener listener, ErrorListener errorListener) { + String path = String.format("sites/%s/purchases", siteId); + get(path, listener, errorListener); + } + + public void exportContentAll(String siteId, Listener listener, ErrorListener errorListener) { + String path = String.format("sites/%s/exports/start", siteId); + post(path, listener, errorListener); + } + + public void sendLoginEmail(Map<String, String> params, Listener listener, ErrorListener errorListener) { + post("auth/send-login-email", params, null, listener, errorListener); + } + + public void isAvailable(String email, Listener listener, ErrorListener errorListener) { + String path = String.format("is-available/email?q=%s", email); + get(path, listener, errorListener); + } + + /** + * Make GET request + */ + public Request<JSONObject> get(String path, Listener listener, ErrorListener errorListener) { + return get(path, null, null, listener, errorListener); + } + + /** + * Make GET request with params + */ + public Request<JSONObject> get(String path, Map<String, String> params, RetryPolicy retryPolicy, Listener listener, + ErrorListener errorListener) { + // turn params into querystring + HashMap<String, String> paramsWithLocale = getRestLocaleParams(mContext); + if (params != null) { + paramsWithLocale.putAll(params); + } + + String realPath = getSanitizedPath(path); + if (TextUtils.isEmpty(realPath)) { + realPath = path; + } + paramsWithLocale.putAll(getSanitizedParameters(path)); + + RestRequest request = mRestClient.makeRequest(Method.GET, mRestClient.getAbsoluteURL(realPath, paramsWithLocale), null, + listener, errorListener); + + if (retryPolicy == null) { + retryPolicy = new DefaultRetryPolicy(REST_TIMEOUT_MS, REST_MAX_RETRIES_GET, REST_BACKOFF_MULT); + } + request.setRetryPolicy(retryPolicy); + AuthenticatorRequest authCheck = new AuthenticatorRequest(request, errorListener, mRestClient, mAuthenticator); + authCheck.send(); + return request; + } + + /** + * Make Synchronous GET request + * + * @throws TimeoutException + * @throws ExecutionException + * @throws InterruptedException + */ + public JSONObject getSynchronous(String path) throws InterruptedException, ExecutionException, TimeoutException { + return getSynchronous(path, null, null); + } + + /** + * Make Synchronous GET request with params + * + * @throws TimeoutException + * @throws ExecutionException + * @throws InterruptedException + */ + public JSONObject getSynchronous(String path, Map<String, String> params, RetryPolicy retryPolicy) + throws InterruptedException, ExecutionException, TimeoutException { + RequestFuture<JSONObject> future = RequestFuture.newFuture(); + + HashMap<String, String> paramsWithLocale = getRestLocaleParams(mContext); + if (params != null) { + paramsWithLocale.putAll(params); + } + + String realPath = getSanitizedPath(path); + if (TextUtils.isEmpty(realPath)) { + realPath = path; + } + paramsWithLocale.putAll(getSanitizedParameters(path)); + + RestRequest request = mRestClient.makeRequest(Method.GET, mRestClient.getAbsoluteURL(realPath, paramsWithLocale), null, future, future); + + if (retryPolicy == null) { + retryPolicy = new DefaultRetryPolicy(REST_TIMEOUT_MS, REST_MAX_RETRIES_GET, REST_BACKOFF_MULT); + } + request.setRetryPolicy(retryPolicy); + + AuthenticatorRequest authCheck = new AuthenticatorRequest(request, null, mRestClient, mAuthenticator); + authCheck.send(); //this insert the request into the queue. //TODO: Verify that everything is OK on REST calls without a valid token + JSONObject response = future.get(); + return response; + } + + /** + * Make POST request + */ + public void post(String path, Listener listener, ErrorListener errorListener) { + Map<String, String> params = null; + post(path, params, null, listener, errorListener); + } + + /** + * Make POST request with params + */ + public void post(final String path, Map<String, String> params, RetryPolicy retryPolicy, Listener listener, + ErrorListener errorListener) { + final RestRequest request = mRestClient.makeRequest(Method.POST, mRestClient.getAbsoluteURL(path, getRestLocaleParams(mContext)), params, + listener, errorListener); + if (retryPolicy == null) { + retryPolicy = new DefaultRetryPolicy(REST_TIMEOUT_MS, REST_MAX_RETRIES_POST, + REST_BACKOFF_MULT); //Do not retry on failure + } + request.setRetryPolicy(retryPolicy); + AuthenticatorRequest authCheck = new AuthenticatorRequest(request, errorListener, mRestClient, mAuthenticator); + authCheck.send(); + } + + + /** + * Make a JSON POST request + */ + public void post(final String path, JSONObject params, RetryPolicy retryPolicy, Listener listener, + ErrorListener errorListener) { + final JsonRestRequest request = mRestClient.makeRequest(mRestClient.getAbsoluteURL(path, getRestLocaleParams(mContext)), params, + listener, errorListener); + if (retryPolicy == null) { + retryPolicy = new DefaultRetryPolicy(REST_TIMEOUT_MS, REST_MAX_RETRIES_POST, + REST_BACKOFF_MULT); //Do not retry on failure + } + request.setRetryPolicy(retryPolicy); + AuthenticatorRequest authCheck = new AuthenticatorRequest(request, errorListener, mRestClient, mAuthenticator); + authCheck.send(); + } + + /** + * Takes a URL and returns the path within, or an empty string (not null) + */ + public static String getSanitizedPath(String unsanitizedPath){ + if (unsanitizedPath != null) { + int qmarkPos = unsanitizedPath.indexOf('?'); + if (qmarkPos > -1) { //strip any querystring params off this to obtain the path + return unsanitizedPath.substring(0, qmarkPos+1); + } else { + // return the string as is, consider the whole string as the path + return unsanitizedPath; + } + } + return ""; + } + + /** + * Takes a URL with query strings and returns a Map of query string values. + */ + public static HashMap<String, String> getSanitizedParameters(String unsanitizedPath){ + HashMap<String, String> queryParams = new HashMap<>(); + + Uri uri = Uri.parse(unsanitizedPath); + + if (uri.getQueryParameterNames() != null ) { + Iterator iter = uri.getQueryParameterNames().iterator(); + while (iter.hasNext()) { + String name = (String)iter.next(); + String value = uri.getQueryParameter(name); + queryParams.put(name, value); + } + } + + return queryParams; + } + + /** + * Returns locale parameter used in REST calls which require the response to be localized + */ + public static HashMap<String, String> getRestLocaleParams(Context context) { + HashMap<String, String> params = new HashMap<>(); + String deviceLanguageCode = LanguageUtils.getCurrentDeviceLanguageCode(context); + if (!TextUtils.isEmpty(deviceLanguageCode)) { + //patch locale if it's any of the deprecated codes as can be read in Locale.java source code: + deviceLanguageCode = LanguageUtils.patchDeviceLanguageCode(deviceLanguageCode); + params.put("locale", deviceLanguageCode); + } + return params; + } + +} diff --git a/libs/networking/build.gradle b/libs/networking/build.gradle new file mode 100644 index 000000000..e69de29bb --- /dev/null +++ b/libs/networking/build.gradle diff --git a/libs/networking/gradle/wrapper/gradle-wrapper.jar b/libs/networking/gradle/wrapper/gradle-wrapper.jar Binary files differnew file mode 100644 index 000000000..8c0fb64a8 --- /dev/null +++ b/libs/networking/gradle/wrapper/gradle-wrapper.jar diff --git a/libs/networking/gradle/wrapper/gradle-wrapper.properties b/libs/networking/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 000000000..4c74aab81 --- /dev/null +++ b/libs/networking/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,6 @@ +#Wed Apr 10 15:27:10 PDT 2013 +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-2.14-all.zip diff --git a/libs/networking/gradlew b/libs/networking/gradlew new file mode 100755 index 000000000..91a7e269e --- /dev/null +++ b/libs/networking/gradlew @@ -0,0 +1,164 @@ +#!/usr/bin/env bash + +############################################################################## +## +## Gradle start up script for UN*X +## +############################################################################## + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS="" + +APP_NAME="Gradle" +APP_BASE_NAME=`basename "$0"` + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD="maximum" + +warn ( ) { + echo "$*" +} + +die ( ) { + echo + echo "$*" + echo + exit 1 +} + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +case "`uname`" in + CYGWIN* ) + cygwin=true + ;; + Darwin* ) + darwin=true + ;; + MINGW* ) + msys=true + ;; +esac + +# For Cygwin, ensure paths are in UNIX format before anything is touched. +if $cygwin ; then + [ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"` +fi + +# Attempt to set APP_HOME +# Resolve links: $0 may be a link +PRG="$0" +# Need this for relative symlinks. +while [ -h "$PRG" ] ; do + ls=`ls -ld "$PRG"` + link=`expr "$ls" : '.*-> \(.*\)$'` + if expr "$link" : '/.*' > /dev/null; then + PRG="$link" + else + PRG=`dirname "$PRG"`"/$link" + fi +done +SAVED="`pwd`" +cd "`dirname \"$PRG\"`/" >&- +APP_HOME="`pwd -P`" +cd "$SAVED" >&- + +CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD="$JAVA_HOME/jre/sh/java" + else + JAVACMD="$JAVA_HOME/bin/java" + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD="java" + which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." +fi + +# Increase the maximum file descriptors if we can. +if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then + MAX_FD_LIMIT=`ulimit -H -n` + if [ $? -eq 0 ] ; then + if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then + MAX_FD="$MAX_FD_LIMIT" + fi + ulimit -n $MAX_FD + if [ $? -ne 0 ] ; then + warn "Could not set maximum file descriptor limit: $MAX_FD" + fi + else + warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" + fi +fi + +# For Darwin, add options to specify how the application appears in the dock +if $darwin; then + GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" +fi + +# For Cygwin, switch paths to Windows format before running java +if $cygwin ; then + APP_HOME=`cygpath --path --mixed "$APP_HOME"` + CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` + + # We build the pattern for arguments to be converted via cygpath + ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` + SEP="" + for dir in $ROOTDIRSRAW ; do + ROOTDIRS="$ROOTDIRS$SEP$dir" + SEP="|" + done + OURCYGPATTERN="(^($ROOTDIRS))" + # Add a user-defined pattern to the cygpath arguments + if [ "$GRADLE_CYGPATTERN" != "" ] ; then + OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" + fi + # Now convert the arguments - kludge to limit ourselves to /bin/sh + i=0 + for arg in "$@" ; do + CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` + CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option + + if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition + eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` + else + eval `echo args$i`="\"$arg\"" + fi + i=$((i+1)) + done + case $i in + (0) set -- ;; + (1) set -- "$args0" ;; + (2) set -- "$args0" "$args1" ;; + (3) set -- "$args0" "$args1" "$args2" ;; + (4) set -- "$args0" "$args1" "$args2" "$args3" ;; + (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; + (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; + (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; + (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; + (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; + esac +fi + +# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules +function splitJvmOpts() { + JVM_OPTS=("$@") +} +eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS +JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME" + +exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@" diff --git a/libs/networking/gradlew.bat b/libs/networking/gradlew.bat new file mode 100644 index 000000000..8a0b282aa --- /dev/null +++ b/libs/networking/gradlew.bat @@ -0,0 +1,90 @@ +@if "%DEBUG%" == "" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS= + +set DIRNAME=%~dp0 +if "%DIRNAME%" == "" set DIRNAME=. +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if "%ERRORLEVEL%" == "0" goto init + +echo. +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto init + +echo. +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:init +@rem Get command-line arguments, handling Windowz variants + +if not "%OS%" == "Windows_NT" goto win9xME_args +if "%@eval[2+2]" == "4" goto 4NT_args + +:win9xME_args +@rem Slurp the command line arguments. +set CMD_LINE_ARGS= +set _SKIP=2 + +:win9xME_args_slurp +if "x%~1" == "x" goto execute + +set CMD_LINE_ARGS=%* +goto execute + +:4NT_args +@rem Get arguments from the 4NT Shell from JP Software +set CMD_LINE_ARGS=%$ + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% + +:end +@rem End local scope for the variables with windows NT shell +if "%ERRORLEVEL%"=="0" goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 +exit /b 1 + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/libs/networking/settings.gradle b/libs/networking/settings.gradle new file mode 100644 index 000000000..62b0b6897 --- /dev/null +++ b/libs/networking/settings.gradle @@ -0,0 +1 @@ +include ':WordPressNetworking' |