Skip to content

Commit fedb7ef

Browse files
hermanliangrogerhu
authored andcommitted
Support for setting up Server Url in the Manifest (#600)
* Supports setting Server Url in Manifest * Add test and update JavaDoc * remove redundant null assignment * using Roboelectric to mock Context & PackageManager add testConfigureFromManifestWithoutClientKey * minor optimization for unit test & update Javadoc
1 parent 511bf39 commit fedb7ef

File tree

4 files changed

+115
-12
lines changed

4 files changed

+115
-12
lines changed

Parse/src/main/java/com/parse/Parse.java

+20-12
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ public static final class Builder {
5151
private Context context;
5252
private String applicationId;
5353
private String clientKey;
54-
private String server = "https://api.parse.com/1/";
54+
private String server;
5555
private boolean localDataStoreEnabled;
5656
private List<ParseNetworkInterceptor> interceptors;
5757

@@ -62,7 +62,7 @@ public static final class Builder {
6262
* initialization.
6363
*
6464
* <p/>
65-
* You may define {@code com.parse.APPLICATION_ID} and {@code com.parse.CLIENT_KEY}
65+
* You may define {@code com.parse.SERVER_URL}, {@code com.parse.APPLICATION_ID} and (optional) {@code com.parse.CLIENT_KEY}
6666
* {@code meta-data} in your {@code AndroidManifest.xml}:
6767
* <pre>
6868
* &lt;manifest ...&gt;
@@ -71,6 +71,9 @@ public static final class Builder {
7171
*
7272
* &lt;application ...&gt;
7373
* &lt;meta-data
74+
* android:name="com.parse.SERVER_URL"
75+
* android:value="@string/parse_server_url" /&gt;
76+
* &lt;meta-data
7477
* android:name="com.parse.APPLICATION_ID"
7578
* android:value="@string/parse_app_id" /&gt;
7679
* &lt;meta-data
@@ -84,7 +87,7 @@ public static final class Builder {
8487
* </pre>
8588
* <p/>
8689
*
87-
* This will cause the values for {@code applicationId} and {@code clientKey} to be set to
90+
* This will cause the values for {@code server}, {@code applicationId} and {@code clientKey} to be set to
8891
* those defined in your manifest.
8992
*
9093
* @param context The active {@link Context} for your application. Cannot be null.
@@ -98,6 +101,7 @@ public Builder(Context context) {
98101
Context applicationContext = context.getApplicationContext();
99102
Bundle metaData = ManifestInfo.getApplicationMetadata(applicationContext);
100103
if (metaData != null) {
104+
server(metaData.getString(PARSE_SERVER_URL));
101105
applicationId = metaData.getString(PARSE_APPLICATION_ID);
102106
clientKey = metaData.getString(PARSE_CLIENT_KEY);
103107
}
@@ -145,7 +149,7 @@ public Builder server(String server) {
145149

146150
// Add an extra trailing slash so that Parse REST commands include
147151
// the path as part of the server URL (i.e. http://api.myhost.com/parse)
148-
if (server.endsWith("/") == false) {
152+
if (server != null && !server.endsWith("/")) {
149153
server = server + "/";
150154
}
151155

@@ -223,6 +227,7 @@ private Configuration(Builder builder) {
223227
}
224228
}
225229

230+
private static final String PARSE_SERVER_URL = "com.parse.SERVER_URL";
226231
private static final String PARSE_APPLICATION_ID = "com.parse.APPLICATION_ID";
227232
private static final String PARSE_CLIENT_KEY = "com.parse.CLIENT_KEY";
228233

@@ -284,7 +289,7 @@ public static void enableLocalDatastore(Context context) {
284289
/**
285290
* Authenticates this client as belonging to your application.
286291
* <p/>
287-
* You must define {@code com.parse.APPLICATION_ID} and {@code com.parse.CLIENT_KEY}
292+
* You may define {@code com.parse.SERVER_URL}, {@code com.parse.APPLICATION_ID} and (optional) {@code com.parse.CLIENT_KEY}
288293
* {@code meta-data} in your {@code AndroidManifest.xml}:
289294
* <pre>
290295
* &lt;manifest ...&gt;
@@ -293,6 +298,9 @@ public static void enableLocalDatastore(Context context) {
293298
*
294299
* &lt;application ...&gt;
295300
* &lt;meta-data
301+
* android:name="com.parse.SERVER_URL"
302+
* android:value="@string/parse_server_url" /&gt;
303+
* &lt;meta-data
296304
* android:name="com.parse.APPLICATION_ID"
297305
* android:value="@string/parse_app_id" /&gt;
298306
* &lt;meta-data
@@ -322,18 +330,18 @@ public static void enableLocalDatastore(Context context) {
322330
*/
323331
public static void initialize(Context context) {
324332
Configuration.Builder builder = new Configuration.Builder(context);
325-
if (builder.applicationId == null) {
333+
if (builder.server == null) {
334+
throw new RuntimeException("ServerUrl not defined. " +
335+
"You must provide ServerUrl in AndroidManifest.xml.\n" +
336+
"<meta-data\n" +
337+
" android:name=\"com.parse.SERVER_URL\"\n" +
338+
" android:value=\"<Your Server Url>\" />");
339+
} if (builder.applicationId == null) {
326340
throw new RuntimeException("ApplicationId not defined. " +
327341
"You must provide ApplicationId in AndroidManifest.xml.\n" +
328342
"<meta-data\n" +
329343
" android:name=\"com.parse.APPLICATION_ID\"\n" +
330344
" android:value=\"<Your Application Id>\" />");
331-
} if (builder.clientKey == null) {
332-
throw new RuntimeException("ClientKey not defined. " +
333-
"You must provide ClientKey in AndroidManifest.xml.\n" +
334-
"<meta-data\n" +
335-
" android:name=\"com.parse.CLIENT_KEY\"\n" +
336-
" android:value=\"<Your Client Key>\" />");
337345
}
338346
initialize(builder.setNetworkInterceptors(interceptors)
339347
.setLocalDatastoreEnabled(isLocalDatastoreEnabled)

Parse/src/test/java/com/parse/ParseClientConfigurationTest.java

+91
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,20 @@
88
*/
99
package com.parse;
1010

11+
import android.content.pm.ApplicationInfo;
12+
import android.content.pm.PackageManager;
13+
import android.os.Bundle;
14+
1115
import com.parse.http.ParseNetworkInterceptor;
1216

1317
import org.junit.Test;
18+
import org.junit.runner.RunWith;
19+
import org.robolectric.RobolectricTestRunner;
20+
import org.robolectric.RuntimeEnvironment;
21+
import org.robolectric.annotation.Config;
22+
import org.robolectric.shadows.ShadowPackageManager;
1423

24+
import java.net.URL;
1525
import java.util.ArrayList;
1626
import java.util.Collection;
1727
import java.util.Iterator;
@@ -22,9 +32,21 @@
2232
import static org.junit.Assert.assertTrue;
2333
import static org.junit.Assert.fail;
2434
import static org.mockito.Mockito.mock;
35+
import static org.mockito.Mockito.verify;
36+
import static org.mockito.Mockito.when;
37+
import static org.robolectric.Shadows.shadowOf;
2538

39+
@RunWith(RobolectricTestRunner.class)
40+
@Config(constants = BuildConfig.class)
2641
public class ParseClientConfigurationTest {
2742

43+
private final String serverUrl = "http://example.com/parse";
44+
private final String appId = "MyAppId";
45+
private final String clientKey = "MyClientKey";
46+
private final String PARSE_SERVER_URL = "com.parse.SERVER_URL";
47+
private final String PARSE_APPLICATION_ID = "com.parse.APPLICATION_ID";
48+
private final String PARSE_CLIENT_KEY = "com.parse.CLIENT_KEY";
49+
2850
@Test
2951
public void testBuilder() {
3052
Parse.Configuration.Builder builder = new Parse.Configuration.Builder(null);
@@ -105,6 +127,75 @@ public void testSetNetworkInterceptors() {
105127
assertTrue(collectionsEqual(configurationB.interceptors, collectionB));
106128
}
107129

130+
@Test
131+
public void testConfigureFromManifest() throws Exception {
132+
Bundle metaData = setupMockMetaData();
133+
when(metaData.getString(PARSE_SERVER_URL)).thenReturn(serverUrl);
134+
when(metaData.getString(PARSE_APPLICATION_ID)).thenReturn(appId);
135+
when(metaData.getString(PARSE_CLIENT_KEY)).thenReturn(clientKey);
136+
137+
Parse.Configuration.Builder builder = new Parse.Configuration.Builder(RuntimeEnvironment.application);
138+
Parse.Configuration config = builder.build();
139+
assertEquals(serverUrl + "/", config.server);
140+
assertEquals(appId, config.applicationId);
141+
assertEquals(clientKey, config.clientKey);
142+
143+
verifyMockMetaData(metaData);
144+
}
145+
146+
@Test(expected = RuntimeException.class)
147+
public void testConfigureFromManifestWithoutServer() throws Exception {
148+
Bundle metaData = setupMockMetaData();
149+
when(metaData.getString(PARSE_SERVER_URL)).thenReturn(null);
150+
when(metaData.getString(PARSE_APPLICATION_ID)).thenReturn(appId);
151+
when(metaData.getString(PARSE_CLIENT_KEY)).thenReturn(clientKey);
152+
153+
// RuntimeException due to serverUrl = null
154+
Parse.initialize(RuntimeEnvironment.application);
155+
}
156+
157+
@Test(expected = RuntimeException.class)
158+
public void testConfigureFromManifestWithoutAppId() throws Exception {
159+
Bundle metaData = setupMockMetaData();
160+
when(metaData.getString(PARSE_SERVER_URL)).thenReturn(serverUrl);
161+
when(metaData.getString(PARSE_APPLICATION_ID)).thenReturn(null);
162+
when(metaData.getString(PARSE_CLIENT_KEY)).thenReturn(clientKey);
163+
164+
// RuntimeException due to applicationId = null
165+
Parse.initialize(RuntimeEnvironment.application);
166+
}
167+
168+
@Test
169+
public void testConfigureFromManifestWithoutClientKey() throws Exception {
170+
Bundle metaData = setupMockMetaData();
171+
when(metaData.getString(PARSE_SERVER_URL)).thenReturn(serverUrl);
172+
when(metaData.getString(PARSE_APPLICATION_ID)).thenReturn(appId);
173+
when(metaData.getString(PARSE_CLIENT_KEY)).thenReturn(null);
174+
175+
Parse.initialize(RuntimeEnvironment.application);
176+
assertEquals(new URL(serverUrl + "/"), ParseRESTCommand.server);
177+
assertEquals(appId, ParsePlugins.get().applicationId());
178+
assertNull(ParsePlugins.get().clientKey());
179+
180+
verifyMockMetaData(metaData);
181+
}
182+
183+
private void verifyMockMetaData(Bundle metaData) throws Exception {
184+
verify(metaData).getString(PARSE_SERVER_URL);
185+
verify(metaData).getString(PARSE_APPLICATION_ID);
186+
verify(metaData).getString(PARSE_CLIENT_KEY);
187+
}
188+
189+
private Bundle setupMockMetaData() throws Exception {
190+
Bundle metaData = mock(Bundle.class);
191+
ShadowPackageManager packageManager = shadowOf(RuntimeEnvironment.application.getPackageManager());
192+
ApplicationInfo info = packageManager.getApplicationInfo(
193+
RuntimeEnvironment.application.getPackageName(),
194+
PackageManager.GET_META_DATA);
195+
info.metaData = metaData;
196+
return metaData;
197+
}
198+
108199
private static <T> boolean collectionsEqual(Collection<T> a, Collection<T> b) {
109200
if (a.size() != b.size()) {
110201
return false;

ParseStarterProject/src/main/AndroidManifest.xml

+3
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,9 @@
1919
android:icon="@mipmap/ic_launcher"
2020
android:label="@string/app_name"
2121
android:theme="@style/AppTheme" >
22+
<meta-data
23+
android:name="com.parse.SERVER_URL"
24+
android:value="@string/parse_server_url" />
2225
<meta-data
2326
android:name="com.parse.APPLICATION_ID"
2427
android:value="@string/parse_app_id" />

ParseStarterProject/src/main/res/values/strings.xml

+1
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
~ of patent rights can be found in the PATENTS file in the same directory.
99
-->
1010
<resources>
11+
<string name="parse_server_url">YOUR_SERVER_URL</string>
1112
<string name="parse_app_id">YOUR_APPLICATION_ID</string>
1213
<string name="parse_client_key">YOUR_CLIENT_KEY</string>
1314

0 commit comments

Comments
 (0)